How many VMs in each LAN?

A nice challenge today, when trying to answer a question in the VMware VI Toolkit community:

How to get an overview of all my networks and the number of VMs connected to each of them?

It’s unfortunately not possible to get VMs, based on which port group they are connected to. So something like this will NOT work: Get-VirtualPortGroup | Get-VM. Let’s try to do it the other way around: Get all the VMs we have. Get the portgroups they are connected to. And then figure out a way to invert the table.

First step: Getting the VMs and their port groups:

$VMs = Get-VM | Select Name, @{N=”PortGroups”;E={Get-VirtualPortGroup -VM $_ | %{$_.Name}}}

OK. That wasn’t too bad. The old Get-VM doing it’s job there. And the Get-VirtualPortGroup can return all port groups for each vm. We are only interested in the name of each port group, though. Using Calculated Properties we can stuff it into a single line.

Now to turn this table around. Piping to Group-Object does not quite deliver the desired result. That’s because some VMs have multiple port groups assigned. Group-Object then groups by each unique combination of port groups instead of per unique port group. Bummer. Let’s just try to list all unique port groups first then:

$PGs = $VMs | %{$_.PortGroups} | Select -Unique

Hey, that’s pretty simple. Now a small script can build a new collection of objects representing port groups for us. And we can definitely calculate how many vms there are associated to each port group, by using the $VMs collection we created earlier!

$myCol = @()
ForEach ($PG in $PGs)
  $myObj = “” | Select PGName, NumVMs
  $myObj.PGName = $PG
  $myObj.NumVMs = ($VMs | Where {$_.PortGroups -contains $PG} | Measure-Object).Count
  $myCol += $myObj

That ought to do the job. Let’s give it a nice, orderly view and we’re good to go!

$myCol | Sort NumVMs -Descending | Format-Table -AutoSize

Mystery solved!