Hyper-V Powershell SCVMM Windows Server

Migrate multiple VM’s from one Hyper-V cluster to another Hyper-V cluster with different Logical Switch using PowerShell.

Another fast publish! (I really should get back and clean these up…)

Recently upgraded one of our Hyper-V clusters and had to migrate workloads to a new Hyper-V cluster.

The naming conventions of our logical switches etc were different so when migrating a VM using Hyper-V manager we were prompted to choose the new logical switch. Handling this via PowerShell in isolation is simple enough using this script but I wanted to do a whole stack of VM’s at once.

As with all of my shared scripts, they come with no warranty and could be better written.

Before running this, take each piece and check it. You’ll likely have issues around permissions etc

Import-Module VirtualMachineManager 
Import-Module Hyper-V 
$UserName = "Yourdomain\administrator" 
$Password = Read-Host -AsSecureString "Password:" 
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName , $Password 
$SCVMM = "YOURVMM.FQDN.Name" 
$Cluster = "oldclustername" 
$sourcehost = "<hostname of source host>" 
$targethost = "<hostname of target host>" 
$Switchname = "LSwitch-Hosts"
$VMS = Get-VMMServer -computername $SCVMM | Get-VM | ` 
    where {$_.Status -eq "Running" -and $_.IsHighlyAvailable -eq "True"} | ` 
    Select-Object -Property Name,IsHighlyAvailable,Cloud,VMHost | ` 
    Sort-Object -Property Name | ` 
    Out-Gridview -Title "Running VM's on $SCVMM" -Passthru 
$VMHost = "hostname of host" 

ForEach ($VM in $VMS) 
{ 
$VMName = $VM.Name 
$HA_VM = Get-Cluster $Cluster | Get-ClusterGroup | where {$_.Name -like "*$VMName*"} 
$OUTPUT= [System.Windows.Forms.MessageBox]::Show("Migrate $VMName to $VMHost and remove resources from cluster?  (Note: VM will remain LIVE)" , "Status" , 4) 
if ($OUTPUT -eq "YES" ) 
    { 
    Get-Cluster $Cluster | ` 
    Move-ClusterVirtualMachineRole -Name $HA_VM -MigrationType Live -Node $sourcehost -ErrorAction SilentlyContinue 
    Get-Cluster $Cluster | ` 
    Get-ClusterResource | where {$_.Name -like "*$VMName*"} | Remove-ClusterResource -Force -ErrorAction SilentlyContinue 
    Get-Cluster $Cluster | ` 
    Get-ClusterGroup | where {$_.Name -like "*$VMName*"} | Remove-ClusterGroup -Force -ErrorAction SilentlyContinue 
    Invoke-Command -ComputerName $sourcehost -Credential $Credential -ScriptBlock { 
        $VMReport = Compare-VM -Name $VM -DestinationHost $targethost 
        $VMReport.Incompatibilities | ?{$_.MessageID -eq 33012} | %{Connect-VMNetworkAdapter $_.source -SwitchName $SwitchName} 
        Move-VM $VMReport -AsJob 
        } 
    } 
else 
    { 
    [System.Windows.Forms.MessageBox]::Show("User stopped any actions on Virtual Machine $VM") 
    } 
}

Obviously do some testing and ensure the variables fit your environment.

Enjoy!
Dan

Leave a Reply