Using PowerCLI for fun and profit in general is a great thing to do – in general… However, in certain cases PowerCLIs implementation is much slower than using the underlying REST calls directly. This is especially true when using Get-CiVm to get information about a vCloud Director (vCD) virtual machine.
Consider the following fragment:
# connect to vCloud PS > Connect-CiServer vCloud; # get a list of all VMs PS > $Vms = Search-Cloud –QueryType adminVM; # grab first reported VM PS > $VmSlim = $Vms[0]; PS > $VmSlim.id; urn:vcloud:vm:deaddead-dead-dead-dead-deaddeaddead
This is all pretty fast, as we are using the Search-Cloud CmdLet, that utilises the vCD Query service.
Now we want to get a “full” VM object and call the Get-CIVM on the id/urn of the (or any) VM as the “slim” VM object returned by the Query service does not contain all properties of a VM:
PS > $Vm = Get-CIVM -id $VmSlim.id;
The interesting thing about this is: when you have a nice test environment with only a few machines it runs through quite quickly (around 300-400ms). But as soon as you have an environment with only a couple of hundred VMs things are getting considerably slower (talking seconds):
PS > Measure-Command { $Vm = Get-CIVM -id $VmSlim.id; } Days : 0 Hours : 0 Minutes : 0 Seconds : 1 Milliseconds : 738 Ticks : 17386313 TotalDays : 2.01230474537037E-05 TotalHours : 0.000482953138888889 TotalMinutes : 0.0289771883333333 TotalSeconds : 1.7386313 TotalMilliseconds : 1738.6313
When checking the REST log in “/opt/vmware/vcloud-director/logs/” you will notice the call of GetCiVm generated these two calls:
GET /api/entity/urn:vcloud:vm:deaddead-dead-dead-dead-deaddeaddead GET /api/query?type=adminVM&format=records&filter=name==vmname&sortAsc=name&pageSize=128
And before you start blaming your environment, database server or whatever, try to execute these REST calls directly via a WebClient object with the same session as described in my post about reusing vCD session cookies:
Measure-Command { $wc.Headers.Add("Accept", $HeaderAcceptValue); $wc.Headers.Add("Cookie", $HeaderCookieValue); $Data = $wc.DownloadString("https://vcloud/api/entity/urn:vcloud:vm:deaddead-dead-dead-dead-deaddeaddead "); $Data $wc.Headers.Add("Accept", $HeaderAcceptValue); $wc.Headers.Add("Cookie", $HeaderCookieValue); $Data = $wc.DownloadString("https://vcloud/api/query?type=adminVM&format=records&filter=name==vmname&sortAsc=name&pageSize=128"); $Data }
And voilà: times range from 115ms to 450ms (regardless of cached or uncached objects) making the direct REST calls a factor between 3 to 10 tims faster!
The question still to be answered is: where does the PowerCLI spend all of its time and lose its speed?