In [1]:
# Jupyter Notebook
# DevNet
# REST API
# Get ServiceTicket/ Token
# List Hosts on the network
# List Network Devices
# Perform Path Trace
import datetime
print ("Current date and time: ")
print(datetime.datetime.now())
print('Hello World')
print("Here are three network tests executed by APIC EM for enterprise networks")
print("- List all active hosts")
print("- List all network devices")
print("- Perform Path Trace in order to test connections in the datacenter")
Current date and time: 
2018-11-29 16:30:35.666244
Hello World
Here are three network tests executed by APIC EM for enterprise networks
- List all active hosts
- List all network devices
- Perform Path Trace in order to test connections in the datacenter
In [2]:
#01_get_ticket.py
#This script retrieves an authentication token from APIC-EM and prints out it's value
#It is standalone, there is no dependency.
print ("Current date and time: ")
print(datetime.datetime.now())
print("Part 1 - Get ServiceTicket or token")
Current date and time: 
2018-11-29 16:30:50.647150
Part 1 - Get ServiceTicket or token
In [3]:
import json       # Import JSON encoder and decoder module
import requests   # requests module used to send REST requests to API
requests.packages.urllib3.disable_warnings() # Disable SSH warnings
print ("Current date and time: ")
print(datetime.datetime.now())
print("Importing necessary modules and disabling SSH warnings")
Current date and time: 
2018-11-29 16:30:54.938870
Importing necessary modules and disabling SSH warnings
In [4]:
# TICKET API URL
# retrieves an authentication token from APIC-EM 
# sandbox_url = 'https://devnetsbx-netacad-apicem-2.cisco.com/'
sandbox_url = 'https://devnetsbx-netacad-apicem-3.cisco.com/'
print ("Current date and time: ")
print(datetime.datetime.now())
post_url = sandbox_url+'api/v1/ticket'
print("URL for getting service ticket has just been created")
print(post_url)
Current date and time: 
2018-11-29 16:31:00.470217
URL for getting service ticket has just been created
https://devnetsbx-netacad-apicem-3.cisco.com/api/v1/ticket
In [5]:
# All APIC-EM REST API request and response content type is JSON.
headers = {'content-type': 'application/json'}
print ("Current date and time: ")
print(datetime.datetime.now())
print('HTTP Header created')
print("Using JSON to communicate parameters")
Current date and time: 
2018-11-29 16:31:05.176188
HTTP Header created
Using JSON to communicate parameters
In [6]:
# JSON  input body content  -- 2: w0ISNW79 -- 3:  Xj3BDqbU
body_json = {
    'username': 'devnetuser',
    'password': 'Xj3BDqbU' 
}
print ("Current date and time: ")
print(datetime.datetime.now())
print("Username and password for access to the sandbox has just been defined")
print('Username and password passed in JSON format')
Current date and time: 
2018-11-29 16:31:19.756390
Username and password for access to the sandbox has just been defined
Username and password passed in JSON format
In [7]:
# Make request and get response - "resp" is the response of this request
resp = requests.post(post_url, json.dumps(body_json), headers=headers,verify=False)
print ("Current date and time: ")
print(datetime.datetime.now())
print("The request and all the necessary parameters have been sent")
Current date and time: 
2018-11-29 16:31:27.292931
The request and all the necessary parameters have been sent
In [8]:
# Create object to contain the request status
status = str(resp.status_code) #status code property of resp object
print ("Current date and time: ")
print(datetime.datetime.now())
print("Ticket request status: " + status) #display response code
Current date and time: 
2018-11-29 16:31:34.969980
Ticket request status: 200
In [9]:
# Create object to contain the converted json-formatted response
response_json = resp.json()
print ("Current date and time: ")
print(datetime.datetime.now())
print("The RAW json reply is being processed")
Current date and time: 
2018-11-29 16:31:45.275771
The RAW json reply is being processed
In [10]:
#parse data for service ticket
serviceTicket = response_json['response']['serviceTicket'] 
print ("Current date and time: ")
print(datetime.datetime.now())
print("The service ticket number is: " + serviceTicket)
Current date and time: 
2018-11-29 16:31:51.423107
The service ticket number is: ST-1125-nNADutkaQE1DLu0Xee4c-cas
In [11]:
print ("Current date and time: ")
print(datetime.datetime.now())
print("We now have a service ticket for the jobs following")
Current date and time: 
2018-11-29 16:31:55.276615
We now have a service ticket for the jobs following
In [12]:
#Based on: lab1-1-get-host.py
#02_get_host_sol
#This script prints out all hosts that are connected to APIC-EM network devices in a tabular list format.
#02_get_host.py
#gets an inventory of hosts from \host endpoint
print ("Current date and time: ")
print(datetime.datetime.now())
print("Part 2 - List of hosts")
Current date and time: 
2018-11-29 16:32:03.198019
Part 2 - List of hosts
In [13]:
import requests
import json
from tabulate import *
print ("Current date and time: ")
print(datetime.datetime.now())
print("Importing necessary modules")
Current date and time: 
2018-11-29 16:32:09.327702
Importing necessary modules
In [14]:
# HOST API URL
post_url = sandbox_url+'api/v1/host'
print ("Current date and time: ")
print(datetime.datetime.now())
print("URL for requesting list of active hosts has just been created")
print(post_url)
Current date and time: 
2018-11-29 16:32:12.501105
URL for requesting list of active hosts has just been created
https://devnetsbx-netacad-apicem-3.cisco.com/api/v1/host
In [15]:
# All APIC-EM REST API request and response content type is JSON.
ticket = serviceTicket 
headers = {'content-type':'application/json','X-Auth-Token':ticket}
print ("Current date and time: ")
print(datetime.datetime.now())
print("Using JSON to communicate parameters and passing the token that was created earlier")
print("Ticket: "+ticket)
Current date and time: 
2018-11-29 16:32:17.454831
Using JSON to communicate parameters and passing the token that was created earlier
Ticket: ST-1125-nNADutkaQE1DLu0Xee4c-cas
In [17]:
print ("Current date and time: ")
print(datetime.datetime.now())
try:
    resp = requests.get(post_url,headers=headers,params="",verify = False)
    response_json = resp.json() # Get the json-encoded content from response
    print ('Status of GET /host request: ',str(resp.status_code))  # This is the http request status
    print ('Printing json reply')
    print ('==============================================================')
    print(response_json)
    print ('==============================================================')
except:
    print ('Something is wrong with GET /host request!')
    sys.exit()
Current date and time: 
2018-11-29 16:32:46.105939
Status of GET /host request:  200
Printing json reply
==============================================================
{'response': [{'hostIp': '10.1.15.117', 'hostMac': '00:24:d7:43:59:d8', 'hostType': 'wireless', 'connectedNetworkDeviceId': 'cd6d9b24-839b-4d58-adfe-3fdf781e1782', 'connectedNetworkDeviceIpAddress': '10.1.14.3', 'connectedAPMacAddress': '68:bc:0c:63:4a:b0', 'connectedAPName': 'AP7081.059f.19ca', 'vlanId': '600', 'lastUpdated': '1479514114932', 'source': '200', 'pointOfPresence': 'ae19cd21-1b26-4f58-8ccd-d265deabb6c3', 'pointOfAttachment': 'ae19cd21-1b26-4f58-8ccd-d265deabb6c3', 'subType': 'UNKNOWN', 'id': '48cdeb9b-b412-491e-a80c-7ec5bbe98167'}, {'hostIp': '10.2.1.22', 'hostMac': '5c:f9:dd:52:07:78', 'hostType': 'wired', 'connectedNetworkDeviceId': '26450a30-57d8-4b56-b8f1-6fc535d67645', 'connectedNetworkDeviceIpAddress': '10.2.1.17', 'connectedInterfaceId': '7075521d-4d7b-4218-92f9-79b60e054635', 'connectedInterfaceName': 'GigabitEthernet1/0/47', 'vlanId': '200', 'lastUpdated': '1479514299803', 'source': '200', 'subType': 'UNKNOWN', 'id': 'f624d4f3-0ab9-4ae3-b09d-62051edbd8f3'}, {'hostIp': '10.1.12.20', 'hostMac': 'e8:9a:8f:7a:22:99', 'hostType': 'wired', 'connectedNetworkDeviceId': '5b5ea8da-8c23-486a-b95e-7429684d25fc', 'connectedNetworkDeviceIpAddress': '10.1.12.1', 'connectedInterfaceId': '6e4e5ae6-6045-4060-9038-1a64d5a101cc', 'connectedInterfaceName': 'GigabitEthernet1/0/47', 'vlanId': '200', 'lastUpdated': '1479513914455', 'source': '200', 'subType': 'UNKNOWN', 'id': '572d4065-abd8-4b97-bfc3-ab5ee13f6c08'}], 'version': '1.0'}
==============================================================
In [18]:
# Now create a list of host info to be held in host_list
host_list=[]
i=0
for item in response_json['response']:
    i+=1
    host_list.append([i,item['hostType'],item['hostIp']])
