Monitoring Windows Services from BIG-IP
Community MVP hwidjaja dropped a bomb-sized nugget of wisdom in the forums last week that I would be remiss if I didn’t write up and share with the greater community at large. Zenoss has a WMI executable for linux called wmic, which allows you to query via wmi a windows box. So in the case for Terminal Services, you can use this tool to check if the TermService service is running, and mark the server up/down appropriately. Because and external executable with be utilized to do this, and external monitor will be necessary. Below, I’ll walk you through the steps.
Note: Putting an non-F5 executable on an LTM may negate F5's ability to support the unit, and might require the non-native executables to be removed before assisting in troubleshooting efforts.
Build & Transfer the wmic Executable
The wmic executable isn’t native on LTM, so it is necessary to build it. I downloaded the centOS 6.4 liveCD to build a virtual machine for the wmic build. Note that you need to use the CentOS version appropriate for your version of BIG-IP. After the vm is finalized, I installed gcc and autoconf with yum and then I followed the steps here:
-
- wget http://openvas.org/download/wmi/wmi-1.3.14.tar.bz2
- tar xfj wmi-1.3.14.tar.bz2
- cd wmi-1.3.14
- make
Once the build was complete, I switched over to my desktop to pull down the executuble, then transferred it to the LTM:
-
- C:\Users\jrahm\Downloads>pscp jrahm@172.16.99.128:/home/jrahm/wmi-1.3.14/Samba/source/bin/wmic .
- C:\Users\jrahm\Downloads>pscp wmic root@10.10.20.5:/var/tmp/
Next, I moved to the LTM and remounted the /usr file system to read-write so I could dump the executable in /usr/local/bin/:
-
- mount –o remount,rw /dev/vg-db-had /usr
- cp /var/tmp/wmic /usr/local/bin/
Note: You’ll need to check your /etc/fstab for the appropriate location of the /usr file system, it varies.
Testing wmic
Now that I had the executable in place, I tested it from the command line (variables need for script in bold italics):
wmic -U testdom/testaccount%testpasswd //192.168.22.31 "select State from Win32_Service where Name='TermService'”
This resulted in the following output:
CLASS: Win32_Service
Name|State
TermService|Running
Creating the Script
After a successful query via wmi to check the service and the string that shows it’s running (TermService|Running), I created a script (/usr/share/monitors/rdpcheck) for the external monitor to reference:
#!/bin/bash
# remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
IP=`echo ${1} | sed 's/::ffff://'`
PORT=${2}PIDFILE="/var/run/`basename ${0}`.${IP}_${PORT}.pid"
# kill of the last instance of this monitor if hung and log current pid
if [ -f $PIDFILE ]
then
kill -9 `cat $PIDFILE` > /dev/null 2>&1
fi
echo "$$" > $PIDFILErm -f $PIDFILE
# send request & check for expected response
wmic -U $3/$4%$5 //$IP "select State from Win32_Service where Name='TermService'" | grep -i "TermService|Running" 2>&1 > /dev/null# mark node UP if expected response was received
if [ $? -eq 0 ]
then
echo "UP"
fiexit
$1 and $2 are IP and Port with external monitors, and arguments are $3 and beyond. So in this case, I needed to supply domain, username, & password. At the command line, this looked like this:
[root@ephesus:Active] monitors # ./rdpcheck ::ffff:192.168.22.31 3389 testdom testaccount testpasswd
UP
[root@ephesus:Active] monitors # ./rdpcheck ::ffff:192.168.22.31 3389 testdom testaccount testpass
NTSTATUS: NT_STATUS_ACCESS_DENIED - Access denied
Deb had a tip a while back when checking external monitors to make sure to supply the ::ffff: ipv6 format with the IPs to make sure the script handles it properly. Make sure to make the script executable (chmod +x rdpcheck).
Creating the Monitor
Now that the script is working at the command line, it’s time to create the monitor. Via the command line with bigpipe first, followed by a screenshot of the GUI.
b monitor rdp_mon '{
defaults from external
interval 10
timeout 31
args "testdom testaccount testpasswd"
run "/usr/share/monitors/rdpcheck"
}'
That’s it! Now, assign it to a pool and you’re set:
2010-12-28 16:58:00.053110: ID 53 :(_main_loop): rfd selected [ addr=::ffff:192.168.22.31:3389 srcaddr=98bd:8bbf:921e:6107:98c1:4009:4715:
f08:0 fd=10 pend=0 ]
2010-12-28 16:58:00.053203: ID 53 :(_recv_external_node_ping): reading [ addr=::ffff:192.168.22.31:3389 ]
2010-12-28 16:58:00.053295: ID 53 :(_kill_external_pinger): killing [ addr=::ffff:192.168.22.31:3389 ]
2010-12-28 16:58:00.053893: ID 53 :(recv_external_node_ping): EAV success [ addr=::ffff:192.168.22.31:3389 ]
Conclusion
This tech tip was specifically to show support for the terminal service, but wmic could be used for any other windows service as well, or could be used to ensure a bundle of services are running before considering a server is up. Standard disclaimers apply, adding things to the file system can cause unexpected results, so test thoroughly. Also, make sure to back things up as the wmic executable won't survive hotfixes and upgrades. Thanks again to hwidjaja for the excellent resource.
- morey_63594NimbostratusThere is another program that could make monitoring easy as well without WMI enabled on servers for any reason.
- JRahmAdminAll good points, and I'll take a look at winexe, perhaps another writeup is in my future!
- Dan_MatherNimbostratusJason,
- Christopher_BooCirrostratusThs is great! You should change the title to "Monitor Any Windows Service from Big IP". Been wanting something like this for a long time.....
- GramofSalt_8283NimbostratusGood Day. I like the idea of using this complied program (wmic) to pull windows services to validate the health of a pool member. I have followed the instructions to a T and am able to call the script from the command line and pull the service status properly. However, when I create the monitor and apply it to a pool member, the script will not run, and what I mean is the 'basename0.IP_PORT.PID' is not create and therefore will not run. It's like the IP=$1 and PORT=$2 will not populate from the pool member to create the process.
- JRahmAdminHave you tried on route domain zero?
- GramofSalt_8283NimbostratusOk I have tried it via route domain zero and the PID started like we want it to!!
- JRahmAdminsure, you can do that in the script, try this line after the first IP setting (stripping the IPv6 header):
- JRahmAdminoh, actually, if quoting the first IP line, the second should reference the IP variable, but better, just add the sed method to the original line:
- hooleylistCirrostratusHi Jason,