EDC.Base.RestartClusterResource.Script.WriteAction (WriteActionModuleType)

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityPublic
RunAsDefault
InputTypeSystem.BaseData

Member Modules:

ID Module Type TypeId RunAs 
Script WriteAction Microsoft.Windows.ScriptWriteAction Default

Overrideable Parameters:

IDParameterTypeSelector
StartOrStopTimeOutSecondsint$Config/StartOrStopTimeOutSeconds$
ScriptTimeoutSecondsint$Config/ScriptTimeoutSeconds$

Source Code:

<WriteActionModuleType ID="EDC.Base.RestartClusterResource.Script.WriteAction" Accessibility="Public" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ResourceName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StartOrStopTimeOutSeconds" type="xsd:int"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ScriptTimeoutSeconds" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="StartOrStopTimeOutSeconds" Selector="$Config/StartOrStopTimeOutSeconds$" ParameterType="int"/>
<OverrideableParameter ID="ScriptTimeoutSeconds" Selector="$Config/ScriptTimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptWriteAction">
<ScriptName>RestartClusterResource.vbs</ScriptName>
<Arguments>"$Config/ResourceName$" $Config/StartOrStopTimeOutSeconds$</Arguments>
<ScriptBody><Script>
Option Explicit
'***********************************************************************************************************
' Disclaimer
'
' This sample script is not supported under any Microsoft standard support program or service. This sample
' script is provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties
' including, without limitation, any implied warranties of merchantability or of fitness for a particular
' purpose. The entire risk arising out of the use or performance of this sample script and documentation
' remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation,
' production, or delivery of this script be liable for any damages whatsoever (including, without limitation,
' damages for loss of business profits, business interruption, loss of business information, or other
' pecuniary loss) arising out of the use of or inability to use this sample script or documentation, even
' if Microsoft has been advised of the possibility of such damages.
'
'***********************************************************************************************************
' RestartClusterResource.vbs 1.0 v20080111
'
' Restarts or starts a given failover cluster resource and all running dependent resources.
'
' Arguments: &lt;ResourceName&gt; [&lt;TimeOut&gt;]
'
' ResourceName: name (not the display name) of the failover cluster resource to be restarted
' TimeOut: Optional. Timeout for waiting for a resource to start or to stop in seconds. The default is 60 s.
' Any value below 60 will be automatically changed to 60.
'
' Version for Operations Manager 2007
'
' JM
'***********************************************************************************************************
'Script specific constants
'Const SCRIPT_NAME = "RestartClusterResource.vbs"
Const SCRIPT_VERSION = "1.0"
Const MSCLUSTER_WMI_NAMESPACE = "root\MSCluster"
Const RESOURCE_WMI_CLASS = "MSCluster_Resource"
Const RESOURCE_TO_DEPENDENT_ASSOC_CLASS = "MSCluster_ResourceToDependentResource"
Const DEPENDENT_QUALIFIER = "Dependent"
Const ANTECEDENT_QUALIFIER = "Antecedent"

Const RESOURCE_START_STOP_MIN_TIMEOUT = 60 'sec
Const SERVICE_TIMEOUT_QUERY_INTERVAL = 1 'sec

'Cluster resource states
Const STATE_UNKNOWN = -1 'StateUnknown -1 The operation was not successful.
Const STATE_INITIALIZING = 1 'Initializing 1 The resource is performing initialization.
Const STATE_ONLINE = 2 'Online 2 The resource is operational and functioning normally.
Const STATE_OFFLINE = 3 'Offline 3 The resource is not operational. This value will be returned if the resource reported a state of ClusterResourceOffline (3) or ClusterResourceCannotComeOnlineOnThisNode (127).
Const STATE_FAILED = 4 'Failed 4 The resource has failed. This value will be returned if the resource reported a state of ClusterResourceFailed (4) or ClusterResourceCannotComeOnlineOnAnyNode (126).
Const STATE_PENDING = 128 'Pending 128 The resource is coming online or going offline.
Const STATE_ONLINE_PENDING = 129 'Online Pending 129 The resource is coming online.
Const STATE_OFFLINE_PENDING = 130 'Offline Pending 130 The resource is going offline.

Call Main

'********************************************************************************
' PROCEDURE: Main
' DESCRIPTION: Read the arguments and restart the given failover cluster resource including
' all resources depending on it if they are running.
' PARAMETERS: void
'******************************************************************************
Private Sub Main()

Dim strResourceName 'As String
Dim lngTimeOut 'As Long
Dim objSWbemServices 'As WbemScripting.SWbemServices
Dim objSWbemObjectSet 'As SWbemObjectSet
Dim objSWbemObject 'As SWbemObject
Dim colResources 'As Scripting.Dictionary
Dim arrResourceNames 'As String
Dim objWSHNetwork 'As WScript.Network
Dim i 'As Long
Dim lngLastProcessedIndex 'As Long
Dim strTemp1 'As String
Dim strTemp2 'As String

Call SetLocale("en-us")

If Not GetScriptParameters(strResourceName, lngTimeOut) Then
Call WScript.Echo("Error! An argument is missing." &amp; vbCrLf &amp; "Syntax: cscript RestartClusterResource.vbs &lt;ServiceName&gt; [&lt;TimeOut&gt;]")
Exit Sub
End If

If ConnectToWbemNS("", MSCLUSTER_WMI_NAMESPACE, objSWbemServices) Then

'On Error Resume Next
Set objSWbemObject = objSWbemServices.Get(RESOURCE_WMI_CLASS &amp; ".Name=" &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
If objSWbemObject Is Nothing Then
Call WScript.Echo("Error! Could not retrieve a " &amp; RESOURCE_WMI_CLASS &amp; " instance with the property Name = " &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
Exit Sub
Else
Set colResources = CreateObject("Scripting.Dictionary")
Call colResources.Add(objSWbemObject.Name, "")
End If

'Check dependencies
If CheckResourceDependencies(objSWbemObject, objSWbemServices, colResources) Then
Call WScript.Echo("Stopping resource " &amp; objSWbemObject.Name &amp; " and all resources depending on it...")
arrResourceNames = colResources.Keys
lngLastProcessedIndex = 0
'Stop the resource after all dependent resources
'If a dependent resource could not be stopped, try to restart all already stopped resources
For i = UBound(arrResourceNames) To 0 Step -1
If Not StopClusterResource(arrResourceNames(i), objSWbemServices, colResources, lngTimeOut) Then
'Because the resource could not be stopped, start only the resources stopped before the error occured
lngLastProcessedIndex = i + 1
Call WScript.Echo("An error occured! Could not stop the resource. Try to start all already stopped resources...")
Exit For
End If
Next 'i
'if it was the first resource that could not be stopped, do nothing
If lngLastProcessedIndex &lt;= UBound(arrResourceNames) Then
For i = lngLastProcessedIndex To UBound(arrResourceNames)
If colResources.Item(arrResourceNames(i)) Or i = 0 Then
'Only restart a dependent resource if it was stopped by this script
'Exception: the resource for which this script was called
If Not StartClusterResource(arrResourceNames(i), objSWbemServices, lngTimeOut) Then
Call WScript.Echo("An error occured! Could not start the resource. Continue...")
End If
End If
Next 'i
End If
End If

Else
Call WScript.Echo("Error! Could not connect to the WMI namespace '" &amp; MSCLUSTER_WMI_NAMESPACE &amp; "'")
End If

End Sub

'******************************************************************************
' FUNCTION: StopClusterResource
' DESCRIPTION: Stop the given failover cluster resource using WMI.
' PARAMETERS: IN String strResourceName: name of the cluster resource to be stopped.
' IN Object objSWbemServices: SWbemServices object connected to root\MSCluster
' IN/OUT Object colResources: initialised Scripting.Dictionary object
' which contains the names of the
' dependent resources as keys. If the resource
' was not running the corresponding item will
' be set to False otherwise to True.
' IN Long lngTimeOut: timeout for starting or stopping a resource in seconds
' RETURNS: Boolean: True if successful, i.e. the resource is offline
'******************************************************************************
Private Function StopClusterResource(ByRef strResourceName, ByRef objSWbemServices, ByRef colResources, ByRef lngTimeOut) 'As Boolean

Dim objSWbemObject 'As SWbemObject
Dim lngReturn 'As Long
Dim i 'As Long
Dim dblStartTime 'As Double
Dim dblStopTime 'As Double
Dim dblElapsedTime 'As Double

colResources.Item(strResourceName) = False
Set objSWbemObject = objSWbemServices.Get(RESOURCE_WMI_CLASS &amp; ".Name=" &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
If objSWbemObject Is Nothing Then
Call WScript.Echo("Error! Could not retrieve a cluster resource instance with the property Name = " &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
Exit Function
Else
If objSWbemObject.State = STATE_ONLINE Then
colResources.Item(strResourceName) = True
'Start the timer
Call WScript.Echo(" Stopping cluster resource " &amp; objSWbemObject.Name &amp; "...")
dblStartTime = Timer()
Call objSWbemObject.TakeOffline(lngTimeOut)
'Stop the timer
dblStopTime = Timer()
'Calculate the elapsed time
Call ReturnIntervalInMs(dblStartTime, dblStopTime, dblElapsedTime)
Set objSWbemObject = objSWbemServices.Get(RESOURCE_WMI_CLASS &amp; ".Name=" &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
If objSWbemObject.State = STATE_OFFLINE Then
Call WScript.Echo(" Cluster resource " &amp; objSWbemObject.Name &amp; " is now offline. The action took " &amp; CStr(dblElapsedTime) &amp; " ms to complete.")
StopClusterResource = True
Exit Function
Else
Call WScript.Echo(" Error! Failed taking cluster resource " &amp; objSWbemObject.Name &amp; " offline. Waited " &amp; CStr(lngTimeOut) &amp; " for completion.")
End If
Else
Call WScript.Echo(" Cluster resource " &amp; objSWbemObject.Name &amp; " is not online. Skipping.")
StopClusterResource = True
End If
Select Case objSWbemObject.State
Case STATE_UNKNOWN
Call WScript.Echo(" Current state is Unknown (" &amp; STATE_UNKNOWN &amp; ").")
Case STATE_INITIALIZING
Call WScript.Echo(" Current state is Initializing (" &amp; STATE_INITIALIZING &amp; ").")
Case STATE_ONLINE
Call WScript.Echo(" Current state is Online (" &amp; STATE_ONLINE &amp; ").")
Case STATE_FAILED
Call WScript.Echo(" Current state is Failed (" &amp; STATE_FAILED &amp; ").")
Case STATE_PENDING
Call WScript.Echo(" Current state is Pending (" &amp; STATE_PENDING &amp; ").")
Case STATE_ONLINE_PENDING
Call WScript.Echo(" Current state is Online Pending (" &amp; STATE_ONLINE_PENDING &amp; ").")
Case STATE_OFFLINE_PENDING
Call WScript.Echo(" Current state is Offline Pending (" &amp; STATE_OFFLINE_PENDING &amp; ").")
End Select
End If

End Function

'******************************************************************************
' FUNCTION: StartClusterResource
' DESCRIPTION: Start the given failover cluster resource using WMI.
' PARAMETERS: IN String strResourceName: name of the cluster resource to be started.
' IN Object objSWbemServices: SWbemServices object connected to root\MSCluster
' OUT Long lngTimeOut: timeout for starting or stopping a resource in seconds
' RETURNS: Boolean: True if successful, i.e. the resource is running.
'******************************************************************************
Private Function StartClusterResource(ByRef strResourceName, ByRef objSWbemServices, ByRef lngTimeOut) 'As Boolean

Dim objSWbemObject 'As SWbemObject
Dim i 'As Long
Dim lngReturn 'As Long
Dim dblStartTime 'As Double
Dim dblStopTime 'As Double
Dim dblElapsedTime 'As Double

Set objSWbemObject = objSWbemServices.Get(RESOURCE_WMI_CLASS &amp; ".Name=" &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
If objSWbemObject Is Nothing Then
Call WScript.Echo("Error! Could not retrieve a cluster resource instance with the property Name = " &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
Exit Function
Else
If objSWbemObject.State = STATE_OFFLINE Then
'Start the timer
Call WScript.Echo(" Starting cluster resource " &amp; objSWbemObject.Name &amp; "...")
dblStartTime = Timer()
Call objSWbemObject.BringOnline(lngTimeOut)
'Stop the timer
dblStopTime = Timer()
'Calculate the elapsed time
Call ReturnIntervalInMs(dblStartTime, dblStopTime, dblElapsedTime)
Set objSWbemObject = objSWbemServices.Get(RESOURCE_WMI_CLASS &amp; ".Name=" &amp; Chr(34) &amp; strResourceName &amp; Chr(34))
If objSWbemObject.State = STATE_ONLINE Then
Call WScript.Echo(" Cluster resource " &amp; objSWbemObject.Name &amp; " is now online. The action took " &amp; CStr(dblElapsedTime) &amp; " ms to complete.")
StartClusterResource = True
Exit Function
Else
Call WScript.Echo(" Error! Failed bringing cluster resource " &amp; objSWbemObject.Name &amp; " online. Waited " &amp; CStr(lngTimeOut) &amp; " for completion.")
End If
ElseIf objSWbemObject.State = STATE_ONLINE Then
Call WScript.Echo(" Cluster resource" &amp; objSWbemObject.Name &amp; " is already online. Skipping.")
StartClusterResource = True
Exit Function
Else
Call WScript.Echo(" Error! Cannot start Cluster resource " &amp; objSWbemObject.Name &amp; ". Skipping.")
End If
Select Case objSWbemObject.State
Case STATE_UNKNOWN
Call WScript.Echo(" Current state is Unknown (" &amp; STATE_UNKNOWN &amp; ").")
Case STATE_INITIALIZING
Call WScript.Echo(" Current state is Initializing (" &amp; STATE_INITIALIZING &amp; ").")
Case STATE_ONLINE
Call WScript.Echo(" Current state is Online (" &amp; STATE_ONLINE &amp; ").")
Case STATE_OFFLINE
Call WScript.Echo(" Current state is Offline (" &amp; STATE_OFFLINE &amp; ").")
Case STATE_FAILED
Call WScript.Echo(" Current state is Failed (" &amp; STATE_FAILED &amp; ").")
Case STATE_PENDING
Call WScript.Echo(" Current state is Pending (" &amp; STATE_PENDING &amp; ").")
Case STATE_ONLINE_PENDING
Call WScript.Echo(" Current state is Online Pending (" &amp; STATE_ONLINE_PENDING &amp; ").")
Case STATE_OFFLINE_PENDING
Call WScript.Echo(" Current state is Offline Pending (" &amp; STATE_OFFLINE_PENDING &amp; ").")
End Select
End If

End Function

'******************************************************************************
' FUNCTION: CheckResourceDependencies
' DESCRIPTION: Looks if other resources depend on the given resource.
' If there are add them to the dictionary object
' PARAMETERS: IN Object objResource: SWbemObject object representing the cluster resource
' IN Object objSWbemServices: SWbemServices object connected to root\MSCluster
' OUT Object colDependentResources: initialised Scripting.Dictionary object
' which contains the names of the
' dependent resources as keys.
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function CheckResourceDependencies(ByRef objResource, ByRef objSWbemServices, ByRef colDependentResources) 'As Boolean

Dim objSWbemObjectSet 'As SWbemObjectSet
Dim objSWbemObject 'As SWbemObject
Dim objSWbemObjectTmp 'As SWbemObject

'Get all associated MSCluster_Resource objects that depend on the given MSCluster_Resource object
Set objSWbemObjectSet = objResource.Associators_(RESOURCE_TO_DEPENDENT_ASSOC_CLASS, "", ANTECEDENT_QUALIFIER, "", False, False, "", "", 0)
'If there are any add their names as keys
'Do the check recursively to consider the complete dependency tree
If Not objSWbemObjectSet Is Nothing Then
For Each objSWbemObject In objSWbemObjectSet
If Not colDependentResources.Exists(objSWbemObject.Name) Then Call colDependentResources.Add(objSWbemObject.Name, "")
'Recursive
Call CheckResourceDependencies(objSWbemObject, objSWbemServices, colDependentResources)
Next
End If

CheckResourceDependencies = True

End Function

'******************************************************************************
' FUNCTION: GetScriptParameters
' DESCRIPTION: Reads the script's parameters and sets the variables accordingly.
' PARAMETERS: OUT String strResourceName: the name of the resource to be restarted
' OUT Long lngTimeOut: timeout for starting or stopping a resource in seconds
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function GetScriptParameters(ByRef strResourceName, ByRef lngTimeOut) 'As Boolean

Dim objArguments

On Error Resume Next

Set objArguments = WScript.Arguments
If objArguments.Count &lt; 1 Then Exit Function

'Get parameters and set global variables
strResourceName = objArguments(0)
If objArguments.Count &gt; 1 Then lngTimeOut = CLng(objArguments(1))
If lngTimeOut &lt; RESOURCE_START_STOP_MIN_TIMEOUT Then lngTimeOut = RESOURCE_START_STOP_MIN_TIMEOUT

If Len(strResourceName) &gt; 0 Then GetScriptParameters = True

End Function

'******************************************************************************
' FUNCTION: ConnectToWbemNS
' DESCRIPTION: Connects to a WMI namespace
' PARAMETERS: IN String strServerName: name of the computer. If empty the local computer will be used.
' IN String strNameSpace: WMI namespace
' OUT Object objSWbemServices: WbemScripting.SWbemServices object
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function ConnectToWbemNS(ByRef strServerName, ByRef strNameSpace, ByRef objSWbemServices) 'As Boolean

Dim objSWbemLocator 'as WbemScripting.SWbemLocator

'Create a new WMI Locator object
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")

'Connect to WMI namespace on strServerName computer and create WMI Services object
Set objSWbemServices = objSWbemLocator.ConnectServer(strServerName, strNameSpace)

'Connect to WMI namespace on strServerName computer with alternative credentials and create WMI Services object
'Set objSWbemServices = objSWbemLocator.ConnectServer(strServerName, strNameSpace, strUserName, strPassWd)

'If object is initialised function will be successful
If objSWbemServices Is Nothing Then ConnectToWbemNS = False Else ConnectToWbemNS = True

End Function

'**************************************************************
' FUNCTION: ReturnIntervalInMs
' DESCRIPTION: Calculate response time
' Timer() returns seconds since midnight. If the date changes between
' start and stop, 86400 s (24 hrs) have to be added to stop.
' Because OpsMgr scripts run less than 1 hrs no other scenarios are considered.
' PARAMETERS: IN Double dblStart - Timer value when started
' IN Doube dblStop - Timer value when stopped
' RETURNS: Boolean
'**************************************************************
Private Function ReturnIntervalInMs(ByRef dblStart, ByRef dblStop, ByRef dblInterval) 'As Boolean

On Error Resume Next

If dblStart &gt; dblStop Then dblStop = dblStop + 86400
dblInterval = (dblStop - dblStart) * 1000

If Not IsEmpty(dblInterval) Then ReturnIntervalInMs = True

End Function
</Script></ScriptBody>
<TimeoutSeconds>$Config/ScriptTimeoutSeconds$</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="Script"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>