vCAC

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.

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..

vRealize Automation reservation service API

I was recently looking in to the vRealize Automation REST API reservation service. I was using 6.2.1 and I was tying to create a reservation using the REST API. I think it’s actually a good way to do this as, 1 it’s better than using the ODATA API connecting to the ManagementModelEntities.svc, and 2, I think it’ll be the way forward to use the vRA REST API in the future.

The online documentation for doing this is a good place to start but I found there are errors, which are easily overcome. I will come onto this later, but some of the JSON fields are incorrect. Here’s the documentation link I followed: http://pubs.vmware.com/vra-62/index.jsp?topic=%2Fcom.vmware.vra.programming.doc%2FGUID-75940FA3-1C17-451C-86FF-638E02B7E3DD.html

However, before we get to the errors in the documentation, the first thing I had to do it get a token. I did this using the firefox REST API plugin. To get a token, you need to POST a token request as follows, making sure you add the Content-Type : application/JSON & Accept : application/JSON headers.

Screen Shot 2015-04-22 at 20.43.54

This is a typical response – the “id” is the token.

Screen Shot 2015-04-22 at 20.44.16

So, now I have a token, I can put this in an Authroization Header and save to use in my up and coming REST API calls:

Screen Shot 2015-04-22 at 20.49.52

Notice how I have “Bearer MTQy….” at the beginning of the Value section in the header. You must include Bearer + the API auth token value, otherwise your header isn’t recognized.

Now we have a valid token, we can start using the API service. To create a reservation, you have to build up the reservation JSON POST payload. First, you need to find out some constructs that make up the JSON payload to create a reservation, one being finding the reservation types. Here’s a REST API call to do this (notice this is a GET request not a POST request as we are just getting information):

Screen Shot 2015-04-22 at 20.57.57

The GET URL contains reservation-service/api/reservations/types. This is the URI that you need to append to your vRA host to get the reservation types it supports. Also, notice my tokens (Authorization Bearer token header being the most important, but also my Content-Type : application/JSON & Accept : application/JSON headers). Here’s the response:

Screen Shot 2015-04-22 at 20.58.58

Next, I need to get the subtenant ID. This is the business group in my tenant (I am using the default tenant here, vsphere.local). My business group is called cloud. So to get this value, I need to run  the following REST API GET call:

Screen Shot 2015-04-22 at 21.06.14

The GET URL contains identity/api/tenants/vsphere.local/subtenants. This returns the following:

Screen Shot 2015-04-22 at 21.08.12

The ID in the JSON response can be checked using the vRO vCAC plugin. You need this value to put in the POST payload when creating the reservation. Next up, we need to get the compute resource for the reservation. This one is a REST API POST call, as follows:

Screen Shot 2015-04-22 at 21.16.29

Notice the empty payload {}. I just put this in as otherwise my POST REST request didn’t return anything. I got this back:

Screen Shot 2015-04-22 at 21.16.35

The Compute Cluster is my Compute Resource in vRA. So, to recap, I have my bearer token, reservation type, my business group ID and my compute resource ID.

Next up is a bit more involved. I need to get my resource schema for each of the reservation constructs. Looking at the documentation here, I need to get reservationMemory, reservationNetworks,  computeResource etc. This is where I found some documentation errors, which I will show you in a moment. However to get the resourcePool schema, I need to run the following API REST call:

Screen Shot 2015-04-22 at 22.02.01

The URL appended to the vRA host is /reservation-service/api/data-service/schema/Infrastructure.Reservation.Virtual.vSphere/default/resourcePool/values. This gives me the schema payload for the resourcePool. I need to take the underlyingValue.

Screen Shot 2015-04-22 at 22.02.19

I need to do this for all the required constructs, reservationNetworks, reservationMemory, computeResource, machineQuota, reservationStorages, resourcePool.

My FINAL payload for creating the JSON payload to create a reservation looks like this:


