vRealize Automation

vRealize Automation bulk update lease on Virtual Machines

I wrote a workflow that takes some inputs and uses an ODATA query to list all virtual machines where their lease is expiring within a certain time frame.

It uses the API to get all the virtual machines and then you can bulk update these lease days by changing the value for the numberOfDaysToAdd variable.

You will need to add the vCACCAFE:vCACHOST value for the host attribute and also make sure that the plugin user configure has the right privileges and entitlements.


var operationName = "Change Lease";
var numberOfDaysToAdd = 30;
var leaseEndDate = "2017-08-15T00:00:00.000Z";
var pageSizeLimit = "20"
var endpoint = "com.vmware.csp.core.cafe.catalog.api";
var restClient = host.createRestClient(endpoint);

var pages = parseJson(api());
System.log("Number of pages found from API query: " + pages.metadata.totalPages);

for (i=1; i-1 < pages.metadata.totalPages; i++){

var json = parseJson(api(i));
if (i >1) {
System.log("Processing page " + i + " of pages." + metadata.totalPages + " . Sleeping for 60 seconds whilst vRA processes change lease operations.");
System.sleep(60000);
}

for each (deployment in json.content){
System.log("Found Deployment: " + deployment.name);
var catalogResource = vCACCAFEEntitiesFinder.findCatalogResources(host , deployment.name)[0];

System.log("Found catalog Resource " + catalogResource.name);

var newLeaseDate = new Date();
newLeaseDate.setDate(newLeaseDate.getDate() + numberOfDaysToAdd);

System.log("Setting new lease date to " + newLeaseDate);

var myvCACCAFEDateTimeLiteral = new vCACCAFEDateTimeLiteral(newLeaseDate) ;

//Get all the operations that are available on the deployment
var operations = catalogResource.getOperations();
var resourceActionNotFound = false;

//Locate the deployment specific operations and store it
for each (operation in operations){
System.log(workflow.currentWorkflow.name + ": " + operation.getName() + " operation is available on this catalog resource")
if (operation.getName().toLowerCase() == operationName.toLowerCase()){
System.log(workflow.currentWorkflow.name + ": " + operation.getName() + " operation identified and selected");
resourceActionNotFound = true;
break;
}
}
if (resourceActionNotFound == false) {continue};

var inputs = new Properties();
inputs.put("provider-ExpirationDate", myvCACCAFEDateTimeLiteral);

System.getModule("com.vmware.library.vcaccafe.request").requestResourceAction(operation,inputs)

}
}

function api(page){

var url = "consumer/resources?&limit=" + pageSizeLimit;
if (page) url = url + "&page=" + page.toString();
var catItemsUrl = url + "&$filter=resourceType/id eq 'composition.resource.type.deployment' and lease/end lt '" + leaseEndDate + "'";
var catItems = restClient.get(catItemsUrl);
return catItems.getBodyAsString();

}

function parseJson(res){

return JSON.parse(res.replace(/\\/g, '').replace(/\\t/g, '').replace(/\\r/g, '').replace(/\\n/g, ''));
}

vRealize Automation & Orchestrator – Updating blueprints deployment values using the Orchestrator createRestClient() method

I’ve been using the createRestClient() for a number of use cases recently and today I had to bulk update all the vRealize Automation composite blueprint deployment values along with each components maximum cluster values.

Here is my code I used:


//Set inputs
var componentMaxValue = 1;
var deploymentNumberOfInstances= 10;

// create rest endpoint for rest client
var endpoint = "com.vmware.csp.component.cafe.composition.api";
var restClient = vcacCafeHost.createRestClient(endpoint);
var blueprintsUrl = "blueprints";

// get blueprints
var blueprints = restClient.get(blueprintsUrl);
var res = blueprints.getBodyAsString();

//clean json and parse
var json = JSON.parse(res.replace(/\\/g, '').replace('\t','').replace('\r','').replace('\n',''));

