Home > PowerCLI, PowerShell, SDK, portgroup, 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 | %{
			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 !

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

    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 | #2

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

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

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

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

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

    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

  4. Suresh
    April 22nd, 2010 at 23:33 | #5

    Very useful script. Thanks Luc.

  1. April 25th, 2010 at 23:07 | #1