Netmiko — SSH That Knows It's a Router
20 min In ProgressLearning Objectives
- Understand the device_type parameter and what it buys you
- Use send_command() vs send_config_set()
- Decide when to reach for Netmiko instead of raw Paramiko
Why Netmiko
Netmiko is Paramiko with one extra ingredient: device_type. Tell it the device is 'cisco_ios' and it automatically handles the things Paramiko makes you do by hand — paging through long output, entering enable mode, knowing what a config prompt looks like. If your target is a router, switch, or firewall, this is almost always the better starting point over raw Paramiko.
The Real Driver (Lab / Real-Device Code)
The production version, including the device_params dictionary Netmiko expects.
from netmiko import ConnectHandler
class netmiko_driver:
def __init__(self, device_params):
self.device_params = device_params
self.connection = None
def connect(self):
self.connection = ConnectHandler(**self.device_params)
def get_version(self):
return self.connection.send_command('show version')
def configure_acl(self, acl_lines):
return self.connection.send_config_set(acl_lines)
def disconnect(self):
if self.connection:
self.connection.disconnect()
ios_device = {
'device_type': 'cisco_ios',
'host': '192.168.1.1',
'username': 'admin',
'password': 'secret',
}
net = netmiko_driver(ios_device)
net.connect()
print(net.get_version())
net.disconnect()
Practice Safely — Simulated Netmiko Session
The simulated session takes the same device_params dict a real ConnectHandler would, and exposes the same three methods you'd actually call: send_command, send_config_set, disconnect.
class simulated_netmiko_session:
"""Mimics netmiko.ConnectHandler: knows the device_type up front and
exposes send_command / send_config_set / disconnect."""
def __init__(self, device_params):
self.device_params = device_params
self.connected = False
self.applied_config = []
def connect(self):
self.connected = True
def send_command(self, command):
if command == 'show version':
return f"{self.device_params['device_type']} -- edge-router-1, uptime 19 days"
return f'% Unknown command: {command}'
def send_config_set(self, lines):
self.applied_config.extend(lines)
return '\n'.join(f'edge-router-1(config)# {line}' for line in lines)
def disconnect(self):
self.connected = False
class netmiko_style_driver:
def __init__(self, device_params):
self.device_params = device_params
self.connection = simulated_netmiko_session(device_params)
def connect(self):
self.connection.connect()
def get_version(self):
return self.connection.send_command('show version')
def configure_acl(self, acl_lines):
return self.connection.send_config_set(acl_lines)
def disconnect(self):
self.connection.disconnect()
ios_device = {'device_type': 'cisco_ios', 'host': 'edge-router-1'}
net = netmiko_style_driver(ios_device)
net.connect()
print(net.get_version())
print(net.configure_acl([
'ip access-list extended BLOCK_BAD',
'deny ip 10.0.0.0 0.255.255.255 any',
'permit ip any any',
]))
net.disconnect()
📝 Exercise: Add save() to Your Driver
Netmiko's real connection has a save_config() method that writes the running config to startup config. Add the same to the simulated session and a matching save() method on the driver, then call it after applying the ACL.