This article presents a system design for automating multi-vendor network operations using a pure Python architecture. It tackles the challenge of heterogeneous network devices by abstracting vendor-specific configurations into a standardized, intent-driven approach. The proposed architecture emphasizes decoupling intent from implementation and integrating validation within a CI/CD pipeline.
Read original on DZone MicroservicesWhile server infrastructure has largely adopted Infrastructure as Code (IaC) principles, network automation remains a significant hurdle, primarily due to the 'Multi-Vendor Trap'. Enterprise networks typically comprise devices from various vendors (Cisco, Juniper, F5), each with unique CLI syntaxes and operational models. This heterogeneity makes standard automation difficult, leading to manual, error-prone processes and extended lead times for network changes, often weeks for simple tasks like VLAN creation or firewall rule updates. The 'human middleware' problem arises where engineers manually translate generic requests into vendor-specific commands, execute them, and then validate the changes, a process heavily reliant on individual expertise and prone to delays.
The core of the proposed solution is to decouple the *intent* (what needs to be done) from the *implementation* (how it's done on specific hardware). Unlike YAML-based automation tools, a pure Python approach using libraries like Nornir offers more robust debugging, type checking, and complex logic handling. This architecture introduces a layered approach:
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_config
def configure_vlan(task, vlan_id, vlan_name):
config_cmds = []
if task.host.platform == "cisco_ios":
config_cmds = [f"vlan {vlan_id}", f"name {vlan_name}"]
elif task.host.platform == "junos":
config_cmds = [f"set vlans {vlan_name} vlan-id {vlan_id}"]
if config_cmds:
task.run(task=netmiko_send_config, config_commands=config_cmds)
nr = InitNornir(config_file="config.yaml")
targets = nr.filter(name__in=network_request["targets"])
result = targets.run(task=configure_vlan, vlan_id=network_request["params"]["vlan_id"], vlan_name=network_request["params"]["name"])A critical aspect of network automation is ensuring that changes do not inadvertently disrupt the network ecosystem. The architecture incorporates a 'health check' pattern using pre-check/post-check validation. Before applying changes, Python scripts capture the current state (e.g., routing tables). After configuration, the state is recaptured, and programmatic diffs are performed to identify any unintended alterations. This treats validation similar to unit testing in software development.
Integration with CI/CD
The entire network automation workflow, from defining intent to executing and validating changes, is designed to integrate into a CI/CD pipeline (e.g., Azure DevOps, Jenkins). This ensures consistency, repeatability, and version control for network configurations, akin to software development practices.