Topology Guide
Introduction
Cisco DNA Center has a Topology Intent API that enables the developer to get an overall look of the physical (Layer 2), logical (layer 3) and site topology.
Goal
The goals of this guide are:
- Get the site topology
- Get the physical topology
- Get the logical topology
Endpoints and methods used
- POST
/dna/system/api/v1/auth/token
- GET
/dna/intent/api/v1/topology/site-topology
- GET
/dna/intent/api/v1/topology/physical-topology
- GET
/dna/intent/api/v1/topology/l2/{vlan_id}
Prerequisites
For this module, it is recommended that the user already has experience authenticating with Cisco DNA Center:
Environment
This guide was developed using:
Authentication
First, we need to authenticate and retrieve a token from the API.
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']
Topology API
The topology API allows the user to obtain information about the site topology, the physical topology of a site, the layer 2 and layer 3 topologies of a network.
Site Topology
Site Topology returns information about the sites in Cisco DNA Center and their hierarchy related to the Global site.
SITE_TOPOLOGY_URL = '/dna/intent/api/v1/topology/site-topology'
response = requests.get(BASE_URL + SITE_TOPOLOGY_URL,
headers=headers, verify=False)
response = response.json()['response']
for site in response['sites']:
print(site['name'], '-->' ,site['groupNameHierarchy'])
Physical Topology
The physical topology returns a raw topology of a site, with information about nodes and connecting links between those nodes.
Links shown are not two way, meaning that a link between two nodes will be shown just once.
PHYSICAL_TOPOLOGY_URL = '/dna/intent/api/v1/topology/physical-topology'
response = requests.get(BASE_URL + PHYSICAL_TOPOLOGY_URL,
headers=headers, verify=False)
data = response.json()['response']
nodes = {}
for node in data['nodes']:
nodes[node['id']] = node['label']
for link in data['links']:
print('Source: {0}({1}) Target: {2}({3}) Status: {4}'.format(
nodes[link['source']], link.get('startPortName', ''),
nodes[link['target']], link.get('endPortName', ''),
link['linkStatus']
))
Layer 2 / VLAN Topology
Returns Layer 2 network topology by specified VLAN ID.
L2_TOPOLOGY_URL = '/dna/intent/api/v1/topology/l2/{vlan_id}'
response = requests.get(BASE_URL + L2_TOPOLOGY_URL.format(vlan_id=vlan_id),
headers=headers, verify=False)
data = response.json()['response']
nodes = {}
for node in data['nodes']:
nodes[node['id']] = node['label']
for link in data['links']:
print('Source: {0}({1}) Target: {2}({3}) Status: {4}'.format(
nodes[link['source']], link.get('startPortName', ''),
nodes[link['target']], link.get('endPortName', ''),
link['linkStatus']
))
Code
The repository for this guide is here. The final code with functions is shown below.
# Modules import
import requests
from requests.auth import HTTPBasicAuth
# 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'
SITE_TOPOLOGY_URL = '/dna/intent/api/v1/topology/site-topology'
PHYSICAL_TOPOLOGY_URL = '/dna/intent/api/v1/topology/physical-topology'
L2_TOPOLOGY_URL = '/dna/intent/api/v1/topology/l2/{vlan_id}'
# Get nodes/links
def get_nodes_links(data):
nodes = {}
for node in data['nodes']:
nodes[node['id']] = node['label']
for link in data['links']:
print('Source: {0}({1}) Target: {2}({3}) Status: {4}'.format(
nodes[link['source']], link.get('startPortName', ''),
nodes[link['target']], link.get('endPortName', ''),
link['linkStatus']
))
# Get Authentication token
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 site topology
def get_site_topology(headers):
response = requests.get(BASE_URL + SITE_TOPOLOGY_URL,
headers=headers, verify=False)
return response.json()['response']
# Get physical topology
def get_physical_topology(headers):
response = requests.get(BASE_URL + PHYSICAL_TOPOLOGY_URL,
headers=headers, verify=False)
return response.json()['response']
# Get L2 topology
def get_l2_topology(headers, vlan_id):
response = requests.get(BASE_URL + L2_TOPOLOGY_URL.format(vlan_id=vlan_id),
headers=headers, verify=False)
return response.json()['response']
def main():
# obtain the Cisco DNA Center Auth Token
token = get_dnac_jwt_token()
headers = {'X-Auth-Token': token, 'Content-Type': 'application/json'}
print('Printing site topology...')
response = get_site_topology(headers)
for site in response['sites']:
print(site['name'], '-->' ,site['groupNameHierarchy'])
print('\nPrinting physical topology...')
response = get_physical_topology(headers)
get_nodes_links(response)
print('\nPrinting L2 topology...')
response = get_l2_topology(headers, 3001)
get_nodes_links(response)
if __name__ == "__main__":
main()