09-22-2021 03:06 PM - edited 09-28-2021 02:10 AM
Hi guys,
I started playing with the DNAC API and the command runner but I ran into a problem where I want to run ten or more show commands inside the payload. Up to four show commands works fine, but more than that comes back with failure to obtain taskId. I am using Python for the scripting language and the DNAC is the online sandbox provided by Cisco.
I tried scripting this job based on the documentation located here: https://developer.cisco.com/docs/dna-center/#!cisco-dna-center-platform-overview. I also tried other sources and ready-made scripts which I found online and problem is the same.
Is this the limitation of the freely available DNAC sandbox, the DNAC API bug or what is it?
Any guidance in this matter will be greatly appreciated!
Solved! Go to Solution.
09-23-2021 02:54 PM
I think I found the answer to my question.
I tried to:
print(commandrunner['response'])
and the message was as follows:
{'errorCode': 'Bad request', 'message': 'Invalid input request', 'detail': 'Maximum of 5 commands allowed per request'}
So, I guess it is the limitation of the API to a maximum of 5 commands allowed per request.
I will test this further by dividing my requests into chunks of 5 commands at a time.
09-22-2021 03:47 PM
When running tests using the API and you experience issues:
This will help the viewing audience to assess the issue and provide feedback.
09-23-2021 02:43 PM
Hi Tomas,
Here goes:
I am using Python for this and the DNAC is the "https://sandboxdnac.cisco.com" (Version 2.2.2.3).
List of devices and their versions is in the attached image, although the WLC seems to be ignored by the command runner.
Script is below:
....Start of script:.....
import requests
from requests.auth import HTTPBasicAuth
import json
import csv
import pandas as pd
import getpass
import time
import urllib3
urllib3.disable_warnings()
'''
DNA Details
'''
print("Enter DNAC Credentials to login:")
DNAC_URL = "https://sandboxdnac.cisco.com"
DNAC_AUTH_URL = '/dna/system/api/v1/auth/token'
DNAC_PORT = 443
DNAC_USER = "devnetuser"
DNAC_PASSWORD = "Cisco123!"
'''
Login
'''
login = requests.post(DNAC_URL + DNAC_AUTH_URL, auth=HTTPBasicAuth(DNAC_USER, DNAC_PASSWORD), verify=False)
token = login.json()['Token']
headers = {'X-Auth-Token': token, 'Content-Type': 'application/json'}
'''
URLs
'''
DEVICES_URL = '/dna/intent/api/v1/network-device'
COMMAND_RUNNER_SEND_URL = '/dna/intent/api/v1/network-device-poller/cli/read-request'
TASK_BY_ID_URL = '/dna/intent/api/v1/task/{task_id}'
FILE_GET_BY_ID = '/dna/intent/api/v1/file/{file_id}'
'''
GETs
'''
get_devices = requests.get(DNAC_URL + DEVICES_URL, headers = headers, verify=False)
get_devices_json = get_devices.json()['response']
devices = []
for device in get_devices.json()['response']:
devices.append(device['id'])
payload = {
"commands": [
"show running-config",
"show ip arp",
"show mac address-table",
"show ip route",
"show interface",
"show ip interface",
"show inventory",
"show version",
"show cdp neighbors detail",
"show cdp neighbors",
"show lldp neighbors",
"show lldp neighbors detail"
],
"deviceUuids": devices,
"timeout": 0
}
commandrunner = requests.post(DNAC_URL + COMMAND_RUNNER_SEND_URL, data=json.dumps(payload), headers=headers, verify=False).json()
time.sleep(10)
task_id = commandrunner['response']['taskId']
get_file_id = requests.get(DNAC_URL + TASK_BY_ID_URL.format(task_id=task_id), headers=headers, verify=False)
progress_json = json.loads(get_file_id.json()['response']['progress'])
file_id = progress_json['fileId']
get_file = requests.get(DNAC_URL + FILE_GET_BY_ID.format(file_id=file_id), headers=headers, verify=False)
file_json = get_file.json()
for item in get_devices_json:
deviceid = item['id']
devicehostname = item['hostname']
for item in file_json:
device = item['deviceUuid']
commandresponse = item['commandResponses']
successfullcommands = commandresponse['SUCCESS']
show_running_config = successfullcommands['show running-config']
show_ip_arp = successfullcommands['show ip arp']
show_mac_address_table = successfullcommands['show mac address-table']
show_ip_route_vrf_xD = successfullcommands['show ip route']
show_interface = successfullcommands['show interface']
show_ip_interface = successfullcommands['show ip interface']
show_inventory = successfullcommands['show inventory']
show_version = successfullcommands['show version']
show_cdp_neighbors_detail = successfullcommands['show cdp neighbors detail']
show_cdp_neighbors = successfullcommands['show cdp neighbors']
show_lldp_neighbors = successfullcommands['show lldp neighbors']
show_lldp_neighbors_detail = successfullcommands['show lldp neighbors detail']
with open(device + "show running-config.txt", 'w') as f:
f.write(show_running_config)
with open(device + "show ip arp.txt", 'w') as f:
f.write(show_ip_arp)
with open(device + "show mac address-table.txt", 'w') as f:
f.write(show_mac_address_table)
with open(device + "show ip route xD.txt", 'w') as f:
f.write(show_ip_route_vrf_xD)
with open(device + "show interface.txt", 'w') as f:
f.write(show_interface)
with open(device + "show ip interface.txt", 'w') as f:
f.write(show_ip_interface)
with open(device + "show inventory.txt", 'w') as f:
f.write(show_inventory)
with open(device + "show version.txt", 'w') as f:
f.write(show_version)
with open(device + "show cdp neighbors detail.txt", 'w') as f:
f.write(show_cdp_neighbors_detail)
with open(device + "show cdp neighbors.txt", 'w') as f:
f.write(show_cdp_neighbors)
with open(device + "show lldp neighbors.txt", 'w') as f:
f.write(show_lldp_neighbors)
with open(device + "show lldp neighbors detail.txt", 'w') as f:
f.write(show_lldp_neighbors_detail)
When running this script, the message I am getting is :
Traceback (most recent call last):
File "C:\temp\DNA\test4.py", line 70, in <module>
task_id = commandrunner['response']['taskId']
KeyError: 'response'
I get the same message each time I run the script with more than four show commands inside the payload. If cut the payload down to only four show commands, everything works fine.
09-23-2021 02:54 PM
I think I found the answer to my question.
I tried to:
print(commandrunner['response'])
and the message was as follows:
{'errorCode': 'Bad request', 'message': 'Invalid input request', 'detail': 'Maximum of 5 commands allowed per request'}
So, I guess it is the limitation of the API to a maximum of 5 commands allowed per request.
I will test this further by dividing my requests into chunks of 5 commands at a time.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide