Migrating virtual machines using PowerCLI
In my current role as a VMware architect, I architected a greenfield VMware vSphere 6.5 environment.
The ‘old’ environment, who I architected 4 year ago, is VMware vSphere 5.5. As the old environment was never updated, the time and risk of upgrading this environment was too high. That’s why, we decided to go for a greenfield installation.
As the new environment was accepted by the customer system administrators, we had to migrate 700 virtual machines to the new environment.
The old environment was using NFS datastores, as the new environment is using hyperconverged.
As the old environment was vSphere 5.5 U1, we weren’t able to vMotion virtual machines to the new cluster, using Cross vCenter vMotion.
To make the migration as painless as possible, I create a PowerCLI script to do the hard work for us.
The script is very straight forward.
- Read ini-file for configuration options
- Read hosts.txt file for a list with ESXi hosts to configure
- Configure ESXi
- DNS
- IPv6
- NTP
- Syslog (see below for sample)
- Power Policy
- Network (including migration to DVS)
- Reboot ESXi
Everything is logged to a logfile in the current directory.
config.ini
; configuration file for VMwareConfig.ps1 ; version 1.0 ; parameters are case sensitive!!! [defaults] ipv6=false powerpolicy=balanced reboot=true esxipassword=[rootpassword] subnetmask=255.255.255.0 [dns] dns1=[dns server] dns2=[dns server] suffix=[dns domain] [servers] syslog=udp://sysloghost:514 ntp=[ntp server] vcenter=[VC Server] [vcenter] datacenter=[Datacenter name] cluster=[cluster name] dvs=[DVS name] dvuplink1=vmnic0 dvuplink2=vmnic1 dvportgroupmgmt=[Management DV Portgroup] portgroupmgmt=Management Network dvportgroupvmotion=[vMotion DV Portgroup] vmkvmotion=vmk2
VMwareConfig.ps1
#Config VMware vSphere #Versie: 1.0 #Author: M. Wilmsen //Log everything Start-Transcript -Path ".\log.txt" function Get-IniFile { param( [parameter(Mandatory = $true)] [string] $filePath ) $anonymous = "NoSection" $ini = @{} switch -regex -file $filePath { "^\[(.+)\]$" # Section { $section = $matches[1] $ini[$section] = @{} $CommentCount = 0 } "^(;.*)$" # Comment { if (!($section)) { $section = $anonymous $ini[$section] = @{} } $value = $matches[1] $CommentCount = $CommentCount + 1 $name = "Comment" + $CommentCount $ini[$section][$name] = $value } "(.+?)\s*=\s*(.*)" # Key { if (!($section)) { $section = $anonymous $ini[$section] = @{} } $name,$value = $matches[1..2] $ini[$section][$name] = $value } } return $ini } #Get variables from config.ini $iniFile = Get-IniFile .\config.ini $username = "$env:USERNAME"+'@grid-ota.internal' $dns1 = $iniFile.dns.dns1 $dns2 = $iniFile.dns.dns2 $suffix = $iniFile.dns.suffix $syslog = $iniFile.servers.syslog $ntp = $iniFile.servers.ntp $ipv6 = $iniFile.defaults.ipv6 $powerpolicy = $iniFile.defaults.powerpolicy $reboot = $iniFile.defaults.reboot $subnetmask = $iniFile.defaults.subnetmask $vcenter = $iniFile.servers.vcenter $datacenter = $iniFile.vcenter.datacenter $cluster = $iniFile.vcenter.cluster $dvSwitch = $iniFile.vcenter.dvs $ESXiPassword = $iniFile.defaults.esxipassword $dvUplink1 = $iniFile.vcenter.dvuplink1 $dvUplink2 = $iniFile.vcenter.dvuplink2 $dvPortgroupMGMT = $iniFile.vcenter.dvportgroupmgmt $portgroupMGMT = $iniFile.vcenter.portgroupmgmt $dvportgroupVMotion = $iniFile.vcenter.dvportgroupvmotion #if ( $ipv6 -notlike "$*" ) { $ipv6 = "$" + $ipv6 } $username = "administrator@vmgrid.internal" Write-Host "The following config will be used..." Write-Host "************************************" Write-Host "ESXi root password: " $ESXiPassword Write-Host "vCenter username: " $username Write-Host "vCenter server: " $vcenter Write-Host "vCenter datacenter: " $datacenter Write-Host "vCenter cluster: " $cluster Write-Host "vCenter DVS: " $dvSwitch Write-Host "dvUplink1: " $dvUplink1 Write-Host "dvUplink2: " $dvUplink2 Write-Host "dvPortgroup Management: " $dvPortgroupMGMT Write-Host "Portgroup Management: " $portgroupMGMT Write-Host "dvPortgroup vMotion: " $dvPortgroupVMotion Write-Host "DNS servers: " $dns1"," $dns2 Write-host "DNS suffix: " $suffix Write-Host "Syslog server: " $syslog write-host "NTP Server" $ntp Write-Host "IPv6 enabled: " $ipv6 Write-Host "PowerPolicy: " $powerpolicy Write-Host "Default Subnetmask :" $subnetmask Write-Host "Reboot: "$reboot Write-Host "************************************" while( "y","Y","n","N" -notcontains $answer ) { $answer = Read-Host "Are these setting correct? [y/n]" } if ( $answer -eq "n" -or $answer -eq "N" ) { Write-Host "Please correct settings in config.ini" break } Write-Host "Oke, here we go!" Write-Host "" $hosts = "./hosts.txt" Write-Host "Configuring the following ESXi host(s):" -ForegroundColor Yellow Get-Content $hosts | ForEach-Object { Write-Host $_ -ForegroundColor Magenta } #Define vCenter Password $Password = Read-Host "Enter your vCenter password" -AsSecureString $VCPasswordDec = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)) #Connect vCenter Server #write-host $username $VCPasswordDec Connect-VIServer $vcenter -User $username -Password $VCPasswordDec Remove-Variable VCPasswordDec $VIserverlist = $Global:DefaultVIServer if ( $VIserverlist -eq $null ) { Write-host "No connection to vCenter server $vcenter. Exiting..." BREAK } Get-Content $hosts | ForEach-Object { $esxi = $_ $fqdn = $esxi + "." + $suffix Write-Host "Configuring ESXi: " $fqdn -ForegroundColor Yellow if ( Test-Connection -ComputerName $fqdn -Quiet ) { Write-Host "ESXi host response to ping" $PingESXi = $true } else { Write-Host "Cannot contact ESXi, skipping" -ForegroundColor Red $PingESXi = $false } if ( $PingESXi ) { Write-Host "Add ESXi $fqdn to vCenter: $vcenter ..." -ForegroundColor Magenta Add-VMHost $fqdn -Location (Get-Datacenter $datacenter | Get-Cluster $cluster) -User root -Password $ESXiPassword -RunAsync -force:$true Start-Sleep -s 20 $vmhost = get-vmhost -Name $fqdn Write-Host "Configuring DNS..." -ForegroundColor Magenta $vmhost | Get-VMHostNetwork | Set-VMHostNetwork -DomainName $suffix -DNSAddress $dns1 , $dns2 -SearchDomain $suffix -Confirm:$False Write-Host "Configuring IPv6..." -ForegroundColor Magenta $vmhost | Get-VMHostNetwork | Set-VMHostNetwork -IPv6Enabled ([System.Convert]::ToBoolean($ipv6)) -Confirm:$False Write-Host "Configuring NTP..." -ForegroundColor Magenta #$ntpold = Get-VMHostNtpServer -VMHost $fqdn #Remove-VMHostNTPServer -NtpServer $ntpold -VMHost $fqdn -Confirm:$false | Out-Null Add-VMHostNTPServer -NtpServer $ntp -VMHost $fqdn -Confirm:$false Get-VMHostService -VMHost $fqdn | where{$_.Key -eq "ntpd"} | Set-VMHostService -policy "on" -Confirm:$false Get-VMHostService -VMHost $fqdn | where{$_.Key -eq "ntpd"} | Restart-VMHostService -Confirm:$false #Syslog Write-Host "Configuring syslog..." -ForegroundColor Magenta Get-AdvancedSetting -Entity $vmhost -Name Syslog.global.logHost | Set-AdvancedSetting -Value $syslog -Confirm:$false #Power Policy Write-Host "Configuring Power Policy..." -ForegroundColor Magenta $vmhostview = Get-View -ViewType Hostsystem -Filter @{"Name"=$($vmhost).Name} -Property ConfigManager.PowerSystem $powerpolicyconfig = Get-View $vmhostview.ConfigManager.PowerSystem switch ( $powerpolicy ) { 'High Performance'{ Write-Host "Configuring PowerPolicy to High Performance" -ForegroundColor Magenta; $powerpolicyconfig.ConfigurePowerPolicy(1) } 'Balanced' { Write-Host "Configuring PowerPolicy to Balanced" -ForegroundColor Magenta; $powerpolicyconfig.ConfigurePowerPolicy(2) } 'Low Power' { Write-Host "Configuring PowerPolicy to Low Power" -ForegroundColor Magenta; $powerpolicyconfig.ConfigurePowerPolicy(3) } 'Custom' { Write-Host "Configuring PowerPolicy to Custom" -ForegroundColor Magenta; $powerpolicyconfig.ConfigurePowerPolicy(4) } default { Write-Host "No valid value of Power Policy: $powerpolicy" -ForegroundColor Red } } #Configuring Network Write-host "Add host $fqdn to dvSwitch $dvSwitch" -ForegroundColor Magenta Add-VDSwitchVMHost -VDSwitch $dvSwitch -VMhost $vmhost -Confirm:$false #Start-Sleep -s 60 #Migrate VMNIC0 to DVS Write-Host "Migrate VMNIC0 to DVS $dvSwitch" -ForegroundColor Magenta $vmhostNetworkAdapter = Get-VMHost $vmhost | Get-VMHostNetworkAdapter -Physical -Name $dvUplink1.toUpper() Get-VDSwitch $dvSwitch | Add-VDSwitchPhysicalNetworkAdapter -VMHostNetworkAdapter $vmhostNetworkAdapter -confirm:$false Start-Sleep -s 3 #Migrated VMNIC1 to DVS Write-Host "Add $dvUplink2 to DVS $dvSwitch" -ForegroundColor Magenta $vmhostNetworkAdapter = Get-VMHost $fqdn | Get-VMHostNetworkAdapter -Physical -Name $dvUplink2.toUpper() Get-VDSwitch $dvSwitch | Add-VDSwitchPhysicalNetworkAdapter -VMHostNetworkAdapter $vmhostNetworkAdapter -confirm:$false Start-Sleep -s 3 Clear-variable -Name "answer" while( "y","Y","n","N" -notcontains $answer ) { $answer = Read-Host "Continue? [y/n]" } if ( $answer -eq "n" -or $answer -eq "N" ) { Write-Host "Exiting" break } #Migrage Management vmk0 to DVS Write-Host "Migrate vmk0 (Management) to DVS $dvSwitch" -ForegroundColor Magenta $vmk = Get-VMHostNetworkAdapter -Name vmk0 -VMHost $vmhost Set-VMHostNetworkAdapter -Portgroup $dvPortgroupMGMT -VirtualNic $vmk -confirm:$false #Add vMotion vmk $fqdnVMotion = $esxi + "vmt.grid.internal" $vmotionIP = [System.Net.Dns]::GetHostAddresses("$fqdnVMotion").IPAddressToString $dvs = Get-VDSwitch -Name $dvSwitch Write-Host "Adding VMotion vmk to $dvSwitch, dvPortgroup $dvportgroupVMotion with address: $vmotionIP / $subnetmask" -ForegroundColor Magenta New-VMHostNetworkAdapter -VMHost $vmhost -PortGroup $dvportgroupVMotion -VMotionEnabled $true -VirtualSwitch $dvs -IP $vmotionIP -SubnetMask $subnetmask #Remove Standard portgroups and vSwitches Write-Host "Remove virtual Switch vSwitch0 including portgroups" $vswitch = Get-VirtualSwitch -VMHost $vmhost -Name vSwitch0 Write-Host "Removing vSwitch portgroup $portgroupMGMT ..." -ForegroundColor Magenta $mgmt_pg = Get-VirtualPortGroup -Name $portgroupMGMT -VirtualSwitch $vswitch Remove-VirtualPortGroup -VirtualPortGroup $mgmt_pg -confirm:$false Write-Host "Removing vSwitch portgroup VM Network..." -ForegroundColor Magenta $vm_pg = Get-VirtualPortGroup -Name "VM Network" -VirtualSwitch $vswitch Remove-VirtualPortGroup -VirtualPortGroup $vm_pg -confirm:$false Write-Host "Removing vSwitch portgroup Backplane Network ..." -ForegroundColor Magenta $bp_pg = Get-VirtualPortGroup -Name "Backplane Network" -VirtualSwitch $vswitch Remove-VirtualPortGroup -VirtualPortGroup $bp_pg -confirm:$false #Remove vSwitch0 Write-Host "Removing standard vSwitch vSwitch0" -ForegroundColor Magenta Remove-VirtualSwitch -VirtualSwitch $vswitch -confirm:$false if ( [System.Convert]::ToBoolean($reboot) ) { #Shutdown Nutanix CVM in order to reboot ESXi host Start-Sleep -s 60 Write-Host "Restart ESXi..." -ForegroundColor Magenta $vmhost | Restart-VMHost -Force -Confirm:$false } } } Write-Host "Disconnect vCenter server $vcenter" -ForegroundColor Magenta Disconnect-VIServer -Server $vcenter -Confirm:$false Write-Host "Done!" -ForegroundColor Magenta
About Michael
Michael Wilmsen is a experienced VMware Architect with more than 20 years in the IT industry. Main focus is VMware vSphere, Horizon View and Hyper Converged with a deep interest into performance and architecture.
Michael is VCDX 210 certified, has been rewarded with the vExpert title from 2011, Nutanix Tech Champion and a Nutanix Platform Professional.