// get all blueprints - match on name
for each (var blueprint in json.content){

System.log("Blueprint name: " + blueprint.name);
var blueprintsUrl = "blueprints/" + blueprint.id;
System.log("URL for blueprint " + blueprintsUrl);

// get blueprint test
var blueprints = restClient.get(blueprintsUrl);
var res = blueprints.getBodyAsString();

try {
//clean json and parse
var json = JSON.parse(res.replace(/\\/g, '').replace('\t','').replace('\r','').replace('\n',''));
}
catch(e){
System.log(e + ": Could not parse JSON payload for " + blueprint.name);
continue;
};

// gets all components.
for (var component in json.components){
if (json.components[component].data._cluster){
System.log("Found component " + component);
System.log("Current min value configured for component " + json.components[component].data._cluster.facets.minValue.value.value);

delete json.components[component].data._cluster.facets.maxValue.value.value;
json.components[component].data._cluster.facets.maxValue.value.value = componentMaxValue;
};
};
if (json.properties._number_of_instances){

System.log("Current number of instances value configured for blueprint " + json.properties._number_of_instances.facets.maxValue.value.value);
delete json.properties._number_of_instances.facets.maxValue.value.value;
json.properties._number_of_instances.facets.maxValue.value.value = deploymentNumberOfInstances;

};
json = JSON.stringify(json);
restClient.put(blueprintsUrl, json);
};

A couple of key things to point out.

var endpoint = "com.vmware.csp.component.cafe.composition.api";
var restClient = vcacCafeHost.createRestClient(endpoint);

This sets the API endpoint to use when creating the vCACCAFE REST Client method.

Once you have the REST client created, you then need to append the various URLs when calling a REST operation using the client. Fro example, to get all the blueprints, would would need to append this:

var blueprintsUrl = "blueprints";

Simply, this creates the complete REST URL to get all blueprints.

Once we get the JSON response, then we can loop through all the blueprints and start appending to the UR, which is this bit of code:

for each (var blueprint in json.content){

    System.log("Blueprint name: " + blueprint.name);
    var blueprintsUrl = "blueprints/" + blueprint.id;

}

You need to use the ID of each blueprint as the ID doesn’t allow any special characters and is set when you create the blueprint.

Once you have the JSON payload for your blueprints, you can loop through and get / set the various values you want, but you will need to loop through you components in order to find the virtual machines that are within your CBP. This is the code that sorts that out:

for (var component in json.components){

        if (json.components[component].data._cluster){
            System.log("Found component " + component);
            System.log("Current min value configured for component " + json.components[component].data._cluster.facets.minValue.value.value);
        }
}

You can match on a particular name here but I am just setting defaults for all my blueprints by firstly deleted the JSON object for the maxValue and then adding a new value:

delete json.components[component].data._cluster.facets.maxValue.value.value;
json.components[component].data._cluster.facets.maxValue.value.value = componentMaxValue;

Notice my inputs are at the top of the script and these could be input parameters in you vRO workflow.

Then once you have set your JSON payload for each blueprint, just do a put and update the CBP using this bit of code:

json = JSON.stringify(json);
restClient.put(blueprintsUrl, json);

You will notice the blueprintsUrl is set for each composite blueprint and therefore your JSON payload is updating specific values for each of your blueprints.

I’ll keep saying that the vRA REST API has come a long way and once you get your feet wet, you can quickly start deploying, managing and configuring resources within your environment.

Remember to set the vcacCafeHost attribute to your CAFE host configured using a user that has the right privileges to update your CBP’s.

vRealize Automation & Orchestrator API ODATA Filters

This is following on from my recent http://virtualdevops.com/2017/03/22/using-createrestclient-in-vrealize-orchestrator-to-create-vrealize-automation-rest-calls/ blog as I often hear people are confused about ODATA filters and specifically, what filters are available to use in both Orchestrator and the vRealize Automation API

ODATA is a common feature used in API calls to apply filter queries to obtain a subset of information based on the query passed in to the REST API call. ODATA filters can be used in both vRA REST calls and vRO workflows. This blog explores a couple of different ways to interact with the vRA REST API and vRO workflows to help minimize the data set returned in the response. Before we look in more detail on how to construct these API calls, lets go through some basic ODATA expressions:

Select a range of values

filter=Entry_No gt 610 and Entry_No lt 615

And

filter=Country_Region_Code eq 'ES' and Payment_Terms_Code eq '14 DAYS'

Or

filter= Country_Region_Code eq 'ES' or Country_Region_Code eq 'US'

Less than

filter=Entry_No lt 610

endswith

filter=endswith(VAT_Bus_Posting_Group,'RT')

startswith

filter=startswith(Name, 'S')

These are some of the most common parameters used, but it doesn’t stop there.

Additionally, it is import to append the pagesize and limit to you ODATA filter to limit the dataset returned.

&page=1&limit=50

The page size is important when expecting a large dataset response. Without providing a pagesize or a limit size, the defaults will be used, which might mean the dataset does not include the information you are expecting.

It is also worth noting that the filter expressions are discussed in the API docs found on the vRealize Automation 7.1+ appliance. To access the docs, goto the following URL on a vRealize Automation 7.1+ appliance

https://{{vra-fqdn}}/component-registry/services/docs

With the above information in mind, let’s start looking at some basic ODATA filter expressions that can be used.

I am using POSTMAN as a REST client to interact with the vRA API.

Take this URI example:

https://vra-01.mylab.com/catalog-service/api/consumer/resources/

I only have a few catalog resources but see the following response:

"metadata": {
    "size": 20,
    "totalElements": 29",
    "totalPages": 2,
    "number": 2,
    "offset": 20
}

This shows that there is a total of 29 elements in the response, 2 pages and a size of 20. This means that the JSON response has 2 pages and the 1st page list the first 20 elements. You would need to go to page 2 to get the other 9 elements. If using POSTMAN, you can see the HREF element that shows you what pagesize and limit defaults are being used.

“href”: https://vra-01.mylab.com/catalog-service/api/consumer/resources/?page=2&limit=20

By changing the pagesize and limit, you can control how many elements are returned, or you can search through each page to find the element that you want.

To limit the response to 40 items instead of the default 20 in this case

https://vra-01.mylab.com/catalog-service/api/consumer/resources/?limit=40

or to get to page 2,

https://vra-01.mylab.com/catalog-service/api/consumer/resources/?page=2

However, even though it is important to understand the pagesize and limit used, it is not an efficient way to query resources using the API.  Many times, the query is set with a large limit and a pagesize of 1 to accommodate all resources, but it’s not an efficient way to find resources. What happens if you have 000’s of resources or you have more resources than what your limit is set to? Here is where you can use ODATA filters and use filter expressions to minimize the result set.

So how do we do this? One way is to read the API docs that come with vRealize Automation and it is important to read through how ODATA filters work.

A very simple example is to add a query expression that targets a particular name or ID. For example:

https://vra-01.mylab.com/catalog-service/api/consumer/resources/?
$filter=id eq '21da4606-ebfa-440e-9945-6ef9102c6292'

If you look at the metadata, you can see we have only one element returned:

"metadata": {

    "size": 20,
    "totalElements": 1,
    "totalPages": 1,
    "number": 1,
    "offset": 0

  }

This is indeed the element that has the ID equal to 21da4606-ebfa-440e-9945-6ef9102c6292.

Just breaking down the filter expression, here is how it worked:

$filter=id eq '21da4606-ebfa-440e-9945-6ef9102c6292'

The $filter is used and is set to equal an expression. In this case id eq ”

You can append the pagesize and limit with a filter. For example:

?page=1&limit=1&$filter=id eq ''

Notice the ? used to append a query to the URI, the & sign to have multiple filters and the $filter value which is the beginning of the ODATA filter query.

We can do additional searches too.

https://vra-01.mylab.com /catalog-service/api/consumer/resources/
?$filter=id eq '21da4606-ebfa-440e-9945-6ef9102c6292' 
or id eq 'f89877f9-7c86-43e1-9956-9cefe22f127e'

Just checking the metadata, we can see the following

  "metadata": {

    "size": 20,
    "totalElements": 2,
    "totalPages": 1,
    "number": 1,
    "offset": 0

  }

That matches our query as we see 2 elements returned.

If we supply an invalid ID, it simply doesn’t return an element.

This is all straight forward so far, so how do we do more complex ODATA filters? Well, there are a couple of ways to see how filters are used within vRealize Automation that will help you understand how to append ODATA filters to your API calls.

The first way is to look at the access_lot.txt log file that resides in /var/log/vcac/. This log file shows you all the API calls that are being made either by an end user or the vRealize Automation system. Looking at this log file can help you understand more complex ODATA filters.

