Due to a weird BIOS error, most of our ESX hosts have thrown a memory warning. This is a known issue, and HP want you to update the BIOS before doing any further troubleshooting, so I scheduled a change window to upgrade all the hosts in our cluster (12 in this cluster). While working on the upgrades, I stumbled across a weird issue with Move-VM.
Our clusters run Distributed Resource Scheduler (DRS), which allows the cluster to migrate guests seamlessly between the hosts when resources become constrained. One of the handy features is when you put a host into maintenance mode, it automatically moves all the guests off of that host. However, because I wanted to make sure all the guests migrated, and manage the alerts in our monitoring system, I threw together a quick script using PowerCLI so I could move all the dev/test/stage machines (lower monitoring thresholds), and then move the production servers after so I could see which boxes I had to mark as “unmanaged” in our monitoring software.
Moving the VMs is really easy with PowerCLI, for example, here is the basics of my script:
1 2 3
Pretty simple, however I was noticing an oddity. When the guests were moving, they were losing the resource pools they were part of. Looking at the documentation for Move-VM, the destination supports a folder, cluster, resource pool, or host. Because I wasn’t explicitly specifying the type as a host, it looks like all the other options were being set to null and the guest moved. So for the next batch of guests to move, I explicitly defined the type:
1 2 3 4
After explicitly defining the type of destination, the guest moved host, but retained it’s resource pool allocations. Much better! Obviously this only moves one guest, and each of our hosts has quite a few guests on it, so I used a Get-VM combination, some pipes, and such.
1 2 3 4 5 6 7
The above code happily moves all our dev, stage, and test, machines off of oldhost onto newhost. From there, it was a case of finding the hosts in the monitoring software, unmanaging them all, and repeating the same code without the conditional name check.
So lesson learned, if a function accepts multiple input types, always explicitly define the type, as you cannot tell what might happen.