3.6 Constructing a Python Script using RESTCONF with JSON for Cisco IOS-XE Devices
Introduction
Lets discuss RESTCONF, a protocol that enables network devices to be configured and managed using a standard set of APIs. We will demonstrate how to use RESTCONF with Python and JSON to manage Cisco IOS-XE devices effectively. By the end of this tutorial, you should have a better understanding of RESTCONF and how to leverage it to configure and manage Cisco IOS-XE devices using Python scripts.
What is RESTCONF?
RESTCONF is a network management protocol that uses HTTP/HTTPS as a transport mechanism and follows REST principles (Representational State Transfer). It is an IETF standard designed to provide a uniform API for managing network devices’ configuration and operational data. RESTCONF allows developers to access and manipulate network device data using standard HTTP methods like GET, PUT, POST, and DELETE. The data can be represented in JSON or XML format, with JSON being the most widely adopted.
Using RESTCONF with Python and Cisco IOS-XE Devices:
To interact with Cisco IOS-XE devices using RESTCONF, we need to perform the following high-level steps:
Enable RESTCONF on the Cisco device
Install Python dependencies
Create a Python script to interact with the device using RESTCONF
Step 1: Enable RESTCONF on the Cisco device
Before you can use RESTCONF with a Cisco IOS-XE device, you need to enable it. Log into the device and execute the following commands:
NOTE: Our example will be using the IOSXE always-on sandbox from DevNet
conf t
netconf-yang
restconf
end
write
Step 2: Install Python dependencies
To interact with RESTCONF using Python, we need to install the ‘requests’ library. You can do this using pip:
pip install requests
Step 3: Create a Python script to interact with the device using RESTCONF
Now that we have installed the necessary dependencies, we can create a Python script to interact with the Cisco IOS-XE device using RESTCONF. In this example, we will create a simple script to retrieve the device’s interfaces information.
"""Example Python RESTCONF script."""
import requests
from requests.auth import HTTPBasicAuth
import json
def main():
# Device information | This is the always-on IOS-XE sandbox from DevNet
# However, the script in the repo is using a local container lab node.
device_ip = "sandbox-iosxe-recomm-1.cisco.com"
username = "developer"
password = "C1sco12345"
# RESTCONF headers
headers = {
"Accept": "application/yang-data+json",
"Content-Type": "application/yang-data+json",
}
# URL for RESTCONF request
url = f"https://{device_ip}/restconf/data/Cisco-IOS-XE-interfaces-oper:interfaces/"
# Send RESTCONF request to the device
response = requests.get(
url, headers=headers, auth=HTTPBasicAuth(username, password), verify=False
)
# Check if the request was successful
if response.status_code == 200:
interfaces = response.json()
print(json.dumps(interfaces, indent=2))
else:
print(f"Error: {response.status_code}")
if __name__ == "__main__":
main()
An example output would look like this:
{
"Cisco-IOS-XE-interfaces-oper:interfaces": {
"interface": [
{
"name": "GigabitEthernet1",
"interface-type": "iana-iftype-ethernet-csmacd",
"admin-status": "if-state-up",
"oper-status": "if-oper-state-ready",
"last-change": "2023-03-13T04:56:17.929+00:00",
"if-index": 1,
"phys-address": "52:54:00:ae:af:00",
"speed": "1000000000",
"statistics": {
"discontinuity-time": "2023-03-13T04:54:28+00:00",
"in-octets": "5829760",
"in-unicast-pkts": "77811",
"in-broadcast-pkts": "0",
"in-multicast-pkts": "0",
"in-discards": 0,
"in-errors": 0,
"in-unknown-protos": 0,
"out-octets": 33399060,
"out-unicast-pkts": "72373",
"out-broadcast-pkts": "0",
"out-multicast-pkts": "0",
"out-discards": "0",
"out-errors": "0",
"rx-pps": "2",
"rx-kbps": "2",
"tx-pps": "2",
"tx-kbps": "2",
"num-flaps": "0",
"in-crc-errors": "0",
"in-discards-64": "0",
"in-errors-64": "0",
"in-unknown-protos-64": "0",
"out-octets-64": "33399060"
},
"vrf": "",
"ipv4": "10.0.0.15",
"ipv4-subnet-mask": "255.255.255.0",
"description": "NORNIR-NETCONF-DESCRIPTION-31",
"mtu": 1500,
"input-security-acl": "",
"output-security-acl": "",
"v4-protocol-stats": {
"in-pkts": "75746",
"in-octets": "5605048",
"in-error-pkts": "0",
"in-forwarded-pkts": "0",
"in-forwarded-octets": "0",
"in-discarded-pkts": "0",
"out-pkts": "72319",
"out-octets": "33395820",
"out-error-pkts": "0",
"out-forwarded-pkts": "72319",
"out-forwarded-octets": "0",
"out-discarded-pkts": "0"
},
"v6-protocol-stats": {
"in-pkts": "0",
"in-octets": "0",
"in-error-pkts": "0",
"in-forwarded-pkts": "0",
"in-forwarded-octets": "0",
"in-discarded-pkts": "0",
"out-pkts": "0",
"out-octets": "0",
"out-error-pkts": "0",
"out-forwarded-pkts": "0",
"out-forwarded-octets": "0",
"out-discarded-pkts": "0"
},
"bia-address": "52:54:00:ae:af:00",
"ipv4-tcp-adjust-mss": 0,
"ipv6-tcp-adjust-mss": 0,
"storm-control": {
"broadcast": {
"filter-state": "inactive"
},
"multicast": {
"filter-state": "inactive"
},
"unicast": {
"filter-state": "inactive"
},
"unknown-unicast": {
"filter-state": "inactive"
}
},
"ether-state": {
"negotiated-duplex-mode": "full-duplex",
"negotiated-port-speed": "speed-1gb",
"auto-negotiate": true,
"enable-flow-control": false,
"media-type": "ether-media-type-virtual"
},
"ether-stats": {
"in-mac-control-frames": "0",
"in-mac-pause-frames": "0",
"in-oversize-frames": "0",
"in-jabber-frames": "0",
"in-fragment-frames": "0",
"in-8021q-frames": "0",
"out-mac-control-frames": "0",
"out-mac-pause-frames": "0",
"out-8021q-frames": "0"
}
}
]
}
}
This script is available in /spauto/scripts/
directory. You can run the script using the following command:
python get_interfaces.py
If the script runs successfully, you should see the JSON output with the device’s interfaces information.