Intro to vRealize Automation REST API With Python · TheHumbleLab

Intro to vRealize Automation REST API With Python

· Read in about 12 min · (2370 words) ·

Important Notes

Introduction

Recently, I started playing around quite a bit with the vRealize Automation REST API. It’s no secret based on the content I’ve been posting on here that I’m a big fan of being familiar with our various API’s. The community lately is turning a big corner and starting to dive really hard into how they can consume API based services. To this end, the awesome guys over at vBrownBag are knee deep in the midst of a series on various API topics. Make sure you tune in and check these out; you’ll learn a WEALTH of information from it. One of my good buddies and someone I look up to (well, down, he’s not tall…at all) Jad El-Zein, Principal Architect from the Cloud Management Business Unit, will be doing a vBrownBag on the vRealize Automation API on 10/11. You should absolutely check it out! He also runs his own blog over at http://www.virtualjad.com.

The vRealize Automation API runs deep and while at first seems very complex; once you start working with it, it’s really easy to start pulling together some relevant results. Mix in something like PrettyTables and you can start building some pretty fun and functional reporting.

Check out the demo below of where we are ultimately going to end up!

Goals

  • Build an Authentication function for vRealize Automation
  • Demonstrate and REST API calls for vRA managed virtual machines
  • Understand Parsing a JSON using JSON Editor Online
  • Return data in a table
  • Build a Function to return data in a table
  • Work with Arrays
  • Provide GitHub material

Authentication

I love VMware; but we like to leverage a different authentication method for every one of our API’s it seems. With vCenter we do an http auth and then use a Session ID that we pass into the headers. For vRA, we use a bearer token. We pass a payload of the username, password, and tenant into an API endpoint and we’re returned with a token number. WE toss Bearer on the front of that number and we’re good to go. We can build a simple function in Python to handle this authentication and return us the token…let’s do it! We’ll be primarily working in Python 3.6 for the contents of this article. I’m doing this on Windows as usual, come at me haters.

We’ll launch python by typing ‘python’ at our command prompt and start hammering away

Python Launch

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def vra_auth(vrafqdn,user,password,tenant):
    url = "https://{}/identity/api/tokens".format(vrafqdn)
    payload = '{{"username":"{}","password":"{}","tenant":"{}"}}'.format(user, password, tenant)
    headers = {
        'accept': "application/json",
        'content-type': "application/json",
        }
    response = requests.request("POST", url, data=payload, headers=headers, verify=False)
    j = response.json()['id']
    auth = "Bearer "+j
    return auth

Let’s take a look at what this is doing. We create a function that takes the vRealize Automation FQDN, username, password, and vRealize Automation Tenant as in input. Our function constructs a URL based on the FQDN that’s fed in. We then create a payload based on the values that we drop in. This payload is ultimately going to be what’s fed into the vRealize Automation API POST. We create the required headers, and then we build a request object that performs our POST. We grab the JSON response of the post, build an object around it, and call the [‘id’] key within the JSON. We prepend Bearer to it, as the auth variable and return that variable.

This returns our authentication token! With this, we can perform future calls easy. All we need to do is build our authentication header to contain this value.

If all things work (which they should, because obviously I ran this at the same time as I was writing this blog post) we can run our function, vra_auth, with the values we want pumped in - and the bearer token will respond. Solid!

Python Auth Run

Calling the vRA API

I continue to stress the importance of VMware{code}’s API explorer in my posts because it REALLY is as incredible as I’m making it out to be. Between that, and the official vRealize Automation 7.3 API Guide; we should be able to really start doing some damage. Let’s start off with a simple use case, listing all virtual machines provisioned by vRealize Automation. I’m very specific when I say virtual machines in this case. vRealize Automation calls the overall item provisioned a Deployment. Deployments contain virtual machines and networks as well as software components. In this case, I want to create a call that only returns the virtual machines.

To do this, we are going to have to make a call to the catalog service, which will return a large JSON of everything. We will then build a new array and inject only the virtual machines into it. For funsies, from there, we will use a python module called PrettyTables to drop the machines as well as some pertinent data into a table. Let’s get started.

Before we jump into the full function, let’s talk about how we get there. You should still have your python shell up from before. We’re going to run the components of our future function so you can see the result that we will parse through.