{
 "name" : "TestCreateReservation",
 "reservationTypeId" : "Infrastructure.Reservation.Virtual.vSphere",
 "tenantId" : "vsphere.local",
 "subTenantId" : "727a7899-b074-4f0a-8ccf-08962f7945c3",
 "enabled" : true,
 "priority" : 3,
 "alertPolicy" : {
 "enabled" : true,
 "frequencyReminder" : 20,
 "emailBgMgr" : false,
 "recipients" : [],
 "alerts" : [
 {
 "alertPercentLevel" : 10,
 "referenceResourceId" : "storage",
 "id" : "storage"
 },
 {
 "alertPercentLevel" : 20,
 "referenceResourceId" : "memory",
 "id" : "memory"
 },
 {
 "alertPercentLevel" : 30,
 "referenceResourceId" : "cpu",
 "id" : "cpu"
 },
 {
 "alertPercentLevel" : 40,
 "referenceResourceId" : "machine",
 "id" : "machine"
 }
 ]
 },
 "extensionData" : {
 "entries" : [
 {
 "key" : "reservationNetworks",
 "value" : {
 "type" : "multiple",
 "elementTypeId" : "COMPLEX",
 "items" : [
 {
 "type" : "complex",
 "componentTypeId" : "com.mycompany.csp.iaas.blueprint.service",
 "componentId" : null,
 "classId" : "reservationNetwork",
 "typeFilter" : null,
 "values" : {
 "entries" : [
 {
 "key" : "networkPath",
 "value" : {
 "type" : "entityRef",
 "componentId" : null,
 "classId" : "Network",
 "id" : "c086a74b-cda1-44fe-8873-ec647265ed08",
 "label" : "VM Network"
 }
 }
 ]
 }
 }
 ]
 }
 },
 {
 "key" : "reservationMemory",
 "value" : {
 "type" : "complex",
 "componentTypeId" : "com.mycompany.csp.iaas.blueprint.service",
 "componentId" : null,
 "classId" : "reservationMemory",
 "typeFilter" : null,
 "values" : {
 "entries" : [
 {
 "key" : "hostMemoryTotalSizeMB",
 "value" : {
 "type" : "integer",
 "value" : 10240
 }
 },
 {
 "key" : "memoryReservedSizeMb",
 "value" : {
 "type" : "integer",
 "value" : 10240
 }
 }
 ]
 }
 }
 },
 {
 "key" : "computeResource",
 "value" : {
 "type" : "entityRef",
 "componentId" : null,
 "classId" : "ComputeResource",
 "id" : "4ad3b822-1099-4355-91b1-47d4dd8f8a56",
 "label" : "Compute Cluster"
 }
 },
 {
 "key" : "machineQuota",
 "value" : {
 "type" : "integer",
 "value" : 2
 }
 },
 {
 "key" : "reservationStorages",
 "value" : {
 "type" : "multiple",
 "elementTypeId" : "COMPLEX",
 "items" : [
 {
 "type" : "complex",
 "componentTypeId" : "com.mycompany.csp.iaas.blueprint.service",
 "componentId" : null,
 "classId" : "reservationStorage",
 "typeFilter" : null,
 "values" : {
 "entries" : [
 {
 "key" : "storageTotalSizeGB",
 "value" : {
 "type" : "integer",
 "value" : 50
 }
 },
 {
 "key" : "storageReservedSizeGB",
 "value" : {
 "type" : "integer",
 "value" : 50
 }
 },
 {
 "key" : "storageEnabled",
 "value" : {
 "type" : "boolean",
 "value" : true
 }
 },
 {
 "key" : "storagePath",
 "value" : {
 "type" : "entityRef",
 "componentId" : null,
 "classId" : "StoragePath",
 "id" : "48d5b4fc-ab89-4483-ab15-20c0eaab210b",
 "label" : "of-nfs01"
 }
 },
 {
 "key" : "storageFreeSizeGB",
 "value" : {
 "type" : "integer",
 "value" : 50
 }
 },
 {
 "key" : "storageReservationPriority",
 "value" : {
 "type" : "integer",
 "value" : 1
 }
 }
 ]
 }
 }
 ]
 }
 },
 {
 "key" : "resourcePool",
 "value" : {
 "type" : "entityRef",
 "componentId" : null,
 "classId" : "ResourcePools",
 "id" : "79e1f291-1001-4ec3-b0b2-c094f8fc865e",
 "label" : "Resources"
 }
 }
 ]
 }
 }

The errors I got were around the wrong constructs being passed in. I received this message:

{
"errors": [
{
"code": 11001,
"message": "Field with id networkPath is required.",
"systemMessage": "Field with id networkPath is required.",
"moreInfoUrl": null
},
{
"code": 11001,
"message": "Field with id storagePath is required.",
"systemMessage": "Field with id storagePath is required.",
"moreInfoUrl": null
},
{
"code": 11001,
"message": "Field with id storageReservationPriority is required.",
"systemMessage": "Field with id storageReservationPriority is required.",
"moreInfoUrl": null
},
{
"code": 11001,
"message": "Field with id storageEnabled is required.",
"systemMessage": "Field with id storageEnabled is required.",
"moreInfoUrl": null
}
]
}

Once I substituted the fields with the correct ones, my JSON payload was good. For example

storageEnabled = reservationStorageEnabled
storageReservationPriority = reservationStorageReservationPriority

You can get these values from LINQPAD as this is the ODATA entities it is expecting.

Good luck!