vRA / vRO new 6.2 REST API Advanced

A couple posts ago I provided simple instructions on how to use the vRA 6.2 REST API. This is a follow up to that post with a more robust workflow that completely closes the automation loop.

I tried those last instructions out with a few co-workers, and while it seemed straightforward to me, I found they were bombing out on actually finishing the REST requests and doing something useful with the server. So, I came up with a more advanced example for them and may I now present to you:

How to Request a Machine and (Pretend to) Do Something Useful With It

Last time, I posted a pretty simple .bat file along with the associated .json file templates you’d need to submit a machine request to your vRA. That .bat file in full is below for your reference; if you don’t recall why we’re doing these things or what a particular command is doing for us, go back and read my last blog post. ¬†Do it now, its ok, the internet will wait for you ūüėČ

curl –insecure -H “Accept: application/json” -H “Content-Type: application/json” –data @HELOTOKEN.json https://vrafqdn/identity/api/tokens > identity.json
jq .id -r < identity.json > bearer.txt
<bearer.txt (
    set /p btoken=
)
curl -X POST –insecure -H “Content-Type: application/json” -H “Authorization: Bearer %btoken%” https://vrafqdn/catalog-service/api/consumer/requests –verbose –data @machineRequest.json

We’d like to expand the above into a full end to end automation demo; monitor the request, if it fails, notify someone that something needs doing, and if it succeeds go ahead and issue a remote command to the server. ¬†The only thing we won’t do is delete the VM when finished, since 95% of my private cloud automation involves creating servers we actually want to hang around; if there’s a lot of interest, I can cover deletion in a future post…

Goals

Our goals are pretty straight-forward here:

  • Monitor the completion of a request
  • Better command-line output
  • Issue a command to the completed VM

Workflow

This is the workflow we’ll create to support the above goals:
Advanced REST API VM Workflow

Prerequisites

In addition to the prerequisites from my previous article, curl and jq, you’ll also need some copy of OpenSSH installed. I use cygwin64, and that might be the easiest way to get it installed and configured; if you want to install OpenSSH by itself, the examples I provide are assuming it’s in c:\cygwin64\bin, so either change the .bat file to use a different folder, or just install OpenSSH to that folder.

You’ll also need to generate a key, testkey and the corresponding testkey.pub using ssh-keygen. It’ll be in whatever folder you installed OpenSSH to; if you’re using cygwin, that’s c:\cygwin64\bin. Just type ssh-keygen at the prompt, enter the path to your keyfile (c:\curl\testkey in this example), and enter your passphrase (I used blank for ease of use in SSH – probably not a good idea in the real world…)

Generating an SSH Key

Our Ubuntu blueprints already prompted the user for the public part of their key and put it in the User’s home folder at ./.ssh/authorized_keys2 which provisions the user’s SSH key appropriately, so I won’t be covering how exactly we do that here – frankly its a hack, and I’m just hoping someone else at Inmar stands up a real enterprise SSH key management solution before I ever have to look at that code again!

Changes to Previous Example

I’ll give you the whole .bat file at the end of this post, but I want to point out some of the changes I made to the existing part of the automation. The first change I did was @ECHO OFF – the @ sign will suppress this line from showing in the command window and the ECHO OFF will suppress future lines from showing.

To go alone with this change, I removed –verbose and added -s to all the curl calls, which changes it to silent mode and suppresses the output. If you’re debugging, you might want to remove the -s and add the –verbose. In case you forget, I added a comment to that effect to the .bat file itself.

The final change I made was I added statements to produce human-friendly status messages such as the following:

ECHO ===========================
ECHO Creating Bearer Token
ECHO ===========================
ECHO.

ECHO normally echoes the content following to the command window. “ECHO.” will produce a new-line in the command window.

Request a Machine: the New Way

I found out the REST call to request a machine includes the URL to check on the status as a header in its response, so I had to modify the previous curl call to add –dump-header requestResult.txt:

curl -s -X POST –insecure -H “Content-Type: application/json” -H “Authorization: Bearer %btoken%” https://vrafqdn/catalog-service/api/consumer/requests –data @machineRequest.json –dump-header requestResult.txt

The content of requestResult.txt looks like:

HTTP/1.1 100 Continue

HTTP/1.1 201 Created
Date: Wed, 08 Jul 2015 18:07:37 GMT
ETag: “0”
Location: https://vrafqdn/catalog-service/api/consumer/requests/973ea8ef-28e8-42fa-b5b2-b39bbe2f7187
Content-Type: application/octet-stream;charset=UTF-8
Content-Length: 0
Vary: Accept-Encoding,User-Agent

What we need to do is parse out the Location: header and save it to an environment variable for further use. I accomplished this with DOS’ underpowered parser, FOR:

for /F “tokens=1,2,3 delims=:” %%i in (requestResult.txt) do (
if %%i==Location (
set async=%%j:%%k
)
)

The first line basically tells the command prompt we want to parse the first three tokens from every line in requestResult.txt, where the tokens will be seperated by colons.  We parse three because this method catches the colon in https: as a delimiter.

The if line, only sets the variable if the header is Location, then the third line sets async to the second token, a colon, and the third token; repairing the mis-parse of the colon in https: and setting the result to an environment variable named async.

The Asynchronous Polling Loop

This is a pattern reviled by developers the world over; it wastes a lot of resources, is always laggy, and is pretty much the worst way to wait for something to finish. That said… when all you’ve got is a hammer, everything starts looking like a nail.

