Cisco Network Programmability Course Guide
Cisco Network Programmability Course Guide
v1.0
Course Introduction
Designing and Implementing Cisco Network Programmability (NPDESI)
v1.0
Learner Skills and Knowledge
• Baseline Python knowledge
• CCNA/CCNP level network background
Course Goal
Upon completing this course, you will be able to meet these objectives:
• Provides the student a foundation to get started with network programmability by
learning how to minimize the amount of manual interactions (“CLI”) with the network
and increase the use of scripts and automation tools to drive down operational
inefficiencies. Within these goals, the learner reviews network programmability
fundamentals such as using Linux and Python, common automation protocols such
as NETCONF and REST, how they relate to YANG data models, SDN controller
northbound and southbound APIs, how to use device APIs on various Cisco
platforms, and how to get started using automation tools such as Ansible and
Puppet.
Course Flow
AM PM
APIC-EM REST
Linux Primer for Network Engineers
Network Programmability Fundamentals
Why Learn Linux?
Linux is everywhere—Used in various devices:
• Mobile devices
• Desktop Computers
• Production Servers
• Hypervisors
• Network switches
Why Learn Linux? (Cont.)
Though Linux is pervasive in technology, a network
programmability engineer should learn Linux
because:
• Network devices now expose the underlying Linux shell
• Network devices now enable engineers to run
containers on the actual network device
• Most software development environments are Linux-
based
• New open source projects such as Open vSwitch,
Docker, and OpenStack all have a Linux foundation
Navigating the Linux File System
Super User Privileges
• “super user” do
• Run a program as another user (ex: root privileges by default)
• Can configure who can run sudo commands in the “sudoers” file
• Debian/Ubuntu distros do not enable the root user
cisco@cisco: ~$
cisco@cisco: ~$ sudo su -
[sudo] password for cisco:
root@cisco: ~#
root@cisco: ~#
root@cisco: ~# exit
logout
cisco@cisco: $
Paths and Directories
Basic Commands
Command Description
man <command> View manual pages (how-to) to learn how to use a given command and it’s flags
Paths and Directories (Cont.)
• Relative Path
– Address relative to the current, or working, directory
• Absolute Path
– Address relative to the root directory
Change Directories
cd .. Change current directory to parent directory
Remove Commands
Command Description
rm Removes a file
cp Copy a file
mv Move/rename a file
cisco@cisco: ~/Nexus9000$
cisco@cisco: ~/Nexus9000$ cp file1 file2
cisco@cisco: ~/Nexus9000$
cisco@cisco: ~/Nexus9000$ mv file2 file3
cisco@cisco: ~/Nexus9000$
cisco@cisco: ~/Nexus9000$ ls
file1 file3
Working with Files and Directories (Cont.)
Viewing Files Commands
Command Description
more similar to using Cisco CL—space bar takes you down a full screen length (% in bottom
left).
less “less is more” because it allows the user to scroll up and down using arrow keys vs. just
the ability to space down.
cat Streams the file top to bottom without pausing.
cisco@cisco:~$ ls -l [Link]
-rw-rw-r-- 1 cisco cisco 117 Aug 6 2015 [Link]
cisco@cisco:~$
File Permissions (Cont.)
cisco@cisco:~$ ls -l vlans_script.py
-rw-rw-r-- 1 cisco cisco 0 Sep 12 15:14 vlans_script.py
cisco@cisco:~$
cisco@cisco:~$ chmod u+x vlans_script.py
cisco@cisco:~$
cisco@cisco:~$ ls -l vlans_script.py
-rwxrw-r-- 1 cisco cisco 0 Sep 12 15:14 vlans_script.py
cisco@cisco:~$
cisco@cisco:~$ chmod go+x+w vlans_script.py
cisco@cisco:~$
cisco@cisco:~$ ls -l vlans_script.py
-rwxrwxrwx 1 cisco cisco 0 Sep 12 15:14 vlans_script.py
cisco@cisco:~$
Linux Processes
Viewing Running Processes
• top
– Displays real time processor utilization
• htop
– Displays real time processor utilization in an easier to read format
• ps
– Display active processes
• ps aux
– Displays an exhaustive list of all processes by all users
Linux Processes (Cont.)
Viewing Running Processes
• ps
• ps aux | grep firefox
cisco@cisco: ~$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 24196 3256 ? Ss 20:15 0:01 /sbin/init splash
root 2 0.0 0.0 0 0 ? S 20:15 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 20:15 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 20:15 0:00 [kworker/0:0H]
(output omitted)
cisco@cisco: ~$
cisco@cisco: ~$ ps aux | grep firefox
cisco 2442 29.0 19.5 574872 200716 ? Sl 21:12 0:01 /usr/lib/firefox/firefox
cisco 2497 0.0 0.0 5108 800 pts/6 S+ 21:12 0:00 grep --color=auto firefox
cisco@cisco: ~$ kill 2442
cisco@cisco: ~$
Discovery 1: Using the Linux
Command Line
Topology
Linux Networking
Network Programmability Fundamentals
Basic Linux Networking Commands
Command Description
ping Test connectivity between two nodes. In Linux, ping will run continuously unless
manually stopped. Supports options such as on Cisco CLI (hint: man pages).
traceroute Displays the layer 3 hops taken to reach a destination
ip addr list
cisco@cisco: ~$ ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet [Link]/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
group default qlen 1000
link/ether 08:00:27:ce:e4:72 brd ff:ff:ff:ff:ff:ff
inet [Link]/24 brd [Link] scope global eth2
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fece:e472/64 scope link
valid_lft forever preferred_lft forever
Basic Linux Networking Commands (Cont.)
ifconfig vs. ip
• The command /bin/ip has been around for a long time, but people are still using the
older command /sbin/ifconfig.
• The ip command is more powerful and will eventually replace it.
Basic Linux Networking Commands (Cont.)
ip addr Assign or delete an IP address to a specific interface. The new network settings are
not persistent through a system restart.
cisco@cisco: ~$
cisco@cisco: ~$ sudo ip addr add [Link]/24 dev eth1
cisco@cisco: ~$
Basic Linux Networking Commands (Cont.)
ip route Add a route to the local system.
cisco@cisco: ~$
cisco@cisco: ~$ sudo ip route add [Link]/24 via [Link] dev eth1
cisco@cisco: ~$
Basic Linux Networking Commands (Cont.)
ifup Used to enable or disable a specific interface.
ifdown
cisco@cisco: ~$
cisco@cisco: ~$ sudo ifdown eth1
cisco@cisco: ~$
cisco@cisco: ~$ sudo ifup eth1
cisco@cisco: ~$
Basic Linux Networking Commands (Cont.)
Netstat Commands
Command Description
cisco@cisco: ~$ netstat -i
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 28677 0 0 0 16559 0 0 0
BMRU
lo 65536 0 2239 0 0 0 2239 0 0 0 LRU
Basic Linux Networking Commands (Cont.)
dig Used to display DNS information such as A Records, MX Records, and CNAMES
cisco@cisco: ~$
cisco@cisco: ~$ dig [Link]
;; ANSWER SECTION:
[Link]. 73480 IN A [Link]
Basic Linux Networking Commands (Cont.)
host Used to resolve a hostname to an IP address or vice versa and learn DNS information
such as MX Records, Name Servers, CNAME, etc.
cisco@cisco: ~$
cisco@cisco: ~$ host [Link]
[Link] has address [Link]
[Link] has IPv6 address 2001:420:1101:1::a
[Link] mail is handled by 20 [Link].
[Link] mail is handled by 10 [Link].
[Link] mail is handled by 30 [Link].
cisco@cisco: ~$
Basic Linux Networking Commands (Cont.)
ssh Used to securely log in to remote systems. The username can be included in the
command.
cisco@cisco: ~$
cisco@cisco: ~$ ip route list
default via [Link] dev enp0s3 proto static metric 100
default via [Link] dev enp0s8 proto static metric 101
default via [Link] dev enp0s9 proto static metric 102
[Link]/24 dev enp0s3 proto kernel scope link src [Link] metric 100
[Link]/24 dev enp0s8 proto kernel scope link src [Link] metric 100
[Link]/24 dev enp0s9 proto kernel scope link src [Link] metric 100
[Link]/16 dev enp0s3 scope link metric 1000
[Link]/24 dev enp0s3 proto kernel scope link src [Link]
cisco@cisco: ~$
Viewing the Routing and ARP Tables (Cont.)
route Another command to view and modify the routing table.
cisco@cisco: ~$
cisco@cisco: ~$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default [Link] [Link] UG 100 0 0 enp0s3
default [Link] [Link] UG 101 0 0 enp0s8
default [Link] [Link] UG 102 0 0 enp0s9
[Link] * [Link] U 100 0 0 enp0s3
[Link] * [Link] U 100 0 0 enp0s8
[Link] * [Link] U 100 0 0 enp0s9
link-local * [Link] U 1000 0 0 enp0s3
[Link] * [Link] U 0 0 0 enp0s3
Viewing the Routing and ARP Tables (Cont.)
arp View local system ARP table. Set a static ARP entry.
cisco@cisco: ~$ arp
Address HWtype HWaddress Flags Mask Iface
[Link] ether 52:54:00:12:35:02 C enp0s3
cisco@cisco: ~$
auto eth0
iface eth0 inet static
address [Link]
netmask [Link]
up ip route add [Link]/24 via [Link] dev eth2
up ip route add [Link]/24 via [Link] dev eth3
auto eth1
iface eth1 inet dhcp
Persistent Network Configuration (Cont.)
Updating DNS
• DNS information is stored in the [Link] file
• The absolute path is /etc/[Link]
• Dynamically constructed from files located in: /etc/resolvconf/[Link].d/
• Files in this directory include head, tail, base – update these and regenerate
/etc/[Link] with sudo resolvconf -u
# Dynamic [Link](5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver [Link]
nameserver [Link]
~
~
~
"/etc/[Link]"
Persistent Network Configuration (Cont.)
Restarting the Networking Service
• Networking service must be restarted after making changes to the network
configuration
– Changing an IP address or subnet mask
– Reconfiguring a gateway
– Adding additional NICs
cisco@cisco: ~$
cisco@cisco: ~$ sudo service networking restart
cisco@cisco: ~$
Discovery 2: Linux Networking
Topology
Python Foundations for Network
Engineers – Part 1
Network Programmability Fundamentals
Understanding Python
Why Learn Python?
• Interpreted Scripting Language
• Low barrier to entry compared to other
languages
• Can be used to write various types of Python
Applications
• Python Execution Engine exists on most Linux
distributions including network operating
systems, such as NX-OS
Understanding Python (Cont.)
Python 2.x Python 3.x
• No longer under active development, • Under active development
but supported by the Python community • Designed to be easier to learn
• Better library support • Fixed major issues are 2.x
• Default on Linux and Mac • Not backwards compatible
• Supported by Cisco NX-OS
Executing Python Code
Using the Dynamic Interpreter (shell)
cisco@cisco: ~$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
#!/usr/bin/env python
if __name__ == "__main__":
course = 'Designing and Implementing Cisco Network Programmability'
print course
>>>
>>> ipaddr = '[Link]'
>>>
Data Types: Strings
• Sequence of characters that >>> ipaddr = '[Link]'
>>>
are surrounded by quotes >>> hostname = 'nxos1'
• Immutable – individual >>>
characters cannot be natively >>> hostname = "nxos2"
>>>
modified >>> hostname[4] = '3'
• Empty string Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item
assignment
>>>
>>>
>>> os_version = ''
>>>
Printing Strings
• Using the print statement to print strings
– Prints the rendered string
• Typing in the variable name on the Interpreter
– Prints the value as a string literal
>>> 5 * 4 >>> 10 / 3
20 3
>>> 10 - 4 >>> 10.0 / 3
6 3.3333333333333335
>>> >>>
>>> 239234 + 4 >>> 10.0 // 3
239238 3.0
>>> >>>
Data Type: Booleans
• Values are True or False AND Result
• Operators are and, or, and not True and False False
• not takes the inverse True and True True
OR Result
– is, is not
Conditionals (Cont.)
>>> switch = 'catalyst 3850'
Conditional Statements >>>
• if, elif, else >>> if 'catalyst' in switch:
• End with a colon ... switch_type = 'catalyst'
... elif 'nexus' in switch:
• Consistent indentation required ... switch_type = 'nexus'
... else:
... switch_type = 'unknown'
...
>>>
>>> print switch_type
catalyst
>>>
Discovery 3: Python Foundations -
Part 1
Topology
Python Foundations for Network
Engineers – Part 2
Network Programmability Fundamentals
Lists
• Contains one or more objects >>> devices = ['asa', 'nexus', 'nexus',
'catalyst', 'asr']
in an ordered list >>>
• Indexed starting at zero >>> devices[2] = 'aci'
>>>
• Mutable – individual elements >>> print devices ['asa', 'nexus', 'aci',
can be modified 'catalyst', 'asr']
>>>
• Supports reverse index values >>> print devices[-1]
• Empty List – [] asr
>>> unknown_devices = []
>>>
Lists (Cont.)
>>> devices = ['asa', 'nexus', 'asa']
Working with common built-in >>>
methods >>> [Link]('aci')
• <list>.append() >>>
>>> [Link](0, 'asr')
• <list>.insert() >>>
• <list>.pop() >>> devices
['asr', 'asa', 'nexus', 'asa', 'aci']
>>>
>>> [Link]()
'aci'
>>>
Lists (Cont.)
>>> [Link]('asa')
Working with common built-in 2
methods (continued) >>>
• <list>.count() >>> devices
['asr', 'asa', 'nexus', 'asa']
• <list>.extend() >>>
• <list>.sort() >>> [Link]()
>>>
Dictionaries
• Contains one or more items >>> facts = {'hostname': 'nxos1', 'os': '7.0.3'}
>>>
and is an unordered list >>> print facts['hostname']
• Item is a key-value pair nxos1
>>>
• Indexed by name/key >>> print facts['os']
• Mutable – individual elements 7.0.3
>>>
can be modified >>> facts['os'] = '7.0.2'
• Uses curly braces {} >>>
>>> print facts
{'hostname': 'nxos1', 'os': '7.0.2'}
>>>
>>> device_facts = {}
>>>
Dictionaries (Cont.)
>>> facts = {'hostname': 'nxos1', 'os': '7.0.3'}
Working with common >>>
built-in methods >>> [Link]({'vendor': 'cisco', 'platform':
• <dict>.update() '9396'})
>>>
• <dict>.pop() >>> facts
• <dict>.get() {'vendor': 'cisco', 'platform': '9396', 'hostname':
'nxos1', 'os': '7.0.3'}
>>>
>>> [Link]('platform')
'9396'
>>>
>>> print [Link]('vendor')
cisco
>>>
>>> print [Link]('os_version')
None
>>>
Dictionaries (Cont.)
>>> [Link]()
Working with common ['vendor', 'hostname', 'os']
built-in methods >>>
(continued) >>> [Link]()
['cisco', 'nxos1', '7.0.3']
• <dict>.keys() >>>
• <dict>.values() >>> [Link]()
[('vendor', 'cisco'), ('hostname', 'nxos1'), ('os',
• <dict>.items() '7.0.3')]
>>>
Loops
For Loops
• Has the ability to iterate over items of any data type
>>> devices = ['asr', 'asa', 'nexus', 'catalyst']
>>>
>>> for item in devices:
... print 'Device type is {}'.format(item)
...
Device type is asr
Device type is asa
Device type is nexus
Device type is catalyst
>>>
Loops (Cont.)
While Loop
• Iterate over object until a given condition
>>> interface_id = 1
>>>
>>> while interface_id <= 4:
... print 'Ethernet1/{}'.format(interface_id)
... interface_id += 1
...
Ethernet1/1
Ethernet1/2
Ethernet1/3
Ethernet1/4
>>>
Function
• Create re-usable objects in your code >>> devices = ['r1', 'r2', 'r3']
>>>
• Helps with making code modular >>> len(devices)
3
• Take note when you see the same lines
>>>
of code more than once in your script >>> hostname = 'SJCRTR01R1'
• Built-in functions >>>
>>> len(hostname)
– len(), type(), dir(), help() 10
>>>
Function (Cont.)
• Create a function by defining it and then calling it
• Optionally passing parameters and returning data
ipaddr = '[Link]'
mask = '24'
def get_ip(ip):
print 'Function 1: ', ip
print 'Function 2: ', mask
print 'Function 3: ', ipaddr
print 'Function 4: ', mask
if __name__ == "__main__":
print 'Main 1: ', ipaddr
print 'Main 2: ', mask
ipaddr = '[Link]'
get_ip(ipaddr)
print 'Main 3: ', ip
Analyzing Code (Cont.)
Variable scoping (continued)
Libraries, in the form of modules and packages, are used to re-use code
between programs.
Python Module
Python module is a standalone file that contains Python definitions and
statements.
1 directory, 3 files
cisco@cisco:~$
>>> from [Link].vlan_check import vlan_exists
>>>
>>> vlan_exists(10)
True
>>>
Discovery 6: Custom Python
Libraries
Topology
APIs and Automation Protocols
Designing and Implementing Cisco Network Programmability (NPDESI)
v1.0
Introduction to Network APIs and
Protocols
APIs and Automation Protocols
Evolution of Device Management and Programmability
• Networks were static when protocols such as Simple Network Management
Protocol (SNMP) emerged.
• Managing networks via the Command Line Interface was (and is) the norm.
• Networks have grown to be overly complex.
• Regular Expressions and Expect scripting was the norm for those who did do any
form of automation.
Evolution of Device Management and Programmability
(Cont.)
!
Simple Network Management snmp-server community SJC-COM-1 RO SNMP_RO
Protocol snmp-server community CA-COM-1 RO_TOOLS
• First developed in late 1980s snmp-server community AM-COM-1 RW RW_TOOLS
snmp-server trap-source Loopback0
• Successfully used for snmp-server location AM-USA-CA-SJC
monitoring networks and for snmp-server contact +1 555-555-5555
very basic device modifications snmp-server host [Link] P@ssw0rd
snmp-server host [Link] P@ssw0rd
• Vendors frequently created snmp ifmib ifindex persist
their own MIBs and extensions !
• Not capable of meeting
demands of scale
Evolution of Device Management and Programmability
(Cont.)
Simple Network Management Protocol
• SNMP’s simplicity was a strength when networks were smaller
• v1 and v2 provide very basic and unencrypted security mechanisms
• Not built for real-time communication
• Lack of writable MIBs
• Difficult to replay/rollback configuration
• Lacks libraries for various programming languages
• In 2015, Google announced intent to disable SNMP for monitoring by 2017
Evolution of Device Management and Programmability
(Cont.)
Telnet, SSH, and the Command Line Interface
• Traditional and currently still the primary means of configuring network devices
• Requires human interaction
• Not modular, repeatable, or efficient
• All text based – no common data model among platforms
Evolution of Device Management and Programmability
(Cont.)
History of Network Device Management
Evolution of Device Management and Programmability
(Cont.)
Evolution of Device Management and Programmability
(Cont.)
Model Driven Network Programmability
Model-Driven Programmability Stack
Data Encoding Formats
JSON
• JavaScript Object Notation {
"ins_api": {
• Language independent "type": "cli_show",
"version": "1.2",
• Way of formatting and transmitting data
"sid": "eoc",
that is both human and machine "outputs": {
readable "output": {
"input": "show hostname",
• Sends data objects using name-value
"msg": "Success",
pairs "code": "200",
"body": {
"hostname": "[Link]"
}
}
}
}
}
JSON (Cont.)
• JSON uses name-value pairs, i.e. key- #!/usr/bin/env python
value pairs
import json
• JSON most closely maps to the
dictionary data type in Python if __name__ == "__main__":
• If you understand Python dictionaries, facts = {
'hostname': 'nxosv',
you understand JSON 'os': '7.3',
'location': 'San_Jose'
}
# print facts dictionary
print facts
# print facts as a JSON string
print [Link](facts, indent=4)
# print a specific value of key
print facts['os']
JSON (Cont.)
Script output from previous figure
$ python json_test.py
{'hostname': 'nxosv', 'os': '7.3', 'location': 'San_Jose'}
{
"hostname": "nxosv",
"os": "7.3",
"location": "San_Jose"
}
7.3
JSON (Cont.)
• Be aware of JSON strings that look like dictionaries
• You may need to use loads() and dumps()
$ python json_test2.py
{"hostname": "nxosv", "os": "7.3", "location": "San_Jose"}
<type 'str'>
{
"hostname": "nxosv",
"os": "7.3",
"location": "San_Jose"
}
JSON (Cont.)
Getting familiar with JSON output while on a Nexus switch
nxosv#
JSON (Cont.)
nxosv# show hostname | json
{
"hostname": "[Link]"
}
nxosv#
JSON (Cont.)
nxosv# show vlan brief | json
{
"TABLE_vlanbriefxbrief": {
"ROW_vlanbriefxbrief": [
{
"vlanshowbr-vlanid": 16777216,
"vlanshowbr-vlanid-utf": 1,
"vlanshowbr-vlanname": "default",
"vlanshowbr-vlanstate": "active",
},
{
"vlanshowbr-vlanid": 1677721600,
"vlanshowbr-vlanid-utf": 100,
"vlanshowbr-vlanname": "web_vlan",
}
print response['TABLE_vlanbriefxbrief']['ROW_vlanbriefxbrief'][1]['vlanshowbr-
vlanname']
web_vlan
JSON (Cont.)
JSON schema definition – describes your JSON data
[
{
"id": 1,
"name": "DEFAULT_VLAN",
"state": "up",
},
{
"id": 10,
"name": “web_vlan",
"state": "down",
}
]
JSON (Cont.)
{
"$schema": "[Link]
"title": "VLAN Table",
"type": "array",
"items": {
"title": “VLAN",
"type": "object",
"properties": {
"id": {
"description": "The unique VLAN identifier",
"type": "number“,
"minimum": 1,
"maximum": 4096,
JSON (Cont.)
},
"name": {
"description": "VLAN NAME",
"type": "string"
},
"state": {
"description": "The unique VLAN admin state",
"type": "string",
"enum": ["up", "down"],
},
},
"required": ["id"]
}
}
Discovery 7: Working with JSON
Objects in Python
Topology
XML
• Extensible Markup Language <?xml version="1.0"?>
<ins_api>
• Language independent <type>cli_show</type>
<version>1.2</version>
• Way of formatting and transmitting data
<sid>eoc</sid>
that is both human and machine <outputs>
readable <output>
<body>
• Not as human readable as JSON
<hostname>[Link]</hostname>
</body>
<input>show hostname</input>
<msg>Success</msg>
<code>200</code>
</output>
</outputs>
</ins_api>
XML (Cont.)
<?xml version="1.0"?>
XML vs. HTML <ins_api>
• XML was designed to describe data <type>cli_show</type>
• HTML was designed to display data <version>1.2</version>
<sid>eoc</sid>
• XML tags are created by the author <outputs>
<output>
• HTML tags are predefined in the HTML
<body>
standard
• They are complementary <hostname>[Link]</hostname>
</body>
<input>show hostname</input>
<msg>Success</msg>
<code>200</code>
</output>
</outputs>
</ins_api>
XML (Cont.)
XML Namespaces
• Provide a means to mitigate element name conflicts
• You can also have a default namespace using xmlns=url eliminating need to have
attribute in each tag
XML (Cont.)
<interface>
<name>Ethernet1</name>
<description>Connects to EDGE</description>
<admin_state>up</admin_state>
</interface>
<interface>
<name>Ethernet1</name>
<oper>down</oper>
</interface>
<cfg:interface xmlns:cfg="[Link]
<cfg:name>Ethernet1</cfg:name>
<cfg:description>Connects to EDGE</cfg:description>
<cfg:admin_state>up</cfg:admin_state>
</cfg:interface>
XML (Cont.)
• Non-native Python object
• lxml—one module that simplifies working with XML
#!/usr/bin/env python
if __name__ == "__main__":
xml_as_string = '''
<ins_api>
<type>cli_show</type>
<version>1.2</version>
XML (Cont.)
<sid>eoc</sid>
<outputs>
<output>
<body>
<hostname>[Link]</hostname>
</body>
<input>show hostname</input>
<msg>Success</msg>
<code>200</code>
</output>
</outputs>
</ins_api>
'''
xml_obj = [Link](xml_as_string)
print xml_obj
XML (Cont.)
• Type is an Element object
• Takes name as first (root) object
$ python xml_scripts.py
<Element ins_api at 0x7f08d9f46170>
XML (Cont.)
• find() method finds the first matching sub-element, by tag name or path.
• Note: [Link]() not shown
xml_obj = [Link](xml_as_string)
print xml_obj
data = xml_obj.find('.//hostname')
print [Link]
$ python xml_scripts.py
<Element ins_api at 0x7f6d2e271170>
[Link]
XML (Cont.)
Getting familiar with XML output while on a Nexus switch
*With REST, there may not have even been a XSD/JSD based model. **NETCONF supports XML only
YANG
• Modeling language defined in RFC 6020
• Initially built for NETCONF
• Now also used by RESTCONF
• Models configuration and operational state data
• Provides syntax and semantics
• Utilizes reusable data structures
YANG (Cont.)
Open & Native YANG Models
Model-Driven Programmability
Data Models
• Other platforms have
their own data models:
– Nexus 9000/3000
with NX-API REST
– Application Centric
Infrastructure
Model-Driven Programmability (Cont.)
• Model-based, structured, computer friendly
• Choice of transport, protocol, and encoding
• Model-driven APIs for abstraction and simplification
• Wide standard support while leveraging open source
• Deploy services faster and more simply
• Simplify application development
• Models manage abstractions of the underlying network device data structures
(configurations, state data, and so on).
Model-Driven Programmability (Cont.)
The model is king and the source of truth
module: openconfig-bgp
+--rw bgp!
+--rw global
| +--rw config
| | +--rw as
| | +--rw router-id?
| +--ro state
| | +--ro as
| | +--ro router-id?
| | +--ro total-paths?
| | +--ro total-prefixes?
...
Model-Driven Programmability Stack
REST
• If you understand how to work with a web browser, you understand REST.
• Same HTTP Request Methods and Response Codes are used.
REST (Cont.)
REST (Cont.)
Create, Retrieve, Update, and Delete (CRUD)
REST (Cont.)
HTTP Verbs
REST (Cont.)
{
Examples "l1PhysIf" : {
• GET [Link] "attributes" : {
– Retrieve Network Objects from an ASA "id" : "eth2/5",
"mtu" : "default"
• POST [Link] "speed" : "auto"
– Configure Interface Eth2/5 "adminSt": "down"
}
}
}
REST (Cont.)
Common HTTP Response Codes
Success (2xx) Description
202
204 The server fulfilled request but does not return a body
401 Unauthorized
import requests
import json
from [Link] import HTTPBasicAuth
if __name__ == "__main__":
Layer Example
Messages <rpc>,<rpc-reply>
Layer
Content
Operations
Messages
Transport Protocol
NETCONF (Cont.)
XML Encoding
• Messages are RPCs
• Operation is copy-config
<?xml version="1.0"?>
<rpc message-id="1" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<copy-config>
<source>
<url>[Link]
</source>
<target>
<candidate/>
</target>
</copy-config>
</rpc>
]]>]]>
NETCONF (Cont.)
• Operation is get
• Content is everything else inside the operation
<?xml version="1.0"?>
<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<get>
<filter type="subtree">
<native xmlns="[Link]
<interface>
<GigabitEthernet>
<name>1</name>
</GigabitEthernet>
</interface>
</native>
</filter>
... output truncated....
NETCONF (Cont.)
Utilities & Tools
• On box NETCONF sub system
$ ssh -p 830 cisco@csr1kv -s netconf
NETCONF (Cont.)
ncclient—Python NETCONF client
get_filter = """
<native xmlns="[Link]
<interface>
</interface>
</native>
"""
nc_get_reply = [Link](('subtree', get_filter))
print [Link](nc_get_reply.data_ele, pretty_print=True)
Discovery 9: NETCONF Capabilities
Exchange
Topology
RESTCONF
• Functional sub-set of NETCONF
• Exposes YANG models via a REST API (URL)
• Uses HTTP(S) as transport
• Uses XML or JSON for encoding
• Developed to use HTTP tools and programming
libraries
• Uses common HTTP verbs in REST APIs
RESTCONF (Cont.)
Protocol Operations
Operation Description
Operation Description
• GET [Link]
– Retrieve full running configuration as an object
• GET [Link]
– Retrieve interface specific attributes
• GET [Link]
– Retrieve interface specific attributes for GigabitEthernet1
RESTCONF (Cont.)
RESTCONF Utilities & Tools
Same tools that are used for native REST interfaces are used for
RESTCONF
• Python requests module
• Postman
• Firefox RESTClient
There are no API docs so YANG tools will be used to generate URL and request body
gRPC
• Google RPC provides a general (open
source) RPC framework
• Interface definition in Cisco IOS XR
specifies device operations
• Provides simple client development
• High performance
• Functional subset of NETCONF
• Runs over HTTPS
gRPC (Cont.)
Protocol Operations
Operation Description
The URI ‘/api' is now redirected to rest agent instead of the normal http
daemon
User Credentials
• Privilege Level 3
– Only /api/monitoring GET
requests
• Privilege Level 5
– All GET requests
• Privilege Level 15
– PUT/POST/DELETE
operations
Cisco ASA REST API Documentation and Console
• Located at [Link]
• You can navigate via left pane to view
all sections
• The browser defines what methods are
usable per URI
• Examples are provided for each URI
• Native API Console, similar to Postman
Cisco ASA REST API Documentation and Console (Cont.)
Cisco ASA REST API Documentation Examples
Cisco ASA REST API Console
Request Methods
• GET—Retrieves data from the specified object.
• PUT—Adds the supplied information
• POST—Creates the object with the supplied information.
• DELETE—Deletes the specified object.
• PATCH—Applies partial modifications to the specified object
Authentication
• Basic Authentication
– Username and password
– cisco:cisco
– Converts to base64 encoded string
• X-Auth-Token
– Retrieve token using basic
authentication or API Console methods
Cisco ASA REST API Examples—Postman
show version
Cisco ASA REST API Examples—Postman (Cont.)
Create Network Object
Cisco ASA REST API Examples—Postman (Cont.)
Cisco ASA REST API Examples—Python
import requests
import json
from [Link] import HTTPBasicAuth
[Link].urllib3.disable_warnings()
url = '[Link]
auth = HTTPBasicAuth('cisco', 'cisco')
if response.status_code == 200:
print 'Status Code: ' + str(response.status_code)
parse = [Link]([Link])
print [Link](parse, indent=4)
else:
print 'ERROR Code: ' + str(response.status_code)
Cisco ASA REST API Examples—Python (Cont.)
cisco@cisco:~$ python show_version.py
Status Code: 200
{
"kind": "object#Version",
"currentTimeinSeconds": 1468510065,
"asaVersion": "9.5(2)207",
"totalFlashinMB": 8192,
"deviceType": "ASAv",
"upTimeinSeconds": 802800,
"firewallMode": "Router",
"selfLink": "/api/monitoring/device/version"
}
cisco@cisco:~$
Example Push Config
<import omitted >
url = '[Link]
auth = HTTPBasicAuth('cisco', 'cisco')
payload = {
"host": {
"kind": "IPv4Address",
"value": "[Link]"
},
"kind": "object#NetworkObj",
"name": "web_server08",
"objectId": "web_server08"
}
Example Push Config (Cont.)
headers = { 'content-type': "application/json" }
response = [Link]( url, data=[Link](payload), headers=headers,
verify=False, auth=auth)
if response.status_code == 201:
print 'Status Code: ' + str(response.status_code)
print [Link]
else:
print 'ERROR Code: ' + str(response.status_code)
print [Link]
cisco@cisco:~$ python push_object.py
Status Code: 201
{'Content-length': '0', 'Accept-ranges': 'bytes', 'Vary': 'Accept-Charset, Accept-
Encoding, Accept-Language, Accept', 'Server': 'CiscoASARestApiServer', 'Location':
'[Link] 'Date': 'Thu, 14
Jul 2016 18:08:41 GMT'}
cisco@cisco:~$
Special APIs
CLI Command Executor
• Generic CLI Command
Executor API
– Returns raw text
• Bulk CLI
– Returns list of JSON objects
REST API Debugging
• ASA provides a command to debug the API
• debug rest-api agent
• Syslog messages also generated for given ASA REST API errors
Error Message %ASA-3-342004: Failed to automatically restart the REST API Agent
after 5 unsuccessful attempts. Use the 'no rest-api agent' and 'rest-api agent'
commands to manually restart the [Link]
The REST API Agent has failed to start after many attempts
NX-OS Programmability
APIs and Automation Protocols
Nexus Programmability Overview
Nexus Programmability Features
NX-API CLI—Part 1
What is NX-API CLI?
• REST-like API that enables programmatic
access to Nexus devices
• Improves accessibility of the CLI by making
them available off box
• Supports show commands, configurations, and
Linux Bash
NX-API CLI—Part 1 (Cont.)
NX-API Transport
• Runs on HTTP/S
• CLI commands are encoded into the HTTP/S
POST body
• The request/response format is encoded with
JSON-RPC, JSON, or XML
• NGINX HTTP backend webserver to listen for
HTTP requests
NX-API CLI—Part 1 (Cont.)
nxosv# conf t
Enabling NX-API nxosv(config)# feature nxapi
• Enable the feature via the CLI
• Identify the port being used
• Enable the sandbox nxosv(config)# nxapi https port 8443
#!/usr/bin/env python
import requests
import json
from [Link] import HTTPBasicAuth
if __name__ == "__main__":
RPC <rpc>,<rpc-reply>
* Only supported on Nexus 7K/5K ** Supports actions including rollback on error, stop on error,
continue on error, default operations, and candidate config *** Cisco-only
NETCONF (Cont.)
Requirements
• The client machine must have SSHv2 installed
• The client machine must have an XML management tool that supports NETCONF
over SSH
• Ensure that the SSH is enabled on the Nexus switch
– feature ssh
• No licensing is required
• NETCONF uses port 22 on Nexus
E = ElementMaker()
nc_filter = [Link](
[Link]()
)
print [Link](nc_filter) # view XML obj as string
Required imports:
def remove_namespaces(xml):
for elem in [Link]():
split_tag = [Link]('}')
if len(split_tag) > 1:
[Link] = split_tag[1]
return xml
Examples (GET):
• [Link]
• [Link]
NX-API REST (Cont.)
Device Login and Authentication—Method: POST
• JSON
URL: [Link]
Body:
{
"aaaUser":{
"attributes":{
"name": "cisco",
"pwd": "cisco"
}
}
}
NX-API REST (Cont.)
Device Login and Authentication—Method: POST
• XML
URL: [Link]
Body:
nxosv# python
Copyright (c) 2001-2012 Python Software Foundation; All Rights Reserved
nxosv# >>>
nxosv# >>>
Python on Box (Cont.)
Built-in Python module called cisco
clid(...)
execute a cli command, return name/value pairs
clip(...)
execute a cli command, dont return it, just display it
set_vrf(...)
specify the vrf name for socket operations
Python on Box (Cont.)
CLI Command APIs
Function Example Description Output
Scheduler
feature scheduler
scheduler job name enforcer
source enforce_config.py
scheduler schedule name enforcer
job name enforcer
time start now repeat 00:00:10
Python on Box (Cont.)
Executing standalone scripts and optionally execute with EEM or Scheduler
EEM
restconf
!
username <username> privilege 15 password <password>
!
ip http server
ip http secure-server
!
Request Methods
• GET—Retrieves data from the specified object
• PUT—Replaces full configuration object of tree specified
• POST—Creates the object with the supplied information
• DELETE—Deletes the specified object
• PATCH—Applies partial modifications to the specified object
PATCH is the recommended method as you get started with the API
RESTCONF Examples
Retrieve Entire Running Configuration Modeled as JSON
GET [Link]
GET [Link]
GET [Link]
GET [Link]
GET [Link]
GET [Link]
GET
[Link]
RESTCONF Examples (Cont.)
Retrieve Interface Configurations
RESTCONF Examples (Cont.)
Adding an Interface
POST [Link]
PATCH [Link]
PUT [Link]
RESTCONF Examples (Cont.)
Adding an Interface (Cont.)—Body
{
"ned:Loopback": {
"name": 100,
"ip": {
"address": {
"primary": {
"address": "[Link]",
"mask": "[Link]"
}
}
}
}
}
RESTCONF Examples (Cont.)
Updating an Interface
{
"ned:Loopback": {
"name": 100,
"ip": {
"address": {
"primary": {
"address": "[Link]",
"mask": "[Link]"
}
}
}
}
}
RESTCONF Examples (Cont.)
Updating an Interface (same Body as previously used)
PUT [Link]
Response 204;
RESTCONF Examples (Cont.)
Result from using a PUT
interface Loopback100
ip address [Link] [Link]
RESTCONF Examples (Cont.)
Update Static Routes
PATCH [Link]
RESTCONF Examples (Cont.)
{
"ned:route": {
"ip-route-interface-forwarding-list": [
{
"prefix": "[Link]",
"mask": "[Link]",
"fwd-list": [
{
"fwd": "[Link]"
}
]
### output continues on next slide ###
RESTCONF Examples (Cont.)
### continuation from previous slide ###
},
{
"prefix": "[Link]",
"mask": "[Link]",
"fwd-list": [
{
"fwd": "[Link]"
}
]
}
]
}
}
RESTCONF Examples (Cont.)
csr1kv# show run | inc route (final)
ip route [Link] [Link] [Link]
ip route [Link] [Link] [Link]
ip route [Link] [Link] [Link]
RESTCONF Examples (Cont.)
csr1kv#show run | inc route (new existing)
ip route [Link] [Link] [Link]
ip route [Link] [Link] [Link]
ip route [Link] [Link] [Link]
PUT [Link]
RESTCONF Examples (Cont.)
csr1kv# show run | inc route (final)
ip route [Link] [Link] [Link]
DELETE [Link]
forwarding-list/[Link],[Link]
No Body Required.
RESTCONF Examples (Cont.)
Get Routes (Python)
#!/usr/bin/env python
import requests
import json
from [Link] import HTTPBasicAuth
[Link].urllib3.disable_warnings()
if __name__ == "__main__":
"prefix": "[Link]",
"mask": "[Link]"
},
{
"fwd-list": [
{
"fwd": "[Link]"
}
],
"prefix": "[Link]",
"mask": "[Link]"
}
],
"static": {}
}
}
IOS XE NETCONF API
NETCONF* on the IOS XE platform is based off XML representation of YANG
models.
Layer Example
Transport SSHv2
Protocol
RPC <rpc>,<rpc-reply>
** Supports operations including rollback on error, stop on error, continue on error, default operations,
merge (default), replace, create, delete, remove. May vary per hardware platform.
IOS XE NETCONF API (Cont.)
Enabling NETCONF
• Enable NETCONF
• User with Privilege 15
• Optionally enable operational data
netconf-yang
!
username <username> privilege 15 password <password>
!
NETCONF
Requirements
• The client machine must have SSHv2 installed
• The client machine must have an XML management tool that supports NETCONF
over SSH
• Ensure that the SSH is enabled on the router
– Ports 830
if __name__ == "__main__":
get_filter = """
<native xmlns="[Link]
<interface>
<GigabitEthernet>
<name>1</name>
</GigabitEthernet>
</interface>
</native>
"""
</address>
</ip>
</Loopback>
</interface>
</native>
</config>
"""
RPC <rpc>,<rpc-reply>
** Supports operations including rollback on error, stop on error, continue on error, default operations,
merge (default), replace, create, delete, remove. May vary per hardware platform.
IOS XR NETCONF APIs (Cont.)
!
Enabling NETCONF ssh server netconf port 830
• Configure port to use for NETCONF netconf-yang agent
• Enable NETCONF over SSH ssh
username <username> privilege 15
• User with Privilege 15 password <password>
!
• Optionally enable local TTY for access to
netconf agent tty
NETCONF sub system
NETCONF
Requirements
• The client machine must have SSHv2 installed
• The client machine must have an XML management tool that supports NETCONF
over SSH
• Ensure that an SSH is enabled on the router
<capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
<capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>
<capability>[Link]
cdp-cfg&revision=2015-01-07</capability>
<capability>[Link]
05</capability>
<200+ more omitted for brevity>
</capabilities>
<session-id>2453920142</session-id>
</hello>]]>]]>
NETCONF Python Scripts
#!/usr/bin/env python
if __name__ == "__main__":
nc_filter = """
<interface-configurations xmlns="[Link]
XR-ifmgr-cfg">
<interface-configuration>
<interface-name>MgmtEth0/0/CPU0/0</interface-name>
</interface-configuration>
</interface-configurations>
"""
nc_filter = """
<config>
<interface-configurations xmlns="[Link]
ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>Loopback100</interface-name>
<interface-virtual/>
</interface-configuration>
</interface-configurations>
</config>
"""
nc_reply = device.edit_config(target='candidate', config=nc_filter)
[Link]()
NETCONF Python Scripts (Cont.)
OpenConfig Data Model
nc_filter = """
<config>
<bgp xmlns="[Link]
<global>
<config>
<as>65512</as>
</config>
</global>
</bgp>
</config>
"""
nc_reply = device.edit_config(target='candidate', config=nc_filter)
[Link]()
Securing the Management Plane
APIs and Automation Protocols
Management Plane
Network Programmability Fundamentals
• The management plane consists of functions that achieve the management goals
of the network
• Includes management sessions that use SSH, SNMP NetFlow, and all APIs
including NETCONF, REST APIs, RESTCONF, gRPC, etc.
• When you consider the security of a network device, it is critical that the
management plane is protected
Management Plane (Cont.)
With more protocols and APIs being implemented on network devices, more
attention is required to ensure unused protocols and APIs are disabled
Access Control Lists
• Prevent unauthorized direct communication to network devices
• Permit connections among trusted hosts or networks that require communication
with network infrastructure devices according to established security policies
• Required communication typically consists of management- and control-plane
traffic such as external BGP, SSH, SNMP, and now specific APIs that may use
various ports and protocols
• After the required connections have been permitted, all other traffic to the
infrastructure is explicitly denied
• Applied in the ingress direction on all interfaces for which an IP address has been
configured
Access Control Lists (Cont.)
• ACLs should be applied on all ip access−list MGMT_IN
!−−− Permit required host connections to
interfaces with IP addresses limiting network management segment
management access permit tcp host <−mgmt−> any eq 22
• Use dedicated out of band management permit tcp host <−mgmt-> any eq 80
permit tcp host <−mgmt−> any eq 443
networks permit udp host <−mgmt−> any eq 161
interface mgmt0
ip access-group MGMT_IN in
Data Models
Designing and Implementing Cisco Network Programmability (NPDESI)
v1.0
YANG Data Modeling
Data Models
YANG Overview
• Data modeling language
defined in RFC 6020
• Analogous to XML schema and
SMI for SNMP
• Models configuration,
operational, and RPC data
• Provides semantics to better
define data
• Extensible and modular
– Constraints (i.e., “MUSTs”)
– Reusable structures
– Built-in and derived types
• Protocol independent
YANG Overview (Cont.)
YANG modules from standard
organizations such as the
IETF, open source, such as
Open Daylight, or vendor-
specific modules.
• [Link]
yang
• [Link]
ublic
YANG Module
YANG Module Contents
YANG Module Header
module acme-module {
namespace "[Link] URI
prefix acme;
import "ietf-yang-types" {
prefix yang;
}
include "acme-system";
NETCONF XML:
<host-name>[Link]</host-name>
YANG Leaf Statement (Cont.)
Data Constraints
• config
– Whether this leaf is a configurable value ("true"), or operational value ("false"). Inherited
from parent container if not specified. Default is "true."
• default
– Specifies default value for this leaf. Implies that leaf is optional.
• mandatory
– Whether the leaf is mandatory ("true"), or optional ("false").
• must
– Xpath constraint that will be enforced for this leaf.
• type
– The data type (range and so on) of this leaf.
YANG Leaf-List Statement
leaf-list domain-search {
Leaf-list Statement type string;
• One value ordered-by user;
• No children description “List of domain names to search";
}
• Multiple instances
NETCONF XML:
<domain-search>[Link]</domain-search>
<domain-search>[Link]</domain-search>
YANG Leaf-List Statement (Cont.)
leaf leaf-list
revision 2016-08-09 {
description "Initial revision.";
}
Putting Things Together (Cont.)
container system {
leaf host-name {
type string;
description "Hostname for this system";
}
leaf-list domain-search {
type string;
description "List of domain names to search";
}
container login {
leaf message {
type string;
description "Message given at start of login session";
}
list user {
key "name";
leaf name {
type string;
}
leaf full-name {
type string;
}
leaf class {
type string;
}
}
}
}
}
YANG Types
Base Types Type Description
• Most YANG elements have a int8/16/32/64 Integer
data type
uint8/16/32/64 Unsigned integer
• Type may be a base type or
derived type: decimal64 Non-integer
...and more
YANG Types (Cont.)
Common YANG Types counter32/64 ipv4-address
• Commonly used YANG types gauge32/64 ipv6-address
defined in RFC 6021
object-identifier ip-prefix
• Use:import “ietf-yang-types”
{ prefix yang; } to reference date-and-time ipv4-prefix
these types as e.g. type timeticks ipv6-prefix
yang:counter64;
timestamp domain-name
phys-address uri
ip-version mac-address
flow-label bridgeid
port-number vlanid
typedef percent {
type uint16 {
range "0 .. 100";
}
description "Percentage";
}
leaf completed {
type percent;
}
YANG Typedef Statement (Cont.)
Typedef & Union Statements
• Define a new type that is either an IPv4 or IPv6 address
typedef ip-address {
type union {
type ipv4-address;
type ipv6-address;
}
}
YANG Choice Statement
Each alternative may consist of multiple definitions, either as a named or
anonymous group
choice route-distinguisher {
case ip-address-based {
leaf ip-address {
type ipv4-address;
}
leaf ip-address-number {
type uint16;
}
}
case asn32-based {
leaf asn32 {
type uint32;
}
leaf two-byte-number {
type uint16;
}
}
}
<asn32>12356789</asn32>
<two-byte-number>2468</two-byte-number>
YANG Grouping Statement
grouping target {
leaf address {
type inet:ip-address;
description "Target IP";
}
leaf port {
type inet:port-number;
description "Target port number";
}
}
container peer {
container destination {
uses target;
}
}
YANG Grouping Statement (Cont.)
YANG Grouping Statement (Cont.)
grouping endpoint {
leaf address {
type ip-address;
}
leaf port {
type port-number;
}
}
container connection {
container source {
uses endpoint {
refine port {
default 80;
}
}
}
container destination {
uses endpoint {
refine port {
default 80;
}
}
}
}
YANG Grouping Statement (Cont.)
<connection>
<source>
<address>[Link]</address>
<port>8080</port>
</source>
<destination>
<address>[Link]</address>
<port>8080</port>
</destination>
</connection>
YANG Miscellaneous Statements
• Leafref list user {
key uid;
– Make an element reference in one of the rows in a unique name;
list, set the element type to leafref. …
• Unique
– Fields can be declared unique (example to the
right).
• Must
– Restricts valid values by XPath expression.
• When
– Used to check for particular conditions.
YANG RPC Statement
Administrative actions with input and output parameters ...and side effects.
YANG RPC Statement (Cont.)
rpc activate-software-image {
input {
leaf image {
type binary;
}
}
output {
leaf status {
type string;
}
}
}
YANG Imports and Includes
YANG Modules and Submodules
module acme-module {
namespace “…”;
prefix acme;
import ”ietf-yang-types" {
prefix yang;
}
include "acme-system";
submodule acme-system {
belongs-to acme-module {
prefix acme;
}
import ”ietf-yang-types" {
prefix yang;
}
container system {
…
}
}
YANG Model Examples
container community-sets {
description “Container for community sets";
list community-set {
key community-set-name;
description "Definitions for community sets";
leaf community-set-name {
type string;
description "name of the community set";
}
leaf-list community-member {
type string {
pattern '([0-9]+:[0-9]+)';
}
description "members of the community set";
}
}
}
XML
<community-sets>
<community-set>
<community-set-name>CSET1</community-set-name>
<community-member>65172:1</community-member>
<community-member>65172:2</community-member>
<community-member>65172:3</community-member>
</community-set>
<community-set>
<community-set-name>CSET10</community-set-name>
<community-member>65172:10</community-member>
<community-member>65172:20</community-member>
<community-member>65172:30</community-member>
</community-set>
</community-sets>
JSON
{ "community-sets": {
"community-set": [
{ "community-set-name": "CSET1",
"community-member": [
"65172:1",
"65172:2",
"65172:3" ]
},
{ "community-set-name": "CSET10",
"community-member": [
"65172:10",
"65172:20",
"65172:30" ]
}
]
}
}
CLI
community-set CSET1
65172:1,
65172:2,
65172:3
end-set
!
community-set CSET10
65172:10,
65172:20,
65172:30
end-set
!
YANG Tools
Data Models
YANG Tools
• YANG Validator
• pyang
• ydk
• YANG Explorer
YANG Validator
YANG Validator (Cont.)
Discovery 12: Validating YANG
Models Using Yang Validator
Topology
pyang
$ pyang -f tree -p /path/to/models <yang-file>
$ pyang -f tree -p yang/standard/ietf/RFC yang/standard/ietf/RFC/ietf-
[Link]
module: ietf-interfaces
+--rw interfaces
| +--rw interface* [name]
| +--rw name string
| +--rw description? string
| +--rw type identityref
| +--rw enabled? boolean
| +--rw link-up-down-trap-enable? enumeration {if-mib}?
+--ro interfaces-state
+--ro interface* [name]
+--ro name string
+--ro type identityref
+--ro admin-status enumeration {if-mib}?
+--ro oper-status enumeration
pyang (Cont.)
$ pyang -f sample-xml-skeleton -p /path/to/models <yang-file>
cisco@cisco:~$ pyang -p tools/ tools/oc-models/release/models/vlan/openconfig-
[Link] -f sample-xml-skeleton
<?xml version='1.0' encoding='UTF-8'?>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><vlans
xmlns="[Link] /><config><vlan-id /><name
/></config><state><vlan-id /><name /></state><members><member><interface-
ref><state><interface /><subinterface /></state></interface-
ref></member></members></vlan></vlans></data>
cisco@cisco:~$
pyang (Cont.)
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<vlans xmlns="[Link]
<vlan>
<vlan-id />
<config>
<vlan-id />
<name />
</config>
<state>
<vlan-id />
<name />
</state>
<members>
<member>
<interface-ref>
<state>
<interface />
<subinterface />
</state>
</interface-ref>
</member>
</members>
</vlan>
</vlans>
</data>
pyang (Cont.)
• JavaScript Tree Output really useful
• Use pyang –f jstree –p <path-to-models> <[Link]> >/tmp/[Link]
pyang (Cont.)
$ pyang -p /path/to/models <yang-file> --lint
• Network Discovery
• Viewing Host and Device Inventories
• Visualizing the Network Topology
• Configuring Backup and Restore
• Managing Users
Starting Network Device Discovery
How APIC-EM Network Discovery Works
Discovery 17: Network Discovery
Configuration
Topology
Performing APIC-EM Tasks
Viewing Device Inventory
Performing APIC-EM Tasks (Cont.)
Deleting a Device
Performing APIC-EM Tasks (Cont.)
Viewing Host Inventory
Performing APIC-EM Tasks (Cont.)
Network Topology Visualization
Performing APIC-EM Tasks (Cont.)
Backing up and Restoring the Database
Performing APIC-EM Tasks (Cont.)
Users and RBAC Roles and Privileges
Discovery 18: APIC-EM Network
Discovery and RBAC
Topology
APIC-EM Applications
APIC-EM Applications (Cont.)
Network Plug-and-Play
APIC-EM Applications (Cont.)
Network Plug-and-Play Components
APIC-EM Applications (Cont.)
Cisco SD-WAN
APIC-EM Applications (Cont.)
Intelligent Wide Area Networks (IWAN)
APIC-EM Applications (Cont.)
IWAN Dashboard
APIC-EM Applications (Cont.)
Path Trace Application
APIC-EM Applications (Cont.)
The EasyQoS Solution
APIC-EM APIs
Using Postman with APIC-EM
Using Postman with APIC-EM (Cont.)
Using Postman with APIC-EM (Cont.)
Using Postman with APIC-EM (Cont.)
Using Python with APIC-EM
Using Postman with APIC-EM (Cont.)
The “uniq” APIC-EM Python Library
Discovery 19: Consuming the APIC-
EM API
Topology
Cisco Application Centric
Infrastructure
SDN Controllers
ACI Overview
Two modes of operation to support different operational models
ACI Overview (Cont.)
9500 Series 9300 Series
• 9504 • 9332PQ
• 9508 • 9372PX / 9372TX
• 9516 • 9396PX / 9396TX
• 93128TX
• 9336PQ (ACI Spine Switch)
ACI Overview (Cont.)
ACI Fabric
ACI Overview (Cont.)
Overloaded Network Constructs
ACI Overview (Cont.)
Application Language Barriers
• Developer and infrastructure teams must translate between disparate languages.
ACI Overview (Cont.)
What is an Application to the Network?
• A collection of all the Application's End Points
• The Application's L2 — L7 Network Policies
• The Relationship between these End Points and their Policies
ACI Overview (Cont.)
Logical Network Provisioning of Stateless Hardware
ACI Overview (Cont.)
ACI – Key Architectural Benefits
• Decoupling of end point identity, location, and
associated policy all of which are independent
from the underlying point of device attachment.
• Distributed Layer 3 gateway
• Any IP address anywhere
• Full normalization of the ingress encapsulation
mechanism used, 802.1Q VLAN, IETF VXLAN,
IETF NVGRE.
• Service insertion and redirection
• Removal of flooding requirements for IP control
plane (ARP/GARP)
ACI Overview (Cont.)
Common Policy and Operations Framework
ACI Overview (Cont.)
Fabric Initialization & Maintenance
ACI Overview (Cont.)
Introduction to APIC GUI
Discovery 20: ACI Fabric Discovery
Topology
Discovery 21: Creating Objects with
APIC GUI
Topology
ACI Object Model
{
JSON "aaaUser":{
• URL: [Link] "attributes":{
• Body: "name":"admin",
"pwd":”cisco123"
}
}
}
APIC REST API (Cont.)
XML
• URL: [Link]
• Method: POST
• Body:
• Event-Driven Notifications
• Opens Web Socket to APIC
• Listens for Changes to a Given Object
APIC REST API (Cont.)
Discovery 23: Using API Inspector
Topology
Using Postman REST Client
Logging In
Using Postman REST Client (Cont.)
Get Object by Distinguished Name
Using Postman REST Client (Cont.)
Visore/Postman Property Comparison
Using Postman REST Client (Cont.)
Creating Objects
Using Postman REST Client (Cont.)
Obtaining the URI
Using Postman REST Client (Cont.)
Native Python
import requests
import json
def get_cookies(apic):
username = 'admin'
password = 'cisco123'
url = apic + '/api/[Link]'
auth = dict(aaaUser=dict(attributes=dict(name=username, pwd=password)))
authenticate = [Link](url, data=[Link](auth), verify=False)
return [Link]
if __name__ == "__main__":
protocol = 'http'
host = 'apic'
apic = '{0}://{1}'.format(protocol, host)
cookies = get_cookies(apic)
Using Postman REST Client (Cont.)
Native Python — Example 2 – Get Subnets
rsp = get_subnets(apic,cookies)
# rsp is a unicode string
rsp_dict = [Link](rsp)
subnets = rsp_dict['imdata']
Using Postman REST Client (Cont.)
{"totalCount":"3","imdata":[{"fvSubnet":{"attributes":{"childAction":"","ctrl":"qu
erier","descr":"","dn":"uni/tn-infra/BD-default/subnet-[[Link]/27]",
"ip":"[Link]/27","lcOwn":"local","modTs":"2016-08-
21T11:47:48.321+00:00","monPolDn":"uni/tn-common/monepg-default",
"name":"","preferred":"no","scope":"private","status":"","uid":"0","virtual":"no"}
}},
{"fvSubnet":{"attributes":{"childAction":"","ctrl":"","descr":"","dn":"uni/tn-
DrPepper/BD-Web/subnet-[[Link]/24]","ip":"[Link]/24",
"lcOwn":"local","modTs":"2016-08-21T11:59:30.416+00:00","monPolDn":"uni/tn-
common/monepg-defaul
t","name":"[Link]:24","preferred":"no","scope":"private","status":"","uid":"153
74","virtual":"no"}}},{"fvSubnet":
{"attributes":{"childAction":"","ctrl":"","descr":"","dn":"uni/tn-DrPepper/BD-
DB/subnet-[[Link]/24]","ip":"10.20.
2.1/24","lcOwn":"local","modTs":"2016-08-
21T12:00:47.046+00:00","monPolDn":"uni/tn-common/monepg-default",
"name":"[Link]:24","preferred":"no","scope":"private","status":"","uid":"15374"
,"virtual":"no"}}}]}
Using Postman REST Client (Cont.)
Native Python — Example 2 – Accessing Return Elements
• Attributes are stored as the value of the imdata key
• Value is a list of dictionaries with each Subnet being a dictionary
• Usually more efficient as less number of MOs need to be serialized and returned
• Filter the response returned using the supplied condition:
– Syntax: [Link]
– Returns only the MOs which satisfies the condition
Using Postman REST Client (Cont.)
Native Python — Example 3 – Using Query Target
• Use API Inspector and Visore to determine correct filter
• Example shows how to query for one or more classes when using DN
mo = [Link]('uni/tn-{0}'.format(name))
return mo
if __name__ == "__main__":
username = 'admin'
password = 'Cisco123'
protocol = 'https'
host = 'apic'
tenants = [Link]('fvTenant')
return tenants
tenant = 'Finance'
ap = 'Finance-3Tier-App'
tenant_mo = [Link]('uni/tn-{0}'.format(tenant))
config_req = ConfigRequest()
config_req.addMo(ap_mo)
[Link](config_req)
Arya
• GUI creates REST API calls
• API Inspector shows REST API calls
• ARYA ([Link]) creates code from REST
(objects)
• Auto-generate Python code
– Uses Cobra
Arya (Cont.)
Workflow
Arya (Cont.)
Optionally get the XML/JSON objects by using API Inspector
{"fvTenant":{"attributes":{"dn":"uni/tn-TENANT6","name":"TENANT6","descr":"sample-
test-for-cisco","rn":"tn-TENANT6","status":"created"},"children":[]}}
Arya (Cont.)
# PORTION OF WHAT IS GENERATED
# list of packages that should be imported for this code to work
import [Link]
import [Link]
import [Link]
import [Link]
import [Link]
from [Link] import toXMLStr
$ [Link] -h
usage: Code generator for APIC cobra SDK [-h] [-f FILEIN] [-s] [-d SOURCEDIR]
[-t TARGETDIR] [-i IP] [-u USERNAME]
[-p PASSWORD] [-nc]
optional arguments:
-h, --help show this help message and exit
-f FILEIN, --filein FILEIN
Document containing post to be sent to REST API
-s, --stdin Parse input from stdin, for use as a filter, e.g., cat
[Link] | [Link] -s
-d SOURCEDIR, --sourcedir SOURCEDIR
Specify a source directory containing ACI object files
you want to convert to python.
### output continues on the next slide ###
Arya (Cont.)
### output continuation from the previous slide ###
[Link]:
<polUni>
<fvTenant name="Tenant_7">
<fvBD name="T7_BD">
<fvSubnet subnet="[Link]/24">
</fvSubnet>
</fvBD>
</fvTenant>
</polUni>
$ [Link] -f [Link]
Arya (Cont.)
$ [Link] -f [Link] -i apic -u admin -p cisco123 -nc
Arya (Cont.)
Example 2 - Create App Pro, EPG, Associations
{
"fvAp": {
"attributes": {
"dn": "uni/tn-Finance/ap-Finance-3Tier-App",
"name": "Finance-3Tier-App",
"rn": "ap-Finance-3Tier-App",
"status": "created"
},
"children": [
{
• GitHub
• Pre-installed OVA
• Docker
ACI Toolkit (Cont.)
Toolkit Object Model
# Login to APIC
[Link]()
# Push configuration
resp = session.push_to_apic(tenant.get_url(), tenant.get_json())
ACI Toolkit (Cont.)
Example 2 – Get Interface Info
</CHASSIS_INFO>
<CHASSIS_INFO sourceChassis="Spine2" type="n9k">
<LINK_INFO sourcePort="eth5/2" destChassis="Leaf2"
destPort="eth1/50"/>
<LINK_INFO sourcePort="eth5/1" destChassis="Leaf1"
destPort="eth1/50"/>
</CHASSIS_INFO>
</DATA_CENTER>
</CISCO_NETWORK_TYPES>
ACI Toolkit Applications — Event Feeds
• ACI Events to Atom Feeds
• Subscribes to APIC Managed Objects and records any updates to the objects over
a web socket connection
• Monitor changes & Display updates in a reader of your choice!
– Monitoring tools readers, or individual, etc.
ACI Toolkit Applications — Event Feeds (Cont.)
• Start the eventfeeds application
• Available feeds are accessible via web
• Subscribe
git add <file/dir> Start tracking files and add them to the staging area
git pull <params> Patch and merge changes from remote repository (combines git fetch
and git merge)
git clone <params> Copy another (remote) project to your local machine
Git Workflow
$ git init
$ git config --global [Link] "John Smith"
$ git config --global [Link] john_smith@[Link]
$ git add [Link]
$ git commit –m "initial commit"
if access_lists_to_fix:
print "{0} ACLs to be fixed:".format(len(access_lists_to_fix))
print [Link](access_lists_to_fix, indent=4)
81 ACLs to be fixed:
[
"copp-system-p-acl-bgp",
"copp-system-p-acl-bgp6",
"copp-system-p-acl-cts",
"copp-system-p-acl-dhcp",
"copp-system-p-acl-dhcp-relay-response",
"copp-system-p-acl-dhcp6",
Network Testing (Cont.)
Test Automation
• The role automation can have on an organization is much larger than configuration
management and deploying configurations faster.
• Keep in mind style, syntax, reachability, ephermal data, configuration, and
compliance checks.
Unit Tests
• Units tests are a practice of testing specific functions and features
• Verify code and an application is working as expected
• A test case is the smallest unit of testing
• Ensure that changes don’t break existing code base
• Python test framework: unittest
Unit Tests (Cont.)
• Test specific portions of an application and library
• Example: ensure subnets work appropriately in the Cisco ACI Toolkit Python library
• Tests are meant to be small and concrete
• Unittests can be run offline – focus is on code
Unit Tests (Cont.)
def test_add_2_valid_subnets(self):
"""
Test adding 2 subnets to the BD
"""
bd, sub1 = self.create_bd_with_subnet()
• Unittests are also for integration testing — verifying that the code is performing as
expected communicating with other systems.
• From a network perspective, this verification is helpful for configuration validation
and ephemerical state validation.
Unit Tests (Cont.)
Test Hostname
@staticmethod
def get_output(commands):
auth = HTTPBasicAuth('cisco', 'cisco')
headers = {
'Content-Type': 'application/json'
}
payload = {
"ins_api": {
"version": "1.0",
"type": "cli_show",
"chunk": "0",
"sid": "1",
"input": commands,
"output_format": "json"
}
}
url = '[Link]
response = [Link](
url, data=[Link](payload), headers=headers, auth=auth)
rx_object = [Link]([Link])
return rx_object
Unit Tests (Cont.)
def test_hostname(self):
expected_hostname = '[Link]'
commands = ['show hostname']
rx_object = self.get_output(commands)
output = rx_object['ins_api']['outputs']['output']['body']
hostname = output['hostname']
[Link](expected_hostname, hostname)
if __name__ == '__main__':
[Link]()
Unit Tests (Cont.)
Automated Testing Workflow using Unit tests
[iosxr]
xrv
[iosxe]
csr1kv
Ansible Overview (Cont.)
Playbook
• A file that contains the
instruction set on tasks that will
be automated, orchestrated,
and the like.
• Uses [Link] as file name for
“main” playbook
• YAML format
Ansible Overview (Cont.)
Plays
• Playbook that is comprised of
plays
• Plays begin with a hyphen “-” at
leftmost position
• name:
– Arbitrary description of the play
that will display on the screen
when the play is executed
• hosts:
– Required and denotes which
hosts or machines the play will
be executed against
Ansible Overview (Cont.)
Tasks
• Individual tasks make up a Play
• Tasks are executed on the
hosts that are defined in the
play definition
• Within each task:
– name:
• Optional, arbitrary description
of the task that will display on
the screen when the task is
executed
– ios_command:
• Specific tasks that perform a
single function
Ansible Overview (Cont.)
Modules & Variables
• Modules automate specific
tasks
– Apply configurations
– Configure VLANs
Ansible Overview (Cont.)
Module Documentation – ios_command
• ios_command - Run arbitrary commands on ios devices
• Synopsis – Sends arbitrary commands to an ios node and returns the results read
from the device
parameter Required Comments
commands Yes List of commands to send to the remote ios device over the configured
provider.
interval No Configures the interval in seconds to wait between retries of the
command.
retries No Specifies the number of retries a command should by tried before it is
considered failed.
waitfor No List of conditions to evaluate against the output of the command.
• *_command
• *_config
Ansible Base Modules (Cont.)
- ios_command:
ios_command commands:
• Run commands on Cisco IOS - show version
• Params username: "{{ username }}"
password: "{{ password }}"
– commands host: "{{ inventory_hostname }}"
– wait_for
– retries
Playbook:
– interval test-ios_command.yml
Ansible Base Modules (Cont.)
$ ansible-playbook -i hosts test-ios_command.yml -v
PLAY [testing ios_command] *****************************************************
- assert:
that:
- "'7.3(1)D1(1)' in output['stdout'][0]"
Ansible Base Modules (Cont.)
• Register - name: Ensure proper OS version is present on
device
– Stores task results into a hosts: nxos
variable connection: local
• Debug tasks:
– Prints variables - name: show version
nxos_command:
commands:
- show version
username: "{{ username }}"
password: "{{ password }}"
host: "{{ inventory_hostname }}"
register: output
- debug: var=output
Ansible Base Modules (Cont.)
$ ansible-playbook -i hosts test-nxos_command.yml
– state
NXOS Features Modules (Cont.)
- name: configure ethernet2/1 ip
nxos_ip_interface address
• Manages Layer 3 attributes of nxos_ip_interface:
interfaces interface: ethernet2/1
addr: "[Link]"
mask: 30
state: present
username: "{{ username }}"
password: "{{ password }}"
host: "{{ inventory_hostname }}"
NXOS Features Modules (Cont.)
Example: Assigning Native VLAN on NXOS
• Ensure VLAN 113 exists
– nxos_vlan
• Ensure Ethernet2/1 is L2
– nxos_interface
• Configure Access Port
– nxos_switchport
NXOS Features Modules (Cont.)
- name: ENSURE VLAN EXISTS
nxos_vlan:
vlan_id=113 - name: ENSURE INTERFACE IS CONFIGURED FOR V113
name=native nxos_switchport:
vlan_state=active interface=eth2/1
host={{ mode=access
inventory_hostname }} access_vlan=113
username={{ username }} host={{ inventory_hostname }}
password={{ password }} username={{ username }}
password={{ password }}
- name: ENSURE INTERFACE IS
L2
nxos_interface:
interface=eth2/1
mode=layer2
host={{
inventory_hostname }}
username={{ username }}
password={{ password }}
NXOS Features Modules (Cont.)
Example: Assigning Native VLAN on NXOS
• Run the playbook
$ ansible-playbook -i hosts test_nxos.yml