Home > portgroup, PowerCLI, PowerShell, SDK, vSphere > Find unused portgroups in a cluster

Find unused portgroups in a cluster

Triggered by a recent post, see get-virtualportgroup, in the PowerCLI Community, I had a closer look at the Get-VirtualPortgroup cmdlet.

This cmdlet returns a VMware.VimAutomation.Types.Host.VirtualPortGroup object, which contains a very useful property called Ports. In that property it lists all the guests that are connected to a port on the portgroup. That would be the solution to find unused portgroups, I thought. But while the vSphere Client also shows powered off guests that are connected, the Port property returned by the Get-VirtualPortgroup cmdlet doesn’t. 🙁

So the question at hand required a bit more scripting than I originally thought.

The algortihm

The HostNetworkInfo object contains all the required information about vSwitches and portgroups.

To make it easier to link all the vSwitches, portgroups and used ports together I decided to go for PowerShell’s hash tables. This is a schematic view of the nested hash tables used in the script.

The script loops over all the ESX/ESXi hosts that belong to the cluster.

It populates the hash tables with the vSwitches, portgroups and ports it can find in the HostNetworkInfo object.

It loops through all the powered off guests on the hosts and find for each network card to which portgroup it is connected.

Finally the scripts displays the data it has captured in the hash tables on screen.

The script

$clusterName = "MyCluster"

