VUM Xtra Module: Extended VUM Automation with the VC Integrity API

Anyone who has been asked to automate vSphere Update Manager processes will know that the CMDlets included within PowerCLI are somewhat sparse. The current functionality focuses mainly around patch baselines and not much else. If you want to automate ESXi images, image baselines or baseline groups, you’re out of luck……until now 🙂

A while ago whilst working for a previous employer, I was asked to spend some time to find some method of automating this functionality, in particular baseline groups. At the time we were using vCenter 6.0 with an external Windows based VUM instance. My initial approach to this was to run a SQL trace on the database to see what VUM was doing when a baseline group was created. What followed was a rather ham-fisted approach to re-running the SQL required to create the appropriate configuration. While this worked, it wasn’t very elegant and of no use when we moved to a 6.5 appliance with an integrated VUM.

This took me down a long path that eventually led to the VUM Xtra module. If you want to cut to the code, it can be found here: https://github.com/TheDotSource/VUMXtra

To see how this works, keep reading.

Figuring out the VC Integrity API

With a bit of further research I came across some interesting posts from a VMTN user bbambalova: https://communities.vmware.com/people/bbambalova/content

Whilst not directly related to what I wanted to automate, it was enough to give me an introduction to the API that underpins VUM, the “VC Integrity” API. This is a private VMware API for which there is no documentation and virtually nothing on Google about.

These code samples showed me how to create a connection to the VUM service and allowed me to start exploring the capabilities of the API.

The key piece of information here is the IntegrityApi.IntegrityService object:

Using Get-Member to look at the members of this object, we can see there are hundreds of methods available, many with promising names such as CreateBaselineGroup. Get-Member also indicates what object types these methods take as input, however this is often somewhat cryptic. We need to find the methods that can create the appropriate object type, then the object may have many properties that need to be set, all of which require very particular values if they are to be understood by the API. As you can imagine, figuring out these values with no documentation is next to impossible. To make matters worse, property values are also case sensitive (the API may reject “Host” but accept “HOST”). Clues were taken from the VUM GUI, the tables inside SQL containing VUM data, an interesting tool on Windows VUM called vmware-vciCli.exe and even the vRO plugin for VUM. This and a lot of trial and error.

So with a little (a lot) of detective work I started to figure out these objects and their properties to get the API to do the tasks I was looking to automate. Some time later I’ve ended up with a module, named after taking inspiration from my favourite Scottish beverage.

Example Code

So with that, we can take a look at some sample code. To get started, ensure that there is a connection to vCenter. Ensuring that the VUM assemblies are loaded into your session will help too. To do that, the simplest thing to do is to call a VUM CMDlet and PowerShell will take care of the rest:

Get-Patch -Id 0

We’ll assign our default vCenter connection to the following variable:

$vCenterServer = $global:DefaultVIServer

Get the VUM extension data to give us access to all the VUM goodness:

$serviceInstance = Get-View ServiceInstance -Server $vCenterServer
$extensionMgr = Get-View $serviceInstance.Content.ExtensionManager -Server $vCenterServer
$vumExtension = $extensionMgr.FindExtension("com.vmware.vcIntegrity")

Then some code to create a connection the VUM service:

$vumWebService = New-Object IntegrityApi.IntegrityService
$vumUrl = $vumExtension.Server[0].Url
$vumWebService.Url = $vumUrl
$vumWebService.CookieContainer = New-Object System.Net.CookieContainer
$vumWebService.Timeout = 300000
$svcRefVum = New-Object IntegrityApi.ManagedObjectReference
$svcRefVum.type = "VcIntegrity"
$svcRefVum.Value = 'Integrity.VcIntegrity'
$sessionManager = Get-View $serviceInstance.Content.SessionManager -Server $vCenterServer
$vumServiceContent = $vumWebService.RetrieveVcIntegrityContent($svcRefVum)
$userSession  = $vumWebService.VciLogin($vumServiceContent.sessionManager, $sessionManager.CurrentSession.UserName,  $sessionManager.CurrentSession.Key,  $sessionManager.CurrentSession.Locale)

With that done, we can start to do something useful. In this case, we’ll create a new empty baseline group as an example.The first step is to create a baseline group specification object:

