Script: Determining Virtual Switch Type Under Hyper-V

Script: Determining Virtual Switch Type Under Hyper-V

  • Comments 3

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

Leave a Comment
  • Please add 4 and 5 and type the answer here:
  • Post
  • Hello Friends,

    It's very useful power shell script form multiple NICs. But I required IP address and vlan id respective All NICs card.

    Thanks & Regards

    RKB

  • Hi Ben , Thanks for these helpful articles,

    Can you tell me in windows server 2012 hyper-v how to map a Physical NIC(pnic) to a virtual NIC(vnic) , is there any way or powershell commands to find this?

  • I would love to see this script updated for Windows Server 2012 R2 and root\virtualization\v2, since some of the WMI classes and relationships have changed.

Page 1 of 1 (3 items)