Getting detailed VM Disk Properties from the vCloud API
Since vCloud Director 8.10 VMware have allowed VMs to be created which have multiple disks using different storage policies. This can be very useful – for example, a database VM might have it’s database on fast storage but another disk containing backups or logs on slower/cheaper disk.
When trying to find out what storage is in use for a VM though this can create issues, the PowerCLI Get-CIVM cmdlet (and the Get-CIView cmdlet used to get extra information) aren’t able to properly report storage for VMs that consume multiple storage policies. This in turn can create problems for Service Providers when they need to report on overall VM disk usage divided by storage policy used.
As an example I’ve created a VM named ‘test01’ in a customer vDC which has 3 disks attached, the 2nd of these is on ‘Capacity’ tier storage while disks 1 and 3 are on ‘Performance’ storage. When we look at the VM details we see the following:
Digging into the ExtensionData shows
The StorageProfile element looks like it may contain what we need, but unfortunately this only shows the ‘home’ Storage for the VM and doesn’t indicate that at least one of the VMs disks is on a different storage profile:
After a lot of mucking around trying to find an easy way to discover the information, I ‘gave up’ and wrote a PowerShell module which accesses the vCD API directly to get the VM storage information (including storage tiers in use by each disk). The module isn’t overly efficient since it queries the storage profile reference for every disk on every VM (and so will result in a lot of calls if run for a large number of VMs), but otherwise works fine.
The module takes VM objects or a VM name as input and returns details on each disk attached to the VM including which storage profile they use. Save the script (e.g. as ‘Get-CIVMStorageProfile.psm1’) and then use ‘Import-Module .\Get-CIVMStorageProfile.psm1’ to import the function.
1<#
2 .Synopsis
3 Gets detailed storage information from a vCloud VM.
4
5.Description
6 This function returns detailed disk information for a vCloud VM. Specifically
7 it shows the number of disks attached and the storage policy assigned to each
8 disk which is useful when VMs consume storage from multiple policies.
9
10.Parameter CIVM
11 The VM object (from Get-CIVM) to report storage for.
12
13.Example
14 Get-CIVM -Name 'test01' | Get-CIVMStorageDetail
15#>
16
17Function Get-CIVMStorageDetail
18{
19 [CmdletBinding()]
20 Param(
21 [Parameter(ValueFromPipeline)]
22 $CIVM
23 )
24 begin {}
25 process
26 {
27
28 # API version to use when communicating with vCloud Director - API 27.0 is vCloud Director 8.20:
29 $vCDAPIVersion = "27.0"
30
31 # Check if we've been passed a VM name or an actual VM object and handle appropriately
32 if ($CIVM.GetType() -eq [String]) {
33 try {
34 $VMObj = Get-CIVM -Name $CIVM -ErrorAction Stop
35 } catch {
36 Write-Host -ForegroundColor Red "Error: Could not find a VM with the name $CIVM."
37 Break
38 }
39 }
40 else {
41 $VMObj = $CIVM
42 }
43
44 # Find our vCloud SessionId that matches the URI of the VM object:
45 $SessionId = $global:DefaultCIServers.SessionId | Where-Object { $VMObj.href -match $_.ServiceUri }
46
47 try {
48 $vmxml = Invoke-RestMethod -Method Get -Uri "$($VMObj.href)/virtualHardwareSection/disks" -Headers @{'x-vcloud-authorization'=$SessionId; 'Accept'="application/*+xml;version=$($vCDAPIVersion)"} -ErrorAction Stop
49 } catch {
50 Write-Host -ForegroundColor Red "Error attempting to get VM details from API:"
51 Write-Host -ForegroundColor Red "Status Code: $($_.Exception.Response.StatusCode.value__)"
52 Write-Host -ForegroundColor Red "Status Description: $($_.Exception.Response.StatusDescription)"
53 Break
54 }
55
56 # Build an empty object for the VM disk details:
57 $vmdisks = @()
58
59 # RASD resource type 17 is a hard disk attached to a VM:
60 foreach($disk in ($vmxml.RasdItemsList.Item | Where-Object -Property ResourceType -eq 17)) {
61
62 # Dereference the StorageProfileHref for each disk to get the Storage Profile Name:
63 try {
64 $sprof = Invoke-RestMethod -Method Get -Uri "$($disk.HostResource.storageProfileHref)" -Headers @{'x-vcloud-authorization'=$SessionId; 'Accept'="application/*+xml;version=$($vCDAPIVersion)"} -ErrorAction Stop
65 } catch {
66 Write-Host -ForegroundColor Red "Error attempting to get Storage Profile Name:"
67 Write-Host -ForegroundColor Red "Status Code: $($_.Exception.Response.StatusCode.value__)"
68 Write-Host -ForegroundColor Red "Status Description: $($_.Exception.Response.StatusDescription)"
69 Break
70 }
71
72 $diskprops = @{
73 VMName = [string]$VMObj.Name
74 InstanceID = [string]$disk.InstanceID
75 StorageProfile = [string]$sprof.VdcStorageProfile.Name
76 CapacityGB = [float][math]::Round(($disk.VirtualQuantity / 1024 / 1024 / 1024),3)
77 ElementName = [string]$disk.ElementName
78 }
79
80 $diskobj = New-Object PSObject -Property $diskprops
81 $vmdisks += $diskobj
82 }
83
84 return $vmdisks
85 } # end process
86
87}
88Export-ModuleMember -Function Get-CIVMStorageDetail
And here is example output from the script for our test VM:
Hope this is useful to some of you and as always, appreciate any comments/feedback.
I’d also love to know if there’s an easier way of generating this information.
Jon.