Hyper-V How To: Modify VLAN Settings using Script

Some friends here on the Hyper-V team shared a PowerShell 2.0 script for modifying hte VLAN settings on your VMs:

# Modify VLAN setting for VM

param(
$vmName = $(throw "Must supply a virtual machine name"),
$vlanId = $(throw "Must supply vlan id"),
$computer = "."
)

$ns = "root\virtualization"

# get the computer system
$vm = gwmi -namespace $ns -computerName $computer Msvm_ComputerSystem -filter "ElementName = '$vmName'"

if ($vm -eq $null)
{
"No virtual machine with name '$vmName'"
return
}

# get its related vssd
$vssd = gwmi -namespace $ns -computerName $computer -query "associators of {$vm} where AssocClass=Msvm_SettingsDefineState"

# get its synthetic and enumlated NICs
$nics = gwmi -namespace $ns -computerName $computer -query "associators of {$vssd} where AssocClass=Msvm_VirtualSystemSettingDataComponent" |
where {$_.ResourceType -eq 10 -and ($_.ResourceSubType -eq 'Microsoft Synthetic Ethernet Port' -or
$_.ResourceSubType -eq 'Microsoft Emulated Ethernet Port')}

if ($nics -eq $null)
{
# vm does not have any NICs.
"Virtual machine '$vmName' does not have any NICs"
return
}
 

# Find the first nic which has a connection
$nic = $nics | where {$_.Connection -ne $null} | select-object -first 1

if ($nic -eq $null)
{
"None of the NICs on virtual machine '$vmName' are connected"
return
}

# get the connected switch port.
$connectedPort = [wmi]$nic.Connection[0]

# need to set the external trunk list of the external port on this same switch
# to include this vlan id, else traffic won't get through.

# first get its switch.
$switch = gwmi -namespace $ns -computerName $computer -query "associators of {$connectedPort} where AssocClass=Msvm_HostedAccessPoint"

# enumerate all of its ports. First the port which is externally connected.
$ports = gwmi -namespace $ns -computerName $computer -query "associators of {$switch} where ResultClass=Msvm_SwitchPort"
$externalPort = $null

foreach ($p in $ports)
{
$switchLanEndpoint = gwmi -namespace $ns -computerName $computer -query "associators of {$p} where ResultClass=Msvm_SwitchLanEndpoint"
if ($switchLanEndpoint -ne $null)
{
$externalEthernetPort = gwmi -namespace $ns -computerName $computer -query "associators of {$switchLanEndpoint} where resultclass=Msvm_ExternalEthernetPort"
if ($externalEthernetPort -ne $null)
{
# we got it, we found the switch port connected to the external
# port, save it and break out of the loop.
$externalPort = $p
break
}
}
}

if ($externalPort -ne $null)
{
# get the port's VlanEndpoint
$vlan = gwmi -namespace $ns -computerName $computer -query "associators of {$externalPort} where AssocClass=Msvm_BindsTo"
# get the vlan's setting object
$vlanSetting = gwmi -namespace $ns -computerName $computer -query "associators of {$vlan} where AssocClass=Msvm_NetworkElementSettingData"

     # get the current trunk list and add the new vlan id into it.
# one thing additionally we could do here, which the Hyper-V UI does is clean up
# the old AccessVlan id of the port from the trunk list. But, we can't just remove the
# old AccessVlan from the trunklist, because another port might be using the same vlan id.
# We would have to enumerate all of the ports on the switch and build a new trunk list.
# For the purposes of this script, don't worry about cleaning up old vlan id' from the trunk list.
$trunkList = $vlanSetting.TrunkedVLANList
if ($trunkList -notcontains $vlanid)
{
$trunkList = $trunkList + $vlanId
$vlanSetting.TrunkedVLANList = $trunkList
$result = $vlanSetting.Put()
}
# set the vlan mode into trunking mode.
if ($vlan.DesiredEndpointMode -ne 5)
{
$vlan.DesiredEndpointMode = 5
$result = $vlan.Put()
}
}

# Now that we have finished with the trunklist, set the vlan id of the original connected port.

$vlan = gwmi -namespace $ns -computerName $computer -query "associators of {$connectedPort} where AssocClass=Msvm_BindsTo"
$vlanSetting = gwmi -namespace $ns -computerName $computer -query "associators of {$vlan} where AssocClass=Msvm_NetworkElementSettingData"
$vlanSetting.AccessVlan = $vlanId
$vlanSetting.Put()

For more info on how to use PS cmdlets see: https://www.microsoft.com/technet/scriptcenter/topics/msh/cmdlets/index.mspx

See also James O’Neil’s New and improved PowerShell Library for Hyper-V. Now with more functions and... documentation!

For all 35 sample Hyper-V PS1 scripts in a zipfile, go to: Hyper-V PowerShell Example Scripts.zip-download