Network Automation
Python · Ansible · GitOps
1. Why Automate?
Manual CLI changes do not scale past a handful of devices and are the leading cause of outages from typos and drift. Automation gives you consistency, speed, audit trails, and rollback — the config becomes code you can review and version.
Config drift
Scheduled backups + diffs catch unauthorized or forgotten changes
Mass changes
Push a VLAN or ACL update to 200 switches in minutes, not days
Compliance
Assert NTP, SNMP, AAA settings across the fleet automatically
Documentation
Inventory and interface reports generated from live state
2. The Tool Landscape
| Tool | Type | Best for |
|---|---|---|
| Netmiko | Python library (SSH) | Sending commands / configs to CLI devices, multi-vendor |
| NAPALM | Python library (API/SSH) | Structured getters (facts, interfaces, BGP) + config replace |
| Nornir | Python framework | Inventory + concurrent task execution, pure Python (no DSL) |
| Ansible | Framework (YAML DSL) | Agentless playbooks, large module ecosystem, idempotency |
| Terraform | IaC (declarative) | Cloud networking (VPCs, LBs, firewalls), state-driven |
| pyATS / Genie | Cisco test framework | Parsing show output, network state validation |
Rule of thumb
Ansible for orchestrated changes and compliance, Netmiko/Nornir for custom Python logic, NAPALM when you want vendor-neutral structured data.
3. Netmiko Essentials
from netmiko import ConnectHandler
devices = [
{
'device_type': 'cisco_ios',
'host': '10.0.0.1',
'username': 'admin',
'password': 'secret',
},
]
for device in devices:
with ConnectHandler(**device) as conn:
hostname = conn.send_command('show run | include hostname')
config = conn.send_command('show running-config')
with open(f"{device['host']}.cfg", 'w') as f:
f.write(config)| device_type | Platform |
|---|---|
| cisco_ios | Cisco IOS / IOS-XE |
| cisco_nxos | Cisco Nexus |
| arista_eos | Arista EOS |
| juniper_junos | Juniper JunOS |
| fortinet | FortiGate |
| alcatel_aos | Alcatel-Lucent OmniSwitch |
4. Ansible for Network Devices
- name: Baseline IOS devices
hosts: switches
gather_facts: false
tasks:
- name: Ensure NTP server
cisco.ios.ios_config:
lines:
- ntp server 10.0.0.123
- name: Save running to startup
cisco.ios.ios_config:
save_when: modified- •Idempotent — running twice makes no second change
- •Inventory groups map to device roles (core, access, edge)
- •Use ansible-vault for credentials, never plaintext
- •`--check --diff` = dry run showing what would change
5. Modern Interfaces: Beyond Screen-Scraping
| Interface | Transport | Data |
|---|---|---|
| NETCONF | SSH (port 830) | XML, YANG models, transactions + rollback |
| RESTCONF | HTTPS | JSON/XML over REST, YANG models |
| gNMI | gRPC / HTTP2 | Streaming telemetry + config, protobuf |
| CLI scraping | SSH | Unstructured text — parse with TextFSM / Genie |
Telemetry shift
SNMP polling every 5 minutes is being replaced by gNMI streaming telemetry — the device pushes counters the moment they change.
6. Source of Truth & GitOps
- •NetBox / Nautobot = intended state: devices, IPs, VLANs, circuits
- •Configs generated from Jinja2 templates + source-of-truth data
- •Changes go through Git pull requests — peer review before production
- •CI pipeline validates (lint, dry-run, lab test) before deploy
- •Live network is compared to intended state; drift raises alerts
{% for vlan in vlans %}
vlan {{ vlan.id }}
name {{ vlan.name }}
{% endfor %}7. Where to Start (Pragmatic Path)
- •1. Read-only first: automated backups and inventory reports — zero risk, instant value
- •2. Diff configs daily; alert on drift
- •3. Automate one boring change type (VLANs, descriptions, NTP)
- •4. Add validation: pre/post checks around every change
- •5. Move templates + data into Git; require reviews
- •6. Only then: full zero-touch provisioning
Interview favorite
"How do you roll back a bad automated change?" — config archive + `configure replace` (IOS), commit rollback (JunOS), or re-render the previous Git version and push.