Execute Cluster Resource Group Method
Microsoft.Windows.Cluster.Group.Action (WriteActionModuleType)
This write action executes operations in windows cluster group.
Element properties: Member Modules:
Overrideable Parameters:
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 "& '%~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 –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" –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(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g, "\\$&"), (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 >= $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 <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 && 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 && undefined !== $iterator) ? $iterator.item() : $iterator;
}
function getResourceNode($r) {
if (undefined !== $r.OwnerNode && 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 && undefined !== $n.Name) ? $n.Name : "";
}
function getResourceGroup($r) {
if (undefined !== $r.OwnerGroup && 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 && undefined !== $g.Name) ? $g.Name : "";
}
function ConvertNumericResourceStateToString($state)
{
$States = ["Inherited", "Initializing", "Online", "Offline", "Failed"];
if ($state >= 0 && $state < 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 >= 0 && $state < 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 <= $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 <= $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 > $MaxParams && 0 !== $MaxParams) { break; }
$args.push($v);
}
}
} catch (e) {
$args = null;
alert("Cannot read command line parameters.");
}
finally {
if (null !== $fl && 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 < $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 && null !== $on && "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 < $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 < $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 && 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 && undefined !== $on.oN && "string" === typeof ($on.oN) && 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 < 3) {
exit("Wrong number of arguments.");
}
else if ($args.length > 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 && "offline" !== $params.MethodName && "move" !== $params.MethodName && "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 && ("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>