Network Programmability
using Netmiko for those New
to Python
Rick Graziani
Cabrillo College
University of California Santa Cruz
2023
Agenda • Why Netmiko? (quick)
Python • Netmiko's 3 basic commands
• Keeping code and terms simple for those
(methods)
NEW to Python
• Many options and variations including use
- Import Netmiko
of dictionaries, functions, etc. - Connect to your device
- Contact me offline or see coming - Disconnect from your device
YouTube channel and code • Sending an IOS command with:
• Just using: print() and a variable
- send_command()
• One 'for loop' to show accessing multiple
devices - send_command_expect()
At the end: • 'copy run start' with save_config()
• Access to my Python code for Netmiko and • Configuring your IOS device with:
TCP/IP (code and videos)
- send_command()
- send_command_set()
- send_command_from_file()
• Summary
Cisco IT students Besides DevNet…
Future of networking
Software
Developers
Network
Programmability
Cisco Routing and Automation
and Switching Netmiko NETCONF, RESTCONF,
(and others) YANG, APIs
• Is DevNet the only or best Python
option to learn network
CCNA or Net Essentials or
automation?
Cisco IOS
• I wouldNet Basics
like to learn coding but
I'm not sure how it relates to
networking?
Netmiko offers a higher-
level abstraction with
features tailored
specifically for network
automation.
Netmiko or NAPALM IOS commands NETCONF RPC (SSH) REST API (Postman)
IOS commands Generic commands +Inventory (Ansible) + Inventory
Netmiko NAPALM NORNIR Ansible NETCONF RESTCONF
(Start Here) (Intermediate) (Advanced) (YAML, Python) (XML) (JSON/XML)
YANG
Structured Data
JSON-YAML-XML
Python Python Python
Cisco IOS or XR/XE/NX-OS Cisco XR/XE/NX-OS
+ SSH (Telnet) + API support
Why Netmiko?
1. Students with minimum knowledge of
Python get to do some cool coding!
2. Students with even a very limited
knowledge of IOS, get to "program"
routers/switches!
- Uses Cisco IOS commands
(advantage for beginner) SSH
3. Minimal Requirements: Requires only Telnet
Telnet or SSH connectivity
As you grow with IOS or as you grow with
Python you can do more network
automation with Netmiko (developed by Kirk
“Do not underestimate the utility of the
SSH Netmiko library, as it’s proven useful
in providing a smooth transition from
traditional network CLI management to
network automation, and it’s heavily
Ivan Pepelnjak
used and developed”
"Netmiko is a Python library built on top
of Paramiko that addresses these
problems. If you want to connect to a wide
variety of network devices without losing
your sanity Netmiko is your best bet."
Getting Started
1. Install Python
2. Install Netmiko
MacOS% pip3 install netmiko
3. Verify SSH/Telnet connectivity to device
ME
Setup
• Routers and switches
preconfigured
• IPv4 static routes for
reachability
• Can SSH to any device
Can you figure out what this does?
# Our first Netmiko program
It really is that easy!
import netmiko
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios',
username='admin',
password='cisco’)
print(connection.send_command('show ip interface brief'))
connection.disconnect() Note: For telnet, use:
device_type='cisco_ios_telnet'
netmiko_1a_
# Required: Imports the Netmiko library
import netmiko 1
# Required: Netmiko ConnectHandler handles the SSH connection using specified 'arguments'
# The connection object (variable) represents the connection to the specified device
# Allows you to interact with it using various Netmiko methods like the send_command.
Device IP address
connection = netmiko.ConnectHandler(ip='192.168.1.1',
2
device_type='cisco_ios',
Device OS
username='admin', SSH username
password='cisco’)
&password
This is the basic framework.
# Using the connection object, the send_command method sends a command
Just add Netmiko/IOS commands!
# to a network device and retrieves the corresponding output.
print(connection.send_command('show ip interface brief’))
# Required: The disconnect method in Netmiko is used to close the SSH connection
3
# to a network device, ensuring proper cleanup
connection.disconnect()
# Imports the Netmiko library
send_command() Another option
import netmiko
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios',
username='admin',
password='cisco’)
# Previous command: Prints the output (if any) from the command
# print(connection.send_command('show ip interface brief’))
# Send output to a variable (output) and then print the (string) variable
output = connection.send_command('show ip interface brief’)
print(output)
Same result when using send_command() but differences with other methods
connection.disconnect() netmiko_1a_
netmiko_1a_
Let’s try it! send_command()
send_command_expect() When IOS expects input/confirmation
import netmiko
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios',
username='admin',
password='cisco’)
# send_command_expect() method is used to specify a string that Netmiko should
# expect to see in the command's output before considering the command as complete.
# Used for confirmation and automatically responds to prompt
# expect_string should be unique enough to identify the point at which the script
# needs to take action, ex. Destination filename [startup-config]?
print(connection.send_command_expect('copy running-config startup-config',
expect_string='Destination filename'))
connection.disconnect()
Let’s try it! send_command_expect()
Added some print commands for readability
Insignificant Python
Change:
• Assigned IPv4
address of the
device to a string
variable so I can
print the IPv4
address later.
save_config() Same as 'copy run start'
import netmiko
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios',
username='admin',
password='cisco')
print("\n")
print("Save running-config to startup-config...")
connection.save_config()
print("Success!")
print("\n")
print("show startup-config...")
print(connection.send_command('show startup-config'))
MacOS% Output (Backup)
Save running-config to startup-config...
Success!
show startup-config...
Using 1942 out of 262136 bytes
!
version 15.4
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname R2
!
boot-start-marker
boot-end-marker
!
<output omitted>
MacOS%
So far…
import netmiko
show commands,
connection = netmiko.ConnectHandler(ip='192.168.1.1',
saving config
device_type='cisco_ios',
username='admin',
password='cisco')
# Secret password not required (enable secret class) for these commands
# However, there are ways to 'secure' these commands within Cisco IOS
print(connection.send_command('User Exec IOS Command'))
print(connection.send_command('show running-config'))
print(connection.send_command_expect('copy running-config startup-config',
expect_string='Destination filename'))
connection.save_config()
Related code you can download from Rick…
• Do an extended ping with send_command_expect()
• Display the prompt with find_prompt()
connection.disconnect()
send_command() Using config mode to configure device
import netmiko
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios',
username='admin',
password='cisco',
secret='class') # Enable password
# send_command() for configuration is similar to CLI - secret password is required
connection.enable() # Privileged exec mode
connection.config_mode() # Global config mode
connection.send_command('access-list 1 permit any') # Global configuration command
connection.exit_config_mode() # Exit global config mode
print(connection.send_command('show running-config | section access-list 1')) # Verify
connection.disconnect()
Let’s try it! send_command(): Configuring Devices
1f_sendcmd_config.py
Added some print commands for readability
send_command_set() Using a list of commands (a better way?)
import netmiko
device = '192.168.1.1'
# send_config_set() method can use commands
ipv6_interface_list = [ # from a list, a string, or from a file to a
'ipv6 unicast-routing',
# list.
'interface g0/0',
# Requires privileged exec access
'ipv6 address 2001:db8:cafe:1::1/64',
# Handles configuration mode
'ipv6 address fe80::1:1 link-local',
# connection.enable() not needed
'exit',
connection.send_config_set(ipv6_interface_list)
'interface g0/1',
'ipv6 address 2001:db8:cafe:2::1/64', # Verify
'ipv6 address fe80::1:2 link-local' print(device)
] print(connection.send_command('show ipv6 interface brief'))
connection = netmiko.ConnectHandler(
ip=‘device',
connection.disconnect()
device_type='cisco_ios',
username='admin',
password='cisco',
Let’s try it! send_command_set(): Configuring Devices
4a_sendconfigset_fromlist.py
output = send_command_set() Display Commands
import netmiko
device = '192.168.2.1'
ipv6_interface_list = [ # Stores the output of the configuration commands (prompts and
'ipv6 unicast-routing',
commands) to the variable output.
'interface g0/0',
output =
'ipv6 address 2001:db8:cafe:3::1/64',
connection.send_config_set(ipv6_interface_list)
'ipv6 address fe80::3:3 link-local',
'exit',
# Print output: prompts and commands
'interface g0/1', print(output)
'ipv6 address 2001:db8:cafe:2::2/64',
'ipv6 address fe80::3:2 link-local' # Verify
] print(connection.send_command('show ipv6 interface brief'))
connection = netmiko.ConnectHandler(
ip=‘device',
connection.disconnect()
device_type='cisco_ios',
username='admin',
password='cisco',
Let’s try it! send_command_set(): Display Commands
4b_sendconfigset_fromlist_displaycomman
ds.py
output = send_command_from_file()
import netmiko
# Use send_config_from_file() to send
# configuration commands from a file
# File containing configuration commands
output = connection.send_config_from_file(config_file)
config_file = 'r1-ipv6-config.txt'
print(f"Config Output:\n{output}\n")
device = '192.168.1.1'
print("Verify configuration")
print(connection.send_command('show ipv6 interface
# Define device parameters
brief'))
connection = netmiko.ConnectHandler(
ip=‘device',
device_type='cisco_ios',
username='admin',
password='cisco',
secret='class')
'r1-ipv6-config.txt
interface gig 0/0
ipv6 address 2001:db8:cafe:1::1/64
ipv6 address fe80::1:1 link-local
exit
interface gig 0/1
ipv6 address 2001:db8:cafe:2::1/64
ipv6 address fe80::1:2 link-local
exit
MacOS%
Output (Backup)
Config Output:
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
R1(config)#interface gig 0/0
R1(config-if)#ipv6 address 2001:db8:cafe:1::1/64
R1(config-if)#ipv6 address fe80::1:1 link-local
R1(config-if)#exit
R1(config)# After configuration
R1(config)#interface gig 0/1 GigabitEthernet0/0 [up/up]
R1(config-if)#ipv6 address 2001:db8:cafe:2::1/64 FE80::1:1
R1(config-if)#ipv6 address fe80::1:2 link-local 2001:DB8:CAFE:1::1
R1(config-if)#exit GigabitEthernet0/1 [down/down]
R1(config)#end FE80::1:2
R1# 2001:DB8:CAFE:2::1
GigabitEthernet0/2 [administratively down/down]
unassigned
MacOS%
import netmiko for loop - Accessing multiple devices
(For those more familiar with Python)
# Assign devices to a list of IP addresses used to SSH into each device
devices = ['192.168.1.1', '192.168.2.2', '192.168.3.2']
# Loop through the IP addresses, assign device to each item in the list of devices
for device in devices:
connection = netmiko.ConnectHandler(ip=device,
device_type='cisco_ios',
username='admin',
password='cisco')
# Print current value of device (IPv4 address) and output from send_command()
print(device)
print(connection.send_command('show ip route static'))
connection.disconnect()
Let’s try it! For Loop and a List of Devices
2a_forloop_listip_sendcmd.py
For those who are
familiar with dictionaries,
each device can be a
dictionary with its own
usernames, passwords,
device types:
See Rick’s stuff for more
information.
Some ideas for those familiar with some of this…
(Otherwise, ignore this )
• Configure multiple devices using a separate files with IOS
commands for each device
• Include Cisco EEM (Embedded Event Manager) files for
connection-sensitive configurations such as ACLs, IP
addressing and routing
• Require SSH and privileged passwords to be entered
manually
• Use a JSON file for list of devices
• Use Netmiko with TextFSM and NTC Templates that converts
semi-formatted text (the CLI output) to structured data
• Etc.
import netmiko # Import Netmiko library
Summary
ipv6_interface_list = [ List of commands ]
config_file = 'r1-ipv6-config.txt'
connection = netmiko.ConnectHandler(ip='192.168.1.1’, device_type='cisco_ios',
username='admin’, password='cisco’, secret='class’)
print(connection.send_command('show ip interface brief'))
print(connection.send_command_expect('copy run start’, expect_string=‘filename'))
connection.enable() # Privileged exec mode
connection.config_mode() # Global config mode
connection.send_command('access-list 1 permit any') # Global configuration command
connection.exit_config_mode() # Exit global config mode
connection.send_config_set(ipv6_interface_list) # Send commands from a list
connection.send_config_from_file(config_file) # Send commands from a file
connection.save_config() # Same as 'copy run start'
connection.disconnect() # Close SSH connection
And you can start right here…
# Our first Netmiko program
import netmiko
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios',
username='admin',
password='cisco’)
print(connection.send_command('show ip interface brief'))
connection.disconnect()
You are welcome to any of my
Python networking programs.
Real-time, specific TCP/IP
information:
• YouTube: What it does
• GitHub: The code
One condition, same as I tell all
my students…
You can’t criticize my code
Netmiko playlist and GitHub
repository coming soon! (Will
post of Facebook IPD)
https://www.linkedin.com/in/rick-graziani-4194674/
Google Drive
https://drive.google.com/drive/folders/13-AlEJe-8seCXa
Email pQzfpAbci0aNEnlJn3?usp=drive_link
[email protected] YouTube
[email protected] https://www.youtube.com/@rickgraziani6055/playlists
GitHub
https://github.com/rigrazia?tab=repositories
Netmiko developed by Kirk Byers
https://github.com/ktbyers/netmiko
import netmiko send_command_set() and other sub-modes
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios', username='admin', password='cisco', secret='class')
connection.enable() # Required: Privileged exec mode
connection.config_mode() # Global config mode – Not required for other sub-modes
connection.exit_config_mode() # Exit global config mode
connection.interface_mode() # Followed by sending a list of interface commands
connection.exit_interface_mode() # Exit interface mode
connection.line_mode() # Followed by sending a list of VTY or con commands
connection.exit_line_mode() # Exit line mode
connection.disconnect()
import netmiko send_command_set() and other sub-modes
connection = netmiko.ConnectHandler(ip='192.168.1.1',
device_type='cisco_ios', username='admin', password='cisco', secret='class')
console_config_commands = [
'line con 0', # Access the console line
'logging synchronous' # Enable synchronous logging
]
connection.enable() # Required: Privileged exec mode
connection.line_mode()
output = connection.send_config_set(console_config_commands)
print(f"Configuration Output:\n{output}\n")
connection.exit_line_mode() # Exit line mode (optional here)
connection.disconnect()