If you have a mixed Hyper-V environment with Hyper-V hosts which have different CPU generations you may cannot live migration Virtual Machines from one Hyper-V host to another without setting the VM CPU Compatibility setting.
Note: I saw a lot of different environments where different generation of Intel CPUs were used, and most of the time Live Migration did still work. I would recommend to set this setting only if you really need it.
If you need to do this for multiple Virtual Machines you may better use Windows PowerShell to do this.
To do this you can use the new Hyper-V PowerShell module and the Get-VMProcessor and Set-VMProcessor cmdlet. With the Get-VMProcessor cmdlet you can get information about the virtual CPU of VMs. You can list this for all virtual machines running on one host by using the following command
Get-VMProcessor *
To change this setting for all virtual machines running on the Hyper-V host you can use the following PowerShell command. This does only working with virtual machines which are not running.
Get-VMProcessor * | Set-VMProcessor -CompatibilityForMigrationEnabled 1
If you want to shut down all the VMs first you can use the following command.
Get-VM | Stop-VM
If you just want to do this for a single VM you can use the following commands.
Get-VM TMG | Stop-VM Get-VM TMG | Set-VMProcessor -CompatibilityForMigrationEnabled 1
To do a full automation you could do it the following way:
Get-VM * | Stop-VM Get-VM * | Set-VMProcessor -CompatibilityForMigrationEnabled 1 Get-VM * | Start-VM
As you can see you can also find the “CompatibilityForOlderOperatingSystemsEnabled” property to enable Processor Compatibility for legacy Operating Systems in Windows Server 2012 Hyper-V for example Windows NT 4.0 Server or Windows 2000.
Tags: CPU, Hyper-V, Live Migration, Microsoft, PowerShell, Processor, Set-VMProcessor, Virtual Machine, VM, VM Processor Compatibility PowerShell, Windows Server, Windows Server 2012 Last modified: January 7, 2019
Stumbled on this post and it’s very helpful. Thank you!
The only thing I am missing is how to do this in a clustered environment.
I’d like to create a script that I can run on my Windows 8.1 computer or just one of my nodes in the cluster, without specifying the node on which the VM is running.
“Get-ClusterGroup | ? {$_.GroupType –eq ‘VirtualMachine’ } | Get-VM” shows me every VM in the cluster, but specifying a VM results in a long list of errors about not being able to pipeline or something.
Is there a way to do this?
For anyone interested:
get-vm -ClusterObject (Get-ClusterResource | where ResourceType -eq “Virtual Machine”) | Get-VMProcessor | where compatibilityformigrationenabled -eq $False
You could probably pipe the results into Stop-VM | Set-VMProcessor -CompatibilityForMigrationEnabled 1 | Start-VM and get the desired automation. The above assumes you’re on one of the clusternodes, else you’d have to specify -Cluster “name” after Get-clusterResource
Full one-liner would be:
Get-VM -ClusterObject (Get-ClusterResource -Cluster cool-awesome-cluster-name | where ResourceType -eq “Virtual Machine”) | Get-VMProcessor | where compatibilityformigrationenabled -eq $False | Stop-VM | Set-VMProcessor -CompatibilityForMigrationEnabled 1 | Start-VM
I can’t test this atm, because I don’t have access to a test-cluster currently. I will remedy this asap.
I got around to testing it and naturally, it wasn’t quite that easy. The objects passed from get-vmprocessor can’t be used to shutdown the guest – and even if you filter it, it has “lost” the cluster-part. So I changed it around a bit, and THIS works like a charm:
get-vm -ClusterObject (Get-ClusterResource | where {$_.resourcetype -eq “Virtual Machine”}) | Get-VMProcessor | where compatibilityformigrationenabled -eq $False | get-clustergroup | get-vm | Stop-VM -passthru| Set-VMProcessor -compatibilityformigrationenabled 1 -passthru| get-clustergroup | get-vm | Start-VM
This must be run on any of the clusternodes, and it will effectively find all machines missing the cpu compatibility flag, shut them down, set the flag, and start the machines again. All machines with the flag already set, are ignored.