$BaseLineGroupSpec = New-Object IntegrityApi.BaselineGroupManagerBaselineGroupSpec
$BaseLineGroupSpec.name = "Sample Baseline Group"    
$BaseLineGroupSpec.description = "A sample description."
$BaseLineGroupSpec.targetType = "HOST"

This is a good example of guessing acceptable property values. In this instance, “HOST” is a valid value. This object is now used as input by the API which will create our group.

$vumWebService.CreateBaseLineGroup($vumServiceContent.baselineGroupManager, $BaseLineGroupSpec)

Resulting VUM Functions

With many hours of head scratching I have ended up with a module that has the following functions:

Attach-BaselineGroup

Attach a baseline group to an entity (host, cluster, datacentre).

Attach-BaselineToGroup

Attach an existing patch or image baseline to a group.

Detach-BaselineGroup

Detatch a baseline group from an entity (host, cluster, datacentre).

Get-BaselineGroup

Get existing baseline groups.

Get-HostImages

Get available host images that have been uploaded to VUM.

Import-VUMContent

Import image and patch content to VUM.

New-BaselineGroup

Create a new empty baseline group.

New-ImageBaseline

Create a new image baseline for a host image.

Remediate-BaselineGroup

Remediate an entity against a particular baseline group.

Remove-BaselineFromGroup

Remove a patch or image baseline from group.

Remove-BaselineGroup

Remove a baseline group from VUM.

Usage Examples

If you are familiar with VUM and PowerCLI then using this module should be fairly self-explanatory. All the functions support Get-Help and have built in examples. However, let’s examine a couple of examples for clarity. A valid PowerCLI vCenter connection is required before attempting these.

Let’s create a new baseline group on the connected vCenter using the New-BaselineGroup CMDlet.

This has created an empty baseline group called “Sample Baseline Group”. An object is returned representing the new group. We now need to add either patch baselines, an image baseline, or both.

Using the Attach-BaselineToGroup CMDlet we will add a patch baseline called “Sample Patch Baseline” which was created previously and can be done with standard VUM PowerCLI:

Again, using the same CMDlet to add an image baseline to our baseline group which was created previously and can be done with this module:

The end result:

…and how that looks from Get-BaselineGroup:

Gotchas

There are 2 caveats to call out about this code which could be addressed with a little more time and detective work:

I have not quite figured out how to query VUM for a list of existing baseline groups. I know how to query for a baseline group given a specific index key, otherwise the API returns a null value. A workaround I have put in place for the time being is to loop from 1 to a 100 and collect any baseline groups I find (or break the loop if a name is specified). This is slower than it should be, and if you have a busy VUM server where a lot of baseline groups have been created and destroyed, you might find you need to increase the index value from 100 to a more suitable value. Time permitting, I will take a closer look at this.

The Import-VUMContent uses another workaround which is not ideal. When asking the API to perform a content import, it looks to a path on the local file system for the specified file (both appliance and Windows). This is fine, but we need to get the file to this location first. Ordinarily a user would upload files via the web client, and this uses the VUM file import manager. I can see broadly how the file import manager works but I haven’t had time to completely research it so this method can’t be used. The workaround is slightly different depending on whether we are dealing with an appliance or Windows. On the appliance, we use the Copy-VMGuestFile to place the content into /storage/updatemgr/patch-store-temp/ on the appliance file system. On the Windows side, I’ve used a PS Drive to copy content to a directory on the Windows file system. In both cases, we need to supply a suitable credential that can access the VUM local file system. Once content has successfully been imported, these files are automatically deleted by VUM.

Compatibility

As far as I’ve had time to do so, I have tested this on various combinations of appliance and Windows VUMs across 6.0, 6.5 and 6.7. It seems that the API hasn’t changed at all and I wouldn’t be surprised if this code also works on earlier versions. If you use this module please do let me know what you used it on and how it worked.

Conclusion and Future Development

I would like to find time to develop the content import and be able to properly query for baseline groups, this may or may not happen depending on time.

Interestingly looking at the HTML 5 client in 6.7, there now appears to be a RESTful API behind VUM. This can be examined by using Chrome Developer Tools to observe what is going between VUM and the HTML 5 client. This may be another potential opportunity for development on 6.7. Of course, I’m sure VMware will have a full suit of PowerCLI CMDlets out before then 🙂

If you are have something in particular that you would like added to a future version, then get in touch.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

%d bloggers like this: