vrandom yet another random IT blog

NSX Python bindings quickstart


Quick start guide to getting an environment setup ready to write some python scripts to control NSX.

Setting up the environment

Our first port of call is to ensure VirtualEnv is installed. We will be using a VirtualEnv environment to setup all the libraries and dependencies our script needs. This can be much easier, especially if you’re working on a host which might need specific versions of libraries for other scripts which are running.

[~]$ sudo pip install virtualenv
[sudo] password for alex: 
You are using pip version 7.1.0, however version 8.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting virtualenv
  Downloading virtualenv-14.0.5-py2.py3-none-any.whl (1.8MB)
    100% |████████████████████████████████| 1.8MB 133kB/s 
Installing collected packages: virtualenv
Successfully installed virtualenv-14.0.5

Now we have VirtualEnv setup lets create a folder for our scripts, and a virtual environment:

[~]$ mkdir nsxlab
[~]$ cd nsxlab/
[nsxlab]$ virtualenv venv
New python executable in /home/alex/nsxlab/venv/bin/python
Installing setuptools, pip, wheel...done.
[nsxlab]$ source venv/bin/activate
(venv) [nsxlab]$ which pip

You’ll notice prompt will change, and as demonstrated python tools such as pip will be run from your virtual environment.

Now the only tricky bit we have is that we need to install some dependencies for lxml and pyOpenSSL, in CentOS you can do this with:

[~]$ sudo yum install libxslt-devel libffi-devel

On Ubuntu you’ll probably have success with (but I’ve not specifically tested this - let me know if anything is missing):

[~]$ apt-get install libxml2-dev libxslt-dev python-dev zlib1g-dev libffi-dev

So now lets install some dependencies we’ll need through out this series of posts:

(venv) [nsxlab]$ pip install nsxramlclient pyvim pyvmomi lxml requests
Collecting nsxramlclient
  Downloading nsxramlclient-1.0.3.tar.gz
Collecting pyvim
  Downloading pyvim-0.0.13-py2-none-any.whl (41kB)
    100% |████████████████████████████████| 45kB 1.9MB/s 
Collecting pyvmomi
  Downloading pyvmomi-6.0.0.tar.gz (216kB)
    100% |████████████████████████████████| 217kB 476kB/s 
Collecting lxml
  Downloading lxml-3.5.0.tar.gz (3.8MB)
    100% |████████████████████████████████| 3.8MB 73kB/s 
Collecting requests
  Downloading requests-2.9.1-py2.py3-none-any.whl (501kB)
    100% |████████████████████████████████| 503kB 462kB/s 
Collecting pyraml-parser>=0.1.3 (from nsxramlclient)
  Downloading pyraml-parser-0.1.5.tar.gz
Collecting ptpython==0.28 (from pyvim)
  Downloading ptpython-0.28-py2-none-any.whl (45kB)
    100% |████████████████████████████████| 49kB 2.1MB/s 
Collecting docopt (from pyvim)
  Downloading docopt-0.6.2.tar.gz
Collecting prompt-toolkit==0.57 (from pyvim)
  Downloading prompt_toolkit-0.57-py2-none-any.whl (208kB)
    100% |████████████████████████████████| 208kB 900kB/s 
Collecting pyflakes (from pyvim)
  Downloading pyflakes-1.0.0-py2.py3-none-any.whl (152kB)
    100% |████████████████████████████████| 155kB 1.3MB/s 
Collecting six>=1.7.3 (from pyvmomi)
  Downloading six-1.10.0-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): setuptools in ./venv/lib/python2.7/site-packages (from pyraml-parser>=0.1.3->nsxramlclient)
Collecting PyYAML>=3.10 (from pyraml-parser>=0.1.3->nsxramlclient)
  Downloading PyYAML-3.11.tar.gz (248kB)
    100% |████████████████████████████████| 249kB 790kB/s 
Collecting jedi>=0.9.0 (from ptpython==0.28->pyvim)
  Downloading jedi-0.9.0-py2.py3-none-any.whl (157kB)
    100% |████████████████████████████████| 159kB 974kB/s 
Collecting pygments (from prompt-toolkit==0.57->pyvim)
  Downloading Pygments-2.1-py2-none-any.whl (754kB)
    100% |████████████████████████████████| 757kB 317kB/s 
Collecting wcwidth (from prompt-toolkit==0.57->pyvim)
  Downloading wcwidth-0.1.6-py2.py3-none-any.whl
Collecting PyOpenSSL
  Using cached pyOpenSSL-0.15.1-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): six>=1.5.2 in ./venv/lib/python2.7/site-packages (from PyOpenSSL)
Collecting cryptography>=0.7 (from PyOpenSSL)
  Using cached cryptography-1.2.2.tar.gz
Collecting cffi>=1.4.1 (from cryptography>=0.7->PyOpenSSL)
  Using cached cffi-1.5.0.tar.gz
Building wheels for collected packages: nsxramlclient, pyvmomi, lxml, pyraml-parser, docopt, PyYAML, cryptography, cffi
  Running setup.py bdist_wheel for nsxramlclient ... done
  Stored in directory: /home/alex/.cache/pip/wheels/02/21/e0/c4a5e6ce29d6b30cf494b8c6aff9745933a26f5fba8693d608
  Running setup.py bdist_wheel for pyvmomi ... done
  Stored in directory: /home/alex/.cache/pip/wheels/a8/31/65/7e404d5173c8e1ab41da777e64b46a83f0798166e8cc72fed4
  Running setup.py bdist_wheel for lxml ... done
  Stored in directory: /home/alex/.cache/pip/wheels/2d/f6/d6/158b79cc088e551305968e312953c9767855a36f39d4e16054
  Running setup.py bdist_wheel for pyraml-parser ... done
  Stored in directory: /home/alex/.cache/pip/wheels/0a/67/64/8546231bd14b0522f2f69286a9bea8f74c2c0b11eb602616ea
  Running setup.py bdist_wheel for docopt ... done
  Stored in directory: /home/alex/.cache/pip/wheels/0d/5c/a7/cb986749520c1950217b5d8405def5c18541322dbc411a80d1
  Running setup.py bdist_wheel for PyYAML ... done
  Stored in directory: /home/alex/.cache/pip/wheels/fa/db/f6/dee55793d344f1706dc4a5a693298f0115241d1085cc212364
  Running setup.py bdist_wheel for cryptography ... done
  Stored in directory: /home/alex/.cache/pip/wheels/1b/a2/47/a2a68fd1435bf7495b74fa545f008365241636e8dff8ff3454
  Running setup.py bdist_wheel for cffi ... done
  Stored in directory: /home/alex/.cache/pip/wheels/ac/44/4b/301cfb6ad4531e8271f7ca364097c5276b65c975942d132151
Successfully built cryptography cffi
Installing collected packages: cffi, cryptography, PyOpenSSL
Successfully built nsxramlclient pyvmomi lxml pyraml-parser docopt PyYAML cryptography cffi
Installing collected packages: PyYAML, six, pyraml-parser, lxml, requests, nsxramlclient, jedi, docopt, pygments, wcwidth, prompt-toolkit, ptpython, pyflakes, pyvim, pyvmomi, cffi, cryptography, PyOpenSSL
Successfully installed PyYAML-3.11 docopt-0.6.2 jedi-0.9.0 lxml-3.5.0 nsxramlclient-1.0.3 prompt-toolkit-0.57 ptpython-0.28 pyflakes-1.0.0 pygments-2.1 pyraml-parser-0.1.5 pyvim-0.0.13 pyvmomi-6.0.0 requests-2.9.1 six-1.10.0 wcwidth-0.1.6 PyOpenSSL-0.15.1 cffi-1.5.0 cryptography-1.2.2

Okay, so lets do some basic checks to ensure the modules are working correctly:

Python 2.7.5 (default, Nov 20 2015, 02:00:19) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from nsxramlclient.client import NsxClient
>>> from pyVim.connect import SmartConnect, Disconnect
>>> from pyVmomi import vim, vmodl

Looking good! All the libraries load, and don’t immediately complain about anything! (this isn’t to say they’ll definitely work, we’ll have to test them for that!)

In order to use the nsxramlclient library we will need a raml file (description of the NSX API). This can be attained by executing the below from your scripts folder:

(venv) [nsxlab]$ git clone https://github.com/vmware/nsxraml
Cloning into 'nsxraml'...
remote: Counting objects: 459, done.
remote: Total 459 (delta 0), reused 0 (delta 0), pack-reused 459
Receiving objects: 100% (459/459), 1.00 MiB | 1.78 MiB/s, done.
Resolving deltas: 100% (214/214), done.

This is a great time to navigate to the nsxramlclient github page and have a quick read of the readme file, the most important point to read is the mapping of create, read, update and delete methods onto POST, GET, PUT and DELETE http requests. You should also save a copy of this file locally on your workstation, and open it in a web browser. It contains a very handy reference to all the NSX API components. A cached copy of this file is available here should you wish to quickly view this now (you can’t directly view from GitHub).

Below you’ll see the description of the VDN Scopes call we’re going to make shortly. nsx_desc

First NSX Python Script

So lets create a very basic script to test our environment, we’ll create two files, one to hold the script itself and another to hold the credentials and endpoints. First create a file called ‘creds.py’ with the below content:

nsx_manager = "nsx01.lab.vrandom.com"
nsx_username = "admin"
nsx_password = "<your password>"

Now create a basic script called ‘nsx_test.py’ to connect to the NSX manager:

from creds import *
from nsxramlclient.client import NsxClient
import pprint
pp = pprint.PrettyPrinter(indent=4)

nsxraml_file = 'nsxraml/nsxvapiv614.raml'
client_session = NsxClient(nsxraml_file, nsx_manager, nsx_username, nsx_password)

vdn_scopes = client_session.read('vdnScopes', 'read')

All being well you should be greeted by the below nicely formatted JSON showing the response from the NSX manager (see screenshot if the output is too wide):

{'vdnScopes': {'vdnScope': {'clientHandle': None,
                            'clusters': {'cluster': [{'cluster': {'clientHandle': None,
                                                                  'extendedAttributes': None,
                                                                  'isUniversal': 'false',
                                                                  'name': 'n54l',
                                                                  'nodeId': '4218115B-03A8-B552-9491-FCB8981E6E51',
                                                                  'objectId': 'domain-c21',
                                                                  'objectTypeName': 'ClusterComputeResource',
                                                                  'revision': '10',
                                                                  'scope': {'id': 'datacenter-2',
                                                                            'name': 'lab1',
                                                                            'objectTypeName': 'Datacenter'},
                                                                  'type': {'typeName': 'ClusterComputeResource'},
                                                                  'universalRevision': '0',
                                                                  'vsmUuid': '4218115B-03A8-B552-9491-FCB8981E6E51'}},
                                                     {'cluster': {'clientHandle': None,
                                                                  'extendedAttributes': None,
                                                                  'isUniversal': 'false',
                                                                  'name': 'gen8',
                                                                  'nodeId': '4218115B-03A8-B552-9491-FCB8981E6E51',
                                                                  'objectId': 'domain-c7',
                                                                  'objectTypeName': 'ClusterComputeResource',
                                                                  'revision': '22',
                                                                  'scope': {'id': 'datacenter-2',
                                                                            'name': 'lab1',
                                                                            'objectTypeName': 'Datacenter'},
                                                                  'type': {'typeName': 'ClusterComputeResource'},
                                                                  'universalRevision': '0',
                                                                  'vsmUuid': '4218115B-03A8-B552-9491-FCB8981E6E51'}}]},
                            'controlPlaneMode': 'UNICAST_MODE',
                            'description': None,
                            'extendedAttributes': None,
                            'id': 'vdnscope-1',
                            'isUniversal': 'false',
                            'name': 'lab1',
                            'nodeId': '4218115B-03A8-B552-9491-FCB8981E6E51',
                            'objectId': 'vdnscope-1',
                            'objectTypeName': 'VdnScope',
                            'revision': '0',
                            'type': {'typeName': 'VdnScope'},
                            'universalRevision': '0',
                            'virtualWireCount': '1',
                            'vsmUuid': '4218115B-03A8-B552-9491-FCB8981E6E51'}}}


So there you have it! You’re now all connected to your NSX manager and ready to start building something amazing! In the next article I’ll cover preparing our lab ready to start dynamically deploying devices via the API.