dvSwitch scripting – Part 2 – dvPortgroup
In Part 1 of the dvSwitch scripting series I created a simple dvSwitch with 2 uplinks, which I connected to all the ESX hosts that were returned as possible candidates. In this part I will show you how to add a dvPortgroups and how you can connect Virtual Machines to this dvPortgroup.
This is the schematic of what we have so far.
And the uplink port allocation.
Update March 28th 2010
The previous version of the New-dvSwPortgroup function was rather simplistic.
This new, and completely re-vamped, version allows you to specify the VLAN type and the VLANIds if required. Note that the new version requires PowerShell v2 RTM.
Update July 22nd 2010
With this new version all the security and teaming options are available. Follow the hyperlinks for more information on the different parameters.
There are a number of options that you can’t configure from the vSphere client! For example the load based teaming as described in Frank Denneman’s blog.
The following table shows the available parameters. The new ones are highighted.
| Parameter | Type | Default | Comment |
| PgNumberPorts | int | 64 | |
| PgBinding | string | earlyBinding | |
| PgVLANType | string | ||
| PgVLANId | int[] | ||
| SecPolPromiciousMode | Boolean | false | |
| SecPolMacChanges | Boolean | true | |
| SecPolForgedTransmits | Boolean | true | |
| TeamingCheckDuplex | Boolean | false | |
| TeamingCheckErrorPercent | Boolean | false | |
| TeamingPercentage | int | ||
| TeamingCheckSpeed | Boolean | false | |
| TeamingSpeed | int | ||
| TeamingPolicy | string | loadbalance_srcid | Accepted values:
loadbalance_ip loadbalance_srcmac loadbalance_srcid failover_explicit loadbalance_loadbased |
| TeamingNotifySwitches | Boolean | true | |
| TeamingRollingOrder | Boolean | false | |
| TeamingReversePolicy | Boolean | true | |
| TeamingActiveUplink | string[] | ||
| TeamingStandbyUplink | string[] |
function Get-dvSwitch{
param([parameter(Position = 0, Mandatory = $true)][string]$DatacenterName,
[parameter(Position = 1, Mandatory = $true)][string]$dvSwitchName)
$dcNetFolder = Get-View (Get-Datacenter $DatacenterName | Get-View).NetworkFolder
$found = $null
foreach($net in $dcNetFolder.ChildEntity){
if($net.Type -eq "VmwareDistributedVirtualSwitch"){
$temp = Get-View $net
if($temp.Name -eq $dvSwitchName){
$found = $temp
}
}
}
$found
}
function Get-VLANRanges{
param ([int[]]$ids)
$return = @()
$nr = 0
$start = $ids[$nr]
$end = -1
while($nr -lt ($ids.Count)){
if(($ids[$nr + 1]-$ids[$nr]) -gt 1){
$end = $ids[$nr]
$nrange = New-Object VMware.Vim.NumericRange
$nrange.start = $Start
$nrange.end = $end
$return += $nrange
$start = $ids[$nr + 1]
$end = -1
}
$nr++
}
if($end -lt 0){
$nrange = New-Object VMware.Vim.NumericRange
$nrange.start = $Start
$nrange.end = $ids[-1]
$return += $nrange
}
$return
}
function New-dvSwPortgroup{
param([parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][VMware.Vim.VmwareDistributedVirtualSwitch]$dvSw,
[parameter(Position = 1, Mandatory = $true)][string]$PgName,
[int]$PgNumberPorts = 64,
[string]$PgBinding = "earlyBinding",
[string]$PgVLANType = "none",
[int[]]$PgVLANId,
[switch]$SecPolPromiciousMode = $false,
[switch]$SecPolMacChanges = $true,
[switch]$SecPolForgedTransmits = $true,
[switch]$TeamingCheckDuplex = $false,
[switch]$TeamingCheckErrorPercent = $false,
[string]$TeamingCheckSpeed = $false,
[switch]$TeamingFullDuplex = $true,
[int]$TeamingPercentage,
[int]$TeamingSpeed,
[string]$TeamingPolicy = "loadbalance_srcid",
[switch]$TeamingNotifySwitches = $true,
[switch]$TeamingRollingOrder = $false,
[switch]$TeamingReversePolicy = $true,
[string[]]$TeamingActiveUplink,
[string[]]$TeamingStandbyUplink
)
process{
$teamingPolicies = "loadbalance_ip",
"loadbalance_srcmac",
"loadbalance_srcid",
"failover_explicit",
"loadbalance_loadbased"
$spec = New-Object VMware.Vim.DVPortgroupConfigSpec
$spec.Name = $PgName
$spec.Type = $PgBinding
$spec.numPorts = $PgNumberPorts
$spec.defaultPortConfig = New-Object VMware.Vim.VMwareDVSPortSetting
switch($PgVLANType.ToLower()){
"vlan" {
$spec.defaultPortConfig.VLAN = New-Object VMware.Vim.VmwareDistributedVirtualSwitchVlanIdSpec
$spec.defaultPortConfig.VLAN.vlanId = $PgVLANId[0]
}
"vlan trunking" {
$spec.defaultPortConfig.VLAN = New-Object VMware.Vim.VmwareDistributedVirtualSwitchTrunkVlanSpec
$spec.defaultPortConfig.VLAN.vlanId = Get-VLANRanges $PgVLANId
}
"private vlan" {
$spec.defaultPortConfig.VLAN = New-Object VMware.Vim.VmwareDistributedVirtualSwitchPvlanSpec
$spec.defaultPortConfig.VLAN.pvlanId = $PgVLANId[0]
}
Default{}
}
$spec.defaultPortConfig.securityPolicy = New-Object VMware.Vim.DVSSecurityPolicy
$spec.defaultPortConfig.securityPolicy.allowPromiscuous = New-Object VMware.Vim.BoolPolicy
$spec.defaultPortConfig.securityPolicy.allowPromiscuous.Value = $SecPolPromiciousMode
$spec.defaultPortConfig.securityPolicy.forgedTransmits = New-Object VMware.Vim.BoolPolicy
$spec.defaultPortConfig.securityPolicy.forgedTransmits.Value = $SecPolForgedTransmits
$spec.defaultPortConfig.securityPolicy.macChanges = New-Object VMware.Vim.BoolPolicy
$spec.defaultPortConfig.securityPolicy.macChanges.Value = $SecPolMacChanges
$spec.defaultPortConfig.uplinkTeamingPolicy = New-Object VMware.Vim.VmwareUplinkPortTeamingPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria = New-Object VMware.Vim.DVSFailureCriteria
if($TeamingCheckDuplex){
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria.checkDuplex = $TeamingCheckDuplex
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria.fullDuplex = $TeamingFullDuplex
}
if($TeamingCheckErrorPercent){
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria.checkErrorPercent = $TeamingCheckErrorPercent
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria.percentage = $TeamingPercentage
}
if("exact","minimum" -contains $TeamingCheckSpeed){
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria.checkSpeed = $TeamingCheckSpeed
$spec.defaultPortConfig.uplinkTeamingPolicy.failureCriteria.speed = $TeamingSpeed
}
$spec.defaultPortConfig.uplinkTeamingPolicy.notifySwitches = New-Object VMware.Vim.BoolPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.notifySwitches.Value = $NotifySwitches
if($teamingPolicies -contains $TeamingPolicy){
$spec.defaultPortConfig.uplinkTeamingPolicy.policy = New-Object VMware.Vim.StringPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.policy.Value = $TeamingPolicy
}
$spec.defaultPortConfig.uplinkTeamingPolicy.reversePolicy = New-Object VMware.Vim.BoolPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.reversePolicy.Value = $TeamingReversePolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.rollingOrder = New-Object VMware.Vim.BoolPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.rollingOrder.Value = $TeamingRollingOrder
$spec.defaultPortConfig.uplinkTeamingPolicy.uplinkPortOrder = New-Object VMware.Vim.VMwareUplinkPortOrderPolicy
$spec.defaultPortConfig.uplinkTeamingPolicy.uplinkPortOrder.activeUplinkPort = $TeamingActiveUplink
$spec.defaultPortConfig.uplinkTeamingPolicy.uplinkPortOrder.standbyUplinkPort = $TeamingStandbyUplink
$taskMoRef = $dvSw.AddDVPortgroup_Task($spec)
$task = Get-View $taskMoRef
while("running","queued" -contains $task.Info.State){
$task.UpdateViewData("Info")
}
$task.Info.Result
}
}
Annotations:
Line 1: since there is in the current PowerCLI build no cmdlet to get the dvSwitch object, I had to write one. The function Get-dvSwitch loops through the children of the Network folder to find the dvSwitch that was requested. If the dvSwitch is not found, the function returns $null.
Line 18-44: The helper function Get-VLANRanges takes an array of VLAN Ids and converts them to the minimal number of NumericRange objects. The function returns an array with the resulting NumericRange objects.
Line 47-67: The New-dvSwPortgroup parameters. Note that several of the parameters have default values. Also note that the function has two positional parameters and that the other parameters are all named parameters. Have a look at the Example calls of the function a bit further along.
Line 69: To allow the function to be used in a pipeline, the new version uses the Process block.
Line 133: the AddDVPortgroup_Task requires the portgroup Type to be specified, allthough the SDK reference says otherwise in the description of the DVPortgroupConfigSpec object. The accepted values can be found in the DistributedVirtualPortgroupPortgroupType enumeration. The possible values are:
- earlyBinding: free port assigned when the VM is configured to connect to the dvPortgroup
- ephemeral: free port assigned when VM is powered on and removed when the VM is powered off
- lateBinding: free port assigned when VM is powered on
These values correspond with what you see under Port binding in the vSphere client.
Line 81-95: The part where the VLAN type of the the new portgroup is configured. Possible values here are:
- None: the portgroup does not use a VLAN
- VLAN: the portgroup uses a single VLAN Id
- VLAN Trunking: the portgroup uses trunk mode.The guest OS manages its own VLAN tags.
- Private VLAN: the portgroup uses a private VLAN Id. The dvSwitch needs to have primary and secondary VLANIds defined and you select the desired secondary PVLANId for this mode.
These values correspond with what you see under VLAN type in the vSphere client when you create a new Distributed Virtual Port Group .
Line 97-103: The part where the security settings are defined.
Line 105-131: The Teaming and failover settings.
Examples
Some sample calls of the New-dvSwPortgroup function.
$datacenterName = "Home1" $dvSwitchName = "dvSw1" $dvPgNumPorts = 32 $dvSw = Get-dvSwitch -DatacenterName $datacenterName -dvSwitchName $dvSwitchName # No VLAN $dvSwPg = New-dvSwPortgroup $dvSw "dvPg1" $dvSwPg = Get-dvSwitch $datacenterName $dvSwitchName | New-dvSwPortgroup -PgName "dvPg2" $dvSwPg = New-dvSwPortgroup $dvSw "dvPg3" -PgNumberPorts $dvPgNumPorts $dvSwPg = New-dvSwPortgroup $dvSw "dvPg4" -PgBinding "earlyBinding" -PgVLANType "none" $dvSwPg = New-dvSwPortgroup $dvSw "dvPg5" -PgBinding "ephemeral" -PgVLANType "none" $dvSwPg = New-dvSwPortgroup $dvSw "dvPg6" -PgBinding "lateBinding" -PgVLANType "none" # VLAN $dvSwPg = New-dvSwPortgroup $dvSw "dvPg7" -PgNumberPorts $dvPgNumPorts -PgVLANType "VLAN" -PgVLANId 2011 # VLAN Trunking $dvSwPg = New-dvSwPortgroup $dvSw "dvPg8" -PgNumberPorts $dvPgNumPorts -PgVLANType "VLAN Trunking" -PgVLANId (2023..2027) $dvSwPg = New-dvSwPortgroup $dvSw "dvPg9" -PgNumberPorts $dvPgNumPorts -PgVLANType "VLAN Trunking" -PgVLANId 2023,2025,2027 # PVLAN $dvSwPg = New-dvSwPortgroup $dvSw "dvPg10" -PgNumberPorts $dvPgNumPorts -PgBinding "lateBinding" -PgVLANType "Private VLAN" -PgVLANId 2031 # MAC addr changes $dvSwPg = New-dvSwPortgroup $dvSw "dvPg11" -SecPolMacChanges:$false # Teaming $dvSwPg = New-dvSwPortgroup $dvSw "dvPg12" -TeamingPolicy "loadbalance_srcid" -TeamingActiveUplink "dvUplink1","dvUplink2"
Annotations
Line 8: Straightforward call, creates a new portgroup taking all the defaults
Line 9: The dvSw is passed through the pipeline to the New-dvSwPortgroup function. Again taking all the defaults.
Line 10: The number of ports is passed to the call.
Line 11-13: These show the possible values for the portgroup type, the PgBinding parameter.
Line 16: Creates a portgroup that uses a single VLAN Id
Line 19-20: Two examples how a portgroup with Trunking VLAN can be created. This shows the usefulness of the Get-VLANRanges helper function. In the vSphere Client you’ll see that a minimal number of ranges was used.
Line 23: A portgroup with a Private VLAN.
Line 26: Create a portgroup with the Security option MAC Address Changes set to Reject.
Line 29: A portgroup with Load Balancing based on the originating virtual port (the default) and with 2 active uplinks.
Portgroup dvPg8
Portgroup dvPg9
Line 23: The final sample call shows how to create a portgroup that uses a Private VLAN. See also dvSwitch scripting – Part 6 – Private VLAN for the concept behind private VLANs.
The secondary VLANId on the Distributed Virtual Switch
The portgroup dvPg10
Now that there is a dvPortgroup, we can configure a VM to connect to the dvPortgroup.
function Set-VM2dvPortgroup{
param($vmName, $nicName, $dvPgName)
$vm = Get-VM $vmName | Get-View
# Find the NIC
foreach($tempdev in $vm.Config.Hardware.Device){
if($tempdev.DeviceInfo.Label -eq $nicName){
$tgtdev = $tempdev
}
}
# Find the dvSwitch & dvPortGroup
$esx = Get-View -Id $vm.Runtime.Host
foreach($netMoRef in $esx.Network){
if($netMoRef.Type -eq "DistributedVirtualPortGroup"){
$net = Get-View -Id $netMoRef
if($net.Name -eq $dvPgName){
$dvPgKey = $net.MoRef.Value
$dvSwitchUuid = (Get-View -Id $net.Config.DistributedVirtualSwitch).Summary.Uuid
}
}
}
# Prepare Spec
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec
$devChange.operation = "edit"
$dev = New-Object ("VMware.Vim." + $tgtdev.GetType().Name)
$dev.deviceInfo = New-Object VMware.Vim.Description
$dev.deviceInfo.label = $tgtdev.DeviceInfo.Label
$dev.deviceInfo.summary = $tgtdev.DeviceInfo.Summary
$dev.Backing = New-Object VMware.Vim.VirtualEthernetCardDistributedVirtualPortBackingInfo
$dev.Backing.Port = New-Object VMware.Vim.DistributedVirtualSwitchPortConnection
$dev.Backing.Port.PortgroupKey = $dvPgKey
$dev.Backing.Port.SwitchUuid = $dvSwitchUuid
$dev.Key = $tgtdev.Key
$devChange.Device = $dev
$spec.deviceChange = $devChange
$taskMoRef = $vm.ReconfigVM_Task($spec)
$task = Get-View $taskMoRef
while("running","queued" -contains $task.Info.State){
$task.UpdateViewData("Info")
}
}
$vmName = "PC2"
$nicName = "Network adapter 1"
$dvPortgroupName = "dvPg1"
Set-VM2dvPortgroup $vmName $nicName $dvPortgroupNam
Annotations:
Line 30: the Device property in the VirtualDeviceConfigSpec object needs to have an object of a type that corresponds with the network card type you are trying to move to the dvPortgroup.
Line 43: Since this requires the ReconfigVM_Task method, which is executed on a VirtualMachine object, you can only migrate one guest per call. You can migrate multiple NICs of the guest in one call to ReconfigVM_Task. To do this you will have to create an array of VirtualDeviceConfigSpec objects. Each array element corresponding with 1 NIC.
Note that this function already appeared in a slightly different format on Arne’s blog. See the PowerCLI: Set-dvSwitch entry.
Schematically we now have something like this.
This concludes Part2 of the dvSwitch series.









