NSX-V Interface Details Using Python: Explained

In this article I will explain the logic behind the python program that I have created to extract interface information from all the NSX edges (DLR + Edge) under a NSX manager

Preface

This program is part of the network-automation-examples repository in my github account where I regularly update automation examples that I have created and used. Feel free to clone the repository and use as you may. Also, I would appriciate if you contribute your programs/ideas as well over there, so that ultimately the networking community can leverage them.

Tools Required

First and foremost we will need Python 3.x, preferably the latest version. Along with python the below python modules are required to run this program. You can install them via pip directly or from the IDE that you are using inside your virtualenv.

  • xml.etree.ElementTree
  • getpass
  • base64
  • requests

Note, in this example I have used NSX-V 6.4.X. If you are running this in any other trails, please refer to the API documentation of that version and modify the requests accoudingly.

Create The Program Bit-by-Bit

First of all create a .py extension file named with your program name and include the modules,

1import requests
2import xml.etree.ElementTree as ET
3import getpass
4import base64

Create Functions For File Operations

Lets create some functions for,

  • Creating Output file
  • Creating Log File
  • Appending data to any file
 1def create_ouput_file(NSX_Manager):
 2    op_filename = NSX_Manager + "_Edges_interfaces_details.csv"
 3    header = "edge_id, Int_Name,connected_with,IPaddr,Mask,isConnected"
 4    with open (op_filename, 'w') as f:
 5        f.write(header + "\n")
 6        f.close()
 7    return  op_filename
 8
 9def create_log_file(NSX_Manager):
10    log_file = NSX_Manager + "_edge_interface_details_Log.txt"
11    with open(log_file, 'w') as f:
12        f.close()
13    return log_file
14
15def append_to_file(filename, line_to_print):
16    with open(filename, 'a') as f:
17        f.write(line_to_print + '\n')
18        f.close()

With the help of append_to_file function we will append our output data and log entries of the program inside the files op_filename and log_file respectively.

Create Function To Connect To NSX Manager Via API And Get The Response

Now lets create a function through which we can connect to NSX manager API using requests module with Base64 authentication (extracted from username and password which we will take as input later). We will use a try and except block to determine the outcome of the block. Note, the content-type supported by the NSX manager API is application/xml.

 1def connection(username, passwd, url, log_filename):
 2
 3    userpass = username + ":" + passwd
 4    encoded_u = base64.b64encode(userpass.encode()).decode()
 5    headers = {
 6        'content-type': "application/xml",
 7        'authorization': "Basic %s" % encoded_u,
 8
 9    }
10    try:
11        response = requests.request("GET", url, headers=headers, verify=False)
12        response.raise_for_status()
13        append_to_file(log_filename,(url + " ++connection sucess++"))
14
15    except requests.exceptions.RequestException as e:
16        raise SystemExit(e)
17        append_to_file(log_filename, (url + e + " --connection failed--"))
18
19    return response.content

Create Function To Get a Directory = {edge_id: edge_type} of NSX Edges

In order to get interface details, first we will need to know the edge_type and ids of NSX edges that are deployed via the NSX manager. We can run a API call to NSX manager to get the list of edges and parse that XML output to create a device dictionary. Note, we are calling the function connection which we created earlier, inside this function.

 1def nsx_edge_list(NSX_Manager,username,passwd,log_filename):
 2    url = "https://" + NSX_Manager + "/api/4.0/edges"
 3    edge_dict = {}
 4    response = connection(username, passwd, url,log_filename)
 5    tree = ET.fromstring(response)[0]
 6
 7    for edge_id in tree.findall("edgeSummary"):
 8        for edge_type in edge_id.findall("edgeType"):
 9            edge_dict[edge_id[0].text] = edge_type.text
10
11    append_to_file(log_filename, "++ nsx_edge_list_prepared ++ ")
12    return edge_dict

Parse XML Config For DLR Type Edges

