Getting Started with Netmiko in Python

When it comes to automating tasks over SSH in Python, two libraries stand out: Paramiko and Netmiko. Both, however, serve different purposes and needs.

Paramiko is a general-purpose SSH library that provides low-level SSH functionality, making it versatile but requiring more code for network automation tasks. With Paramiko, you must handle all the details of connecting, authenticating, and sending commands. Visit this link for my article on Paramiko.

Netmiko is built on top of Paramiko and is specifically designed for network automation. It simplifies interactions with network devices, particularly those from vendors like Cisco, Juniper, and Arista.

Netmiko deals with the complexities of SSH connections and command parsing, letting you focus on the task at hand rather than the underlying connection. This makes it easier to implement common network tasks, like retrieving interface information, pushing configuration changes, or working with multiple devices in one go. If you’re primarily working with network equipment, Netmiko can save you time and simplify your code.

Here’s a guide to setting up Netmiko with Python, creating a virtual environment on Windows and Linux, and using it in real-world scenarios.

1. Setting Up a Virtual Environment

Before we dive into Netmiko, let’s set up a virtual environment (venv) to keep dependencies isolated. This makes sure you can work on multiple projects without conflicts.

Windows

Open a command prompt.

Navigate to your project directory:

cd C:\path\to\your\project

Create the virtual environment:

python -m venv venv

Activate the environment:

venv\Scripts\activate

Linux

Open a terminal.

Navigate to your project directory:

cd /path/to/your/project

Create the virtual environment:

python3 -m venv venv

Activate the environment:

source venv/bin/activate

Once the environment is activated, install Netmiko using pip:

pip install netmiko

2. Connecting to a Network Device

Netmiko simplifies connecting to a variety of network devices, including Cisco, Juniper, and Arista hardware. To begin, let’s establish a connection to a Cisco router and retrieve basic information.

Example 1: Connecting to a Cisco Device and Running a Command

File: basic_connect.py

In this example, we’ll connect to a Cisco router and fetch its version information.

from netmiko import ConnectHandler

# Device details
cisco_device = {
    "device_type": "cisco_ios",
    "host": "your-router-ip",
    "username": "your-username",
    "password": "your-password",
}

# Establish the connection
connection = ConnectHandler(**cisco_device)

# Run a command
output = connection.send_command("show version")
print(output)

# Close the connection
connection.disconnect()

In this script, replace host, username, and password with your device’s information. The device_type specifies the device’s platform (in this case, Cisco IOS). Running this script will display the router’s version information.

3. Executing Multiple Commands

Often, you’ll want to run multiple commands. Netmiko allows you to send multiple commands in sequence, making it easy to automate routine tasks.

Example 2: Running Multiple Commands in Sequence

File: multi_command.py

This example connects to the device and gathers details about interfaces and routing protocols.

from netmiko import ConnectHandler

# Device details
device = {
    "device_type": "cisco_ios",
    "host": "your-router-ip",
    "username": "your-username",
    "password": "your-password",
}

# Connect to the device
connection = ConnectHandler(**device)

# List of commands to execute
commands = [
    "show ip interface brief",
    "show ip route",
    "show running-config",
]

for cmd in commands:
    output = connection.send_command(cmd)
    print(f"Output for '{cmd}':\n{output}\n")

# Close the connection
connection.disconnect()

This script runs each command in the commands list and prints the output for each one. It’s a straightforward way to gather information without manually entering each command.

4. Automating Configuration Changes

Netmiko can also handle configuration tasks, making it easy to push changes across multiple devices.

Example 3: Applying Configuration Changes

File: config_change.py

In this script, we’ll push a configuration update to a router.

from netmiko import ConnectHandler

# Device details
device = {
    "device_type": "cisco_ios",
    "host": "your-router-ip",
    "username": "your-username",
    "password": "your-password",
}

# Connect to the device
connection = ConnectHandler(**device)

# Configuration commands
config_commands = [
    "interface GigabitEthernet0/1",
    "description Configured by Netmiko",
    "ip address 192.168.1.2 255.255.255.0",
    "no shutdown",
]

# Send configuration commands
connection.send_config_set(config_commands)
print("Configuration changes applied.")

# Save configuration
connection.send_command("write memory")
print("Configuration saved.")

# Close the connection
connection.disconnect()

In this example, replace interface GigabitEthernet0/1 and other interface details to match your network settings. The script applies configuration changes to the specified interface and saves them.

5. Working with Multiple Devices

In real-world scenarios, network engineers often work with many devices. Here’s an example showing how to connect to multiple devices and run commands across all of them.

Example 4: Connecting to Multiple Devices

File: multi_device.py

We’ll define multiple devices in a list and use a loop to run commands on each one.

from netmiko import ConnectHandler

# List of devices
devices = [
    {
        "device_type": "cisco_ios",
        "host": "router1-ip",
        "username": "your-username",
        "password": "your-password",
    },
    {
        "device_type": "cisco_ios",
        "host": "router2-ip",
        "username": "your-username",
        "password": "your-password",
    },
]

# Commands to run on each device
commands = ["show ip interface brief", "show version"]

for device in devices:
    print(f"Connecting to {device['host']}...")
    connection = ConnectHandler(**device)
    for cmd in commands:
        output = connection.send_command(cmd)
        print(f"Output for '{cmd}' on {device['host']}:\n{output}\n")
    connection.disconnect()

In this script, each device is defined with its IP address, username, and password. The script iterates through each device, connecting and running commands sequentially.

6. Using SSH Keys for Authentication

Netmiko also supports SSH key authentication, which is safer than using passwords.

Example 5: Connecting with an SSH Key

File: ssh_key_connect.py

Make sure your SSH key is already set up on the remote devices before using this script.

from netmiko import ConnectHandler

# Device details
device = {
    "device_type": "cisco_ios",
    "host": "your-router-ip",
    "username": "your-username",
    "use_keys": True,
    "key_file": "C:/path/to/your/private_key.pem",
}

# Establish the connection
connection = ConnectHandler(**device)

# Run a command
output = connection.send_command("show ip interface brief")
print(output)

# Close the connection
connection.disconnect()

The use_keys parameter is set to True, and the key_file parameter points to the private key file. This way, Netmiko will authenticate using the SSH key instead of a password.

7. Error Handling in Netmiko

When working with network devices, connections can sometimes fail. Handling these errors is essential for reliability.

Example 6: Handling Connection Errors

File: error_handling.py

This example demonstrates a try-except block to handle connection errors.

from netmiko import ConnectHandler, NetmikoTimeoutException, NetmikoAuthenticationException

device = {
    "device_type": "cisco_ios",
    "host": "your-router-ip",
    "username": "your-username",
    "password": "your-password",
}

try:
    connection = ConnectHandler(**device)
    output = connection.send_command("show ip interface brief")
    print(output)
except NetmikoTimeoutException:
    print("Connection timed out.")
except NetmikoAuthenticationException:
    print("Authentication failed.")
finally:
    connection.disconnect()

This script will catch timeout and authentication errors, ensuring your program handles issues gracefully.


Thank you for reading this article. We hope you found it helpful and informative. If you have any questions, or if you would like to suggest new Python code examples or topics for future tutorials/articles, please feel free to join and comment. Your feedback and suggestions are always welcome!

You can find the same tutorial on Medium.com.

Leave a Reply