@LucD
Wow… are you from this planet ? Thanks !!
Hi Luc…
I’ve been trying to get some experience with PowerShell\PowerCLI and your posts helped me a lot… thank you !
I was just wondering if it would be possible to add some other properties to your New-dvSwPortgroup function, specifically… I am looking to change the default value “Mac Address Change : Accept” to Reject…
Thanks in advance,
Pablo.
Hi Pablo, the script has been updated.
It now has support for the security policy and for the teaming policy.
14 new parameters available !
Hi Luc,
Nice script you make. I am trying to refine your script to change to connect a vm to a dvportgroup.
I have a NIC with a static mac address, but when I use the script it changes to a dynamic address.
I found VMware.Vim.VirtualDeviceConnectInfo but I cannot get it to work.
can you get me started?
Gert
Thanks Gert.
As it happens I’m nearly done with the creation of 2 new dvSwitch related functions that will offer the Get-NetworkAdapter and Set-NetworkAdapter functionality for dvSwitch based portgroups.
Gert,
The two functions I mentioned earlier are now posted in dvSwitch scripting – Part 8 – Get and Set network adapters. Have a look if this is what you meant.
Luc.
Hi,
Maybe you can help me..
I am looking for a way to check if a dvp with a certain VLAN exists. Do you have any idea how to do this?
I am creating a sort of class setup with for each workspot a seperate vlan, connected on a distributed portgroup
thanks in advance.
greetings.
Gert.
Hi Gert,
Yes that’s possible.
I’ll get back to you with a script to do that. Might even do a new post on it.
Gert, you can find a script to do this in dvSwitch scripting – Part 7 – Find portgroup/Change VLAN Id.
Luc.
Wow, Luc you are a genius! This and part 1 was exactly what I needed, didn’t have to modify anything!
One thing though, I have a requirement to create VMkernel ports for VMotion on the dvSwitches… do you have any idea how I can do that? or do i just need to wait a bit longer for part 3?
Keep up the great work!
Thanks Mark.
The next part should be published in the coming days.