ⓘ Accuracy Disclaimer
Technical content in this article was researched and compiled with AI assistance under the direct supervision of the author. While every effort has been made to ensure accuracy, errors may still be present. If you spot an inaccuracy or have a correction, the author welcomes feedback — please reach out at github@it-solutionsusa.com or open an issue at github.com/ikonstas70.
The current stack solves the "last mile" problem — serial console access via a REST API. Phase 2 transforms it into a professional-grade automation platform: structured device interaction, parallel fleet operations, live topology graphing, and packet-level diagnostics, all served over local HTTPS with no external cloud dependencies.
Replaces the current shell=True subshell with a structured connection handler. Handles prompt detection, output parsing, and timing natively — eliminating fixed sleep delays and the shell injection risk in the current implementation.
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios_telnet",
"host": "127.0.0.1",
"port": 2301,
}
with ConnectHandler(**device) as conn:
output = conn.send_command("show ip interface brief")
print(output)
Runs tasks across all 10 routers simultaneously. A fleet-wide poll that currently takes 40+ seconds sequentially completes in under 5 seconds with Nornir.
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
nr = InitNornir(config_file="config.yaml")
result = nr.run(
task=netmiko_send_command,
command_string="show ip interface brief"
)
print_result(result)
Provides a unified API for retrieving structured data from network devices — Python dicts instead of raw CLI text. Works on top of Netmiko for Cisco IOS.
from napalm import get_network_driver
driver = get_network_driver("ios")
device = driver("127.0.0.1", "admin", "password",
optional_args={"port": 2301})
device.open()
facts = device.get_facts()
interfaces = device.get_interfaces()
bgp = device.get_bgp_neighbors()
device.close()
Builds a live, queryable graph of the router fleet. Detects topology changes, calculates shortest paths, and provides the data layer for visualisation and AI-driven network analysis.
import networkx as nx
G = nx.Graph()
G.add_nodes_from(["R1", "R2", "R3", "R4", "Hub"])
G.add_edges_from([
("Hub", "R1"), ("Hub", "R2"),
("Hub", "R3"), ("Hub", "R4"),
])
path = nx.shortest_path(G, source="R1", target="R4")
centrality = nx.betweenness_centrality(G)
Enables low-level network testing — custom ICMP probes, TCP session inspection, DSCP marking verification, and traffic capture.
from scapy.all import IP, ICMP, sr1
packet = IP(dst="192.168.2.1", ttl=64) / ICMP()
response = sr1(packet, timeout=2, verbose=0)
if response:
print(f"Reply from {response.src} TTL: {response.ttl}")
Replaces the Cloudflare Tunnel with self-hosted SSL termination. Fully offline, no external dependency, persistent across reboots.
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/lab.crt;
ssl_certificate_key /etc/nginx/ssl/lab.key;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
| Phase | Deliverable | Impact |
|---|---|---|
| 1 | Netmiko replaces raw subshell | Removes shell injection risk, eliminates fixed sleeps |
| 2 | Nornir parallel fleet polling | 10× performance improvement on fleet-wide operations |
| 3 | NAPALM structured data layer | Structured JSON responses for AI and analytics |
| 4 | NetworkX topology endpoint | Live graph API for topology-aware automation |
| 5 | Scapy diagnostic module | Packet-level testing and DSCP verification |
| 6 | Nginx SSL termination | Full local HTTPS, no external dependencies |