Last active
June 13, 2022 13:18
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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