In this appendix, we provide some examples on how to produce reports with the help of PowerCLI.
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
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
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
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.
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)
})
}
}
}
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.
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
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
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
}
}
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.
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.
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.