VMware Cloud Community
RobertSJr
Contributor
Contributor
Jump to solution

Using Get-View against many datacenters some with same named VMs

So I've run into a odd little issue and I'm stumped.

I've got a basic report built along the lines of foreach ($vm in $VMList)

{$VMStat = "" | Select-object VMName, DC, Cluster, Host, ....

Then one of the objects something like:

$VMStat.TotalMemoryGB = [math]::Round($vm.summary.config.memorysizemb*1MB/1GB,2)

Works fine on everything until I run into this non template VM that the other system admin guys leave around called dupW2k8 or whatever.   There are many of them one in each cluster of which there are many.

So if you do a get-vm dupW2k8  you get a list of 10+ VMs all with their own CPU and Memory but in my foreach loop this creates a problem in producing a report.  Any ideas on how to loop through or around them.   I guess I could create an ignore list or something but I'm sure there are others.   I don't manage the VM Farm I'm just working a report with read only access.

thanks for any suggestions

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try changing line 10 like this

$vm=Get-View -ViewType Virtualmachine -SearchRoot $cluster.ExtensionData.MoRef -filter @{"Name"="$($vm.Name)"}


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

View solution in original post

0 Kudos
10 Replies
LucD
Leadership
Leadership
Jump to solution

I assume you are doing your reporting cluster-based.

Then you could do the Get-VM with the Location parameter, which would point to the specific cluster you reporting on.

I would need to see your script to check if there are other possibilities.


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

0 Kudos
RobertSJr
Contributor
Contributor
Jump to solution

Hi LucD,

Hey it's somewhat based on one of your's I found in this forum actually.

Here is the important bits.

#Get a list of DataCenters in sorted order

$DCs=get-datacenter | sort

foreach ($dc in $DCs){

    $ClusterList=get-datacenter $dc | get-cluster | sort

    foreach ($cluster in $ClusterList){

        $VMList = get-cluster $cluster | get-vm | sort    

        foreach($vm in $VMList){

            Write-Host $vm.Name #Just for testing and seeing what VMs are throwing errors if any while I test

            $vm=Get-View -ViewType Virtualmachine -filter @{"Name"="$vm"}

            # The Report

            $VMStats = "" | Select-Object  VMName, DC, Cluster, ESXiHost, Folder, HardwareVersion, OS, VMstate, TotalCPU, CPUAffinity, CPUreservation, TotalMemoryGB, MemoryReservationMB, TotalNics, IPAddress, MacAddress, Portgroup, Datastore, ProvisionedSpaceGB, UsedSpaceGB, ToolsStatus, ToolsVersion

            #The List of things we can view follows below.

            #Get Parent Details From vCenter (Data Center, Cluster, ESXi Host, Folder)

            $VMStats.DC = $DC

            $VMStats.Cluster = $cluster

            $VMStats.ESXiHost = Get-View -Id $vm.Runtime.Host -property Name | select -ExpandProperty Name

            $VMStats.Folder = Get-View -Id $vm.Parent -Property 'Name' | select -ExpandProperty Name

            

            

            # Basic Info about the VM (Hostname, HardwareVersion, ESXiHost, IPAddress(s), OS, Powered/ON/Off

            $VMStats.VMName = $vm.Name

            $VMStats.HardwareVersion = $vm.config.Version

            $VMStats.IPAddress = $vm.guest.IPAddress -join ', '

            $VMStats.OS = $vm.Config.GuestFullName

            $VMStats.VMState = $vm.summary.runtime.powerState

            # CPU Info

            $VMStats.TotalCPU = $vm.summary.config.numcpu

            $VMStats.CPUAffinity = $vm.Config.CpuAffinity

            $VMStats.CPUreservation = $vm.resourceconfig.cpuallocation.reservation

          

            # Memory Info

            $VMStats.TotalMemoryGB = [math]::Round($vm.summary.config.memorysizemb*1MB/1GB,2)

            $VMStats.MemoryReservationMB = $vm.resourceconfig.memoryallocation.reservation

           

            #Network Info

            $VMStats.TotalNics = $vm.summary.config.numEthernetCards

            $VMStats.MacAddress = $vm.config.hardware.device.macaddress

            #VLAN - Portgroup info

            $VMStats.Portgroup = Get-View -Id $vm.Network -Property Name | select -ExpandProperty Name

           

            #Storage Info

            $VMStats.Datastore = $vm.Config.DatastoreURL[0].Name

            $VMStats.ProvisionedSpaceGB = [math]::Round($vm.Summary.Storage.UnCommitted/1GB,2)

            $VMStats.UsedSpaceGB = [math]::Round($vm.Summary.Storage.Committed/1GB,2)

            #VMware Tools Info

            $VMStats.ToolsStatus = $vm.guest.toolsstatus

            $VMStats.ToolsVersion = $vm.config.tools.toolsversion

           

            #Add details to the report

            $Report += $VMStats

        }

    }

}

Here is some one liner testing with the results.

PowerCLI C:\Users\rstacks\Desktop> $vm=Get-View -ViewType Virtualmachine -filter @{"Name"="Win2k8"}

PowerCLI C:\Users\rstacks\Desktop> $vm.summary.config.memorysizemb

2048

2048

2048

2048

2048

2048

2048

2048

2048

2048

2048

2048

2048

2048

PowerCLI C:\Users\rstacks\Desktop> get-vm Win2k8

Name                 PowerState Num CPUs MemoryGB

----                 ---------- -------- --------

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

Win2k8               PoweredOff 1        2.000

So maybe I need to switch up the loop to pull from a specific cluster one at a time?  Is that what you are suggesting?  That would make sense.

I sorta thought that was what I was doing in the way the loops are setup but I guess line 10 breaks that logic.  Because I over write $vm.   Maybe I should give that a different value so it would be a different object type?

Robert

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try changing line 10 like this

$vm=Get-View -ViewType Virtualmachine -SearchRoot $cluster.ExtensionData.MoRef -filter @{"Name"="$($vm.Name)"}


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

0 Kudos
RobertSJr
Contributor
Contributor
Jump to solution

Thanks that seems to have addressed my issue!

0 Kudos
RobertSJr
Contributor
Contributor
Jump to solution

Well that did fix the problem but now I have a another problem related to the same thing.

Down in the loop I have

$VMStats.Portgroup = Get-View -Id $vm.Network -Property Name | select -ExpandProperty Name

On one of those duplicate VMs I now get an error

+ $VMStats.Portgroup = Get-View -Id $vm.Network -Property Name | select -Expand ... +                                   ~~~~~~~~~~~ + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets    .Commands.DotNetInterop.GetVIView

On a side note, how do I insert code on this forum so it looks right?  I've been trying to use the syntax highlighter but that doesn't look right.  No idea why they would leave off Powershell in the drop down.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Could it be that you have a VM that is not connected to a network?

To avoid the error, you can do

if ($vm.Network) {

   $VMStats.Portgroup = Get-View -Id $vm.Network -Property Name | select -ExpandProperty Name

}


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

RobertSJr
Contributor
Contributor
Jump to solution

Thanks mate I really appreciate your help!

0 Kudos
RobertSJr
Contributor
Contributor
Jump to solution

Doh I guess I spoke too soon, I have one last oddity everything else is working.

I had to put in some Write-Host statements to see what was going on.

I have a 2 VMs lets call them VM01 and VM01v6.

VM01 has an IP that ends in .5 and VM02v6 has an IP that ends in .6

VM01 has 4gb of ram and VM01v6 has 16gb

But when the script runs for some reason on VM01 it shows IPs for both VMs for VM01 then tosses errors when it tries to do the math for RAM and such.   When I tried the Write-Host.  Here is what I see

$VMStats.TotalMemoryGB = [math]::Round($vm.summary.config.memorysizemb*1MB/1GB,2)

Write-Host "MemoryGB: " $VMStats.TotalMemoryGB

Output to screen:

MemoryMB: 16384 4096

When it tries to do the math

$VMStats.TotalMemoryGB = [math]::Round($vm.summary.config.memorysizemb*1MB/1GB,2)

I get an error:

Method invocation failed because [System.Object[]] doesn't contain a method named 'op_Division'.

$VMStats.TotalMemoryGB = [math]::Round($vm.summary.config.memorysizemb*1MB/1G ...

CategoryInfo: InvalidOperation: (op_Division:String) [], RuntimeException

Here is the current Script

#Get a list of DataCenters in sorted order

$DCs=get-datacenter | sort

foreach ($dc in $DCs){

    $ClusterList=get-datacenter $dc | get-cluster | sort

    foreach ($cluster in $ClusterList){

        $VMList = get-cluster $cluster | get-vm | sort    

        foreach($vm in $VMList){

            Write-Host $vm.Name #Just for testing and seeing what VMs are throwing errors if any while I test

            $vm=Get-View -ViewType Virtualmachine -SearchRoot $cluster.ExtensionData.MoRef -filter @{"Name"="$($vm.Name)"}

            # The Report

            $VMStats = "" | Select-Object  VMName, DC, Cluster, ESXiHost, Folder, HardwareVersion, OS, VMstate, TotalCPU, CPUAffinity, CPUreservation, TotalMemoryGB, MemoryReservationMB, TotalNics, IPAddress, MacAddress, Portgroup, Datastore, ProvisionedSpaceGB, UsedSpaceGB, ToolsStatus, ToolsVersion

            #Get Parent Details From vCenter (Data Center, Cluster, ESXi Host, Folder)

            $VMStats.DC = $DC

            $VMStats.Cluster = $cluster

            $VMStats.ESXiHost = Get-View -Id $vm.Runtime.Host -property Name | select -ExpandProperty Name

            $VMStats.Folder = Get-View -Id $vm.Parent -Property 'Name' | select -ExpandProperty Name

                

            # Basic Info about the VM (Hostname, HardwareVersion, ESXiHost, IPAddress(s), OS, Powered/ON/Off

            $VMStats.VMName = $vm.Name

            $VMStats.HardwareVersion = $vm.config.Version

            $VMStats.IPAddress = $vm.guest.IPAddress -join ', '

            $VMStats.OS = $vm.Config.GuestFullName

            $VMStats.VMState = $vm.summary.runtime.powerState

            # CPU Info

            $VMStats.TotalCPU = $vm.summary.config.numcpu

            $VMStats.CPUAffinity = $vm.Config.CpuAffinity

            $VMStats.CPUreservation = $vm.resourceconfig.cpuallocation.reservation

          

            # Memory Info

            $VMStats.TotalMemoryGB = [math]::Round($vm.summary.config.memorysizemb*1MB/1GB,2)

            $VMStats.MemoryReservationMB = $vm.resourceconfig.memoryallocation.reservation

           

            #Network Info

            $VMStats.TotalNics = $vm.summary.config.numEthernetCards

            $VMStats.MacAddress = $vm.config.hardware.device.macaddress

            #VLAN - Portgroup info

            if ($vm.Network) {$VMStats.Portgroup = Get-View -Id $vm.Network -Property Name | select -ExpandProperty Name}

           

            #Storage Info

            $VMStats.Datastore = $vm.Config.DatastoreURL[0].Name

            $VMStats.ProvisionedSpaceGB = [math]::Round($vm.Summary.Storage.UnCommitted/1GB,2)

            $VMStats.UsedSpaceGB = [math]::Round($vm.Summary.Storage.Committed/1GB,2)

            #VMware Tools Info

            $VMStats.ToolsStatus = $vm.guest.toolsstatus

            $VMStats.ToolsVersion = $vm.config.tools.toolsversion

           

            #Add details to the report

            $Report += $VMStats

        }

    }

}

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The error is because you have more than object in variable $vm.
This changes the type of $vm into an [array], and arrays don't the division operation defined.

The reason why you are getting more than 1 object in $vm, because on the Get-View cmdlet the Filter parameter takes the right-hand operand to be a regular expression (RegEx).

So when the right-hand operand is 'VM01', it will also return the VM wiht the name 'VM01v06'.

To avoid that, you can make it an exact match by specifying locations.
In a RegEX expression these locations can be the beginning of the string (^) and the end of the string ($).

If you change the line the following, you will get an exact match, and only 1 VM will be returned.

$vm = Get-View -ViewType Virtualmachine -SearchRoot $cluster.ExtensionData.MoRef -filter @{"Name" = "^$($vm.Name)$"}

PS: that was a lot of text :smileygrin:

But RegEx are powerful and really something most PowerCLI users should have a look at.


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

0 Kudos
RobertSJr
Contributor
Contributor
Jump to solution

Doh I didn't realize that was Regex string.  Thanks!  I'm still getting a feel for powershell.

thanks again!

0 Kudos