We’re going to start doing a few things right off the bat…

import requests
import json
varray = []
auth = vra_auth('hlcloud.humblelab.com','codyde@vsphere.local','VMware123!','vsphere.local')
vraheaders = {
        'accept': "application/json",
        'authorization': auth
        }
vraApiUrl = "https://{}/catalog-service/api/consumer/resources".format(vrafqdn)

What we’ve done here is essentially build objects around each component of our future request. We’re going to need our array to store our VM information in, we need our authentication object (bearer token), we need headers that contain our authentication, and we need the API endpoint we are trying to hit. With all of that built, we can call our actual request

requests.request("GET", vraApiUrl, headers=vraheaders, verify=False)

This is going to return an underwhelming response. You’ll likely get something back that says . This is response object. We know this object is returned as a JSON; so, let’s modify our call slightly…

requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()

Better! We’re getting a big JSON blob back. It’s a bit hard to read…especially if you’ve never worked with a JSON file before. We can fix this…let’s turn it into an object and print it out like.

import requests
import json
req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()
print(json.dumps(req, indent=4))

That’s even better. We’re now getting this nicer JSON back. If we copy and paste it, and drop it into a site like JSON Editor Online we can start to parse this object out and see the items we need.

JSONEditorOnline

First thing we see is that there are 3 larger keys within this; ultimately all we care about is [‘content’]. Let’s modify our call slightly…

import requests
import json
req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()['content']
print(json.dumps(req, indent=4))

This will now return to us only the values within the content key; which subsequently is all our deployment information. It’s important to understand that vRealize Automation organizes the results of catalog requests into Deployments which contain all the components such as networks, software components, and virtual machines.

When we drop this newly returned item into JSON Editor Online, we are returned with a series of objects.

JSONEditorOnline

If we expand the first object we can see a deployment is returned.

JSONEditorOnline-Expanded

In my case it’s a CentOS deployment. We’re given a lot of great information here that we can start to build out some form of a simple report out of. Right now, this entire object is stored in the req variable. We can iterate over this to do some interesting things, such as use the prettytable module to build a ASCII table out of the data. Make sure you do a pip install prettytable if you haven’t already so we can import it! Let’s give this a spin.

import requests
import json
from prettytable import PrettyTable
req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()['content']
vratable = PrettyTable(['Name','ID','Resource Type'])
for i in req:
    vratable.add_row((i['name'],i['id'],i['resourceTypeRef']['id']))

print(vratable)

Voila! Great table response! This is getting good!

PrettyTable Table Parsed

Now, within this, we can see that we’re getting several results back. What if we only wanted to list out the virtual machines? We can do that! Earlier we instantiated an empty array, varray = []. We’re going to use this. We will shift around our for loop to push these only the Infrastructure.Virtual objects into the array, which we can then parse out!

import requests
import json
from prettytable import PrettyTable
req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()['content']
vratable = PrettyTable(['Name','ID','Resource Type'])
for i in req:
    if i['resourceTypeRef']['id'] == 'Infrastructure.Virtual':
        varray.append(i)
        vratable.add_row((i['name'],i['id'],i['resourceTypeRef']['id']))

print(varray)
print(vratable)

Prettytable Table Parsed

Perfect! We’ve got our values going into the array which we print out, and we also print out our table again. Now that we’ve decided to only list our virtual infrastructure, do we need to keep the column reflecting the resource type in the table? Let’s grab something more interesting. We can also stop printing out the array; we’re focusing more on a table at this point.

If we go look at our JSON Editor Online, we can see that if we expand the owners key, and the first array in there, we can actually get the owners name. This seems pertinent info that we might want to drop in a table (plus, it serves as a good example of how to parse down a few keys…). Let’s do it!

import requests
import json
from prettytable import PrettyTable
req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()['content']
vratable = PrettyTable(['Name','ID','Owner'])
for i in req:
    if i['resourceTypeRef']['id'] == 'Infrastructure.Virtual':
        vratable.add_row((i['name'],i['id'],i['owners'][0]['value']))

print(vratable)

Which results in… Prettytable Table Owner

Awesome, but let’s take this further. You’ll notice on JSON Editor Online, we can’t see any details about what the provisioned resources for this object are. Something like OS Type?

