Cisco Catalyst Center API Client Code Examples¶
This guide shows how to use the
CiscoCatalystCenter client to interact with Cisco Catalyst Center APIs.
The wingpy Catalyst Center client is designed for seamless interaction with Cisco DNA Center's intent REST API. E.g. advanced device management, credential operations, and task polling.
Wingpy handles authentication, token refresh, logging, concurrency and error management for you.
- The client raises
UnsupportedMethodErrorfor unsupported HTTP methods (e.g., PATCH). - You can call
catalyst.authenticate()to force (re-)authentication.
The Basics - Connect and Get Devices¶
Environment Variables
You can set the environment variables in your shell to avoid hardcoding sensitive information in your code. Check out the FAQ section on Environment Variables for more details.
from wingpy import CiscoCatalystCenter
catalyst = CiscoCatalystCenter(
base_url="https://catalyst.example.com", # (1)!
username="...", # (2)!
password="...", # (3)!
verify=False,
)
-
Environment variable:
-
Environment variable:
-
Environment variable:
# list[dict]
devices = catalyst.get_all("/dna/intent/api/v1/network-device/")
for device in devices:
print(device["id"], device["hostname"])
device_id = "<your-device-id>"
# httpx.Response
response = catalyst.get(f"/dna/intent/api/v1/network-device/{device_id}")
print(response.json())
SNMP Credential Management Examples¶
As you may or may not know, the Catalyst Center REST API supports managing SNMP credentials.
With these examples we assume that you have set the environment variables for authentication as shown above.
When you create, delete or update SNMP credentials, Catalyst Center uses asynchronous tasks. This is true for many operations. That means you need to wait and poll for task completion, if you want to ensure the operation has completed successfully.
As Catalyst Center uses IDs internally, we will also need to get the credential ID based on the description.
To solve both, we will define some simple helper functions to make our code cleaner and easier to read.
Helper functions¶
Here's a poller for the purpose of waiting for task completion:
import time
import wingpy
def poll_task(catalyst: wingpy.CiscoCatalystCenter, task_id):
while True:
status = catalyst.get(f"/dna/intent/api/v1/tasks/{task_id}")
if status.json()["response"].get("isError") or status.json()["response"].get("endTime"):
break
time.sleep(2)
return status.json()["response"]["status"]
Often, you will need to translate a name to the corresponding internal ID used by the API. So, let's define a little helper function to get that ID based on the description of the credential:
def get_credential_id(credentials, description):
try:
return [cred["id"] for cred in credentials if cred["description"] == description][0]
except IndexError:
raise ValueError(f"Credential with description '{description}' not found")
With these simple helpers in place, you can now create, update, and delete SNMP credentials as shown below.
Create, Update, and Delete SNMP Credentials¶
When creating SNMP credentials, a task is created that you need to poll for completion.
We usually prefer to use the context manager (the with statement) to ensure proper cleanup of resources.
snmp = {
"description": "Example SNMP",
"readCommunity": "public",
}
# context manager
with wingpy.CiscoCatalystCenter(verify=False) as catalyst:
rsp = catalyst.post(
"/dna/intent/api/v2/global-credential",
data={"snmpV2cRead": [snmp]},
)
task_id = rsp.json()["response"]["taskId"]
# poll for task completion using the helper function
status = poll_task(catalyst, task_id)
print(f"Task completed with status:\n {status}")
To update existing credentials, we first need to get the credential ID based on the description. Then we can issue the update request.
# context manager
with wingpy.CiscoCatalystCenter(verify=False) as catalyst:
response = catalyst.get("/dna/intent/api/v2/global-credential").json()["response"]
snmpv2c_read_credentials = response["snmpV2cRead"]
# get the SNMPv2c-read credential ID based on description
snmp_description = "Example SNMP Description"
snmp_id = get_credential_id(credentials=snmpv2c_read_credentials, description=snmp_description)
# define the update payload
update = {
"instanceUuid": snmp_id,
"description": "Example SNMP",
"readCommunity": "public_updated",
}
with wingpy.CiscoCatalystCenter(verify=False) as catalyst:
rsp = catalyst.put(
"/dna/intent/api/v1/global-credential/snmpv2-read-community",
data=update,
)
task_id = rsp.json()["response"]["taskId"]
# poll for task completion using the helper function
status = poll_task(catalyst, task_id)
print(f"Task completed with status:\n {status}")
credential_path = "/dna/intent/api/v2/global-credential"
snmp_description = "Example SNMP"
with wingpy.CiscoCatalystCenter(verify=False) as catalyst:
snmp_read = catalyst.get(credential_path).json()["response"]["snmpV2cRead"]
snmp_id = get_credential_id(snmp_read, snmp_description)
rsp = catalyst.delete(f"{credential_path}/{snmp_id}")
print(rsp.status_code)
If the delete operation is successful, you should see a 202 status code printed.
HTTP status code 202 indicates that the request has been accepted for processing, but the processing has not been completed yet.
Again, you may want to poll for task completion if needed, but for delete operations it's often sufficient to just check the status code,
unless you specifically need to confirm the deletion - e.g. in case you want to re-create a credential with the same description or name
right after deletion.
Full Example Script¶
import time
import wingpy
def poll_task(catalyst: wingpy.CiscoCatalystCenter, task_id):
while True:
status = catalyst.get(f"/dna/intent/api/v1/tasks/{task_id}")
if status.json()["response"].get("isError") or status.json()["response"].get("endTime"):
break
time.sleep(2)
return status.json()["response"]["status"]
def get_credential_id(credentials, description):
try:
return [cred["id"] for cred in credentials if cred["description"] == description][0]
except IndexError:
raise ValueError(f"Credential with description '{description}' not found")
snmp = {
"description": "Example SNMP",
"readCommunity": "public",
}
with wingpy.CiscoCatalystCenter(verify=False) as catalyst:
# Create SNMP Credential
rsp = catalyst.post(
"/dna/intent/api/v2/global-credential",
data={"snmpV2cRead": [snmp]},
)
task_id = rsp.json()["response"]["taskId"]
status = poll_task(catalyst, task_id)
print(f"Create Task completed with status:\n {status}")
# Update SNMP Credential
snmpv2c_read = catalyst.get("/dna/intent/api/v2/global-credential").json()["response"]["snmpV2cRead"]
snmp_id = get_credential_id(credentials=snmpv2c_read, description=snmp["description"])
update = {
"instanceUuid": snmp_id,
"description": "Example SNMP",
"readCommunity": "public_updated",
}
rsp = catalyst.put(
"/dna/intent/api/v1/global-credential/snmpv2-read-community",
data=update,
)
task_id = rsp.json()["response"]["taskId"]
status = poll_task(catalyst, task_id)
print(f"Update Task completed with status:\n {status}")
# Delete SNMP Credential
rsp = catalyst.delete(f"/dna/intent/api/v2/global-credential/{snmp_id}")
print(f"Delete response status code: {rsp.status_code}")