Apendix
Example Reports

In this appendix, we provide some examples on how to produce reports with the help of PowerCLI.

Virtual Machines

Virtual machine (VM) information is retrieved using the Get-VM cmdlet. The cmdlet in its simplest form returns all VMs in your infrastructure:

Get-VM

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
VM001                PoweredOn  1        1.000
VM002                PoweredOff 1        1.000
VM003                PoweredOn  2        2.000

You can specify a VM name via the -Name parameter to be more specific in your request. If you prefer, you can omit the -Name parameter name and use wildcards. By default, only the default properties defined in the types.ps1xml file, located in the PowerShell installation directory, are displayed. To view all properties, you can use the Format-List cmdlet on the pipeline. This cmdlet formats the output of a command as a list of properties in which each property is displayed on a separate line. You can specify which properties are displayed by using the -Property parameter. Specifying the parameter name is optional and therefore the parameter name may be omitted. Since wildcards are allowed, just specify an asterisk (*) to display all properties.

Get-VM VM001 | Format-List *

PowerState              : PoweredOn
Version                 : v11
Description             :
Notes                   :
Guest                   : VMware.VimAutomation.ViCore.Impl.V1.↵
                          VM.Guest.VMGuestImpl
NumCpu                  : 1
MemoryMB                : 1024
MemoryGB                : 1.000
HardDisks               : {Hard disk 1}
NetworkAdapters         : {Network adapter 1}
UsbDevices              : {}
CDDrives                : {CD/DVD Drive 1}
FloppyDrives            : {Floppy drive 1}
Host                    : esx001.mydomain.local
HostId                  : HostSystem-host-2177
VMHostId                : HostSystem-host-2177
VMHost                  : esx001.mydomain.local
VApp                    :
FolderId                : Folder-group-v874
Folder                  : Discovered virtual machine
ResourcePoolId          : ResourcePool-resgroup-163
ResourcePool            : Resources
PersistentId            : 503dc141-f749-110e-727b-57cfa46a38fa
UsedSpaceGB             : 12.17572
ProvisionedSpaceGB      : 23.00673
DatastoreIdList         : {Datastore-datastore-2181}
HARestartPriority       : ClusterRestartPriority
HAIsolationResponse     : AsSpecifiedByCluster
DrsAutomationLevel      : AsSpecifiedByCluster
VMSwapfilePolicy        : Inherit
VMResourceConfiguration : VMware.VimAutomation.ViCore.Impl.V1.↵
                          VM.VMResourceConfigurationImpl
CustomFields            : {}
ExtensionData           : VMware.Vim.VirtualMachine
Id                      : VirtualMachine-vm-2192
Name                    : VM001
Uid                     : /VIServer=@vc01:443/VirtualMachine=
                          VirtualMachine-vm-2192/

Simply displaying all VMs isn’t very useful in the real world. Let’s take it one step further and look at ways to generate a more meaningful report. What about finding out which VMs are powered off?

Get-VM | ?{$_.PowerState -eq "PoweredOff"}

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
VM002                PoweredOff 1        1.000

Or what about reporting on each VM’s VMware Tools version?

Get-VM | Get-View |
    Select-Object Name, @{Name="ToolsVersion";
    Expression={$_.Config.Tools.ToolsVersion}}

Name                                    ToolsVersion
----                                    ------------
VM001                                   7302
VM002                                   8192
VM003                                   7303

Notice how the Select-Object cmdlet is used to filter the specified properties. In fact, when you use the Select-Object cmdlet, a new object is created with the specified properties and the property values are copied from the input object. Besides selecting an existing property like the Name property, you can use the Select-Object cmdlet to create a calculated property like a ToolsVersion property. The ToolsVersion property is created by specifying a hash table for the property. Valid keys inside the hash table are Name and Expression, where the Name key specifies the property name and the Expression key specifies its value. Instead of typing the full key names, you can also type just N for Name or E for Expression:

Get-VM | Get-View |
    Select-Object Name, @{N="ToolsVersion";
    E={$_.Config.Tools.ToolsVersion}}

Let’s make it a bit more complicated and generate a report that lists each VM and its associated host, cluster, and datastores. Again, you’re going to use the Select-Object cmdlet and calculated properties.

Get-VM | Select-Object Name,
    Host, @{N="Cluster";E={$_ | Get-Cluster}},
    @{N="Datastore";E={$_ | Get-Datastore}}

