Python 4 - Useful Python Libraries for Network Engineers

By Sheldon L Published at 2020-03-08 Updated at 2020-03-08


Manipulating Data formats

# xml
!pip install xmltodict
import xmltodict

with open('example.xml')as f:
  xml_example = f.read()          # always return str

xml_dict = xmltodict.parse(xml_example)
back_to_xml = xmltodict.unparse(xml_dict)


# JSON
import json

with open('example.json') as f:
  json_example = f.read()

json_dict = json.loads(json_example)
back_to_json = json.dumps(json_dict)


# YAML
!pip install yaml
import yaml

with open('example.yml') as f:
  yaml_example = f.read()

yaml_dict = yaml.load(yaml_example)
back_to_yaml = yaml.dump(json_dict)


# CSV
import csv

with open('example.csv') as f:
  csv_example = csv.reader(f)

  for row in csv_example:
    device = row[0],
    location = row[1]
    ip = row[2]
    print(f'{device}, {location}, {ip}')



# YANG
import pyang  # data modeling language - IETF Standard
              # for NETCONF/RESTCONF/gRPC

API Libraries

REST

# RESTCONF Basic request for Device Data
!pip install request
import requests, urllib3
import sys

# add parent dir to allow importing common vars,
# and suppose there's a device_info.py in parent dir
sys.path.append("..")
from device_info import ios_xel as device

# Disable self-signed Cert warning, not a nessesary
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Setup base vars for request
restconf_headers = {"Accept": "application/yang-data+json"}
restconf_base = "https://{ip}:{port}/restconf/data"
interface_url = restconf_base + "/ietf-interfaces:interfaces/interfaces={int_name}"

url = interface_url.format(
  ip = device["address"],
  port = device["resconf_port"],
  int_name = device["GigabitEthernet2"],
)

r = requests.get(
  url,
  headers = restconf_headers,
  auth = (device["username"], device["password"]),
  verify = False
)

print(r.text)

interface = r.json()["ietf-interfaces:interface"]
print("{name}, {ip}/{mask}".format(
  name = interface["name"],
  ip = interface["ietf-ip:ipv4"]["address"][0]["ip"],
  mask = interface["ietf-ip:ipv4"]["adress"][0]["netmask"],
))

# RESTCONF: Creating a new lookback
restconf_headers["Content-Type"] = "application/yang-data+json"
lookback = {
  "name": "Lookback01",
  "description": "Demo interface by RESTCONF",
  "ip": "192.168.101.1",
  "netmask": "255.255.255.0",
}

data = {
  "ietf-interfaces:interface": {
    "name": "lookback["name"],
    "description": lookback["description"],
    "type": "iana-if-type:softwareLookBack",
    "enabled": True,
    "ietf-ip:ipv4": {
      "address": [
        {
          "ip": lookback["ip"],
          "netmask": lookback["netmask"],
        }
      ]
    }
  }
}
# Create url and send RESTCONF request to corel for GigE2 config
url = interface_url.format(
  ip=corel_ip,
  int_name=lookback["name"]
)

r = requests.put(
  url,
  headers = restconf_headers,
  auth = (username, password),
  json = data,
  verify = False,
)
print("Request status code: {}".format(r.statuas_code))
# NETCONF: basic request
!pip install ncclient
import ncclient
from ncclient import manager
import xmltodict

interface_filter = """
<filter>
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface>
      <name>{int_name}</name>
    </interface>
  </interfaces>
</filter>
"""

with manager.connect(
  host=corel_ip,
  username=username,
  password=password,
  hotkey_verify=False,
) as m:
  # create desired NETCONF filter and <get_config>
  filter = interface_filter.format(int_name = "GigabitEthernet2")
  r = m.get_config("running", filter)
  # process the XML to python dict
  interface = xmltodict.parse(r.xml)
  interface = interface["rpc-reply"]["data"]["interfaces"]["interface"]

  print("{name}, {ip}/{mask}".format(
    name = interface["name"]["#text"],
    ip = interface["ipv4"]["address"]["ip"],
    mask = interface["ipv4"]["address"]["netmask"],
  ))

# NETCONF: update
config_data = """<config>
  <filter>
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface>
    <name>{int_name}</name>
    <description>{description}</description>
    <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">
      ianaift: softwareLookack
    </type>
    <enabled>true</enabled>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip>
      <address>
      <ip>{ip}</ip>
      <netmask>{netmask}</netmask>  
      </address>
    </ipv4>
    </interface>
  </interfaces>
  </filter>
</config>"""

lookback = {
  "name": "Lookback02",
  "description": "Demo interface by NETCONF",
  "ip": "192.168.102.1",
  "netmask": "255.255.255.0",
}

with manage.connect(
  host=corel_ip,
  username=username,
  password=password,
  hotkey_verify=False,
) as m:
  # create desired NETCONF config payload and <edit_config>
  config = config_data.format(**lookback)
  r = m.edit_config(targe="running", config=config)

  print("NETCONF RPC OK: {}".format(r.ok))
# Network CLI: if no other API available ...

#
!pip install netmiko
import netmiko

# SNMP
!pip install pysnmp