Execute Cluster Resource Group Method

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

This write action executes operations in windows cluster group.

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$Timeout(sec)

Source Code:

<WriteActionModuleType ID="Microsoft.Windows.Cluster.Group.Action" Accessibility="Internal" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NodeName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="GroupName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="MethodName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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>%SystemRoot%\system32\cmd.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>/c $file/Main.cmd$</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Main.cmd</Name>
<Contents><Script>

@echo off

set psscript=ClusterGroupMethod.ps1
set vbscript=ClusterGroupMethod.js

set cscript=%windir%\system32\cscript.exe
set ps=%windir%\system32\WindowsPowerShell\v1.0\powershell.exe
set params=

if Exist "%cscript%" goto vb
if Exist "%ps%" goto pshell
goto end
:vb
if not exist "%~dp0%vbscript%" goto end

"%cscript%" /nologo "%~dp0%vbscript%"
goto end
:pshell
if not exist "%~dp0%psscript%" goto end

"%ps%" -nologo -EP bypass -command "&amp; '%~dp0%psscript%'"
goto end

:end



</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>ClusterGroupMethod.ps1</Name>
<Contents><Script>

function Get-CmdFilename([string]$fullname)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$fileparam = "psparams.txt"
$fullnameparams = ".\$fileparam"
$fullparams = [System.IO.Path]::GetFullPath($fullnameparams)
if (0 -ne $error.Count)
{
$error.Clear()
$fullparams = $fullnameparams
}

if ($false -eq [string]::IsNullOrEmpty($fullname))
{
$error.Clear()
$fullnameparams = [System.IO.Path]::GetDirectoryName($fullname)
if (0 -eq $error.Count)
{
$fullpath = [System.IO.Path]::Combine($fullnameparams,$fileparam)
if (0 -ne $error.Count)
{
$error.Clear()
$fullpath = $fullnameparams + "\" + $fileparam
}

$fullparams = $fullpath
}
}

$error.Clear()
$IsFlag = $null
$IsFlag = [System.IO.File]::Exists($fullparams)

if ($null -eq $IsFlag)
{
$error.Clear()
return $null
}

if ($false -eq $IsFlag )
{
$fullparams = $null
}

$error.Clear()

return $fullparams
}

Function Parse-Params([string]$Value)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

if ([string]::IsNullOrEmpty($Value))
{
return null
}

$i = $Value.IndexOf("=")
if (-1 -eq $i) { return $null; }

$i++;

$result = ""

if ($i -le $Value.Length )
{
$result = $Value.Substring($i)
}

return $result
}

Function Get-CmdParams([string]$fullname,[int]$MaxCount=0)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

if ($MaxCount -lt 0)
{
$MaxCount = 0
}

$filename = Get-CmdFilename -fullname $fullname

if ($null -eq $filename)
{
return $null
}

$ap = Get-Content -Path $filename -Force

if (0 -ne $error.Count)
{
return $null
}

if (0 -eq $ap.Length)
{
return $null
}

$result = @()
$i = 0
foreach($d in $ap)
{
$p = Parse-Params -Value $d
if ($null -ne $p)
{
$i++
if ($i -gt $MaxCount -and 0 -ne $MaxCount) { break; }
$result += $p
}
}

return $result
}

function Check-WmiMethod($oObject,[string]$MethodName,$useCim) #As Boolean
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$method = $null

if ([string]::IsNullOrEmpty($oObject))
{
return $NodeName
}


if($true -eq $useCim)
{
$method = $oObject | Get-Member -Name $MethodName -MemberType Method
}
else
{
$methods = $oObject.CimClass.CimClassMethods
if($null -ne $methods)
{
$method = $methods[$MethodName]
}
}

$result = ($null -ne $method -and 0 -eq $error.Count )

return $result;
}

Function CheckCimModule()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$retval = $false
$cim = Get-Module -Name CimCmdlets

########Check for powershell 1.0
if ($error.Count -ne 0)
{
if ($null -eq $error[0].Exception)
{
return $retval
}

$type = $error[0].Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
return $retval
}

$error.Clear()
}

if ($null -eq $cim)
{
Import-Module CimCmdLets
if ($error.Count -eq 0)
{
$retval = $true
}

$error.Clear()
}
else
{
$retval = $true
}

return $retval
}

function CheckCmdLets()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$retval = $false
$objSWbemObjectSet =$null

if (CheckCimModule)
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$objSWbemObjectSet = Get-CimInstance -CimSession $cimsession -Class Win32_OperatingSystem
}
catch
{
$objSWbemObjectSet = Get-WMIObject -Class Win32_OperatingSystem
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -eq 0)
{
$retval = $true
}
}

$error.Clear()
return $retval;
}

function Check-CimInstance($oWmiInstance)
{
$result = $null

if([string]::IsNullOrEmpty($oWmiInstance))
{
return $result
}

$type = $oWmiInstance.GetType()
if([string]::IsNullOrEmpty($type))
{
return $result
}

$useCim = $type.Fullname -eq "Microsoft.Management.Infrastructure.CimInstance"
if ($true -eq $useCim)
{
return $useCim
}

$useCim = $type.Fullname -eq "System.Management.ManagementObject"
if ($true -eq $useCim)
{
$result = $false
}

return $result
}

Function Get-WmiEscapedName([string]$Name)
{
$Name = ($Name -replace "\\", "\\") -replace "'","\'"

return $Name
}

Function Get-WmiCimSession([string]$ComputerName)
{
$ErrorActionPreference = 'SilentlyContinue'
$Error.Clear()

$CimSession = = $null
$CimSession = = Get-CimSession -ComputerName $ComputerName

if ($null -eq $CimSession)
{
$Error.Clear()
$CimSession = New-CimSession -ComputerName $ComputerName
}
else
{
if ($CimSession.Count -gt 1)
{
$CimSession = $cims[0]
}

}

return $CimSession
}

Function Get-WmiCimAssociatorInstance
{
param (
[string]$ComputerName,
[string]$sNamespace,
[string]$sAssociatorName,
$oWmiInstance,
[string]$relatedClass,
[string]$Source,
[string]$Target,
$CimSession
)

$ErrorActionPreference = 'SilentlyContinue'
$Error.Clear()

$result = $null

if ([string]::IsNullOrEmpty($CimSession))
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
}
else
{
$type = $CimSession.GetType()
if ([string]::IsNullOrEmpty($type))
{
return $result
}

if ("Microsoft.Management.Infrastructure.CimSession" -ne $type.FullName)
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
}

}

if (0 -ne $Error.Count)
{
return $result
}
$result = $CimSession.EnumerateAssociatedInstances($sNamespace,$oWmiInstance,$sAssociatorName,$relatedClass,$Source,$Target)

return $result
}

Function Get-WmiAssociatorInstanceNoAbort
{
param (
[string]$ComputerName,
[string]$sNamespace,
[string]$sAssociatorName,
$oWmiInstance,
[string]$relatedClass,
[string]$Source,
[string]$Target,
$CimSession
)

$ErrorActionPreference = 'SilentlyContinue'
if ([string]::IsNullOrEmpty($ComputerName))
{
$ComputerName = "."
}

$Error.Clear()

$oInstance = $null
$result = @()

if([string]::IsNullOrEmpty($oWmiInstance))
{
return $result
}

$useCim = Check-CimInstance -oWmiInstance $oWmiInstance

if ($null -eq $useCim)
{
return $result
}

if ($true -eq $useCim)
{
$oInstance = Get-WmiCimAssociatorInstance -ComputerName $ComputerName -sNamespace $sNamespace -sAssociatorName $sAssociatorName -oWmiInstance $oWmiInstance -Source $Source -Target $Target -CimSession $CimSession
}
else
{
$oInstance = $oWmiInstance.GetRelated($relatedClass,$sAssociatorName,$null,$null,$Target,$Source,$null,$null)
}

if ($null -eq $oInstance)
{

return $null
}

$result += $oInstance

return $result
}

Function Get-WmiInstanceNoAbort
{
param (
[string]$ComputerName,
[string]$sNamespace,
[string]$sClassName,
[string]$sFilter,
[bool] $useCim
)

$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$KerberosErrorCode = 2147943712
$ConnectionErrorCode = 2147942453
$WmiConnectErrorCode = -2147023174

if ([string]::IsNullOrEmpty($ComputerName))
{
$ComputerName = "."
}

if ([string]::IsNullOrEmpty($sNamespace))
{
$sNamespace = "root\cimv2"
}

if ($true -eq $useCim)
{
$oInstance = $null
if ([string]::IsNullOrEmpty($sFilter))
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName -ComputerName $ComputerName
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorData.Error_code
If ($KerberosErrorCode -eq $ErrorCode -or $ConnectionErrorCode -eq $ErrorCode)
{
$error.Clear()
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}
}
}
else
{
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $ComputerName -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName -Filter $sFilter
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName -ComputerName $ComputerName -Filter $sFilter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorData.Error_code
If ($KerberosErrorCode -eq $ErrorCode -or $ConnectionErrorCode -eq $ErrorCode)
{
$error.Clear()
Load-CimModules
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$oInstance = Get-CimInstance -CimSession $cimsession -Namespace $sNamespace -ClassName $sClassName -Filter $sFilter
}
catch
{
$oInstance = Get-WMIObject -Namespace $sNamespace -ClassName $sClassName -Filter $sFilter
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}
}

}
}
else
{
$oInstance = $null
if ([string]::IsNullOrEmpty($sFilter))
{
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace -ComputerName $ComputerName
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorCode
If ($WmiConnectErrorCode -eq $ErrorCode)
{
$error.Clear()
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace
}
}
}
else
{
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace -Filter $sFilter -ComputerName $ComputerName
if ($error.Count -ne 0)
{
$ErrorCode = $error[0].Exception.ErrorCode
If ($WmiConnectErrorCode -eq $ErrorCode)
{
$error.Clear()
$oInstance = Get-WmiObject -Class $sClassName -Namespace $sNamespace -Filter $sFilter
}
}

}
}

return $oInstance
}

Function ConvertNumericResourceStateToString($state)
{
if ($null -eq $state)
{
return "Unknown"
}

$States = @{[uint32]0 = "Inherited";[uint32]1 = "Initializing";[uint32]2 = "Online";[uint32]3 = "Offline";[uint32]4 = "Failed";[uint32]128 = "Pending";[uint32]129 = " Online Pending";[uint32]130 = "Offline Pending"}
$textualState = $States[$state]

if ($null -eq $textualState)
{
$textualState = "Unknown"
}

return $textualState;
}

Function ConvertNumericResourceGroupStateToString($state)
{
if ($null -eq $state)
{
return "Unknown"
}

$States = @{[uint32]0 = "Online";[uint32]1 = "Offline";[uint32]2 = "Failed";[uint32]3 = "Partially Online";[uint32]4 = "Pending"}
$textualState = $States[$state]

if ($null -eq $textualState)
{
$textualState = "Unknown"
}

return $textualState;
}


Function Load-CimModules
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$CimModule = Get-Module CimCmdlets

if ($null -eq $CimModule)
{
Import-Module CimCmdlets
$error.Clear()

}
}

#==========================================================================
# FUNCTIONS
#==========================================================================

function Main()
{

if([string]::IsNullOrEmpty($GroupName))
{
Write-Host "Group name is empty."
return
}

if ([string] -ne $GroupName.GetType())
{
Write-Host "Group name is empty."
return
}

if ([string]::IsNullOrEmpty($GroupName.Trim()))
{
Write-Host "Group name is empty."
return
}


if([string]::IsNullOrEmpty($NodeName))
{
Write-Host "Node name is empty."
return
}

if ([string] -ne $NodeName.GetType())
{
Write-Host "Node name is empty."
return
}

if ([string]::IsNullOrEmpty($NodeName.Trim()))
{
Write-Host "Node name is empty."
return
}

if ("Move" -ne $MethodName -and ("Cluster Group" -eq $GroupName -or "Available Storage" -eq $GroupName) )
{
Write-Host "Cannot provide this operation on Core Cluster Group."
return

}

$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$useCim = CheckCmdLets
if ($null -eq $useCim)
{
Write-Host "Cannot get wmi cmdlets version."
return
}

$oGroup = Get-ClusterGroup -useCim $useCim -GroupName $GroupName

if(0 -ne $error.Count)
{
$e = $error[0].Exception.Message
Write-Host "Cannot get cluster group from wmi. Error: $e"
return
}

if ($null -eq $oGroup)
{
Write-Host "Cluster resource group $GroupName is not found."
return

}

switch($MethodName)
{

"Delete"{
Delete-Group -oGroup $oGroup
break;
}
"Move"{
MoveToNextNode -oGroup $oGroup
break;
}
"Online" {
Bring-Online -oGroup $oGroup -Offline $false -timeoutInSeconds $timeoutInSeconds
break;
}
"Offline"{
Bring-Online -oGroup $oGroup -Offline $true -timeoutInSeconds $timeoutInSeconds
break;
}default{
write-host "[Error]: " "Unrecognized method " $MethodName " used"
}

}

}