You can simply use the UI and execute a search, which logs the ODATA filter used in the UI when searching in the access_log.txt  . A good example of this is searching for catalogue items as we have a nice advanced search box that we can use to trigger a ODATA search.

Screen Shot 2017-04-09 at 19.21.30

Searching the access_log.txt log file, I can see the following API call which show how the search made via UI translates in to a more complex ODATA query.

/catalog-service/api/catalogItems/?$top=30&$skip=0&$orderby=name%20
asc&$filter=substringof%28%27docker%20-%20coreos%27%2Ctolower%28
name%29%29%20and%20substringof%28%27sample%27%2Ctolower%28
description%29%29%20and%20outputResourceType%2Fid%20eq%20%27
composition.resource.type.deployment%27%20and%20providerBinding%2F
provider%2Fid%20eq%20%275a4f1ed5-7a6c-4000-8263-5cbbcc888e84%27%20
and%20status%20eq%20%27PUBLISHED%27%20and%20organization%2F
tenant%20ne%20null

The URL has been encoded but we can simply decode this using an online decoder to give you the format that you require:

/catalog-service/api/catalogItems/?$top=30&$skip=0&$orderby=name 
asc&$filter=substringof('docker - coreos',tolower(name)) and 
substringof('sample',tolower(description)) and outputResourceType/id 
eq 'composition.resource.type.deployment' and 
providerBinding/provider/id eq '5a4f1ed5-7a6c-4000-8263-5cbbcc888e84'
and status eq 'PUBLISHED' and organization/tenant ne null

Some interesting filters have been used, specifically new filters we haven’t discussed, for example  substringof(‘docker – coreos’,tolower(name)).

Substringof returns name records for catalog items with names containing the string ‘docker – coreos’

We could also use this :

catalog-service/api/catalogItems/?$filter=startswith(name,'Docker')

This returns 2 results as expected, as we have 2 OOTB catalogue items that have a name that starts with Docker.

You can also do precedence grouping which enables you to override the precedence conventions to manipulate your dataset based on the precedence grouping defined.

catalog-service/api/catalogItems/?$filter=substringof
('docker - coreos',tolower(name)) and 
substringof('sample',tolower(description))

You can list all virtual machines that were created between 2 different dates:

