Multi-Vendor Network Automation: Stop Fighting the CLI with NAPALM and Python

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

The Nightmare of Multi-Vendor CLI

Managing a single-vendor network is hard enough. But in reality, most production racks are a “best-of-breed” mix of Cisco IOS, Juniper Junos, and Arista EOS. This usually means keeping three different cheat sheets for the same basic VLAN change. Each vendor has its own syntax, its own way of handling commits, and its own messy output format for simple tasks like checking interface status.

Last quarter, my team spent nearly 15 hours a week just parsing text from show commands to verify port status during audits. It was tedious and prone to error. To fix this, we integrated NAPALM into our workflow. Since moving to this model, our configuration consistency has skyrocketed. We now treat our infrastructure like versioned code rather than a collection of unique, hand-configured “snowflakes.”

Core Concepts: Why NAPALM?

NAPALM stands for Network Automation and Programmability Abstraction Layer with Multivendor support. Think of it as a universal translator for your network hardware. Instead of writing separate scripts for a Cisco Catalyst and a Juniper MX, you write one Python script. NAPALM handles the heavy lifting of connecting to the device and translating your requests into the specific vendor’s language.

1. The Abstraction Layer

NAPALM’s biggest advantage is its “Getters.” If you need to check device uptime or the serial number, you just call get_facts(). It doesn’t matter if you’re hitting a Cisco ISR or an Arista switch; NAPALM returns a standardized Python dictionary every time. This saves you from writing 200 lines of complex Regular Expressions (Regex) just to find a MAC address in a wall of text.

2. Configuration Management

NAPALM does more than just read data; it manages the actual state of your devices. It supports two primary methods: Merge for adding small snippets and Replace for overwriting a configuration with a known-good template. More importantly, the compare_config() feature acts as a safety net. It shows you exactly what will change before you commit. If a change breaks connectivity, the rollback() feature can revert the device to its previous state in seconds.

Hands-on: Setting Up Your Environment

Getting started is straightforward. You’ll need Python 3.6 or newer and the specific driver libraries for your hardware. I recommend using a virtual environment to keep your dependencies clean.

# Set up your workspace
python3 -m venv napalm-env
source napalm-env/bin/activate

# Install the library
pip install napalm

Before running scripts, verify that your hardware APIs are ready. For Cisco IOS, ensure SSH is active. Arista devices require eAPI to be enabled, while Juniper gear needs NETCONF turned on.

Connecting and Fetching Data

Let’s look at a script that pulls basic info from a Cisco router. Notice how simple the logic is once we define the driver.

from napalm import get_network_driver
import json

# Specify 'ios', 'junos', or 'eos'
driver = get_network_driver('ios')
device = driver(hostname='10.1.1.50', username='admin', password='secure_password')

print("Opening connection...")
device.open()

# Fetch data using a standardized method
facts = device.get_facts()

# Output the results
print(json.dumps(facts, indent=4))

device.close()

If you swap 'ios' for 'junos' and update the IP, the get_facts() method returns the same data structure. Your automation logic remains identical regardless of the hardware brand.

Automating Configuration Changes

The real value appears when pushing changes. In this example, we’ll update an interface description using the Merge strategy. This is generally safer for daily operations than a full replacement.

from napalm import get_network_driver

driver = get_network_driver('ios')
device = driver('10.1.1.50', 'admin', 'secure_password')
device.open()

print("Staging configuration...")
device.load_merge_candidate(config='interface GigabitEthernet1\n description Link_to_Core')

# The 'diff' shows you what is about to happen
diff = device.compare_config()

if diff:
    print("Pending Changes:\n" + diff)
    
    confirm = input("Commit these changes? (y/n): ")
    if confirm.lower() == 'y':
        device.commit_config()
        print("Done.")
    else:
        device.discard_config()
else:
    print("No changes detected.")

device.close()

In a live environment, that diff output is a lifesaver. It prevents the “fat-finger” typos that usually lead to emergency midnight bridge calls.

The Rollback Safety Net

Mistakes happen even with the best planning. One reason I rely on NAPALM for production is the rollback() function. If a commit goes through but the monitoring system starts flagging latency spikes, you can revert immediately.

try:
    # Run a post-check script here
    validate_ospf_neighbor_count()
except Exception as e:
    print(f"Alert: {e}. Reverting to previous state!")
    device.rollback()

Keep in mind that for Cisco IOS, NAPALM simulates this by archiving the config. On Juniper, it uses the native rollback architecture built into the OS.

Hard-Won Lessons from Production

After six months of daily use, I’ve found a few ways to make these scripts more robust:

  • Stop Hardcoding Passwords: Use os.environ or a tool like HashiCorp Vault. Your Git history shouldn’t contain your network credentials.
  • Adjust Your Timeouts: Large config changes on an old Cisco ISR 4000 can be slow. Increase the timeout parameter in the driver to 60 or 90 seconds to prevent random disconnects.
  • Keep an Audit Trail: Always log the compare_config() output to a central file. It’s helpful to know exactly who changed what and when.
  • Verify the State: Don’t just trust the commit. Follow up with get_bgp_neighbors() to ensure your routing table didn’t disappear after the change.

Moving Forward

Moving from manual CLI work to Python automation can feel like a steep climb. However, the consistency it provides is worth the learning curve. By abstracting away vendor quirks, you can focus on high-level network design rather than memorizing command syntax. Whether you’re managing a small office or a sprawling data center, unified configuration management is a mandatory step for modern infrastructure.

Share: