Framework for Cisco APIs

Home

This document discusses all the Cisco APIs that are avaiable and compares each of them. For detail, you can access the following orgmode documents:

1 API documents

2 15% 3.0 Cisco Platforms and Development

For each of these you should know:

  1. how to get the documentation for the API?
  2. how does the API handle authentication?
  3. what APIs are supported?
  4. what python sdk or toolkits are available and where do I download them?

3 3.1 Construct a Python script that uses a Cisco SDK given SDK documentation

For each of the files types, best to use the with contstruct to open them for reading into python

with open("myformattedfile") as f:
    ingestintopython = f.read()

Then the ingested file can be parsed according to the file type, i.e. xml, json, yaml, csv.

Data formats:

Format Python Usage
  library x should be more descriptive. using here to save space
    eg xmldict, or jsondict, or yamldict respectively
xml import x = xmltodict.parse("ingestintopython")
  xmltodict intname = x["interface"]["name"]
    x["interface"]["ipv4"]["address"]["ip"] = "10.1.1.4"
     
     
    output = xmltodict.unparse(x)
json import x = json.loads(ingestintopython)
  json intname = x["interface"]["name"]
    x["interface"]["ipv4"]["address"][0]["ip"] = "10.1.1.4"
     
    output = json.dumps(x)
     
    loads and dumps means " json load string" and "dump string"
yaml PyYAML x = yaml.load(ingestintopython)
    intname = x["interface"]["name"]
  import x["interface"]["ipv4"]["address"][0]["ip"] = "10.1.1.4"
  yaml  
    output = yaml.dump(x, defaultflowstype=False)
csv csv # same with open as the rest, but must use csv.reader eg:
    ingestingopython = csv.reader(f) # one line at a time
  import for row in ingestintopython:
  csv print("{device} is in {location} and has IP {ip}".format(
    device = row[0],
    location = row[2],
    ip = row[1]))
     
YANG pyang See YANG file
     

3.0.1 API Libraries

Type usage Library Often used with
REST APIs pip intsll requests requests RESTCONF
  import requests   native REST APIs
      JSON-RPC
NETCONF pip install ncclient ncclient NETCONF YANG
  import ncclient    
Network pip install netmiko netmiko  
CLI import netmiko    
SNMP pip install pysnmp PySNMP  
  import pysnmp    

See both NETCONF.org and RESTCONF.org for details on both those.

3.1 netmiko for Network CLI API library

Use this only if the other libraries are not available. Because you will be manually handling the parsing where before you could let ncclient, or request do the mundane heavy lifting for you.

  • builds on paramiko library for SSH connectivity
  • works with multi vendors and multiple operating systems
  • send and receive clear text
  • will need to run post-processing on the data.

Example gathering info using netmiko

from netmiko import ConnectHandler
import re     # regexp useful here as we will be parsing text
import sys

# Add parent directory to path to allow importing device_info (common vars)
sys.path.append("..")
from device_info import iox_xe1 as device  #noqa

# set device_type for netmiko
device["device_type"] = "cisco_ios"

# create a cli command template
show_interface_config_temp = "show running-config interface {}"

with  ConnectHandler(ip = device["address"],
             port = device["ssh_port"],
             username = device["username"],                    
             password = device["password"],                    
             device_type = device["device_type"]) as ch:

    # create desired CLI command and send to device
    command = show_interface_config_temp.format("GigabitEthernet2")
    interface = ch.send_command(command)

    print(interface)                    

# Use regular expressions to parse the outpout for desired data
name = re.search(r'interfacer (.*)', interface).group(1)
description = re.search(r'description (.*)', interface).group(1)
ip_info = re.search(r'ip address (.*)', interface)
ip = ip_info.group(1)
netmask = ip_info.group(2)

# print the info I wanted
print(f'The interface{name} hs ip address {ip}/{netmask}')

Example updating a config using netmiko

from netmiko import ConnectHandler
import re     # regexp useful here as we will be parsing text
import sys

# Add parent directory to path to allow importing device_info (common vars)
sys.path.append("..")
from device_info import iox_xe1 as device  #noqa 

# set device_type for netmiko
device["device_type"] = "cisco_ios"

# create the details for a loopback interface and store in a dictionary
loopback = {"int_name": "Loopback27",
        "description": "Created looback27 using netmiko",
        "ip": "10.1.1.5",
        "netmask": "255.255.0.0"}

# create the CLI config as a list.  They are a series of commands I want to send
interface_config = [
     "interfacer {}".format(loopback["int_name"],
     "description {}".format(loopback["description"],
     "ip address {}".format(loopback["ip"], loopback["netmask"]),
     "no shut"]

with  ConnectHandler(ip = core1["ip"],
             username=username,                    
             password=password,                    
             device_type = core1["device_type"]) as ch:

    # send the configuration to the device.  Notice that my config set did
    # NOT include the command "config t".  Netmiko assumes that's what you
    # want to do when you do a "ch.send_config_set" so it has it covered.:)
    output = ch.send_config_set(interface_config)

3.2 SNMP as API using PySNMP

This one is more complex. Use examples readily available online.

PySNMP supports both GET and TRAP communications. Data is returnd in custom objects, see http://snmplabs.com/pysnmp/ and https://github.com/etingof/pysnmp

The PySNMP docs has these samples. pysnmp.readthedocs.io/…/quick-start.html pysnmp.readthedocs.io/…/walking-operations.html pysnmp.readthedocs.io/…/modifying-variables.html

3.3 Cisco Configuration Management using Opensource Python modules

There are four common modules, and probably many niche modules, that are used for configuration management. They are:

Network Automation, programmed in python:

  1. NAPALM
    • library providing standard set of functions for working with different network OSes.
  2. Nornir
    • can leverage other tools like NAPALM

Server Automation, programmed in python:

  1. Ansible
    • declarative, agent-less automation framework for managing configuration.
    • Many "modules" available from many network vendors, and Unix admin.
  2. Salt
    • config management and remote code execution engine. net automation not yet fully baked.

3.3.1 NAPALM

  • very robust and mature
  • multivendor
  • quite popular and widely used.
  • builds on availabe backend libs and interfaces (CLI, NX-API, NETCONF)
  • can be used and integrated into Anisble and Nornir.
  • config options include "Replace, Merge, Compare Commit, Discard, Rollback

Docs are in readthedocs.io

3.3.2 Ansible

Currently the leading devops tool for network config mgt.

  • agentless
  • uses ssh
  • supports cli and NETCONF as way of interacting with the network device.
  • has many usable network modules published by Cisco and others.

One common tools is "Ansible SALT Stack" combines Ansible with SALT.

3.3.3 VIRLUTILS

virlutils is a python utility/libarary. Great for virl and cml. virlutils is a command-line wrapper written in python that lets you very easily access and control your virl, or cml, environment.

Really useful for NetDevOps workflows, when you are running tests and config changes in a simulation before applying to a production environment. The simulation is VIRL or CML. i.e. great for CI/CD pipelines.

See developer.cisco.com/…/virlutils/

virlutils is the newer approach to vagrant. Examples of common commands:

  • $ virl up starts up a virl lab
  • $ virl ls to list what simulations you have running
  • $ virl nodes # first have to tell cml which lab is "current"
  • $ virl use <id> # make <id> the current lab

To use virlutils:

  1. clone the repo:
  2. use pip or setup.py
    • pip install cmlutils
    • pip install virlutils

    or,

    • python3 -m venv venv-cmlutils
    • source venv-cmlutils/bin/activate
    • python setup.py install
  3. Setup .virlrc with these virl credentials:
    • VIRL_HOST myvirlserver.zintis.net=
    • VIRL_USERNAME=admin
    • VIRL_PASSWORD=M0dellinglabs
    • CML_VERIFY_CERT=False # or if you had the cml server .pem file

Alternatively you can use environment variables:

  • export VIRL_HOST 192.168.11.66
  • export VIRL_USERNAME=admin
  • export VIRL_PASSWORD=M0dellinglab
  • CML_VERIFY_CERT=False # or /etc/certs/ca_bundle.pem

I ran this and virl ls worked.

This command will be passed the CML controller VM IP, the console path of the node, and the CML controller username (note: you may have to force a TTY allocation in your SSH command. On my mac I did NOT have to.)

More info at developer.cisco.com/…/virltuils

3.4 Using cmlutils / virlutils

Once a lab is up and virlults is working, you should name your lab so that you can run virl use <name> You can name it using the cml web interface, first select your lab, then, the name appears at the top line. This is an editable field. Call it something good, i.e. <name>

Here's what I did:

$ virl ls
Labs on Server
╒════════╤═════════════════════╤═══════════════╤═════════╤══════════╤═════════╤═════════╤══════════════╕
│ ID     │ Title               │ Description   │ Owner   │ Status   │   Nodes │   Links │   Interfaces │
╞════════╪═════════════════════╪═══════════════╪═════════╪══════════╪═════════╪═════════╪══════════════╡
│ dcede0 │ Lab at Mon 14:46 PM │               │ admin   │ STARTED  │       9 │      14 │           82 │
╘════════╧═════════════════════╧═══════════════╧═════════╧══════════╧═════════╧═════════╧══════════════╛
(venv-pyats) /Users/zintis/bin/python/venv-pyats/cml[667]:

Then I renamed my lab to Zint-cml *and gave it a description too, using the web interface:

$ virl ls
Labs on Server
╒════════╤══════════╤══════════════════════╤═════════╤══════════╤═════════╤═════════╤══════════════╕
│ ID     │ Title    │ Description          │ Owner   │ Status   │   Nodes │   Links │   Interfaces │
╞════════╪══════════╪══════════════════════╪═════════╪══════════╪═════════╪═════════╪══════════════╡
│ dcede0 │ Zint-cml │ route redistribution │ admin   │ STARTED  │       9 │      14 │           82 │
╘════════╧══════════╧══════════════════════╧═════════╧══════════╧═════════╧═════════╧══════════════╛

Then

$ virl use Zint-cml
(venv-pyats) /Users/zintis/bin/python/venv-pyats/cml[670]:
$ virl nodes
Here is a list of nodes in this lab
╒══════╤════════════════════╤════════════════════╤═════════╤══════════╤══════════════════╕
│ ID   │ Label              │ Type               │ State   │ Wiped?   │ L3 Address(es)   │
╞══════╪════════════════════╪════════════════════╪═════════╪══════════╪══════════════════╡
│ n1   │ unmanaged-switch-0 │ unmanaged_switch   │ BOOTED  │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n2   │ iosv-0             │ iosv               │ BOOTED  │ False    │ 192.168.11.68    │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n3   │ iosv-1             │ iosv               │ BOOTED  │ False    │ 192.168.11.67    │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n4   │ iosv-2             │ iosv               │ BOOTED  │ False    │ 192.168.11.69    │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n5   │ iosv-3             │ iosv               │ BOOTED  │ False    │ 192.168.11.71    │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n6   │ iosv-4             │ iosv               │ BOOTED  │ False    │ 192.168.11.70    │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n7   │ alpine-0           │ alpine             │ BOOTED  │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n8   │ iosv-5             │ iosv               │ BOOTED  │ False    │ 192.168.11.72    │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n0   │ ext-conn-0         │ external_connector │ BOOTED  │ False    │                  │
╘══════╧════════════════════╧════════════════════╧═════════╧══════════╧══════════════════╛
(venv-pyats) /Users/zintis/bin/python/venv-pyats/cml[671]:

And finaly shutting the lab down:

$ virl down
Shutting down lab Zint-cml (ID: dcede0).....
SUCCESS
(venv-pyats) /Users/zintis/bin/python/venv-pyats/cml[672]:
$ virl ls
Labs on Server
╒════════╤══════════╤══════════════════════╤═════════╤══════════╤═════════╤═════════╤══════════════╕
│ ID     │ Title    │ Description          │ Owner   │ Status   │   Nodes │   Links │   Interfaces │
╞════════╪══════════╪══════════════════════╪═════════╪══════════╪═════════╪═════════╪══════════════╡
│ dcede0 │ Zint-cml │ route redistribution │ admin   │ STOPPED  │       9 │      14 │           82 │
╘════════╧══════════╧══════════════════════╧═════════╧══════════╧═════════╧═════════╧══════════════╛
(venv-pyats) /Users/zintis/bin/python/venv-pyats/cml[673]:
$ virl nodes
Here is a list of nodes in this lab
╒══════╤════════════════════╤════════════════════╤═════════╤══════════╤══════════════════╕
│ ID   │ Label              │ Type               │ State   │ Wiped?   │ L3 Address(es)   │
╞══════╪════════════════════╪════════════════════╪═════════╪══════════╪══════════════════╡
│ n1   │ unmanaged-switch-0 │ unmanaged_switch   │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n2   │ iosv-0             │ iosv               │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n3   │ iosv-1             │ iosv               │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n4   │ iosv-2             │ iosv               │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n5   │ iosv-3             │ iosv               │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n6   │ iosv-4             │ iosv               │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n7   │ alpine-0           │ alpine             │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n8   │ iosv-5             │ iosv               │ STOPPED │ False    │                  │
├──────┼────────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│ n0   │ ext-conn-0         │ external_connector │ STOPPED │ False    │                  │
╘══════╧════════════════════╧════════════════════╧═════════╧══════════╧══════════════════╛
(venv-pyats) /Users/zintis/bin/python/venv-pyats/cml[674]:
   

3.5 3.2 Describe the capabilities of Cisco network management platforms and APIs

(Meraki, Cisco DNA Center, ACI, Cisco SD-WAN, and NSO)

3.6 3.3 Describe the capabilities of Cisco compute management platforms and APIs

(UCS Manager, UCS Director, and Intersight)

3.7 3.4 Describe the capabilities of Cisco collaboration platforms and APIs

(Webex Teams, Webex devices, Cisco Unified Communication Manager including AXL and UDS interfaces, and Finesse)

3.8 3.5 Describe the capabilities of Cisco security platforms and APIs (Firepower,

Umbrella, AMP, ISE, and ThreatGrid)

3.9 3.6 Describe the device level APIs and dynamic interfaces for IOS XE and NX-OS

3.10 3.7 Identify the appropriate DevNet resource for a given scenario (Sandbox,

Code Exchange, support, forums, Learning Labs, and API documentation)

3.11 3.8 Apply concepts of model driven programmability (YANG, RESTCONF, and

NETCONF) in a Cisco environment

3.12 3.9 Construct code to perform a specific operation based on a set of

requirements and given API reference documentation such as these:

3.12.1 3.9.a Obtain a list of network devices by using

  • Meraki,
  • Cisco DNA Center,
  • ACI,
  • Cisco SD-WAN, or NSO

3.12.2 3.9.b Manage spaces, participants, and messages in Webex Teams

3.12.3 3.9.c Obtain a list of clients / hosts seen on a network using

  • Meraki or
  • Cisco DNA Center

4 3.2

5 API Authentication Links

The exam blue print asks that you know common API authentication mechanisms:

  • basic,
  • custom token, and
  • API keys

The following table compares each APIs auth method.

API Method URI
  <c> URI
DNA Center Basic "https:///dna/system/api/v1/auth/token" or
  Auth "https:///dna/system/api/v1/auth/token?hostname=Switch1"
    with these headers:
  Returns - Content-Type "application/json"
  a - Authorization "Basic + base64encodedstring"
  Token - Accept "application/json"
Webex token Retrieve manually from "Your Personal Access Token" in
    https://developer.webex.com/docs/api/getting-started
Meraki API token Retrieve it manually from dashboard, my profile.
ACI REST API cookie POST https://{{apic}}/api/aaLogin.json
ACI SDK   POST https://{{apic}}/api/aaLogin.xml
ACI Toolkit   see ACI API REST API i.e. mysess = Session(URL, LOGIN, PASSWD)
NSO REST API u + p $ curl -i -X GET http://localhost:8080/api -u admin:admin
NSO RESTCONF token the token does not support encryption.
    NSO does not support client-certificate based authentication.
SDWAN API token  
AMP API Basic Authorization: Basic mybase64string
  Auth AMP = {"KEY": "e815426e-bb64-cf4f-71ba-5112febdead5",
    "ID": "8595782abe51ba411223"}
  Token url = "https://<ampid>:<ampkey>@api.amp.cisco.com/v1/computers"
     
Firepower oAuth Request a password-granted access token based on
Threat 2.0 username/password using the admin account, or optionally
Defence (token) request a custom token. After which you the access token
    in your API calls in the Authorization: Bearer header
    When token expires, reissue a new one.

Reminder that curl also support -H "Accept: application/vnd.yang.api+json" style headers.

6 API Tokens from Responses

API Method Postman
DNA Center token X-Auth-Token header. You will have to refresh
    the token quite regularly by running the
    authorization code (zp-update-tokens.py)
Webex token 'Authorization': "Bearer " + zintis_bearer_code
    header. Also has
Meraki token 'X-Cisco-Meraki-API-Key': env_user_zp.ZP_MERAKI_API_KEY'
ACI REST API cookie Browser will get a
ACI SDK   cookie and use that
ACI Toolkit   session = Session(URL, LOGIN, PASSWORD
NSO API token for RESTCONF a token, for older REST API just -u -p
SDWAN API token  
AMP API Basic  
  Returns  
  a  
  Token  
     

7 API Documentation / Catalog

API Documentation / Catalog
DNA Center From Appliance home page, click Platform
  > View the API Catalog,
  > Developer Toolkit (see search box top-R)
Meraki API From logged in dashboard.meraki.com
  > Help > API Documentation or directly to
  https://developer.cisco.com/meraki/api-v1/
ACI REST API https://{{apic}}/api/aaLogin.json
ACI SDK https://{{apic}}/api/aaLogin.xml
ACI Toolkit  
NSO API  
SDWAN API  
AMP API api-docs.amp.cisco.com/apiresources
   
   

8 API documents

9

9.1 Home