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.
- Article 1: Creating a VSS and migrating the virtual machines
- Article 2: Migrating the host off the VDS
- Article 3: Migrating the host to a new vCenter and back into the distributed switch
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