function Get-OwnerSet($cols,[HashTable]$Set,$IsFirst)
{
$result = @{}

if ($true -eq $IsFirst)
{
foreach ($col in $cols)
{
if($false -eq [string]::IsNullOrEmpty($col.Name))
{
$nodeName = $col.Name.ToLower()
$result[$nodeName] = 1;

}
}

}
else
{
$Count = $cols.Count

if ($null -eq $Count)
{
if ($null -eq $cols)
{
$Count = 0
}
else
{
$Count = 1
}
}

if (0 -eq $Count)
{
return $result;
}

foreach ($col in $cols)
{
if($false -eq [string]::IsNullOrEmpty($col.Name))
{
$nodeName = $col.Name.ToLower()
if(1 -eq $Set[$nodeName])
{
$result[$nodeName] = 1;
}
}
}
}

return $result

}

Function Get-ClusterGroup([string]$GroupName,$useCim)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$NameSpace = "root\mscluster"
$ClassName = "MSCluster_ResourceGroup"
$EscapeGroupName = Get-WmiEscapedName -Name $GroupName
$Filter = "Name='$EscapeGroupName'"
$oGroup = $null

$oGroup = Get-WmiInstanceNoAbort -ComputerName $NodeName -sNamespace $NameSpace -sClassName $ClassName -sFilter $Filter -useCim $useCim

if ($oGroup.Count -gt 1 )
{
$oGroup = $oGroup[0]
}

return $oGroup
}

Function Get-ClusterActiveNodes($oGroup,[ref]$oldOwner)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$NameSpace = "root\mscluster"
$Assoc = "MSCluster_NodeToActiveGroup"
$rClass = "MSCluster_Node"
$ClassName = "MSCluster_Node"

$oNode = $null

if ([string]::IsNullOrEmpty($oGroup))
{
return $oNode
}

$oNode = Get-WmiAssociatorInstanceNoAbort -sNamespace $NameSpace -sAssociatorName $Assoc -relatedClass $rClass -oWmiInstance $oGroup -ComputerName $NodeName

if (0 -ne $error.Count)
{
return $null
}

if($null -eq $oNode -or 0 -eq $oNode.Count)
{
return $null
}

if($oNode.Count -gt 1)
{
$oNode = $oNode[0]
}

if ([string]::IsNullOrEmpty($oNode.Name) )
{
return $null
}

$oldName = $oNode.Name

if ($null -ne $oldOwner )
{
$oldOwner.Value = $oldName
}

$Filter = "Name != '$($oNode.Name)' and State = 0"
$useCim = Check-CimInstance -oWmiInstance $oGroup

$Nodes = Get-WmiInstanceNoAbort -sNamespace $NameSpace -sClassName $ClassName -sFilter $Filter -useCim $useCim -ComputerName $NodeName

if ($null -eq $Nodes)
{
return $null
}

$result = @{}

foreach($node in $Nodes)
{
if ([string]::IsNullOrEmpty($node.Name) )
{
continue
}

$nodeName = $node.Name.ToLower()
$result[$nodeName] =1
}

if (0 -eq $result.Count)
{
$result = $null
}

return $result
}

Function Get-PreferredNodes($oGroup)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$NameSpace = "root\mscluster"
$Assoc = "MSCluster_ResourceGroupToPreferredNode"
$rClass = "MSCluster_Node"

$oNodes = $null

if ([string]::IsNullOrEmpty($oGroup))
{

return $oNodes
}

$oNodes = Get-WmiAssociatorInstanceNoAbort -sNamespace $NameSpace -sAssociatorName $Assoc -relatedClass $rClass -oWmiInstance $oGroup -ComputerName $NodeName

if (0 -ne $error.Count)
{
$error.Clear()
return $null
}

if($null -eq $oNodes -or 0 -eq $oNodes.Count)
{
return $null
}


return $oNodes
}

function Get-PossibleGroupOwner(
$oGroup
)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$result = $null
$ClassName = "MSCluster_ResourceGroupToResource"
$DepAssoc = "MSCluster_ResourceToPossibleOwner"
$wmiAssoc = "MSCluster_Resource"
$rNodeClass = "MSCluster_Node"
$NameSpace = "root\mscluster"

if ([string]::IsNullOrEmpty($oGroup))
{
write-host "[Error]: Group is empty. "
return
}

$useCim = Check-CimInstance -oWmiInstance $oGroup

if($null -eq $useCim)
{
return $result
}

$oResources = $null
$oResources = Get-WmiAssociatorInstanceNoAbort -ComputerName $NodeName -sNamespace $NameSpace -sAssociatorName $ClassName -oWmiInstance $oGroup -relatedClass $wmiAssoc

if(0 -ne $error.Count)
{
$e = $error[0].Exception.Message
Write-Host "Cannot get resources in the group. Error: $e"
return $result
}

if($null -eq $oResources )
{
return $oResources
}

$nSet = @{}
$IsFirst = $true
$IsNullSet = $true

ForEach($oResource in $oResources)
{
$oPosNodes = $null
$oPosNodes = Get-WmiAssociatorInstanceNoAbort -ComputerName $NodeName -sNamespace $NameSpace -sAssociatorName $DepAssoc -oWmiInstance $oResource -relatedClass $rNodeClass

If(0 -ne $error.Count)
{
$e = $error[0].Exception.Message
Write-Host "Cannot get possible owners of the resources. Error: $e"
return $result
}

If($null -eq $oPosNodes)
{
continue
}
else
{
$nSet = Get-OwnerSet -cols $oPosNodes -Set $nSet -IsFirst $IsFirst
if ($true -eq $IsFirst)
{
if ($nSet.Count -gt 0)
{
$IsFirst = $false;
$IsNullSet = $false;
}
}

}

}

if (0 -eq $nSet.Count)
{
Write-Host "Cannot get possible owners of the resources. "
exit
}

if ($true -eq $IsNullSet )
{

$nSet = $null

}

return $nSet;
}

Function Get-IntersectionOfSets([hashtable]$Nodes,[hashtable]$Set)
{
$result = $null
if ($null -eq $Nodes -or $null -eq $Set -or 0 -eq $Set.Count -or 0 -eq $Nodes.Count)
{
return $result
}

$result = @{}

foreach ($nodeName in $Nodes.keys)
{
if ([string]::IsNullOrEmpty($nodeName))
{
continue
}

if ($true -eq $Set.Contains($nodeName))
{
$result[$nodeName] = 1
}

}

if (0 -eq $result.Count)
{
$result = $null
}

return $result
}

function Get-NodeToMove($oGroup, [ref]$oldOwner)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

$result = $null
$useCim = Check-CimInstance -oWmiInstance $oGroup

if($null -eq $useCim)
{
return $result
}

$RealGroupName = $oGroup.Name

if ([string]::IsNullOrEmpty($RealGroupName))
{
Write-Host "Group Name is empty."
return $result
}

$oldName = ""
$ActiveNodes = Get-ClusterActiveNodes -oGroup $oGroup -oldOwner ([ref] $oldName)