print ("Current date and time: ")
print(datetime.datetime.now())
print('Looping accross all detected hosts')
Current date and time: 
2018-11-29 16:32:54.860717
Looping accross all detected hosts
In [19]:
print ("Current date and time: ")
print(datetime.datetime.now())
print("Here's the list of active hosts")
print (tabulate(host_list,headers=['Number','Type','IP'],tablefmt='rst'))
Current date and time: 
2018-11-29 16:32:59.100821
Here's the list of active hosts
========  ========  ===========
  Number  Type      IP
========  ========  ===========
       1  wireless  10.1.15.117
       2  wired     10.2.1.22
       3  wired     10.1.12.20
========  ========  ===========
In [20]:
#Based on: lab1-1-get-host.py
#04_get_device_sol
print ("Current date and time: ")
print(datetime.datetime.now())
print("This script prints out all network devices that are connected to APIC-EM network devices in a tabular list format")
Current date and time: 
2018-11-29 16:33:03.454728
This script prints out all network devices that are connected to APIC-EM network devices in a tabular list format
In [21]:
import requests
import json
import sys
from tabulate import *
print ("Current date and time: ")
print(datetime.datetime.now())
print("Importing necessary modules")
Current date and time: 
2018-11-29 16:33:06.260157
Importing necessary modules
In [22]:
# NETWORK-DEVICE API URL
post_url = sandbox_url+'api/v1/network-device'
print ("Current date and time: ")
print(datetime.datetime.now())
print("Preparing URL for list of network devices")
print(post_url)
Current date and time: 
2018-11-29 16:33:09.648733
Preparing URL for list of network devices
https://devnetsbx-netacad-apicem-3.cisco.com/api/v1/network-device
In [23]:
# Setup API request headers.
ticket = serviceTicket 
headers = {'content-type' : 'application/json','X-Auth-Token': ticket}
print ("Current date and time: ")
print(datetime.datetime.now())
print('Ticket: ' + ticket)
print("Using JSON to communicate parameters and passing the token that was created earlier")
Current date and time: 
2018-11-29 16:33:12.939155
Ticket: ST-1125-nNADutkaQE1DLu0Xee4c-cas
Using JSON to communicate parameters and passing the token that was created earlier
In [24]:
print ("Current date and time: ")
print(datetime.datetime.now())
device_list=[]
try:
    resp = requests.get(post_url,headers=headers,params='',verify = False)
    response_json = resp.json() # Get the json-encoded content from response
    print ('Status of GET /device request: ',resp.status_code)  # This is the http request status
except:
    print ('Something wrong with GET /host request!')
    sys.exit()
    # Now create a list of host summary info
i=0
for item in response_json['response']:
    i+=1
    device_list.append([i,item['type'],item['managementIpAddress']])
print('Looping accross all detected network devices')
Current date and time: 
2018-11-29 16:33:16.345452
Status of GET /device request:  200
Looping accross all detected network devices
In [25]:
print ("Current date and time: ")
print(datetime.datetime.now())
print ("List of network devices")
print (tabulate(device_list,headers=['Number','Type','IP'],tablefmt='rst'))
Current date and time: 
2018-11-29 16:33:20.789149
List of network devices
========  ==============================================  =============
  Number  Type                                            IP
