Documentation is an important part of the automation and development process. When I first started using PowerCLI, I found the docs to be overwhelming and confusing. As my PowerCLI knowledge grew, I started to use them more and more. Instead of frustratingly browsing the multiple levels of properties that make up vCenter objects in a terminal, I found I could easily pick them out in the docs. As part of this blog post, we’re going to walk through the available documentation, which documentation should be used at what points, and then walk-through two use cases of using the documentation to perform a task.
PowerCLI Objects
PowerCLI allows us to access two different types of objects, .Net and vSphere. It’s important to know about these two object types and how to interact with them to understand what documentation should be used at what points.
To summarize the two objects quickly, the .Net objects are what PowerCLI high-level cmdlets interact with. Example: Get-VM returns back a UniversalVirtualMachineImpl .Net object. The vSphere objects are what the low-level cmdlets interact with, which is a direct connection to the vSphere Web Services API. These vSphere objects are accessible through Get-View and when referencing a .Net object’s ExtensionData property. Example: (Get-VM).ExtensionData returns back a VirtualMachine vSphere object.
If there’s a question about what object type we’re interacting with, we can verify the object type by using either the object level method of ‘GetType’ or with the ‘Get-Member’ cmdlet. Here’s how we can use the GetType method against the three examples I’ve already mentioned:
These two object types also have their own sets of documentation. The .Net objects are available in the “Types” section of the PowerCLI Cmdlet Reference. The vSphere objects are available in the vSphere Web Services API Reference. The vSphere API has two main object types we’ll want to become familiar with, Managed Objects and Data Objects. Think of Managed Objects as the top-level inventory items, such as Datacenters, Clusters, Hosts, and VMs. It’s also worth noting that Managed Objects can also be services, such as the EventManager and ScheduledTaskManager, but we won’t be using them as part of this blog post. We can then think of Data Objects as the child objects that make up the top-level Managed Objects.
If you want to learn some more about these two objects and how they pertain to PowerCLI, PowerCLI mastermind Luc Dekens and I walked through these in a VMworld session last year: A Deep(er) Dive with PowerCLI 10 (VIN1992BE)
Documentation Lingo
At first glance, the documentation for both PowerCLI and the vSphere APIs can be a little overwhelming. There’s a lot of information available to consume. Let’s cover the main sections that are consistently available for both object types. These sections are: Property of, Parameter to, Returned by, Extends and/or Extended by, and Properties. “Property of” means that this particular object will be returned as a property for the listed objects. “Parameter to” means this object can be used as input for a particular cmdlet and/or method. “Returned by” means that a particular object will be the response by a cmdlet and/or method. Then we have “Extends” and/or “Extended by”, which is interesting because these can actually add properties to the given object which may not be listed in the documentation since it can change based on the object being referenced. Lastly, there are the “Properties” which are the items and objects that make up each object. Every time you get an object based response in PowerCLI, you’ll find those properties.
Next, we’re going to put all of this information to use in order to solve an issue where we’re looking for more information about a VM’s disk space and its associated filesystem.
Disk Space Utilization – .Net Object
For the first object type, we’ll be working with the .Net objects. We’ll want to start by referencing the PowerCLI documentation, known as the cmdlet reference. Instead of diving right in on the cmdlet list, we’re going to instead take a look at the Types. Since, at the root of the request, we’re looking for information about a VM, we’ll start with the VirtualMachine object. There, we can see all of the available properties including some that are relevant to our task such as: HardDisks, UsedSpaceGB, and ProvisionedGB. We can also take note of a deprecation notice for the HardDisks property which, as part of the Type column, refers us to the HardDisk object. Moving to the HardDisk object page, we can see some additional properties we might want to reference by the names of CapacityGB and CapacityKB. We’re not quite ready to move to coding just yet, we haven’t found any filesystem information. There’s one other section, that’s part of the VirtualMachine object, we should explore. This is the VMGuest object. Here we can see properties that have been pulled from VMware Tools, including one very interesting property for the our task: Disks. This property is related to the DiskInfo object. On the DiskInfo object page, we can see properties such as Path, Capacity, FreeSpace, CapacityGB, and FreeSpaceGB.
Quick recap, based on the request for hard disk and filesystem of a VM, we’re going to be interested in the following properties:
Object | Property |
---|---|
VirtualMachine | UsedSpaceGB |
VirtualMachine | ProvisionedSpaceGB |
HardDisk | CapacityGB |
DiskInfo | Path |
DiskInfo | CapacityGB |
DiskInfo | FreeSpaceGB |
We now know what information we’re looking to retrieve, so we can start figuring out what code we can use to retrieve this information. The two main areas we’ll be concerned with are the “Property of” and “Returned by” sections. For the first two properties, we can use the Get-VM cmdlet to return those. Due to the deprecation of the HardDisk property, we have to use the Get-HardDisk cmdlet to return CapacityGB. Then, for our last three properties, we can use the output from the original Get-VM cmdlet. We know this because the DiskInfo object is a property of VMGuest, which just happens to be a property of VirtualMachine.
We can break it down to be the following properties:
Cmdlet | Property Path |
---|---|
Get-VM | UsedSpaceGB |
Get-VM | ProvisionedSpaceGB |
Get-HardDisk | CapacityGB |
Get-VM | Guest – Disks – Path |
Get-VM | Guest – Disks – CapacityGB |
Get-VM | Guest – Disks – FreeSpaceGB |
Here’s what it looks like in PowerCLI code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Populating variables with required cmdlets $vm = Get-VM -Name $vmName $hardDisk = Get-HardDisk -VM $vm # Creating a new PowerShell custom object to easily output properties $output = New-Object -TypeName PSCustomObject # Adding desired properties to the new PowerShell object Add-Member -InputObject $output -MemberType NoteProperty -Name UsedSpaceGB -Value $vm.UsedSpaceGB Add-Member -InputObject $output -MemberType NoteProperty -Name ProvisionedSpaceGB -Value $vm.ProvisionedSpaceGB Add-Member -InputObject $output -MemberType NoteProperty -Name CapacityGB -Value $hardDisk.CapacityGB Add-Member -InputObject $output -MemberType NoteProperty -Name GuestPath -Value $vm.Guest.Disks.Path Add-Member -InputObject $output -MemberType NoteProperty -Name GuestCapacityGB -Value $vm.Guest.Disks.CapacityGB Add-Member -InputObject $output -MemberType NoteProperty -Name GuestFreeSpaceGB -Value $vm.Guest.Disks.FreeSpaceGB # Viewing the output $output |
Here’s what it looks like in our PowerShell session:
Disk Space Utilization – vSphere Object
For the second object type, we’ll be working with the vSphere objects. vSphere objects are vSphere Web Services API based, which means that we’ll be using a different set of documents to pull the same data. This document is known as the vSphere Web Services API Reference.
Taking a look at our request from the vSphere API level, we will again want to start at the VirtualMachine Managed Object. We can immediately notice a larger amount of data available to consume, since accessing the API gives us access to all of the available information. We’ll first want to start in the storage property, which leads us to the VirtualMachineStorageInfo data object. We can see there’s a property of perDatastoreUsage which is related to the VirtualMachineUsageOnDatastore object. This object has two properties we’re interested in, committed and uncommitted. The committed property will represent the used space amount, while the sum of committed and uncommitted will represent the provisioned space amount. Note, both of those properties are referenced in bytes so there will need to be some conversion done later.
Next, we’re looking for information about the hard disk itself. This is a multi-step process. Referencing the VirtualMachine object, we can see the layoutEx property contains information about the files that comprise a VM. The layoutEx property aligns with the VirtualMachineFileLayoutEx object, which has the property of disk. This disk property aligns with the VirtualMachineFileLayoutExDiskLayout object which gives us a key property. By reading the description of the key property, we can see that this key matches up to a VirtualDevice object which also has a key property. In reading through the available properties, we’re missing the property we’re looking for, which is a capacity-based property. This is where the ‘DynamicData’ comes into play. At the bottom of the properties, it specifies that some additional properties could be inherited by “DynamicData”. This is where the “Extended by” section comes into play. For our request, we can see that the VirtualDevice object is extended by the VirtualDisk object. When we look at the VirtualDisk object, we see the property that we’re looking for: capacityInBytes! At this point, we have our property but we don’t know how to retrieve it. Using the “Property of” section, we can backtrack to the VirtualMachine object. VirtualDisk is extended by the VirtualDevice object. The VirtualDevice object is a property of the VirtualHardware object. The VirtualHardware object is a property of the VirtualMachineConfigInfo object. Which takes us back to the VirtualMachine object, since the VirtualMachineConfigInfo is a property of the VirtualMachine object.
Last, we’re looking for filesystem-based information. Similarly to the .Net object, the VirtualMachine object has a guest property which is a GuestInfo object. The GuestInfo object has a property of disk, which is a GuestDiskInfo object. The GuestDiskInfo object has the capacity, diskPath, and freeSpace properties we’re looking for.
Attempting a quick recap, based on the request for hard disk and filesystem of a VM, we’re going to be interested in the following properties of the vSphere objects:
Object | Property |
---|---|
VirtualMachineUsageOnDatastore | committed |
VirtualMachineUsageOnDatastore | uncommitted |
VirtualMachineFileLayoutExDiskLayout | key |
VirtualDisk | capacityInBytes |
GuestDiskInfo | diskPath |
GuestDiskInfo | capacity |
GuestDiskInfo | freeSpace |
Since we’re only going to be working with the root VirtualMachine object, we can move right over to the code. We can access the vSphere object in two ways, either through the usage of the Get-View cmdlet or through an object’s Extension Data. Once we have established that object in a variable, the experience is the same.
The two ways to retrieve the vSphere object for a particular VM can actually be extended into three ways, depending on what you are most comfortable with:
1 2 3 4 5 6 7 8 |
# Option 1: Using a .Net object’s ExtensionData $vm = Get-VM -Name $vmName $vm.ExtensionData # Option 2: Piping a .Net object to the Get-View cmdlet $vm = Get-VM -Name $vmName $vmView = $vm | Get-View # Option 3: Using Get-View and filtering for the desired VM Get-View -ViewType VirtualMachine -Filter @{"Name" = $vmname} |
We can break it down to be the following cmdlets and properties:
Cmdlet | Property Path |
---|---|
Get-VM | Get-View | storage – perDatastoreUsage – committed |
Get-VM | Get-View | storage – perDatastoreUsage – uncommitted |
Get-VM | Get-View | layoutEx – disk – key |
Get-VM | Get-View | config – hardware – device – capacityInBytes |
Get-VM | Get-View | guest – disk – diskPath |
Get-VM | Get-View | guest – disk – capacity |
Get-VM | Get-View | guest – disk – freeSpace |
Here’s what it looks like in PowerCLI code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Establishing the connection to our vSphere object $vm = Get-VM -Name $vmName $vmView = $vm | Get-View # Creating a new PowerShell custom object to easily output properties $output = New-Object -TypeName PSCustomObject # Adding desired properties to the new PowerShell object $diskCommit = $vmView.Storage.PerDatastoreUsage.Committed $diskUncommit = $vmView.Storage.PerDatastoreUsage.Uncommitted Add-Member -InputObject $output -MemberType NoteProperty -Name UsedSpaceGB -Value ($diskCommit / 1GB) Add-Member -InputObject $output -MemberType NoteProperty -Name ProvisionedSpaceGB -Value (($diskCommit + $diskUncommit) / 1GB) $diskKey = $vmView.LayoutEx.Disk.Key $diskCapacity = $vmView.Config.Hardware.Device | Where-Object {$_.key -eq $diskKey} | Select-Object -ExpandProperty capacityInBytes Add-Member -InputObject $output -MemberType NoteProperty -Name CapacityGB -Value ($diskCapacity / 1GB) Add-Member -InputObject $output -MemberType NoteProperty -Name GuestPath -Value $vmView.Guest.Disk.DiskPath Add-Member -InputObject $output -MemberType NoteProperty -Name GuestCapacityGB -Value ($vmView.Guest.Disk.Capacity / 1GB) Add-Member -InputObject $output -MemberType NoteProperty -Name GuestFreeSpaceGB -Value ($vmView.Guest.Disk.FreeSpace / 1GB) # Viewing the output $output |
Here’s what it looks like in our PowerShell session:
Summary
Documentation is often an overlooked part of the PowerCLI development process. PowerCLI allows us to work with both it’s own set of objects as well as the entire set of vSphere API objects! This blog post discussed the differences between those objects, where to find the documentation to interact with those objects, how to read the documentation, and wrapped up with an example of fulfilling a request using both types of objects.
Let us know in the comments what type of scenario you would like walked through for the next documentation based blog post!