Hello! Welcome to the next lesson in our journey through Network Automation and Programmability.
In our last session, we focused on deconstructing and interpreting the JSON data that network devices return from REST API calls. We learned how to navigate the nested objects and arrays to find specific information, a crucial skill for any automation task.
Today, we'll build directly on that foundation. Our learning outcome is to interpret a basic Python script that uses a REST API to retrieve or configure network device state. We'll bridge the gap between understanding the data format (JSON) and understanding the tool that interacts with it (Python). You'll learn to look at a Python script and determine its purpose: Is it reading device information, or is it making configuration changes?
Given your familiarity with APIs, we'll focus on how Python implements these interactions, specifically using the popular requests library. We'll examine practical scripts that interact with Cisco IOS XE and DNA Center, which are directly relevant to your CCNP ENCOR preparation.
The Anatomy of a Python Network Automation Script
Python has become the language of choice for network automation due to its simple syntax and a vast ecosystem of libraries. For interacting with REST APIs, the most important library is requests. It simplifies the process of making HTTP requests, allowing you to focus on the task rather than the low-level complexities of network connections.
A typical Python script for network automation follows a standard structure. To see this in action, let's look at an article that explains how to use requests with various APIs, including Cisco's.
Using the Python Requests Module to Work with REST APIs
This article from Network to Code provides an excellent overview of the Python requests library. It covers the fundamentals we'll be discussing today.
Please read the introductory section and the short section on 'Retrieving Data'. This will set the stage by explaining what the requests library does and showing a basic GET request.
As the article highlights, a script using requests essentially emulates what a tool like Postman or a web browser does, but programmatically.
Most scripts you encounter will contain these core components:
- Imports: The script begins by importing necessary libraries, almost always including
requests. - Variable Definitions: Key information like device IPs, API endpoints (URLs), and credentials are stored in variables for clarity and reusability.
- Authentication: The script performs the necessary steps to authenticate with the API. This might be as simple as adding a token to a header or a more complex multi-step process.
- Request Execution: The script uses a
requestsmethod (likerequests.get()orrequests.post()) to send the API request. - Response Handling: The script checks the response, typically by looking at the HTTP status code, and then processes the returned data, often by parsing a JSON payload.
Let's see these components in a real-world script that interacts with Cisco DNA Center.
Interpreting a "Read" Operation (GET Request)
The most common and safest operation is reading data from a device without changing its state. This is done using an HTTP GET request.
The following resource contains Python scripts that perform read operations against the Cisco DNA Center sandbox.
Cisco DNA REST API calls with Python's requests library
This article from wandernets.com provides clear, practical examples of using Python to interact with the Cisco DNA Center API.
Read the section titled 'Devices'. Pay close attention to the Python code block and the author's explanation of the authentication process and the GET request.
Let's dissect the script from the article to solidify our understanding.
import requests
import json
# 1. Variable Definitions
USER = 'devnetuser'
PASSWORD = 'Cisco123!'
BASE_URL = 'https://sandboxdnac.cisco.com/dna/intent/api/v1'
# 2. Authentication
AUTH = requests.auth.HTTPBasicAuth(USER, PASSWORD)
AUTH_RESPONSE = requests.post('https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token', auth=AUTH, verify=False)
TOKEN = json.loads(AUTH_RESPONSE.text)['Token']
HEADERS = { 'X-Auth-Token': TOKEN }
# 3. Request Execution
RESOURCE = '/network-device'
call_response = requests.get(BASE_URL + RESOURCE, headers=HEADERS, verify=False)
# 4. Response Handling
devices = json.loads(call_response.text)['response']
for device in devices:
print('Hostname: {hostname}, Type: {type}'.format(hostname=device['hostname'],type=device['type']))
Interpretation Breakdown:
- Authentication (Lines 8-12): You can immediately tell this script uses a two-step authentication process.
- It first sends a
POSTrequest to an/auth/tokenendpoint using basic authentication (HTTPBasicAuth). - It then parses the JSON response to extract a token:
json.loads(AUTH_RESPONSE.text)['Token']. - Finally, it prepares a
HEADERSdictionary to include this token for all subsequent requests. This is a very common pattern for enterprise APIs.
- It first sends a
- Request Execution (Lines 15-16): The line
requests.get(...)is the clear indicator of a read operation. The script is requesting data from the/network-deviceendpoint. It is not sending any payload, only headers for authentication. - Response Handling (Lines 19-21): The script parses the JSON response (
json.loads(call_response.text)) and accesses the['response']key to get the list of devices. It then iterates through this list to print information. This shows the script's intent is to retrieve and display device data.
The key takeaway is that by identifying the requests.get() method and observing that the script is parsing and displaying the response, you can confidently interpret its purpose as data retrieval.
Interpreting a "Write" Operation (POST/DELETE)
Now, let's move on to scripts that change the device's state. These typically use POST (to create), PUT/PATCH (to update), or DELETE (to remove) methods. A key difference you'll see is the presence of a payloadโthe data sent to the device.

