Provisioning vRealize Automation Catalog Items with Ruby

Posted by

Overview

In this post I’m going to show how to provision vRealize Automation (vRA) catalog items with Ruby.  I’ll enter all the commands in the Ruby interactive console (irb) so you can enter them as you follow along and explore the environment.  The steps we will take are:

  1. Log into vRA
  2. Request all of the catalog items available
  3. Find the one want to provision
  4. Extract all of the needed values from the catalog item
  5. Read a template file from disk and substitute the necessary values
  6. Request a new item

 

Ruby setup

If you haven’t already installed Ruby, go here https://www.ruby-lang.org/en/documentation/installation/.  I’m running Ruby ruby 2.0.0p353 on CentOS 7.  Once you have Ruby installed we will need to install a couple of gems.  From the command line run:

gem install rest-client
gem install multi_json

Issuing commands using Ruby’s irb

Access irb:

[chris@docker ~]$ irb

This will place you into irb where we will run our Ruby commands.  I’m going to paste in the results from my irb session so that you’ll be able to see the input and output.  Items in blue are input.  The output is the text that follows the => characters. Sometimes the output from the commands can be long, but I’ve decided to include them so you can cross reference.  For the long JSON outputs, you may want to paste into http://jsonformatter.curiousconcept.com/ to make the viewing easier.
 
Add the modules that we will need

irb(main):001:0> require ‘rest_client’
=> true

irb(main):002:0> require ‘multi_json’
=> true

irb(main):003:0> require ‘erb’
=> true

irb(main):004:0> require ‘pp’
=> true

 

Log into vRA

 
Set our login URL

irb(main):029:0> url = ‘https://vra62a.vmware.local/identity/api/tokens’
=> “https://vra62a.vmware.local/identity/api/tokens”

 

Create a JSON login string that will be the payload we send to the login URL

irb(main):030:0> payload = ‘{“username”:”chris@vmware”,”password”:”super password”,”tenant”:”vsphere.local”}’
=> “{\”username\”:\”chris@vmware\”,\”password\”:\”super password\”,\”tenant\”:\”vsphere.local\”}”

 
Execute the login request

irb(main):032:0> response = RestClient::Request.execute(:url => url, :method => :post, :payload => payload, :verify_ssl => false, :headers => { :content_type => ‘application/json’, :accept => ‘application/json’} )
=> “{\”expires\”:\”2015-02-28T17:32:57.688Z\”,\”id\”:\”MTQyNTA1ODM3NzY4ODphMzYxNGQzNjFlYmU1OTBiYzdmMzp0ZW5hbnQ6dnNwaGVyZS5sb2NhbHVzZXJuYW1lOmNocmlzQHZtd2FyZTowMzkzOTVkOTNkZTIxODJlZmM5MmU3ZDA5ZWE2ODFlYjlhOGE4ZjBkMDkyNTM0NGIwMzA4Yjg2OWM5YjgxNWUzOGVhNjZjOGQ1YmMyMDNjYzgwMTZjNDhmNzAzY2Q0NzFlMTAzNDM4MzE0Njc0N2RlZmIyOThhNzY3YWE2YjVjNQ==\”,\”tenant\”:\”vsphere.local\”}

The ‘id’ entry is our bearer token that we will need to use on future requests so let’s save it.

 

Convert the above response into JSON

irb(main):033:0> json_response = JSON.parse(response)
=> {“expires”=>”2015-02-28T17:32:57.688Z”, “id”=>”MTQyNTA1ODM3NzY4ODphMzYxNGQzNjFlYmU1OTBiYzdmMzp0ZW5hbnQ6dnNwaGVyZS5sb2NhbHVzZXJuYW1lOmNocmlzQHZtd2FyZTowMzkzOTVkOTNkZTIxODJlZmM5MmU3ZDA5ZWE2ODFlYjlhOGE4ZjBkMDkyNTM0NGIwMzA4Yjg2OWM5YjgxNWUzOGVhNjZjOGQ1YmMyMDNjYzgwMTZjNDhmNzAzY2Q0NzFlMTAzNDM4MzE0Njc0N2RlZmIyOThhNzY3YWE2YjVjNQ==”, “tenant”=>”vsphere.local”}

 

Extract the the bearer token

irb(main):034:0> bearer = json_response[‘id’]
=> “MTQyNTA1ODM3NzY4ODphMzYxNGQzNjFlYmU1OTBiYzdmMzp0ZW5hbnQ6dnNwaGVyZS5sb2NhbHVzZXJuYW1lOmNocmlzQHZtd2FyZTowMzkzOTVkOTNkZTIxODJlZmM5MmU3ZDA5ZWE2ODFlYjlhOGE4ZjBkMDkyNTM0NGIwMzA4Yjg2OWM5YjgxNWUzOGVhNjZjOGQ1YmMyMDNjYzgwMTZjNDhmNzAzY2Q0NzFlMTAzNDM4MzE0Njc0N2RlZmIyOThhNzY3YWE2YjVjNQ==”

 

Retrieve catalog item

 
irb(main):035:0> url = ‘https://vra62a.vmware.local/catalog-service/api/consumer/entitledCatalogItems’
=> “https://vra62a.vmware.local/catalog-service/api/consumer/entitledCatalogItems”

irb(main):036:0> response = RestClient::Request.execute(:url => url, :method => :get, :verify_ssl => false, :headers => { :content_type => ‘application/json’, :accept => ‘application/json’, :authorization => “Bearer #{bearer}” } )
=> “{\”links\”:[],\”content\”:[{\”@type\”:\”ConsumerEntitledCatalogItem\”,\”catalogItem\”:{\”id\”:\”c25770de-789e-474c-b261-780542cec1a4\”,\”version\”:1,\”name\”:\”RHEL_6.5_Full_Clone\”,\”description\”:\”\”,\”status\”:\”PUBLISHED\”,\”statusName\”:\”Published\”,\”organization\”:{\”tenantRef\”:\”vsphere.local\”,\”tenantLabel\”:\”vsphere.local\”,\”subtenantRef\”:null,\”subtenantLabel\”:null},\”providerBinding\”:{\”bindingId\”:\”b374952e-f368-4b45-a8be-8d0aace542b8\”,\”providerRef\”:{\”id\”:\”84e032be-11a6-46a0-a587-16d47ccdaa89\”,\”label\”:\”iaas-service\”}},\”forms\”:null,\”callbacks\”:null,\”isNoteworthy\”:false,\”dateCreated\”:\”2015-02-24T17:47:18.398Z\”,\”lastUpdatedDate\”:\”2015-02-24T17:47:50.666Z\”,\”iconId\”:\”cafe_default_icon_genericCatalogItem\”,\”catalogItemTypeRef\”:{\”id\”:\”Infrastructure.Virtual\”,\”label\”:\”Virtual Machine\”},\”serviceRef\”:{\”id\”:\”a0d245ab-c453-4e48-b0ea-9a1d84b51c8d\”,\”label\”:\”RHEL\”},\”outputResourceTypeRef\”:{\”id\”:\”Infrastructure.Virtual\”,\”label\”:\”Virtual Machine\”}},\”entitledOrganizations\”:[{\”tenantRef\”:\”vsphere.local\”,\”tenantLabel\”:\”vsphere.local\”,\”subtenantRef\”:\”817a772c-6401-4243-84e1-0dc5ae4a074a\”,\”subtenantLabel\”:\”cloudadmin\”}]},{\”@type\”:\”ConsumerEntitledCatalogItem\”,\”catalogItem\”:{\”id\”:\”9f5c66e6-43c1-4a6b-aa9f-d0199b2bd21e\”,\”version\”:1,\”name\”:\”RHEL-Linked-Clone\”,\”description\”:\”\”,\”status\”:\”PUBLISHED\”,\”statusName\”:\”Published\”,\”organization\”:{\”tenantRef\”:\”vsphere.local\”,\”tenantLabel\”:\”vsphere.local\”,\”subtenantRef\”:null,\”subtenantLabel\”:null},\”providerBinding\”:{\”bindingId\”:\”91493798-353c-43e6-9912-d8e5e328bbc3\”,\”providerRef\”:{\”id\”:\”84e032be-11a6-46a0-a587-16d47ccdaa89\”,\”label\”:\”iaas-service\”}},\”forms\”:null,\”callbacks\”:null,\”isNoteworthy\”:false,\”dateCreated\”:\”2015-02-26T20:28:59.584Z\”,\”lastUpdatedDate\”:\”2015-02-26T20:29:48.753Z\”,\”iconId\”:\”cafe_default_icon_genericCatalogItem\”,\”catalogItemTypeRef\”:{\”id\”:\”Infrastructure.Virtual\”,\”label\”:\”Virtual Machine\”},\”serviceRef\”:{\”id\”:\”a0d245ab-c453-4e48-b0ea-9a1d84b51c8d\”,\”label\”:\”RHEL\”},\”outputResourceTypeRef\”:{\”id\”:\”Infrastructure.Virtual\”,\”label\”:\”Virtual Machine\”}},\”entitledOrganizations\”:[{\”tenantRef\”:\”vsphere.local\”,\”tenantLabel\”:\”vsphere.local\”,\”subtenantRef\”:\”817a772c-6401-4243-84e1-0dc5ae4a074a\”,\”subtenantLabel\”:\”cloudadmin\”}]}],\”metadata\”:{\”size\”:20,\”totalElements\”:2,\”totalPages\”:1,\”number\”:1,\”offset\”:0}}”

irb(main):037:0> catalog_items = JSON.parse(response)
=> {“links”=>[], “content”=>[{“@type”=>”ConsumerEntitledCatalogItem”, “catalogItem”=>{“id”=>”c25770de-789e-474c-b261-780542cec1a4”, “version”=>1, “name”=>”RHEL_6.5_Full_Clone”, “description”=>””, “status”=>”PUBLISHED”, “statusName”=>”Published”, “organization”=>{“tenantRef”=>”vsphere.local”, “tenantLabel”=>”vsphere.local”, “subtenantRef”=>nil, “subtenantLabel”=>nil}, “providerBinding”=>{“bindingId”=>”b374952e-f368-4b45-a8be-8d0aace542b8”, “providerRef”=>{“id”=>”84e032be-11a6-46a0-a587-16d47ccdaa89”, “label”=>”iaas-service”}}, “forms”=>nil, “callbacks”=>nil, “isNoteworthy”=>false, “dateCreated”=>”2015-02-24T17:47:18.398Z”, “lastUpdatedDate”=>”2015-02-24T17:47:50.666Z”, “iconId”=>”cafe_default_icon_genericCatalogItem”, “catalogItemTypeRef”=>{“id”=>”Infrastructure.Virtual”, “label”=>”Virtual Machine”}, “serviceRef”=>{“id”=>”a0d245ab-c453-4e48-b0ea-9a1d84b51c8d”, “label”=>”RHEL”}, “outputResourceTypeRef”=>{“id”=>”Infrastructure.Virtual”, “label”=>”Virtual Machine”}}, “entitledOrganizations”=>[{“tenantRef”=>”vsphere.local”, “tenantLabel”=>”vsphere.local”, “subtenantRef”=>”817a772c-6401-4243-84e1-0dc5ae4a074a”, “subtenantLabel”=>”cloudadmin”}]}, {“@type”=>”ConsumerEntitledCatalogItem”, “catalogItem”=>{“id”=>”9f5c66e6-43c1-4a6b-aa9f-d0199b2bd21e”, “version”=>1, “name”=>”RHEL-Linked-Clone”, “description”=>””, “status”=>”PUBLISHED”, “statusName”=>”Published”, “organization”=>{“tenantRef”=>”vsphere.local”, “tenantLabel”=>”vsphere.local”, “subtenantRef”=>nil, “subtenantLabel”=>nil}, “providerBinding”=>{“bindingId”=>”91493798-353c-43e6-9912-d8e5e328bbc3”, “providerRef”=>{“id”=>”84e032be-11a6-46a0-a587-16d47ccdaa89”, “label”=>”iaas-service”}}, “forms”=>nil, “callbacks”=>nil, “isNoteworthy”=>false, “dateCreated”=>”2015-02-26T20:28:59.584Z”, “lastUpdatedDate”=>”2015-02-26T20:29:48.753Z”, “iconId”=>”cafe_default_icon_genericCatalogItem”, “catalogItemTypeRef”=>{“id”=>”Infrastructure.Virtual”, “label”=>”Virtual Machine”}, “serviceRef”=>{“id”=>”a0d245ab-c453-4e48-b0ea-9a1d84b51c8d”, “label”=>”RHEL”}, “outputResourceTypeRef”=>{“id”=>”Infrastructure.Virtual”, “label”=>”Virtual Machine”}}, “entitledOrganizations”=>[{“tenantRef”=>”vsphere.local”, “tenantLabel”=>”vsphere.local”, “subtenantRef”=>”817a772c-6401-4243-84e1-0dc5ae4a074a”, “subtenantLabel”=>”cloudadmin”}]}], “metadata”=>{“size”=>20, “totalElements”=>2, “totalPages”=>1, “number”=>1, “offset”=>0}}

 
Find the catalog item that we want to provision

Here I’m going to retrieve the catalog item with the name of ‘RHEL-Linked-Clone’

irb(main):038:0> catalog_item = catalog_items[‘content’].find { |catalogItem| catalogItem[‘catalogItem’][‘name’] == ‘RHEL-Linked-Clone’ }
=> {“@type”=>”ConsumerEntitledCatalogItem”, “catalogItem”=>{“id”=>”9f5c66e6-43c1-4a6b-aa9f-d0199b2bd21e”, “version”=>1, “name”=>”RHEL-Linked-Clone”, “description”=>””, “status”=>”PUBLISHED”, “statusName”=>”Published”, “organization”=>{“tenantRef”=>”vsphere.local”, “tenantLabel”=>”vsphere.local”, “subtenantRef”=>nil, “subtenantLabel”=>nil}, “providerBinding”=>{“bindingId”=>”91493798-353c-43e6-9912-d8e5e328bbc3”, “providerRef”=>{“id”=>”84e032be-11a6-46a0-a587-16d47ccdaa89”, “label”=>”iaas-service”}}, “forms”=>nil, “callbacks”=>nil, “isNoteworthy”=>false, “dateCreated”=>”2015-02-26T20:28:59.584Z”, “lastUpdatedDate”=>”2015-02-26T20:29:48.753Z”, “iconId”=>”cafe_default_icon_genericCatalogItem”, “catalogItemTypeRef”=>{“id”=>”Infrastructure.Virtual”, “label”=>”Virtual Machine”}, “serviceRef”=>{“id”=>”a0d245ab-c453-4e48-b0ea-9a1d84b51c8d”, “label”=>”RHEL”}, “outputResourceTypeRef”=>{“id”=>”Infrastructure.Virtual”, “label”=>”Virtual Machine”}}, “entitledOrganizations”=>[{“tenantRef”=>”vsphere.local”, “tenantLabel”=>”vsphere.local”, “subtenantRef”=>”817a772c-6401-4243-84e1-0dc5ae4a074a”, “subtenantLabel”=>”cloudadmin”}]}

 

Substitute our template values into our request template

 
irb(main):039:0> @catalogItemId = catalog_item[‘catalogItem’][‘id’]
=> “9f5c66e6-43c1-4a6b-aa9f-d0199b2bd21e”
 
irb(main):040:0> @tenantName = catalog_item[‘catalogItem’][‘organization’][‘tenantRef’]
=> “vsphere.local”
 
irb(main):041:0> @businessGroupId = catalog_item[‘entitledOrganizations’][0][‘subtenantRef’]
=> “817a772c-6401-4243-84e1-0dc5ae4a074a”
 
irb(main):042:0> @blueprintId = catalog_item[‘catalogItem’][‘providerBinding’][‘bindingId’]
=> “91493798-353c-43e6-9912-d8e5e328bbc3”
 
irb(main):043:0> @username = ‘chris@vmware.local’
=> “chris@vmware.local”
 
irb(main):044:0> @cpuCount = 1
=> 1
 
irb(main):045:0> @memorySize = 512
=> 512
 
irb(main):046:0> @leaseDays = 30
=> 30
 
irb(main):047:0> @notes = ‘Provisioned via Ruby’
=> “Provisioned via Ruby”
 
irb(main):048:0> @disk0Size = ’10’
=> “10”
 
irb(main):049:0> @disk0Letter = ‘C’
=> “C”
 
irb(main):050:0> @disk0Label = ‘main’
=> “main”

 

Insert our request information into the catalog request template

 
I’m using Ruby’s templating system ERB.  I’ve created a file called ‘catalogRequest.erb’ on my filesystem with the contents of:

{
    "@type": "CatalogItemRequest",
    "catalogItemRef": {
        "id": "<%= @catalogItemId %>"
    },
    "organization": {
        "tenantRef": "<%= @tenantName %>",
        "subtenantRef": "<%= @businessGroupId %>"
    },
    "requestedFor": "<%= @username %>",
    "state": "SUBMITTED",
    "requestNumber": 0,
    "requestData": {
        "entries": [{
            "key": "provider-blueprintId",
            "value": {
                "type": "string",
                "value": "<%= @blueprintId %>"
            }
        },
        {
            "key": "provider-provisioningGroupId",
            "value": {
                "type": "string",
                "value": "<%= @businessGroupId %>"
            }
        },
        {
            "key": "requestedFor",
            "value": {
                "type": "string",
                "value": "<%= @username %>"
            }
        },
        {
            "key": "provider-VirtualMachine.CPU.Count",
            "value": {
                "type": "integer",
                "value": <%= @cpuCount %>
            }
        },
        {
            "key": "provider-VirtualMachine.Memory.Size",
            "value": {
                "type": "integer",
                "value": <%= @memorySize %>
            }
        },
        {
            "key": "provider-VirtualMachine.LeaseDays",
            "value": {
                "type": "integer",
                "value": <%= @leaseDays %>
            }
        },
        {
            "key": "provider-__Notes",
            "value": {
                "type": "string",
                "value": "<%= @notes %>"
            }
        },
        {
            "key": "provider-VirtualMachine.Disk0.Size",
            "value": {
                "type": "string",
                "value": "<%= @disk0Size %>"
            }
        },
        {
            "key": "provider-VirtualMachine.Disk0.Letter",
            "value": {
                "type": "string",
                "value": "<%= @disk0Letter %>"
            }
        },
        {
            "key": "provider-VirtualMachine.Disk0.Label",
            "value": {
                "type": "string",
                "value": "<%= @disk0Label %>"
            }
        }]
    }
}

Each of the bolded items such as @blueprintId will be replaced by our locally defined variables.
 
Read in the request

irb(main):051:0> request = File.read(‘catalogRequest.erb’)
 
Substitute in our values

irb(main):053:0> erb_request = ERB.new(request).result()
 
Convert the request to JSON

irb(main):054:0> json_request = JSON.parse(erb_request).to_json
=> “{\”@type\”:\”CatalogItemRequest\”,\”catalogItemRef\”:{\”id\”:\”9f5c66e6-43c1-4a6b-aa9f-d0199b2bd21e\”},\”organization\”:{\”tenantRef\”:\”vsphere.local\”,\”subtenantRef\”:\”817a772c-6401-4243-84e1-0dc5ae4a074a\”},\”requestedFor\”:\”chris@vmware.local\”,\”state\”:\”SUBMITTED\”,\”requestNumber\”:0,\”requestData\”:{\”entries\”:[{\”key\”:\”provider-blueprintId\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”91493798-353c-43e6-9912-d8e5e328bbc3\”}},{\”key\”:\”provider-provisioningGroupId\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”817a772c-6401-4243-84e1-0dc5ae4a074a\”}},{\”key\”:\”requestedFor\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”chris@vmware.local\”}},{\”key\”:\”provider-VirtualMachine.CPU.Count\”,\”value\”:{\”type\”:\”integer\”,\”value\”:1}},{\”key\”:\”provider-VirtualMachine.Memory.Size\”,\”value\”:{\”type\”:\”integer\”,\”value\”:512}},{\”key\”:\”provider-VirtualMachine.LeaseDays\”,\”value\”:{\”type\”:\”integer\”,\”value\”:30}},{\”key\”:\”provider-__Notes\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”Provisioned via Ruby\”}},{\”key\”:\”provider-VirtualMachine.Disk0.Size\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”10\”}},{\”key\”:\”provider-VirtualMachine.Disk0.Letter\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”C\”}},{\”key\”:\”provider-VirtualMachine.Disk0.Label\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”main\”}}]}}”

 

