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!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s