VMware Cloud Community
richard612
Enthusiast
Enthusiast
Jump to solution

Another quick question about a LucD inventory scripting technique

I've been working with brilliant nested ForEach loops thanks to LucD‌ :

foreach ($dc in Get-Datacenter) {

        foreach ($cluster in Get-Cluster -Location $dc) {

            foreach ($esx in Get-VMHost -Location $cluster) {

                Get-VM -Location $esx

Walking down the tree is fantastic because this method collects the datacenter and cluster name for each VM as a byproduct of the scripting logic.  Unfortunately we have some VMs that aren't part of a cluster.  Is there a simple way to pick up these outliers?  I think I'd need to compare the output of the above with a simple Get-VM then += the delta to the original output.  But I'm a PowerShell novice and I'm struggling a little.  Has anyone already solved this issue?

Tags (2)
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

You can do something like this.

It stores the name of all the VMs that are in a cluster in an array.

Then it fetches all the VM in the datacenter, but with the Where-clause only the ones that are not in a cluster are passed through.

foreach ($dc in Get-Datacenter) {

    $clusterVM = @()

    foreach ($cluster in Get-Cluster -Location $dc) {

        foreach ($esx in Get-VMHost -Location $cluster) {

            $vm = Get-VM -Location $esx

            $clusterVM += $vm.Name

            # Other code on the VM that is in a cluster

        }

    }

    foreach($vm in (Get-VM -Location $dc | where{$clusterVM -notcontains $_.Name)){

        $vm

        # Code for VM that are not in a cluster

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
5 Replies
LucD
Leadership
Leadership
Jump to solution

You can do something like this.

It stores the name of all the VMs that are in a cluster in an array.

Then it fetches all the VM in the datacenter, but with the Where-clause only the ones that are not in a cluster are passed through.

foreach ($dc in Get-Datacenter) {

    $clusterVM = @()

    foreach ($cluster in Get-Cluster -Location $dc) {

        foreach ($esx in Get-VMHost -Location $cluster) {

            $vm = Get-VM -Location $esx

            $clusterVM += $vm.Name

            # Other code on the VM that is in a cluster

        }

    }

    foreach($vm in (Get-VM -Location $dc | where{$clusterVM -notcontains $_.Name)){

        $vm

        # Code for VM that are not in a cluster

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
richard612
Enthusiast
Enthusiast
Jump to solution

Excellent.  I think I figured out another way:

$LucVMs += Compare-Object -ReferenceObject ($LucVMs | Sort-Object) -DifferenceObject ((Get-VM) | Sort-Object) -PassThru

I ran this and it added the missing VMs to $LucVMs.  Do you think this is also an acceptable approach?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Sure, whatever does the job.
As always, there is no single correct solution when you use PowerShell


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

richard612
Enthusiast
Enthusiast
Jump to solution

Is there a way to speed this up and make it perform at all like the above?

foreach ($vm in (get-vm)) {

    Get-Cluster -VM $vm

    Get-Datacenter -VM $vm

    Get-VMHost -VM $vm

}

It's returning a ton of extra information (which is probably why the LucD method is so much faster).

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not really, except for going the way with nested ForEach I posted.
In this version you are doing N (total number of VMs) x a Get-Cluster and Get-Datacenter.

Suppose you have 2 datacenters, 3 clusters and 100 VMs, then you will do:

1 x Get-VM

100 x Get-Datacenter

100 x Get-CLuster

While in the other method

1 x Get-Datacenter

2 x Get-Cluster

3 x Get-VM

See the difference :smileygrin:


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos