클러스터 리소스 그룹 실행 방법

Microsoft.Windows.Cluster.Group.Action (WriteActionModuleType)

이 쓰기 작업은 Windows 클러스터 그룹에서 작업을 실행합니다.

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityInternal
RunAsMicrosoft.Windows.Cluster.PrivilegedAccount
InputTypeSystem.BaseData

Member Modules:

ID Module Type TypeId RunAs 
WA WriteAction System.CommandExecuter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
TimeoutSecondsint$Config/TimeoutSeconds$시간 제한(초)

Source Code:

<WriteActionModuleType ID="Microsoft.Windows.Cluster.Group.Action" Accessibility="Internal" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false">
<Configuration>
<xsd:element name="NodeName" type="xsd:string"/>
<xsd:element name="GroupName" type="xsd:string"/>
<xsd:element name="MethodName" type="xsd:string"/>
<xsd:element name="TimeoutSeconds" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="WA" TypeID="System!System.CommandExecuter">
<ApplicationName/>
<WorkingDirectory/>
<CommandLine>cscript ClusterGroupMethod.vbs "$Config/NodeName$" "$Config/GroupName$" "$Config/MethodName$" "$Config/TimeoutSeconds$"</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>ClusterGroupMethod.vbs</Name>
<Contents><Script>
'Copyright (c) Microsoft Corporation. All rights reserved.
Option Explicit

SetLocale("en-us")

Dim g_oUtil
Set g_oUtil = New Util

Call g_oUtil.SetDebugLevel(g_oUtil.DBG_NONE)

Dim g_oClusterUtil
Set g_oClusterUtil = new ClusterUtil

Dim oArgs
Set oArgs = WScript.Arguments

If oArgs.Count &lt; 3 Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Need to provide arguments"

Wscript.Quit -1
End If

'==========================================================================
' Initialize the arguments in VBScript
'==========================================================================

Dim NodeName
NodeName = oArgs(0)

Dim GroupName
GroupName = oArgs(1)

Dim MethodName
MethodName = oArgs(2)

Dim timeoutInSeconds
timeoutInSeconds = oArgs(3)

'==========================================================================
' Main
'==========================================================================

Call Main()

'==========================================================================
' FUNCTIONS
'==========================================================================

Sub Main()

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Started at machine local time: " &amp; CStr(Time)

Dim e
Set e = New Error
On Error Resume Next

Dim Service
Set Service = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" &amp; NodeName &amp; "\root\mscluster")

e.Save
On Error Goto 0
If IsEmpty(Service) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Unable to connect.", e
End If
On Error Resume Next

Dim oGroup
Set oGroup = Service.ExecQuery("select Name, State from MSCluster_ResourceGroup where Name = """ &amp; g_oClusterUtil.EscapeString(GroupName) &amp; """")

e.Save
On Error Goto 0
If IsEmpty(oGroup) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

Dim oRealGroup
For Each oRealGroup in oGroup

Select Case MethodName

Case "Delete" Call DeleteGroup(Service, oRealGroup)
Case "Move" Call MoveToNextNode(Service, oRealGroup)

Case "Online"
WScript.Echo "The state of the " &amp; oRealGroup.Name &amp; " resource group is " &amp; ConvertNumericResourceGroupStateToString (oRealGroup.State)
WScript.Echo "Attempting to bring the resource group online"

oRealGroup.BringOnline(timeoutInSeconds)

Set oRealGroup = Service.Get(oRealGroup.Path_)
WScript.Echo "The state of the " &amp; oRealGroup.Name &amp; " resource group is " &amp; ConvertNumericResourceGroupStateToString (oRealGroup.State)

Case "Offline"
WScript.Echo "The state of the " &amp; oRealGroup.Name &amp; " resource group is " &amp; ConvertNumericResourceGroupStateToString (oRealGroup.State)
WScript.Echo "Attempting to take the resource group offline"

oRealGroup.TakeOffline(timeoutInSeconds)

Set oRealGroup = Service.Get(oRealGroup.Path_)
WScript.Echo "The state of the " &amp; oRealGroup.Name &amp; " resource group is " &amp; ConvertNumericResourceGroupStateToString (oRealGroup.State)

Case Else g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Unrecognized method " &amp; MethodName &amp; " used"

End Select

Next

g_oUtil.LogMessageNewLine _
g_oUtil.DBG_TRACE, _
"Finished at machine local time: " &amp; CStr(Time)

End Sub

Function ConvertNumericResourceGroupStateToString(ByVal state)

Dim textualState

Select Case state
Case 0
textualState = "Online"
Case 1
textualState = "Offline"
Case 2
textualState = "Failed"
Case 3
textualState = "Partial Online"
Case 4
textualState = "Pending"
Case Else
textualState = "Unknown"
End Select

ConvertNumericResourceGroupStateToString = textualState

End Function

Sub DeleteGroup ( _
ByRef oService, _
ByRef oGroup _
)

Dim e
Set e = New Error
On Error Resume Next

Dim DoLoop
DoLoop = True

While DoLoop
Dim oResources
Set oResources = oService.ExecQuery("select GroupComponent, PartComponent from MSCluster_ResourceGroupToResource where GroupComponent = ""MSCluster_ResourceGroup.Name=\""" &amp; g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oGroup.Name))) &amp; "\""""")

e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query for resources returned an error. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

If IsEmpty(oResources) Or oResources.Count = 0 Then
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"No more resources in group " &amp; oGroup.Name

DoLoop = False
Else

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
oResources.Count &amp; " resources in group " &amp; oGroup.Name

Dim oResource
For Each oResource in oResources

Dim oRes
Set oRes = oService.Get(oResource.PartComponent)

e.Save
On Error Goto 0
If IsNull(oRes) Then
Exit For
End If
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Did not get a resource. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

Dim oDepResources
Set oDepResources = oService.ExecQuery("select Antecedent, Dependent from MSCluster_ResourceToDependentResource where Dependent = ""MSCluster_Resource.Name=\""" &amp; g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oRes.Name))) &amp; "\""""")

e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query for dependent resources returned an error. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

If IsEmpty(oDepResources) Or oDepResources.Count = 0 Then
DeleteResource (oRes)
End If

Next

End If

Wend

oGroup.DeleteGroup
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Unable to delete resource group.", e
End If
On Error Resume Next

End Sub

Sub DeleteResource (_
ByRef oRes _
)

Dim e
Set e = New Error
On Error Resume Next

If Not ( oRes.State = 4 ) Then
oRes.TakeOffline 32,767
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Unable to take resource " &amp; oRes.Name &amp; " offline.", e
End If
On Error Resume Next
End If

oRes.DeleteResource
e.Save
On Error Goto 0
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Unable to delete resource " &amp; oRes.Name &amp; "." , e
End If
On Error Resume Next

End Sub

Sub MoveToNextNode ( _
ByRef oService, _
ByRef oGroup _
)

Dim e
Set e = New Error
On Error Resume Next

Dim oActiveNode
Set oActiveNode = oService.ExecQuery("select GroupComponent, PartComponent from MSCluster_NodeToActiveGroup where PartComponent = ""MSCluster_ResourceGroup.Name=\""" &amp; g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oGroup.Name))) &amp; "\""""")

e.Save
On Error Goto 0
If IsEmpty(oActiveNode) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query for active node returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

Dim newNodeName
newNodeName = NodeName

If oActiveNode.Count &gt; 0 Then
Dim oNode
For Each oNode in oActiveNode

Dim oActive
Set oActive = oService.Get(oNode.GroupComponent)

e.Save
On Error Goto 0
If IsNull(oActive) Then
Exit For
End If
If e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Did not get a Node. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

Dim oNodes
Set oNodes = oService.ExecQuery("select Name, State from MSCluster_Node where Name != '" &amp; oActive.Name &amp; "'")

e.Save
On Error Goto 0
If IsEmpty(oNodes) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "The Query for nodes returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next

Dim oNextNode
For Each oNextNode in oNodes

' only move when node is online
If oNextNode.State = 0 Then
newNodeName = oNextNode.Name

g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Trying to move group " &amp; oGroup.Name &amp; " to node " &amp; newNodeName

e.Save
On Error Goto 0
If IsEmpty(oNodes) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Get node name failed.", e
End If
On Error Resume Next

Call oGroup.MoveToNewNode ( newNodeName, 32,767 )

e.Save
On Error Goto 0
If IsEmpty(oNodes) Or e.Number &lt;&gt; 0 Then
g_oUtil.ThrowScriptError "Move to new node failed.", e
End If
On Error Resume Next

Exit Sub
End If
Next

Exit For
Next
End If

g_oUtil.ThrowScriptError "Unable to move group " &amp; oGroup.Name &amp; " as there are no online nodes.", -1

End Sub

'==========================================================================
' Description: HELPERS
'==========================================================================

Class Error
Public Description
Public Number
Public Source

Sub Class_Initialize()
Number = 0
End Sub

Sub Save
Description = Err.Description
Number = Err.Number
Source = Err.Source
Err.Clear
End Sub

Sub Raise(strDescription)
Err.Raise Number, Source, strDescription &amp; GetErrorString(Number, Description)
End Sub
End Class

'==========================================================================
' Class: ClusterUtil
' Description: Utility methods for clustering
'==========================================================================
Class ClusterUtil

'**********************************************************************
Public Function EscapeString(ByVal sText)
Const METACHARACTERS = """"
Dim sResult
Dim i
For i = 1 To Len(sText)
Dim sCurrentChar
sCurrentChar = Mid(sText, i, 1)
If InStr(METACHARACTERS, sCurrentChar) &lt;&gt; 0 Then
sResult = sResult &amp; "\"
End If
sResult = sResult &amp; sCurrentChar
Next
EscapeString = sResult
End Function

End Class 'ClusterUtil

'==========================================================================
' Class: Util
' Description: Utility methods for logging
'==========================================================================
Class Util

'**********************************************************************
Public Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
LogMessage _
DBG_ERROR, _
sMessage &amp; vbCrLf &amp; oErr.Description

Set ThrowScriptErrorNoAbort = Nothing
End Function

'**********************************************************************
Public Function ThrowScriptError(Byval sMessage, ByVal oErr)
ThrowScriptErrorNoAbort sMessage, oErr
Quit
Set ThrowScriptError = Nothing
End Function

Public Function Quit
LogMessage _
DBG_ERROR, _
"Terminated on error!"

Wscript.Quit -1
End Function

' Used to say to LogMessage when/how to print the message.
Public DBG_NONE
Public DBG_ERROR
Public DBG_WARNING
Public DBG_TRACE

'Internal Debug Level
Private m_nDebugLevel

'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
' Initialize Debug level constants
DBG_TRACE = 1
DBG_WARNING = 2
DBG_ERROR = 3
DBG_NONE = 4

'by default only errors are logged
m_nDebugLevel = DBG_ERROR

End Sub

'======================================================================
' Method: GetCurrentLevel
' Description: retrieve current logging level.
' Parameters:
'======================================================================
Public Function GetCurrentLevel()
GetCurrentLevel = m_nDebugLevel
End Function

'======================================================================
' Method: SetDebugLevel
' Description: To change the debugging output level of information
' generated by this utility.
' Parameters:
' nLevel - DBG_NONE, DBG_TRACE, DBG_WARNING or DBG_ERROR
'======================================================================
Public Sub SetDebugLevel(ByVal nLevel)
m_nDebugLevel = nLevel
End Sub

'======================================================================
' Method: LogMessage
' Description: Log a debug message to ScriptContext
' Parameters:
' nLevel - Debug level for the message that
' we're logging.
' strMessage - The message to write to the trace.
'======================================================================
Public Sub LogMessage( _
ByVal nLevel, _
ByVal strMessage _
)
If (nLevel &gt;= GetCurrentLevel()) Then
if (nLevel = DBG_ERROR) Then
WScript.Echo "[Error]: " &amp; strMessage
ElseIf (nLevel = DBG_WARNING) Then
WScript.Echo "[Warning]: " &amp; strMessage
ElseIf (nLevel = DBG_TRACE) Then
WScript.Echo "[Trace]: " &amp; strMessage
End If
End If
End Sub
Public Sub LogMessageNewLine( _
ByVal nLevel, _
ByVal strMessage _
)
If (nLevel &gt;= GetCurrentLevel()) Then
if (nLevel = DBG_ERROR) Then
WScript.Echo vbCrLf &amp; "[Error]: " &amp; strMessage
ElseIf (nLevel = DBG_WARNING) Then
WScript.Echo vbCrLf &amp; "[Warning]: " &amp; strMessage
ElseIf (nLevel = DBG_TRACE) Then
WScript.Echo vbCrLf &amp; "[Trace]: " &amp; strMessage
End If
End If
End Sub

End Class ' Util
</Script></Contents>
<Unicode>false</Unicode>
</File>
</Files>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="WA"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>