Using Python with the VeloCloud Orchestrator

VeloCloud has an API available to perform different actions including pushing configurations and reading back status information. Unfortunately, a lot of the API access functions are limited to end customers. However, any information you can obtain through the usual VeloCloud Orchestrator web interface, you can retrieve programmatically. I will explain how to do this using Python 3.

JSON

I have a very specific issue with my VeloCloud deployment in that when using cable circuits from Comcast, the modem hands out a 10.1.10.x address by default. Unfortunately, this causes issues with my locations because that subnet is used internally. When local traffic tries to reach the 10.1.10.x destination, the VeloCloud Edge device sees that subnet as being available through a locally-connected interface (in addition to the VPN).

Normal routing rules still apply, and a connected interface beats learning the route over the VPN. I thought about advertising 10.1.10.0/25 and 10.1.10.128/25 over the VPN, but unfortunately I have production systems using .127 and .128, so that’s not an option.

We are left with three choices to rectify this situation: provision Comcast circuits with static IP addresses, have the modems placed into bridged mode, or change the private IP subnet that the Comcast modem provides. All three of these options have the same downfall: if a Comcast technician ever has to replace a modem and they don’t verify the previous modem configuration, we’ll fall right back into the same trap.

I don’t have a permanent answer yet for this situation, but after reading this excellent post by Martijn Smit, I started using Postman to explore the VC API a little bit. Through trial and error, I discovered that as the end customer, there are many functions for which I do not have permissions to access, or what is available doesn’t provide the information I’m looking for. One of the things I couldn’t figure out how to do directly through the API was how to get the local interface IP address of the VC edges. Yet, I could access this information through the VCO web interface.

I used the developer tools built into Google Chrome to log into the VCO and click the usual links to get the information I want. In version 3.2 of the VCO, you get the local IP address of a particular VC edge by clicking “Test & Troubleshoot” > “Remote Diagnostics” > select the edge you want > then click the “Run” button under the “Interface Status” section.

Interface Status

When you select the VC edge, there is an average 15- to 30-second pause while the edge enters “Live” mode, which is how VeloCloud chose to quiesce the current operational statistics. Then there is another delay of typically 10 seconds when you click the “Run” button. Clearly, this process is not going to work if you want to retrieve this information from hundreds of sites. However, using Python, you can batch and automate these kinds of requests and then manipulate the returned data however you wish.

With the Chrome developer tools (other browsers have them as well), you can see exactly what was sent and received in a particular transaction. One of the first transactions is /enterprise/getEnterpriseEdges which obtains an overview of every VC edge that is accessible within your portal. With the developer tools, you can see the exact JSON-formatted request that was sent (and to where it was sent). The response is also JSON-formatted, which you can then convert to other formats within Python to more easily extract the usable data.

GEE

After you click the “Run” button next to “Interface Status” you will eventually see a “liveData” entry in the developer tools that shows you the different statistics available for the WAN links on the VC edge. Included is the information I was looking for (localIpAddress), along with the public WAN address and lots of other statistics. It would be fairly trivial to create a script that polls edges at regular intervals and compares statistics from previous runs to determine trends such as packet loss or monitor for IP address changes.

LS

The script I wrote has lots of inline comments explaining everything so that a beginner can understand what is going on. Putting in all the comments was almost a blog post unto itself. The script uses your defined credentials to log into the VCO and establish a session. Part of the session establishment is being assigned a unique “token” value that you will use on all subsequent requests. The script then pulls an overview of all the available edges and creates a list of edges that are connected at that moment.

Then the level of multi-threading is established. I have hundreds of sites to query, and while the script is perfectly capable of querying every single site simultaneously, I wanted to respect the fact that the VCO I am contacting is not under my administrative control, so I did not want to risk flooding it with hundreds of simultaneous requests. My script will perform its work in batches of 10 by default.

The batches are then sent to the main function. The VC edge is placed into live mode, then the script pauses to account for the quiescing process. The script then attempts to gather the information from the edge. If the edge has not yet fully entered live mode, or if the data being requested does not exist, an exception is thrown. My script accounts for this and retries the operation after going through the pause time again.

Finally, after the full set of information is obtained, my script determines if there are one, two, three or four WAN uplinks connected, and obtains the local IP address depending on the number of links. The results are written to a timestamped output file.

If you wish to modify my script and do some exploring on your own, I recommend doing this in an open Python interpreter window because there is a lot of trial and error in retrieving the specific information you want. This is because the data inside the JSON-formatted responses is deeply nested. You can use this abbreviated (uncommented) version of my script that is designed to interact with a single VC edge. Once you define the few variables at the top, you can paste this into an open Python3 interpreter. In the very first line, replace “483” with the ID of one of your edges.

python3

edgeid = str(483)
username = "you@your.com"
password = "pass"
urllogin = "https://yourvco.com/portal/login/enterpriseLogin"
urlportal = "https://yourvco.com/portal/"
urllivedata = "https://yourvco.com/livepull/liveData"

import json
import requests
import time
import threading
exectime = time.strftime("%Y-%m-%d_%H%M%S")
loginjson = '{"username":"' + username + '","password":"'\
             + password + '"}'
session1 = requests.Session()
session1.post(urllogin, data=loginjson)
livejson = '{"jsonrpc":"2.0","method":"liveMode/enterLiveMode",\
              "params":{"id":' + edgeid + '},"id":' + edgeid + '}'
livemode = session1.post(urlportal, data=livejson)
jsonlive = json.loads(livemode.text)
jsonlivedict = dict(jsonlive.get('result'))
token = jsonlivedict.get('token')
edgeselectjson = '{"jsonrpc":"2.0",\
   "method":"liveMode/requestLiveActions",\
   "params":{"actions":[{"action":"listDiagnostics",\
   "parameters":{}}],"token":"' + token + '"},"id":1}'
edgeselect = session1.post(urllivedata, data=edgeselectjson)
time.sleep(60)
localipjson = '{"jsonrpc":"2.0","method":"liveMode/readLiveData",\
   "params":{"token":"' + token + '"},"id":2}'
localip = session1.post(urllivedata, data=localipjson)
ip = json.loads(localip.text)

Once you reach this point, type in “ip” and then press the “Enter” key. You will be presented with tons of information about this edge (much of it repeated multiple times for some reason). Now is where you can drill down into the exact information you’re looking for. Type “ip.keys()” to see what’s in the next level. Going several layers deep, you can see more specific information:

ip['result']['data']['linkStats']['data'][1]['data'][0]['localIpAddress']

Where each [‘x’] represents a new sub-level.

Once again, my original (fully commented) script is available on my GitHub] page.

It’s good that I explored how to interact with the VCO with Python and JSON because these kinds of interactions are what our industry is moving toward, but keep in mind that existing tools can still serve your needs quite well. In this case, I could have obtained the same local IP address information nearly instantly by doing an SNMP GET to OID .1.3.6.1.2.1.4.20.1.2.18 (GE1 interface) against the VC edge management IP address. Some tools are more appropriate than others. The key is to really know and understand the tools that are available to you so you can apply the proper tool for the appropriate situation.