In this block we will parse the the XML config of NSX edges which are Distributed Router.

 1def nsx_edge_dlr_int_details(edge_id,NSX_Manager,username,passwd,op_filename,log_filename):
 2    url = "https://" + NSX_Manager + "/api/4.0/edges/" + edge_id + "/interfaces"
 3    response = connection(username, passwd, url,log_filename)
 4    tree = ET.fromstring(response)
 5    for vnic in tree.findall('interface'):
 6        vnic_name = vnic.find('name').text
 7        vnic_ip_addr = vnic.find('addressGroups/addressGroup/primaryAddress').text
 8        vnic_ip_mask = vnic.find('addressGroups/addressGroup/subnetMask').text
 9        vnic_connected_with = vnic.find('connectedToName').text
10        vnic_connected_status = vnic.find('isConnected').text
11        line_to_print = edge_id + ',' + vnic_name + ',' + vnic_connected_with + ',' + vnic_ip_addr + ',' + vnic_ip_mask+\
12                        ',' + vnic_connected_status
13        append_to_file(op_filename,line_to_print)
14        append_to_file(log_filename, ('--worked on ' + edge_id + ' ' + vnic_name + " --"))

Parse XML Config For GatewayServices Type Edges

In this block we will parse the the XML config of NSX edges which are of type gatewayservices.

 1def nsx_edge_esg_int_details(edge_id,NSX_Manager,username,passwd,op_filename,log_filename):
 2    url = "https://" + NSX_Manager + "/api/4.0/edges/" + edge_id + "/vnics"
 3    response = connection(username, passwd, url,log_filename)
 4    tree = ET.fromstring(response)
 5    for vnic in tree.findall('vnic'):
 6        if (vnic.find('isConnected').text) == 'true':
 7            vnic_name = (vnic.find('name').text).strip()
 8            vnic_connected_status = vnic.find('isConnected').text
 9            vnic_connected_with = vnic.find('portgroupName').text
10            vnic_primary_addrs = vnic.findall('addressGroups/addressGroup')
11            for vnic_primary_addr in vnic_primary_addrs:
12                vnic_pri_ip = vnic_primary_addr.find('primaryAddress').text
13                vnic_pri_mask = vnic_primary_addr.find('subnetMask').text
14                line_to_print = edge_id + ',' + vnic_name + ',' + vnic_connected_with + ',' + vnic_pri_ip + ',' + \
15                                vnic_pri_mask + ',' + vnic_connected_status
16                append_to_file(op_filename,line_to_print)
17                append_to_file(log_filename, ('--worked on ' + edge_id + ' ' + vnic_name + " --"))

Assemble The Functional Blocks And Create The main() Workflow

Now that we have created all the functional blocks needed for-

  • Get the list of NSX edge IDs and types
  • Get the data for individual NSX edges
  • Parse the data according to their type
  • Created Output, Log file and function to appened data to these files.

Lets, assemble these functional blocks inside our main() function.

 1def main(NSX_Manager,username,passwd):
 2    
 3    NSX_Manager = input("NSX Manager IP: ")
 4    username = input("Enter username: ")
 5    passwd = getpass.getpass()
 6
 7    op_filename = create_ouput_file(NSX_Manager)
 8    log_filename = create_log_file(NSX_Manager)
 9
10    edge_dict = nsx_edge_list(NSX_Manager,username,passwd,log_filename)
11
12    for key in edge_dict.keys():
13
14        if edge_dict[key] == 'distributedRouter':
15            append_to_file(log_filename, ('++ Started working on edge ' + key + ' ++'))
16            nsx_edge_dlr_int_details(key,NSX_Manager,username,passwd,op_filename,log_filename)
17            append_to_file(log_filename, ('++ Finished working on edge ' + key + ' ++'))
18
19        elif edge_dict[key] == "gatewayServices":
20            append_to_file(log_filename, ('++ Started working on edge ' + key + ' ++'))
21            nsx_edge_esg_int_details(key,NSX_Manager,username,passwd,op_filename,log_filename)
22            append_to_file(log_filename, ('++ Finished working on edge ' + key + ' ++'))

Note, inside the main() function only we are taking user input for NSX_Manager IP, username and password when user is running this program.

And that's it!

The entire script can be found in this link.