As technology moves forward, more and more ways to achieve your goal become available. Many people still rely on the good old trusty GUI to achieve their goal, I know I do at times. Is this because it’s quicker, more comfortable or familiar? Or perhaps because they don’t realise there are other options out there!?
This blog post will be one of many, where I highlight some of the options available for completing various technical tasks or configurations, in the hope it can provide additional options or tools for consideration.
To kick off, let’s take a look at a common example for a vSphere Administrator, creating Port Groups on a Distributed Switch.
vSphere Client
So let’s first look at the process via the GUI, in this case, the vSphere Client. I wont go into too much detail on the steps involved, as it is a well documented process, but the screenshots are below:
Repeat for the remaining Port Groups and you will be left with the finished article.
And there we have it, three Port Groups on a distributed Switch. Now, imagine doing this for 10’s or 100’s of Port Groups? It’s going to be slow and painful, so let’s look at some other options.
PowerShell
Firstly, PowerShell, specifically the VMware PowerCLI PowerShell module. Here is an example script that will create the same three Port Groups that we did using the GUI:
1$vDSName = "vDS-Workload-Networks"
2$Ports = "8"
3$LoadBalancing = "LoadBalanceLoadBased"
4$ActiveUP = "Uplink 1", "Uplink 2"
5
6$vdpgs = @(
7 [pscustomobject]@{PG = 'dvPG-Guest-VM-1'; VLANID = '20'}
8 [pscustomobject]@{PG = 'dvPG-Guest-VM-2'; VLANID = '21'}
9 [pscustomobject]@{PG = 'dvPG-Secure-VM-1'; VLANID = '25'}
10)
11
12#Create Distributed Virtual Port Group.
13ForEach ($vdpg in $vdpgs) {
14 Get-VDSwitch -Name $vDSName | New-VDPortGroup -Name $VDPG.PG -VLanId $VDPG.VLANID -NumPorts $Ports
15 #Set Load Balancing option
16 Get-VDswitch -Name $vDSName | Get-VDPortgroup $VDPG.PG | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -LoadBalancingPolicy $LoadBalancing -ActiveUplinkPort $ActiveUP
17}
So lets break down this code. Firstly we are defining some variables;
$vDSName
- This is the name of an existing virtual distributed switch in which you will be creating your Port Groups.$Ports
- This defines the number of ports the Port Group will be initially configured with. (By default 128 ports are created, there is nothing wrong with using the default, see the note further down as to why I have specified 8.)$LoadBalancing
- This is the load balancing policy I wish to set for the Port Group. Available options are:LoadBalanceLoadBased, LoadBalanceIP, LoadBalanceSrcMac, LoadBalanceSrcId, ExplicitFailover. This can be adjusted as required.$ActiveUP
- This variable defines the uplinks you wish to set as active for the Port Group. (If you want to add standby uplinks, you could add this parameter in too)$VDPGS
- Finally, this is an array containing both the name and VLAN ID for each Port Group.
Now we have our input information in variables, we move onto the next two lines of code. These are within a ‘ForEach Loop’. This will take each entry within an array and run a block of code against it. In this case, each Port Group we wish to create.
So for each entry in the array, Get-VDswitch -Name $vDSName
gets the existing Virtual Distributed Switch based on the variable and then pipes (’|’) this into the command New-VDPortGroup -Name $VDPG.PG -VLanId $VDPG.VLANID -NumPorts $Ports
to create the Port Group on the Distributed Switch, using the properties set for each line of the array.
Secondly, we get the Port Group we just created Get-VDswitch -Name $vDSName | Get-VDPortgroup $VDPG.PG
and then ‘Get & Set’ the Teaming and Loadbalancing options Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -LoadBalancingPolicy $LoadBalancing -ActiveUplinkPort $ActiveUP
, again ‘piping’ the results into the next command.
Below is the output from PowerShell after running the script above:
1Name NumPorts PortBinding
2---- -------- -----------
3dvPG-Guest-VM-1 8 Static
4
5VDPortgroup : dvPG-Guest-VM-1
6NotifySwitches : True
7NotifySwitchesInherited : True
8LoadBalancingPolicy : LoadBalanceLoadBased
9LoadBalancingPolicyInherited : False
10FailoverDetectionPolicy : LinkStatus
11ActiveUplinkPort : {Uplink 1, Uplink 2}
12StandbyUplinkPort : {}
13UplinkPortOrderInherited : False
14Failback : False
15EnableFailback : True
16FailbackInherited : True
17UnusedUplinkPort : {}
18FailoverDetectionPolicyInherited : True
19Uid : /VIServer=vsphere.local\administrator@vm-vcsa-01.smt-lab.local:443/VDPortgroupUplinkTeamingPolicy=cec49f0b7f124d0c9f37814392494a31/
20
21dvPG-Guest-VM-2 8 Static
22
23VDPortgroup : dvPG-Guest-VM-2
24NotifySwitches : True
25NotifySwitchesInherited : True
26LoadBalancingPolicy : LoadBalanceLoadBased
27LoadBalancingPolicyInherited : False
28FailoverDetectionPolicy : LinkStatus
29ActiveUplinkPort : {Uplink 1, Uplink 2}
30StandbyUplinkPort : {}
31UplinkPortOrderInherited : False
32Failback : False
33EnableFailback : True
34FailbackInherited : True
35UnusedUplinkPort : {}
36FailoverDetectionPolicyInherited : True
37Uid : /VIServer=vsphere.local\administrator@vm-vcsa-01.smt-lab.local:443/VDPortgroupUplinkTeamingPolicy=e126093ed67f45a3b7c42874c5affc20/
38
39dvPG-Secure-VM-1 8 Static
40
41VDPortgroup : dvPG-Secure-VM-1
42NotifySwitches : True
43NotifySwitchesInherited : True
44LoadBalancingPolicy : LoadBalanceLoadBased
45LoadBalancingPolicyInherited : False
46FailoverDetectionPolicy : LinkStatus
47ActiveUplinkPort : {Uplink 1, Uplink 2}
48StandbyUplinkPort : {}
49UplinkPortOrderInherited : False
50Failback : False
51EnableFailback : True
52FailbackInherited : True
53UnusedUplinkPort : {}
54FailoverDetectionPolicyInherited : True
55Uid : /VIServer=vsphere.local\administrator@vm-vcsa-01.smt-lab.local:443/VDPortgroupUplinkTeamingPolicy=b5f1889461584b1daf314379cd935f50/
Terraform
Now let’s take a look at using Terraform to achieve the same result. Terraform is an infrastructure and code tool used to manage infrastructure in the form of configuration files and state:
1provider "vsphere" {
2 vsphere_server = "vCenter Server FQDN"
3 user = "Domain\\Username"
4 password = "Password"
5}
6data "vsphere_datacenter" "datacenter" {
7 name = "dc-smt-01"
8}
9data "vsphere_distributed_virtual_switch" "vds" {
10 name = "vDS-Workload-Networks"
11 datacenter_id = data.vsphere_datacenter.datacenter.id
12}
13resource "vsphere_distributed_port_group" "pg20" {
14 name = "dvPG-Guest-VM-1"
15 distributed_virtual_switch_uuid = data.vsphere_distributed_virtual_switch.vds.id
16 number_of_ports = 8
17 vlan_id = 20
18}
19resource "vsphere_distributed_port_group" "pg21" {
20 name = "dvPG-Guest-VM-2"
21 distributed_virtual_switch_uuid = data.vsphere_distributed_virtual_switch.vds.id
22 number_of_ports = 8
23 vlan_id = 21
24}
25resource "vsphere_distributed_port_group" "pg25" {
26 name = "dvPG-Secure-VM-1"
27 distributed_virtual_switch_uuid = data.vsphere_distributed_virtual_switch.vds.id
28 number_of_ports = 8
29 vlan_id = 25
30}
Lets break this down.
First we are specifying which terraform provider we want to use, this will be the vSphere provider in this case. We are then providing some parameters for Terraform to connect to your vCenter instance; VCSA FQDN and credentials.
We then have two ‘data’ blocks. These are used to get information about an existing resource, such as the Distributed Switch and the Datacenter it resides in. You could loosely consider this similar to populating variables in the PowerShell example.
Next we have three ‘resource’ blocks. Each block represents one of the three Port Groups we want to configure. It provides parameters for Name, number of ports and vlan ID for each, along with a reference to the Distributed Switch from the ‘data’ block.
Now when you run ’terraform apply’ to apply for code, here is the output:
1terraform apply
2
3Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
4 + create
5
6Terraform will perform the following actions:
7
8 # vsphere_distributed_port_group.pg20 will be created
9 + resource "vsphere_distributed_port_group" "pg20" {
10 + active_uplinks = (known after apply)
11 + allow_forged_transmits = (known after apply)
12 + allow_mac_changes = (known after apply)
13 + allow_promiscuous = (known after apply)
14 + auto_expand = true
15 + block_all_ports = (known after apply)
16 + check_beacon = (known after apply)
17 + config_version = (known after apply)
18 + directpath_gen2_allowed = (known after apply)
19 + distributed_virtual_switch_uuid = "50 33 5e 01 05 1e 32 66-ea f7 7c 42 ce fa f1 96"
20 + egress_shaping_average_bandwidth = (known after apply)
21 + egress_shaping_burst_size = (known after apply)
22 + egress_shaping_enabled = (known after apply)
23 + egress_shaping_peak_bandwidth = (known after apply)
24 + failback = (known after apply)
25 + id = (known after apply)
26 + ingress_shaping_average_bandwidth = (known after apply)
27 + ingress_shaping_burst_size = (known after apply)
28 + ingress_shaping_enabled = (known after apply)
29 + ingress_shaping_peak_bandwidth = (known after apply)
30 + key = (known after apply)
31 + lacp_enabled = (known after apply)
32 + lacp_mode = (known after apply)
33 + name = "dvPG-Guest-VM-1"
34 + netflow_enabled = (known after apply)
35 + network_resource_pool_key = "-1"
36 + notify_switches = (known after apply)
37 + number_of_ports = 8
38 + port_private_secondary_vlan_id = (known after apply)
39 + standby_uplinks = (known after apply)
40 + teaming_policy = (known after apply)
41 + tx_uplink = (known after apply)
42 + type = "earlyBinding"
43 + vlan_id = 20
44
45 + vlan_range {
46 + max_vlan = (known after apply)
47 + min_vlan = (known after apply)
48 }
49 }
50
51 # vsphere_distributed_port_group.pg21 will be created
52 + resource "vsphere_distributed_port_group" "pg21" {
53 + active_uplinks = (known after apply)
54 + allow_forged_transmits = (known after apply)
55 + allow_mac_changes = (known after apply)
56 + allow_promiscuous = (known after apply)
57 + auto_expand = true
58 + block_all_ports = (known after apply)
59 + check_beacon = (known after apply)
60 + config_version = (known after apply)
61 + directpath_gen2_allowed = (known after apply)
62 + distributed_virtual_switch_uuid = "50 33 5e 01 05 1e 32 66-ea f7 7c 42 ce fa f1 96"
63 + egress_shaping_average_bandwidth = (known after apply)
64 + egress_shaping_burst_size = (known after apply)
65 + egress_shaping_enabled = (known after apply)
66 + egress_shaping_peak_bandwidth = (known after apply)
67 + failback = (known after apply)
68 + id = (known after apply)
69 + ingress_shaping_average_bandwidth = (known after apply)
70 + ingress_shaping_burst_size = (known after apply)
71 + ingress_shaping_enabled = (known after apply)
72 + ingress_shaping_peak_bandwidth = (known after apply)
73 + key = (known after apply)
74 + lacp_enabled = (known after apply)
75 + lacp_mode = (known after apply)
76 + name = "dvPG-Guest-VM-2"
77 + netflow_enabled = (known after apply)
78 + network_resource_pool_key = "-1"
79 + notify_switches = (known after apply)
80 + number_of_ports = 8
81 + port_private_secondary_vlan_id = (known after apply)
82 + standby_uplinks = (known after apply)
83 + teaming_policy = (known after apply)
84 + tx_uplink = (known after apply)
85 + type = "earlyBinding"
86 + vlan_id = 21
87
88 + vlan_range {
89 + max_vlan = (known after apply)
90 + min_vlan = (known after apply)
91 }
92 }
93
94 # vsphere_distributed_port_group.pg25 will be created
95 + resource "vsphere_distributed_port_group" "pg25" {
96 + active_uplinks = (known after apply)
97 + allow_forged_transmits = (known after apply)
98 + allow_mac_changes = (known after apply)
99 + allow_promiscuous = (known after apply)
100 + auto_expand = true
101 + block_all_ports = (known after apply)
102 + check_beacon = (known after apply)
103 + config_version = (known after apply)
104 + directpath_gen2_allowed = (known after apply)
105 + distributed_virtual_switch_uuid = "50 33 5e 01 05 1e 32 66-ea f7 7c 42 ce fa f1 96"
106 + egress_shaping_average_bandwidth = (known after apply)
107 + egress_shaping_burst_size = (known after apply)
108 + egress_shaping_enabled = (known after apply)
109 + egress_shaping_peak_bandwidth = (known after apply)
110 + failback = (known after apply)
111 + id = (known after apply)
112 + ingress_shaping_average_bandwidth = (known after apply)
113 + ingress_shaping_burst_size = (known after apply)
114 + ingress_shaping_enabled = (known after apply)
115 + ingress_shaping_peak_bandwidth = (known after apply)
116 + key = (known after apply)
117 + lacp_enabled = (known after apply)
118 + lacp_mode = (known after apply)
119 + name = "dvPG-Secure-VM-1"
120 + netflow_enabled = (known after apply)
121 + network_resource_pool_key = "-1"
122 + notify_switches = (known after apply)
123 + number_of_ports = 8
124 + port_private_secondary_vlan_id = (known after apply)
125 + standby_uplinks = (known after apply)
126 + teaming_policy = (known after apply)
127 + tx_uplink = (known after apply)
128 + type = "earlyBinding"
129 + vlan_id = 25
130
131 + vlan_range {
132 + max_vlan = (known after apply)
133 + min_vlan = (known after apply)
134 }
135 }
136
137Plan: 3 to add, 0 to change, 0 to destroy.
138
139Do you want to perform these actions?
140 Terraform will perform the actions described above.
141 Only 'yes' will be accepted to approve.
142
143 Enter a value: yes
144
145vsphere_distributed_port_group.pg20: Creating...
146vsphere_distributed_port_group.pg21: Creating...
147vsphere_distributed_port_group.pg25: Creating...
148vsphere_distributed_port_group.pg25: Creation complete after 0s [id=dvportgroup-2669728]
149vsphere_distributed_port_group.pg21: Creation complete after 0s [id=dvportgroup-2669730]
150vsphere_distributed_port_group.pg20: Creation complete after 0s [id=dvportgroup-2669729]
151
152Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
For more information on the vSphere provider from Terraform, check out this link.
You will have noticed that I have explicitly defined the number of ports in both the PowerShell and Terraform examples. This is purely to match up with the default value that is set when using the vSphere Client; 8. By default the port allocation automatically expands as required, so this is for consistency rather than anything else.
If you are someone who relies heavily on a GUI as part of your work, I hope this have given you some idea’s on how you can perhaps leverage other options, especially when looking to build or configure in bulk.
Thanks for reading!