========  ==============================================  =============
       1  Cisco Catalyst 2960C-8PC-L Switch               165.10.1.39
       2  Cisco 3500I Unified Access Point                10.1.14.3
       3  Cisco Catalyst 29xx Stack-able Ethernet Switch  10.2.1.17
       4  Cisco 2911 Integrated Services Router G2        10.2.2.1
       5  Cisco 2911 Integrated Services Router G2        10.2.2.2
       6  Cisco 2911 Integrated Services Router G2        218.1.100.100
       7  Cisco Catalyst 3850-48U-E Switch                10.1.12.1
       8  Cisco Catalyst 6503 Switch                      10.1.7.1
       9  Cisco Catalyst 6503 Switch                      10.1.10.1
      10  Cisco Catalyst 4507R plus E Switch              10.255.1.5
      11  Cisco Catalyst 4507R plus E Switch              10.1.11.1
      12  Cisco 4451 Series Integrated Services Router    10.1.2.1
      13  Cisco 4451 Series Integrated Services Router    10.1.4.2
      14  Cisco 5508 Wireless LAN Controller              10.1.14.2
========  ==============================================  =============
In [26]:
#04_path_trace_sol.py
#Path Trace testing network connectivity
print ("Current date and time: ")
print(datetime.datetime.now())
print("Part 3 - Path Trace Testing Network Connectivity")
Current date and time: 
2018-11-29 16:33:24.376119
Part 3 - Path Trace Testing Network Connectivity
In [27]:
#==================================================
# Section 1. Setup the environment and variables required to interact with the APIC-EM
#===================================================
import requests
import json
import time
import sys
from tabulate import *
requests.packages.urllib3.disable_warnings() #disables certificate security warning
print ("Current date and time: ")
print(datetime.datetime.now())
print("Importing necessary modules and disabling SSH warnings")
Current date and time: 
2018-11-29 16:33:27.214766
Importing necessary modules and disabling SSH warnings
In [28]:
# Path Trace API URL for flow_analysis endpoint
post_url = sandbox_url+'api/v1/flow-analysis'
print("Preparing URL for path trace")
print ("Current date and time: ")
print(datetime.datetime.now())
print(post_url)
Preparing URL for path trace
Current date and time: 
2018-11-29 16:33:30.392491
https://devnetsbx-netacad-apicem-3.cisco.com/api/v1/flow-analysis
In [29]:
# Get service ticket number using imported function
ticket = serviceTicket
print ("Current date and time: ")
print(datetime.datetime.now())
print("The token or serviceticket has to be passed in the request")
print("Ticket: "+ticket)
Current date and time: 
2018-11-29 16:33:33.244518
The token or serviceticket has to be passed in the request
Ticket: ST-1125-nNADutkaQE1DLu0Xee4c-cas
In [30]:
# Create headers for requests to the API
headers = {
			"content-type" : "application/json",
			"X-Auth-Token": ticket
			}
print ("Current date and time: ")
print(datetime.datetime.now())
print('HTTP Header created')
print("Alongside the token, the system informs that json will be used in communicatons with the services")
Current date and time: 
2018-11-29 16:33:36.423609
HTTP Header created
Alongside the token, the system informs that json will be used in communicatons with the services
In [31]:
#============================
# Section 2. Display list of devices and IPs by calling get_host() and get_devices()
#============================

#++++++++++++++++++++++++++++++++++++++++++
print ("Current date and time: ")
print(datetime.datetime.now())
print('List of hosts on the network: ')
print (tabulate(host_list,headers=['Number','Type','IP'],tablefmt='rst'))
print('\n') #prints blank line to format output
print('List of devices on the network: ')
print (tabulate(device_list,headers=['Number','Type','IP'],tablefmt='rst'))
Current date and time: 
2018-11-29 16:33:39.502206
List of hosts on the network: 
========  ========  ===========
  Number  Type      IP
========  ========  ===========
       1  wireless  10.1.15.117
       2  wired     10.2.1.22
       3  wired     10.1.12.20
========  ========  ===========


List of devices on the network: 
========  ==============================================  =============
  Number  Type                                            IP
========  ==============================================  =============
       1  Cisco Catalyst 2960C-8PC-L Switch               165.10.1.39
       2  Cisco 3500I Unified Access Point                10.1.14.3
       3  Cisco Catalyst 29xx Stack-able Ethernet Switch  10.2.1.17
       4  Cisco 2911 Integrated Services Router G2        10.2.2.1
       5  Cisco 2911 Integrated Services Router G2        10.2.2.2
       6  Cisco 2911 Integrated Services Router G2        218.1.100.100
       7  Cisco Catalyst 3850-48U-E Switch                10.1.12.1
       8  Cisco Catalyst 6503 Switch                      10.1.7.1
       9  Cisco Catalyst 6503 Switch                      10.1.10.1
      10  Cisco Catalyst 4507R plus E Switch              10.255.1.5
      11  Cisco Catalyst 4507R plus E Switch              10.1.11.1
      12  Cisco 4451 Series Integrated Services Router    10.1.2.1
      13  Cisco 4451 Series Integrated Services Router    10.1.4.2
      14  Cisco 5508 Wireless LAN Controller              10.1.14.2
========  ==============================================  =============
In [32]:
# ============================
# Section 3. Get the source and destination IP addresses for the Path Trace
# ============================
print ("Current date and time: ")
print(datetime.datetime.now())
while True:
	#++++++++++++++++++++++++++++++++++++++++++
	s_ip = input('Please enter the source IP address for the path trace: ')
	d_ip = input('Please enter the destinaion IP address for the path trace: ')
	#++++++++++++++++++++++++++++++++++++++++++
	#Various error traps should be completed here - POSSIBLE CHALLENGE
	if s_ip != '' or d_ip != '':
		#this creates a python dictionary that will be dumped as a 
		path_data = {                     
					"sourceIP": s_ip, 
					"destIP": d_ip
					}
		print('Source IP address is: ' + path_data['sourceIP']) #stud: optional challenge
		print('Destination IP address is: ' + path_data['destIP']) #stud: optional challenge
		break #Exit loop if values supplied
	else:
		print("\n\nYOU MUST ENTER IP ADDRESSES TO CONTINUE.\nUSE CTRL-C TO QUIT\n")
		continue #Return to beginning of loop and repeat
Current date and time: 
2018-11-29 16:33:43.133571
Please enter the source IP address for the path trace: 10.2.2.2
Please enter the destinaion IP address for the path trace: 10.1.12.20
Source IP address is: 10.2.2.2
Destination IP address is: 10.1.12.20
In [33]:
#============================
# Section 4. Initiate the Path Trace and get the flowAnalysisId
#============================

#++++++++++++++++++++++++++++++++++++		
# Post request to initiate Path Trace
path = json.dumps(path_data) #variable to hold the path_data
resp = requests.post(post_url,path,headers=headers,verify=False)

# Inspect the return, get the Flow Analysis ID, put it into a variable
resp_json = resp.json()
flowAnalysisId = resp_json["response"]["flowAnalysisId"]
print ("Current date and time: ")
print(datetime.datetime.now())
print('FLOW ANALYSIS ID: ' + flowAnalysisId)
print(path)
Current date and time: 
2018-11-29 16:34:24.213710
FLOW ANALYSIS ID: 4e78ccb8-01f4-4a3d-b826-38a5c9b99e69
{"sourceIP": "10.2.2.2", "destIP": "10.1.12.20"}
In [43]:
#============================
# Section 5. Check status of Path Trace request, output results when COMPLETED
#============================
print("This section might take some time to run")
status = ""

#Add Flow Analysis ID to the endpoint URL in order to check the status of this specific path trace
#++++++++++++++++++++++++++++++++++++
check_url = post_url + "/" + flowAnalysisId
#++++++++++++++++++++++++++++++++++++

checks = 0 #variable to increment within the while loop. Will trigger exit from loop after x iterations
print ("START - Current date and time: ")
start=datetime.datetime.now()
print(datetime.datetime.now())
while status != 'COMPLETED':
	checks += 1
	r = requests.get(check_url,headers=headers,params="",verify = False)
	response_json = r.json()
	#++++++++++++++++++++++++++++++++++++
	status = response_json["response"]["request"]["status"]
	#++++++++++++++++++++++++++++++++++++
	print('REQUEST STATUS: ' + status)
	#wait one second before trying again
	time.sleep(2)
	if checks == 15: #number of iterations before exit of loop; change depending on conditions
		print("Number of status checks exceeds limit. Possible problem with Path Trace.")
		#break
		sys.exit()
	elif status == 'FAILED':
		print('Problem with Path Trace')
		print('Problem with FlowAnalysisId: ' + check_url)
		#break
		sys.exit()
	print('REQUEST STATUS: ' + status)
print(check_url)
print("Response in json format")
print ('==============================================================')
print(response_json)
print ('==============================================================')
print ("STOP - Current date and time: ")
print('START TIME: ' + str(start))
stop = datetime.datetime.now()
print('END TIME: ' + str(stop))
print('TIME NEEDED: '+ str(stop-start))
This section might take some time to run
START - Current date and time: 
2018-11-29 16:38:28.155529
REQUEST STATUS: COMPLETED
REQUEST STATUS: COMPLETED
https://devnetsbx-netacad-apicem-3.cisco.com/api/v1/flow-analysis/4e78ccb8-01f4-4a3d-b826-38a5c9b99e69
Response in json format
==============================================================
{'response': {'request': {'sourceIP': '10.2.2.2', 'destIP': '10.1.12.20', 'periodicRefresh': False, 'id': '4e78ccb8-01f4-4a3d-b826-38a5c9b99e69', 'status': 'COMPLETED', 'createTime': 1543505665029, 'lastUpdateTime': 1543505672353}, 'lastUpdate': 'Thu Nov 29 15:38:29 UTC 2018', 'networkElementsInfo': [{'id': '6ce631db-9212-4587-867f-b8f3aed1702d', 'name': 'Branch-Router2', 'type': 'Routers', 'ip': '10.2.2.2', 'egressInterface': {'physicalInterface': {'id': '0b3b2b54-e7c6-4d03-bca8-27e9c0c0b272', 'name': 'GigabitEthernet0/0'}}, 'role': 'BORDER ROUTER', 'linkInformationSource': 'OSPF'}, {'id': 'UNKNOWN', 'name': 'UNKNOWN', 'ip': 'UNKNOWN', 'role': 'UNKNOWN', 'linkInformationSource': 'NetFlow'}, {'id': '9712ab62-6140-43fd-b1ee-1b07d1fb67d7', 'name': 'CAMPUS-Router1', 'type': 'Routers', 'ip': '10.1.2.1', 'ingressInterface': {'physicalInterface': {'id': '6dc56935-8268-45e4-acaa-de1c15a8832d', 'name': 'GigabitEthernet0/0/1'}}, 'egressInterface': {'physicalInterface': {'id': '43ee5993-b8a0-4ed8-8c1b-376273834582', 'name': 'GigabitEthernet0/0/0'}}, 'role': 'BORDER ROUTER', 'linkInformationSource': 'ECMP'}, {'id': '30d39b18-9ada-4148-ad6c-2ee20975b845', 'name': 'CAMPUS-Core1', 'type': 'Switches and Hubs', 'ip': '10.1.7.1', 'ingressInterface': {'physicalInterface': {'id': '6df9d717-5c7a-479e-a595-563480aaada0', 'name': 'GigabitEthernet1/2'}}, 'egressInterface': {'physicalInterface': {'id': 'f8a45bfd-0e1f-4f3e-b56c-150e3a9fc103', 'name': 'GigabitEthernet1/1'}}, 'role': 'CORE', 'linkInformationSource': 'OSPF'}, {'id': 'c8ed3e49-5eeb-4dee-b120-edeb179c8394', 'name': 'CAMPUS-Dist1', 'type': 'Switches and Hubs', 'ip': '10.255.1.5', 'ingressInterface': {'physicalInterface': {'id': '729002b4-a1cd-4700-a2f9-b68cbdfe2f70', 'name': 'GigabitEthernet5/7'}}, 'egressInterface': {'physicalInterface': {'id': 'b10dcdea-1675-4509-b554-f047f6a37595', 'name': 'GigabitEthernet5/5'}, 'virtualInterface': [{'id': '4adadf2b-d496-4d70-96e6-ad1bc0855bae', 'name': 'Vlan200'}]}, 'role': 'DISTRIBUTION', 'linkInformationSource': 'InterVlan Routing'}, {'id': '5b5ea8da-8c23-486a-b95e-7429684d25fc', 'name': 'CAMPUS-Access1', 'type': 'Switches and Hubs', 'ip': '10.1.12.1', 'ingressInterface': {'physicalInterface': {'id': '38c72319-855e-43bc-8458-94f695d435b6', 'name': 'GigabitEthernet1/0/1'}}, 'egressInterface': {'physicalInterface': {'id': '6e4e5ae6-6045-4060-9038-1a64d5a101cc', 'name': 'GigabitEthernet1/0/47'}, 'virtualInterface': [{'id': '6ca61e1e-89b8-4093-9294-f530a794cde3', 'name': 'Vlan200'}]}, 'role': 'DISTRIBUTION', 'linkInformationSource': 'Switched'}, {'id': '572d4065-abd8-4b97-bfc3-ab5ee13f6c08', 'type': 'wired', 'ip': '10.1.12.20'}], 'detailedStatus': {'aclTraceCalculation': 'SUCCESS'}}, 'version': '1.0'}
==============================================================
STOP - Current date and time: 
START TIME: 2018-11-29 16:38:28.155529
END TIME: 2018-11-29 16:38:30.487553
TIME NEEDED: 0:00:02.332024
In [44]:
#============================
# Section 6. Display results
#============================

#+++++++++++Add Values+++++++++++++++
# Create required variables
path_source = response_json['response']['request']['sourceIP'] 	#the source address for the trace, printed below
path_dest = response_json['response']['request']['destIP'] 	#the destination address for the trace, printed below
networkElementsInfo = response_json['response']['networkElementsInfo'] 	#variable holding a list of all the network element dictionaries
print ("Current date and time: ")
print(datetime.datetime.now())
print("Responses are being processed")
print("Path Source "+path_source)
print("Path Dest "+path_dest)
print("Network Elements Information "+json.dumps(networkElementsInfo))
Current date and time: 
2018-11-29 16:38:41.878909
Responses are being processed
Path Source 10.2.2.2
Path Dest 10.1.12.20
Network Elements Information [{"id": "6ce631db-9212-4587-867f-b8f3aed1702d", "name": "Branch-Router2", "type": "Routers", "ip": "10.2.2.2", "egressInterface": {"physicalInterface": {"id": "0b3b2b54-e7c6-4d03-bca8-27e9c0c0b272", "name": "GigabitEthernet0/0"}}, "role": "BORDER ROUTER", "linkInformationSource": "OSPF"}, {"id": "UNKNOWN", "name": "UNKNOWN", "ip": "UNKNOWN", "role": "UNKNOWN", "linkInformationSource": "NetFlow"}, {"id": "9712ab62-6140-43fd-b1ee-1b07d1fb67d7", "name": "CAMPUS-Router1", "type": "Routers", "ip": "10.1.2.1", "ingressInterface": {"physicalInterface": {"id": "6dc56935-8268-45e4-acaa-de1c15a8832d", "name": "GigabitEthernet0/0/1"}}, "egressInterface": {"physicalInterface": {"id": "43ee5993-b8a0-4ed8-8c1b-376273834582", "name": "GigabitEthernet0/0/0"}}, "role": "BORDER ROUTER", "linkInformationSource": "ECMP"}, {"id": "30d39b18-9ada-4148-ad6c-2ee20975b845", "name": "CAMPUS-Core1", "type": "Switches and Hubs", "ip": "10.1.7.1", "ingressInterface": {"physicalInterface": {"id": "6df9d717-5c7a-479e-a595-563480aaada0", "name": "GigabitEthernet1/2"}}, "egressInterface": {"physicalInterface": {"id": "f8a45bfd-0e1f-4f3e-b56c-150e3a9fc103", "name": "GigabitEthernet1/1"}}, "role": "CORE", "linkInformationSource": "OSPF"}, {"id": "c8ed3e49-5eeb-4dee-b120-edeb179c8394", "name": "CAMPUS-Dist1", "type": "Switches and Hubs", "ip": "10.255.1.5", "ingressInterface": {"physicalInterface": {"id": "729002b4-a1cd-4700-a2f9-b68cbdfe2f70", "name": "GigabitEthernet5/7"}}, "egressInterface": {"physicalInterface": {"id": "b10dcdea-1675-4509-b554-f047f6a37595", "name": "GigabitEthernet5/5"}, "virtualInterface": [{"id": "4adadf2b-d496-4d70-96e6-ad1bc0855bae", "name": "Vlan200"}]}, "role": "DISTRIBUTION", "linkInformationSource": "InterVlan Routing"}, {"id": "5b5ea8da-8c23-486a-b95e-7429684d25fc", "name": "CAMPUS-Access1", "type": "Switches and Hubs", "ip": "10.1.12.1", "ingressInterface": {"physicalInterface": {"id": "38c72319-855e-43bc-8458-94f695d435b6", "name": "GigabitEthernet1/0/1"}}, "egressInterface": {"physicalInterface": {"id": "6e4e5ae6-6045-4060-9038-1a64d5a101cc", "name": "GigabitEthernet1/0/47"}, "virtualInterface": [{"id": "6ca61e1e-89b8-4093-9294-f530a794cde3", "name": "Vlan200"}]}, "role": "DISTRIBUTION", "linkInformationSource": "Switched"}, {"id": "572d4065-abd8-4b97-bfc3-ab5ee13f6c08", "type": "wired", "ip": "10.1.12.20"}]
In [45]:
all_devices = [] # create a list variable to store the hosts and devices
device_no = 1  #this variable is an ordinal number for each device, incremented in the loop

#Iterate through returned Path Trace JSON and populate list of path information
for networkElement in networkElementsInfo:
    # test if the devices DOES NOT have a "name", absence of "name" identifies an end host
    if not 'name' in networkElement:  #assigns values to the variables for the hosts
       name = 'Unnamed Host'
       ip = networkElement['ip']
       egressInterfaceName = 'UNKNOWN'
       ingressInterfaceName = 'UNKNOWN'
       device = [device_no,name,ip,ingressInterfaceName,egressInterfaceName]
    # if there is the "name" key, then it is an intermediary device
    else: #assigns values to the variables for the intermediary devices
       name = networkElement['name']
       ip = networkElement['ip']   
       if 'egressInterface' in networkElement: #not all intermediary devices have ingress and egress interfaces
           egressInterfaceName = networkElement['egressInterface']['physicalInterface']['name']
       else:
           egressInterfaceName = 'UNKNOWN'
           
       if 'ingressInterface' in networkElement:
           ingressInterfaceName = networkElement['ingressInterface']['physicalInterface']['name']
       else:
           ingressInterfaceName = 'UNKNOWN'       
       device = [device_no,name,ip,ingressInterfaceName,egressInterfaceName] #create the list of info to be displayed
    all_devices.append(device) #add this list of info for the device as a new line in this variable
    device_no += 1  #increments the ordinal variable for the device in the list
print ("Current date and time: ")
print(datetime.datetime.now())
print("Looping through all the devices")
Current date and time: 
2018-11-29 16:38:46.758996
Looping through all the devices
In [46]:
print ("Current date and time: ")
print(datetime.datetime.now())
print('Path trace \nSource: ' + path_source + '\nDestination: ' + path_dest) #print the source and destination IPs for the trace
print('List of devices on path:')
print (tabulate(all_devices,headers=['Item','Name','IP','Ingress Int','Egress Int'],tablefmt="rst")) #print the table of devices in the path trace
Current date and time: 
2018-11-29 16:38:49.830385
Path trace 
Source: 10.2.2.2
Destination: 10.1.12.20
List of devices on path:
======  ==============  ==========  ====================  =====================
  Item  Name            IP          Ingress Int           Egress Int
======  ==============  ==========  ====================  =====================
     1  Branch-Router2  10.2.2.2    UNKNOWN               GigabitEthernet0/0
     2  UNKNOWN         UNKNOWN     UNKNOWN               UNKNOWN
     3  CAMPUS-Router1  10.1.2.1    GigabitEthernet0/0/1  GigabitEthernet0/0/0
     4  CAMPUS-Core1    10.1.7.1    GigabitEthernet1/2    GigabitEthernet1/1
     5  CAMPUS-Dist1    10.255.1.5  GigabitEthernet5/7    GigabitEthernet5/5
     6  CAMPUS-Access1  10.1.12.1   GigabitEthernet1/0/1  GigabitEthernet1/0/47
     7  Unnamed Host    10.1.12.20  UNKNOWN               UNKNOWN
======  ==============  ==========  ====================  =====================