/catalog-service/api/consumer/resources/?$filter=(dateCreated 
gt '2017-01-01T00:0:00' and dateCreated le ‘17-01-02T00:0:00')

This will display all virtual machine created between ‘2017-01-01T00:0:00’ and ‘2017-01-02T00:0:00’

You can actually append a filter to this precedence and say all virtual machine that are active.

/catalog-service/api/consumer/resources/?$filter=(dateCreated 
gt '2017-03-29T11:42:00' and dateCreated le '2017-03-29T11:50:00') 
and status eq 'ACTIVE'

To be safe, you could make the active status to uppercase, just to ensure any parameters programmatically set are capitalized

catalog-service/api/consumer/resources/?$filter=(dateCreated gt 
'2017-03-29T11:42:00' and dateCreated le '2017-03-29T11:50:00') 
and status eq toupper('active')

Additionally, you can use the orderby function to sort your queries too.

orderby=dateSubmitted+desc

But how do we know what parameters can be passed in using the ODATA filter?

Well, this is a bit of trial and error. You can use the JSON response elements and using the key element and see whether you get results you are expecting that means the expression is working successfully. So take this JSON response payload:

  {

      "@type": "CatalogResource",
      "id": "21da4606-ebfa-440e-9945-6ef9102c6292",
      "iconId": "cafe_default_icon_genericCatalogItem",
      "resourceTypeRef": {
        "id": "composition.resource.type.deployment",
        "label": "Deployment"
      },
      "name": "vm-app-01-88805337",
      "description": null,
      "status": "ACTIVE",
      "catalogItem": {
        "id": "8e04dceb-f040-4bbc-b312-8a1b0d0a3b95",
        "label": "VM app 01"
      },
      "requestId": "3f49e42a-5e4e-4293-b3f0-eff2a34a5108",
      "providerBinding": {
        "bindingId": "3ee7fe9f-197c-4fac-8e59-cea6ac4f2336",
        "providerRef": {
          "id": "5a4f1ed5-7a6c-4000-8263-5cbbcc888e84",
          "label": "Blueprint Service"
        }
      },
      "owners": [
        {
          "tenantName": "vsphere.local",
          "ref": "oleach@vmware.com",
          "type": "USER",
          "value": "Oliver Leach"
        }
      ],
      "organization": {
        "tenantRef": "vsphere.local",
        "tenantLabel": "vsphere.local",
        "subtenantRef": "8723d842-d6f0-48c0-b0a3-e555eaeecdd5",
        "subtenantLabel": "Corp"
      },
      "dateCreated": "2017-01-00T00:00:00.000Z",
      "lastUpdated": "2017-01-00T00:00:00.000Z",
      "hasLease": true,
      "lease": {
        "start": "2017-01-00T00:00:00.000Z"
      },
      "leaseForDisplay": null,
      "hasCosts": true,
      "totalCost": null,
      "hasChildren": false,
      "operations": null,
      "forms": {
        "catalogResourceInfoHidden": false,
        "details": {
          "type": "external",
          "formId": "composition.deployment.details"
        }
      },
      "resourceData": {
        "entries": []
      },
      "destroyDate": null,
      "pendingRequests": []
    },

We can test setting the expression filter to use any of the above JSON payload elements, although there are ones that won’t work and other caveats you need to follow.

For example, take the request ID. This should look like ?$filter=requestId, however that doesn’t work. Trial and error lead me to use ?$filter=request as shown here:

catalog-service/api/consumer/resources/?$filter=request 
eq '3f49e42a-5e4e-4293-b3f0-eff2a34a5108'

Additionally, in the vRA API docs, there are some caveats to be aware of. See this notes in the API docs.

Note: Notice how even though the providerRef object contains a label element, we use provider (and not providerRef) and name (and not label) to craft the filter:

$filter=provider/name eq 'theName'
      "providerBinding": {
        "bindingId": "cd1c0468-cc1a-404d-a2e0-a4e78fc06d4d",
        "providerRef": {
          "id": "2575e506-acfe-487a-b080-9898a30f519f",
          "label": "XaaS"
        }
      },

Therefore, in order to get all providers that are of type XaaS, we need to run the following ODATA filter

/catalog-service/api/consumer/resources/?$filter=
providerBinding/provider/name eq ‘XaaS’

Notice provider is missing the Ref and the label is now the name. However, you can just use id too, for example:

catalog-service/api/consumer/resources/?$filter=
providerBinding/provider/id eq 
'2575e506-acfe-487a-b080-9898a30f519f'

In order to get to an element that is an array, for example using the owner information in above JSON payload, you can simply do this:

catalog-service/api/consumer/resources?$filter=owners/ref 
eq 'oleach@vmware.com'

You can also use firebug or chrome dev tools to see what API calls are being made via the UI and intercept the API call and look at the filters being used. For example, let’s redo the search we did above to see catalogue item entitlements and sniff the request using the firebug add-on in Firefox.

Here you can see the output of firebug:

Screen Shot 2017-04-08 at 12.34.14

The request URL will give you the UTF-8 encoded format and you can see also the ODATA filters used.

Additionally, you can also use ODATA filters in vRealize Orchestrator and these principles still apply.

Take this code example:

service = cafeHost.createCatalogClient().getCatalogConsumerResourceService();

var filter = new Array();

filter[0] = vCACCAFEFilterParam.substringOf("providerBinding/provider/id",
vCACCAFEFilterParam.string('2575e506-acfe-487a-b080-9898a30f519f'));
var query = vCACCAFEOdataQuery.query().addFilter(filter);
var odataRequest = new vCACCAFEPageOdataRequest(1, 10000, query);
resources = service.getResourcesList(odataRequest);

You can add you filter parameters in the same was as you can using the API ODATA filters.

To add additional parameters, you can build up the filter array with your queries.

Remember to consider the caveats I have been talking about above but by using the API JSON response, you can determine what filters to use. Please add comments if you find any caveats regarding ODATA filters not mentioned above.

vRealize Automation – Changing a Virtual Machine’s Business Group in 7.2 and 6.x

Changing business groups in both vRealize Automation v6 and v7 is a common task and below demonstrates how to automate the process. Luckily, VMware provides an out of the box vRealize Orchestrator workflow solution in both vRealize 6.x and 7.2, however, the workflow you need to use in both versions is different. Let’s have a look:

vRealize Automation 7.2

As of v7.2, we have a new workflow that changes the business group of the IaaS virtual machine entity as well as the CAFE deployment entity. The virtual machine entity is still part of the IaaS model, however, the deployment is a CAFE entity and therefore there are a few things you need to be aware of before changing the business group. We’ll cover those later. However, here is a screenshot of the workflow that you need to use:

The workflow you need to run to change business group can be found in the following location, noting this is under the Library folder:

screen-shot-2017-01-28-at-16-55-52

You need to provide the following inputs:

Screen Shot 2017-01-28 at 16.56.39.png

There are a few things to be considered.

1 – The owner of the virtual machine must also be a member of the target business group. The business group is determined based on the reservation you select. If the user is not a member of the target business group, the virtual machine IaaS entity business group will get updated, however, the deployment CAFE entity business group entity will not get updated, leaving you in a position where the 2 entities that are out of sync. If this is the case, your my items will be out of sync as the deployment will still appear under the original business group but the virtual machine will appear under the new business group.

2 – You may have more than one Virtual Machine within the deployment so make sure you update all virtual machine entities within the deployment.

3 – This workflow is not available prior to version vRealize Automation 7.2, although if you need it, contact VMware GSS support as they may be able to help you get your hands on a fix. Or, better still upgrade to vRealize 7.2.

Based on the above, one way I would implement this solution would be to create a day 2 operation on the deployment CAFE entity. Then you can do a couple of things as follows:

1 – Check that the owner of the deployment is a member of the target business group. If not, flag this on the day 2 XaaS form.

2 – Get all virtual machines that are part of the deployment so you update all virtual machines which are part of the deployment.

That’s it but you can enhance the custom day 2 resource operation if you need to.

vRealize Automation 6.x

In my opinion, it is slightly easier to update the virtual machine business group as we don’t have to worry about the CAFE deployment as the entity doesn’t exist in vRA 6.x. We do have MMBP, but this is part of the IaaS model which can be updated. This post just concentrates on single machine blueprints. The workflow you need to run to change business groups can be found in the following location, noting this is under the Library folder:

Screen Shot 2017-01-28 at 17.12.29.png

You can just run the import vCAC Virtual Machine and you can rerun this over an over again. It won’t register the machine multiple times but just update the business group based on the following inputs:

screen-shot-2017-01-28-at-17-14-02

You can see there are few more options to supply in vRA 6.x. You can also make this a day 2 operation by wrapping this workflow around another workflow as you can see the actual code that changes the business group is this:

vm.register()

Where vm is a vCAC:VirtualMachine type. You can see this in the ‘start register workflow‘ scripting element.

You can see the requirements parameters using the API library, but here’s a screenshot of what you need:

screen-shot-2017-01-28-at-17-18-32

That’s pretty much it. Happy Business Group Automating.

vRealize Automation 7. How to get Deployment Name and Virtual machines from a deployment

In vRealize Automation 7, we have a deployment now that contains all the resources. This is different to how it worked previously. But how do we get information about the deployment, so in a case that we need to update the owner of a deployment if we have deployed a composite blueprint using XaaS?

Here is  snippet of code I use to determine what is what in the deployment.

screen-shot-2016-11-11-at-16-04-36

The key is once you have found the catalogue resource, this line determines whether it is the deployment or virtual machine.

var catResources = vCACCAFEEntitiesFinder.findCatalogResources(cafeHost);
var resourceName = "<deployment name>;
for each (resource in catReosurces){
    if (resource.resourceTypeRef.getLabel() == "Deployment")) +
    resource.getName() == resourceName;
        catalogResource = resource;
break;
}

