Path Trace Guide
Introduction
Path trace is the feature in Catalyst Center that allows you to execute a trace between two devices in your network. It is possible to get device and interface statistics, QoS details and/or ACLs traces and do it using different ports and protocols.
Use it to troubleshoot network problems like packet loss and traffic not reaching its destination due to ACLs or routing issues.
Goal
The goals of this guide are:
- Retrieve a list of previously executed path traces.
- Execute a path trace.
- Obtain the path trace result.
- Delete the path trace.
Endpoints and methods used
- POST
/dna/system/api/v1/auth/token
- GET
/dna/intent/api/v1/network-device
- GET
/dna/intent/api/v1/flow-analysis
- POST
/dna/intent/api/v1/flow-analysis
- GET
/dna/intent/api/v1/flow-analysis/{flowAnalysisId}
- DELETE
/dna/intent/api/v1/flow-analysis/{flowAnalysisId}
Prerequisites
For this guide, we recommend that the developer becomes familiar with authenticating and obtaining the device ID of the target devices.
Environment
This guide was developed using:
Authentication
First, we must authenticate and retrieve a token from the API.
Notes: Do not use
verify=False
orurllib3.disable_warnings()
if you are not sure of its purpose. Read Authentication and Authorization.
import requests
from requests.auth import HTTPBasicAuth
import urllib3
urllib3.disable_warnings()
BASE_URL = 'https://<IP Address>'
AUTH_URL = '/dna/system/api/v1/auth/token'
USERNAME = '<USERNAME>'
PASSWORD = '<PASSWORD>'
response = requests.post(BASE_URL + AUTH_URL, auth=HTTPBasicAuth(USERNAME, PASSWORD), verify=False)
token = response.json()['Token']
headers = {'X-Auth-Token': token, 'Content-Type': 'application/json'}
Get Devices' IPs
With the token, we can proceed to query the devices API using the hostnames of the two devices we want to use for the path trace.
headers = {'X-Auth-Token': token, 'Content-Type': 'application/json'}
DEVICES_URL = '/dna/intent/api/v1/network-device'
src_ip_address = ''
query_string_params = {'hostname': 'CSR1Kv-01.devnet.local'}
response = requests.get(BASE_URL + DEVICES_URL, headers = headers, params=query_string_params, verify=False)
src_ip_address = response.json()['response'][0]['managementIpAddress']
dst_ip_address = ''
query_string_params = {'hostname': 'CSR1Kv-09.devnet.local'}
response = requests.get(BASE_URL + DEVICES_URL, headers = headers, params=query_string_params, verify=False)
dst_ip_address = response.json()['response'][0]['managementIpAddress']
Path Trace API
The Path Trace API consists of four endpoints for creating a path trace, getting the result, deleting it, or getting a summary of all path traces in the system.
This API lets a user execute a path trace between two devices that are known by Catalyst Center. Path trace is asynchronous, so results aren't obtained immediately. Check the async guide for more information.
Generate a new Path trace
With the IPs, we can create a new path trace. Source and destination IPs are mandatory. It is possible to ask for more details using the inclusions
list with one or several of the following options:
- INTERFACE-STATS
- DEVICE-STATS
- ACL-TRACE
- QOS-STATS
The following snippet shows the path trace creation:
PATH_TRACE_URL = '/dna/intent/api/v1/flow-analysis'
path_trace_payload = {
'sourceIP': src_ip_address,
'destIP': dst_ip_address,
'inclusions': [
'INTERFACE-STATS',
'DEVICE-STATS',
'ACL-TRACE',
'QOS-STATS'
],
'protocol': 'icmp'
}
response = requests.post(BASE_URL + PATH_TRACE_URL, headers=headers, json=path_trace_payload, verify=False)
flow_analysis_id = response.json()['response']['flowAnalysisId']
Get path trace result
Query the result of the path trace from the API:
PATH_TRACE_ID_URL = '/dna/intent/api/v1/flow-analysis/{flow_analysis_id}'
response = requests.get(BASE_URL + PATH_TRACE_ID_URL.format(flow_analysis_id=flow_analysis_id), headers=headers, verify=False)
print(response.json['response'])
Get path trace summary
It is also possible to get a summary of all the path traces in the system, filtered by different parameters, for example, destination IP address.
query_string_params = {'destIP': dst_ip_address}
response = requests.get(BASE_URL + PATH_TRACE_URL, params=query_string_params, headers=headers, verify=False)
print(response.json())
Delete path trace
Finally, we can delete our path trace if we want to.
response = requests.delete(BASE_URL + PATH_TRACE_ID_URL.format(flow_analysis_id=flow_analysis_id), headers=headers, verify=False)
Code
The repository for this guide is here.
# Modules import
import requests
from requests.auth import HTTPBasicAuth
import sys
import time
# Disable SSL warnings. Not needed in production environments with valid certificates
import urllib3
urllib3.disable_warnings()
# Authentication
BASE_URL = 'https://<IP Address>'
AUTH_URL = '/dna/system/api/v1/auth/token'
USERNAME = '<USERNAME>'
PASSWORD = '<PASSWORD>'
# URLs
DEVICES_URL = '/dna/intent/api/v1/network-device'
PATH_TRACE_URL = '/dna/intent/api/v1/flow-analysis'
PATH_TRACE_ID_URL = '/dna/intent/api/v1/flow-analysis/{flow_analysis_id}'
def get_dnac_jwt_token():
response = requests.post(BASE_URL + AUTH_URL,
auth=HTTPBasicAuth(USERNAME, PASSWORD),
verify=False)
token = response.json()['Token']
return token
# Get list of devices
def get_devices(headers, query_string_params):
response = requests.get(BASE_URL + DEVICES_URL,
headers = headers,
params = query_string_params,
verify=False)
return response.json()['response']
# Create path trace
def create_path_trace(headers, path_trace_payload):
response = requests.post(BASE_URL + PATH_TRACE_URL, headers=headers,
json=path_trace_payload, verify=False)
return response.json()['response']
# Get path trace result
def get_path_trace_by_id(headers, flow_analysis_id):
response = requests.get(BASE_URL + PATH_TRACE_ID_URL.format(flow_analysis_id=flow_analysis_id),
headers=headers, verify=False)
return response.json()['response']
# Get path trace summary
def get_path_traces_summary(headers, query_string_params):
response = requests.get(BASE_URL + PATH_TRACE_URL,
params=query_string_params,
headers=headers, verify=False)
return response.json()['response']
# Delete path trace
def delete_path_trace(headers, flow_analysis_id):
response = requests.delete(BASE_URL + PATH_TRACE_ID_URL.format(flow_analysis_id=flow_analysis_id),
headers=headers, verify=False)
return response
def main():
# obtain the Catalyst Center Auth Token
token = get_dnac_jwt_token()
headers = {'X-Auth-Token': token, 'Content-Type': 'application/json'}
# Get src device IP
print('Printing source device IP ...')
query_string_params = {'hostname': 'CSR1Kv-01.devnet.local'}
response = get_devices(headers, query_string_params)
src_ip_address = response[0]['managementIpAddress']
print(src_ip_address)
# print devices list
print('\nPrinting destination device IP ...')
query_string_params = {'hostname': 'CSR1Kv-09.devnet.local'}
response = get_devices(headers, query_string_params)
dst_ip_address = response[0]['managementIpAddress']
print(dst_ip_address)
# Generate a new path trace
print('\nPrinting flow analysis id ...')
path_trace_payload = {
'sourceIP': src_ip_address,
'destIP': dst_ip_address,
'inclusions': [
'INTERFACE-STATS',
'DEVICE-STATS',
'ACL-TRACE',
'QOS-STATS'
],
'protocol': 'icmp'
}
response = create_path_trace(headers, path_trace_payload)
flow_analysis_id = response['flowAnalysisId']
print(flow_analysis_id)
# Waiting until the path trace is done
time.sleep(10)
# Get path trace result
print('\nPrinting path trace result ...')
response = get_path_trace_by_id(headers, flow_analysis_id)
print(response)
# Get path traces summary
print('\nPrinting path trace summary...')
query_string_params = {'destIP': dst_ip_address, 'limit': 2}
response = get_path_traces_summary(headers, query_string_params)
print(response)
# Delete path trace summary
print('\nPrinting path trace delete status code ...')
response = delete_path_trace(headers, flow_analysis_id)
print(response.status_code)
if __name__ == "__main__":
main()