The loop is conceptually very simple: check status of thing, if status doesn’t meet desired end-state, wait a little while and re-check. Checking for the status is easy, we want to visit that async URL that we parsed previously. Within the JSON, there’s a .requestCompletion.requestCompletionState variable that holds the status we’re looking for. So using the same jq parsing syntax as the previous article, the code to check the status is:

curl -s -X GET –insecure -H “Content-Type: application/json” -H “Authorization: Bearer %btoken%” %async% > status.json
jq -r .requestCompletion.requestCompletionState < status.json > status.txt
< status.txt (
set /p status=
)

The entire loop, without the status checking code, is as follows. You’ll note my repurposing of the ping command here; since ping sends a packet once a second by default, regardless of whether those packets are received or not or whatever, ping -n count is a pretty good way to delay a set number of seconds on the Windows platform without having to install yet another utility.

ECHO ===========================
:polling

REM Status check here

if %status%==SUCCESSFUL goto done
if %status%==null goto loop
goto NoMachineErr

:loop
ECHO Status is %status%, waiting 90 seconds and trying again

ping localhost -n 90 > nul
goto polling

:done
ECHO ===========================
ECHO.
ECHO ===========================
ECHO Machine is built
ECHO ===========================
ECHO.

For the error detection to work, add the following at the end of the .bat file:

goto exit

:NoMachineErr
ECHO ===========================
ECHO.
ECHO ===========================
ECHO Unexpected status of %status%
REM Real error handling goes here

ECHO ===========================
ECHO.
goto exit

:exit

Parse MachineName, Send Command

Finally, we want to parse the new VM’s name and send it a command. We again use jq to parse out the machine name from .requestCompletion.completionDetails – that field contains the same text you see on the Request tab in vRA, so for a successful machine it’ll be something like Request succeeded. Created hostname. To parse it, use the FOR command again:

for /F “tokens=1,2,3,4 delims=. ” %%i in (machineName.txt) do (
set machinename=%%l
)

This time, since the only reliable seperators in the text are “.” and ” “, we want those to be our delimiters, and we’ll ask for all four words to be passed into the do block. Note that delims= .” results in an error; delims is just fine accepting the space as a delimiter, but it needs to be the last one listed on the line. Finally, we need to send the command via SSH. ¬†In this example I’m issuing a simple “echo Hello World” command, but once you’ve proven the general method you can do whatever you want.

C:\cygwin64\bin\ssh -2 -o StrictHostKeyChecking=false -i c:\curl2\testkey -q username@%machinename% “echo Hello World”

Note the StrictHostKeyChecking=false option; this is due to the fact that we don’t put real certs on servers, they’re all self-signed certs, so we need OpenSSH to accept an invalid key. ¬†The username is decided by the automation that adds the SSH key, but in our environment that matches our Windows profile name.

The Complete .BAT File

See my previous article for a description of how to generate the HELOToken.json and machineRequest.json files used below.

@echo off
ECHO ===========================
ECHO Creating Bearer Token
ECHO ===========================
ECHO.

REM remove -s, add –verbose for debugging purposes
curl -s –insecure -H “Accept: application/json” -H “Content-Type: application/json” –data @HELOTOKEN.json https://vrafqdn/identity/api/tokens > identity.json
jq .id -r < identity.json > bearer.txt
<bearer.txt (
    set /p btoken=
)

ECHO ===========================
ECHO Posting request for machine
ECHO ===========================
ECHO.

curl -s -X POST –insecure -H “Content-Type: application/json” -H “Authorization: Bearer %btoken%” https://vrafqdn/catalog-service/api/consumer/requests –data @machineRequest.json –dump-header requestResult.txt

for /F “tokens=1,2,3 delims=:” %%i in (requestResult.txt) do (
    if %%i==Location (
        set async=%%j:%%k
    )
)
ECHO ===========================
:polling

curl -s -X GET –insecure -H “Content-Type: application/json” -H “Authorization: Bearer %btoken%” %async% > status.json
jq -r .requestCompletion.requestCompletionState < status.json > status.txt
<status.txt (
    set /p status=
)

if %status%==SUCCESSFUL goto done
if %status%==null goto loop
goto NoMachineErr

:loop
ECHO Status is %status%, waiting 90 seconds and trying again

ping localhost -n 90 > nul
goto polling

:done
ECHO ===========================
ECHO.
ECHO ===========================
ECHO Machine is built
ECHO ===========================
ECHO.

jq -r .requestCompletion.completionDetails < status.json > machineName.txt

for /F “tokens=1,2,3,4 delims=. ” %%i in (machineName.txt) do (
    set machinename=%%l
)
ECHO.
ECHO ===========================
ECHO Testing access – if you see “Hello World”, access is successful
ECHO ===========================
ECHO.

C:\cygwin64\bin\ssh -2 -o StrictHostKeyChecking=false -i c:\curl2\testkey -q jmccrack@%machinename% “echo Hello World”
goto exit

:NoMachineErr
ECHO ===========================
ECHO.
ECHO ===========================
ECHO Unexpected status of %status%
ECHO ===========================
ECHO.
goto exit

:exit

Conclusion

That’s it for today!  Post a comment, tell me what you liked or what needs more clarification on this concept, or just tell me you enjoyed my article!

As always, follow @merlinjim on twitter to be notified when I write new articles.

Advertisements
About

I've been automating everything I can get my hands on since I was a wee lad, these days its mostly Office, UC4, or VMWare - but I have a strong interest in AI, microfluidics, and 3D printing when I'm not slaving for "da man"

Tagged with: , , , , , , ,
Posted in vRA

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

Head Shot of Jim

Jim McCracken

Enter your email address to follow this blog and receive notifications of new posts by email.

Follow me on Twitter
Past Posts
Automate The Cloud pages
%d bloggers like this: