Forum Discussion

hc_andy_35682's avatar
hc_andy_35682
Icon for Nimbostratus rankNimbostratus
May 24, 2010

External TCP Helath Monitor

Hi All,

We are load balancing a cluster of webmail and imap servers on our LTM. Users log onto webmail which then makes a connection to the imap_vip on port 143.

I would like to create an external TCP/Telnet health monitor so that if the webmail machines in the webmail pool can not telnet to the imap_vip on port 143 and receive the string "OK Imap Server Mail Ready" (see below) then disable (out of service) the respective webmail pool member.

> telnet imap.server.net.au 143
Trying 210.15.254.x...
Connected to imap.server.net.au.
Escape character is '^]'.
* OK Imap Server Mail Ready.
The imap_vip uses source address persistence and we've had a few issues where some webmail machines which are persisted to a particular imap server (for what ever reason) can not communicate with the imap server on port 143. To fix this we've had to manually delete the persistence entry.

I believe I need an external TCP health monitor to do this as none of the pre-configured health monitors on the LTM offer this level of customization.

I've read the external health monitor doco's but I'm not really a shell programmer so appreciate any help given.

Thanks. Andy
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Hi Andy,

     

     

    You can create an inbuilt IMAP monitor and set the username, password, etc in the monitor definition. Or if that didn't work for you for some reason, you could create a custom TCP monitor with no send string and the following receive string:

     

     

    \* OK IMAP Mail Ready

     

     

    The latter option will probably result in an error on the server for each request, but the monitor should still mark the pool member up.

     

     

    Aaron
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    If you did want to use an external script for some reason, you could try something like this which uses netcat to open a TCP connection to the pool member and then checks the response for the "\* OK" string followed by "Ready". I suppose you could use expect or some other utility to send an IMAP command to close the connection. I'm just timing it out after 2 seconds.

    If you add a DEBUG variable in the monitor definition and set it to 1, the script will write out debug to /var/log/ltm.

    Aaron

    Monitor definition

     b monitor custom_netcat_monitor list
    monitor custom_netcat_monitor {
       defaults from external
       DEBUG "0"
       run "custom_netcat.bash"
    }
    

    Monitor script

    !/bin/bash
    
     Check an IMAP server for a response with \* OK.*Ready
     using netcat (nc) as a client.
    
     Save this file as /usr/bin/monitors/custom_telnet.bash
     Make executable using chmod 744 custom_telnet.bash
    
     Log debug to local0.debug (/var/log/ltm)?
     Check if a variable named DEBUG exists from the monitor definition
     This can be set using a monitor variable DEBUG=0 or 1
    if [ -n "$DEBUG" ]
    then
       if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: true: \$DEBUG: $DEBUG" | logger -p local0.debug; fi
    else
        If the monitor config didn't specify debug, enable/disable it here
       DEBUG=0
       echo "EAV `basename $0`: false: \$DEBUG: $DEBUG" | logger -p local0.debug
    fi
    
     Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
    IP=`echo $1 | sed 's/::ffff://'`
    
     The pool member port is passed as the second parameter
    PORT=$2
    
     Check if there is a prior instance of the monitor running
    pidfile="/var/run/`basename $0`.$IP.$PORT.pid"
    if [ -f $pidfile ]
    then
       kill -9 `cat $pidfile` > /dev/null 2>&1
       echo "EAV `basename $0`: exceeded monitor interval, needed to kill ${IP}:${PORT} with PID `cat $pidfile`" | logger -p local0.error
    fi
    
     Add the current PID to the pidfile
    echo "$$" > $pidfile
    
     Send the IMAP request and look for \* OK.*Ready in the response
     Use a timeout of 2 seconds on the netcat request.
     This timeout seems to be necessary as we're not explicitly closing the TCP connection with an IMAP command.
     Redirect stderr and stdout to nothing to ensure we don't errantly mark the pool member up
    nc $IP $PORT -w 2 | grep '\* OK.*Ready' 2>&1 > /dev/null
    
     Debug
    if [ $DEBUG -eq 1 ]
    then
       echo "EAV `basename $0`: Running for ${IP}:${PORT}" | logger -p local0.debug
    fi
    
     Check if the command ran successfully
     Note that any standard output will result in the script execution being stopped
     So do any cleanup before echoing to STDOUT
    if [ $? -eq 0 ]
    then
       rm -f $pidfile
       if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: Succeeded for ${IP}:${PORT}" | logger -p local0.debug; fi
       echo "UP"
    else
       rm -f $pidfile
       if [ $DEBUG -eq 1 ]; then echo "EAV `basename $0`: failed for ${IP}:${PORT}" | logger -p local0.debug; fi
    fi
    

    Aaron