Automation

 View Only
  • 1.  Using Get-View against many datacenters some with same named VMs

    Posted Feb 11, 2019 09:07 PM

    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



  • 2.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 11, 2019 09:36 PM

    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.



  • 3.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 04:00 PM

    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



  • 4.  RE: Using Get-View against many datacenters some with same named VMs
    Best Answer

    Posted Feb 12, 2019 04:36 PM

    Try changing line 10 like this

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



  • 5.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 05:58 PM

    Thanks that seems to have addressed my issue!



  • 6.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 06:15 PM

    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.



  • 7.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 06:20 PM

    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

    }



  • 8.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 07:15 PM

    Thanks mate I really appreciate your help!



  • 9.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 07:32 PM

    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

            }

        }

    }



  • 10.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 07:42 PM

    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.



  • 11.  RE: Using Get-View against many datacenters some with same named VMs

    Posted Feb 12, 2019 07:46 PM

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

    thanks again!