Skip to content

Instantly share code, notes, and snippets.

@sqlchow
Last active June 13, 2022 13:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sqlchow/5e838a3f7cb321a60375 to your computer and use it in GitHub Desktop.
Save sqlchow/5e838a3f7cb321a60375 to your computer and use it in GitHub Desktop.
To find those cluster groups that are not running on the preferred owners i.e. those that are stacked on a different node than the preferred owner.
function Search-ClusterNodesForStacking
{
<#
.SYNOPSIS
This script provides options for an administrator to check if any cluster
services are stacked i.e. not running on their preferred nodes.
.DESCRIPTION
The script works in the following way:
1. Connect to a cluster and get a list of nodes that belong to it.
2. For each node in the cluster check which services are available on a
given node.
3. For each clustered service on the node, check if the current node is
its preferred node.
.PARAMETER ClusterName
Name of the Cluster which needs to be validated.
Required true
Position named
Default value
Accept pipeline input false
Accept wildcard characters false
.EXAMPLE
Search-ClusterNodesForStacking -ClusterName SKYNETCL
------------------------------------------------------------
ClusterName: SKYNETCL
------------------------------------------------------------
NodeName: SKYNETA
NodeState: ONLINE
ActiveGroup: Available Storage
GroupState: OFFLINE
Preferred Node:<-StackingDetected
PhysicalNode: SKYNETA
ActiveGroupName: Available Storage
ActiveGroupDescription:
PreferredNode:
ActiveGroup: SKYSQL014
GroupState: ONLINE
Preferred Node: SKYNETA <- Good
ActiveGroup: SKYSQL015
GroupState: ONLINE
Preferred Node:SKYNETB<-StackingDetected
PhysicalNode: SKYNETA
ActiveGroupName: SKYSQL015
ActiveGroupDescription:
PreferredNode: SKYNETB
------------------------------------------------------------
NodeName: SKYNETB
NodeState: ONLINE
ActiveGroup: Cluster Group
GroupState: ONLINE
Preferred Node:SKYNETA<-StackingDetected
PhysicalNode: SKYNETB
ActiveGroupName: Cluster Group
ActiveGroupDescription:
PreferredNode: SKYNETA
------------------------------------------------------------
NodeName: SKYNETC
NodeState: ONLINE
ActiveGroup: SKYSQL017
GroupState: ONLINE
Preferred Node: SKYNETC <- Good
ActiveGroup: SKYSQL018
GroupState: ONLINE
Preferred Node: SKYNETC <- Good
ActiveGroup: SKYSQL019
GroupState: ONLINE
Preferred Node: SKYNETC <- Good
ActiveGroup: SKYSQL016
GroupState: ONLINE
Preferred Node: SKYNETC <- Good
------------------------------------------------------------
.LINK
https://sqlchow.wordpress.com/2013/06/24/detecting-cluster-group-stacking-using-powershell/
.NOTES
Since, the function shows the information on screen we will not accept
pipeline input.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, HelpMessage="Enter cluster name which needs to be validated.")]
[ValidateNotNullOrEmpty()]
[string]$ClusterName
)
BEGIN
{
Function Get-ClusterState
{
param(
[int]$state = $( Throw "Please specify cluster state.")
)
$getState = "";
switch($state){
-1 { $getState = "STATE_UNKNOWN"}
0 { $getState = "ONLINE"}
1 { $getState = "OFFLINE"}
2 { $getState = "FAILED"}
3 { $getState = "PARTIAL_ONLINE"}
4 { $getState = "PENDING"}
default { $getState = "ERROR GETTING STATE"}
}
$getState
}
}
PROCESS
{
[string] $virtualClusName = "";
[boolean] $bStacking, $bFound = ($False, $False);
[string] $sPrefNode = "";
#Get the cluster nodes and name.
$Cluster = Get-WmiObject -namespace "Root\MSCluster" -Class "MSCluster_Cluster" -computerName $ClusterName -Authentication "PacketPrivacy" -Impersonation "Impersonate";
$virtualClusName = $Cluster.Name.ToString();
$clusterNodes = Get-WmiObject -namespace "Root\MSCluster" -query "Select * from MSCluster_Node" -computerName "$($virtualClusName)" -Authentication "PacketPrivacy" -Impersonation "Impersonate";
$clusNodeNames = $clusterNodes | Select-Object Name, Description, @{Name="ClusState"; Expression={Get-ClusterState $_.State}}
Write-Host ("-" * 60) -ForegroundColor Yellow -BackgroundColor Black
Write-Host "ClusterName: $($virtualClusName)" -ForegroundColor Green
Write-Host ("-" * 60) -ForegroundColor Yellow -BackgroundColor Black
#Loop through the collection of physical cluster nodes
$bStacking = $False
Foreach ($node in $clusNodeNames)
{
Write-Host "`tNodeName: " $node.Name -ForegroundColor Yellow
Write-Host "`tNodeState: " $node.ClusState -ForegroundColor Yellow
#Get the Active Group for each node
$qryStr = "ASSOCIATORS OF {MSCluster_Node='" + $node.Name + "'} WHERE AssocClass=MSCluster_NodeToActiveGroup"
$clusNodeAssoc = Get-WmiObject -namespace "Root\MSCluster" -query $qryStr -computerName $virtualClusName -Authentication "PacketPrivacy" -Impersonation "Impersonate"
$clusGroupNames = $clusNodeAssoc | Select-Object Name, Description, @{Name="ClusState"; Expression={Get-ClusterState $_.State}}
#Loop through each Active group
Foreach ($group in $clusGroupNames)
{
If($group.Name -ne $null)
{
If ( ($group.Description -ine "") -or ($group.Description -eq $null)){
Write-Host "`t`tActiveGroup: $($group.Name)" -ForegroundColor Magenta
Write-Host "`t`tDescription: $($group.Description)" -ForegroundColor Magenta
} Else{
Write-Host "`t`tActiveGroup: $($group.Name)" -ForegroundColor Magenta
}
Write-Host "`t`tGroupState: $($group.ClusState)" -ForegroundColor Magenta
#Get the preferred node for this Active Group.
#If there isn't one we just skip this because we can't detect stacking.
$qryStr = "ASSOCIATORS OF {MSCluster_ResourceGroup='" + $group.Name + "'} WHERE AssocClass=MSCluster_ResourceGroupToPreferredNode"
$clusGroupAssoc = Get-WmiObject -namespace "Root\MSCluster" -query $qryStr -computerName $virtualClusName -Authentication "PacketPrivacy" -Impersonation "Impersonate"
$clusPrefNodes = $clusGroupAssoc | Select-Object Name, Description, @{Name="ClusState"; Expression={Get-ClusterState $_.State}} -First 1
#Loop through this collection to determine if this Active Group is on a preferred node
Foreach ($prefNode in $clusPrefNodes){
if($prefNode -ne $null)
{
$sPrefNode = [string]$prefNode.Name
If ([string]$prefNode.Name.ToUpper() -eq [string]$node.Name.ToUpper()){
#$sPrefNode = [string]$prefNode.Name
$result = "`t`tPreferred Node: " + $sPrefNode + " <- Good"
Write-Host $result -ForegroundColor Green
$bFound = $True
}else{
$bFound = $False
}
}
}
If ((-not $bFound) -and ($clusGroupNames.Count -ine 0)){
$stckDet = "`t`tPreferred Node:" + $sPrefNode + "<-StackingDetected"
Write-Host $stckDet -ForegroundColor Red
$bStacking = $True
Write-Host "`t`tPhysicalNode: " $node.Name -ForegroundColor Red
Write-Host "`t`tActiveGroupName: " $group.Name -ForegroundColor Red
Write-Host "`t`tActiveGroupDescription: " $group.Description -ForegroundColor Red
Write-Host "`t`tPreferredNode:" $sPrefNode -ForegroundColor Red
}
$bFound = $False
}else{
Write-Host "`t`tActiveGroup: Unable to get group name" -ForegroundColor Cyan
}
}
Write-Host ("-" * 60) -ForegroundColor Yellow -BackgroundColor Black
}
}
END
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment