Step-by-Step: Live Migrate Multiple (Clustered) VMs in One Line of PowerShell - Revisited

A while back, I wrote an article showing how to Live Migrate Your VMs in One Line of Powershell between non-clustered Windows Server 2012 Hyper-V hosts using Shared Nothing Live Migration.  Since then, I’ve been asked a few times for how this type of parallel Live Migration would be performed for highly available virtual machines between Hyper-V hosts within a cluster. 

In this article, we’ll walk through the steps of doing exactly that … via Windows PowerShell on Windows Server 2012 or 2012 R2 or our FREE Hyper-V Server 2012 R2 bare-metal, enterprise-grade hypervisor in a clustered configuration.

Wait! Do I need PowerShell to Live Migrate multiple VMs within a Cluster?

Well, actually … No.   You could certainly use the Failover Cluster Manager GUI tool to select multiple highly available virtual machines, right-click and select Move | Live Migration

Failover Cluster Manager – Performing Multi-VM Live Migration

But, you may wish to script this process for other reasons … perhaps to efficiently drain all VM’s from a host as part of a maintenance script that will be performing other tasks.

Can I use the same PowerShell cmdlets for Live Migrating within a Cluster?

Well, actually … No again.   When VMs are made highly available resources within a cluster, they’re managed as cluster group resources instead of being standalone VM resources.  As a result, we have a different set of Cluster-aware PowerShell cmdlets that we use when managing these cluster groups.   To perform a scripted multi-VM Live Migration, we’ll be leveraging three of these cmdlets:

Now, let’s see that one line of PowerShell!

Before getting to the point of actually performing the multi-VM Live Migration in a single PowerShell command line, we first need to setup a few variables to handle the "what" and "where" of moving these VMs. 

First, let’s specify the name of the cluster with which we’ll be working.  We’ll store it in a $clusterName variable.

$clusterName = read-host -Prompt "Cluster name"

Next, we’ll need to select the cluster node to which we’ll be Live Migrating the VMs.  Lets use the Get-ClusterNode and Out-GridView cmdlets together to prompt for the cluster node and store the value in a $targetClusterNode variable.

$targetClusterNode =
Get-ClusterNode -Cluster $clusterName |
Out-GridView -Title "Select Target Cluster Node" `
-OutputMode Single


And then, we’ll need to create a list of all the VMs currently running in the cluster. 

We can use the Get-ClusterGroup cmdlet to retrieve this list.  Below, we have an example where we are combining this cmdlet with a Where-Object cmdlet to return only the virtual machine cluster groups that are running on any node except the selected target cluster node.  After all, it really doesn’t make any sense to Live Migrate a VM to the same node on which it’s currently running! Winking smile

$haVMs =
Get-ClusterGroup -Cluster $clusterName |
Where-Object {($_.GroupType -eq "VirtualMachine") `
-and ($_.OwnerNode -ne $targetClusterNode.Name)}

We’ve stored the resulting list of VMs in a $haVMs variable.

Ready to Live Migrate!

OK … Now we have all of our variables defined for the cluster, the target cluster node and the list of VMs from which to choose.  Here’s our single line of PowerShell to do the magic …

$haVMs |
Out-GridView -Title "Select VMs to Move" –PassThru |
Move-ClusterVirtualMachineRole -MigrationType Live `
-Node $targetClusterNode.Name -Wait 0


Proceed with care: Keep in mind that your target cluster node will need to have sufficient available resources to run the VM's that you select for Live Migration. Of course, it's best to initially test tasks like this in your lab environment first.

Here’s what is happening in this single PowerShell command line:

  • We’re passing the list of VMs stored in the $haVMs variable to the Out-GridView cmdlet. 
  • Out-GridView prompts for which VMs to Live Migrate and then passes the selected VMs down the PowerShell object pipeline to the Move-ClusterVirtualMachineRole cmdlet. 
  • This cmdlet initiates the Live Migration for each selected VM, and because it’s using a
    –Wait 0 parameter, it initiates each Live Migration one-after-another without waiting for the prior task to finish.

As a result, all of the selected VMs will Live Migrate in parallel, up to the maximum number of concurrent Live Migrations that you’ve configured on these cluster nodes. The VMs selected beyond this maximum will simply queue up and wait their turn.  Unlike some competing hypervisors, Hyper-V doesn't impose an artificial hard-coded limit on the number of VMs that can be Live Migrated concurrently.  Instead, it's up to you to set the maximum to a sensible value based on your hardware and network capacity.

Do you have your own PowerShell automation ideas for Hyper-V?

Feel free to share your ideas in the Comments section below.

See you in the Clouds!

- Keith