If you’ve upgraded to vSphere 4.1 and have Standard licensing, you may have noticed that vMotion is now supported at that licensing level. Previously, vMotion was only available with Enterprise licenses and above. (Storage vMotion is still a feature only available with Enterprise & Enterprise Plus.)
One of the nice features about rebooting hosts in DRS-enabled clusters is that you can use the -Evacuate parameter with Restart-VMHost. That parameter, however, will not work in non-DRS enabled clusters. So what do you do if you need to reboot an entire cluster? Or more than one cluster? You could do it manually: that is, selecting a host, vMotioning all the VM’s to other hosts in the cluster, placing it in maintenance mode, rebooting it, waiting for it to come back online, and then exit maintenance mode. Rinse, repeat, gag at the hundreds of mouseclicks you need to endure. 🙂
That’s where this little script comes in. It will do all of that work for you, and in addition, will verify that each host in the cluster is running ESX(i) 4.1 and has a vMotion enabled vmknic.
[powershell]
$cluster = Get-Cluster -Name (Read-Host "Name of the cluster you’d like to reboot")
# Getting all connected hosts that are equal to version 4.1.0.
$vmhosts = Get-VMHost -Location $cluster | where { ($_.State -eq "Connected") -and ($_.Version -eq "4.1.0") }
if (!$vmhosts) {
Write-Output "No ESX(i) 4.1 hosts found in cluster. Aborting script!"
} else {
$err = $null
# Verifying vMotion is enabled on a specific portgroup
foreach ($vmhost in $vmhosts) {
Write-Output "Verifying vMotion requirements on host $vmhost"
$vmknic = Get-VMHostNetworkAdapter -VMHost $vmhost | where {$_.PortGroupName -like "*vmotion*"}
if ($vmknic.VMotionEnabled.Equals($false)) {
Write-Output "vMotion requirement failed on host $vmhost. Aborting script!"
$err = "1"
break;
}
}
}
if(!$err) {
Write-Output "vMotion requirements passed."
foreach ($vmhost in $vmhosts) {
$clusterpartners = Get-VMHost -Location $cluster | where { ($_.State -eq "Connected") -and ($_.Name -ne $vmhost.Name) }
$vms = Get-VMHost $vmhost | Get-VM
# vMotion all of the VM’s from the current host to random partners in the cluster
if($vms) {
foreach ($vm in $vms) {
$dsthost = $clusterpartners | Get-Random
Write-Output "vMotioning VM $vm to $dsthost"
Move-VM -VM $vm -Destination $dsthost -Confirm:$false | Out-Null
}
}
Write-Output "Putting $vmhost into maintenance mode"
Set-VMHost -VMHost $vmhost -State "Maintenance" | Out-Null
Write-Output "Rebooting $vmhost"
Restart-VMHost -VMHost $vmhost -Confirm:$false | Out-Null
# Sleep until the host isn’t responding anymore
do {Start-Sleep -Seconds 5} until ( (Get-VMHost -Name $vmhost).State -eq "NotResponding")
# Sleep until the host begins responding in vCenter again
do {Start-Sleep -Seconds 5} until ( (Get-VMHost -Name $vmhost).State -eq "Maintenance")
# Remove the host from Maintenance Mode
Write-Output "Taking $vmhost out of maintenance mode"
Set-VMHost -VMHost $vmhost -State "Connected" | Out-Null
}
}
[/powershell]
I’ve found some cool use cases for this script so far. One of them is to complete joining an AD domain (use Luc Deken’s AD Auth script for that). Another one would be to finalize storage timeout settings, after your storage provider’s vCenter plugin makes the changes. Yet another would be as part of a scripted driver install.
This script can also be easily modified to reboot multiple clusters based on an PowerShell array or location in vCenter. There are many different possibilities, and I hope this is of use.
K F says
This is nice. For the others on my team I would probably error on putting the host in maintenance mode and having this mechanism evacuate the VMs.