Migrating off a distributed virtual switch to standard switch Article 1

Normally people want to migrate from virtual standard switches to distributed switches.   I am a huge fan of the distributed switch and feel it should be used everywhere.   The distributed switch becomes a challenge when you want to migrate hosts to a new vCenter.   I have seen a lot of migrations to new vCenters via detaching the ESXi hosts and connecting to the new vCenter.   This process works great assuming you are not using the distributed switch.   Removing or working with VM’s on a ghosted VDS is a real challenge.   So remove it before you migrate to a new vCenter.

In this multi-article solution I’ll provide some steps to migrate off a VDS to a VSS.

It’s important to understand that assuming that networking is correct this process should not interrupt customer virtual machines.   The movement from a distributed switch to a standard switch at most will lose a ping.   When you assign a new network adapter a gratuitous arp is sent out the new adapter.   If you only have two network adapters this process does remove network adapter redundancy while moving.

Step 1:​​ Create a VSS with the same port groups

You need to create a standard switch with port groups on the correct VLAN ID’s.  ​​​​ You can do this manually but one of the challenges of the standard switch is the name must be exactly the same including case sensitivity to avoid vMotion errors. ​​ (One great reason for the VDS) ​​ So we need to use a script to create the standard switch and port groups.  ​​​​ Using PowerCLI (sorry orchestrator friends I didn’t do it in Orchestrator this time)

Code:

#Import modules for PowerCLI

 ​​ ​​ ​​​​ Import-Module​​ -Name​​ VMware.VimAutomation.Core

 ​​ ​​ ​​​​ Import-Module​​ -Name​​ VMware.VimAutomation.Vds

 

 ​​​​ #Variables to change

 ​​ ​​ ​​​​ $standardSwitchName​​ =​​ "StandardSwitch"

 ​​ ​​ ​​​​ $dvSwitchName​​ =​​ "dvSwitch"

 ​​ ​​ ​​​​ $cluster​​ =​​ "Basement"

 ​​ ​​ ​​​​ $vCenter​​ =​​ "192.168.10.14"

 

 ​​ ​​ ​​​​ #Connect to vCenter

 ​​ ​​ ​​​​ connect-viserver​​ -server​​ $vCenter

 

 

 

 ​​​​ $dvsPGs​​ =​​ Get-VirtualSwitch​​ -Name​​ $dvSwitchName​​ |​​ Get-VirtualPortGroup​​ |​​ Select​​ Name,​​ @{N="VLANId";E={$_.Extensiondata.Config.DefaultPortCOnfig.Vlan.VlanId}},​​ NumPorts

 

 ​​​​ #Get all ESXi hosts in a cluster

 ​​​​ $vmhosts​​ =​​ get-cluster​​ -Name​​ $cluster​​ |​​ get-vmhost

 

 ​​ ​​ ​​​​ #Loop ESXi hosts

 ​​ ​​ ​​​​ foreach​​ ($vmhost​​ in​​ $vmhosts)

 ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Create new VSS

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $vswitch​​ =​​ New-VirtualSwitch​​ -VMHost​​ $vmhost​​ -Name​​ $standardSwitchName​​ -Confirm:$false

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Look port groups and create

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ foreach​​ ($dvsPG​​ in​​ $dvsPGs)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Validate the port group is a number the DVUplink returns an array

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ if​​ ($dvsPg.VLANId​​ -is​​ [int]​​ )

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ New-VirtualPortGroup​​ -Name​​ $dvsPG.Name​​ -VirtualSwitch​​ $vswitch​​ -VlanId​​ $dvsPG.VLANId​​ -Confirm:$false

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 

 ​​ ​​ ​​​​ }​​ 

 

Explained: ​​ 

  • Provide variables

  • Connect to vCenter

  • Get all port groups into $dvsPGs

  • Get all ESXi hosts

  • Loop though ESXi hosts one at a time

  • Create the new standard switch

  • Loop through port groups and create them with same name as DVS and VLAN ID

 

This will create a virtual standard switch with the same VLAN and port group configuration as your DVS.  ​​ ​​​​ 

 

I like to be able to validate that the source and destination are configured the same so this powercli script provides the checking:

Code:

#Validation check DVS vs VSS for differences

 

 ​​ ​​ ​​​​ $dvsPGs​​ =​​ Get-VirtualSwitch​​ -Name​​ $dvSwitchName​​ |​​ Get-VirtualPortGroup​​ |​​ Select​​ Name,​​ @{N="VLANId";E={$_.Extensiondata.Config.DefaultPortCOnfig.Vlan.VlanId}},​​ NumPorts

 ​​ ​​ ​​​​ #Get all ESXi hosts in a cluster

 ​​ ​​ ​​​​ $vmhosts​​ =​​ get-cluster​​ -Name​​ $cluster​​ |​​ get-vmhost

 

 ​​ ​​ ​​​​ #Loop ESXi hosts

 ​​ ​​ ​​​​ foreach​​ ($vmhost​​ in​​ $vmhosts)

 ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Write-Host "Host: "$vmhost.Name "VSS: "$standardSwitchName

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Get VSSPortgroups for this host

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $VSSPortGroups​​ =​​ $vmhost​​ |​​ Get-VirtualSwitch​​ -Name​​ $standardSwitchName​​ |​​ Get-VirtualPortGroup

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Sort based upon name of VSS

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ foreach​​ ($dvsPG​​ in​​ $dvsPGs)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ if​​ ($dvsPg.VLANId​​ -is​​ [int]​​ )

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Write "VSSPortGroup: " $VSSPortGroup.Name

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Loop on DVS

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $match​​ =​​ $FALSE

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ foreach​​ ($VSSPortGroup​​ in​​ $VSSPortGroups)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ if​​ ($dvsPG.Name​​ -eq​​ $VSSPortGroup.Name)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Write-Host "Found a Match vss: "$VSSPortGroup.Name" to DVS: "$dvsPG.Name" Host: " $vmhost.name

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $match​​ =​​ $TRUE

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $missing​​ =​​ $dvsPG.Name

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ if​​ ($match​​ -eq​​ $FALSE)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ Write-Host​​ "Did not find a match for DVS: "$missing​​ " on "$vmhost.name

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 

 ​​ ​​ ​​​​ }​​ 

 

Explained:

  • Get the VDS

  • Get all ESXi hosts

  • Loop through VM hosts

  • Get port groups on standard switch

  • Loop though the standard switch port groups and look for matches on DVS

  • If missing then output missing element

 

 

Now we need to give the standard switch an uplink (this is critical otherwise VM’s will fail when moved)

 

Once it has an uplink you can use the following script to move all virtual machines:

 

Code:

#Move Virtual machines to new Adapters

 

 ​​ ​​ ​​​​ $vms​​ =​​ get-vm​​ 

 

 ​​ ​​ ​​​​ foreach​​ ($vm​​ in​​ $vms)

 ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #grab the virtual switch for the hosts​​ 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $vss​​ =​​ Get-VirtualSwitch​​ -Name​​ $standardswitchname​​ -VMHost​​ $vm.VMHost

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #check that the virtual switch has at least one physical adapter

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ if​​ ($vss.ExtensionData.Pnic.Count​​ -gt​​ 0)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #VMHost

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $adapters​​ =​​ $vm​​ |​​ Get-NetworkAdapter​​ 

 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Loop through adapters

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ foreach​​ ($adapter​​ in​​ $adapters)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Get VSS port group of same name returns port group on all hosts

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ $VSSPortGroups​​ =​​ Get-VirtualPortGroup​​ -Name​​ $adapter.NetworkName​​ -VirtualSwitch​​ $standardSwitchName

 ​​ ​​​​ 

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Loop the hosts

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ foreach​​ ($VSSPortGroup​​ in​​ $VSSPortGroups)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Search for the PortGroup on our host

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ if​​ ([string]$VSSPortGroup.VMHostId​​ -eq​​ [string]$vm.VMHost.Id)

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ {

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ #Change network Adapter to standard switch

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ Set-NetworkAdapter​​ -NetworkAdapter​​ $adapter​​ -Portgroup​​ $VSSPortGroup​​ -Confirm:$false

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 ​​ ​​ ​​ ​​ ​​ ​​ ​​​​ }

 ​​ ​​ ​​​​ }​​ 

 

Explained: ​​ 

  • Used same variables from previous script

  • Get all virtual machines (you could use get-vm “name-of-vm” to test a single vm

  • Loop through all virtual machines one at a time

  • Get the VSS for the VM (host specific)

  • Check for at least one physical uplink to switch (gut / sanity check)

  • Loop though the adapters on a virtual machine​​ 

  • For each adapter get VDS port group name and switch the adapter

 

 

 

 

 

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.