The getLabel() tells you whether it is a virtual machine or whether its the deployment. Now , once you have the catalogue resource, you can get the deployment and execute a change owner on the deployment.

var operations = catalogResource.getOperations();
var operationName = 'Change Owner';

for each(op in operations){
    System.log(workflow.currentWorkflow.name + ": " + op.getName() +
    " operation is available on this catalog resource");
    if (op.getName() = operationName){
        System.log(workflow.currentWorkflow.name + ": " + op.getName() +
        " operation identified and selected");
        changeOwnerOperation = op;
        break;
    }
}

Now we have the operation of on the deployment, we can pass that in to the requestResourceAction in vRealize Orchestrator and submit the change owner process.

The inputs to the resource action requires the vCACCAFE:ConsumerResourceOperation and the payload for the new user. The payload is a property object. as follows:

ownerProperties = new Properties();
ownerProperties.put("provider-NewOwner", newOwner);

This helps go some way to changing the owner of a deployment. Great is you need to use XaaS to wrap deployments. In future releases, we won’t need to do this as we will have the ability to hide CBP from the catalogue. So we will be able to deploy a catalogue item using the correct owner but the owner won’t see the catalogue item as you can mark it hidden. Hence the logged in user won’t see the catalogue item, but still be entitled to request it.

vRealize Orchestrator 7 VAPI vSphere tags workflow