This information is kept specifically in the individual resources API endpoint. Look at the JSON Editor Online example I’ve provided below…

JSONEditorOnline ResourceData

We need to make another API call. Fortunately, we can use a for loop, and call those API’s during the loop to return the data. We can then use the results of that call to add to our table. Let’s give it a shot. We’ve been hacking apart at our code quite a bit - so let’s bring it all together quick to work off…

import requests
import json
from prettytable import PrettyTable
vrafqdn = 'hlcloud.humblelab.com'
auth = vra_auth('hlcloud.humblelab.com','codyde@vsphere.local','VMware123!','vsphere.local')
vraheaders = {
        'accept': "application/json",
        'authorization': auth
        }
vraApiUrl = "https://{}/catalog-service/api/consumer/resources".format('hlcloud.humblelab.com')
req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()['content']
vratable = PrettyTable(['Name','ID','OS'])
for i in req:
    if i['resourceTypeRef']['id'] == 'Infrastructure.Virtual':
        resid = i['id']
        vraResUrl = "https://{}/catalog-service/api/consumer/resources/{}".format(vrafqdn,resid)
        resreq = requests.request("GET", vraResUrl, headers=vraheaders, verify=False).json()
        vratable.add_row((i['name'],i['id'],resreq['resourceData']['entries'][0]['value']['value']))

print(vratable)

And just like that…

Prettytable Table OS

Wow. What an adventure that was! So now, what we’ve done, is dropped another API call within our first API call (inception much?). We’re then feeing that call into our prettytable table. You can see how this makes it easy for us to keep building more involved tables for data.

Converting our API call to a Function

So, we’ve now got a functioning call from the python shell, but what if we want to make this into a reusable function? Easy stuff! We’re going to change it around a bit to make it more extensible, allowing us to feed in new authentication values, and FQDN endpoints. Let’s do it!

def return_vra_vms_asTable(vrafqdn,user,password,tenant):
    auth = vra_auth(vrafqdn,user,password,tenant)
    vraheaders = {
            'accept': "application/json",
            'authorization': auth
            }
    vraApiUrl = "https://{}/catalog-service/api/consumer/resources".format(vrafqdn)
    req = requests.request("GET", vraApiUrl, headers=vraheaders, verify=False).json()['content']
    vratable = PrettyTable(['Name','ID','OS'])
    for i in req:
        if i['resourceTypeRef']['id'] == 'Infrastructure.Virtual':
            resid = i['id']
            vraResUrl = "https://{}/catalog-service/api/consumer/resources/{}".format(vrafqdn,resid)
            resreq = requests.request("GET", vraResUrl, headers=vraheaders, verify=False).json()
            vratable.add_row((i['name'],i['id'],resreq['resourceData']['entries'][0]['value']['value']))
    return print(vratable)

If the modules have all been imported, you’ll simply be able to run the function and it will result in successfully returning the table.

Prettytable Table OS Function

We originally started focused on getting into an array; but moved onto leveraging PrettyTables to return the data as much a cleaner way to go. From a programmability perspective; we might still want the values in an array - which as we showed above is just as simple as reading the varray = [], and doing a varray.append(i) within our loop. Isn’t python fun?!

Conclusion

Well, this post really escalated quickly! We’ve only dove into one endpoint - but we’ve dug deep into some of the ways we can ‘GET’ and manipulate data within that endpoint.

There will be many more of these posts, in our next adventure with the REST API we will look at how we can build functions that can request catalog items, build business groups, and build reservations. In the meantime, you can access the sample code from this blog on my GitHub at https://github.com/codyde/vrealize-auto-python-examples

Special Shout Out

Shout out to Russell Pope at Kovarus who has been hacking away at the vRA API within Python for much longer than I. He’s working on a vRealize Automation Python SDK which greatly simplifies the consumption of the vRA API’s. I’ve jumped in and contributed to the project, you should too! Take a gander at it at https://github.com/kovarus/vrealize-pysdk. Expect a lot more to come from this!

Also, I want to give a shout out to Jon Schulman, Staff Functional Architect with the Cloud Management Business Unit, who put together a great post on his blog around the vRealize Automation 7.3 API; which includes some great Postman libraries for the API. It’s absolutely a great resource, and worth the look. Check it out here

Thanks for tuning in! Look forward to the next installment!