3

I need to script up some things in PowerCLI (VMWare's bolt on to PowerShell). Basically we have a server cluster with three hosts. Each host has multiple virtual switches. Each virtual switch has multiple vlans ('port groups' in VMWare speak). I need to audit the fact that the same port groups exist on each host (so things keep working if the VM is moved).

Step 1 to achieving this is would be to know that the port group name exists on each of the three host machines.

I'm falling over with how to filter some objects out of all the ones returned by a cmdlet, based on number of results returned from a property of those objects. I then need to perform further operations with original object type that passes the filter test to go on down the pipeline.

To give some specifics, this an example showing 'Some PortGroup Name' and the three hosts it exists on (and as a bonus, the vSwitch):

Get-VirtualPortGroup -Name 'Some PortGroup Name' |
    Select-Object Name, VMHostID, VirtualSwitchId

produces the output

Name                VMHostId              VirtualSwitchId
----                --------              ---------------
Some PortGroup Name HostSystem-host-29459 key-vim.host.VirtualSwitch-vSwitch6
Some PortGroup Name HostSystem-host-29463 key-vim.host.VirtualSwitch-vSwitch6
Some PortGroup Name HostSystem-host-29471 key-vim.host.VirtualSwitch-vSwitch6

Instead of 3, I'm starting with the 1849 port group names that are being returned by Get-VirtualPortGroup. I need a pipeline to whittle the number of VirtualPortGroup objects down to a collection consisting of only those objects where a count of the 'VMHostId' property is less than 3, and pass the remaining VirtualPortGroup objects down the pipeline for further processing.

This seems simple enough to do. I'm still failing though.

The following almost works. Piping it to measure shows a count of 229, instead of the original 1849 (so it's definitely filtered a lot out, and is possibly correctly returning the subset I'm after...?). The problem is, the object type is now a 'Group' or something at this point in the pipeline, and doesn't have all the properties and methods of the original Get-VirtualPortGroup objects.

Get-VirtualPortGroup |
    Group-Object -Property Name |
    Where-Object $_.Count -lt 3

Bolting a | Select-Object -ExpandProperty Group to the end of the above seemed promising, except it then seems to return the entire collection of Get-VirtualPortGroup objects as though I had done no filtering in there at all....

Am I doing something fundamentally wrong?

How can I filter out objects based on the count of the number of results returned by a specific property of an object, but still pass the original object type down the pipe?

2
  • Why do you need more than Get-VirtualPortGroup -Standard | Group-Object -Property Name | Where-Object { $_.Count -lt 3 }. The Group property of the resulting object probably has all the info you need including Host ID etc? Commented Oct 23, 2018 at 10:30
  • I see where you are coming from, but I can't end with just the group object count (helpful though that is as a summary). The reason is that I wanted to have the actual portgroup objects (that passed the filter), getting passed down the pipeline so I could then use the script find which hosts they are/aren't on and to synchronise settings from other hosts etc. Commented Oct 23, 2018 at 21:53

1 Answer 1

3

Your approach is correct, but you got the Where-Object syntax wrong. The abbreviated syntax is:

Where-Object <property> <op> <value>

without the current object variable ($_). In your case that would be:

Where-Object Count -lt 3

Otherwise you must use scriptblock notation:

Where-Object { $_.Count -lt 3 }

This should do what you want:

Get-VirtualPortGroup |
    Group-Object -Property Name |
    Where-Object { $_.Count -lt 3 } |
    Select-Object -Expand Group
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that's impressively obvious after a nights sleep and having someone point it out for you, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.