02 July 2012

VMware View reporting -- PowerShell without Broker-based cmdlets -- Part 0

The need:  reportability/manageability of VMware View environments
The tool from VMware:  PowerShell Integration with VMware View -- a PowerShell snapin provided with VMware View.

Some problems:
  • must be used on the Broker server on which VMware View Connection Server software is running (local or via PSRemoting)
  • slow
  • has not been updated since View 4.5 release
  • slow!
So, I checked around for alternatives, and were eventually put onto the local ADAM instance that runs on each Connection Server.  After some inspection/investigation (thanks, Sysinternals AD Explorer), I found how to use the data in the ADAM database to return valuable VMware View environment information in a timely fashion.

LDAP and Quest's AD cmdlets?  Sounds good.

Overview:  by using Quest's Get-QAD* cmdlets and querying the local ADAM database on a Connection Server, most any VMware View info can be had.  As for speed -- with the proper planning, the reporting we are doing is far faster than using the standard View cmdlets on a Connection server -- in some cases, an order of magnitude faster, in some cases, an even greater increase!  A quick example of the amount of time for getting pools, their template, and their description for an environment with about 75 pools by each method:
using standard View cmdlets on the Brokerabout 70 seconds
querying LDAP to grab the desired infoless than one (1) second!

Obviously, some serious speed gains to be had.  More on those results later.

To dig in:  A couple of key organizational units ("OUs") and basic object types/properties that help along the way to being able to mine this info:
pool objects' OU distinguished nameOU=Applications,DC=vdi,DC=vmware,DC=int
pool objectClasspae-DesktopApplication
pool property that specifies the pae-ServerPool object which contains additional pool settings<poolObject>.{pae-Servers}
pool property that specifies the pool's display name<poolObject>.{pae-DisplayName}

Further info about row three -- the "pae-ServerPool" LDAP objects hold further info about the actual View pool with which they are associated.

And, so as to show the ADAM DB object types and OUs for some items, I labeled a snippet of a screenshot from the View Admin console:
labeled View Admin web console screenshot snippet

So, to get some pool info (display name, description, template/parent VM name) for VDI pools using Get-QADObject:
## some juicy properties to retrieve with the pae-ServerPool (Pool additional info) objects
$arrIncludedProperties = "pae-DisplayName,description,pae-VmTemplateName,pae-SVIVmParentVM,Name".Split(",")

## use Get-QADObject to connect to the given ADAM instance (on the given Connection Server), retrieve objects and return info
Get-QADObject -Service myConnectionServer.domain.com -DontUseDefaultIncludedProperties -IncludedProperties $arrIncludedProperties -LdapFilter "(objectClass=pae-ServerPool)" -SizeLimit 0 | Sort-Object "pae-DisplayName" | Select-Object Name, "pae-SVIVmParentVM"

which returns some info like:
Name                pae-SVIVmParentVM
----                -----------------
testPool            /datacenter2/vm/XP/Imgs/templV101
testPool2           /datacenter2/vm/XP/Imgs/4v101
test-2011           /datacenter0/vm/XP/Imgs/hangarV101
jamPool             /datacenter0/vm/XP/Imgs/slaughterv101
Note: "pae-SVIVmParentVM" is the path to the parent VM for a linked-clone pool

If you are not quite following the -LdapFilter parameter in the code above, it is, as the parameter name suggests, a way to filter the objects returned in the query.  In this case, it helps to return just the items that are the "additional info about pools and their settings" objects.  A quick but good bit about LDAP query syntax is available in the Search and Compare section about LDAP at wikipedia.org.

Ok, good start. Now, put that into a function, and try a few other calls:
## Script purpose:  function to get pool info (display name, description, template/parent VM name) for VDI pools
## Author:  vNugglets.com -- Feb 2012
function Get-VNVDIPoolTemplateInfo {
    #Requires –PsSnapIn Quest.ActiveRoles.ADManagement
    param (
        ## one of the connection servers of the given VDI environment
        [string]$connectionServerName_str = "someBroker.domain.com"
    ) ## end param

    $arrIncludedProperties = "pae-DisplayName,description,pae-VmTemplateName,pae-SVIVmParentVM,Name".Split(",")
    Get-QADObject -Service $connectionServerName_str -DontUseDefaultIncludedProperties -IncludedProperties $arrIncludedProperties -LdapFilter "(objectClass=pae-ServerPool)" -SizeLimit 0 | Sort-Object "pae-DisplayName" | Select-Object $arrIncludedProperties
} ## end fn
Some sample usage:
## Gets template-based pools and their description and template info
PS C:\> Get-VNVDIPoolTemplateInfo -connectionServer someBroker.domain.com | ?{$_."pae-VmTemplateName"} | select pae-DisplayName,pae-VmTemplateName

pae-DisplayName             pae-VmTemplateName
---------------             ------------------
Sharepoint Crew             /datacenter0/vm/XP/Templates/myOldTemplate0
Developer POC               /datacenter0/vm/XP/Templates/myTemplate1
## gets VDI pools whose linked clone "parent" property is like "*v101", gives pool ID and the linked clone parent VM info
PS C:\> Get-VNVDIPoolTemplateInfo -connectionServer someBroker.domain.com | ?{$_."pae-SVIVmParentVM" -like "*v101"} | select Name,pae-SVIVmParentVM,description

Name                pae-SVIVmParentVM                       Description
----                -----------------                       -----------
testPool            /datacenter2/vm/XP/Imgs/templV101       Temporary testing pool...
testPool2           /datacenter2/vm/XP/Imgs/4v101           Old "next-gen" pool for..

As for those speed gains reported above -- part of why querying the LDAP directory (ADAM DB) is soo much faster than the standard View cmdlets is the focus/scope of the queries.  Using the View cmdlets pulls back a prescribed amount of data about the objects in question, pools in this example. Cheers to VMware for providing the cmdlets.  But, there is some work to be done with them, still.  Meanwhile, specifying just the necessary properties/objects/attributes to get the desired info helps keep things fast (FaF).  The actual results of the speed tests performed:
## on broker console, native cmdlet
PS C:\> Measure-Command {Get-Pool | select pool_id,parentVMPath,description}
TotalSeconds      : 72.4010917
## on remote machine using vNugglets function
PS C:\> Measure-Command {Get-VNVDIPoolTemplateInfo -connectionServerName connectionServer.somedomain.com | select Name,pae-SVIVmParentVM,description}
TotalSeconds      : 0.6809141

What's that?  100+ times faster?  Nice.  Again, the speed gain is thanks to the planning and the upfront cost of writing the specific ADAM queries -- it is not pure magic (just only a little).

And, some of the other places on the web that talk about alternative ways to mine View data (mostly without using [slow] cmdlets local to the View Broker) that may be of interest:
Wait, there is more! But, for the sake of having a reasonable length for this post, I will save those for now. Upcoming pieces in this series include further discussion about the OUs/objects in the View ADAM DB and how to use them for looking at pool entitlees, finding out what pools use a given parent / template VM, and reporting on pool VMs and their assigned users.