Script: Determining Virtual Switch Type Under Hyper-V
When you are scripting against virtual switches – it is good to know what type of switch you are talking to. In order to figure this out you need to find out whether the virtual switch has an internal network connection, external network connection, neither or both. Here are some scripts that will do just that:
VBScript:
option explicit
Dim HyperVServer
Dim WMIService
Dim VirtualSwitches
Dim VirtualSwitch
Dim InternalPortCount
Dim ExternalPortCount
Dim SwitchPorts
Dim SwitchPort
Dim SwitchLANEndPoints
Dim SwitchLANEndPoint
Dim EthernetPort
Dim Output
Dim FullMessage
FullMessage = "The following virtual networks were discovered:" & chr(10)
'Prompt for the Hyper-V Server to use
HyperVServer = InputBox("Specify the Hyper-V Server to create the internal virtual network switch:")
'Get an instance of the WMI Service in the virtualization namespace.
set WMIService = GetObject("winmgmts:\\" & HyperVServer & "\root\virtualization")
'Get the list of all available network switches
Set VirtualSwitches = WMIService.ExecQuery("Select * From Msvm_VirtualSwitch")
for each VirtualSwitch in VirtualSwitches
'Initialize variables for counting number of internal and external ports per switch
InternalPortCount = 0
ExternalPortCount = 0
'Get the switch ports associated with the switch
Set SwitchPorts = VirtualSwitch.Associators_("CIM_HostedAccessPoint", "CIM_SwitchPort")
for each SwitchPort in SwitchPorts
'Get the Msvm_SwitchLANEndpoint associated with the switch port
Set SwitchLANEndpoints = SwitchPort.Associators_("Msvm_ActiveConnection", "Msvm_SwitchLANEndpoint")
for each SwitchLANEndPoint in SwitchLANEndPoints
'Get the CIM_EthernetPort associated with the SwitchLanEndPoint
Set EthernetPort = (SwitchLANEndPoint.Associators_("CIM_DeviceSAPImplementation", "CIM_EthernetPort")).ItemIndex(0)
if EthernetPort.Path_.Class = "Msvm_InternalEthernetPort" then InternalPortCount = InternalPortCount + 1
if EthernetPort.Path_.Class = "Msvm_ExternalEthernetPort" then ExternalPortCount = ExternalPortCount + 1
next
next
Select Case InternalPortCount
Case 0
Select Case ExternalPortCount
Case 0
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is a virtual machine only virtual network."
Case 1
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is an external-only virtual network."
Case Else
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is not a standard virtual network."
End Select
Case 1
Select Case ExternalPortCount
Case 0
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is an internal virtual network."
Case 1
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is an external virtual network."
Case Else
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is not a standard virtual network."
End Select
Case Else
Output = "The virtual switch '" & VirtualSwitch.ElementName & "' is not a standard virtual network."
End Select
FullMessage = FullMessage & chr(10) & Output
next
'Display the complete information about the virtual switches
Wscript.echo FullMessage
PowerShell:
# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
write-host
# Get the list of all available network switches
$query = "Select * From Msvm_VirtualSwitch"
$VirtualSwitches = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer
# Iterate over each virtual switch
foreach ($VirtualSwitch in $VirtualSwitches)
{
# Initialize variables for counting number of internal and external ports per switch
$InternalPortCount = 0
$ExternalPortCount = 0
# Get the Switch ports on the virtual switch
$query = "Associators of {$VirtualSwitch} where ResultClass=CIM_SwitchPort"
$switchPorts = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer
# A VM only switch with no VMs connected will return null
if ($switchPorts -ne $null)
{
# Iterate over each switch port
foreach ($switchPort in @($switchPorts))
{
# Get the Msvm_SwitchLANEndpoint associated with the switch port
$query = "Associators of {$switchPort} where ResultClass=Msvm_SwitchLANEndpoint"
$SwitchLANEndpoint = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer
# If there is no active connection on the switch port the results will be null
if ($SwitchLANEndpoint -ne $null)
{
# Get the CIM_EthernetPort for the Msvm_SwitchLANEndpoint
$query = "Associators of {$SwitchLANEndpoint} where ResultClass=CIM_EthernetPort"
$EthernetPort = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer
# Check to see if the associated Ethernet port is an internal port
if ($EthernetPort.__CLASS -eq "Msvm_InternalEthernetPort")
{
$InternalPortCount = $InternalPortCount + 1
}
# Check to see if the associated Ethernet port is an external port
if ($EthernetPort.__CLASS -eq "Msvm_ExternalEthernetPort")
{
$ExternalPortCount = $ExternalPortCount + 1
}
}
}
}
switch ($InternalPortCount)
{
0
{
switch ($ExternalPortCount)
{
0 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is a virtual machine only virtual network."}
1 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an external-only virtual network."}
default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."}
}
}
1
{
switch ($ExternalPortCount)
{
0 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an internal virtual network."}
1 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an external virtual network."}
default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."}
}
}
default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."}
}
write-host $output
}
write-host
The logic flow for these scripts is as follows:
- Get all virtual switches (Msvm_VirtualSwitch) and then iterate over each switch.
- Follow the CIM_HostedAccessPoint association on the switch to get every CIM_SwitchPort associated with the virtual switch.
- Follow the Msvm_ActiveConnection association on the switch port to get every Msvm_SwitchLANEndpoint associated with each switch port.
- Follow the CIM_DeviceSAPImplementation association on the switch LAN endpoint to get every CIM_EthernetPort associated with each switch LAN endpoint.
- Look at the Ethernet port class (external or internal) and tally the number of internal and external Ethernet ports associated with the switch in question.
- Look at the final tally to figure out the type of the switch.
Some notes to make
- Many of these queries return 0, 1 or many results – which VBScript tends to do a better job of handling than PowerShell. Hence why the VBScript is shorter.
- UPDATE: An MVP pointed out how to make my PowerShell Script shorter – so it has been corrected.
- Switch ports that are connected to virtual machines do not return a Msvm_SwitchLANEndpoint (they return a Msvm_VMSwitchLANEndpoint) so these switch ports are not considered during this code.
- The “Msvm_ActiveConnection” object only exists on switch ports that are connected to internal Ethernet ports, external Ethernet ports or running virtual machines.
- It is possible to have a virtual switch with more than 1 external Ethernet port or more than 1 internal Ethernet port – but the Hyper-V UI will never make one (and such configurations are not tested or recommended).
Cheers,
Ben