I have a v0.5 grade PowerCLI script that patches a esxi cluster that doesn't have DRS available, I personally use Linux exclusively so it is cross platform by default.
https://github.com/gerdesj/Patch_VMWare_Cluster
I've been a VMware sysadmin for around 20 years as a consultant. Not everyone can afford E+ and hence have DRS make patching easy. It is a bloody pain to remediate a reasonably large three node Essentials Plus cluster with 1 Gbs-1 networking. 10Gb helps but still a pain.
There are quite a few scripts for 4.x and a few other efforts I've found but nothing modern, that I could find. I had to learn PowerShell and a few other things to create this thing.
It has patched my work cluster successfully but the last phase - return VMs from whence they came was bollocks and I have rewritten that bit but not tested yet. I use tags to note where my VMs run "statically".
My next effort will be cluster balancing without DRS ...
I am currently working on a similar script. This what I've come up with for non-DRS clusters and migrations. I have tested the migration of VM's off of the selected host to other hosts in the cluster, and that seems to work. It isn't very smart (ie it doesn't take into account resource utilization or anything), but it does disperse the count of VM's relatively evenly across other hosts in the cluster.
I have not yet tested the migration back to the original host portion yet. But my logic is that if the original array of VM's that was migrated off the host doesn't change, it should be able to reuse that array and migrate them all back to the host after patching.
Also, if you'd like to see the rest of the script, I can share. The basic idea is to use a do/until loop to loop through an array of hosts in the cluster and patch them all one at a time, accommodating for single host clusters, DRS/non-DRS clusters, and a few more features as well.
$ClusterName = Read-Host "Please enter the full name of the cluster you want to update"
$HostArray = Get-Cluster $ClusterName | Get-VMHost
$HostCount = $HostArray.count
$SelectHost = $HostArray
$HostName = $SelectHost.name
# Migrate powered on VM's off of current host
Write-Host "Migrating VM's off of host $HostName to other hosts in cluster $ClusterName." -ForegroundColor Cyan -BackgroundColor Black
"$(Get-Date) - Migrating VM's off of host $HostName to other hosts in cluster $ClusterName." >> $LogFile
$VMArray = $SelectHost | Get-VM | where {$_.powerstate -eq ‘PoweredOn’ -and $_.name -notlike '*vCLS-*'}
$VMCount = $VMArray.count
$OtherHostsArray = $GetCluster | Get-VMHost | where {$_.name -notlike "$HostName"}
$OtherHostsCount = $OtherHostsArray.count
$VMInt = 0
$HostInt = 0
do {
$TargetVM = $VMArray[$VMInt].name
$TargetHost = $OtherHostsArray[$HostInt].name
Write-Host "Migrating $TargetVM to $TargetHost"
$VMArray[$VMInt] | Move-VM -Destination $OtherHostsArray[$HostInt]
$VMInt++
$HostInt++
if ($HostInt -eq $OtherHostsCount){
$HostInt = 0
} else {}
} until ($VMInt -eq $VMCount)
# Confirm that all powered on VM's are migrated off of current host
do {
$VMArrayCount = ($SelectHost | Get-VM | where {$_.powerstate -eq ‘PoweredOn’ -and $_.name -notlike '*vCLS-*'}).count
Write-Host "Confirming that all powered-on VM's are migrated off of $HostName..." -ForegroundColor Cyan -BackgroundColor Black
"$(Get-Date) - Confirming that all powered-on VM's are migrated off of $HostName..." >> $LogFile
Start-Sleep 5
} until ($VMArrayCount -eq "0")
################################### Perform ESXi update steps ###################################
# Migrate powered on VM's back to current host
Write-Host "Migrating VM's back to host $HostName." -ForegroundColor Cyan -BackgroundColor Black
"$(Get-Date) - Migrating VM's back to host $HostName." >> $LogFile
$VMArray | Move-VM -Destination $SelectHost
My effort has managed to patch a couple of clusters so far after some pretty mad screw ups which I've fixed! I've deliberately gone for returning the VM to host relationship after patching because that is generally how Essentials(+) type sites work.
When I evacuate a host, I look for the least loaded (memory only, not CPU) host each time. The stats are not calculated in real time for obvious reasons and if using very fast vmotion, you could overwhelm a host by accident. Thanks to overcommit, ballooning etc this isn't much off an issue, provided the cluster is a proper n+1 job. Eg a three node cluster only has around 66% memory in use on each node.
A better approach would be to grab the state of the cluster and calculate how to best place VMs. However, starting with a list of hosts and evacuating them one by one, patching them and then starting with the last host patched, return VMs to it and work back through the list and do the same seems to work pretty well.