if ($false -eq [string]::IsNullOrEmpty($oldName))
{
if ($null -ne $oldOwner)
{
$oldOwner.Value = $oldName
}
}

If(0 -ne $error.Count -or $null -eq $ActiveNodes){
$e = $error[0].Exception.Message
Write-Host "Cannot get available online nodes. $e"
return $result
}

$posNodes = Get-PossibleGroupOwner -oGroup $oGroup
If(0 -ne $error.Count){
$e = $error[0].Exception.Message
Write-Host "Cannot get possible group owners. $e"
return $result
}

if ($null -eq $posNodes)
{
$avNodes = $ActiveNodes
}
else
{
$avNodes = Get-IntersectionOfSets -Nodes $ActiveNodes -Set $posNodes
}

if($null -eq $avNodes)
{
return $null
}

$prNodes = Get-PreferredNodes -oGroup $oGroup

$nodeName = $null
if ($null -eq $prNodes)
{
foreach($nodeName in $avNodes.keys)
{
break
}

return $nodeName
}

foreach ($node in $prNodes)
{
if ([string]::IsNullOrEmpty($node.Name))
{
continue
}

$nodName = $node.Name.ToLower()
if ($avNodes.Contains($nodName))
{
return $nodName
}
}

if ($null -eq $nodeName)
{
foreach($nodeName in $avNodes.keys)
{
break
}


}

return $nodeName
}

Function Bring-Online($oGroup,$Offline,$timeoutInSeconds)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

if ([string]::IsNullOrEmpty($oGroup))
{
write-host "[Error]: Group is empty. "
return
}

$gState = ConvertNumericResourceGroupStateToString $oGroup.State
Write-Host "The state of the Group [$($oGroup.Name)] is $gState"

If ($true -eq $Offline)
{
$state = 1
$StrState = "offline"
$method = "TakeOffline"
}
else
{
$state = 0
$StrState = "online"
$method = "BringOnline"

}

if( $state -eq $oGroup.State)
{
Write-Host "The state of the resource [$($oGroup.Name)] is already $StrState."
return
}

if ([string]::IsNullOrEmpty($timeoutInSeconds))
{
$timeoutInSeconds = $DefaultTimeOut
}
else
{
$error.Clear()
$timeoutInSeconds = [int32]$timeoutInSeconds
if(0 -ne $error.Count)
{
$timeoutInSeconds = $DefaultTimeOut
$error.Clear()
}
}

$useCim = Check-CimInstance -oWmiInstance $oGroup

if ([string]::IsNullOrEmpty($useCim))
{
write-host "[Error]: Wrong wmi object provided. "
return
}

Write-Host "Attempting to bring the resource group $StrState"
if($true -eq $useCim)
{
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -SessionOption $cimSessionOption
$result = invoke-CimMethod -CimSession $cimsession -InputObject $oGroup -MethodName $method &#x2013;Arguments @{ TimeOut = $timeoutInSeconds }
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
} elseif($false -eq $useCim)
{

if ($true -eq $Offline)
{
$oGroup.TakeOffline($timeoutInSeconds)
}
else
{
$oGroup.BringOnline($timeoutInSeconds)
}
}

if (0 -ne $error.Count)
{
$e = $error[0].Exception.Message
write-host "[Error]: Cannot bring [$($oGroup.Name)] $StrState. Details: $e"
return
}
else
{
write-host "Operation completed successfully."
Write-Host "Trying to get resource group state."
}

$Group = $null
$Group = Get-ClusterGroup -useCim $useCim -GroupName $GroupName

if (0 -ne $error.Count -and $null -eq $Group)
{
$message = "[Error]: Cannot get state of resource $($oGroup.Name). Details: " + $error[0].Exception.Message
write-host $message
return
}

$gState = ConvertNumericResourceGroupStateToString -state $Group.State
Write-Host "The state of the resource group $($oGroup.Name) is $gState"

}


function MoveToNextNode (
$oGroup
)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

if ([string]::IsNullOrEmpty($oGroup))
{
write-host "[Error]: Group is empty. "
return
}

$useCim = Check-CimInstance -oWmiInstance $oGroup
if ($null -eq $useCim)
{
write-host "[Error]: Wrong wmi object provided. "
return
}

Write-Host "Finding available nodes"
$oldOwner = ""
$newNodeName = Get-NodeToMove -oGroup $oGroup -oldOWner ([ref] $oldOwner)

if ([string]::IsNullOrEmpty($newNodeName))
{
Write-Host "Cannot get correct node name."
return
}

Write-Host "Successfully found available nodes."

$oGroupName = $oGroup.Name
$error.Clear()

if ($false -eq [string]::IsNullOrEmpty($oldOwner))
{
$oldOwner = $oldOwner.ToLower();
}

write-host "Trying to move group $oGroupName from $oldOwner to node $newNodeName"
if($useCim)
{
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $NodeName -SessionOption $cimSessionOption
$result = invoke-CimMethod -CimSession $cimsession -InputObject $oGroup -MethodName "MoveToNewNode" &#x2013;Arguments @{ NodeName = $newNodeName;TimeOut=$timeoutInSeconds}
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}else
{
$oGroup.MoveToNewNode($newNodeName, $timeoutInSeconds)
}

if(0 -ne $error.Count){
$e = $error[0].Exception.Message
Write-Host "Move to new node failed. Error: $e"
}
else
{
Write-Host "Operation finished successfully."
}

return
}

function Delete-Group($oGroup)
{
$ErrorActionPreference = 'SilentlyContinue'
$error.Clear()

if ([string]::IsNullOrEmpty($oGroup))
{
return
}

$useCim = Check-CimInstance -oWmiInstance $oGroup
if ($null -eq $useCim)
{
write-host "[Error]: Wrong wmi object provided. "
return
}

Write-Host "Trying to delete $($oGroup.Name)"
if($useCim)
{
try
{
$cimSessionOption = New-CimSessionOption -Protocol DCOM
$cimsession = New-CimSession -ComputerName $NodeName -SessionOption $cimSessionOption
$result = invoke-CimMethod -CimSession $cimsession -InputObject $oGroup -MethodName "DestroyGroup"
}
Finally
{
Get-CimSession | Remove-CimSession
$cimsession =$null
$cimSessionOption = $null
}
}
else
{
$oGroup.DestroyGroup()
}

if(0 -ne $error.Count){
$e = $error[0].Exception.Message
Write-Host "Cannot delete resource group. Error: $e"
}
else
{

Write-Host "Operation finished successfully."
}

}

Function Get-ScriptParams([string]$fullscriptname, [ref]$NodeName, [ref]$GroupName, [ref]$MethodName, [ref]$timeoutInSeconds)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$params = Get-CmdParams -fullname $fullscriptname -MaxCount 4

