Dnac Python
Dnac Python
Rahul Verma
Mohit Sahai
DEVWKS-2725
Cisco Webex Teams
Questions?
Use Cisco Webex Teams to chat
with the speaker after the session
How
1 Find this session in the Cisco Events Mobile App
2 Click “Join the Discussion”
3 Install Webex Teams or go directly to the team space
4 Enter messages/questions in the team space
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 3
What’s in it for me?
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 4
Agenda
• Why DNAC?
• Getting starting with Cisco DNA Center
• What is API and REST Method
• Cisco DNAC API
• DNAC automation using Python
• Hands-on with Lab guide
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 5
Why existing tools Not Work
Traditional Management tools Digital Network Ready Management
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 7
Getting started with DNA Centre
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 8
Getting started with DNA Centre
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 9
Getting started with DNA Centre
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 10
Getting started with DNA Centre
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 11
Why Automation with DNAC
• Python is widely accepted language for automation.
• It can be used to schedule multiple tasks through scripts which have
interdependency.
• Efficient automated network testing.
• Automated analysis of the data extracted from DNAC through scripts.
• Automated troubleshooting based of the data fetched from DNA through scripts.
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 12
Introduction to APIs
An Application Programming Interface (API) is a way for two pieces of
software to talk to each other.
Mobile Device
Web Site
Web Portal
B2B Partners
Cloud App
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 13
REST APIs
REST works around the HTTP request and response model.
R1R1
HTTP GET HTTP GET R1
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 14
DNA APIs
• HTTPS verbs GET, POST, PUT, and Cisco DNA Center Platform
DELETE.(intent APIs)
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 15
Lab Topology
Switch
Fusion
Router
Border Border
Access Access
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 16
Pre-requisite
To connect to your workstation, perform the following
tasks:
Log onto Cisco Lab Environment using Cisco
Anyconnect “cxlabs.dmz-01.cisco.com” with below
credentials
Username: cxlabs
Password: cxlabs
• Username: admin
• Password: C!sc0123
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 17
Pre-requisite
cd Desktop/
git clone https://github.com/rahul02999/Python_dna.git
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 18
Pre-requisite
• “dnac_config.py” contains DNAC details. • “dnac_code.py” has the DNAC REST API
calls
• This file will be used by “dnac_code.py”.
• Performs the functions of authentication,
sites, devices and networks.
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 19
Importing Modules in Python
• “requests” module is used to provide the HTTP functions- GET, POST, PUT and
DELETE.
• “PrettyTable” is used to print the output in the tabular form.
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 20
DNAC automation using Python
Step 1
Step 2
Step 3
Step 4
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 21
Authentication
Code
Burl= “https://192.168.113.100/{}”
• Obtains security token to
authenticated REST caller. def get_auth_token():
global token
url = Burl.format("dna/system/api/v1/auth/token")
resp = requests.post(url, auth=HTTPBasicAuth(DNAC_USER,
• Token is attached to all the API DNAC_PASSWORD),verify=False)
requests. token = resp.json()['Token’] # Retrieve the Token from the returned JSON
print("Token Retrieved: {}".format(token)) # Print out the Token
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 22
Devices
get_network_device Code
• Fetch the network device using the
def get_network_device():
url = Burl.format("dna/intent/api/v1/network-device")
GET operation.
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
resp = requests.get(url, headers=hdr,verify=False)
network_device = resp.json()
get_network_device()
Output Preview
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 23
Devices Code
def device_create(ip_add,username,password):
print("\n\n\n\ncreating the device:")
payload = {
device_create "cliTransport": "ssh","enablePassword": "yes",
"ipAddress": [ip_add],"password": password,
"snmpAuthPassphrase": "cisco123","snmpAuthProtocol": "sha",
10.10.10.10
"snmpRWCommunity": "cisco123","snmpRetry": "3",
"snmpTimeout": "5","snmpUserName": "admin",
"snmpVersion": "v2", "type": "NETWORK_DEVICE",
"userName": username
}
• Credentials and snmp details are url = Burl.format("dna/intent/api/v1/network-device")
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
provided in the dictionary “payload”. time.sleep(5)
try:
response = requests.post(url, headers=hdr, data=json.dumps(payload),
verify=False)
• To add the device POST api call is time.sleep(10)
except requests.exceptions.RequestException as cerror:
device_create("10.10.10.10","cisco","cisco")
Output Preview
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 24
Devices Code
def device_update_detail(device_ip,role):
print("\n\n\n\nupdating device role:")
get_network_device()
device_update_detail url = Burl.format("dna/intent/api/v1/network-device")
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
resp = requests.get(url, headers=hdr, verify=False)
• update the device role to “Access” network_device = resp.json()
for key in network_device['response']:
using the PUT api call. if key['managementIpAddress']==device_ip:
device_id=key['id']
payload = {
"id": device_id,
"role": role,
"roleSource": "MANUAL"
}
url = Burl.format("dna/intent/api/v1/network-device/brief")
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
time.sleep(5)
try:
response = requests.put(url, headers=hdr, data=json.dumps(payload),
verify=False)
time.sleep(10)
except requests.exceptions.RequestException as cerror:
print("Error processing request", cerror)
sys.exit(1)
print("\nDevice role updated successfully-",response.json()['response'])
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 25
Get Site health Code
def get_site_health():
url = Burl.format("dna/intent/api/v1/site-health?timestamp=") +
str(time.time()*1000)
get_site_health hdr = {'x-auth-token': token, 'content-type': 'application/json'}
resp = requests.get(url, headers=hdr,verify=False) # Make the Get Request
site_health = resp.json()
• Get the site details like location site dnac_devices = PrettyTable(["siteName", "siteId", "parentSiteName", "siteType",
type and the percentage of healthy "latitude", "longitude","healthy Network Device Percentage", "healthy Clients
Percentage","number Of Network Device"])
devices dnac_devices.padding_width = 1 # to put width after each entry
print('\n\n','Site-Health\n', dnac_devices)
get_site_health()
Output Preview
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 26
Create a New Site Code
def create_site(filename):
print("\n\nCreating Area in DNA:")
• This code would create a site on the print("\ncreating the area having name- {} and parent name-
DNAC appliance
{}".format(key['name'],key['parentName']))
response = create_area_request(key['name'],key['parentName'])
print(response)
print("\nArea Creation is completed\n\n")
print("\nCreating Building in Area in DNA:")
for key in data['building']:
print("\ncreating the building having area name- {}, area parent name- {},
building name- {}, building address- {} with latitude- {} and longitude-
{}".format(key["area_name"], key["area_parentName"], key["bld_name"],
{ key["bld_address"], key["lat"], key["long"]))
"area": [
{ response = create_building_request(key["area_name"], key["area_parentName"],
"name": "US-East", key["bld_name"],key["bld_address"])
"parentName": "Global"
} print(json.dumps(response))
], print("\nBuilding Creation is completed","\noverall site creation is
"building": [ completed\n\n")
{ time.sleep(30)
"area_name": "Area1", print("\nVerfying the Area Sites:")
"area_parentName": "US-East", for key in data['area']:
"bld_name": "Area1-BLD1",
"bld_address": "170 West Tasman Drive, San Jose 95134" print("\nVerifying the site is created and getting the site health of area-
} {}".format(key['name']))
] #Getting the site health after creating it.
} time.sleep(10)
get_specific_site_health(key["name"])
create_site("site-info.txt")
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 27
Create a New Site cont.. Code
def create_area_request(name,parentname):
DNAC appliance
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
try:
response = requests.post(url, headers=hdr, data=json.dumps(payload),
verify=False)
time.sleep(20)
except requests.exceptions.RequestException as cerror:
print("Error processing request", cerror)
sys.exit(1)
return response.json()
def create_building_request(area_name,area_parent,bld_name,area_add,lati,longi):
payload = {"type": "building",
"site": {
"area": {
"name": area_name,"parentName": area_parent},
"building": {
"name": bld_name,
"address": area_add}
}
}
url = Burl.format("dna/system/api/v1/site")
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
time.sleep(5)
try:
response = requests.post(url, headers=hdr, data=json.dumps(payload),
verify=False)
time.sleep(10)
except requests.exceptions.RequestException as cerror:
print("Error processing request", cerror)
sys.exit(1)
return response.json()
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 28
Code
Assigning Device to a Site #this below function is based on ip so passing directly the ip from the device-to-
site_2.txt
def assign_device_to_site(filename):
assign_device_to_site site_id={}
time.sleep(30)
• Assign devices to the newly created url = Burl.format("dna/intent/api/v1/site-health?timestamp=") + str(time.time() *
1000)
sites. hdr = {'x-auth-token': token, 'content-type': 'application/json'}
resp = requests.get(url, headers=hdr, verify=False) # Make the Get Request
site_health = resp.json()
def add_device_to_site(site_id, ip_add): for i in site_health['response']:
payload = {"device": [{"ip": ip_add}]} site_id[i['siteName']] = i['siteId']
url = Burl.format("dna/intent/api/v1/site/")+site_id + "/device"
hdr = {'x-auth-token': token, 'content-type': 'application/json'} print("\nAssigning device to the newly created site:")
try: with open(filename, "r") as f:
response = requests.post(url, headers=hdr, data=json.dumps(payload), data = json.load(f)
verify=False) for key in data['device']:
except requests.exceptions.RequestException as cerror:
print("Error processing request", cerror) print("\nAssigning the device with ip address- {} to the site-
sys.exit(1) {}".format(key['ipadd'], key['siteName']))
return response.json()
response = add_device_to_site(site_id[key["siteName"]], key['ipadd'])
print(response) # json.dumps(response)
{ time.sleep(10)
"device": [ print("\n\nAdding Devices to Site is complete !!\n\n")
{ time.sleep(10)
"ipadd": "10.10.10.10", print("\nVerfying the Area Sites:")
"siteName": "Area1-BLD1" get_network_device()
}
]
} assign_device_to_site("device-to-site_2.txt”)
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 29
Devices Code
def device_delete(device_ip):
print("\n\n\n\nDeleting the device:")
get_network_device()
device_delete url = Burl.format("dna/intent/api/v1/network-device")
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
resp = requests.get(url, headers=hdr, verify=False)
• delete the previously added device network_device = resp.json()
for key in network_device['response']:
with the ip address “10.10.10.10”. if key['managementIpAddress']==device_ip:
device_id = key['id']
url = Burl.format("dna/intent/api/v1/network-device/")+device_id
hdr = {'x-auth-token': token, 'content-type': 'application/json'}
time.sleep(5)
try:
response = requests.delete(url, headers=hdr, verify=False)
time.sleep(10)
except requests.exceptions.RequestException as cerror:
print("Error processing request", cerror)
sys.exit(1)
print("\nDevice deleted successfully-", response.json()['response’])
device_delete("10.10.10.10")
Output Preview
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 30
References
• https://www.cisco.com/c/en/us/support/cloud-systems-management/dna-
center/video-resources.html
• https://www.cisco.com/c/en/us/solutions/collateral/enterprise-networks/cisco-
digital-network-architecture/nb-06-cisco-dna-soln-ovw-cte-en.html
• https://developer.cisco.com/docs/dna-center/
• https://<your DNAC ip>/dna/platform/app/consumer-portal?module-view=apis
• To practice “Cisco DNA Center Lab” - https://devnetsandbox.cisco.com/
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 31
Continue your education
Demos in the
Walk-In Labs
Cisco Showcase
DEVWKS-2725
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 32
Complete your
online session
survey • Please complete your session survey
after each session. Your feedback
is very important.
• Complete a minimum of 4 session
surveys and the Overall Conference
survey (starting on Thursday) to
receive your Cisco Live t-shirt.
• All surveys can be taken in the Cisco Events
Mobile App or by logging in to the Content
Catalog on ciscolive.com/emea.
DEVWKS-2725 © 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public 33
Thank you