Last active
June 20, 2018 07:15
-
-
Save systemcenterblog/6c0ca59c41c9a7ae3f2c36b69e5d1b19 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
<# | |
Script Disclaimer: The sample scripts provided here are not supported under any Microsoft standard support program or service. All scripts are provided AS IS without warranty of any kind. | |
Server Group - Drain Stop Script | |
Collects current operation status of all nodes in Cluster - i.e. Paused, Running | |
Checks if Localhost is Paused -- $LocalNodeStatus=$True | |
Checks if additional nodes in cluster are paused $AdditionalNodeStatus=$True | |
If $LocalNodeStatus=$False and $AdditionalNodeStatus=False Drain Stop the local node | |
Checks that the local node is in Paused State | |
Check that all the VM have evacuated the node | |
If the $LocalNodeStatus=$False or $LocalVMNodeStatus=$False implying the drain stop has not been successful report failure | |
Issue exit code 1 and revert the node to Running | |
Author: | |
Twitter @Syswow64blog | |
Web: systemcenterblog.co.uk | |
#> | |
#//Initialize | |
$LocalNodeIsPaused = $False | |
$LocalVMNodeStatus = $False | |
$OtherNodesOffline = @() | |
$LocalNode = $env:computername | |
#//Setting the log location | |
$env:LogPath = "$env:ProgramData\SystemCenterBlog\Logs" | |
#// Checking the log path | |
if((Test-Path $env:logpath) -eq $False) | |
{ | |
New-Item -path $env:LogPath -type directory | |
} | |
#Starting the log file | |
Start-Transcript -path "$env:LogPath\PatchDrain.log" -append | |
#// SMTP Config | |
$mail = 'mail.SystemCenterBlog.co.uk' | |
$smtp = New-Object Net.Mail.SmtpClient($mail) | |
$from = '[email protected]' | |
$to = '[email protected]' | |
$sub = "Patch Start Script on [$LocalNode] $Node" | |
#// Functions | |
Function SendMail($subject,$message,[switch] $fail = $False) { | |
Write-Output "$subject`: $message" | |
$smtp.Send($from,$to,$subject,$message) | |
if ($Fail) {Throw $message} | |
} | |
Function Check-VMNodeStatus{ | |
Param($NodeName) | |
Process | |
{ | |
$count = 0 | |
Do | |
{ | |
write-host "$NodeName Checking Node has evacuated all running VM's.............. $(get-date)" | |
start-sleep 5 | |
[void](Suspend-ClusterNode -drain -wait) # Graceful VM migration | |
#[void](Suspend-ClusterNode -drain -forcedrain -wait) # Forceful VM migration | |
$count += 1 | |
} | |
Until (((get-VM).count -eq 0) -or ($count -eq 3)) | |
if ($count -eq 3){return $False} | |
else {return $True} | |
} | |
} | |
Function Pause-LocalNode{ | |
Param($NodeName) | |
Process | |
{ | |
$count = 0 | |
Write-host "$NodeName Drain node ...................... $(get-date)" | |
Suspend-ClusterNode -drain -wait | |
#Check that local node has been Paused | |
Do | |
{ | |
write-host "$NodeName Checking Node is in a Paused state........................ $(get-date)" | |
start-sleep 2 | |
$count += 1 | |
#$PausedClusterNodes = Get-WmiObject -Class "MSCluster_Node" -Namespace "root\MSCluster" | Where-Object {$_.state -eq 2} | |
} | |
Until ((Get-WmiObject -Class "MSCluster_Node" -Namespace "root\MSCluster" | Where-Object {$_.state -eq 2}).name -eq $NodeName -or $count -eq 60) | |
if ($count -eq 20) | |
{ | |
write-host "$NodeName did not enter a Paused state ........................................... $(get-date)" | |
return $False | |
} | |
else | |
{ | |
write-host "$NodeName is in a Paused state ........................................... $(get-date)" | |
return $True | |
} | |
} | |
} | |
Function Write-Output{ | |
Param($Node,$OperationStatus,$NodePaused,$VMStatus) | |
Process | |
{ | |
write-host "$Node has Operation Status $OperationStatus ...... $(get-date)" | |
write-host "$Node $ LocalNodeStatus = $NodePaused .......... $(get-date)" | |
write-host "$Node $ LocalVMNodeStatus = $VMStatus ............ $(get-date)" | |
} | |
} | |
#Get Cluster Node Status | |
$ClusterNodes = Get-WmiObject -Class "MSCluster_Node" -Namespace "root\MSCluster" | |
foreach ($CNode in $ClusterNodes) | |
{ | |
if($CNode.State -eq 2) # Paused state | |
{ | |
if ($CNode.name -eq $LocalNode) # check if local node is paused | |
{ | |
$LocalNodeIsPaused=$True | |
write-host "Local node in Paused state = $LocalNodeIsPaused -- "$CNode.name" .... $(get-date)" | |
} | |
else # another node is paused | |
{ | |
$OtherNodesOffline += $CNode.name + "," + $CNode.state | |
write-host "Additional node in Paused State Will not proceed-- "$CNode.name" .... $(get-date)" | |
} | |
} | |
elseif ($CNode.State -eq 1) # Check for Failed state and exit | |
{ | |
write-host "Node is in failed state = $CNode.name .... $(get-date)" | |
$OtherNodesOffline += $CNode.name + "," + $CNode.state | |
} | |
} | |
if ($OtherNodesOffline.count -gt 0) | |
{ | |
if ($LocalNodeIsPaused) # Resume the local node if this is paused also as the SCCM script is going to fail | |
{ | |
Resume-ClusterNode | |
} | |
foreach ($Node in $OtherNodesOffline) | |
{ | |
$NodeName = $Node.split(",")[0] | |
$NodeState = $Node.split(",")[1] | |
write-host ""$NodeName" has Operation Status $NodeState .... $(get-date)" | |
} | |
write-host "SCCM Exit code 1................................................$(get-date)" | |
Return 1 | |
} | |
else | |
{ | |
if ($LocalNodeIsPaused -eq $False) # No nodes are paused, pause the local node | |
{ | |
$LocalNodeIsPaused = Pause-LocalNode -NodeName $LocalNode # try to pause local node | |
} | |
if($LocalNodeIsPaused -eq $True) # Only Local Node paused, check VM Count | |
{ | |
$CheckVMNode = Check-VMNodeStatus -NodeName $LocalNode | |
Write-Output -Node $LocalNode -OperationStatus 2 -NodePaused $LocalNodeIsPaused -VMStatus $CheckVMNode | |
if ($CheckVMNode -eq $true) # VM Status is true | |
{ | |
write-host "SCCM Exit code 0................................................$(get-date)" | |
Return 0 | |
} | |
else # VM Status is false | |
{ | |
write-host "SCCM Exit code 1................................................$(get-date)" | |
Return 1 | |
} | |
} | |
else | |
{ | |
$NodeStatus = Get-WmiObject -Class "MSCluster_Node" -Namespace "root\MSCluster" | Where-Object {$_.name -like $LocalNode} | |
$CheckVMNode = Check-VMNodeStatus -NodeName $LocalNode | |
Write-Output -Node $LocalNode -OperationStatus $NodeStatus.state -NodePaused $LocalNodeIsPaused -VMStatus $CheckVMNode | |
Write-Host "SCCM Exit code 1................................................$(get-date)" | |
Return 1 | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment