Fundamentals of Network Automation blog

We introduced resource modules in Ansible 2.9, which provided a path for users to ease network management, especially across multiple different product vendors. This announcement was significant because these resource modules added a well structured representation of device configurations and made it easy to manage common network configurations.

At AnsibleFest 2022, we announced a new addition to the content ecosystem offered through the platform: Ansible validated content. Ansible validated content is use cases-focused automation that is packaged as Collections. They contain Ansible plugins, roles and playbooks that you can use as an automation job through Red Hat Ansible Automation Platform.

The Ansible validated content for network base focuses on abstract platform-agnostic network automation and enhances the experience of resource module consumption by providing production-ready content. This network base content acts as the core to the other network validated content, which I will explain more about in the examples below.

Network base use cases

The network.base Collection acts as a core for other Ansible validated content, as it provides the platform agnostic role called Resource Manager, which is the platform-agnostic entry point for managing all of the resources supported for a given network OS. It includes the following capabilities: 

  • Build Brownfield Inventory. The persist action enables users to be able to get the facts for a given resource and store it as inventory host_vars. The idea is to have this dynamic inventory as a single source of truth for provided action.
  • Supported Resource Query. The list action enables users to be able to get the list of all resource modules supported for a given network OS.
  • Display Structured Configuration. The gather action enables users to be able to gather and display the facts for specified network resources.
  • Deploy Changes: The deploy action enables users to deploy the host vars facts changes to the device. You should be aware that there is also another way of pushing configurations  onto the device through the configure action

Using the list action - Supported Resource Query

The list action enables users to be able to get the list of all resource modules supported for a given network OS.

Here is an Ansible Playbook example of using action: list and displaying the result with a list of all supported resource modules.

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network Resource Manager
      ansible.builtin.include_role:
        name: resource_manager
      vars:
        action: list

Execute the Ansible Playbook with the ansible-navigator command:

$ ansible-navigator run example.yml -i inventory.yaml
        action: list

Here is the provided result:

ok: [192.168.122.220] => {
    "msg": {
        "ansible_connection": "ansible.netcommon.network_cli",
        "ansible_network_os": "cisco.ios.ios",
        "changed": false,
        "failed": false,
        "modules": [
            "acl_interfaces",
            "acls",
            "bgp_address_family",
            "bgp_global",
            "hostname",
            "interfaces",
            "l2_interfaces",
            "l3_interfaces",

You can check out the full detailed listing of the output of this example in the action: list reference gist.

Using action persist - Building an Ansible inventory

The persist action enables users to invoke the Ansible resource modules to gather configuration facts for a given resource, create the new inventory directory and store the result  as YAML into  host_vars in that directory. This dynamic inventory acts as a single source of truth  for other actions; this is extremely useful considering networks are more complex and dynamic than ever, and allows network engineers to quickly obtain an updated inventory in a simple way for specific resources.  

This is the native command output for the configured interfaces as shown below.

R1#show ip interface br | ex una
Interface             IP-Address      OK? Method Status                Protocol
GigabitEthernet0/0    192.168.255.108 YES DHCP   up                    up      
GigabitEthernet0/1    11.0.15.1       YES manual administratively down down 

To create the inventory with required resources,  we can write a task as shown below:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network Resource Manager
      ansible.builtin.include_role:
        name: resource_manager
      vars:
        action: persist
        resources:
          - 'interfaces'
          - 'l2_interfaces'
          - 'l3_interfaces'
          - 'ospfv2'
          - 'ospfv3'
          - 'ospf_interfaces'

Execute the Ansible Playbook with the ansible-navigator command:

$ ansible-navigator run example.yml

Here is the new inventory directory structure that was created:

$ tree 
.
├── ansible.cfg
├── bindep.txt
├── CHANGELOG.rst
├── changelogs
│   ├── changelog.yaml
│   ├── config.yaml
│   └── fragments
├── cspell.config.yaml
├── galaxy.yml
├── inventory
│   ├── host_vars
│   │   └── 192.168.122.220
│   │       ├── interfaces.yaml
│   │       ├── l2_interfaces.yaml
│   │       ├── l3_interfaces.yaml
│   │       └── ospf_interfaces.yaml
│   └── inventory.yaml

In the output, we can observe that it created files for non-empty results with names similar to resource module names. The content of these files are resource module gathered facts as shown below:

$ cat inventory/host_vars/192.168.122.220/l3_interfaces.yaml
l3_interfaces:
-   ipv4:
    -   dhcp:
            enable: true
    name: GigabitEthernet0/0
-   ipv4:
    -   address: 11.0.15.1/29
    name: GigabitEthernet0/1
-   name: GigabitEthernet0/2
-   name: GigabitEthernet0/3

Using the deploy action - Deploy configuration changes

The deploy action enables users to deploy the host_vars facts changes in dynamic inventory onto the network devices.

Let’s add some loopback interfaces in the l3_interfaces.yaml file as shown below:

$ cat  inventory/host_vars/192.168.122.220/l3_interfaces.yaml 
l3_interfaces:
-   ipv4:
    -   dhcp:
            enable: true
    name: GigabitEthernet0/0
-   ipv4:
    -   address: 11.0.15.1/29
    name: GigabitEthernet0/1
-   name: GigabitEthernet0/2
-   name: GigabitEthernet0/3
-   ipv4:
    -   address: 11.1.5.1/24
    name: Loopback55
-   ipv4:
    -   address: 11.1.6.1/24
    name: Loopback66
-   ipv4:
    -   address: 11.1.7.1/24
    name: Loopback77

Now that we have modified the l3_interfaces host_vars, we can use deploy action as shown below:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network Resource Manager
      ansible.builtin.include_role:
        name: resource_manager
      vars:
        action: deploy
        resources:
          - 'interfaces'
          - 'l2_interfaces'
          - 'l3_interfaces'
          - 'ospfv2'
          - 'ospfv3'
          - 'ospf_interfaces'

Execute the Ansible Playbook with the ansible-navigator command:

$ ansible-navigator run example.yml

We can confirm these changes on the box with native command as shown below:

R1#show ip interface br | ex una
Interface             IP-Address      OK? Method Status                Protocol
GigabitEthernet0/0    192.168.255.108 YES DHCP   up                    up      
GigabitEthernet0/1    11.0.15.1       YES manual administratively down down
Loopback55            11.1.5.1        YES manual up                    up      
Loopback66            11.1.6.1        YES manual up                    up      
Loopback77            11.1.7.1        YES manual up                    up

If you want to know more about the tasks executed internally you can checkout the result.

Using the gather action - Display structured configuration

The gather action enables users to gather and display the facts for specified network resources as shown below:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network Resource Manager
      ansible.builtin.include_role:
        name: resource_manager
      vars:
        action: gather
        resources:
          - 'all'
          - '!vlans'
          - '!lacp'

Please note that Instead of mentioning each resource, we can use ‘all’, and if we want to exclude any resource, then we can use ‘!’ as shown above.

Execute the Ansible Playbook with the ansible-navigator command:

$ ansible-navigator run example.yml

Here is snippet from the output of the gather action show below:

…
TASK [network.base.resource_manager : Resource Facts] **************************
ok: [192.168.122.220] => {
    "msg": {
        "ansible_connection": "ansible.netcommon.network_cli",
        "ansible_network_os": "cisco.ios.ios",
        "changed": false,
        "failed": false,
        "gathered": [
            {
                "name": "Loopback55"
            },
            {
                "name": "Loopback66"
            },
            {
                "name": "Loopback77"
            },
            {
                "name": "GigabitEthernet0/0"
            },
…

We can also see the detailed output here.

Takeaways and next steps

As shown above, with the help of the Ansible validated content for network base, we can enhance the experience of resource module consumption by providing production-ready  content. By using the persist, gather and deploy actions, network engineers can gain much more flexibility and adopt platform agnostic automation focused on certain use cases. These actions are fundamental to the other network Ansible validated content like Network BGP and Network OSPF, which will be covered in upcoming blogs. If you want to learn more about Ansible Automation Platform and network automation, you can check out these resources:


About the author

Rohit Thakur is a Senior Software Engineer for Red Hat Ansible Automation, where he brings over 9 years in development of Telecommunication Networks, Optical Networks and Network Automation.

Read full bio