Python 3.x
Just like any API or tool, your first stop is to check out the documentation:
pip install dnacentersdk
By default, DNA Center SDK will look for the following environment variables to create new connection objects:
In our case, we will not use environment variables. We will add it to part of our Python code.
1: Clone the code repo.
In your terminal, run:
git clone https://github.com/CiscoLearning/dnac-config-manager.git
Kick-start Python in interactive mode:
python3
2: Import the DNA Center SDK.
from dnacentersdk import DNACenterAPI
3: Define the connection string.
In this case, we will create a Python dictionary with the connection string:
dnac_creds = {}
dnac_creds['url'] = 'https://sandboxdnac.cisco.com'
dnac_creds['username'] = 'devnetuser'
dnac_creds['password'] = 'Cisco123!'
4: Instantiate “Connection Object.”
dnac = DNACenterAPI(username=dnac_creds['username'], password=dnac_creds['password'], base_url=dnac_creds['url'], verify=False)
5: Display your Auth Token.
print("Auth Token: ", dnac.access_token)
6: Let’s look at the completed script.
Head over to the working directory from our cloned repo and run the Authentication.py
file:
cd dnac-config-manager/
ls -al
7: Run it.
python Authentication.py
Now that we have an understanding on how the DNA Center SDK works and we’ve authenticated, let’s build our use case!
I’d like to be able to take a snapshot of all of the device config to detect configuration drift and have a golden image.
Command Runner is a feature in Cisco DNA Center that allows you to execute a handful of read-only (for now) Cisco IOS commands on the devices managed by DNA Center.
Here is how you can get a list of all supported Cisco IOS commands:
commands = dnac.command_runner.get_all_keywords_of_clis_accepted()
⚠️ Cisco DNA Center API calls are asynchronous, which means that for each executed task, a task ID is created. Upon task completion, content can be retrieved from the /file endpoint.
API endpoints that we are planning on using:
SDK methods that we are planning on using:
0: Using your IDE of choice, create a new ‘.py’ file and import libraries.
Click the + sign next to the cloned folder ciscolive-devwks-2107:
from dnacentersdk import DNACenterAPI
import json
import warnings
1: Authenticate.
By now, we know how to do this. We need to pass Basic Auth and capture our API token.
Copy this step to the editor last; this needs to be at the end of the file.
if __name__ == '__main__':
dnac_creds = {}
dnac_creds['url'] = 'https://sandboxdnac.cisco.com'
dnac_creds['username'] = 'devnetuser'
dnac_creds['password'] = 'Cisco123!'
dnac = DNACenterAPI(username=dnac_creds['username'], password=dnac_creds['password'], base_url=dnac_creds['url'],
verify=False)
print("Auth Token: ", dnac.access_token)
print("Gathering Device Info ... \n")
get_device_list()
2: Retrieve a list of devices.
get_device_list()
method to retrieve a list of all managed devices.Switches and Hubs
and extract the device ID. We need to leverage it to programmatically run the command on each device.device.id
and pass it to and call the cmd_run()
function (we will build next).Notice anything?
"""
This function handles getting device list
"""
def get_device_list():
devices = dnac.devices.get_device_list()
devicesuid_list = []
for device in devices.response:
if device.family == 'Switches and Hubs':
print("Managed Device IP: {} ".format(device.managementIpAddress))
devicesuid_list.append(device.id)
print("\n")
cmd_run(devicesuid_list)
3: Initiate Command Runner.
show run
command. To do so, use the command_runner
class and call read run_read_only_commands_on_devices()
method. This method requires two inputs of type list: commands
and deviceUuids
.taskId
(asynchronous, remember?).task
class by calling the get_task_by_id()
method. Once the task has been successfully executed (you can use the built-in error handling within the SDK to check, but that’s for another blog post), grab the returned fileId
.file
class and call the download_a_file_by_fileid()
method … and VOILA!
"""
This function handles command runner execution
"""
def cmd_run(device_list):
for device in device_list:
print("Executing Command on {}".format(device))
run_cmd = dnac.command_runner.run_read_only_commands_on_devices(commands=["show run"], deviceUuids=[device])
print("Task started! Task ID is {}".format(run_cmd.response.taskId))
task_info = dnac.task.get_task_by_id(run_cmd.response.taskId)
task_progress = task_info.response.progress
print("Task Status : {}".format(task_progress))
while task_progress == 'CLI Runner request creation':
task_progress = dnac.task.get_task_by_id(run_cmd.response.taskId).response.progress
task_progress= json.loads(task_progress)
cmd_output = dnac.file.download_a_file_by_fileid(task_progress['fileId'], dirpath='file.json', save_file=True)
print("Saving config for device ... \n")
Congratulations! You’ve successfully completed this tutorial!
This is a great example of configuration management. You could use this as a base to start building out a simple configuration drift monitoring tool, given that the config is returned as JSON data. We can easily use a JSON query to check for any configuration drift and automatically rebase it to the original config.
This can be taken a step further even by leveraging Git for version control of your device config.