This Script will clone an existing vDS and its port groups.  **with new UUIDs**
This is great if you get a corrupted vDS and need to migrate away from it.
Or, if you want to recreate a new vDS in the image of an old one without using the export/import method.

** quick notes:
– This creates a new distributed switch and port groups with new IDs.  This isn’t good to use as an Export/Import when migrating hosts and VMs to a new vCenter.
– This script does not keep special Security Policies but its very easy to add it to the script. I left all of the vars complete so you can pull and assign the extension data for additional needs.
– This code pulls an old vDS and its port groups, then recreates a new one using a “-2” at the end of the names.  At the very end of the script, it then removes the “-2” from the names.   Keep this in mind if you have “-2” in the name of your vDS or port groups.  If you do use this “-2” string in your existing names, change it in the script to something like “QQQQ” so you can remove the trailing text at the end without impacting your existing names.

## Set your old vDS name and paste the rest.

Add-PSSnapin VMware.*
$oldVDSName = “dvs-MyvDS”

#Grab the old vDS info
$oldvDS = get-VDSwitch $oldVDSName

#Create the new one and rename its uplink
$newvDS = new-vdswitch -name ($”-2″) -location $ -NumUplinkPorts $oldvDS.NumUplinkPorts -mtu $oldvDS.Mtu
$oldUpLink = $oldvDS | get-vdportgroup | where {$_.IsUplink -eq “True”}
$newvDS | get-vdportgroup | where {$_.IsUplink -eq “True”}  | set-vdportgroup -name ($”-2″) -vlantrunkRange $oldUpLink.VlanConfiguration

#Pull the old vDS port groups and recreate them on the new vDS
$Portgroups = $oldvDS | get-vdportgroup | ?{$_.IsUplink -ne “True”}
foreach($port in $portgroups){
$Pname = $ + “-2”
$PVlanid = $port.VlanConfiguration.vlanid
$pNumPorts = $port.numports
$newvDS | New-VDPortgroup -Name $Pname -Vlanid $PVlanid -numports $pNumPorts
$newvDS | New-VDPortgroup -Name $Pname -numports $pNumPorts

#Here you can migrate ESXi Host links and VMs from your old vDS to your new vDS.
#If you want to migrate to the new vDS, you can get some code help here :
#If you copied the vDS to the same vCenter, keep in mind that vDS names and vDS Port group names are vcenter unique.
#You will need to delete your old vDS or rename it to remove the “-2” from the new one.

#Remove the old vDS if you no longer need it – Do this Manual so you can verify that everything has migrated…
#$oldvDS | remove-vdswitch -confirm:$False

#rename the new vDS and its port groups to match the orginal.
$newvDS | set-vdSwitch -name ($ -replace “-2″,””)
$Portgroups = $newvDS | get-vdportgroup

foreach($port in $portgroups){
$port | set-vdportgroup -name ($ -replace “-2″,””)


#Here is some extra code to set the Teaming Load Balancing policy for all port groups on your new vDS. This is configured to set all port groups to “Route based on Physical NIC load”
#Change the port group load policy to Load based
$newvDSPortgroups = get-VDSwitch $newVDS | get-vdportgroup
Function Set-VDPortGroupTeamingPolicy {
param (

Process {
$spec = New-Object VMware.Vim.DVPortgroupConfigSpec
$spec.configVersion = $VDPortgroup.ExtensionData.Config.ConfigVersion
$spec.defaultPortConfig = New-Object VMware.Vim.VMwareDVSPortSetting
$spec.defaultPortConfig.uplinkTeamingPolicy = New-Object VMware.Vim.VmwareUplinkPortTeamingPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.inherited = $false
$spec.defaultPortConfig.uplinkTeamingPolicy.policy = New-Object VMware.Vim.StringPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.policy.inherited = $false
$spec.defaultPortConfig.uplinkTeamingPolicy.policy.value = “loadbalance_loadbased”

foreach($port in $newvDSPortgroups){
$port| Set-VDPortgroupTeamingPolicy


#this code will scan all hosts in your vcenter and check for duplicate IPs. You can narrow the scan by placing a get-cluster or get-datacenter object when loading the “$thedata” var.

$thedata = get-vmhost | Get-VMHostNetwork | Select Hostname, VMkernelGateway -ExpandProperty VirtualNic
$report = @()
$temp = $thedata | %{$_.ip}
$h = @{}
$temp | foreach {$h[“$_”] += 1}
$dups = $h.keys | where {$h[“$_”] -gt 1}
foreach($a in $dups){
$report += $thedata | where {$_.ip -eq $a} | select hostname,ip,ManagementTrafficEnabled,VMotionEnabled
$report | ft

#sample output :
#HostName     IP                        ManagementTrafficEnabled       VMotionEnabled
#———-         ———-             ———                                             —————-
#esx01        False                                                True
#esx06       False                                                 True

#if you want the report to include more information you can edit the “report +=” line and add extra fields  (to the select area).
#example : You can add the Devicename and PortGroupName if you need help finding the exact vmk with the dup IP.
$report += $thedata | where {$_.ip -eq $a} | select hostname,ip,devicename,portgroupname,ManagementTrafficEnabled,VMotionEnable

This code will pull the list of vlans on your vDS trunk, pull the vlans of each port group on the vDS, then compare the two to find any misconfigurations.
This can help identify if any vDS Trunk is missing vlans (for vDS healthcheck to work right.)
Help find vDS objects that have a vlan configured on the trunk but no port group to use it.
— Ultimately.. this is a Health Check for the vDS Health Check.

$report = @()
$vds = get-vdswitch

foreach($a in $vds){
$pgs = $a | get-vdportgroup
$uplinkvlans = @()
$uplinkvlantypecheck = $pgs| ?{$ -like “*Uplinks*”} | %{$_.VlanConfiguration.vlantype}
if($uplinkvlantypecheck -eq “Trunk”){
$uplinkvlanrange = $pgs| ?{$ -like “*Uplinks*”} | %{$_.VlanConfiguration.ranges}
foreach($b in $uplinkvlanrange){
if($b.StartVlanId -eq “0” -and $b.EndVlanId -eq “4094”){$report += $ + ” Trunk is configured with ALL VLANs — 0-4094″ }else{
$start = $b.StartVlanId
$end = $b.EndVlanId
$uplinkvlans += $start..$end
} #end Else
} #end foreach vlan on trunk
} #end if trunk
else{$uplinkvlans = $pgs| ?{$ -like “*Uplinks*”} | %{$_.VlanConfiguration.vlanid}
} #end else

#end uplink vlan collection

$vmPGs = $pgs | ?{$ -notlike “*Uplinks*”}
$pgvlans = @()
foreach($apg in $vmPGs){
if(($apg.VlanConfiguration.vlantype) -eq “Trunk”){
$pgvlanrange = $apg | %{$_.VlanConfiguration.ranges}
foreach($b in $pgvlanrange){
$start = $b.StartVlanId
$end = $b.EndVlanId
$pgvlans += $start..$end
} #end foreach vlan in PG
} #end if trunk
else{$pgvlans += $apg| %{$_.VlanConfiguration.vlanid}
} #end else
} #end port group vlan collection

$pgvlans = $pgvlans | select -unique
$checkit = Compare-Object $uplinkvlans $pgvlans
if($checkit.inputobject.count -gt 0){
foreach($aa in $checkit){
if($aa.sideindicator -eq “<="){$texta = "PortGroup"} if($aa.sideindicator -eq "=>“){$texta = “Trunk”}
$report += $ + ” ” +$texta+” is missing vlan “+ $aa.inputobject

If your hosts can see the CDP info from your physical network, this will help check or map your port configs.

$Clustername = “hotness”
$report = @()
$allhosts = get-cluster $Clustername | get-vmhost
foreach($singlehost in $allhosts){
Get-VMHost $singlehost | Where-Object {$_.State -eq “Connected”} |
%{Get-View $_.ID} |
%{$esxname = $_.Name; Get-View $_.ConfigManager.NetworkSystem} |
%{foreach($physnic in $_.NetworkInfo.Pnic){
$pnic = $_.QueryNetworkHint($physnic.Device)
foreach($thing in $pnic){
$ReportRow = “” | select Hostname,vmnic,Ttl,Samples,DevId,Address,PortId,HardwarePlatform,Vlan,FullDuplex,Mtu
if( $thing.ConnectedSwitchPort ) {
$reportRow.Hostname = $esxname
$reportRow.vmnic = $physnic.Device
$reportRow.Ttl = $thing.ConnectedSwitchPort.ttl
$reportRow.Samples = $thing.ConnectedSwitchPort.samples
$reportRow.DevId = $thing.ConnectedSwitchPort.Devid
$reportRow.Address = $thing.ConnectedSwitchPort.address
$reportRow.PortId = $thing.ConnectedSwitchPort.portid
$reportRow.HardwarePlatform = $thing.ConnectedSwitchPort.HardwarePlatform
$reportRow.Vlan = $thing.ConnectedSwitchPort.vlan
$reportRow.FullDuplex = $thing.ConnectedSwitchPort.fullduplex
$reportRow.Mtu = $thing.ConnectedSwitchPort.mtu
}}$report += $reportrow}}}

 Then you can “export-csv”  the $report var or just throw it on the command line to see the output.

This code will help you step though the creation of VMotion networks on your hosts.

######### the vars ####
$thehost = “”
$theVswitch = “vSwitch1”
$vmotion1IP = “”
$vmotion2IP = “”
$theSubnetMask = “”

### the code ###
### Create the Vmotion Port groups
get-vmhost -name $thehost | Get-VirtualSwitch -name $theVswitch | new-VirtualPortGroup -name vmotion1 -vlanid 0
get-vmhost -name $thehost | Get-VirtualSwitch -name $theVswitch | new-VirtualPortGroup -name vmotion2 -vlanid 0

### Create the Vmotion VMKernels
New-VMHostNetworkAdapter -VMHost $thehost -PortGroup vmotion1 -VirtualSwitch $theVswitch -IP $vmotion1IP -SubnetMask $theSubnetMask -VMotionEnabled:$true
New-VMHostNetworkAdapter -VMHost $thehost -PortGroup vmotion2 -VirtualSwitch $theVswitch -IP $vmotion2IP -SubnetMask $theSubnetMask -VMotionEnabled:$true

### Change the Network Teaming Policy to Active/Standby on both vmotion network port groups.
### Use this code if you are using two vmotion networks and want them to run on seperate NICs
$thingy = get-virtualswitch -vmhost $thehost -name $theVswitch | Get-virtualportgroup -name “vmotion1” | get-nicteamingPolicy
$thingy | Set-NicTeamingPolicy -MakeNicActive “vmnic1” -MakeNicStandby “vmnic2”
$thingy = get-virtualswitch -vmhost $thehost -name $theVswitch | Get-virtualportgroup -name “vmotion2” | get-nicteamingPolicy
$thingy | Set-NicTeamingPolicy -MakeNicActive “vmnic2” -MakeNicStandby “vmnic1”

VMWare Links:

This code will migrate everything on a standard switch to a distributed switch at a cluster wide level.
***Note: If the hosts in the cluster have inconsistent vmnic numbers, this script will probably explode if ran at a cluster level.
For example: If all hosts in the cluster use “vmnic1 and vmnic2″ for vswitch1” then this works great.
Basic steps this code executes:
1- Set vars from a reference host in the cluster.
2- Creates the Distributed switch, scans the portgroup names on the specified standard vSwitch and creates the new portgroups on the vDS.
– It names the switch “vds-ClusterName” and the portgroups “ClusterName-YourOldPortGroupName”
3 – Sets all of the portgroups on the vDS to a “load based” policy.
4 – Adds the hosts to the vDS then migrates all but one of the vmnics to the vDS.  I have it place the vmnic in standby before it’s removed from the host.
5 – Migrates all of the VMs that were part of that vSwitch to the new vDS portgroups.
6 – Removes the last vmnic from the vSwitch and adds it to the vDS.  I added a check to not migrate the vmnic is a VM still exists on the vSwitch.

This code could be cleaned but I shoot for slow and sure. I paste it in steps to be 100% sure everything completes.
Some quick notes before you start :
– I suggest setting DRS to manual to prevent any vm migrations. An active migration will cause a VM portgroup change to fail.
– If your vSwitch has more than two vmnics, you can add those to the vars below. Anything that is not added to $hostvnic1 is removed from the host in the first vnic pull. For example: If you set $hostvnic1 to “vmnic3,vmnic4” then it will keep vmnic3 and vmnic4 on the host and move all remaining vmnics to the vDS during the first vmnic migration. The end of the script will migrate the remaining vnics noted in $hostvnic1.

Add-PSSnapin VMware.VimAutomation.Core
Add-PSSnapin VMware.VimAutomation.Vds
Connect-VIServer “MyvCenter”
####### Step1 = These are the only settings you need to change for a basic vDS migration
$datacentername = “MyDataCenter”
$clustername = “MyCluster”
$hostname = “”
$vswitch = “vswitch2”
$hostvnic1 = “vmnic4”
$hostvnic2 = “vmnic5”

####### Step2 – vDS and portgroup creation
$VDSName = “vDS-“+$Clustername
$UplinkName = $vdsname+”Uplinks”
new-vdswitch -name $VDSName -location $datacentername
get-vdswitch -name $vdsname | get-vdportgroup | ?{$ -like “*Uplinks*”} | set-vdportgroup -name “$uplinkName”
$Portgroups = get-vmhost -name $hostname | get-virtualswitch -name $vswitch | get-virtualportgroup
foreach($port in $portgroups){
$Pname = $clustername +”-“+ $
$PVlanid = $port.vlanid
Get-VDSwitch -Name $vdsname | New-VDPortgroup -Name $Pname -Vlanid $PVlanid -numports 256

####### Step3 – Set the portgroups to a Load Based Policy
$DVSPortgroups = get-virtualswitch -name $vdsname | get-virtualportgroup
Function Set-VDPortGroupTeamingPolicy {
param (
Process {
$spec = New-Object VMware.Vim.DVPortgroupConfigSpec
$spec.configVersion = $VDPortgroup.ExtensionData.Config.ConfigVersion
$spec.defaultPortConfig = New-Object VMware.Vim.VMwareDVSPortSetting
$spec.defaultPortConfig.uplinkTeamingPolicy = New-Object VMware.Vim.VmwareUplinkPortTeamingPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.inherited = $false
$spec.defaultPortConfig.uplinkTeamingPolicy.policy = New-Object VMware.Vim.StringPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.policy.inherited = $false
$spec.defaultPortConfig.uplinkTeamingPolicy.policy.value = “loadbalance_loadbased”
foreach($port in $DVSportgroups){
$singlePG = $
Get-VDPortgroup $singlePG | Set-VDPortgroupTeamingPolicy

####### Step4 – First vmnic pull – For each host in the cluster, mark the vmnics in var $hostvnic2 as unused, remove them from the host and add them to the vDS.
$clusterhosts = @()
$clusterhosts += get-cluster $clustername | get-vmhost
foreach($hosts in $ClusterHosts){
$singlehost = $
Get-VMHost $singlehost | Get-VirtualSwitch | Where-Object {$_.Name -eq $vswitch} | get-nicteamingpolicy | set-nicteamingpolicy -makenicunused $hostvnic2
sleep 10
Get-VMHost $singlehost | Get-VirtualSwitch | Where-Object {$_.Name -eq $vswitch} | Set-VirtualSwitch -Nic $hostvnic1 -confirm:$false
Add-VDSwitchVMHost -vdswitch $vdsname -vmhost $singlehost
$hostadapter = get-vmhost -name $singlehost | Get-vmhostnetworkadapter -physical -name $hostvnic2
get-vdswitch $VDSName |add-vdswitchphysicalnetworkadapter -vmhostnetworkadapter $hostadapter -confirm:$false

####### Step5 – Migrate all of the VMs on the vSwitch to the vDS port groups.
foreach($hosts in $ClusterHosts){
$singlehost = $
foreach($port in $portgroups){
$Pname = $clustername +”-“+ $
$OldNetwork = $
$NewNetwork = $Pname
Get-Cluster $clustername |get-vmhost $singlehost |Get-VM |Get-NetworkAdapter |Where {$_.NetworkName -eq $OldNetwork } |Set-NetworkAdapter -NetworkName $NewNetwork -Confirm:$false

####### Step6 – For each host , check if any VMs still exist on the vSwitch, if its empty, migrate the vmnics in var $hostvnic1 to the vDS.
$nic = @()
foreach($hosts in $ClusterHosts){
$singlehost = $
$checkme = get-vmhost $singlehost | get-vm | get-virtualswitch | where {$ -eq $vswitch} | %{$} | out-string |measure-object -character
$checkcount = $checkme.characters
if($checkcount -lt 1){
Get-VMHost $singlehost | Get-VirtualSwitch | Where-Object {$_.Name -eq $vswitch} | get-nicteamingpolicy | set-nicteamingpolicy -makenicunused $hostvnic1
sleep 10
Get-VMHost $singlehost | Get-VirtualSwitch | Where-Object {$_.Name -eq $vswitch} | Set-VirtualSwitch -Nic $nic -confirm:$false
$hostadapter = get-vmhost -name $singlehost | Get-vmhostnetworkadapter -physical -name $hostvnic1
get-vdswitch $VDSName |add-vdswitchphysicalnetworkadapter -vmhostnetworkadapter $hostadapter -confirm:$false
}else {
Write-host “$singlehost vmnic $hostvnic1 Migration FAILED – VMs STILL EXIST ON THE VSWITCH!!”

####### End of script #######

Here are some checks I do before and after running this:
– Before I run it, I set the cluster DRS Setting to manual or partial. If a VM is migrating during the script it will not be able to migrate its portgroup config.
– I also like to pull a list of all VMs in the cluster and start a constant Ping. This way I know if something didn’t migrate correctly. For a click list, click the cluster level and select the Virtual Machine tab, then you can right click in the list and export to csv.
– After Step2 I check the vDS to make sure everything was created correctly and that the names look good.
– After Step4 I like to scan a few hosts to make sure things the correct vmnics are still active. You can also check the vDS and see all of the hosts and active vmnics.
– During Step5 I watch my active ping script to look for lost connections.
– Before pasting Step6, to remove the last of the vmnics from the hosts, I run through and look for vms that did not migrate. The script will catch it but I like to double check.
– Once the script is complete, I launch the webclient interface and enable “Health Check”. You can enable the health check by clicking on a Distributed Switch, click manage, Health Check, then click EDIT and change the two values “VLAN and MTU”, and “Teaming and failover” to Enabled then click OK. Once that is done, you can click on the Monitor tab then click health to see each hosts “vDS health.” You can find out if vlans are missing on your trunks or if you have an invalid MTU setting.

Some extra things to note :
– The health check will complain if you leave the vDS uplink vlans set to 0-4094. I change the list to match what vlans I have configured on my portgroups.
– You can set the vDS to use a 9000 MTU by placing (-mtu 9000) in Step2 on the “New-vdswitch” line

This code will create a new Distributed switch at the datacenter level of your vcenter.
Keep in mind that distributed switchs are vCenter objects instead of host objects.
If you are running vcenter 5.1 and deploying distributed switches, I highly suggest the vDS backup script here >
Add-PSSnapin VMware.VimAutomation.Vds
new-vdswitch -name “MyNewvDS”-location “MyDataCenterName” -mtu 9000

VMware Link:

This code will restore your distributed switch to a new vcenter or the existing vcenter (if the vDS is fully deleted or missing.)
Doing this restore will allow all VMs to go from “invalid backing” to the real portgroup name, and all hosts will show their nics attached to the vDS.

#edit the path and filename as needed:

Add-PSSnapin VMware.VimAutomation.Core
Add-PSSnapin VMware.VimAutomation.Vds

Connect-VIServer “MyvCenter” -username “username” -password “password”
new-vdswitch -backuppath “E:\VDSBackup\” -keepIdentifiers -location “NameOfDatacenter”

Vmware Link:

This script will backup your Distributed Switch config to a zip file.
You can then use this zip file to restore the vDS to a new vcenter or if your vcenter database corrupts.

Add-PSSnapin VMware.VimAutomation.Core
Add-PSSnapin VMware.VimAutomation.Vds
Connect-VIServer “MyVcenter” -username “username” -pass “password”
$date= (get-date).tostring(‘ddMMMyyy-HHmm’)
$VDSwitches = get-VDSwitch | %{$}
foreach($vdswitch in $VDSwitches){
$filename = “E:\VDSBackup\”+$vdswitch +”-“+ $date+”.zip”
Get-VDSwitch -Name $vdswitch | Export-VDSwitch -Destination $filename

Disconnect-viserver -confirm:$False

View the Restore code here >

Vmware Link: