Add vCloud Harddisks with PowerCLI When it comes to adding new disks to a VM,it is a little tough and you must be careful due to the many implementation of the objects in the SDK, tasks like conversion from XML to a .NET object is very tough, mostly to the with the vCloud API’s intricate nodes, elements, attributes and many more.the solution is to use the 4 HTTP methods used in REST APIs: GET, POST, PUT, DELETE. So the combination of PowerCLI and powershell.NET you create a new CLHarddisk, though it’s made on advanced level you can pipe a vCloud VM to it:
# Passing VM via pipeline
Get-CIVM “MyVM” | New-CIHarddisk -size 10240
# Or just using a VM name
New-CIHarddisk -vm “MyVM” -size 10240
So the whole process is made with this code though it may create many disks just be keen:
function New-CIHarddisk
{
[cmdletbinding()]
param
(
[Parameter (ParameterSetName=”pipeline”,ValueFromPipeline=$true,Mandatory=$true)]$vm,
[Parameter (Position=0, Mandatory=$true)]$size
)
Process
{
# 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”
$webclient = New-Object system.net.webclient
$webclient.Headers.Add(“x-vcloud-authorization”,$vmHardware.Client.SessionKey)
$webclient.Headers.Add(“accept”,$hardwareContentType)
[xml]$hardwareConfXML = $webclient.DownloadString($vmhardware.href)
# 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.Headers.Add(“x-vCloud-authorization”,$vmHardware.Client.SessionKey)
$request.Accept=”application/vnd.vmware.vcloud.task+xml”
$request.Method=”PUT”
$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()
$requestStream.write($xmlEnc, 0, $xmlEnc.Length)
$requestStream.Close()
$response = $request.GetResponse()
$responseStream = $response.getResponseStream()
$streamReader = new-object System.IO.StreamReader($responseStream)
$result = $streamReader.ReadtoEnd()
$streamReader.close()
$response.close()
}
}
Home/