if ($null -eq $params -or 0 -eq $params.Count)
{
return
}

if ($null -eq $params.Count -or 1 -eq $params.Count)
{
if ($null -ne $NodeName) { $NodeName.Value = $params }
return
}

if ($params.Count -gt 1 )
{
if ($null -ne $NodeName) { $NodeName.Value = $params[0] }
if ($null -ne $GroupName) { $GroupName.Value = $params[1] }

}

if ($params.Count -gt 2 )
{
if ($null -ne $MethodName) { $MethodName.Value = $params[2] }
}

if ($params.Count -gt 3 )
{
$timep = $params[3]
$error.Clear()
$itime = [int32]$timep
if (0 -ne $error.Count)
{
$error.Clear()
}
else
{
if ($itime -ge($DefaultTimeOut + $Delta))
{
if ($null -ne $timeoutInSeconds) { $timeoutInSeconds.Value = $itime - $delta }
}
}
}

return
}

#==========================================================================
# Main
#==========================================================================
$NodeName = ""
$GroupName = ""
$MethodName = ""
$DefaultTimeOut = 300
$Delta = 60
$timeoutInSeconds = $DefaultTimeOut
$fullscriptname = $MyInvocation.MyCommand.Definition

Get-ScriptParams -fullscriptname $fullscriptname -NodeName ([ref] $NodeName) -GroupName ([ref] $GroupName) -MethodName ([ref] $MethodName) -timeoutInSeconds ([ref] $timeoutInSeconds)
Main




</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>ClusterGroupMethod.js</Name>
<Contents><Script>function alert($message)
{
WScript.Echo($message);
}

function exit($message)
{
alert($message);
WScript.Quit(0);
}

String.prototype.trim = function()
{
return this.replace(/^\s+|\s+$/gm,'');
}

String.prototype.replaceAll = function (str1, str2, ignore) {
return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\&lt;\&gt;\-\&amp;])/g, "\\$&amp;"), (ignore ? "gi" : "g")), (typeof (str2) == "string") ? str2.replace(/\$/g, "$$$$") : str2);
}


String.prototype.padRight = function ($c,$n) {
if ("number" !== typeof ($n) || "string" !== typeof ($c) || 0 === $c.length) { return this; }
if (this.length &gt;= $n) { return this; }
return this + Array($n - this.length + 1).join($c);
}

Enumerator.prototype.forEach = function($f,$params)
{
var $result = null;

if ("function" !== typeof($f)) { return undefined;}

for(;!this.atEnd();this.moveNext())
{
$result = $f(this.item(),$params);
if (undefined === $result)
{
break;
}
}

return $result;
}

function getPropCount($O)
{
var $i = 0;
for ($i in $O) { $i++; }

return $i;
}

function GetErrorDetails($e)
{
if (!($e instanceof Error)) { return; }

if ($e.number &lt;0)
{
$e.number = 0xffffffff + $e.number + 1;
}

return " Error details: Error code: 0x" + $e.number.toString(16) + ". Description : " + $e.description;
}

function getEscapedName($Name)
{
return $Name.replaceAll("\\", "\\\\").replaceAll("'", "\\'");
}

function getAescapedName($Name) {
return $Name.replaceAll("\\", "\\\\\\\\").replaceAll("\"", "\\\\\\\"");
}

function getClusterService($NodeName)
{
$wmiPath = "winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\\\" + $NodeName + "\\root\\mscluster";
var Service = null;
var $message = "";

try
{
Service = GetObject($wmiPath);
}
catch(e)
{
$message = GetErrorDetails(e);
$message = "Cannot connect to Cluster Namespace. " + $message;
exit($message);
}

return Service;
}

function GetWmiQuery($query, $Service, $message, $IsA) {
var $coll = null;
var $iterator = null;
var $Count = null;
var $Message = null;

try {
$coll = $Service.ExecQuery($query);
$Count = $coll.Count;
if (0 !== $Count) {
$iterator = new Enumerator($coll);
}
}
catch (e) {
$iterator = undefined;
if (!$IsA) {
$Message = GetErrorDetails(e);
$Message = $message + "\n" + $Message;
alert($Message);
}
}
finally {
delete $coll;
$coll = null;
}

return $iterator;

}

function GetWmiAssoc($Object, $AssocName, $message, $IsA) {
var $collection = null;
var $iterator = null;
var $Count = null;
var $Message = null;

try {
$coll = $Object.Associators_($AssocName, "", "", "", false, false, "", "", 0);
$Count = $coll.Count;
if (0 !== $Count) {
$iterator = new Enumerator($coll);
}

} catch (e) {
$iterator = undefined;
if (!$IsA) {
$Message = GetErrorDetails(e);
$Message = $message + "\n" + $Message;
alert($Message);
}
}
finally {
delete $coll
$coll = null;
}

return $iterator;

}

function checkWmiMethod($Object, $MethodName) {
if (null === $Object || undefined === $Object || null === $MethodName || undefined === $MethodName || "object" !== typeof ($Object)) {
return false;
}

var $methods = null;
var $result = true;
$methods = $Object.Methods_;

if (null === $methods || undefined === $methods || "object" !== typeof ($methods)) { delete $methods; $methods = null; return false; }
if (0 === $methods.Count || null === $methods.Count) { delete $methods; $methods = null; return false; }

try {
$methods.Item($MethodName);
} catch (e) {
$result = false;
}

delete $methods;
$methods = null;

return $result;
}

function getClusterGroup($GroupName,$Service)
{
if (undefined === $GroupName || null === $GroupName)
{
return undefined;
}

var $query = "select Name,State from MSCluster_ResourceGroup where Name='" + getEscapedName($GroupName) + "'";
var $iterator = GetWmiQuery($query,$Service,"Cannot get resource group name " + $GroupName + " . ");

return (null !== $iterator &amp;&amp; undefined !== $iterator) ? $iterator.item() : $iterator;
}

function addResource($rpath,$Resources)
{
if (undefined === $Resources || null === $Resources || "object" !== typeof ($Resources)) { return undefined; }
if (undefined === $rpath || null === $rpath || "object" !== typeof ($rpath) ) { return undefined; }
if (undefined === $rpath.Dependent || null === $rpath.Dependent || "string" !== typeof ($rpath.Dependent)) { return 0; }

var $r = null;

try {
$r = $Resources.service.Get($rpath.Dependent)
$Resources.rr.push($r);

} catch (e) {

}
finally
{
delete $r;
$r = null
}

return 0;
}

