Monitoring Application Level Health
This example demonstrates monitoring services on Network Load Balancing (NLB) nodes, stopping NLB on any nodes where the monitored service has stopped.
'''''''''''''''''''''''''''''''''''
' NlbMon.vbs
'
' Sample script to monitor NLB clusters.
'
' User can pass any NT service on the NLB cluster nodes for the
' script to check status. If that service is stopped on any of
' NLB nodes, the script will stop NLB on that node.
'
' Optionally includes capability of passing alternate credentials
' to use when connecting to the cluster nodes.
'
' Note: Windows Server 2003 nodes should have remote control
' enabled. Otherwise, you can extend the -n command-line
' parameter to accept multiple nodes to connect to individually.
'
'
' Suggested additional enhancements/customizations:
'
' This script can be customized for much more complicated health
' monitoring and dynamic load-balancing capabilities. Examples
' include:
'
' - Loop infinitely, checking for latest service status. This
' script currently executes one iteration against the cluster
' nodes.
' - Automatically start back NLB on a node if the service
' comes back to the started state. Currently, this script
' waits for interaction from the administrator to debug the
' service problem before restarting NLB on the affected nodes.
' - Check stress level on nodes (for example, checking CPU,
' memory, or other performance metrics on the system).
' - Check application response times. For example, if the
' application being load balanced is slow in responding on one
' of the nodes, the script can change NLB weights and/or
' stop NLB on the affected nodes.
' - Work on a localized computer.
'
'''''''''''''''''''''''''''''''''''
' Variables used throughout the script
Dim strUserName,strPassword
Dim objNlb
Dim strServer,strClusterVip
Dim strService
Dim strURLFile
' Parse the command line.
call ParseCommand()
' Display a warning if only the VIP is provided.
call IsVipOnly()
wscript.echo "Using server IP to query for nodes: " & strServer
wscript.echo "Using primary cluster IP: " & strClusterVip
wscript.echo
' Perform the NT service check.
if strService <> "" then
call CheckServiceAndControlNLB(strService , "Stopped")
end if
' Perform the Web GET request check.
if strURLFile <> "" then
call CheckWebURL(strServer,strClusterVip,strURLFile)
end if
wscript.quit
Function IsVipOnly()
'
' Check if a VIP was the only connection IP passed.
' If it is, set strClusterVip to strServr.
'
if strServer = "" then
wscript.echo "WARNING: Only the VIP was passed."
wscript.echo "Using the VIP to manage cluster may result "_
& "in errors with connecting to individual nodes. "
wscript.echo "If you encounter any error, you should specify a "_
& "host name or host IP to connect to."
wscript.echo
wscript.echo "Attempt the initial connection using the VIP."
IsVipOnly = (strClusterVip = "")
strServer = strClusterVip
exit Function
end if
end Function
Function CheckServiceAndControlNLB( byVal strService, _
byVal strServiceState)
'
' Connects to specified node to get other nodes in cluster and then
' queries for state on each NLB node and sets NLB state as appropriate.
'
Dim objCimv2
Dim objNodes1,objNLBNode
if ( ConnectProvEx("root\microsoftnlb", strUserName, strPassword, strServer, objNlb, true) ) then
wscript.echo "Unable to connect to NLB node."
CheckServiceAndControlNLB = -1
exit Function
end if
if ( ConnectProvEx("root\cimv2", strUserName, strPassword, strServer, objCimv2, true) ) then
wscript.echo "Unable to connect to cimv2 namespace."
CheckServiceAndControlNLB = -1
exit Function
end if
if (GetClusterMembers(objNlb,strClusterVip ,objNodes1)<>0) then
CheckServiceAndControlNLB = -1
exit Function
end if
for each objInst in objNodes1
szName = objInst.name
szRelPath = objInst.path_.Relpath
szComputername = objInst.Computername
wscript.echo "#### Attempting to connect to server " _
& szComputername & " to check that service " _
& strService & " is " & strServiceState & " ######"
call ConnectProvEx( "root\microsoftnlb", strUserName, strPassword, szComputername, objNLBNode, true )
call ConnectProvEx("root\cimv2", strUserName, strPassword, szComputername, objCimv2, true )
wscript.echo "Connected to " & szComputername
szActualState = ""
if ( GetStateOfServiceOnNode( objCimv2, strService, strServiceState, szActualState ) ) then
wscript.echo("!!!! Attempt to stop NLB on node: " & szComputername)
call NodeControl(objNLBNode,szRelPath, "stop")
wscript.echo
end if
next
end Function
Function CheckWebURL(byVal strServer, strClusterVip, byVal strURLFile)
'
' Connects to specified node to get other nodes in cluster and then
' runs a simple HTTP test and sets NLB state as appropriate.
'
Dim strURL
Dim objNodes1,objNLBNode
if (ConnectProvEx( "root\microsoftnlb", strUserName, strPassword, strServer, objNlb, true ) ) then
wscript.echo "Unable to connect to NLB node."
exit Function
end if
if (GetClusterMembers(objNlb,strClusterVip ,objNodes1) <> 0) then
exit Function
end if
for each objInst in objNodes1
szRelPath = objInst.path_.Relpath
szComputername = objInst.Computername
wscript.echo "#### Attempting to get URL " & strURL & " ######"
strURL= "http://" & szComputername & "/" & strURLFile
if CheckWeb(strURL) = False then
wscript.echo ("Page is unavailable")
wscript.echo("!!!! Attempt to stop NLB on node: "& szComputername)
if ConnectProvEx("root\microsoftnlb", strUserName, strPassword, szComputername, objNLBNode, true ) <> 0 then
wscript.echo "!!!!" & szRelPath
call NodeControl(objNLBNode,szRelPath, "stop")
end if
end if
next
end Function
Function GetClusterMembers( byRef objNLBNode, _
byVal szVip, _
byRef objMembers)
'
' Enumerate the cluster members given the VIP.
'
on error resume next
szQueryString = "select * from MicrosoftNLB_Node where name like '%" & szVip & "%'"
set objMembers = objNLBNode.ExecQuery(szQueryString)
if (Err.Number) then
Wscript.echo "Failed to get cluster members for " & szVip & ": " & err.description
GetClusterMembers = err.number
else
if objMembers.count = 0 then
wscript.echo "NLB is not bound. Make sure that you are using the primary cluster IP address."
wscript.echo "Using any other VIP will fail to find the cluster instance."
GetClusterMembers = 1
else
GetClusterMembers = 0
end if
end if
end function
Function NodeControl(byRef objNLBNode, byVal szPath, byVal szAction)
'
' Control NLB cluster node state.
' Action is one of: stop, start, suspend, resume.
'
on error resume next
wscript.echo "Attempt to get NLB instance: " & szPath
Set objNode = objNLBNode.Get(szPath)
if Err.Number <> 0 then
Wscript.echo "Failed to get NLB instance " & WMIClass & ": " & err.description
else
Set objOutParam = objNode.ExecMethod_(szAction)
wscript.echo("Execute method returned:")
call DisplayReturnValue(objOutParam.ReturnValue)
end if
end function
sub DisplayReturnValue(ReturnValue)
'
' Translate the return value to a string and display it to output.
'
select case ReturnValue
case 1000
wscript.echo " Success."
case 1001
wscript.echo " Cluster mode is already stopped/started, or traffic handling is already" _
& " enabled/disabled on specified port."
case 1002
wscript.echo " Cluster mode stop or start operation interrupted connection draining process."
case 1003
wscript.echo " Cluster mode could not be started due to configuration problems on the target host."
case 1004
wscript.echo " Port number not found among port rules."
case 1005
wscript.echo " Cluster mode is stopped on the host."
case 1006
wscript.echo " Cluster is converging."
case 1007
wscript.echo " Cluster or host converged successfully."
case 1008
wscript.echo " Host is converged as default host."
case 1009
wscript.echo " Host is draining after drainstop command."
case else:
wscript.echo " Unknown return (" & ReturnValue & ")."
end select
End Sub
Function Ping(ByVal szIP)
'
' Ping an remote machine using \root\cimv2:Win32_PingStatus
'
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colPings = objWMIService.ExecQuery( "Select * From Win32_PingStatus where Address = '" _
& szIP & "'")
for Each objStatus in colPings
if IsNull(objStatus.StatusCode) or objStatus.StatusCode<>0 then
Ping = false
WScript.Echo "Computer did not respond."
else
Ping = true
Wscript.Echo "Computer responded."
end If
next
End Function
Function CheckWeb(byVal strURL)
'
' Validates that a specified Web page is accessible by running an
' HTTP GET request.
'
on error resume next
With CreateObject("MSXML2.XMLHTTP")
.open "GET", strURL, False
wscript.echo "Attempt to get: " & strURL
.send
if .status <> 200 then
CheckWeb = false
wscript.echo "HTTP GET returned " & .status
else
CheckWeb = true
Wscript.echo "GET sucess. Page content as follows:"
WScript.Echo .responseText
end if
End With
end function
Function ConnectProvEX( ByVal strNameSpace, _
ByVal strUserName, _
ByVal strPassword, _
ByRef strServer, _
ByRef objService, _
ByVal LOAD_DRIVE)
'
' Connect to WMI provider name space.
'
on error resume next
Dim objLocator, objWshNet
ConnectProvEx = False 'There is no error.
'Create Locator object to connect to remote CIM object manager.
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
if LOAD_DRIVE <> False then
objLocator.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True
end if
if Err.Number then
wscript.echo(" Error 0x" & CStr(Hex(Err.Number)) & _
" occurred in creating a locator object." )
if Err.Description <> "" then
wscript.echo(" Error description: " & Err.Description )
end if
ConnectProvEx = err.number 'An error occurred
Err.Clear
Exit Function
end if
Set objService = objLocator.ConnectServer( strServer, _
strNameSpace, _
strUserName, _
strPassword)
if err = -2147023174 then 'HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
wscript.echo err.Description
wscript.echo "Verify that server name or IP address is correct for " _
& strServer
ConnectProvEx = err.number
exit function
end if
ObjService.Security_.impersonationlevel = 3
if Err.Number then
wscript.echo(" Error 0x" & CStr(Hex(Err.Number))
& " occurred in connecting to server " & strServer & ".")
if Err.Description <> "" then
wscript.echo(" Error description: " & Err.Description )
end if
Err.Clear
ConnectProvEx = err.number
end if
End Function
Function GetStateOfServiceOnNode( byRef objCimvServer, _
byVal strService, _
byVal chkState, _
byRef isState)
'
' Query NT service for a given state and return the state.
'
szQueryString = "Select * from Win32_Service where name = '" & strService & "'"
Set objService = objCimvServer.ExecQuery(szQueryString)
if objService.count = 0 then
wscript.echo "Service " & strService & " is not installed"
GetStateOfServiceOnNode = -1
exit function
end if
for each objInst in objService
isState = objInst.State
wscript.echo "Service " & strService & " is " & isState
if chkState = isState then
GetStateOfServiceOnNode = true
end if
next
end Function
Function ParseCommand()
'
' Parses the command line and fills the script variables
' with the appropriate values.
'
Dim ArgCount
Dim oArgs
Set oArgs = Wscript.Arguments
ArgCount = 0
if oArgs.Count = 0 then
wscript.echo "No arguments specified."
wscript.echo
call Help()
end if
While ArgCount < oArgs.Count
Select Case LCase(oArgs(ArgCount))
Case "-u"
ArgCount = ArgCount + 1
strUserName=LCase(oArgs(ArgCount))
Case "-p"
ArgCount = ArgCount + 1
strPassword=oArgs(ArgCount)
Case "-s"
ArgCount = ArgCount + 1
strService= LCase(oArgs(ArgCount))
Case "-f"
ArgCount = ArgCount + 1
strURLFile = LCase(oArgs(ArgCount))
Case "-n"
ArgCount = ArgCount + 1
strServer= LCase(oArgs(ArgCount))
Case "-v"
ArgCount = ArgCount + 1
strClusterVip= LCase(oArgs(ArgCount))
Case Else:
wscript.echo "Invalid command."
wscript.echo
call Help()
wscript.quit
End Select
ArgCount = ArgCount + 1
Wend
End Function
sub Help()
'
' Display command-line syntax for the script.
'
wscript.echo "Network Load Balancing (NLB) service monitor tool"
wscript.echo "Checks any Windows service state and stops NLB hosts if that service is stopped."
wscript.echo "Service Monitor command Line help"
wscript.echo
wscript.echo "Syntax:"
wscript.echo
wscript.echo "-u User name"
wscript.echo "-p Password"
wscript.echo "-n Server name or IP"
wscript.echo "-s Service name to monitor"
wscript.echo "-v Primary cluster IP"
wscript.echo "-f File to HTTP GET"
wscript.echo
wscript.echo "Examples:"
wscript.echo
wscript.echo "nlbmon.vbs -n 2.77.2.2 -v 2.77.22.200 -s w3svc"
wscript.echo "nlbmon.vbs -v 2.77.22.200 -s w3svc"
wscript.echo "nlbmon.vbs -v 2.77.22.200 -s w3svc -f whoami.txt"
wscript.echo "nlbmon.vbs -n 2.77.2.2 -v 2.77.22.200 -f whoami.txt"
wscript.quit
End Sub
Related topics