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?
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
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
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?
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
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).
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