In the previous article from this series I outlined an example use case for extensibility via vRO to the Cloud Assembly API. The links to the other articles in this series are below.
The first thing we are going to look at now that we have authentication into the Cloud Assembly API is what information can I get without doing anything and what information am I going to have to work a bit harder to retrieve.
Note that details of all available API calls for Deployments and IaaS components can be found here:
https://api.mgmt.cloud.vmware.com/deployment/api/swagger/ui
https://api.mgmt.cloud.vmware.com/iaas/api/swagger/ui/
I will be using the calls detailed in the above link as part of this use case.
Event Broker Topic and its Payload
There are several event topics with Cloud Assembly that generate information that we can extract and leverage however each event topic (when combined into an subscription) fires at different stages within a build process and therefore includes different information.
In this example use case I want to update the CMDB once a successful deployment has been made so I am going to use the “Compute Post Provision” event topic. We can see the information this topic includes when combined with a subscription by dumping the events payload via a workflow (see https://vnuggets.com/2019/06/19/cloud-assembly-using-vro-to-apply-cas-tags for an example on how to do this).

Based on the event topic schema and the test dump above I can work out which information I already have and which information I need to retrieve via other means.
- VM hostname – Yes
- VM IP address(es) – Yes
- VM spec (vCPU and memory quantity) – Partial (no vCPU quantity)
- Deployment name – No
- Endpoint name – No
CPU Quantity
The first problem to overcome is getting the CPU quantity value. The event payload (currently) does not hold this value (I expect this to change as the product develops and is more likely to be an omission rather than intended functionality).
My blueprints use “Flavor Mappings” (think T-Shirt sizes relating to CPU and memory quantities) so when I examine an event payload I can see the flavor which has been applied to the machine provisioned but not necessarily all the information that is contained within the flavor itself. In the screenshot above I can see my mapping is called “AK-Medium”.
We could try and get this from the flavor mapping however this could be a complicated process due to the fact that a mapping can have multiple sets of values (i.e. medium might mean different things depending on the target endpoint). A simpler option would be to get the actual provisioned machine details via an API call and extract its CPU quantity from one of its properties.
The process order for extracting the CPU quantity will be:
- Authenticate
- Extract machine name and object ID from the event payload
- Fetch the IaaS machine record that corresponds to the name and ID
- Extract the CPU value from the machine record.
The first item in this list is covered in part 1 of this series where we created an action to exchange an API token for a bearerToken. Item 2 requires me to take the payload provided by the event (inputProperties which is a properties object) and search it for the machine name and object ID. I know the property names to use to extract data from the payload by looking at the payload test dump I did earlier.

The data can be extracted from the payload using two simple lines of JavaScript code which we can add to a script element (we’ll call this “Extract Payload”).
var machineName = inputProperties.get("resourceNames");
var machineID = inputProperties.get("resourceIds");
Item 3 on my list requires an API call to fetch the machine using the two attributes above. The API call details for machines can be found in the IaaS API swagger interface (see above for swagger links).

Using the above information we can create an API call within vRO to execute the request and fetch the machine details. As this seems like something I might re-use I will create it as an action.

Now we need some code to process the response in order to verify we have the right machine (just double checking via machine name) and to get at the CPU quantity. This is contained in a script element called “Get CPU”.
var jsonMachineResponse = JSON.parse(machineResponse);
var machineNameFromJson = jsonMachineResponse.name;
if(machineName == machineNameFromJson)
{
cpuQuantity = jsonMachineResponse.customProperties.cpuCount;
}
else
{
throw "Machine name from event does not match machine name from IaaS API call";
}
Linking all this together in a workflow looks like this:

Deployment Name
Next we can progress to the deployment name. The event payload already has an ID for the deployment so I should be able to use that in an API query to get the deployment details.
The API call details for deployments can be found in the deployment API swagger interface.

The API call details above provide the information needed to write some JavaScript to fetch a deployment by its ID. This means I need the ID to execute the API call. Looking at the payload test dump again you can see there is a “deploymentId” attribute so we need to add some code to “Extract Payload” script element to extract it. It now looks as follows:
machineName = inputProperties.get("resourceNames");
machineID = inputProperties.get("resourceIds");
deploymentID = inputProperties.get("deploymentId");
With the deployment ID extracted it can be passed to the API call. The code for the API call will be mostly the same as the machine API call (different URL and customized exception messages) and when dropped into an action looks like this:

Finally we need to process the API call response to extract the deployment name from it. I’ll do this in another script element (“Get Dep Name”) with the following code:
var jsonDeploymentResponse = JSON.parse(deploymentString);
deploymentName = jsonDeploymentResponse.name;
The overall workflow now looks like this:

Endpoint Name
Last on the list is the endpoint name. There several ways we might go about this.
- Use the “endpointId” attribute in the event payload to fetch the cloud account and get the endpoint hostname from there.
- Use the “zoneId” attribute in the event payload to fetch the cloud zone and fetch the region from there.
Option one is quite straightforward however it has a drawback in that it only works for vCenter endpoints. Cloud accounts for services like AWS don’t have a hostname therefore if we use this method it’s only going to work for some environments. We could add some additional code to fetch the region if a non-vSphere cloud account is used but then what if the account is configured for multiple regions….
Option two allows me to get to the “Cloud Zone” and then the regionId (which we can use to get the region name) but we won’t be able to get a hostname for deployments to vCenter endpoints. As a cloud zone can only be linked to a single region this option does eliminates the problem of not knowing which region has been used for provisioning.
Instead of either (and in the spirit of making this as agnostic as possible) we are going to combine both approaches. Our execution order will looks as follows:
- Extract zoneId and endpointId from event payload
- Get cloud account using API call with endpointId
- if the account type is vSphere then extract hostname
- Get cloud zone using API call with zoneId
- Get regionId from cloud zone
- Get region using API call with regionId
- Get externalRegionId from region
The first addition we need to make to our overall workflow is to extract the two object IDs we will need. This makes our “Extract Payload” script element now look like this:
machineName = inputProperties.get("resourceNames");
machineID = inputProperties.get("resourceIds");
deploymentID = inputProperties.get("deploymentId");
zoneID = inputProperties.get("zoneId");
endpointID = inputProperties.get("endpointId");
Next on this list is to get the Cloud Account from the endpointId. The swagger interface shows the following API call.

We can turn that into another vRO action following the same layout as previously used.

To determine whether or not the cloud account is for a vCenter endpoint (and therefore whether to try and fetch the hostname value) we can process the cloud account response using our next script element (“Get VC Hostname”).
var jsonCloudAccountResponse = JSON.parse(cloudAccountString);
var accountType = jsonCloudAccountResponse.cloudAccountType;
if(accountType == "vsphere")
{
vcHostname = jsonCloudAccountResponse.cloudAccountProperties.hostName;
}
To supplement the vCenter hostname we are also going to fetch the region name so that we have sufficient information to populate the CMDB no matter whether the endpoint is on-prem or public cloud. This means fetching the cloud zone using its ID (we added the ID extraction from the event payload previously so we don’t need to modify anythign in the payload extraction script). Here’s the action to do that.

To get to the region ID within the cloud zone requires us to traverse a few levels in the cloud zone response, which we can do as follows.
var jsonCloudZoneResponse = JSON.parse(cloudZoneString);
var regionIDLink = jsonCloudZoneResponse._links.region.href;
var index = regionIDLink.lastIndexOf("/");
regionID = regionIDLink.substring(index+1, regionIDLink.length);
Now that we have the regionID we can perform a final lookup to fetch the region by its ID and extract the region name.

var jsonRegionResponse = JSON.parse(regionString);
regionName = jsonRegionResponse.externalRegionId;
The End Result
Stringing all of the above together gives us the following workflow.

Note that this could be tidied up to use less script elements or use sub-workflows but the above gives you a good idea of the steps required to achieve our goal.
Here is the output from the workflow execution kicked off from an event subscription, which simulates what would be sent to a CMDB.

Pingback: Cloud Assembly – Using the API via vRO (Part 1) | vnuggets