vCAC: Dynamically load properties in PowerShell for vCAC entities

I recently wrote about on how to use the mgmtContext from vCAC so that you can use it outside the script/file repository of vCAC. With it you can easily access VirtualMachines, GlobalProperties without the need to use the ODATA REST interface of vCAC. However, when you first grab a virtual machine you might have wondered why you do not get all the related properties of it:

PS > $Vm = $m.VirtualMachines |? VirtualMachineName -eq 'DUB100124'
PS > $Vm.VirtualMachineProperties
PS > $Vm.VirtualMachineProperties.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Collection`1                             System.Object

PS > $Vm.VirtualMachineProperties.Count
0

In C# you would use a “LINQ Expand” or in ODATA you would use a “ODATA exapnd” expression. This is obviously not possible in this case. However the mgmtContext provides you a property that you can use to dynamically load additional objects into a context:

PS > $m.LoadProperty

OverloadDefinitions
-------------------
System.Data.Services.Client.QueryOperationResponse LoadProperty(System.Object entity, string propertyName)
System.Data.Services.Client.QueryOperationResponse LoadProperty[T](T source,
System.Linq.Expressions.Expression[System.Func[T,System.Object]] property)
System.Data.Services.Client.QueryOperationResponse LoadProperty(System.Object entity, string propertyName, uri nextLinkUri)
System.Data.Services.Client.QueryOperationResponse LoadProperty(System.Object entity, string propertyName,
System.Data.Services.Client.DataServiceQueryContinuation continuation)
System.Data.Services.Client.QueryOperationResponse[T] LoadProperty[T](System.Object entity, string propertyName,
System.Data.Services.Client.DataServiceQueryContinuation[T] continuation)

Here, we are interested in the first overload. With it we can load a property by name for its base entity. So, to load the “VirtualMachineProperties” we use the following command and will see that we now have access to 72 properties:

# System.Data.Services.Client.QueryOperationResponse 
#  LoadProperty(System.Object entity, string propertyName)

$null = $m.LoadProperty($vm, 'VirtualMachineProperties')
PS > $vm.VirtualMachineProperties.Count
72

In order to load all properties at a time you can simply enumerate over all properies of the base entity and issue a “LoadProperty()” for each of them:

($vm|gm -Type Property).Name |% { $null = $m.LoadProperty($vm, $_); }

To further simplify (read-only) access to the machine properties you can add them to a hash table like this:

$hp = @{};
$vm.VirtualMachineProperties | Select-Object PropertyName, PropertyValue 
  |% { $hp.Add($_.PropertyName, $_.PropertyValue); };

To access a property you only have to code like this:

$Location = $hp.'Vrm.DataCenter.Location';

The properties you loaded in this way certainly have a link to its base entity, so when changing them you only have to call “UpdateObject()” and then “SaveChanges()”. Quite simple, isn’t it …

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: