Executing a vRO action via REST API

The ability to execute a vRO workflow or action via API is useful if you are using vRA or vRO as part of an overall CI/CD pipeline. If a vRA catalog item uses vRO actions to filter or set values on a custom form how can this be done if the vRA catalog item will be requested via REST.

In the example below I have a simple action that takes two inputs:

  • firstName – Type:String
  • secondName – Type:String

In order to be able to execute a vRO action you need to submit basic auth credentials. This will require the user account to be a member of the vco-admins group in vRO. This can either be a local user or an Active Directory user if vRA has been configured to integrate with Active Directory

The process for being able to execute the action via REST is a three part step. Part 1 is to determine the ID of the action that you wish to call. Execute the following operation:

GET - https://vro-fqdn/vco/api/actions

The result will be a large array of actions that looks something like this:

{
     "link": [
         {
             "attributes": [
                 {
                     "value": "d7e461f6-b88f-4f63-a2cc-7f3c76d1bd19",
                     "name": "id"
                 },
                 {
                     "value": "isBlocking",
                     "name": "name"
                 },
                 {
                     "name": "description"
                 },
                 {
                     "value": "com.vmware.library.vcaccafe.workflow.subscription/isBlocking",
                     "name": "fqn"
                 },
                 {
                     "value": "0.0.0",
                     "name": "version"
                 }
             ],
             .......

You’ll need to process this array to search for the name of the action that you wish to execute.

Part 2 is to retrieve the inputs for the action which is achieved via the following REST operation:

GET - https://vro-fqdn/vco/api/actions/{actionid}

The result will look something like this:

{

    "href": "https://192.168.1.26:443/vco/api/actions/278a1622-1924-4f37-bb24-0c5d36346ae9/",
    "relations": {
        "link": [
            {
                "href": "https://192.168.1.26:443/vco/api/actions/com.cloudkindergarten.examples/executedByApi/",
                "rel": "alternate"
            },
            {
                "href": "https://192.168.1.26:443/vco/api/actions/278a1622-1924-4f37-bb24-0c5d36346ae9/permissions/",
                "rel": "permissions"
            },
            {
                "href": "https://192.168.1.26:443/vco/api/actions/278a1622-1924-4f37-bb24-0c5d36346ae9/executions/",
                "rel": "executions"
            }
        ]
    },
    "id": "278a1622-1924-4f37-bb24-0c5d36346ae9",
    "output-type": "string",
    "name": "executedByApi",
    "description": "",
    "version": "0.0.0",
    "fqn": "com.cloudkindergarten.examples/executedByApi",
    "script": "var fullName = (firstName + \" \" + secondName);\nreturn fullName;",
    "input-parameters": [
        {
            "description": "",
            "type": "string",
            "name": "firstName"
        },
        {
            "description": "",
            "type": "string",
            "name": "secondName"
        }
    ]
}

From this we can see that action is expecting two input parameters; firstName and secondName both of type string.

Part 3 is to execute this action. We do this by using the following body content

{"parameters":
 [
  {
   "value": {"string":{ "value": "Andy"}},
   "type": "string",
   "name": "firstName",
   "scope": "local"
  },
  {
   "value":{"string":{"value": "Davies"}},
   "type": "string",
   "name": "secondName",
   "scope": "local"
  }
 ]
}

This is then executed with the REST Operation:

POST https://{vro-fqdn}/vco/api/actions/{actionid}/executions/

The response will hopefully be the returned value from the action. In this case the full name of the person:

{
    "value": {
        "string": {
            "value": "Andy Davies"
        }
    },
    "type": "string"
}

Custom Groups vs Custom Datacenters

Recently I have been working with a global organisation to assist with capacity planning and wastage of their virtual estate. This organisation has a significant number of business units and network zones that need to have their capacity planning performed independently, but the clusters within those boundaries are generally managed by the same vCenter server with geographically focussed datacenters. The challenge therefore was how do we manage capacity of our groups of clusters (this customer has hundreds of clusters)? One thing to note is that this customer has a standard (which is then reflected in a vROps policy) to only use an allocation based model of capacity utilisation and they were unable, for a variety of reasons, to move to a demand based model.

In vROps we have two means of grouping objects; custom groups and custom datacenters. Unfortunately neither of these is ideal for our purposes, due to the reasons shown in the table below:

PROS CONS
Custom Group
  • Membership can be dynamically configured based on many metrics, relationships or properties
  • Capacity remaining can be calculated via super metrics that sum the capacity remaining of child objects
  • Time remaining is not available as a metric on the object
  • Custom groups are just that groups as opposed to objects in their own right
Custom Datacenter
  • Allows large datacentres to be configured into logical groupings that more readily reflect the breakdown of an organisation
  • Treated as a full object in its own right meaning that capacity remaining and time remaining are calculated for the custom datacenter based on the child objects
  • Different policies can be configured between custom datacenters and their child objects
  • Membership cannot be natively configured
  • Different policies can be configured between custom datacenters and their child objects
  • Consistency between the values computed for a custom datacenter and its child objects can sometimes be challenging
  • Based entirely on infrastructure so can only be broken down into clusters or hosts. It is not possible to create a custom datacenter based upon virtual machines directly

When discussing these with the customer they asked the obvious question:

Is there a way to determine the time remaining of a group of clusters based on the time remaining of the individual clusters via a super metric?

The simple answer is no, and the more complex answer is still no

Take the following simple example where we have two identically sized clusters and every VM that we deploy is the same size and we deploy a set number of VMs per day (to make this example easier to understand)

  • Cluster A has capacity for 10 VMS and we deploy 2 VMs per day
  • Cluster B has capacity for 20 VMs and we deploy 1 VM per day

Based on the above the time remaining for each of these would be as follows:

  • Cluster A – 5 days
  • Cluster B – 20 days

So what is the time remaining for the clusters as a group? 20 days? 25 days? Something else? The table below shows us how the group of clusters will be filled and therefore how much time remaining there is:

        Day
 0 1 2 3 4 5 6 7 8 9 10
  Cluster A  Capacity Remaining  10 8 6 4 2 0
 Time Remaining  5 4 3 2 1 0
  Cluster B  Capacity Remaining  20 19 18 17 16 15 12 9 6 3 0
 Time Remaining  20 19 18 17 16 15 4 3 2 1 0

This is a a simple example and yet the maths is pretty complex, imagine this with 10 clusters, differing virtual machine sizes, different and changeable deployment patterns and the ability to define a single value via the super metric mechanism is not suitable.

The answer therefore seems to be custom datacenters, as by using these we gain access to vROps inbuilt capacity engine to calculate the time remaining figure for groups of clusters. Custom Datacenters are top-level objects within vROps and every benefit that goes with that.

There are still some challenges that I’ve experienced specifically around consistency of numbers whereby the number of virtual machines remaining in the clusters that make up a custom datacenter don’t necessarily add up to the number of VMs remaining for the custom datacenter itself. This can however be masked by the use of super metrics.

The second and much larger challenge however is that there is no dynamic membership mechanism for custom datacenters. In smaller environment this may not be so much of a problem whereby the membership can be managed manually. However, in environments with hundreds of clusters, then managing this manually via the UI is both impractical and prone to mistakes.

With my current customer we’ve used the vROps API both to create the custom datacenters but also to manage the relationships between the custom datacenters and the underlying clusters. More information on how to use the vROps API can be found at the following links:

Straight up flying with the vrealize operations rest api

vRealize Operations Manager API Guide

In doing so PowervROps was born, a module that allows the use of the vROps API directly from within PowerShell, but that is worthy of a post all to itself:

PowervOps – PowerShell cmdlets for the vROps API