The following video provides an excellent walkthrough of scripts that create and delete multiple loopback interfaces on an IOS XE router.
Free CCNP 350-401 ENCOR Complete Course: 6.4: REST APIs Part 6
In this video, David Bombal demonstrates how to use a Python loop to automate the creation and deletion of multiple interfaces using a REST API. This is a perfect example of a practical 'write' script.
Please watch from 1:00 to 8:12. Focus on these key aspects: The 'Create' Script (1:00-3:27): Notice how the payload variable is constructed inside the for loop. This is how the script dynamically generates the JSON for each new interface. The HTTP Status Codes (3:27-5:37): Observe the 201 Created status code for success and the 409 Conflict code when trying to create an interface that already exists. This is how a script confirms its actions. The 'Delete' Script (5:37-8:12): See how the URL is dynamically constructed to target a specific interface and how the requests.delete() method is used.
Let's analyze the structure of the "create" script from the video.
Interpretation Breakdown:
- The Goal: The
for x in range(int_number):loop immediately tells you the script is designed to perform a repetitive task. - The Payload: Inside the loop, you see the
payloadbeing defined. This is the most critical part for aPOSTrequest.
You can see that the# Simplified from video payload = f""" {{ "ietf-interfaces:interface": {{ "name": "Loopback123{x}", "description": "Configured by RESTCONF", "type": "iana-if-type:softwareLoopback", "enabled": true, "ietf-ip:ipv4": {{ "address": [ {{ "ip": "1.2.3.{x}", "netmask": "255.255.255.255" }} ] }} }} }} """nameof the loopback and itsipaddress are being dynamically generated in each iteration of the loop. - The Method: The script then calls
requests.post(url, data=payload, ...). The use ofpostcombined with apayloadis the definitive sign of a write operation. - The Outcome: The script prints the
response.status_code. As you saw, a201means success, while other codes like409indicate a problem. An automation script must check the status code to verify the outcome of its actions.
The "delete" script follows a similar pattern but uses requests.delete(url_with_interface_name, ...) and expects a 204 No Content status code on success.
Test your understanding!
You are reviewing a colleague's Python script and see the following line:response = requests.delete(f"{api_url}/interfaces/Loopback101", headers=auth_headers)
What is the most likely purpose of this line of code? What HTTP status code would you expect to see in the response object if the operation was successful?
Show answer
- Purpose: The code is sending an HTTP
DELETErequest to remove the interface named "Loopback101". - Expected Status Code: A successful
DELETEoperation typically returns a204 No Contentstatus code, indicating the resource was removed and there is no data to return in the response body.
Tying It All Together: An Interactive Script
So far, we've seen scripts where the configuration data is hardcoded or generated in a simple loop. A more advanced script might prompt the user for the details at runtime.
This final video demonstrates a script that does just that. It asks the user for the router's IP address, the desired loopback interface name, its IP address, and more, before building and sending the API call.
Fundamentals of Network Automation
To conclude, let's watch this segment from a Kevin Wallace training session. It demonstrates modifying a script found on GitHub to make it interactive, tying together everything we've discussed.
Please watch from 1:20:20 to 1:27:32. Notice how the script uses the input() function to gather information from the user and then uses those variables to construct the payload for a POST request. This is a great example of a practical, reusable automation tool.
When you interpret a script like the one in the video, you would see:
- Multiple calls to the
input()function to gather data from the user. - The variables from the
input()calls being used to construct the URL and the JSON payload. - A
requests.post()call to send the user-defined configuration to the device. - A final print statement confirming the result based on the API response.
This represents a complete, albeit basic, network automation workflow: gather intent, build a payload, execute the change, and verify the result.
Conclusion
In this lesson, we moved from simply reading JSON to interpreting the Python scripts that produce and consume it. You are now equipped to analyze a basic automation script and understand its function.
Key Takeaways:
- Python's
requestslibrary is the standard for making HTTP API calls. - You can determine a script's intent by identifying the HTTP method used:
requests.get()implies a read operation to retrieve data.requests.post(),put(), orpatch()implies a write operation to create or update a resource, and will be accompanied by a data payload.requests.delete()implies a write operation to remove a resource.
- Interpreting a script involves checking how it handles authentication, how it constructs payloads and URLs (statically or dynamically), and how it processes the response (especially HTTP status codes).
Preview of the Next Lesson:
We've now worked with REST APIs and interpreted the JSON data they exchange. But how does a device know what structure the JSON should have? How does it know that an interface object should have a "name" key and an "enabled" key? This is defined by a data model. In our next lesson, we will explore the learning outcome: "Describe the purpose of data modeling languages such as YANG." We'll uncover how YANG provides the formal blueprint for the network data we've been manipulating.