I created a workflow using the VAPI plugin to assign vSphere tags to a VC:VirtualMachine object.

You will need to import the package, then configure VAPI with your vCenter endpoints by following these instructions:

1 – Run the Import VAPI metamodel workflow

2 – Run the Add VAPI endpoint workflow

Both workflows take the same inputs, but you must run the workflows in that order. Screen shot of inputs as follows:

Screen Shot 2016-07-19 at 22.56.04

 

Once you have configured your VAPI endpoints, download the following package from github

com.virtualdevops.tags.package

Import the package and then the following workflows and actions.

Screen Shot 2016-07-19 at 23.02.25

Screen Shot 2016-07-19 at 23.03.11

Run the Add tag to VC vm workflow (highlighted in the package screen shot above), and as long as you have configured VAPI endpoints, you can add vSphere Tags and vSphere Categories to a VC:VirtualMachine object.

10_26_38_40

  • The vCenter Virtual Machine is the VC:VirtualMachine object
  • The VAPI Endpoint drop down list should contain all your VAPI endpoints
  • The Create new Tag Category allows you to create a new Category
  • The Tag Category displays existing tag categories configured on your VAPI Endpoint
  • The Tag Name is the name of the tag you wish to create
  • The Tag description is the description and is optional

Code is more of an example, as I found the OOTB VAPI plugins for tags pretty limited. You can move the input parameters to attributes as desired and pass in values for the tag name using maybe an API call to a SNOW or CMDB to get values for your tag name.

Any issues, send in a comment.

 

Updating vRA ASD Service Blueprint workflows

There isn’t an easy way to find out what vRealize Orchestrator workflow is associated to a vRealize Automation Service Blueprint. You can query the vPostgres database to find out the workflow ID as follows:

1 – Log in to vPostgres and connect to the vcac database

2 – Run the following SQL command

vcac=# \x on;
Expanded display is on.
vcac=# select * from asd_serviceblueprint;

This should output something similar to this:

-[ RECORD 1 ]------------------------------------------------
id | 850b9e17-024e-44f7-9831-a5651a5d6e0f
description | This is a workflow description.
name | My XAAS workflow
status | 1
tenant | vsphere.local
workflowid | 1eea8b02-15e8-41b8-992e-3df1cd8e4b99
baseform |
outputparameter | ea001bf4-d43f-4c74-a010-b6027c7ecbdf
catalogrequestinfohidden | t
version | 1.0.0
-----------------------------------------------------------

You can change the vRealize Orchestrator workflow that gets called by a vRealize Automation service blueprint pretty easily, by changing the workflow ID value in the vPostgres database

vcac=# update asd_serviceblueprint 
set workflowid='ad9e2cc2-2efa-44c1-a574-6a02bec2f998'
where id = '9d6510ad-24a6-4f0c-adc8-736cc3e99d77';

This will change what workflow gets executed without redeploying the ASD form. It’s handy when you want to clone the ASD service blueprint and actually change the underlying workflow to test something new, without having to rebuild the ASD form.

You can also run a vRealize Orchestrator workflow using the below javascript to find out what the name is using the workflow ID

wfId = '9d6510ad-24a6-4f0c-adc8-736cc3e99d77'
System.log("Workflow name: " + Server.getWorkflowWithId(wfId).name);

 

All of this can be managed by creating your own service blueprint and publishing as a catalog item..