With the advent of PowerCLI for vCloud Director the reasons for using vCenter Orchestrator (vCO) blur even more. VMware provides us several CmdLets that we can all find in the “VMware.VimAutomation.Cloud” snapin (“Get-Command -Module VMware.VimAutomation.Cloud”). Sure this library is by far not perfect, there is quite some functionality. However, when using the “Get-CiVm” CmdLet you will probably find out quickly that you only get the half you paid for (actuallya third): storage information of a virtual machine is missing:

PowerCLI > $vm | fl * -force
ExtensionData : VMware.VimAutomation.Cloud.Views.Vm
Status : PoweredOff
Deleted : False
GuestOsFullName : Microsoft Windows Server 2008 R2 (64-bit)
CpuCount : 1
MemoryMB : 2048
MemoryGB : 2
VMVersion : v7
Org : Appclusive
OrgVdc : OvDC-Appclusive-0001
VApp : vApp_MS01_W2k8Stdx86
Description : Windows 2008 R2 x64 Standard Edition (Patch Release: July 2012)
Href : https://vcdint.dfch.biz/api/vApp/vm-420542-dead-dead-dead-05054242
Id : urn:vcloud:vm:420542-dead-dead-dead-05054242
Name : W2K8SP2x64-STD-Patched
Client : /CIServer=rro:system@vcdint.dfch.biz:443/
Uid : /CIServer=rro:system@vcdint.dfch.biz:443/CIVM=urn:vcloud:vm:420542-dead-dead-dead-05054242/

There is no storage shown.

You can get around this by querying the underlying vCenter objects via the “ExtensionData” property on the “CIVMImpl” object. Then you would query the hardware section for the disks (ResourceType 17) and add each individual disk to get the total storage (in MB) for that virtual machine:

# $vm.GetType() -- CIVMImpl / VMware.VimAutomation.Cloud.Impl.V1.CIObjectImpl as returned by Get-CiVm
$VmExt = $vm.ExtensionData;
$VmExtHw = $Vmext.GetVirtualHardwareSection();
[int] $diskCapacity = 0;
foreach ( $disk in ( $VmExtHw.Item | Where {$_.ResourceType.Value -eq <span style="color:#ff0000;">17</span>} ) ) {
  $hs = $disk.hostresource[0];
  [string] $diskAttribute = $hs.AnyAttr.OuterXml;
  $fReturn = $diskAttribute -match "vcloud:capacity=.(\d+).";
  if($fReturn) {
    $diskCapacity += $Matches[1] -as [int];
  } # if
} # foreach disk

Beware to check if the calls for “ExtensionData” and “GetVirtualHardwareSection” succeed. I already found some VMs on vCD that would return $null on these calls. So in real life guard this with try/catch.


  1. Hi, is it possible to add a disk to a VM om powercli? I wrote a function:
    function New-CIHarddisk
    [Parameter(Position=0, Mandatory=$true)]$size

    # Get indexes to create unique IDs for our new disk.
    if ($vm -is [System.String])
    $vm = get-civm $vm
    $vmHardware = $vm.ExtensionData.GetVirtualHardwareSection()
    $scsiController = $vmHardware.item | where {$_.resourceType.value -eq “6”}
    $highaddress = ($vmHardware.item | where {$_.resourcetype.value -eq “17”} | Sort-Object addressonParent)[-1].addressonParent.value
    $addressOnParent = [int]$highaddress + 1
    $highInstance = ($vmHardware.item | where {$_.resourcetype.value -eq “17”} | Sort-Object instanceID)[-1].instanceId.value
    $instanceId = [int]$highInstance + 1
    $highElement = ($vmHardware.item | where {$_.resourcetype.value -eq “17”} | Sort-Object elementName)[-1].elementName.value
    $elementName = [int]$highElement.Split()[-1] + 1

    # We need to get the raw XML via vCloud API to add the new disk.
    $hardwareContentType = “application/vnd.vmware.vcloud.virtualHardwareSection+xml;version=5.1”
    $webclient = New-Object system.net.webclient
    echo $vmHardware.Client.SessionKey
    #$vmHardware.href = $vmHardware.href + “/disks”
    echo $vmHardware.href
    [xml]$hardwareConfXML = $webclient.DownloadString($vmHardware.href)
    echo $hardwareConfXML

    # Clone the XML node, assign our variables, and insert child into the XML
    $newDisk = ($hardwareConfXML.VirtualHardwareSection.Item | where {$_.resourcetype -eq 17})[-1].clonenode(1)
    $newDisk.AddressOnParent = “$addressOnParent”
    $newDisk.InstanceId = “$instanceId”
    $newDisk.elementName = “Hard Disk $elementName”
    $newdisk.hostresource.capacity = “$size”
    $newDisk.parent = “$($scsiController.instanceID.value)”
    [void]$hardwareConfXML.VirtualHardwareSection.InsertAfter($newDisk,($hardwareConfXML.VirtualHardwareSection.Item | where {$_.resourcetype -eq 17})[-1])

    # PUT the data back through vCloud API
    $request = [System.Net.WebRequest]::Create($vmHardware.href);

    $request.ContentType = $hardwareContentType
    $postData = $hardwareConfXML.virtualhardwaresection.outerxml
    $xmlString = $postData.replace(” “,””) # adding strings to xml puts in silly newlines.
    [byte[]]$xmlEnc = [System.Text.Encoding]::UTF8.GetBytes($xmlString)
    $request.ContentLength = $xmlEnc.length
    [System.IO.Stream]$requestStream = $request.GetRequestStream()
    $response = $request.GetResponse()
    $responseStream = $response.getResponseStream()
    $streamReader = new-object System.IO.StreamReader($responseStream)
    $result = $streamReader.ReadtoEnd()

    but seems the request is bad? can you advice ? Thanks.

    • Hi Alex, as I am on the move I cannot test your example, and I could not find an error that is returned by your function. But a quick look around showed me that someone else seemed to have tackled the same issue. Though the example is a little bit hard to read (formatting lost?) you might want to have a look at: http://geekafterfive.com/2012/06/29/add-vcloud-harddisks-with-powercli/ and compare your solutions. Hope it helps otherwise pls let me know. Ronald

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.