function getDependentResouces($ResourceName,$Service)
{
if (undefined === $ResourceName || null === $ResourceName) {
return undefined;
}

if (undefined === $ResourceName || null === $ResourceName || "object" !== typeof ($Service)) { return undefined; }

$ResourceName = getAescapedName($ResourceName);

var $query = "select Dependent from MSCluster_ResourceToDependentResource where Antecedent=\"MSCluster_Resource.Name=\\\"" + $ResourceName + "\\\"\"";
var $iterator = GetWmiQuery($query, $Service, "Cannot get dependent resources for " + $ResourceName + " . ");

if (null === $iterator || undefined === $iterator) { return $iterator;}
var $Resources = {rr:[],service:$Service};

if (undefined === $iterator.forEach(addResource, $Resources)) { return undefined; }
if (0 === $Resources.rr.length) { return null;}


return $Resources.rr;

}

function getClusterResource($ResourceName,$Service,$all)
{
if (undefined === $ResourceName || null === $ResourceName)
{
return undefined;
}

var $query =" from MSCluster_Resource where Name='" + getEscapedName($ResourceName) + "'"
$query = !$all ? "select Name,State" + $query : "select *" + $query;
var $iterator = GetWmiQuery($query,$Service,"Cannot get resource [" + $ResourceName + "] . ");

return (null !== $iterator &amp;&amp; undefined !== $iterator) ? $iterator.item() : $iterator;
}

function getResourceNode($r) {
if (undefined !== $r.OwnerNode &amp;&amp; null !== $r.OwnerNode) { return $r.OwnerNode; }

var $iterator = GetWmiAssoc($r, "MSCluster_NodeToActiveResource", "Cannot get active owner of resource.",true);
if (undefined === $iterator || null === $iterator) { return undefined;}
var $n = $iterator.item();
if (undefined === $n || null === $n) { return ""; }

return (null !== $n.Name &amp;&amp; undefined !== $n.Name) ? $n.Name : "";
}

function getResourceGroup($r) {

if (undefined !== $r.OwnerGroup &amp;&amp; null !== $r.OwnerGroup) {return $r.OwnerGroup;}

var $iterator = GetWmiAssoc($r, "MSCluster_ResourceGroupToResource", "Cannot get resource group.",true);
if (undefined === $iterator || null === $iterator) { return ""; }
var $g = $iterator.item();
if (undefined === $g || null === $g) { return ""; }

return (null !== $g.Name &amp;&amp; undefined !== $g.Name) ? $g.Name : "";
}

function ConvertNumericResourceStateToString($state)
{

$States = ["Inherited", "Initializing", "Online", "Offline", "Failed"];

if ($state &gt;= 0 &amp;&amp; $state &lt; 5) { return $States[$state]; }
if (128 === $state) { return "Pending"; }
if (129 === $state) { return "Online Pending"; }
if (130 === $state) { return "Offline Pending"; }

return "Unknown";
}

function ConvertNumericResourceGroupStateToString($state) {

$States = ["Online", "Offline", "Failed", "Partial Online","Pending"];

if ($state &gt;= 0 &amp;&amp; $state &lt; 5) { return $States[$state]; }

return "Unknown";
}

function getCmdFileName() {
var $f = WScript.ScriptName;
var $p = WScript.ScriptFullName;
var $nf = "";

if (undefined === $f || null === $f || "string" !== typeof ($f)) { return null; }
if (undefined === $p || null === $p || "string" !== typeof ($p)) { return null; }
if (0 === $f.length || 0 === $p.length || $p.length &lt;= $f.length) { return null; }

return $p.substring(0, $p.length - $f.length) + "vbparams.txt";
}

function parseCmd($s,$d)
{
if ("string" !== typeof ($s) || undefined === $s || null === $s ) { return null; }
if ("string" !== typeof ($d) || undefined === $d || null === $d || 0 === $d.length) { $d = "="; }

var $l = $s.length;
var $i = -1;

if (0 === $l) { return null; }

$i = $s.indexOf($d, 0)

if (-1 === $i) { return null; }

$i += $d.length;

return $l &lt;= $i ? "" : $s.slice($i,$l);
}


function getCmdParams($MaxParams) {
var $fso = null;
var $fl = null;
var $filename = getCmdFileName();
var $args = [];
var $i = 0;
var $v = null;
if (null === $filename) { return $args; }
if (undefined === $MaxParams || null === $MaxParams || "number" !== typeof ($MaxParams)) { $MaxParams = 0; }

try {
$fso = new ActiveXObject("Scripting.FileSystemObject");
if (!$fso.FileExists($filename)) { return $args; }
$fl = $fso.OpenTextFile($filename,1,false,-1);
if (null === $fl || undefined === $fl) { return null; }
$i = 0;
for (; !$fl.AtEndOfStream;) {
$v = parseCmd($fl.ReadLine(), "=");
if (null !== $v) {
$i++;
if ($i &gt; $MaxParams &amp;&amp; 0 !== $MaxParams) { break; }
$args.push($v);
}

}
} catch (e) {
$args = null;
alert("Cannot read command line parameters.");
}
finally {
if (null !== $fl &amp;&amp; 0 !== $i) { $fl.Close(); }
}

return $args;
}



// Add available Node Name to aNodes array
function addAvNode($oNode,$aNodes)
{
if (undefined === $oNode.Name || null === $oNode.Name || "string" !== typeof ($oNode.Name) || 0 === $oNode.Name.length) { return 0; }
$aNodes.push($oNode.Name.toLowerCase());

return 0;
}

function addActiveNode($NodeName,$Nodes)
{
if (undefined !== $Nodes.pN[$NodeName]) { $Nodes.pN[$nN] = false; $Nodes.aC++; }

return 0;
}

function addNode($oNode,$Nodes)
{
if (undefined === $oNode.Name || null === $oNode.Name || "string" !== typeof ($oNode.Name) || 0 === $oNode.Name.length) { return 0; }
if (undefined === $Nodes.pN || null === $Nodes.pN || "object" !== typeof ($Nodes.pN)) { return 0; }
if (undefined === $Nodes.Count || null === $Nodes.Count) { $Nodes.Count = 0; }

var $NodeName = $oNode.Name.toLowerCase();

if (true === $Nodes.Ct) {
if (undefined === $Nodes.pN[$NodeName]) { $Nodes.pN[$NodeName] = true; $Nodes.Count++; }
}
else
{
if (undefined !== $Nodes.pN[$NodeName]) { $Nodes.pN[$NodeName] = false; }
}

return 0;
}

function getPossibleOwner($oRes,$Nodes)
{
if (undefined === $Nodes || null === $Nodes || "object" !== typeof ($Nodes)) { return undefined; }
if (undefined === $Nodes.pN || null === $Nodes.pN || "object" !== typeof ($Nodes.pN)) { return undefined; }
if (undefined === $Nodes.Ct) { return $Nodes.Ct = true; }


var $Message = "Cannot get possible owners of resource.";
var $pNodes = GetWmiAssoc($oRes, "MSCluster_ResourceToPossibleOwner", $Message);
var $result = 0;
var $i = null;

if (undefined === $pNodes || null === $pNodes) { return undefined; }

$result = $pNodes.forEach(addNode, $Nodes);
if (!$Nodes.Ct)
{
if (0 === $Nodes.Count) { return $result;}
for ($i in $Nodes.pN) {
if ($Nodes.pN[$i]) { delete $Nodes.pN[$i]; $Nodes.Count--; }
else { $Nodes.pN[$i] = true; }
}
}
else
{
if (0 &lt; $Nodes.Count) { $Nodes.Ct = false; }
}

return $result;
}

function getPreferredNode($oNode,$Nodes)
{
if (undefined === $Nodes || null === $Nodes || "object" !== typeof ($Nodes)) { return undefined; }
if (undefined === $oNode.Name || null === $oNode.Name || "string" !== typeof ($oNode.Name) || 0 === $oNode.Name.length) { return 0; }
if (undefined === $Nodes.pN || null === $Nodes.pN || "object" !== typeof ($Nodes.pN)) { return 0; }
if (undefined === $Nodes.Count || null === $Nodes.Count) { $Nodes.Count = 0; }

var $NodeName = $oNode.Name.toLowerCase();

if (undefined === $Nodes.pN[$NodeName]) { $Nodes.pN[$NodeName] = true; $Nodes.Count++; }

return 0;
}

function getGroupPossibleNodes($oGroup)
{
var $rIter = null;
var $Nodes = {};
var $Message = "Cannot get resources in group " + $oGroup.Name;

$Nodes.pN = {};
$Nodes.Ct = true;
$Nodes.Count = null;
$rIter = GetWmiAssoc($oGroup, "MSCluster_ResourceGroupToResource", $Message);

if (undefined === $rIter){return undefined;}
if (null === $rIter) {return null;}

if (undefined === $rIter.forEach(getPossibleOwner,$Nodes)){return undefined;}
if (null === $Nodes.Count || 0 === $Nodes.Count || 1 === $Nodes.Count) { return undefined;}
delete $Nodes.Ct;

return $Nodes;
}

function getGroupPreferredNodes($oGroup)
{
var $rIter = null;
var $Nodes = {};
var $Message = "";

$rIter = GetWmiAssoc($oGroup, "MSCluster_ResourceGroupToPreferredNode ", $Message);

if (null === $rIter || undefined === $rIter) {return null;}
$Nodes.pN = {};
$Nodes.Count = null;
if (undefined === $rIter.forEach(getPreferredNode,$Nodes)){return null;}
if (null === $Nodes.Count || 0 === $Nodes.Count) { return null;}

return $Nodes;
}

//$on object for owner node
function getGroupAvailableNodes($Group, $Service,$on) {
if (undefined === $Group || null === $Group) {return undefined;}

var $iterator = GetWmiAssoc($Group, "MSCluster_NodeToActiveGroup", "Cannot get owner of the resource group " + $Group.Name + ".");
var $Node = null;
var $Message = null;

if (null === $iterator || undefined === $iterator) {return undefined;}

try {
$Node = $iterator.item();
} catch (e) {
$Message = "Cannot get active node." + GetErrorDetails(e);
alert($Message);
$iterator = undefined;
return $iterator;
}

if (undefined === $Node.Name || null === $Node.Name || "string" !== typeof ($Node.Name) || 0 === $Node.Name.length) { return undefined; }

$query = "select Name, State from MSCluster_Node where Name != '" + $Node.Name + "' and State = 0";
$iterator = GetWmiQuery($query, $Service, "Cannot get available nodes.");

if (undefined !== $on &amp;&amp; null !== $on &amp;&amp; "object" === typeof ($on)) {
$on.oN = $Node.Name.toLowerCase();
}

delete $Node;
$Node = null;

if (null === $iterator || undefined === $iterator) {return undefined;}
$Node = [];
$iterator.forEach(addAvNode,$Node);
if (0 === $Node.length) {return undefined;}
$Node.sort();


return $Node;

}

function getAllPosibleNodes($aNodes,$poN)
{
var $Nodes = [];
var $i = 0;
var $l = $aNodes.length;
var $n = "";

if (null === $poN) {
return $aNodes;
}
else {
if (undefined === $l || null === $l || 0 === $l) { return undefined; }

for (; $i &lt; $l; $i++)
{
$n = $aNodes[$i];
if (undefined !== $poN.pN[$n]) { $Nodes.push($n); }
}
}

return $Nodes;
}

function getBestNode($aNodes, $poN) {
var $i = 0;
var $l = $aNodes.length;
var $n = "";
var $nName = null;

if (undefined === $l || null === $l || 0 === $l) { return undefined; }
if (null === $poN) { return $aNodes[0]; }

for (; $i &lt; $l; $i++) {
$n = $aNodes[$i];
if (undefined !== $poN.pN[$n]) { $nName = $n; break;}
}

return null === $nName ? $aNodes[0] : $nName;
}

function getGroupNodesToMove($oGroup,$Service,$on)
{
// get all available Nodes in online state
var $oNodes = getGroupAvailableNodes($oGroup, $Service,$on);

// get all possible Nodes via resource possible owners
var $pNodes = getGroupPossibleNodes($oGroup);

// get all preferred Nodes via resource possible owners
var $prNodes = getGroupPreferredNodes($oGroup);
var $aNodes = null;
var $NodeName = null;
var $s = null;

if (undefined === $oNodes || undefined === $pNodes || null === $oNodes) { return undefined; }

$aNodes = getAllPosibleNodes($oNodes, $pNodes);
if (0 === $aNodes.length) { return undefined; }
$NodeName = getBestNode($aNodes,$prNodes);

return $NodeName;
}

function deleteResources($Resource,$timeoutInSeconds)
{
if ("object" !== typeof ($Resource) || undefined === $Resource.Name || null === $Resource.Name || "string" !== typeof($Resource.Name))
{
return undefined;
}

if (0 === $Resource.Name.trim().length) { return undefined; }

var $DepRes = getDependentResouces($Resource.Name,$Service);;
var $Message = null;

if (undefined === $DepRes)
{
return undefined;
}

if (null === $DepRes)
{
try {
if(4 !== $Resource.State &amp;&amp; 3 !== $Resource.State)
{
$Resource.TakeOffline($timeoutInSeconds);
}

$Resource.DeleteResource();
} catch (e) {
$Message = "Cannot delete resource " +$Resource.Name + " . " + GetErrorDetails(e);
alert($Message);
return undefined;
}
}

return 0;

}

function deleteGroupLegacy($oGroup,$timeoutInSeconds)
{
if ("object" !== typeof($oGroup))
{
return ;
}

var $ResIter = null;
var $Message = "Unable to delete resource group. ";

for(;;)
{
$ResIter = GetWmiAssoc($oGroup,"MSCluster_ResourceGroupToResource","Cannot get resources in group " + $oGroup.Name);
if (undefined === $ResIter)
{
return ;
}

if (null === $ResIter)
{
break;
}

if (undefined === $ResIter.forEach(deleteResources,$timeoutInSeconds))
{
return ;
}
}

try {
$oGroup.DeleteGroup();
} catch (e) {
$Message += GetErrorDetails(e);
alert($Message);
}

return;
}

function destroyGroup($oGroup) {
if ("object" !== typeof ($oGroup)) {
return;
}

var $Message = "Unable to delete resource group. ";

try {
$oGroup.DestroyGroup();
} catch (e) {
$Message += GetErrorDetails(e);
alert($Message);
}

return;
}

function DeleteGroup($oGroup,$timeoutInSeconds)
{
var $isNew = checkWmiMethod($oGroup, "DestroyGroup");

if (!$isNew)
{ deleteGroupLegacy($oGroup, $timeoutInSeconds); }
else
{ destroyGroup($oGroup); }

}

function bringOnOff($Group,$IsOnline,$Service,$timeoutInSeconds)
{
alert("The state of the " + $Group.Name + " resource group is " + ConvertNumericResourceGroupStateToString ($Group.State));
var $message = "";

try {
if (!$IsOnline)
{
if (0 === $Group.State || 2 === $Group.State)
{
alert("Attempting to bring the resource group offline");
$Group.TakeOffline($timeoutInSeconds);
}
else {
alert("Group is already offline or in an incompatible state.");
return;
}
}
else
{
if (1 === $Group.State || 2 === $Group.State){
alert("Attempting to bring the resource group online");
$Group.BringOnline($timeoutInSeconds);
}
else {
alert("Group is already online or in an incompatible state.");
return;
}
}

} catch (e) {
$message = GetErrorDetails(e);
$message = "Attempt failed with error. " + $message;
alert($message);
return;
}

var $oGroup = null;
try {
$oGroup = $Service.Get($Group.Path_);
alert("The state of the " + $oGroup.Name + " resource group is " + ConvertNumericResourceGroupStateToString($oGroup.State));

} catch (e) {
$message = GetErrorDetails(e);
$message = "Cannot get resource group state. " + $message;
alert($message);
}

delete $oGroup;
$oGroup = null;

return;
}

function MoveToNextNode($oGroup,$Service,$timeoutInSeconds)
{
var $NewNode = null;
var $on = { oN: null };

alert("Finding available nodes");

$NewNode = getGroupNodesToMove($oGroup,$Service,$on);

if (null === $NewNode || undefined === $NewNode || "string" !== typeof($NewNode))
{
alert("Cannot get available Nodes to move the group to" + $oGroup.Name);
return;
}

alert("Successfully found available nodes.");

if (null !== $on.oN &amp;&amp; undefined !== $on.oN &amp;&amp; "string" === typeof ($on.oN) &amp;&amp; 0 !== $on.oN.length)
{
alert("Trying to move the group from " + $on.oN + " to node " + $NewNode);

}
else
{
alert("Trying to move the group to node " + $NewNode);
}

var $Message = null;
try {
$oGroup.MoveToNewNode($NewNode, $timeoutInSeconds);
alert("Operation finished successfully.");
} catch (e) {
$Message = GetErrorDetails(e);
$Message = "Cannot move the resourse group " + $oGroup.Name + " to node " + $NewNode.Name + " . " + $Message;
alert($Message);
}

}

function getParams($params) {

if ("object" !== typeof ($params)) {
return false;
}

var $args = getCmdParams(4);

if (null === $args) { exit(""); }

$params.timeoutInSeconds = 300;

if ($args.length &lt; 3) {
exit("Wrong number of arguments.");
}
else if ($args.length &gt; 3) {
$params.timeoutInSeconds = parseInt($args[3], 10);
if (isNaN($params.timeoutInSeconds)) {
$params.timeoutInSeconds = 300;
}
}

$params.NodeName = $args[0];
$params.GroupName = $args[1];
$params.MethodName = $args[2];


if (0 === $params.NodeName.length || 0 === $params.NodeName.trim().length) {
exit("Node name is empty.");
}

if (0 === $params.GroupName.length || 0 === $params.GroupName.trim().length) {
exit("Group Name is empty.");
}

if (0 === $params.MethodName.length || 0 === $params.MethodName.trim().length) {
exit("Unrecognized empty method used");
}

$params.MethodName = $params.MethodName.toLowerCase();

if ("online" !== $params.MethodName &amp;&amp; "offline" !== $params.MethodName &amp;&amp; "move" !== $params.MethodName &amp;&amp; "delete" !== $params.MethodName) {
exit("[Error]: Unrecognized method " + $params.MethodName + " used");
}

return true;
}

function Main()
{
var $params = {};

getParams($params);

var $lgrp = $params.GroupName.toLowerCase();

if ("move" !== $params.MethodName &amp;&amp; ("cluster group" === $lgrp || "available storage" === $lgrp))
{
alert("Cannot provide this operation on Core Cluster Group.");
return
}

var $Service = null;
var $oGroup = null;

$Service = getClusterService($params.NodeName);
$oGroup = getClusterGroup($params.GroupName,$Service);

if (null === $oGroup)
{
delete $Service;
$Service = null;
exit("Cluster resource group" + $params.GroupName + " is not found.");
}
else if(undefined === $oGroup)
{
delete $Service;
$Service = null;
exit("");
}
else if ("object" !== typeof($oGroup)) {
delete $Service;
$Service = null;
exit("");
}

if ("online" === $params.MethodName)
{
bringOnOff($oGroup,true,$Service,$params.timeoutInSeconds);
}
else if("offline" === $params.MethodName)
{
bringOnOff($oGroup,false,$Service,$params.timeoutInSeconds);
}
else if("delete" === $params.MethodName)
{
DeleteGroup($oGroup,$params.timeoutInSeconds);
}
else if("move" === $params.MethodName)
{
MoveToNextNode($oGroup,$Service,$params.timeoutInSeconds);
}

delete $oGroup;
delete $Service;
$oGroup = null;
$Service = null;
}

Main();
</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>vbparams.txt</Name>
<Contents><Script>

=$Config/NodeName$
=$Config/GroupName$
=$Config/MethodName$
=$Config/TimeoutSeconds$

</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>psparams.txt</Name>
<Contents><Script>

=$Config/NodeName$
=$Config/GroupName$
=$Config/MethodName$
=$Config/TimeoutSeconds$

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