Troubleshooting vRealize Automation Provisioning

If you’ve worked with vRealize Automation (vRA) for any amount of time you’ve most likely experienced a provision that has either failed or gotten stuck in progress. I’m going to show how you can begin troubleshooting these scenarios.

Read the rest of this entry »


Using Powershell to work with vRealize Automation work items

I’m going to show how to use Powershell to access a vRealize Automation (vRA) work item and use the work item data to add the machine requestor to the local admins group of the provisioned machine.

This script is for demonstration purposes only and not intended for production use. Please do not call VMware GSS with questions relating to this post as they will not be able to assist.

Read the rest of this entry »


Provisoning vRealize Automation Catalog Items with Powershell and REST

I’ve dabbled with Powershell in the past but never considered it one of my go to languages since it was only available on Windows. This limited my usage of Powershell to primarily working with VMware’s PowerCLI, but now that Powershell has been ported to Linux and OSX I’ve decided to put more effort into learning it. At work I’m working with vRealize Automation (vRA) so I thought I’d try to provision some vRA catalog items via Powershell and REST. Compared to other languages I’ve used, Powershell makes working wtih RESTful APIs very easy. Let’s get started.

This post is designed so you can follow along line by line. You can find a functionalized version on Github.

You can follow along by opening up a Powershell window. Let’s set up some variables:

$vraServer = ‘vra72.vmware.local’
$catalogItem = ‘CentOS 7 Base’
$username = ‘cloudadmin’
$password = ‘VMware1!’
$tenant = ‘vsphere.local’

Getting a login token

The first thing we need to do is get a login token from vRA. You can find out more about this in the vRA API Documentation. You can see an example request in curl here. We can get a login token by making a request to the following URL:

$url = “https://$($vraServer)/identity/api/tokens”

As described in the above links, we must be a POST request and the body of the request must be our username, password and tenant in JSON format. Powershell makes this really easy. Let’s start by defining a hash table with the required values:

$properties = @{‘username’ = $username; ‘password’ = $password; ‘tenant’ = $tenant}

If we view the contents of our $properties variable, we will see the following:

2017-01-24_21-15-46.png

Now let’s convert this into a Powershell object:

$bodyObject = New-Object –TypeName PSObject –Property $properties

Viewing the contents of $bodyObject gives us:

2017-01-24_21-18-01.png

We still need to convert this to JSON as this is what the request for a token requires. This can easily be done like so:

$body = $bodyObject | ConvertTo-Json

The $body variable looks like this:

2017-01-24_21-19-47.png

If you’ve worked with JSON in the past this should look familiar.

Now we are going to request another hash table containing our headers:

$headers = @{“Content-Type” = “application/json”; “Accept” = “application/json”}

We are now ready to request our login token:

$request = Invoke-WebRequest $url -Method POST -Headers $headers -Body $body

Here you can see we used Poweshell’s Invoke-WebRequest commandlet. We specified the method as POST along with our headers and body. The $request variable looks like this:

2017-01-24_21-23-03.png

If you look at Content you’ll see that it contains our token along with other information such as the expiration date. The value of Content is a Powershell String, but we want it in JSON format so we can parse out the id. We can do this by running:

$content = $request.content | convertFrom-json

$content contains:

2017-01-24_22-17-29.png

To get the id, we just need to grab the id field:

$bearerToken = $content.id

The $bearerToken variable will look something like this:

2017-01-24_21-28-28.png

Requesting a catalog item

To request a catalog item we need to perform the following:

  1. Make a GET request on the entitled catalog items
  2. Make a GET request to get the view of our catalog item
  3. Get a the request template for our catalog item
  4. Make a POST request for our catalog item

I’m not going to go into as much detail as in the Getting a login token section as it’s the same pattern over and over.

In the following block of code we specify the URL that contains our entitled catalog items, define $headers again but this time we specify an Authorization header and use our bearer token, make our request and convert the returned content into JSON:

$url = “https://$($vraServer)/catalog-service/api/consumer/entitledCatalogItems/”
$headers = @{“Content-Type” = “application/json”; “Accept” = “application/json”; “Authorization” = “Bearer ${bearerToken}”}
$request = Invoke-WebRequest $url -Method GET -Headers $headers
$content = $request.Content | ConvertFrom-Json

If we look at the content field of $contentJson, we see we have various catalog items:

2017-01-24_22-18-34.png

How do we know what’s in each of these? Let’s grab the first one item and see what type of Poweshell object it is:

2017-01-24_22-19-01.png

So we can see that the BaseType is an object. This means we can use the Get-Member commandlet to get all the objects members or fields:

2017-01-24_22-19-51.png

The catalogItem field looks promising. Let’s check it out:

2017-01-24_22-20-16.png

OK, so we know we look at $contentJson.content we get a list of catalog items and we can look at the catalogItem field to get details about each one. To find which item we are looking for $catalogItem, we can do the following:

$consumerEntitledCatalogItem = $content.content | where { $_.catalogItem.name -eq $catalogItem }

Let’s verify that we have the correct catalog item:

2017-01-24_21-55-01.png

In the next block we will get the catalog item’s id since that’s what we will append to the catalog item view URL, make our request and convert the results to a Powershell object:

$consumerEntitledCatalogItemId = $consumerEntitledCatalogItem.catalogItem.id
$url = “https://$($vraServer)/catalog-service/api/consumer/entitledCatalogItemViews/$($consumerEntitledCatalogItemId)”
$request = Invoke-WebRequest $url -Method GET -Headers $headers
$content = $request.Content | ConvertFrom-Json

If we look at at the links field of $content, we will see:

2017-01-24_22-03-52.png

We need the href that ends in template and we can get it like this:

$requestTemplateURL = $content.links | ? { $_.rel -eq ‘GET: Request Template’ }

Let’s go ahead and get the POST URL while we’re at it:

$requestPOSTURL = $content.links | ? { $_.rel -eq ‘POST: Submit Request’ }

Now we can make a request to $requestTemplateURL. This will allow us to access a “template” of the request data. Once we have this we can either use the same data to make a request or modify somehow like changing the number of CPUs we want:

$request = Invoke-WebRequest $requestTemplateURL.href -Method GET -Headers $headers

2017-01-24_22-11-50.png

Now we have everything we need to make the catalog item request:

$request = Invoke-WebRequest $requestPOSTURL.href -Method POST -Headers $headers -body $request.content

If the request was successful, you should see a status code of 201 and the request should be In Progress in vRA:

2017-01-24_22-13-14.png

Here are all of the steps:

$vraServer = ‘vra72.vmware.local’
$catalogItem = ‘CentOS 7 Base’
$username = ‘cloudadmin’
$password = ‘VMware1!’
$tenant = ‘vsphere.local’

$url = “https://$($vraServer)/identity/api/tokens”

$properties = @{‘username’ = $username; ‘password’ = $password; ‘tenant’ = $tenant}

$bodyObject = New-Object –TypeName PSObject –Property $properties

$body = $bodyObject | ConvertTo-Json

$headers = @{“Content-Type” = “application/json”; “Accept” = “application/json”}

$request = Invoke-WebRequest $url -Method POST -Headers $headers -Body $body
$content = $request.content | convertFrom-json
$bearerToken = $content.id

$url = “https://$($vraServer)/catalog-service/api/consumer/entitledCatalogItems/”
$headers = @{“Content-Type” = “application/json”; “Accept” = “application/json”; “Authorization” = “Bearer ${bearerToken}”}
$request = Invoke-WebRequest $url -Method GET -Headers $headers
$content = $request.Content | ConvertFrom-Json
$consumerEntitledCatalogItem = $content.content | ? { $_.catalogItem.name -eq $catalogItem }
$consumerEntitledCatalogItemId = $consumerEntitledCatalogItem.catalogItem.id
$url = “https://$($vraServer)/catalog-service/api/consumer/entitledCatalogItemViews/$($consumerEntitledCatalogItemId)”
$request = Invoke-WebRequest $url -Method GET -Headers $headers
$content = $request.Content | ConvertFrom-Json
$requestTemplateURL = $content.links | ? { $_.rel -eq ‘GET: Request Template’ }
$requestPOSTURL = $content.links | ? { $_.rel -eq ‘POST: Submit Request’ }
$request = Invoke-WebRequest $requestTemplateURL.href -Method GET -Headers $headers
$request = Invoke-WebRequest $requestPOSTURL.href -Method POST -Headers $headers -body $request.content

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Getting Started with vSphere Integrated Containers using vRealize Automation

Overview

In this post how show how to set up vSphere Integrated Containers (VIC) and integrate them into vRealize Automation (vRA). The vSphere Integrated Containers documentation can be found here. I’ll only reference the Install Guide in this post.

vSphere Integrated Container resources:

The following software versions were used:

  • vSphere Integrated Containers 1.0 (or 0.8?)
  • vRealize Automatin 7.2
  • vCenter 6.0 U2 Build:3634794
  • ESXi: 6.0 U2 Build: 3620759

Read the rest of this entry »


Provisioning vRealize Automation Catalog Items with Ruby

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


User Name and Password fields does not appear on the vRealize Automation login page

VMware recently posted KB User Name and Password fields does not appear on the vRealize Automation login page, which is something that I’m experiencing in my lab.   When I load up vRA in Firefox I see:

2015-01-22_17-37-55

As you can see there is no login or password fields.  The KB article says there is no resolution so far and to disable the client, but I found that you can get the login and password fields to appear by dragging the horizontal scroll bar to the right.  If you look at the very bottom-right of the image above, you will see a little space where the scroll bar can move into.  After dragging the bar to the right, the login and password fields will appear and you can see that there is a small space to the left where the scroll bar has been moved:

