VMware to Hyper-V Migration with MAT and my addons

Today I was on Sommarkollo at Microsoft Sweden and speaking on the event and this was the last of two sessions about the MAT (Migration Automation Toolkit).

This automation tool that I first got to know about at MMS 2013 in Las Vegas (sadly it looks like there will be no more MMS 🙁 but that is another story ) in the session held by “Migration Mark” and Matt McSpirit WS-B325 and there in the video about 41 minutes into I ask about how the MAT take care of IP addresses on the migrated VM´s and they answered me that is not part of the MAT yet! And well I would say that this would be quite painful to migrate 100-200 VM´s with this automation tool and still have to enter IP settings for each migrated vm manually!!

But I have an example on how that can be done, I have not integrated it into the MAT scripts yet but it automates the collection of not just the IP addresses but also dns,subnet and gateway.

The information is available via the PowerCLI from the vCenter and here I show you how you can collect all that info after you have got the migration list

01# Collect Networking info from VM´s
02#
03# Niklas Akerlund / 2013-07-01
04if(!(Get-PSSnapin "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue)){
05    Add-PSSnapin "VMware.VimAutomation.Core"
06}
07$MigVMs = Get-Content "d:\mat\vmlist.txt"
08$VMNetConf = @()
09Connect-VIServer vCenter.vniklas.com
10remove-module Hyper-V -ErrorAction SilentlyContinue
11 
12foreach ($MigVM in $MigVMs){
13     $VM = Get-VM $MigVM.Split(".")[0]
14     #write-host $VM
15     #$VM = Get-VM $VM
16     $VMNics = Get-VMGuestNetworkInterface $VM | where {$_.IP -ne $null -and $_.IPPolicy -eq "Static"}
17     foreach ($VMNic in $VMNics){
18         $VMNetAdapter = Get-NetworkAdapter -VM $VMNic.VM -Name $VMNic.NetworkAdapter
19          $obj = [PSCustomObject]@{
20                        VMName = $VM.Name
21                        NetworkName = $VMNetAdapter.NetworkName
22                        IP = $VMNic.Ip
23                        Subnet = $VMNic.SubnetMask
24                        DNS = [string]$VMNic.Dns
25                        GW = $VMNic.DefaultGateway
26                        }
27          $VMNetConf +=$obj
28     }
29}
30 
31$VMNetConf | Export-csv -Path d:\mat\vmniclist.txt -NoTypeInformation -NoClobber -UseCulture

Here you can see the csv file after it has run in my test environment, one thing that I will extend with after discussing with some folks is the vlan number the port group the vm is connected to so that can be configured on the other side also.

Screen Shot 2013-08-15 at 23.30.25

And then I also with the possibility that there is in Hyper-V 2012, configure the network on the guest from the host, this requires that the virtual machine has the latest integration components installed. Ravikanth has done a blog post about how his function, I have added the possibility to run it from a remote computer

01# Set-VMNetworkConfiguration
02# Orginial by Ravikanth http://www.ravichaganti.com/blog/?p=2766
03#
04# Added computername to remotly set IP to guest from hosts
05# Niklas Akerlund
06Function Set-VMNetworkConfiguration {
07    [CmdletBinding()]
08    Param (
09         
10        [Parameter(Mandatory=$true,
11                   Position=1,
12                   ParameterSetName='DHCP',
13                   ValueFromPipeline=$true)]
14        [Parameter(Mandatory=$true,
15                   Position=0,
16                   ParameterSetName='Static',
17                   ValueFromPipeline=$true)]
18        [Microsoft.HyperV.PowerShell.VMNetworkAdapter]$NetworkAdapter,
19         
20        [Parameter(Mandatory=$true,
21                   Position=2,
22                   ParameterSetName='DHCP',
23                   ValueFromPipeline=$true)]
24        [Parameter(Mandatory=$true,
25                   Position=5,
26                   ParameterSetName='Static',
27                   ValueFromPipelineByPropertyName=$true)]
28        [String[]]$ComputerName=@(),
29 
30        [Parameter(Mandatory=$true,
31                   Position=1,
32                   ParameterSetName='Static')]
33        [String[]]$IPAddress=@(),
34 
35        [Parameter(Mandatory=$false,
36                   Position=2,
37                   ParameterSetName='Static')]
38        [String[]]$Subnet=@(),
39 
40        [Parameter(Mandatory=$false,
41                   Position=3,
42                   ParameterSetName='Static')]
43        [String[]]$DefaultGateway = @(),
44 
45        [Parameter(Mandatory=$false,
46                   Position=4,
47                   ParameterSetName='Static')]
48        [String[]]$DNSServer = @(),
49          
50        [Parameter(Mandatory=$true,
51                   Position=0,
52                   ParameterSetName='DHCP')]
53        [Switch]$Dhcp
54         
55    )
56 
57    $VM = Get-WmiObject -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' -ComputerName $ComputerName | Where-Object { $_.ElementName -eq $NetworkAdapter.VMName }
58    $VMSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' }   
59    $VMNetAdapters = $VMSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData')
60 
61    $NetworkSettings = @()
62    foreach ($NetAdapter in $VMNetAdapters) {
63        if ($NetAdapter.Address -eq $NetworkAdapter.MacAddress) {
64            $NetworkSettings = $NetworkSettings + $NetAdapter.GetRelated("Msvm_GuestNetworkAdapterConfiguration")
65        }
66    }
67 
68    if ($Dhcp) {
69        $NetworkSettings[0].DHCPEnabled = $true
70    } else {
71        $NetworkSettings[0].DHCPEnabled = $false
72        $NetworkSettings[0].IPAddresses = $IPAddress
73        $NetworkSettings[0].Subnets = $Subnet
74        $NetworkSettings[0].DefaultGateways = $DefaultGateway
75        $NetworkSettings[0].DNSServers = $DNSServer
76        $NetworkSettings[0].ProtocolIFType = 4096
77    }
78 
79    $Service = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace "root\virtualization\v2" -ComputerName $ComputerName
80    $setIP = $Service.SetGuestNetworkAdapterConfiguration($VM, $NetworkSettings[0].GetText(1))
81 
82    if ($setip.ReturnValue -eq 4096) {
83        $job=[WMI]$setip.job
84 
85        while ($job.JobState -eq 3 -or $job.JobState -eq 4) {
86            start-sleep 1
87            $job=[WMI]$setip.job
88        }
89 
90        if ($job.JobState -eq 7) {
91            write-host "Success"
92        }
93        else {
94            $job.GetError()
95        }
96    } elseif($setip.ReturnValue -eq 0) {
97        Write-Host "Success"
98    }
99}

And here is the script that I run to configure the VM´s after the MAT has done the conversions, and yes as Mark says about MAT, there is room for improvements here also of course, As you can see I start with injecting the latest integration components into the VM, the sleep cmdlet is used to get the vm fully booted and integration components installed and then an reboot inside the VM.

01# Configure and set VM after Conversion
02#
03# Niklas AKerlund / 2013-07-01
04 
05# Function import
06. .\Set-VMNetworkConfiguration.ps1
07 
08$VMNICs = Import-CSV -Path D:\mat\vmniclist.txt -Delimiter ";"
09$ConvertedVMs = Get-Content -Path D:\mat\VMlist.txt
10 
11# Configure each vm before starting
12foreach ($ConvertedVM in $ConvertedVMs){
13    $VM = Get-VM $ConvertedVM.Split(".")[0]
14    write-host $VM.Name
15    #patch each VM with latest Integration Tools
16    $virtualHardDiskToUpdate =($VM | Get-VMHardDiskDrive).path
17    $integrationServicesCabPath ="C:\Windows\vmguest\support\amd64\Windows6.x-HyperVIntegrationServices-x64.cab"
18 
19    #Mount the VHD
20    $diskNo=(Mount-VHD -Path $virtualHardDiskToUpdate –Passthru).DiskNumber
21 
22    #Get the driver letter associated with the mounted VHD, note this assumes it only has one partition if there are more use the one with OS bits
23    $driveLetter=(Get-Disk $diskNo | Get-Partition | where Size -GT 100MB).DriveLetter
24 
25    #Check to see if the disk is online if it is not online it
26    if ((Get-Disk $diskNo).OperationalStatus -ne 'Online'){Set-Disk $MountedVHD.Number -IsOffline:$false -IsReadOnly:$false}
27 
28    #Install the patch
29    Add-WindowsPackage -PackagePath $integrationServicesCabPath -Path ($driveLetter + ":\")
30 
31    #Dismount the VHD
32    Dismount-VHD -Path $virtualHardDiskToUpdate
33     
34    Start-VM -VM $VM
35 
36    Start-Sleep -Seconds 300
37     
38    # Wait for the Integration components being installed and the server reboot (reboot requires interaction or automatic script inside VM or you will have to do an unclean poweroff
39 
40    Start-VM -VM $VM
41 
42    # check that the migrated VM actually has ic that responds
43    do {
44        $notok = Get-VMIntegrationService -VM $VM | Select -First 1 | where PrimaryStatusDescription -eq "OK"
45    } while( $notok -eq $null)
46 
47    # COnfigure NICs
48    foreach ($VMNic in $VMNICs){
49        write-host "Configuring"
50        if($VMNIC.VMName -eq $VM.Name){
51           if(!(Get-VMNetworkAdapter -VM $VM)){
52               $VMNetAdapter = Add-VMNetworkAdapter -VM $VM -SwitchName $VMNic.NetworkName -Passthru
53               $VMNetAdapter | Set-VMNetworkConfiguration -IPAddress $VMNic.IP -DefaultGateway $VMNic.GW -Subnet $VMNic.SubnetMask -DNSServer $VMNic.Dns -ComputerName HV03
54          
55           }else {
56            
57               Connect-VMNetworkAdapter -VMName $VM.Name -SwitchName $VMNic.NetworkName
58               $VMNetAdapter = Get-VMNetworkAdapter -VM $VM
59               write-host "connecting $VMNic.NetworkName "
60               $VMNetAdapter | Set-VMNetworkConfiguration -IPAddress $VMNic.IP -DefaultGateway $VMNic.GW -Subnet $VMNic.Subnet -DNSServer $VMNic.DNS -ComputerName HV03
61          }
62        }
63    }
64 
65}

And after running as you can see in the Hyper-V manager I have the right IP on the VM (and if you check inside the VM, you will see that the dns,subnet and gateway also has been set correctly.

Screen Shot 2013-08-15 at 23.38.27

Comments

tasos
Reply

Hello.I’m trying to use Set-VMNetworkConfiguration on a linux vm but i get an wmi error.The integration services are installed.Any ideas?Have you made it work on linux?
Thanks in advanced!

Francesco
Reply

Hi Niklas,

can you say me how i can set the alternate DNS Server with “Set-VMNetworkConfiguration” Script?

Thx for your Feedback.

Leave a comment

name*

email* (not published)

website