$vsH = @{}
Get-View -ViewType HostSystem -SearchRoot (Get-Cluster -Name $clusterName | Get-View).MoRef | %{
	$esx = $_

# Get vswitches
	$esx.Config.Network.Vswitch | %{
		if($vsH.ContainsKey($_.Key)){$pgH = $vsH[$_.Key][1]}
		else{$pgH = @{}}
		$_.Portgroup | %{
				$pgH[$_] = "", @(), 0, @{}
		$vsH[$_.Key] = $_.Name, $pgH

# Get portgroups
	$esx.Config.Network.Portgroup | %{
		$pgHash = $vsH[$_.Vswitch][1]
		$esxTab = $pgHash[$_.Key][1]
		$esxTab += $esx.Name
		$puH = @{}
			$_.Port | %{
				$puH[$_.Key] = "poweredon", $_.Type, $_.Mac
			$pgHash[$_.Key] = $_.Spec.Name, $esxTab, $_.Port.Count, $puH
			$pgHash[$_.Key] = $_.Spec.Name, $esxTab, 0, @{}

		$vsH[$_.Vswitch][1] = $pgHash

# Get poweredoff VMs on host, find their NICs and increment counter
	$esx.Vm | %{Get-View -Id $_} | where {$_.Runtime.PowerState -eq ([VMware.Vim.VirtualMachinePowerState]"poweredOff")} | %{
		$vm = $_
		$vm.Config.Hardware.Device | where {$_.DeviceInfo.Label -like "Network*"} | %{
			$nic = $_
			$esx.Config.Network.Portgroup | where {$_.Spec.Name -eq $nic.Backing.DeviceName} | %{
				$vSw = $vsH[$_.Vswitch]
				$pg = $vSw[1][$_.Key]
				$pg[2] += 1
				$pg[3][$vm.Name + "/" + $nic.Key] = "poweredOff", "virtualMachine", $nic.MacAddress
				$vSw[1][$_.Key] = $pg
				$vsH[$_.Vswitch] = $vSw

# Display results on console
$vsH.GetEnumerator() | %{
	Write-Host $_.Value[0]
	$_.Value[1].GetEnumerator() | %{
		Write-Host "`t" $_.Value[0] -NoNewline
			$foCol = "green"
			$foCol = "red"
		Write-Host -ForegroundColor $foCol " Ports:" $_.Value[2]
		Write-Host "`tUsed on:"
		$_.Value[1] | %{
			Write-Host "`t " $_
		Write-Host "`tPorts"
		$_.Value[3].GetEnumerator() | %{
			Write-Host "`t" $_.Value


Line 1: Specify the name of the cluster you want check for unused portgroups in variable $clusterName

Line 4: Loop over all the nodes for the requested cluster.

Line 8-17: Loop through all the vSwitches on the host and populate the $vsH hash table

Line 12-14: If there is a portgroup defined on this vSwitch that is not yet in the $pgH hash table, add it.

Line 19-36: Loop through all the portgroups on the host and add the data to the hash tables

Line 22-23: The $pgH hash table contains an array with hostnames of all the nodes where the portgroup is found.

Line 26-28: Inject the information from the Port property into the $puH hash table.

Line 39-53: Enter the information from the network cards for all powered off guests into the hash tables.

Line 46: Increment the counter of the used ports for a powered off guest.

Line 56-77: Display the results on screen.

Sample output

The following screenshot is from a run of the script on a 2-node cluster.

The report shows clearly that there is a portgroup, called PG77, on node esx4.test.local which has 0 ports in use.

This looks clearly like an unused portgroup and would require further investigation !

  1. TJ
    September 15th, 2015 at 16:22 | #1

    Hi Luc,
    Wondering if there had been updates to this script to work with VDS and vSphere 5.5? This is exactly what I’m looking for in order to complete some tasks. Would appreciate any insight!

  2. Jim
    September 25th, 2014 at 17:31 | #2

    I’m going to hazard a guess that you never determined why it didn’t work for vSphere 5.0+? Running into the same issue.

  3. Ken
    November 1st, 2012 at 22:17 | #3

    This script does not seem to function properly on ESX 5.0. Are there changes that need to be made for the newer ESX versions? It’s not accurately displaying the VMs connected to my portgroups so most of them appear unused.

  4. Jordan
    May 23rd, 2012 at 21:39 | #4


    I know this an old post, but what about Distributed Switches? They don’t seem to have to Ports property…

    • May 23rd, 2012 at 22:39 | #5

      Hi Jordan, yes, you are correct, that Ports property doesn’t exist for portgroups on dvSwitches.
      It should be possible to do this though, have a look at my dvSwitch scripting – Part 12 – Find free ports post, where I find the first free ports on a dvSwitch portgroup.
      I’ll see if I can come up with something.

  5. Sven
    November 5th, 2010 at 10:28 | #6

    Hello Luc,

    You may find time to work on the script?

    best regards, Sven

    • November 5th, 2010 at 11:32 | #7

      @Sven. I’m currently in the final days of writing for our upcoming book.
      Once that is done I will tackle all the open questions and requests.
      Sorry to keep you waiting.

  6. Yev Berman
    October 18th, 2010 at 10:48 | #8

    Fine, I’ll wait for it.

  7. Yev Berman
    October 14th, 2010 at 12:58 | #9

    Hey Luc,
    I haven’t seen any script that can generate a list of VLANs on dvSwitch,
    have you know some script that can do such a thing?
    Best regards,
    Yev Berman.

    • October 14th, 2010 at 13:33 | #10

      There is indeed no such function (yet).
      I’ll have a look when I’m back home from VMworld

  8. uxmax
    June 28th, 2010 at 18:10 | #11

    Hello Luc,

    is there a way to modify the script to actually show

    – used ports or how much ports left (default switch 24 or 56) per host or cluster
    (for example i opened a case last week regarding disconnected machines after updating our esx hosts to U2. Reason/Problem: all ports were in use and therefor a few guests got disconnected from network/vSwitch)

    Thanks Luc

    • June 28th, 2010 at 22:21 | #12

      That should be possible. But first I’m going to try to fix the problem with zero counters that was reported earlier.

  9. Pcli
    June 22nd, 2010 at 07:13 | #13

    Would be nice if this can work with Virtulization EcoShell 🙂

    Output displays as part of the message window and not on the result windows

  10. Sven
    June 4th, 2010 at 09:40 | #14

    After changing the cluster name on top of the script i run the script. It show’s me on several networks “Ports: 0” but there are 6 VM’s connected.
    The values for “used on: “ are correct.
    Best regards, Sven

  11. Suresh
    April 22nd, 2010 at 23:33 | #15

    Very useful script. Thanks Luc.

  1. April 25th, 2010 at 23:07 | #1
  2. October 25th, 2010 at 20:41 | #2
  3. May 8th, 2014 at 10:46 | #3