Tuesday, April 14, 2009

[vbscript] WMI Smart Cluster Reboot Script

So moving though some of my older admin scripts today I found my cluster reboot script using a batch file was pretty dated - while it still works it was lacking intelligence, including the fact that it simply moved cluster resources then blindly rebooted the server without any confirmation that the resources had actually moved. So it got a VBScript makeover... While this version is more for 2 node Active/Passive clusters it should get you started on your own cluster reboot script for any configuration. Enjoy.

'==========================================================================
' NAME: CluReboot.vbs
'
' AUTHOR: DH Collier - dhcollier.com
' DATE : 4/14/2009
' Revision: 1.1
'
' COMMENT: Script for rebooting clusters - can be run local to cluster or
' Remotely. See SCRIPT CONFIGURATION section before running.
'
'==========================================================================

' ------ SCRIPT DECLARATIONS ------
Option Explicit
Dim objCluster, objWMIOS, objOS, objWMIService, objItem, objFS, objLogFile
Dim strMethod, strWMISQL, strComputer
Dim colItems, colOS
Dim intRC, intCount, intWork
Dim varCluGroup, varPriNode, varCluName, varSecNode, varLogFile
Const ForAppending = 8
' ------ END DECLARATIONS ------

' ------ SCRIPT CONFIGURATION ------
' varCluName is the Cluster name as shown in cluadmin
' varPriNode is the server name of the Primary node
' varSecNode is the server name of the Secondary node
' varCluGroup is the name of the Cluster Group you wish to failOver (set as "" to do all resources)
' varLOG_FILE is the name of the Log File to write to (placed in the same dir as script) - will be created

varCluName = "CLUSTERNAME"
varPriNode = "NODEA"
varSecNode = "NODEB"
varCluGroup = ""
varLogFile = "CluReboot.log"
' ------ END CONFIGURATION ---------

' ------ LOG HANDLER ------
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objLogFile = objFS.OpenTextFile(Replace(WScript.ScriptFullName, WScript.ScriptName, "") & varLogFile, ForAppending, TRUE)
' ------ END LOG HANDLER ------

' ------ ARGUMENTS HANDLER ------
if WScript.Arguments.Count <> 1 Then
WScript.Echo "USAGE: CluReboot.vbs [primary] [secondary] [config]"
WScript.Echo ""
WScript.Echo "Examples:"
Wscript.Echo "CluReboot.vbs primary"
Wscript.Echo " Moves cluster resources from Primary to Secondary node"
Wscript.Echo " then reboots Primary Node"
WScript.Echo ""
Wscript.Echo "CluReboot.vbs secondary"
Wscript.Echo " Moves cluster resources from Secondary to Primary node"
Wscript.Echo " then reboots Secondary Node"
WScript.Quit 0
Else
Select Case lcase(WScript.Arguments(0))
Case "primary"
strMethod = lcase(WScript.Arguments(0))
strComputer = varPriNode
subWriteLog("-------------CLUSTER MOVE/REBOOT INITIATED---------------")
subWriteLog(varCluName & " will be failed over from " & varPriNode & " to " & varSecNode)
Case "secondary"
strMethod = lcase(WScript.Arguments(0))
strComputer = varSecNode
subWriteLog("-------------CLUSTER MOVE/REBOOT INITIATED---------------")
subWriteLog(varCluName & " will be failed over from " & varSecNode & " to " & varPriNode)
Case "config"
Wscript.Echo "Script Configuration Report"
Wscript.Echo ""
Wscript.Echo "Cluster Name: " & ucase(varCluName)
Wscript.Echo ""
Wscript.Echo "Primary Node: " & ucase(varPriNode)
Wscript.Echo ""
Wscript.Echo "Secondary Node: " & ucase(varSecNode)
Wscript.Echo ""
if varCluGroup <> "" then
Wscript.Echo "Cluster Resource: " & ucase(varCluGroup)
else
Wscript.Echo "Cluster Resource: All Resource Groups"
End If
Wscript.echo ""
Wscript.Quit 0
case else
Wscript.Echo WScript.Arguments(0) & " is an invalid option...."
Wscript.Echo ""
WScript.Echo "USAGE: CluReboot.vbs [primary] [secondary] [config]"
WScript.Echo ""
WScript.Echo "Examples:"
Wscript.Echo "CluReboot.vbs primary"
Wscript.Echo " Moves cluster resources from Primary to Secondary node"
Wscript.Echo " then reboots Primary Node"
WScript.Echo ""
Wscript.Echo "CluReboot.vbs secondary"
Wscript.Echo " Moves cluster resources from Secondary to Primary node"
Wscript.Echo " then reboots Primary Node"
WScript.Quit 0
End Select
End If
' ------ END ARGUMENTS HANDLER ------

' ------ CLUSTER MOVE HANDLER ------
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\mscluster")
If varCluGroup = "" then
strWMISQL = "Select * from MSCluster_ResourceGroup"
else
strWMISQL = "Select * from MSCluster_ResourceGroup WHERE Name='" & varCluGroup & "'"
end if
Set colItems = objWMIService.ExecQuery( strWMISQL )
For Each objItem in colItems
intWork = 0
if (funResourceOwner(objItem.name) = lcase(varPriNode) And strMethod = "primary") Then
On Error Resume Next
objItem.MoveToNewNode(varSecNode)
subWriteLog(objItem.name & " move initiated to " & varSecNode)
On Error Goto 0
intWork = 1
elseif (funResourceOwner(objItem.name) = lcase(varSecNode) And strMethod = "secondary") Then
On Error Resume Next
objItem.MoveToNewNode(varPriNode)
subWriteLog(objItem.name & " move initiated to " & varPriNode)
On Error Goto 0
intWork = 1
End If
intCount = 0
Do while funStatusCheck(objItem.name) <> 0 'requery WMI for cluster status code - 0 = online
wscript.sleep(30000)
intCount = intCount + 1
if intCount > 19 then ' failover takes longer than 10m likely a problem - so don't reboot.
subWriteLog("WARNING: Resource Group Move has taken longer than 10min - script has exited without reboot")
WScript.Quit 0
End if
loop
if intWork = 1 then subWriteLog(objItem.name & " move successful")
Next

Set colItems = nothing
set objItem = nothing
' ------ END CLUSTER MOVE HANDLER ------

' ------ REBOOT HANDLER ------
set objWMIOS = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
objWMIOS.Security_.AuthenticationLevel = 6
objWMIOS.Security_.Privileges.AddAsString"seShutdownPrivilege",True

set colOS = objWMIOS.InstancesOf("Win32_OperatingSystem")
for each objOS in colOS
intRC = ObjOS.Reboot() ' Reboot
if intRC <> 0 then
subWriteLog("ERROR: Unable to reboot server "& strComputer & " error code: " & intRC)
else
subWriteLog("Server Rebooted: " & strComputer)
end if
next
subWriteLog("-------------CLUSTER MOVE/REBOOT COMPLETED---------------")
objLogFile.Close()
' ------ END REBOOT HANDLER ------

' ------ STATUS CHECK FUNCTION ------
function funStatusCheck(strItemName)
Dim objStatusWMIService, colStatusItems, objStatusItem
Set objStatusWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\mscluster")
Set colStatusItems = objStatusWMIService.ExecQuery("Select * from MSCluster_ResourceGroup WHERE Name='" & strItemName & "'")
For Each objStatusItem in colStatusItems
funStatusCheck = objStatusItem.State
Next
end function
' ------ END STATUS CHECK FUNCTION ------

' ------ OWNER CHECK FUNCTION ------
function funResourceOwner(strCluGroup)
Set objCluster = CreateObject("MSCluster.Cluster")
objCluster.Open(varCluName)
funResourceOwner = lcase(objCluster.ResourceGroups.Item(strCluGroup).OwnerNode.Name)
End Function
' ------ END OWNER CHECK FUNCTION ------

' ------ WRITE LOG SUB ------
Sub subWriteLog(LogMessage)
Dim objCon, sqlQuery
'wscript.echo Now() & ": " & LogMessage
objLogFile.Writeline(Now() & ": " & LogMessage)
End Sub
' ------ END WRITE LOG SUB ------
Here is the link to a .txt copy of the script for ease of download (and no page break issues with copy/paste)

No comments:

Post a Comment