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 | %{
			if(!$pgH.ContainsKey($_)){
				$pgH[$_] = "", @(), 0, @{}
			}
		}
		$vsH[$_.Key] = $_.Name, $pgH
	}

# Get portgroups
	$esx.Config.Network.Portgroup | %{
		$pgHash = $vsH[$_.Vswitch][1]
		$esxTab = $pgHash[$_.Key][1]
		$esxTab += $esx.Name
		$puH = @{}
		if($_.Port){
			$_.Port | %{
				$puH[$_.Key] = "poweredon", $_.Type, $_.Mac
			}
			$pgHash[$_.Key] = $_.Spec.Name, $esxTab, $_.Port.Count, $puH
		}
		else{
			$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
		if($_.Value[2]){
			$foCol = "green"
		}
		else{
			$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
		}
		Write-Host
	}
}

Annotations

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 !

16 thoughts on “Find unused portgroups in a cluster

  1. Pingback: Get-Scripting Podcast Episode 18 – (Thorbjörn Sjövold – Specops) | CrypticZero

  2. Luc,
    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.

  3. Luc,

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

    • @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.

  4. Pingback: Top 5 Planet V12n blog posts week 16 | Download VDI Solutions

  5. 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.

  6. 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

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

  7. Would be nice if this can work with Virtulization EcoShell :)

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

  8. Hello,
    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

  9. Pingback: Top 5 Planet V12n blog posts week 16 | VMvisor

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>