Save to My DOJO
Luke wrote a fantastic article that detailed how to use Compare-VM to Live Migrate a Hyper-V virtual machine to a host with a different virtual switch name. What happens if you need to change the VLAN as well? Turns out, you can do so easily.
How to Change the VLAN ID When Using Compare-VM for Live Migration
We start out the same way that we would for a standard migration when switch names don’t match. Get a compatibility report and store it in a variable:
$CR = Compare-VM -Name movingvm -DestinationHost newhost
If we want to verify that the problem is an incompatible virtual switch, we just look at the Message property of the Incompatibilities items:
$CR.Incompatibilities.Message
If the destination host does have a virtual switch with the sHoame name, you won’t get this line item in the compatibility report. In fact, you might not get a compatibility report at all. We’ll come back to that situation momentarily.
It’s not quite obvious, but the output above shows you three different incompatibility items. Let’s roll up one level and see the objects themselves. We do that by only asking for the Incompatibilities property.
$CR.Incompatibilities
We can’t read the message (why I showed you the other way first), but we can clearly see three distinct objects. The first two have no meaningful associated action; they only tell you a story. The last one, though, we can do something with. Look at the Source item on it.
$CR.Incompatibilities[2].Source
If the [2] doesn’t make sense, it’s array notation. The first item is 0, second is 1, and the third (the one that we’re interested in) is 2. I could have also used Where-Object with the MessageID.
Can you identify that returned object? It’s a VMNetworkAdapter.
$CR.Incompatibilities[2].Source.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False VMNetworkAdapter Microsoft.HyperV.PowerShell.VMNetworkAdapterBase
The incompatibility report embeds a copy of the virtual machine’s virtual network adapter. Luke’s article tells you to modify the network adapter’s connection during migration. However, you can modify any setting on that virtual network adapter object that you could on any other. That includes the VLAN.
Change the VLAN and the switch in the compatibility report like this:
$CR.Incompatibilities | where MessageID -eq 33012 | foreach { Connect-VMNetworkAdapter -VMNetworkAdapter $_.Source -SwitchName vSwitch -Passthru | Set-VMNetworkAdapterVlan -Access -VlanId 25 }
I did all of that using the popular “one-liner” format. I’ve never been a huge fan of the one-liners fad; it’s usually preposterous showboating. But, if you can follow this one, it lets you work interactively. If you’d rather go multi-line, say for automation purposes, you can build something like this:
($CR.Incompatibilities | where MessageID -eq 33012).Source | foreach { Connect-VMNetworkAdapter -VMNetworkAdapter $_ -SwitchName vSwitch Set-VMNetworkAdapterVlan -VMNetworkAdapter $_ -Untagged # ... other VMNetworkAdapter-related settings ... # }
Once you’ve got the settings the way that you like them, perform the Live Migration:
Move-VM -CompatibilityReport $CR
Don’t forget that if the VM’s storage location(s) at the destination host will be different paths than on the source, you need to specify the location(s) when you make the Compare-VM call. Otherwise, you’ll get the networking part prepared for Move-VM, but then it will fail because of storage.
Changing the VLAN without a Compatibility Report
I tried for a while to generate a malleable compatibility report when the switch names match. You can run Compare-VM, of course. Doing so will get you a VMCompatibilityReport object. But, you won’t get the 33012 object/error combination object that we need to modify. There’s no way for the VLAN itself to cause an error because every Hyper-V switch supports VLANs 1-4096. The .Net objects involved (Microsoft.HyperV.PowerShell.VMCompatibilityReport and Microsoft.HyperV.PowerShell.VMCompatibilityError) do not have constructors that I can figure out how to call from PowerShell. I thought of a few ways to deal with that, but they were inelegant at best.
Instead, I chose to move the VLAN assignment out of the Live Migration:
$MovingVM = Move-VM -Name movingvm -DestinationHost desthost -Passthru # and other parameters like storage $MovedVM = Get-VM -ComputerName desthost -Id $MovingVM.VMId Set-VMNetworkAdapterVlan -VM $MovedVM -Access -VlanId 25
A slightly different method would involve using Get-VM first and saving that to $MovingVM, then manipulating $MovingVM. I chose this method to save other tinkerers the trouble of exploring PassThru in this context. PassThru with Move-VM captures the original virtual machine, not the transferred virtual machine. Also, I didn’t need to match by VMId. I chose that technique because virtual machine names are not guaranteed to be unique. So, you have some room to change this script to suit your needs.
Whatever modifications you come up with, you’ll wind up with a two step operation:
- Move the virtual machine to the target host
- Change the VLAN
I hear someone overthinking it: If we’re accustomed to Live Migration causing only a minor blip in network connectivity, won’t this two step operation cause a more noticeable delay? Yes, it will. But that’s not because we’ve split it into two steps. It’s because the VLAN is being changed. That’s always going to cause a more noticeable interruption. The amount of effort required to combine the VLAN change into the Live Migration would not yield worthwhile results.
I should also point out the utility of the $MovedVM object. We focused on the VLAN and virtual network adapter in this article. With $MovedVM, you can modify almost any aspect of the virtual machine.
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!