Provisioning a VM from an OVF is easy with vRealize Automation

Since the Project Cava team started writing about how they use vRealize Automation to serve the needs of the VMware teams that work on vRealize Automation, its been clear that customers want to know how we manage to keep a small catalog by deploying from OVFs in our build farm.  In our case we’re using properties supplied at request time to control many aspects of the deployment including the build type being deployed and the build number.

vRealize Automation Catalog Item with User Input
vRealize Automation Catalog Item with User Input

These are reflected as custom properties on the actual request and get passed to vRealize Orchestrator workflows during the vRealize Automation provisioning lifecycle.  Specifically we take advantage of the BuildingMachine stub to call out to vRealize Orchestrator so that it can do the heavy lifting for us:

  • Compute the expected template name and check if the template already exists in the target vCenter
  • Lookup the OVF URL based on the build number
  • Upload the OVF using the OVF Transfer Plugin by SVA
  • Update the vRealize Automation request to clone from the template that was uploaded

The vRealize Orchestrator workflow

OK Here’s the workflow, looks simple right?  In case it doesn’t we’ll go into more of the important details, keep reading.

vRealize Orchestrator Workflow Stub for Building Machine state
vRealize Orchestrator Workflow Stub for Building Machine state

Reading Properties and Computing OVF Location

The first step is to digest the request and compute the name of the template that we’re looking for, the code takes the vCACVmProperties and extracts the properties for the build type and build number in our build farm called “GoBuild”.  This content is served over HTTP so its easy to consume through a standard web client.

// Lookup blueprint GoBuild custom properties
function validate(property){
 if(!vCACVmProperties[property] || vCACVmProperties[property] == ""){
 throw "Lookup request properties - Mandatory VM field not set: gobuild." + property;
 }
 //display passed in property value
 //System.log("gobuild." + property + "=" + vCACVmProperties[property]);
 return vCACVmProperties[property];
}

var buildProduct = validate("gobuild_product");
buildType = validate("gobuild_product_" + buildProduct.replace(/-/g,'_') + "_type");
buildNumber = validate("gobuild_product_" + buildProduct.replace(/-/g,'_') + "_number");
// Empty when targeting root component
componentPath = [];

// Generate GoBuild VM template name
virtualMachineName = buildProduct + "-" + buildType + "-" + buildNumber;

// Lookup OVF custom properties
vappProperty = new Properties()
var vappConfigPropertyNamespace = "vappconfig.property.";
for (var propertyName in vCACVmProperties){
 if(propertyName.indexOf(vappConfigPropertyNamespace) == 0 && propertyName.length > vappConfigPropertyNamespace.length ){
 var relativePropertyName = propertyName.split(vappConfigPropertyNamespace)[1];
 vappProperty[relativePropertyName] = vCACVmProperties[propertyName];
 }
}

This outputs the virtualMachineName, buildNumber and buildType for later use in the workflow.  The first place that this is used is checking if the needed template exists in vCenter.  This is done through the out-of-the-box plugin for vCenter by calling Find VM By Name.

Looking up the OVF URL

Looking up the OVF URL happens by passing buildNumber, and buildType into the GoBuild plugin that we wrote to work with our build system.  This outputs a list of artifacts produced in the build that match our pattern.  This is passed into the Extract OVF Location script task which outputs the ovfLocationUrl string and does some simple error checking.  This is something like https://<buildserver>/<build type>/<build number>/deliverables/<Virtual Appliance OVF Name>.ovf

//Verify whether parameters about requested vRA VA OVF returned by 
//are not empty and pick up 1st array element as a location 
if(buildDeliverables.length > 0){
 ovfLocationUrl = buildDeliverables[0];
 System.log("nn CHECK: Target vRA VA OVF location on BuildWeb: " + ovfLocationUrl +"n");
} else { //Throw an exception
 throw "Extract BuildWeb OVF location URL - failed to retrieve VA OVF location, buildDeliverables.length ="+buildDeliverables.length;
}

Uploading the Template

Once we have the location of the OVF and some details about the vCenter that we need to upload into we’re able to construct the upload request using the OVF Transfer plugin from SVA , that is available on the VMware Solution Exchange

OVF Transfer Plugin Upload Workflow
OVF Transfer Plugin Upload Workflow

Pulling it All Together

We’ve done the work of:

  • Determining which OVF is needed
  • Uploading it into the vCenter

If all you need to do is upload a new version of an existing template and proceed with the clone you’re done, there’s nothing more that you need to do.

At the end of the day we get a catalog with 1 item that can provision any build of vRealize Automation.  Its simple for users, its low impact for administrators and it doesn’t create lots of blueprints

vRealize Automation Simple Catalog
vRealize Automation Simple Catalog

Our workflow goes on to make some changes to the internal IaaS Repository to manipulate entries on the Virtual Machine Properties, which lets us use new templates in addition to updating already in use ones.  We won’t go into that here because there is no guarantee that that will be supported going forward and it may cause upgrade problems.

You can save the time of manually keeping blueprints in sync with recommended builds when you build on what I’ve described here.  This lets you easily replace an existing template like a recommended build.  You can also take this as a starting point for building an XaaS catalog item to upload an OVF from an HTTP server and push it into vCenter for later use authoring blueprints.  We’ll follow up with more on this later.