Name       Host                      Cluster    Datastore
----       ----                      -------    ---------
VM001      esx001.mydomain.local     CL02       {Datatore_01,
                                                 Datastore_02}
VM002      esx002.mydomain.local     CL02       Datatore_01
VM003      esx003.mydomain.local     CL01       Datatore_04

Resource Limits

Now that you’re getting familiar with it, let’s take a look at some more examples. Do you know if any of the VMs in your infrastructure have resource limits or reservations set? You can retrieve this information by using the Get-VMResourceConfiguration cmdlet:

Get-VM |
    Get-VMResourceConfiguration | Select VM, CpuReservationMhz,
    CpuLimitMhz, MemReservationMB, MemLimitMB | Format-Table

VM     CpuReservation   CpuLimit   MemReservation   MemLimit
       Mhz              Mhz        MB               MB
--     --------------   --------   --------------   ----------
VM001               0         -1                0           -1
VM002               0         -1                0           -1
VM003               0         -1                0         1024
VM004               0      40284                0          512

The output will include all VMs in the report. In a real-world scenario, you’re probably only interested in the VMs that are nondefault and have a reservation or limit set. In Listing A-1 you’ll find a script that filters out the default VMs and puts the nondefault VMs into an array called $report. In the script, we use a Where clause on the relevant properties in the VMResourceConfiguration object to filter the nondefault ones.

Listing A-1: Resource limits and reservations

$report = Get-VM | Get-VMResourceConfiguration |
where{($_.CpuReservationMhz -ne '0') -or
      ($_.CpuLimitMhz -ne '-1') -or
      ($_.MemReservationMB -ne '0') -or
      ($_.MemLimitMB -ne '-1')} |
Select -ExpandProperty VM
$report | Format-Table

Snapshots

One of our favorite vSphere features is the ability to take snapshots of a virtual machine, but when unmanaged, snapshots can be catastrophic. The problem with snapshots is that they tend to be forgotten once created. For each snapshot you create, vSphere creates a new hard disk underwater, also referred to as a delta disk, for every disk that’s affected by the snapshot operation. These delta disks keep track of the changes made to their parent disk and therefore grow as more data is modified. When the snapshot is kept for a long time, these delta disks can grow quite large and could eventually occupy all the free space on your datastore. Large delta disks slow down the performance of your VM, and when you eventually want to delete the snapshot, it can take hours until all the changes are committed to the parent disks, which in turn can lead to unavailability of your VM. Snapshot information is retrieved using the Get-Snapshot cmdlet. Let’s create a simple overview of all snapshots in your infrastructure:

Get-VM | Get-Snapshot

Name                 Description                    PowerState
----                 -----------                    ----------
Snap001              Before upgrade                 PoweredOff
VM001_Snap01         Installation test 1            PoweredOn
VM003_01             Before patches                 PoweredOn

There are other interesting properties that aren’t shown by default, like the SizeGB and Created properties. The SizeGB property calculates the total size of all related snapshot files on disk. In the real world, you would use this property to monitor the size of your snapshot files on disk so that they don’t become too large. This way, you can avoid the havoc caused by large snapshots. The Created property contains the date and time at which the snapshot was created. As stated before, you don’t want your snapshots to live a long life. Best practice is to never let a snapshot get older than a couple of days. Now, let’s use the Created property to calculate the age of the snapshot in days so that you can easily spot snapshots that are older than the maximum allowed number of days:

Get-VM | Get-Snapshot |
    Select VM, Name, Description, @{N="DaysOld";
    E={((Get-Date) - $_.Created).Days}}

VM          Name              Description              DaysOld
--          ----              -----------              -------
VM002       Snap001           Before upgrade                 1
VM001       VM001_Snap01      Installation test 1           40
VM003       VM003_01          Before patches                20

Now that you know the age of the snapshot in days, you can easily report only the snapshots that are older than, for instance, 7 days:

Get-VM | Get-Snapshot |
    Select VM, Name, Description, @{N="DaysOld";
    E={((Get-Date) - $_.Created).Days}} | ? {$_.DaysOld –gt 7}

VM         Name               Description              DaysOld
--         ----               -----------              -------
VM001      VM001_Snap01       Installation test 1           40
VM003      VM003_01           Before patches                20

Guest Operating Systems

With VMware Tools installed, it is possible to retrieve information from a virtual machine’s guest OS. By default, a number of properties are available in the virtual machine object, such as the operating system and IP address, which you can retrieve by using the Get-VMGuest cmdlet:

Get-VMGuest -VM VM001

State    IPAddress      OSFullName
-----    ---------      ----------
Running  {192.168.1.1}  Microsoft Windows Server 2008 (64-bit)

If other information is needed, you can use the Invoke-VMScript cmdlet to run scripts inside the guest. See Chapter 9, “Advanced Virtual Machine Features,” for more information on using the Invoke-VMScript cmdlet.

Let’s look at how the VMGuest object can be used to create a report about the guest’s disk usage.

VM Guest Disk Usage

In Listing A-2 you’ll find a function that uses the virtual machine’s guest information to report on the guest’s disk usage. Using this report, you can easily spot volumes that are running out of disk space and take actions accordingly to avoid a system crash. This report can also be used to spot volumes that are heavily underutilized; you can replace those disks with smaller ones or convert them to thin-provisioned disks to free up valuable space on your datastores.

Listing A-2: Get-VMGuestDiskUsage

function Get-VMGuestDiskUsage {
<#
.SYNOPSIS
  Gets a vm's guest OS disk usage information
.DESCRIPTION
  This function creates a report with disk usage information
  of the vm's guest OS
.NOTES
  Source:  Automating vSphere Administration
  Authors: Luc Dekens, Brian Graf, Arnim van Lieshout,
           Jonathan Medd, Alan Renouf, Glenn Sizemore,
           Andrew Sullivan
.PARAMETER VM
  The VM object to create a report on
.EXAMPLE
  Get-VMGuestDiskUsage -VM (Get-VM WIN*)
.EXAMPLE
  Get-VM | Get-VMGuestDiskUsage
#>

  Param(
    [Parameter(ValueFromPipeline = $true, Mandatory = $true,
      HelpMessage = "Enter a vm entity")]
  [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]$VM)

  Process {
#Hide errors which appear if VMware Tools is not installed
#or VM is PoweredOff
    $ErrorActionPreference = "SilentlyContinue"

    foreach($disk in $VM.Guest.Disks) {
      New-Object -Type PSObject -Property ([ordered]@{
        VM = $VM.Name
        Volume = $disk.Path
        CapacityGB = [math]::Round($disk.Capacity / 1GB)
        FreeSpaceGB = [math]::Round($disk.FreeSpace / 1GB)
        'Usage%' = "{0:p2}" -f `
          (($disk.Capacity - $disk.FreeSpace ) / $disk.Capacity)
      })
    }
  }
}

Hosts

Host information is retrieved using the Get-VMHost cmdlet:

Get-VMHost | Format-Table

Name             Connection Power     NumCpu CpuUsage CpuTotal  MemoryUsage
                 State      State            Mhz      Mhz       GB
----             ---------- --------- ------ -------- --------  -----------
esx1.local.test  Connected  PoweredOn   2    94       6798      1.453
esx2.local.test  Connected  PoweredOn   2    103      6798      1.443

You can specify a hostname via the -Name parameter to be more specific in your request. If you have a virtual machine, datastore, or folder object, you can pass that object on the pipeline to get only the hosts associated with that object:

Get-VM VM001 | Get-VMHost | FT

Name             Connection Power     NumCpu CpuUsage CpuTotal  MemoryUsage
                 State      State            Mhz      Mhz       GB
----             ---------- --------- ------ -------- --------  -----------
esx2.local.test  Connected  PoweredOn   2    103      6798      1.443

Now, let’s look at some more advanced reporting.

Host Bus Adapters

For the sake of documentation, you probably want a report on your host’s host bus adapters. This information can be retrieved using a simple one-liner:

Get-VMHost -Name "ESX001" |
    Get-VMHostHba | Select Pci,Device,Type,Model,Status |
    Format-Table -AutoSize

WARNING: column "Status" does not fit into the display and was
removed.

Pci      Device           Type  Model
---      ------           ----  -----
02:04.0  vmhba0          Block  Smart Array 5i
03:07.0  vmhba1   FibreChannel  QLA2300 64-bit Fibre Channel ...
03:08.0  vmhba2   FibreChannel  QLA2300 64-bit Fibre Channel ...
00:04.1  vmhba3          Block  AMD 8111 IDE/PATA Controller
00:04.1  vmhba32         Block  AMD 8111 IDE/PATA Controller

When you want to know the World Wide Port Numbers (WWPN) of the host’s Fibre Channel adapters, you can query the PortWorldWideName property. This property is an integer value, however, and it probably doesn’t mean anything to you in this format. WWPNs are commonly denoted in hexadecimal format. You can convert the reported value to hexadecimal using the PowerShell -f format operator:

"{0:x}" -f $intVariable

To generate the full report, you can use the script in Listing A-3. This script creates a report of all storage adapters on all hosts in all clusters.

Listing A-3: Host bus adapter report

$hbaReport = @()
foreach ($cluster in Get-Cluster) {
  foreach ($vmHost in @($cluster | Get-VMHost)) {
    foreach ($hba in @($vmHost | Get-VMHostHba)) {
      $objHba = "" | Select ClusterName,HostName,Pci,Device, `
          Type,Model,Status,Wwpn
      $objHba.ClusterName = $cluster.Name
      $objHba.HostName = $vmhost.Name
      $objHba.Pci = $hba.Pci
      $objHba.Device = $hba.Device
      $objHba.Type = $hba.Type
      $objHba.Model = $hba.Model
      $objHba.Status = $hba.Status
      $objHba.Wwpn = "{0:x}" -f $hba.PortWorldWideName
      $hbaReport += $objHba
    }
  }
}

$hbaReport | Export-Csv HbaReport.csv

Network Interface Cards

As with the host bus adapter report, you can report the status of your network interface cards. You can retrieve network interface card information by using the Get-VMHostNetworkAdapter cmdlet:

Get-VMHost -Name "ESX001" |
    Get-VMHostNetworkAdapter | Select DeviceName,Mac,
    BitRatePerSec,FullDuplex
DeviceName Mac               BitRatePerSec FullDuplex
---------- ---               ------------- ----------
vmnic1     00:aa:bb:cc:dd:e1             0      False
vmnic0     00:aa:bb:cc:dd:e0          1000       True
vmnic2     00:aa:bb:cc:dd:e2          1000       True
vmnic3     00:aa:bb:cc:dd:e3          1000       True
vswif0     00:50:56:cc:dd:ee
vmk0       00:50:56:cc:dd:ef

If you want to know the Peripheral Component Interconnect (PCI) information for the network card, you have to query the underlying SDK object; the information isn’t available from the objects returned by the Get-VMHostNetworkAdapter cmdlet. This can be done through the .ExtensionData property. Let’s generate a full report like the HBA report we created with the script in Listing A-3. The script in Listing A-4 creates a report of all network interface cards on all hosts in all clusters.

Listing A-4: Network interface card report

$nicReport=@()
foreach ($cluster in Get-Cluster) {
  foreach ($vmHost in @($cluster | Get-VMHost)) {
    foreach ($nic in @($VMHost | Get-VMHostNetworkAdapter)) {
      $objNic = "" | Select ClusterName,HostName,Pci, `
          DeviceName,Mac,BitRatePerSec,FullDuplex
      $objNic.ClusterName = $cluster.Name
      $objNic.HostName = $vmHost.Name
      $objNic.Pci = $nic.ExtensionData.Pci
      $objNic.DeviceName = $nic.DeviceName
      $objNic.Mac = $nic.Mac
      $objNic.BitRatePerSec = $nic.BitRatePerSec
      $objNic.FullDuplex = $nic.FullDuplex
      if ($nic.ExtensionData.Pci) {
        $nicReport += $ObjNic
      }
    }
  }
}
$nicReport | Export-Csv NicReport.csv

PCI Devices

Besides storage adapters and network cards, there is a lot of other hardware present in your hosts. The function in Listing A-5 generates a report of all hardware devices present in your host. The function downloads PCI information from http://pci-ids.ucw.cz/ to provide more information on each PCI device found. To use the function, provide one or more VMHost objects through the pipeline or use the -VMHost parameter:

Get-VMHost "ESX001" | Get-VMHostPciDevice | Format-Table

Listing A-5: The Get-VMHostPciDevice function

function Get-VMHostPciDevice {
<#
.SYNOPSIS
  Returns the ESX(i) host's PCI Devices
.DESCRIPTION
  This function returns the ESX(i) host's PCI devices and the
  associated ESX devices. Pci device information is downloaded
  from http://pci-ids.ucw.cz/
.NOTES
  Source:  Automating vSphere Administration
  Authors: Luc Dekens, Brian Graf, Arnim van Lieshout,
           Jonathan Medd, Alan Renouf, Glenn Sizemore,
           Andrew Sullivan
.PARAMETER VMHost
  The ESX(i) host entity for which the PCI devices should be
  returned
.PARAMETER forceDownload
  Switch parameter to force a download of the pci information
.EXAMPLE
  Get-VMHostPciDevice -VMHost (Get-VMHost "esx001")
.EXAMPLE
  Get-VMHost "esx001" | Get-VMHostPciDevice
#>

  Param (
  [parameter(ValueFromPipeline = $true, Mandatory = $true,
  HelpMessage = "Enter an ESX(i) host entity")]
  [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl] `
      $VMHost,
  [Switch]$forceDownload)

  Begin {
    $urlPci = "http://pci-ids.ucw.cz/v2.2/pci.ids"
    $filename =  "${env:Temp}pci.ids"
    $pciDevices= @{}
# Download file if not present or if forced download
    if(!(Test-Path $filename) -or $forceDownload){
      $web = New-Object Net.WebClient
      $web.DownloadFile($urlPCI,$filename)
    }
# Read file into hash table
    Get-Content $filename | Where-Object {
        $_.Length -ne 0 -and $_[0] -ne "#"} | Foreach-Object {
      if($_[0] -eq "`t"){
        if($_[1] -eq "`t"){
          $subdeviceId = $_.Substring(2,4)
          if(!$pciDevices[$vendorId].deviceTab.ContainsKey( `
              $subdeviceId)){
            $pciDevices[$vendorId].deviceTab[$subdeviceId] =
              $_.Substring(6).TrimStart(" ")
          }
        }
        else{
          $deviceId = "0x" + $_.Substring(1,4)
          if(!$pciDevices[$vendorId].deviceTab.ContainsKey( `
              $deviceId)){
            $pciDevices[$vendorId].deviceTab[$deviceId] =
              $_.Substring(5).TrimStart(" ")
          }
        }
      }
      else{
        $vendorId = "0x" + $_.Substring(0,4)
        if(!$pciDevices.ContainsKey($vendorId)){
          $pciDevices[$vendorId] = New-Object PSObject `
              -ArgumentList @{
            Vendor = $_.Substring(4).TrimStart(" ")
            deviceTab = @{}
          }
        }
      }
    }
# Create PCI class array
    $PciClass = @("Unclassified device",
      "Mass storage controller","Network controller",
      "Display controller","Multimedia controller",
      "Memory controller","Bridge","Communication controller",
      "Generic system peripheral","Input device controller",
      "Docking station","Processor","Serial bus controller",
      "Wireless controller","Intelligent controller",
      "Satellite communications controller",
      "Encryption controller","Signal processing controller")
  }

  Process {
# Get the host's PCI Devices
    $hostDevices = @()
    foreach ($dev in $VMHost.ExtensionData.Hardware.PciDevice) {
      $strVendorId = "0x" + "{0}" -f
        [Convert]::ToString($dev.VendorId,16).ToUpper(). `
            PadLeft(4, '0')
      $strDeviceId = "0x" + "{0}" -f
        [Convert]::ToString($dev.DeviceId,16).ToUpper(). `
            PadLeft(4, '0')
      $objDevice = "" |
        Select-Object Pci, ClassName, VendorName, DeviceName, `
            EsxDeviceName
      $objDevice.Pci = $dev.Id
      $objDevice.ClassName = $PciClass[[int]($dev.ClassId/256)]
      if($pciDevices.ContainsKey($strVendorId)){
        $objDevice.VendorName = $pciDevices[$strVendorId].Vendor
      }
      else{
        $objDevice.VendorName = $strVendorId
      }
      if($pciDevices[$strVendorId].deviceTab.ContainsKey( `
          $strDeviceId)){
        $objDevice.DeviceName =
          $pciDevices[$strVendorId].deviceTab[$strDeviceId]
      }
      else{
        $objDevice.DeviceName = $strDeviceId
      }
      $hostDevices += $objDevice
    }

# Find associated ESX storage devices
    foreach ($hba in $_.ExtensionData.Config.StorageDevice. `
        HostBusAdapter) {
      $hostDevices | Where-Object {$_.Pci -match $hba.Pci} |
        Foreach-Object {$_.EsxDeviceName = "["+$hba.device+"]"}
    }

# Find associated ESX network devices
    foreach ($nic in $_.ExtensionData.Config.Network.Pnic) {
      $hostDevices | Where-Object {$_.Pci -match $nic.Pci} |
        Foreach-Object {$_.EsxDeviceName = "["+$nic.device+"]"}
    }
    $hostDevices
  }
}

Clusters

You retrieve cluster information by using the Get-Cluster cmdlet:

Get-Cluster | FT –AutoSize

Name HAEnabled HAFailoverLevel DrsEnabled DrsAutomationLevel
---- --------- --------------- ---------- ------------------
CL01 True      1               False      FullyAutomated
CL05 False     1               False      FullyAutomated
CL02 False     1               True       FullyAutomated
CL03 False     1               False      FullyAutomated
CL04 False     1               False      FullyAutomated

Notice that the cluster objects returned contain only basic High Availability (HA) and Distributed Resource Scheduler (DRS) information. If you want to know more information, you have to use the underlying SDK object, which is accessible through the .ExtensionData property. If you want to know the number of hosts in a cluster, you can simply count the items in the .ExtensionData.Host property.

Get-Cluster | Select Name, `
    @{N="NumHosts";E={$_.ExtensionData.Host.count}} | ft -AutoSize

Name NumHosts
---- --------
CL01        0
CL05        0
CL02        3
CL03        0
CL04        0

Take a look, too, at how we used the –AutoSize parameter with the Format-Table cmdlet to automatically size the width of the columns according to their content.

Cluster Summary Report

Let’s generate a small summary report on the clusters. Things that are interesting to include in this report are the number of hosts, VMs, datastores, networks, and numbers on memory and CPU usage. The function in Listing A-6 will generate such a report.

Listing A-6: Get-ClusterSummary

function Get-ClusterSummary {
<#
.SYNOPSIS
  Gets summary information from the cluster
.DESCRIPTION
  This function creates a report with summary information of the
  cluster
.NOTES
  Source:  Automating vSphere Administration
  Authors: Luc Dekens, Brian Graf, Arnim van Lieshout,
           Jonathan Medd, Alan Renouf, Glenn Sizemore,
           Andrew Sullivan
.PARAMETER Cluster
  The cluster object to create a report on
.EXAMPLE
  Get-ClusterSummary -Cluster (Get-Cluster CL01)
.EXAMPLE
  Get-Cluster | Get-ClusterSummary
#>

  Param(
   [parameter(ValueFromPipeline = $true, Mandatory = $true,
     HelpMessage = "Enter a cluster entity")]
   [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl] `
       $cluster)

  process {
    $objCluster = "" | Select ClusterName, NumHost, NumVM, `
        NumDatastore, NumNetwork, AssignedCpu, NumCores, `
        vCpuPerCore, TotalCpuGHz, TotalMemGB, AssignedMemGB, `
        MemUsagePct
    $vm = @($cluster | Get-VM)
    $objCluster.ClusterName = $cluster.Name
    $objCluster.NumHost = `
        $cluster.ExtensionData.Summary.NumHosts
    $objCluster.NumVM = $vm.Count
    $objCluster.NumDatastore = `
        $cluster.ExtensionData.Datastore.Count
    $objCluster.NumNetwork = `
        $cluster.ExtensionData.Network.Count
    $objCluster.AssignedCpu = ($vm | Where {
      $_.PowerState -eq "PoweredOn"} |
      Measure-Object -Property NumCpu -Sum).Sum
    $objCluster.NumCores = `
        $cluster.ExtensionData.Summary.NumCpuCores
    $objCluster.vCpuPerCore = "{0:n2}" -f
      ($objCluster.AssignedCpu / $objCluster.NumCores)
    $objCluster.TotalCpuGhz = "{0:n2}" -f
      ($cluster.ExtensionData.Summary.TotalCpu / 1000)
    $objCluster.TotalMemGB = "{0:n2}" -f
      ($cluster.ExtensionData.Summary.TotalMemory / 1GB)
    $objCluster.AssignedMemGB = "{0:n2}" -f (($vm |
      Where {$_.PowerState -eq "PoweredOn"} |
      Measure-Object -Property MemoryMB -Sum).Sum / 1024)
    $objCluster.MemUsagePct = "{0:p2}" -f
      ($objCluster.AssignedMemGB / $objCluster.TotalMemGB)
    $objCluster
  }
}

Now that you’ve examined the Get-ClusterSummary function, let’s give it a try and take a look at the generated report:

Get-Cluster CL02 | Get-ClusterSummary

ClusterName   : CL02
NumHost       : 3
NumVM         : 48
NumDatastore  : 13
NumNetwork    : 15
AssignedCpu   : 63
NumCores      : 24
vCpuPerCore   : 2.63
TotalCpuGHz   : 64.08
TotalMemGB    : 135.67
AssignedMemGB : 90.95
MemUsagePct   : 67.04 %

Generating this report for just one cluster is nice, but what about your other clusters? The benefit of writing the Get-ClusterSummary code as a function is that you can use the code with any cluster object you like. To generate a report for all your clusters, you only have to put them all on the pipeline by just removing the cluster name from the Get-Cluster cmdlet:

Get-Cluster | Get-ClusterSummary | Format-Table

Cluste Num  NumVM NumDat NumNe Assig  NumCo vCpuP  Total   Total
rName  Host       astore twork nedCpu   res erCore CpuGHz  MemGB
------ ---- ----- ------ ----- ------ ----- ------ ------ ------
CL01      5   102     14    62    138    64   2.16 151.07 335.99
CL02      3    48     13    15     63    24   2.63  64.08 135.67
CL03      1    16      4     5     16     8   2.00  22.50  40.00
CL04      2    24      3    14     28    16   1.75  44.99 111.99

Notice that the Format-Table cmdlet is used here to display the output in a table format. The output shown is also edited to fit onto the page.

Inconsistent Port Groups

If you’re using standard switches, it’s important that all port groups be consistently defined on all hosts in your cluster. If you fail to do so, you might encounter vMotion errors. The function in Listing A-7 will help you detect inconsistently named port groups.

Listing A-7: Get-MissingPortGroup

function Get-MissingPortgroup {
<#
.SYNOPSIS
  Gets the inconsistent virtual portgroups in a cluster
.DESCRIPTION
  This function creates a report of the inconsistent portgroups
  in a cluster. It reports which portgroups are missing on which
  host.
.NOTES
  Source:  Automating vSphere Administration
  Authors: Luc Dekens, Brian Graf, Arnim van Lieshout,
           Jonathan Medd, Alan Renouf, Glenn Sizemore,
           Andrew Sullivan
.PARAMETER Cluster
  The cluster object to check
.EXAMPLE
  Get-MissingPortGroup -Cluster (Get-Cluster CL01)
.EXAMPLE
  Get-Cluster | Get-MissingPortGroup
#>

  Param(
   [parameter(ValueFromPipeline = $true, Mandatory = $true,
     HelpMessage = "Enter a cluster entity")]
   [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl] `
       $cluster)

  process{
#create an array with all available portgroups in the cluster
    $clusterHosts = @($cluster | Get-VMHost)
    $refPortGroups = @($clusterHosts | Get-VirtualPortGroup -Standard |
      Select-Object -Unique)

#compare the hosts against the reference array
    foreach ($vmHost in $clusterHosts) {
      $difPortGroups = @($vmHost | Get-VirtualPortGroup -Standard)
      $differences = @(Compare-Object $refPortGroups `
          $difPortGroups)
      foreach ($item in $differences) {
        $objPG = "" | Select Cluster,HostName,MissingPortGroup
        $objPG.Cluster = $cluster
        $objPG.HostName = $vmHost.Name
        $objPG.MissingPortGroup = $item.InputObject
        $objPG
      }
    }
  }
}

Now let’s look at the report:

Get-Cluster CL02 | Get-MissingPortGroup

Cluster         HostName                      MissingPortGroup
-------         --------                      ----------------
CL02            esx001.mydomain.local         Management Network
CL02            esx003.mydomain.local         Management Network
CL02            esx002.mydomain.local         VLAN020

Notice that the hosts esx001 and esx003 are both missing a Management Network port group and that host esx002 doesn’t contain the VLAN020 port group.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset