PowerCLI Report Tip – Part 4

Introduction

Finally, it’s the last PowerCLI Report Tip series! In this blog post, it will be discussing how PLINK could be used for advanced reporting. This will be quite short compared to other blog series and if you want to read previous series, they could be found below:

What is PLINK?

Many of you would already be familiar with SSH client. Putty if you are running Windows or terminal for Mac. PLINK is a command-line interface to the PuTTY back ends. More information could be found and downloaded here.

Why PLINK with PowerCLI?

Normally, PowerCLI would be enough for reports with information from vCenter Server and ESXi server. However, sometimes, reports will require additional information from external sources. I will explain reasons in Examples section.

How do you run PLINK with PowerCLI?

Running PLINK with PowerCLI is quite simple:

  1. Download the file
  2. Locate it under a folder
  3. Run

Example attached below:

PowerCLI C:\script\plink> .\PLINK.EXE
PuTTY Link: command-line connection utility
Usage: plink [options] [user@]host [command]
("host" can also be a PuTTY saved session name)
Options:
  -V        print version information and exit
  -pgpfp    print PGP key fingerprints and exit
  -v        show verbose messages
  -load sessname  Load settings from saved session
  -ssh -telnet -rlogin -raw -serial
            force use of a particular protocol
  -P port   connect to specified port
  -l user   connect with specified username
  -batch    disable all interactive prompts
The following options only apply to SSH connections:
  -pw passw login with specified password
  -D [listen-IP:]listen-port
            Dynamic SOCKS-based port forwarding
  -L [listen-IP:]listen-port:host:port
            Forward local port to remote address
  -R [listen-IP:]listen-port:host:port
            Forward remote port to local address
  -X -x     enable / disable X11 forwarding
  -A -a     enable / disable agent forwarding
  -t -T     enable / disable pty allocation
  -1 -2     force use of particular protocol version
  -4 -6     force use of IPv4 or IPv6
  -C        enable compression
  -i key    private key file for authentication
  -noagent  disable use of Pageant
  -agent    enable use of Pageant
  -m file   read remote command(s) from file
  -s        remote command is an SSH subsystem (SSH-2 only)
  -N        don't start a shell/command (SSH-2 only)
  -nc host:port
            open tunnel in place of session (SSH-2 only)
  -sercfg configuration-string (e.g. 19200,8,n,1,X)
            Specify the serial configuration (serial only)

Specifically, you could execute the following to run a command over a server:

C:\script\PLINK\plink.exe -pw "Password of the user" "Username@ServerName" "Command you want to run"

Assuming the connection is successfully made, let’s go through the tips.

Tips, PLINK with PowerCLI

First tip

When you run SSH command to a server for the first time, it asks you to accept the certification like the following:

PowerCLI C:\script\plink> .\PLINK.EXE -pw "Password" "Username@ServerName" "Command you want to run"
The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is.
The server's dss key fingerprint is:
ssh-dss 1024 aa:bb:cc:dd:ee:ff:gg:aa:bb:cc:dd:ee:ff:gg:aa:bb
If you trust this host, enter "y" to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, enter "n".
If you do not trust this host, press Return to abandon the connection.
Store key in cache? (y/n)

Instead of typing yes all the time for the first connection, you could simply use “echo” to avoid it. Use the following:

echo y | C:\script\PLINK\plink.exe -pw "Password of the user" "Username@ServerName" "Command you want to run"

Second tip

When you save an output from PLINK to a PowerCLI variable, formatting it is not straightforward. Let’s have a look at example. Below is an output from Dell Remote Access Control (DRAC):

PowerCLI C:\script\plink> .\PLINK.EXE -pw ""root@10.10.10.1" "racadm getniccfg"
IPv4 settings:
 NIC Enabled = 1
 IPv4 Enabled = 1
 DHCP Enabled = 0
 IP Address = 10.10.10.1
 Subnet Mask = 255.255.255.0
 Gateway = 10.10.10.254