Make the catalog item request

 
Set the request URL

irb(main):055:0> url = ‘https://vra62a.vmware.local/catalog-service/api/consumer/requests’
=> “https://vra62a.vmware.local/catalog-service/api/consumer/requests”

Assign our prepared JSON request into the payload variable

irb(main):056:0> payload = json_request
=> “{\”@type\”:\”CatalogItemRequest\”,\”catalogItemRef\”:{\”id\”:\”9f5c66e6-43c1-4a6b-aa9f-d0199b2bd21e\”},\”organization\”:{\”tenantRef\”:\”vsphere.local\”,\”subtenantRef\”:\”817a772c-6401-4243-84e1-0dc5ae4a074a\”},\”requestedFor\”:\”chris@vmware.local\”,\”state\”:\”SUBMITTED\”,\”requestNumber\”:0,\”requestData\”:{\”entries\”:[{\”key\”:\”provider-blueprintId\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”91493798-353c-43e6-9912-d8e5e328bbc3\”}},{\”key\”:\”provider-provisioningGroupId\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”817a772c-6401-4243-84e1-0dc5ae4a074a\”}},{\”key\”:\”requestedFor\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”chris@vmware.local\”}},{\”key\”:\”provider-VirtualMachine.CPU.Count\”,\”value\”:{\”type\”:\”integer\”,\”value\”:1}},{\”key\”:\”provider-VirtualMachine.Memory.Size\”,\”value\”:{\”type\”:\”integer\”,\”value\”:512}},{\”key\”:\”provider-VirtualMachine.LeaseDays\”,\”value\”:{\”type\”:\”integer\”,\”value\”:30}},{\”key\”:\”provider-__Notes\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”Provisioned via Ruby\”}},{\”key\”:\”provider-VirtualMachine.Disk0.Size\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”10\”}},{\”key\”:\”provider-VirtualMachine.Disk0.Letter\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”C\”}},{\”key\”:\”provider-VirtualMachine.Disk0.Label\”,\”value\”:{\”type\”:\”string\”,\”value\”:\”main\”}}]}}”
 
Execute the catalog item request.  If you receive no response (“”), then the request was valid

irb(main):057:0> response = RestClient::Request.execute(:url => url, :method => :post, :payload => payload, :verify_ssl => false, :headers => { :content_type => ‘application/json’, :accept => ‘application/json’, :authorization => “Bearer #{bearer}” } )
=> “”
 
You should now be able to see the request in vRA and eventually your VM:

2015-02-27_10-27-43

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 )

Facebook photo

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

Connecting to %s