First steps at network programmability (Frameworks)
As network automation evolves several frameworks and libraries are available, which brings a common question of network engineers: which one is the best for my project?
To answer that question, you must look at the project and analyze the following points: What level of abstraction is required? And does that framework/library supports my devices?
In terms of abstraction, I separate the libraries into the following categories: SSH, CLI Parser, Configuration Automation, Device Serialization, Testing, Programming language, and User Interface.
At this level, we have Paramiko that encapsulates the connection logic, in other words, it’s responsible for opening the SSH connection, keeping the connection state, sending commands through the connection, and closing.
Those activities are fundamental for network automation because, when configuring a network device, first you connect to the device and then perform some privilege escalation activities like going to Exec mode, or Configuration mode, that requires a persistent connection state.
After connecting to a device, each vendor has a particular syntax sometimes differing at a very basic level as the command prompt, as an example:
Hostname <Hostname> Hostname(config) [ ]
Those differences might be quite difficult to handle, and if for every implementation you have to deal with that, the complexity of the code will grow excessively and it will be poorly maintainable.
To deal with that we have Netmiko, PyEz, and Genie, these libraries encapsulate the CLI syntax delivering the devices' operational status as programmatic objects, exposing interfaces for issuing exec level commands and configuration level commands.
From a vendor support perspective, we have Netmiko with multi-vendor support, PyEz for Juniper, and Genie mostly Cisco devices.
When configuring a network device, it’s a good practice: to perform a backup, make the change, evaluate whether that change has had the desired effect and, if there’s any problem, rollback the device to a previous working state.
That process also can be encapsulated, which is done by Napalm and Genie, both provide an interface for configuration backup, configuration difference, and rollback.
In most automation scenarios there will be several tasks that must be performed on multiple devices of different brands.
To handle multiple tasks efficiently and work with multiples threads, might be a difficult job that increases significantly the complexity of your automation code.
For that, Ansible, Nornir, and Genie encapsulate the inventory management and the tasks' serialization, allowing the developer to deal only with the automation logic, coding only the desired tasks.
After every change on a network device, it’s a good practice to test if it delivers the desired results and if there are any side effects, for that pyATS provides a great test framework with end-to-end capabilities.
It is fair to emphasize that those functionalities are also possible with Ansible through the assert module, however with limited features.
At those previous layers, we were dealing directly with Python, Ansible, on the other hand, encapsulates the whole programming language providing a new Domain-Specific Language allowing the user to configure only the tasks required for the automation without the knowledge of any programming language, using only a markup language (YAML) for the modules configurations.
In our last layer, we have Ansible AWX, Ansible Tower, and XPRESSO that provides a web interface for managing the inventory and calling the Ansible Playbook, or pyATS scripts.
To summarize, we can organize the several frameworks in the diagram below, and if your project involves simple tasks without third-party integrations, like an end-user interface, Ansible with AWX or Tower might be a good choice, but if you want full control of the execution and intent to integrate with some monitoring system or end-user interface, Nornir might be a good choice.
Finally, there will be cases that your device won't have any support, in that scenario you might need NETMIKO or PARAMIKO to create an interface for commands and then integrate your module with Ansible or Nornir.