Where I work, we use VMware to virtualize the majority of our servers. Last
year, we bought four new servers in order to provide more resources to our
virtual evironment, and also to aid in the upgrade to vSphere 4 from VI3. The
plan was to power off all virtual machines and perform an offline migration of
all the VMs from the old cluster to the new cluster. However, we were also
migrating from the vSwitch to the distributed virtual switch (dvSwitch).
The Setup:
To start out, I upgraded VMware vCenter Server to version 4.x. After that was
done, I created a new cluster and added all four new hosts to it. I then mapped
all of the same LUNs to the new cluster that were already mapped to the old
cluster. This allowed me to do a migration from the old cluster to the new
without having to worry about storage migrations. Next, I created the new
dvSwitch with all the same port groups as the old vSwitch. It was important to
make sure all VLAN IDs were present. Finally, I powered off all virtual
machines.
The Code
Now for the interesting part. I wrote a PowerShell script to automate the
migration of the VMs from the old cluster to the new. At the same time, it
looks at the vSwitches and maps them to their equivalent dvSwitch port group by
looking for matching VLALN IDs. For example, if there is a vSwitch port group
called “Monkey” with VLAN ID of 123, it will check the dvSwitch port groups and
map that to whichever one also has VLAN ID 123.
# Generate a hash of dvSwitch port group VLAN IDs and names, using ID as key.function CreateDVMap() {
$vlanmap = @{}
$pgs = Get-VIew -ViewType DistributedVirtualPortgroup
foreach ($pg in $pgs) {
$vlan = $pg.Config.DefaultPortConfig.vlan.vlanid
if ($vlan -and !$vlanmap.ContainsKey($vlan)) {
$vlanmap.Add($vlan, $pg.name)
}
}
return $vlanmap
}
function MigrateVM($vm, $target, $dvMap) {
# Is the virtual machine in the "Test Dev" resource pool? $resPool = Get-ResourcePool -VM $vm
if ($resPool -and $resPool.Name.CompareTo("Test Dev") -eq 0) {
$TestDev = $true
} else {
$TestDev = $false
}
$newnetnames = @()
Write-Host "Migrating VM", $vm.Name
# Translate the vSwitch PG of each NIC to the equivalent dvSwitch PGforeach ($nic in $vm.NetworkAdapters) {
Write-Host $nic.name -ForegroundColor Blue
Write-Host $nic.NetworkName -ForegroundColor Green
$vlanid = (Get-VirtualPortGroup -Name $nic.NetworkName -VMHost $vm.Host).VlanId
Write-Host "VLAN ID is" $vlanid
$newnetnames += $dvMap.get_item($vlanid)
}
$newvm = Move-VM -VM $vm -Destination $target
if ($TestDev) {
# If it is a Test/Dev VM, move it to the new resource pool $rp = Get-ResourcePool -Location $newvm.host.parent -Name "Test Dev" $newvm = Move-VM -vm $newvm -Destination $rp
}
# Now, set all the NICs to their new dvSwitch port group $i = 0
foreach ($nic in $newvm.NetworkAdapters) {
Set-NetworkAdapter -NetworkAdapter $nic -NetworkName $newnetnames[$i++] -Confirm:$false
}
}
# Connect to the vCenter Server$vihost = Connect-VIServer "vCenter-Server-Hostname"# Target host in the new cluster to deposit all VMs on$targetHost = Get-VMHost "Some-Hostname-Here"# Generate a hash of all dvSwitch PGs$vlanmap = CreateDVMap
# Get a list of all VMs in "Production cluster"$vmlist = Get-VM -Location (Get-Cluster "Production") | Where { $_.PowerState -eq "PoweredOff" } | Select "Name"# Iterate through the VMs and migrate themforeach ($vmname in $vmlist) {
$vm = Get-VM $vmname.name
MigrateVM $vm $targetHost $vlanmap
}
Disconnect-VIServer $vihost -Confirm:$false