Getting started with the vCloud Director API with Python

api

I have been working closely with vCloud Director from a front end point of view as one of our customers wanted to leverage our public cloud offering. I wanted to show them the power of the API and I decided to use Python as the scripting language of my choice to script some API calls. Now there is one problem I faced straight away which is there is no vCloud SDK for Python. What does this mean? Well, an SDK provides a library that you can leverage which makes vCloud API calls easier. So was the only other option was to use the REST API provided by vCloud. This is fine, but it just means more work rather then use something that someone else has written to make your life easier.

Just for the record, there are SDK’s for vCloud for DOT NET, Java and PHP.

So the first thing to understand is the documentation – you need to understand how it’s laid out and how to find what you want to do. Easier said than done. There are loads of goods resources here but I have listed a few to start with:

vCloud Dirtector API reference documentation
https://www.vmware.com/support/pubs/vcd_pubs.html

Exploring the vCloud Director API
http://blogs.vmware.com/vsphere/2012/03/exploring-the-vcloud-rest-api-part-2.html

Once you have muddled through the API documentation, you need to use a Python library that will interact with HTTP. I used the great Python Requests library rather than HTTPLIB2. I find it much easier to use, more simple and cleaner to understand.

The next thing to do is to build a login function. Here is my snippet of Python code:

class vCloud_Deploy(object):

    def __init__(self):

        self.login = None
        self.headers = None
        self.endpoint = None
        self.org = None
        self.root = None

    def sessions(self, username, org, password, key, secret, endpoint):

        self.endpoint = endpoint

        self.login = {'Accept':'application/*+xml;version=5.1', \
            'Authorization':'Basic '+ base64.b64encode(username + "@" + org + ":" + password), \
            'x-id-sec':base64.b64encode(key + ":" + secret)}

        p = requests.post(self.endpoint + 'sessions', headers = self.login)

        self.headers = {'Accept':'application/*+xml;version=5.1'}

        for k,v in p.headers.iteritems():
            if k == 'x-json':
                access_token_value = 'Bearer %s' % v[21:57]
                self.headers["Authorization:"]=access_token_value
                if k == "x-vcloud-authorization" : self.headers[k]=v

The public cloud I was working with needed 2 forms of authentication. The first authentication mechanism was to send an api and secret key in a base64 encoded URL. This bit doesn’t really matter as it’s not part of the vCloud Director authentication mechanism but merely an added layer of authentication provided by the company I work for. What is important is logging in to the vCloud Director API and for this, you need to get the x-vcloud-authorization header value. This is then passed in when ever you call other vCloud APIs. This is your token.

You can see above that I am requesting a login and once I have passed in all the headers I need to for the inital login request, if it is successful I then look at the headers returned. I iterate through all the headers and find the x-vcloud-authorization header and its value and then add this information to my self.headers. Whenever I call another API, I just use the self.header which contains a valid x-vcloud-authorization token. The point here, is once you have the login function set up and working, you’ve gone a long way to then starting to use the API. Get this sorted and your in basically.

So now you can start with some simple get requests. Here is an example function that gets the org URL. This tacks on to the script snippet above.

    def org_url(self):

        g = requests.get(self.endpoint + 'org', data=None, headers = self.headers)
        root = ET.fromstring(g.content)

        for child in root:

            self.org = child.get("href")

            g = requests.get(self.org, data=None, headers = self.headers)
            self.root = ET.fromstring(g.content)

            return self.org

In my python class constructor, I have set up various parameters I need when using the API. This includes my endpoint which is something you need to know before you use the API.

    def __init__(self):

        ....
        self.endpoint = None
        ....

So back to the how I get the org URL, you will notice that I have passed the endpoint in my get request, followed by the ‘org’ appended. This essentially gives me the REST API call which gets me the org URL and how this is done can be found in the VMware documentation, see here – http://pubs.vmware.com/vcd-55/topic/com.vmware.vcloud.api.reference.doc_55/doc/operations/GET-Organizations.html. Once I collect the information, I set the self.org value to the HREF org_url. I use the self.org value to specify in future API calls that its this org I want to query or provision to.

This is just a blog, not a how to step by step article. The full version of the script can be found on my github account here – https://github.com/oliverleach/vcloud-autodeploy/blob/master/vCloudDeployVm.py. Get in touch if you have any questions or comments.

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