Migrating VMs to a Standard Switch

One of my customers has asked me to help them migrate from one vCenter server to another.  In order to do this without causing interruptions, we're using ESXi servers like boats to bring the VMs from the old environment into the new one; basically the same process that I used last time a customer asked me to do this.

This time, we're completing this process at many different sites and each site has many VMs that need to traverse the vCenter servers.  Since this customer doesn't yet have vSphere 6 with its inter-vCenter vMotion capability, we're left doing it the hard way.  That means doing an arduous, detail oriented, highly repetitive task... or, writing a script to do it for me.

The worst part of this process comes from the VM networking.  We have to create Standard vSwitches on each ESXi host with VLAN configurations that mirror the Distributed vSwitch that belongs in the vCenter, then move all of the VMs to the appropriate Port Groups on the newly created standard switches.  Since this is the worst step, it's the first thing that I scripted.

I did it with 2 scripts.  The first one creates all of the Port Groups on the ESXi host and creates a table mapping the VDS Port Group to the VSS Port Group.  The second script uses that table and moves each VM onto the VSS.  In this environment, we have redundant network connections (hopefully that's the case everywhere) and so we split the team up half way between the VSS and the VDS during the transitional period in order to minimize the impact to the VMs.  In the end, this creates a very small network hiccup for each VM, very similar to a vMotion.

Here's the first script, to create the VSS Port Groups:

#Copies all Port Groups from a Distributed vSwitch to a Standard vSwitch
#Author: Jason Coleman (virtuallyjason.blogspot.com)
#Usage: Make-VSS.ps1 -h [the target ESXi host to get the new standard switch, must have access to the DVS] -s [the name of the DVS to copy] -d [the name of the VSS to copy the Port Groups to]

param
(
   [alias("h")]
   [string]$thisHost = $(read-host -Prompt "Enter the target Host"),
   [alias("s")]
   [string]$source = $(read-host -Prompt "Enter the Source Distributed Virtual Switch name"),
   [alias("d")]
   [string]$destination = $(read-host -Prompt "Enter the Destination Virtual Switch name"),
   [alias("o")]
   [string]$outputFile = "C:\Temp\PGTranslations.xml"
)
#Create an empty array to store the port group translations
$pgTranslations = @()
#Get the destination vSwitch
$destSwitch = Get-VirtualSwitch -host $thisHost -name $destination
#Get a list of all port groups on the source distributed vSwitch
$allPGs = get-vdswitch -name $source | get-vdportgroup
foreach ($thisPG in $allPGs)
{
   $thisObj = new-object -Type PSObject
   $thisObj | add-member -MemberType NoteProperty -Name "dVSPG" -Value $thisPG.Name
   $thisObj | add-member -MemberType NoteProperty -Name "VSSPG" -Value "$($thisPG.Name)-VSS"
   new-virtualportgroup -virtualswitch $destSwitch -name "$($thisPG.Name)-VSS"
   # Ensure that we don't try to tag an untagged VLAN
   if ($thisPG.vlanconfiguration.vlanid)
   {
      get-virtualportgroup -virtualswitch $destSwitch -name "$($thisPG.Name)-VSS" | Set-VirtualPortGroup -vlanid $thisPG.vlanconfiguration.vlanid
   }
   $pgTranslations += $thisObj
} 

$pgTranslations | export-clixml $outputFile

And here's the second script, that moves the VMs onto those Port Groups:

#Moves all VMs from Distributed Port Groups to Standard Port Groups as defined by an input translation table. Designed to use the output translation table from Make-VSS.ps1
#Author: Jason Coleman (virtuallyjason.blogspot.com)
#Usage: Move-to-VSS.ps1 -h [the target ESXi host]
param
(
   [alias("h")]
   [string]$hostIn = $(read-host -Prompt "Enter the target Host"),
   [validateScript({test-path $_ -pathType leaf})]
   [alias("i")]
   [string]$inputFile = "C:\Temp\PGTranslations.xml"
)

#Build the Hashtable
$pgHash = @{}
$allPGs = import-clixml $inputFile
foreach ($thisPG in $allPGs)
{
   $pgHash.add($thisPG.dVSPG, $thisPG.VSSPG)
}

#Sets all VMs on the Host to the new VSS Port groups based on the Hashtable
$thisHost = get-vmhost $hostIn
foreach ($thisVM in ($thisHost | get-VM ))
{
   foreach ($thisNIC in ($thisVM | Get-NetworkAdapter))
   {
      if ($pgHash[$thisNIC.NetworkName])
      {
         if ($portGroup = $thisHost | get-virtualportgroup -name $pgHash[$thisNIC.NetworkName])
         {
            $thisNIC | set-networkadapter -confirm:$false -portgroup $portGroup
         }
         else
         {
            write-host "$($pgHash[$thisNIC.NetworkName]) does not exist."
         }
      }
      else
      {
         echo "$($thisVM.name) $($thisNIC.Name) uses $($thisNIC.NetworkName), which not have a match in the Hash Table."
      }
   }
}

This process has worked great for me, but I'm the only person who's used these scripts.  While they've been tested thoroughly in this environment under my normal working conditions, that's no guarantee that they'll work for you in yours.  Please consider these educational and test everything thoroughly, especially when you're playing around with networking configurations.

Comments

Popular posts from this blog

Orphaned VMDK Files

Migrating from one vCenter to Another, Improved

Copying VM Folders and Permissions from One vCenter to Another