IPv6 settings:
 IPv6 Enabled = 0
 DHCP6 Enabled = 1
 IP Address 1 = ::
 Gateway = ::
 Link Local Address = ::
 IP Address 2 = ::
 IP Address 3 = ::
 IP Address 4 = ::
 IP Address 5 = ::
 IP Address 6 = ::
 IP Address 7 = ::
 IP Address 8 = ::
 IP Address 9 = ::
 IP Address 10 = ::
 IP Address 11 = ::
 IP Address 12 = ::
 IP Address 13 = ::
 IP Address 14 = ::
 IP Address 15 = ::
LOM Status:
 NIC Selection = Dedicated
 Link Detected = Yes
 Speed = 100Mb/s
 Duplex Mode = Full Duplex

Let’s say you would like to pull out network settings, i.e. IP address/Subnet Mask/Gateway, how could we pull only three elements out? First of all, save the output to a variable:

PowerCLI C:\script\plink> $output = .\PLINK.EXE -pw ""root@10.10.10.1" "racadm getniccfg"

Good news is that the output is saved as an array, not to a single line meaning you could do the following:

PowerCLI C:\script\plink> $output[5]
IP Address = 10.10.10.1
PowerCLI C:\script\plink> $output[6]
Subnet Mask = 255.255.255.0
PowerCLI C:\script\plink> $output[7]
Gateway = 10.10.10.254

Then you could simply use -replace and -split functions to get the information you are after:

PowerCLI C:\script\plink> $output[5] -replace " "
IPAddress=10.10.10.1 

PowerCLI C:\script\plink> ($output[5] -replace " ") -split "="
IPAddress
10.10.10.1

PowerCLI C:\script\plink> $ipaddress = (($output[5] -replace " ") -split "=")[1]
PowerCLI C:\script\plink> $ipaddress
10.10.10.1

Not a simple way but it’s achievable.

Let’s take a look at another example. This time, it’s an output from IBM SVC:

PowerCLI C:\script\plink> .\PLINK.EXE -pw "Password!" "UserName@ServerName" "lsvdisk"
id name             IO_group_id IO_group_name status mdisk_grp_id mdisk_grp_name capacity type    FC_id FC_name RC_id RC_name vdisk_UID                        fc_map_count copy_count fast_write_state se_copy_count RC_change compressed_copy_count
0  vDisk1           0           io_grp0       online 0            MDISK1         1.00TB   striped                             6005076812345678A000000000000000 0            1          not_empty        0             no        0
1  vDisk2           0           io_grp0       online 1            MDISK2         1.00TB   striped                             6005076812345678A000000000000003 0            1          empty            0             no        0

Referring to the output, it won’t be as easy as the first example since the elements are separated with spaces that varies.

Thinking about the SVC command, it has the parameter to output with delimiter, i.e. CSV output:

PowerCLI C:\script\plink> .\PLINK.EXE -pw "Password!" "Username@ServerName" "lsvdisk -delim ,"PowerCLI C:\script\plink> output.csv
id,name,IO_group_id,IO_group_name,status,mdisk_grp_id,mdisk_grp_name,capacity,type,FC_id,FC_name,RC_id,RC_name,vdisk_UID,fc_map_count,copy_count,fast_write_state,se_copy_count,RC_change,compressed_copy_count
0,vDisk1,io_grp0,online,0,MDISK1,striped,,,,,6005076812345678A000000000000000,0,1,not_empty,0,no,0
1,vDisk2,io_grp0,online,1,MDISK2,striped,,,,,6005076812345678A000000000000003,0,1,empty,0,no,0

Why would you want to output with delimiter “,”? The reason is simple, PowerCLI has CSV function Import-CSV and using this, formatting the output will be quite easy:

  1. > to save the output as a CSV file
  2. Then, run Import-Csv
PowerCLI C:\script\plink> $output > test.csv
PowerCLI C:\script\plink> Import-Csv .\test.csv

Now, you will see formatted output:

id                    : 0
name                  : vDisk1
IO_group_id           : 0
IO_group_name         : io_grp0
status                : online
disk_grp_id           : 0
mdisk_grp_name        : MDISK1
capacity              : 1.00TB
type                  : striped
FC_id                 :
FC_name               :
RC_id                 :
RC_name               :
vdisk_UID             : 6005076812345678A000000000000000
fc_map_count          : 0
copy_count            : 1
fast_write_state      : not_empty
se_copy_count         : 0
RC_change             : no
compressed_copy_count : 0

id                    : 1
name                  : vDisk2
IO_group_id           : 0
IO_group_name         : io_grp0
status                : online
mdisk_grp_id          : 1
mdisk_grp_name        : MDISK2
capacity              : 1.00TB
type                  : striped
FC_id                 :
FC_name               :
RC_id                 :
RC_name               :
vdisk_UID             : 6005076812345678A000000000000003
fc_map_count          : 0
copy_count            : 1
fast_write_state      : empty
se_copy_count         : 0
RC_change             : no
compressed_copy_count : 0

This is a way of formatting the output nice and simple. One thing to note is that it will save the output to your local disk, e.g. C drive. I suggest you to delete the file once you save it to a variable, like this:

PowerCLI C:\script\plink> .\PLINK.EXE -pw "Password!" "Username@ServerName" "lsvdisk -delim ,"PowerCLI C:\script\plink> output.csv
PowerCLI C:\script\plink> $output = Import-Csv output.csv
PowerCLI C:\script\plink> Remove-Item output.csv

Time to go through examples.

Example 1

I already wrote a blog post Virtual Machines running on vDisks in relationships. The purpose of this report was to find which virtual machines are mapped with VMFS volumes that are in Metro Mirror relationship, i.e. synchronous replication. Why would you need PLINK for this?

Even though the naming convention across VMFS volumes is solid to represent which ones are in relation, administrators make mistakes. Meaning that if there are VMFS volumes with wrong naming convention, then the report will not be accurate. Hence, I decided to match against UID so the report is 100% right! For more information, refer to the link attached above.

Example 2

To check custom services running on ESXi servers:

PowerCLI C:\script\plink> Get-VMHostService -VMHost (Get-VMHost -Name "ESXi.test.com")
Key Label Policy Running Required
--- ----- ------ ------- --------
DCUI Direct Console UI on True False
TSM ESXi Shell off False False
TSM-SSH SSH on True False
lbtd lbtd on True False
lsassd Local Security Authenticati... off False False
lwiod I/O Redirector (Active Dire... off False False
netlogond Network Login Server (Activ... off False False
ntpd NTP Daemon on True False
sfcbd-watchdog CIM Server on True False
snmpd snmpd on False False
vmware-fdm vSphere High Availability A... off False False
vprobed vprobed off False False
vpxa vpxa on True False
xorg xorg on False False

How about if there is a custom VIB installed, for example HP AMS and want to check the status? Unfortunately, Get-VMHostService won’t show this.

The way of checking the status is, SSH to ESXi directly and run /etc/init.d/hp-ams.sh status:

PowerCLI C:\script\plink> .\PLINK.EXE -pw "Password!" "Username@ESXiServer" "/etc/init.d/hp-ams.sh status"

Wrap-Up

Hope the PowerCLI Report Tip series helped and in near future, I will come back with PowerCLI automation tips.

As always, feel free to leave a comment for any clarifications.

PowerCLI Report Tip – Part 3

Introduction

For PowerCLI tip part 3, it will be going through advanced reporting using ESXCLI.

For the contents below, the version of ESXi server used was 5.5 No Update.

What’s ESXCLI?

I suggest you to go and read the following blogs:

Why ESXCLI For Reporting?

PowerCLI itself already has most of the functions to generate a report. However, there are some ESXCLI commands that could be used to produce a report in a faster and easier way. This will be discussed in the later sections with specific examples (scenarios).

In this blog post, there will be two examples discussed:

  1. Storage 
  2. Network & Firewall

Preparation

Before starting, one of the advantages of running ESXCLI through PowerCLI is that SSH does not have to be enabled. But, it requires certain roles so might as well run it with Read-Only account and add permissions accordingly.

First of all, let’s run and save ESXCLI to a variable $esxcli = Get-VMHost -Name “ESXi” | Get-ESXCLi. Then, calling $esxcli will output the following:

PowerCLI C:\> $esxcli
===============================
EsxCli: esx01.test.com

Elements:
---------
device
esxcli
fcoe
graphics
hardware
iscsi
network
sched
software
storage
system
vm
vsan

The output looks very similar to running ESXCLI on ESXi shell. The difference is, for example, if you want to call storage object, then you run $esxcli.storage. No space in between, i.e. esxcli storage. 

With the preparation work above, we are ready to go through some examples! 🙂

Storage

Let’s give an example. There is a request from storage team to generate a report across all VMFS volumes (mapped with FC disk), literally same as the following screenshot:
PowerCLI Report Tip #3 1
 

NOTE: For the report below, I am assuming the virtual disks from storage array are mapped to all ESXi servers in a cluster (Well I guess this is usual for most of people to benefit from HA/DRS).

Looking at above screenshot, the report should contain:

  • Cluster
  • Adapter, e.g. vmhba2 or vmhba3
  • Device, i.e. UID
  • TargetIdentifier, e.g. 50:05:07……
  • RuntimeName, e.g. C0:T1:L11
  • LUN, e.g. 11
  • State, e.g. Active

Using ESXCLI, it could be achieved quite simply.  Assuming you already have saved ESXCLI value to a variable $esxcli, save the following to variables accordingly:

  • $esxcli.storage.core.path.list()
    • It outputs the list of all paths of storage devices attached to this ESXi server.
  • $esxcli.storage.core.device.list()
    • It outputs the list of all storage devices attached to this ESXi server.

Then, using the device list, filter it to query only Fibre Channel devices and for each of them, if the list of path match to this device, select elements.

Combining above it becomes:

$path_list = $esxcli.storage.core.path.list()
$device_list = $esxcli.storage.core.device.list()
$vmfs_list = $esxcli.storage.vmfs.extent.list() 
$cluster = Get-Cluster -VMHost (Get-VMHost -Name $esxcli.system.hostname.get().FullyQualifiedDomainName)

$device_list | where {$_.DisplayName -match "Fibre Channel"} | ForEach-Object { $device = $_.Device; $path_list | where {$_.device -match $device} | select @{N=“Cluster”;E={$cluster.Name}}, Adapter, Device, TargetIdentifier, RuntimeName, LUN, State }

Example Output:

Cluster : Development
Adapter : vmhba3
Device : naa.60050768018d8303c000000000000003
TargetIdentifier : fc.5005076801000002:5005076801100002
RuntimeName : vmhba3:C0:T0:L11
LUN : 11
State : active

Cluster : Development
Adapter : vmhba3
Device : naa.60050768018d8303c000000000000003
TargetIdentifier : fc.5005076801000001:5005076801100001
RuntimeName : vmhba3:C0:T1:L11
LUN : 11
State : active 

Cluster : Development
Adapter : vmhba2
Device : naa.60050768018d8303c000000000000003
TargetIdentifier : fc.5005076801000002:5005076801200002
RuntimeName : vmhba2:C0:T0:L11
LUN : 11
State : active

Cluster : Development
Adapter : vmhba2
Device : naa.60050768018d8303c000000000000003
TargetIdentifier : fc.5005076801000001:5005076801200001
RuntimeName : vmhba2:C0:T1:L11
LUN : 11
State : active

Quite easy, isn’t it?

Another example: virtualisation team manager asked for virtual disks (FC type) that are attached to ESXi servers but not formatted as VMFS. To make it more specific, he was expecting the following:

  • Cluster
  • Device
  • Device file system path
  • Display Name
  • Size

With the report above, it would be very handy to identify which virtual disks are being wasted.

Using ESXCLI, above report could be accomplished simply. Save the following to variables accordingly:
  • $esxcli.storage.core.path.list()
    • It outputs the list of all paths of storage devices attached to this ESXi server.
  • $esxcli.storage.vmfs.extent.list()
    • It outputs the list of all storage devices partitioned (formatted) with VMFS volumes attached to this ESXi server.

Using device list, run a where filter to:

  • Make sure this device is not formatted as VMFS
    • I used -match against all VMFS volumes joined by | which means or
  • The type is Fibre Channel

Combining above, it will become:

$device_list = $esxcli.storage.core.device.list()
$vmfs_list = $esxcli.storage.vmfs.extent.list()
$cluster = Get-Cluster -VMHost (Get-VMHost -Name $esxcli.system.hostname.get().FullyQualifiedDomainName)

$device_list | where {$_.Device -notmatch ([string]::Join("|", $vmfs_list.DeviceName)) -and $_.DisplayName -match "Fibre Channel" } | select @{N="Cluster";E={$cluster.Name}}, Device, DevfsPath, DisplayName, @{N="Size (GB)";E={$_.Size / 1024}}

Example Attached:

Cluster : Development
Device : naa.60050768018d8303c000000000000006
DevfsPath : /vmfs/devices/disks/naa.60050768018d8303c000000000000006
DisplayName : IBM Fibre Channel Disk (naa.60050768018d8303c000000000000006)
Size (GB) : 128
Hope the examples above were easy to follow and let us move on to Network.

Network

In this Network section, I will be giving two examples with:

  1. Firewall
  2. LACP

Let’s start with Firewall.

One of the VMware administrators deployed vRealize Log-Insight and before configuring ESXi servers to point to Log-Insight, he wanted to check the allowed IP addresses configured before and remove them in advance. It was configured to restrict access to syslog server for security purpose.

This time, it will be using $esxcli.network.firewall command. First of all, save the list of ruleset with allowedIP addresses:

  • $esxcli.network.firewall.ruleset.allowedip.list()

Then, use the filter to query only syslog service. Combining above:

$esxi= $esxcli.system.hostname.get().FullyQualifiedDomainName
$ruleset_list = $esxcli.network.firewall.ruleset.allowedip.list() 
$ruleset_list | where {$_.ruleset -eq "syslog"} | select @{N="ESXi";E={$esxi}}, Ruleset, AllowedIPAddresses

Example output:

ESXi : esx01.test.com
Ruleset : syslog
AllowedIPAddresses : {10.10.1.10}

Another example: network team wanted an output from ESXi servers to check the following:

  1. Check the status of LACP DUs, i.e. transmit/receive and see if there are any errors
  2. Check LACP configuration, especially the LACP period. Either fast or slow

I wrote an article about Advanced LACP Configuration using ESXCLI, I suggest you to read it if not familiar with LACP configuration on ESXi.

Similar to above, save the LACP stats to a variable and select the following:

  • Name of ESXi
  • Name of dvSwitch
  • NIC, e.g. vmnic0
  • Receive errors
  • Received LACPDUs
  • Transmit errors
  • Transmitted LACPDUs

And the script would be:

$esxi= $esxcli.system.hostname.get().FullyQualifiedDomainName
$lacp_stats = $esxcli.network.vswitch.dvs.vmware.lacp.stats.get()
$lacp_stats | select @{N="ESXi";E={$esxi}}, DVSwitch, NIC, RxErrors, RxLACPDUs, TxErrors, TxLACPDUs

Example Output:

ESXi : esx01.test.com
DVSwitch : dvSwitch_Test
NIC : vmnic1
RxErrors : 0
RxLACPDUs : 556096
TxErrors : 0
TxLACPDUs : 555296
ESXi : esx01.test.com
DVSwitch : dvSwitch_Test
NIC : vmnic0
RxErrors : 0
RxLACPDUs : 556096
TxErrors : 0
TxLACPDUs : 555296

For the configuration report, you might be interested in Fast/Slow LACP period as mentioned above.

Similarly, save the LACP status output to a variable. Then for each object pointing to NicList, select the following:

  • Name of ESXi server
  • Name of dvSwitch
  • Status of LACP
  • NIC, e.g. vmnic0
  • Flag Description
  • Flags

Combining above:

$esxi= $esxcli.system.hostname.get().FullyQualifiedDomainName
$information = $esxcli.network.vswitch.dvs.vmware.lacp.status.get()

$information.NicList | ForEach-Object { $_ | Select @{N="ESXi";E={$esxi}}, @{N="dvSwitch";E={$information.dvSwitch}}, @{N="LACP Status";E={$information.Mode}}, Nic, @{N="Flag Description";E={$information.Flags}}, @{N="Flags";E={$_.PartnerInformation.Flags}} }

Example Output:

ESXi : esx01.test.com
dvSwitch : dvSwitch_Test
LACP Status : Active
Nic : vmnic1
Flag Description : {S - Device is sending Slow LACPDUs, F - Device is sending fast LACPDUs, A - Device is in active mode, P - Device is in passive mode}
Flags : SA

ESXi: esx01.test.com
dvSwitch : dvSwitch_Test
LACP Status : Active
Nic : vmnic0
Flag Description : {S - Device is sending Slow LACPDUs, F - Device is sending fast LACPDUs, A - Device is in active mode, P - Device is in passive mode}
Flags : SA

With the report above, network team could find out which ESXi server is configured with Fast or Slow so that they could configure the LACP accordingly (LACP period mis-match is not good!).

Wrap-Up

In this blog post, it discussed the way of using ESXCLI command to generate an advanced report. I didn’t go through properties deeply as I discussed in Part 2 and you could slowly take a look properties on your own.

Hope it was easy enough to follow and understand. On the next series, I will be discussing how to use PLINK to generate a combined report with ESXi and non ESXi.

Always welcome for for you to leave a reply for any questions or clarifications.

PowerCLI Report Tip – Part 2

Introduction

In this blog post, I will be deep-diving into the following to improve your report:

  • Select *
  • ExtensionData (also known as Get-View)

This is the second series continued from Part 1 which could be found here.

Select *

Select is used to filter an output. For example, Get-VM | Select Name, NumCPU, MemoryGB would give you 3 properties only. What would Select * give you? In regular expression world ,* normally means “everything” and the output is attached below:

PowerState : PoweredOn
Version : v9
Description :
Notes :
Guest : testVM
NumCpu : 4
MemoryMB : 2048
MemoryGB : 2
HardDisks : {Hard disk 1}
NetworkAdapters : {Network adapter 1}
UsbDevices : {}
CDDrives : {CD/DVD drive 1}
FloppyDrives : {Floppy drive 1}
Host : esxi1.test.com
HostId : HostSystem-host-19843
VMHostId : HostSystem-host-19843
VMHost : esxi1.test.com
VApp :
FolderId : Folder-group-v23748
Folder : TestFolder
ResourcePoolId : ResourcePool-resgroup-22471
ResourcePool : Resources
PersistentId : 501c2be6-da23-928f-7d58-e278c8a2cf62
UsedSpaceGB : 102.13691748306155204772949219
ProvisionedSpaceGB : 102.13691792357712984085083008
DatastoreIdList : {Datastore-datastore-24700}
HARestartPriority : ClusterRestartPriority
HAIsolationResponse : AsSpecifiedByCluster
DrsAutomationLevel : AsSpecifiedByCluster
VMSwapfilePolicy : Inherit
VMResourceConfiguration : CpuShares:Normal/4000 MemShares:Normal/20480
GuestId : debian6Guest
Name : testVM
CustomFields :
ExtensionData : VMware.Vim.VirtualMachine
Id : VirtualMachine-vm-25976
Uid : /VIServer=administrator@vcenter.test.com:443/VirtualMachine=VirtualMachine-vm-25976/
Client : VMware.VimAutomation.ViCore.Impl.V1.VimClient

The reason I wanted to go through Select * is to show you guys that Get-VM function itself has a lot of properties already. Let’s take a look at a report below:

ESXi,ResourcePool,VM,CPU,Memory
ESXi_test1,RP1,test1,1,1
ESXi_test1,RP2,test2,1,1
ESXi_test2,RP2,test3,1,4

Without knowing the properties well, to generate the report above, some might come up with a script like the following:

foreach ($vm in Get-VM) {
 $resourcepool = Get-ResourcePool -VM $vm
 $esxi = Get-VMHost -VM $vm
 $vm | Select @{N=“ESXi”;E={$esxi.Name}}, @{N=“ResourcePool”;E={$resourcepool.Name}}, Name, NumCPU, MemoryGB
}

The above script looks good, it has no problem. But looking at properties, some of them could actually be retrieved from Get-VM, i.e. without running the commands Get-ResourcePool and Get-VMHost. Let’s do some performance testing. For the testing, I selected a cluster with 300 virtual machines and with the script above, it has taken 62 minutes. Suppose there are 10000 virtual machines, I do not want to imagine that. Using the properties already queried (script attached below), it improved the script significantly. It took 28 seconds. Seconds, not minutes!

Get-VM | Select @{N=“ESXi”;E={$_.VMHost.Name}}, @{N=“ResourcePool”;E={$_.ResourcePool}}, Name, NumCPU, MemoryGB

The point here I made is that since Get-VM itself already runs Get-ResourcePool, Get-VMHost, do not run them again! Otherwise, it will significantly reduce the performance of your script. It’s not only for Get-VM, it could be Get-Cluster, Get-VMHost and so on. I strongly recommend you to get familiar with properties.

ExtensionData

ExtensionData, also known as Get-View is another property that I would want to talk about. I will take Get-VMHost as an example this time and the following two commands produce the same output:

  • Get-VMHost -Name esxi1.test.com | Get-View
  • (Get-VMHost -Name esxi1.test.com).ExtensionData
Runtime : VMware.Vim.HostRuntimeInfo
Summary : VMware.Vim.HostListSummary
Hardware : VMware.Vim.HostHardwareInfo
Capability : VMware.Vim.HostCapability
LicensableResource : VMware.Vim.HostLicensableResourceInfo
ConfigManager : VMware.Vim.HostConfigManager
Config : VMware.Vim.HostConfigInfo
Vm : {VirtualMachine-vm-7950, VirtualMachine-vm-7941, VirtualMachine-vm-4299, VirtualMachine-vm-4583...}
Datastore : {Datastore-datastore-3500, Datastore-datastore-3501, Datastore-datastore-3502, Datastore-datastore-3503...}
Network : {DistributedVirtualPortgroup-dvportgroup-7890, DistributedVirtualPortgroup-dvportgroup-4523, DistributedVirtualPortgroup-dvportgroup-4580, DistributedVirtualPortgroup-dvportgroup-3272...}
DatastoreBrowser : HostDatastoreBrowser-datastoreBrowser-host-7674
SystemResources : VMware.Vim.HostSystemResourceInfo
LinkedView :
Parent : ClusterComputeResource-domain-c3265
CustomValue : {}
OverallStatus : green
ConfigStatus : green
ConfigIssue : {}
EffectiveRole : {285213786}
Permission : {}
Name : esxi1.test.com
DisabledMethod : {ExitMaintenanceMode_Task, PowerUpHostFromStandBy_Task, ReconnectHost_Task}
RecentTask : {}
DeclaredAlarmState : {alarm-1.host-7674, alarm-12.host-7674, alarm-13.host-7674, alarm-14.host-7674...}
TriggeredAlarmState : {}
AlarmActionsEnabled : True
Tag : {}
Value : {}
AvailableField : {}
MoRef : HostSystem-host-7674
Client : VMware.Vim.VimClientImpl

It looks quite complex but actually it’s not. Let us take a look at one example:

  • (Get-VMHost -Name esxi1.test.com).ExtensionData.Hardware
SystemInfo : VMware.Vim.HostSystemInfo
CpuPowerManagementInfo : VMware.Vim.HostCpuPowerManagementInfo
CpuInfo : VMware.Vim.HostCpuInfo
CpuPkg : {0 1 2 3 4 5 6 7 8 9 10 11, 12 13 14 15 16 17 18 19 20 21 22 23}
MemorySize : 206144823296
NumaInfo : VMware.Vim.HostNumaInfo
SmcPresent : False
PciDevice : {00:00.0, 00:01.0, 00:03.0, 00:04.0...}
CpuFeature : {VMware.Vim.HostCpuIdInfo, VMware.Vim.HostCpuIdInfo, VMware.Vim.HostCpuIdInfo, VMware.Vim.HostCpuIdInfo...}
BiosInfo : VMware.Vim.HostBIOSInfo
ReliableMemoryInfo :
DynamicType :
DynamicProperty :

The output above is representing hardware details of this ESXi server. Isn’t it surprising? Single PowerCLI command could generate a report with a lot of information if you know the properties well enough.

This is how you generate advanced reports and it’s quite simple to achieve that – get familiar with properties especially ExtensionData. I will leave the rest to you guys to play with, such as BiosInfo, SystemInfo and so on.

Wrap-Up

Throughout the blog, it discussed:

  • Taking a closer look at Select * to avoid running repeated commands
  • Generating advanced reports with ExtensionData

Hope this helps and on the next series, I will be deep-diving into esxcli