Using PowerShell to configure live migration networks in a Hyper-V cluster

A long time ago, Didier Van Hoye asked me how to configure the networks that should be used for live migration by a Hyper-V cluster using nothing but PowerShell.  Unfortunately, I never got around to getting an answer for him – until today.

Didier – this one is for you.

Now for a bit of background:  When you create a Hyper-V cluster, you need to configure which networks are used for virtual machine live migration.  You want to ensure that virtual machine live migration is going over a network with enough bandwidth available (a minimum of 500mbit per concurrent live migration is recommended) and where we are not going to disrupt other network traffic (i.e. do not have live migration run over your storage network).  You also want to ensure that the network used by live migration is appropriately secure – either physically secure, or using technology like IPsec – as we do not do any encryption of the data being sent over this network.

You can do this through the UI quite easily:


But how do you do this with PowerShell?  Well, after a lot of digging around it turns out that it is not that hard.  It is not obvious, but it is not hard.  If you only have one network for live migration – you can actually do this in one line.  If you know the cluster network name you can run:

Get-ClusterResourceType -Name "Virtual Machine" | Set-ClusterParameter -Name MigrationExcludeNetworks -Value ([String]::Join(";",(Get-ClusterNetwork | Where-Object {$_.Name -ne "Migration Network"}).ID))

Or, if you just know the IP subnet for the live migration network you can run this:

Get-ClusterResourceType -Name "Virtual Machine" | Set-ClusterParameter -Name MigrationExcludeNetworks -Value ([String]::Join(";",(Get-ClusterNetwork | Where-Object {$_.Address -ne ""}).ID))

So what is this doing?

Well, it is getting the “Virtual Machine” resource from the cluster (which is actually a global resource – that is not specific to a single virtual machine – bad naming, I know) and then it is setting the “MigrationExcludeNetworks” parameter on this resource.  Which, unsurprisingly, is a list of the cluster networks to exclude from live migration.

Where things get a little fiddly here is:

  • This parameter wants the cluster network IDs rather than the names.  For example: instead of specifying “Management Network” I need to specify “b18643a5-0cab-4d7d-93bf-6b4dc983ed2b”.  This is annoying – but luckily the Get-ClusterNetwork Cmdlet returns this information through the “ID” property.
  • This parameter takes a semi-colon separated list (and there must be no spaces – otherwise it gets mad at you).  Again, annoying but not the end of the world.  In the samples above I use [String]::Join to pull this off. 

It would get quite fiddly (but not impossible) if you wanted to configure multiple networks for live migration – but hopefully you should have the gist of how to do it from reading this article.