2015-01-22_17-37-43

I’m using Firefox 35 on Windows 7.


Unable to perform a data collection on a vCloud Air OnDemand endpoint with vRealize Automation

I recently signed up for the newly released vCloud Air OnDemand service and wanted to provision VMs to it using vRealize Automation (vRA).  I followed the instructions found on page 13 of the IaaS Configuration for vCloud Air and vCloud Director guide, but  the instructions didn’t match what I was seeing as there was no “vCloud Director API URL” link to select.  https://brianragazzi.wordpress.com/2014/08/21/adding-a-vcloud-air-endpoint-to-vcloud-automation-center/ shows what the doc describes.  I filed a service request with VMware and they said that vRA endpoints only works with vCloud Air subscription based plans and not the OnDemand plan.  They also said that the OnDemand plan should be compatible with vRA endpoints in the upcoming months.

When I performed a data collection on the vRA vCloud Air endpoint, it would fail with the error:

Workflow ‘vCloudEndpointDataCollection’ failed with the following exception: There is an error in XML document (1, 2).

2015-01-21_11-36-11

They also said that they were having issues with the API that may have been what was preventing me from working through the instructions at Log In and Receive Access Token.  I’ll go ahead and post what I performed even though it didn’t work.  Maybe once the issue with the API gets resolved it will work or maybe it’s not related and I can update this post in the future.

The first thing we need to convert your login credentials into a Base64 encoded string.  The login credentials will be in the form of user@domain:password.  If you’re on a Linux system, you can convert this into a Base64 string by running:

$ echo ‘username@example.com:password’ | base64
dXNlcm5hbWVAZXhhbXBsZS5jb206cGFzc3dvcmQK

You can also go to https://www.base64encode.org/ to perform the encoding.

Now we need to make a call to the login URL at https://iam.vchs.vmware.com/api/iam/login:

curl -I -H 'Accept: application/xml;version=5.7' \
        -H 'Content-Type: application/xml;version=5.7' \
        -H 'Authorization: Basic dXNlcm5hbWVAZXhhbXBsZS5jb206cGFzc3dvcmQK' \
        -X POST https://iam.vchs.vmware.com/api/iam/login

Make sure to use the -I parameter or you won’t be able to see the authorization token that is sent back.  You should get something back like this:

HTTP/1.1 201 Created
Date: Thu, 22 Jan 2015 02:42:10 GMT
Server: Apache-Coyote/1.1
vchs-authorization: eyJhbGciOiJSU……NU8FTtGIlMln5Q
Content-Type: application/xml; version=5.7
Content-Length: 165
Set-Cookie: ROUTEID=.186; path=/; Domain=.vmware.com
Connection: close

The long string after vchs-authorization is our token.  Let’s go ahead and assign it to a variable since it’s so long and you need to send it in each subsequent request.

$ token=’eyJhbGciOiJSU……NU8FTtGIlMln5Q’

Now we will follow the example and list out our current service plans:

curl -I -H 'Accept: application/xml;version=5.7' \
        -H "Authorization: Bearer $token" \
        https://iam.vchs.vmware.com/api/sc/plans

Note that now we have a new header with our token.  I received the following response:

HTTP/1.1 302 Found
Date: Thu, 22 Jan 2015 03:37:45 GMT
Server: Apache/2.2.15 (CentOS)
Location: https://us-california-1-3.vchs.vmware.com/api/sc/plans
Connection: close
Content-Type: text/html; charset=iso-8859-1

302 is a temporary redirect and is redirecting to https://us-california-1-3.vchs.vmware.com/api/sc/plans.  So I changed my request to:

curl -I -H 'Accept: application/xml;version=5.7' \
        -H "Authorization: Bearer $token" \
        https://us-california-1-3.vchs.vmware.com/api/sc/plans

and received:

HTTP/1.1 405 Method Not Allowed
Date: Thu, 22 Jan 2015 03:44:22 GMT
Server: Apache-Coyote/1.1
X-TraceId: 04abda8b-1821-441c-8dd6-77d2159a9e98-54bd7a33-15413
X-TraceUrl: /insight/services/traces/04abda8b-1821-441c-8dd6-77d2159a9e98-54bd7a33-15413?type=json
X-insight-endpoint-name: default
X-insight-application-name: localhost|ROOT
X-insight-server-name: 04abda8b-1821-441c-8dd6-77d2159a9e98
X-insight-source: HTTP
Content-Type: text/plain;charset=UTF-8
Content-Length: 66
Via: 1.1 us-california-1-3.vchs.vmware.com
Vary: Accept-Encoding

Here is where I stopped as I didn’t want to put more effort into it if the API service is having issues.  This is the first time I’ve looked at the vCloud Air API so maybe I’m missing something.  I’ll update this post when I have a solution or if someone knows the solution, please leave it in the comments.  Thanks.