Using the VI APIs from PowerShell

The trigger for this article was a question I got from Alan. He wanted to know how he could get, from within a PowerShell script, a report of all the tasks that were run against a specific virtual machine during the last seven days.

The VI Toolkit (VITK) has a Get-Task cmdlet, but that cmdlet is in the current release of the VITK a bit restricted in it’s use. See the community thread “Determine the “lineage” of a VM | From which Template was a given VM authored?” for a further discussion on this.

Since it became clear that the VITK wouldn’t give me what I wanted, the only possible alternative was to go to the VI APIs.

Every time I need to use the VI APIs I start by looking in the API Reference Documentation.

This document, which is in fact a web-based search tool, has a rather straight-forward layout. In the left pane you find the main menu and in the right pane you will find the details on everything you select in the left pane.

API-main

Where you start your search in the API Reference depends a bit on what you have to start with.

Alan’s question gave me 2 keywords to start with, “task” and “history”.

Looking in the SDK Reference under the Managed Objects Types we find an object which is called TaskHistoryCollector.

clip_image002

Looks promising.

For that object we see, in the right pane, that it is returned by a method called CreateCollectorForTasks.

clip_image004

Selecting the hyperlink, we get to the details of the method and we see it has two parameters:

· a TaskManager object to call this method

· a filter for the query in an object of the type TaskFilterSpec

clip_image006

The TaskManager object is easy: Get-View TaskManager

The TaskFilterSpec we will tackle later.

One more thing to take into account, the CreateCollectorForTasks method returns a ManagedObjectReference, or MoRef. Something like a pointer to the actual object.

But to call methods on the collector from within PowerShell we need the object itself.

Again the VITK makes this rather easy:  $thCol = Get-View –Id $taskHistoryCollector

Now that we have the object lets look further.

clip_image008

There are 2 methods that seem interesting for our purpose:

  • the RewindCollector, which doesn’t need any parameters.
  • the ReadNextTasks method which needs a parameter to specify the number of task events to read in a call to the method.

In short, what the “collector” does:

  • it gets all the tasks that comply with the filter specifications
  • it offers a kind of “window” to scroll through the list of tasks
  • the scrolling can be done with RewindCollector, which places the “window” at the start of the list, and ReadNextTasks, which returns all the tasks that are visible in the “window”
  • the size of the “window” is defined by a parameter you pass to the ReadNextTasks method
  • When there are no tasks left to read the method will return $null.

clip_image010

Now let’s have a look at the filter object.

clip_image012

Quit a lot of options available. But in our case we were looking for all the tasks during a specific period of time. The time property seems to do just that.

Clicking on the TaskFilterSpecByTime hyperlink shows us the details of the object.

clip_image014

Just what we needed. We need to populate the beginTime property with with the timestamp of seven days ago.

Again, quit easy in PowerShell: (Get-Date).AddDays(-7)

Now for the 2nd part of our query; Alan was looking for the tasks against a specific VM.

Let’s have a look at the entity property of the TaskFilterSpec object. It seems we need the MoRef (managed object reference) for the VM in question.

That’s also something we know how to do : (Get-VM <VM-name> | Get-View).MoRef

 

Putting it all together we come to the following script:

$myVM = <VM-name>
$taskManager = Get-View TaskManager
$vmMoRef = (Get-VM $myVM | Get-View).MoRef

$spec = New-Object VMware.Vim.TaskFilterSpec
$spec.time = New-Object VMware.Vim.TaskFilterSpecByTime
$spec.time.beginTime = (Get-Date).AddDays(-7)
$spec.entity = New-Object VMware.Vim.TaskFilterSpecByEntity
$spec.entity.entity = $vmMoRef

$taskHistoryCollectorMoRef = $taskManager.CreateCollectorForTasks($spec)
$thCol = Get-View -Id $taskHistoryCollectorMoRef
$thCol.RewindCollector()
do {
    $tasks = $thCol.ReadNextTasks(100)
    foreach($task in $tasks){
        Write-Host $task.StartTime $task.Name
    }
} until($tasks -eq $null)

In the script we just show the timestamp and the name of the task on screen, but there are a lot more properties in the TaskInfo object.

taskinfo

In conclusion, I hope this short article made using the VI APIs in your PowerShell scripts a bit less frightening and a bit more accessible.

And if you want to learn more on the SDK and VI APIs have a look at the Programming Guide.  Chapters 2, 3 and 4 will give you a good understanding of the VI internals.

Leave a Reply