Subscribe to our blog
bcp management blog

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

Now that we understand what Ansible validated content is, we still have  to see what it brings to  network automation practices. We have already talked about a generic Ansible validated content for network automation which is network.base.

Network Border Gateway Protocol (BGP) is more focused  on very specific use cases –  managing BGP resources and neighborship,  platform-agnostic network automation and enhancing the experience of BGP management by providing production ready -content.

Network BGP Use Cases

The network.bgp Collection enables users to manage the BGP resources independent of platforms, as well as performing BGP health checks. It includes the following capabilities: 

  • Build Brownfield Inventory. The persist action enables users to be able to get the BGP global and address family facts  and store it as inventory host_vars. The idea is to have this dynamic inventory as a single source of truth for any action.
  • Display Structured Configuration. The gather action enables users to be able to gather and display the BGP global and address family facts.
  • Deploy Changes: The deploy action enables users to deploy the host vars facts changes to the device.
  • BGP Health Checks. The health_check action enables users to fetch the current status of BGP neighborship health for a given network OS.

Using action persist - Building an Ansible inventory

The persist action enables users to be able to get the BGP global and BGP address family running configuration facts, 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 BGP management actions. This  is extremely useful considering the complexity and size of BGP routing, and it allows network engineers to quickly obtain an updated inventory in a simple way for BGP resources.  

This is the native command output for the BGP summary on one of the routers: 

R1#sh ip bgp summary 
BGP router identifier 192.168.255.229, local AS number 500
BGP table version is 3, main routing table version 3
2 network entries using 288 bytes of memory
2 path entries using 168 bytes of memory
2/2 BGP path/bestpath attribute entries using 320 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 776 total bytes of memory
BGP activity 2/0 prefixes, 2/0 paths, scan interval 60 secs
Neighbor  V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
12.0.0.1  4    500   19052   19065    3      0    0    1w5d     1
23.0.0.1  4    500       0       0    1      0    0    never    Idle

Let’s save this BGP configuration as YAML based host_vars for the inventory. We can write a task as shown below:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network BGP Management
      ansible.builtin.include_role:
        name: network.bgp.run
      vars:
        ansible_network_os: cisco.ios.ios
        actions:
          - name: persist

Execute the Ansible Playbook with the ansible-navigator:

$ ansible-navigator run example.yaml -i inventory.yaml

Here is the new inventory directory structure that was created :

$ tree inventory
inventory
├── host_vars
│   └── 192.168.122.220
│       ├── bgp_address_family.yaml
│       └── bgp_global.yaml
└── inventory.yaml

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

$ cat inventory/host_vars/192.168.122.220/bgp_global.yaml 
bgp_global:
    as_number: '500'
    bgp:
        log_neighbor_changes: true
    neighbors:
    -   neighbor_address: 12.0.0.1
        peer_group: CCIE
    -   neighbor_address: 23.0.0.1
        remote_as: '500'
    -   neighbor_address: CCIE
        remote_as: '500'
        update_source: Loopback1
        version: 4
    networks:
    -   address: 10.0.0.0

Please note that when running network.bgp action for the first time, we specified inventory explicitly and this could result in something similar to what is shown below:

$ cat inventory.yaml 
all:
  children:
    ios:
      hosts:
        192.168.122.220:
      vars:
        ansible_ssh_user: cisco
        ansible_ssh_pass: cisco
        ansible_connection: ansible.netcommon.network_cli

Using the deploy action - Deploy BGP  Configuration

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

Let’s change update_source to Loopback0  in the bgp_global.yaml file as shown below:

$ cat inventory/host_vars/192.168.122.220/bgp_global.yaml 
bgp_global:
    as_number: '500'
    bgp:
        log_neighbor_changes: true
    neighbors:
    -   neighbor_address: 12.0.0.1
        peer_group: CCIE
    -   neighbor_address: 23.0.0.1
        remote_as: '500'
    -   neighbor_address: CCIE
        remote_as: '500'
        update_source: Loopback0
        version: 4
    networks:
    -   address: 10.0.0.0

Now that we have modified the bgp_global 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: network.bgp.run
      vars:
        ansible_network_os: cisco.ios.ios
        actions:
          - name: deploy

Execute the Ansible Playbook with the ansible-navigator:

$ ansible-navigator run example.yaml

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

R1#show running-config | section ^router bgp
router bgp 500
 bgp log-neighbor-changes
 network 10.0.0.0
 neighbor CCIE peer-group
 neighbor CCIE remote-as 500
 neighbor CCIE password cisco123
 neighbor CCIE update-source Loopback1
 neighbor CCIE version 4
 neighbor 12.0.0.1 peer-group CCIE
 neighbor 23.0.0.1 remote-as 500

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

Using the gather action -   Display BGP Configuration

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

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network BGP Manager
      ansible.builtin.include_role:
        name: network.bgp.run
      vars:
        ansible_network_os: cisco.ios.ios
        actions:
          - name: gather

Execute the Ansible Playbook with the ansible-navigator:

$ ansible-navigator run example.yaml

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": {
            "as_number": "500"
        },
        "resource_module_name": "cisco.ios.ios_bgp_address_family"
    }
}
…

We can also see the detailed output here.

Using the detect action - Detect configuration drift

The detect action will read the facts from the provided/default inventory and detect if any configuration changes are there on the appliances:

For example, let's change update_source to Loopback1 within bgp_global host_vars in our inventory as shown below.

$ cat inventory/host_vars/192.168.122.220/bgp_global.yaml 
bgp_global:
    as_number: '500'
    bgp:
        log_neighbor_changes: true
    neighbors:
    -   neighbor_address: CCIE
        remote_as: '500'
        update_source: Loopback1
        version: 4
    networks:
    -   address: 10.0.0.0
…

The detect task can be shown as below:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network BGP Manager
      ansible.builtin.include_role:
        name: network.bgp.run
      vars:
        ansible_network_os: cisco.ios.ios
        actions:
          - name: detect

Execute the Ansible Playbook with the ansible-navigator:

$ ansible-navigator run example.yaml

Here is snippet from the output of the gather action:

We can also see the detailed output here.

Using the remediate action - Remediate configuration drift

The remediate action will read the facts from the provided/default inventory and remediate if there are any configuration changes on the appliances. This is done by overriding the running configuration with read facts from the provided/default inventory.

For example, last time we changed update_source to Loopback1 for the detect action and now we can actually use the remediate action to apply those changes as shown here:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network BGP Manager
      ansible.builtin.include_role:
        name: network.bgp.run
      vars:
        ansible_network_os: cisco.ios.ios
        actions:
          - name: remediate

Execute the Ansible Playbook with the ansible-navigator:

$ ansible-navigator run example.yaml

Here is snippet from the output of the gather action:

TASK [network.base.resource_manager : Apply provided configuration] ************
changed: [192.168.122.220] => {
    "after": {
        "as_number": "500",
        "bgp": {
            "log_neighbor_changes": true
        },
        "neighbors": [
            {
                "neighbor_address": "12.0.0.1",
                "peer_group": "CCIE"
            },
            {
                "neighbor_address": "23.0.0.1",
                "remote_as": "500"
            },
            {
                "neighbor_address": "CCIE",
                "remote_as": "500",
                "update_source": "Loopback1",
                "version": 4
            }
        ],
        "networks": [
            {
                "address": "10.0.0.0"
            }
        ]
    },
    "ansible_connection": "ansible.netcommon.network_cli",
    "ansible_network_os": "cisco.ios.ios",
    "changed": true,
    "commands": [
        "router bgp 500",
        "neighbor CCIE update-source Loopback1"
    ],

We can also see the detailed output here.

Using the health_check action - Run Health Checks

 The health_check action enables users to be able to perform certain BGP health-checks as mentioned below.

  • all_neighbors_up: This health-check returns successful only when all the BGP neighbors are up and running.
  • all_neighbors_down: This health-check returns successful only when all the neighbors are down.
  • min_neighbors_up: This health-check takes min_count as input and returns successful only when the minimum number of  many neighbors are up and running.
  • bgp_status_summary: This health-check provides the BGP status summary.

Here is an Ansible Playbook example of using action: health_check  with all_neighbors_up check and displaying the result:

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network BGP Manager
      ansible.builtin.include_role:
        name: network.bgp.run
      vars:
        ansible_network_os: cisco.ios.ios
        actions:
          - name: health_check
            vars:
              checks:
                - name: all_neighbors_up

Execute the Ansible Playbook with the ansible-navigator

$ ansible-navigator run example.yaml

Here is the provided result:

fatal: [192.168.122.220]: FAILED! => {
    "failed_when_result": true,
    "health_checks": {
        "all_neighbors_up": {
            "check_status": "unsuccessful",
            "down": 1,
            "total": 2,
            "up": 1
        },
        "status": "unsuccessful"
    }
}
…

Please note that the performed health all_neighbors_up has failed. The reason it failed is because there were a total of two BGP neighbors and only one of the neighbors was in the Established state.

We can also perform a health-check where we want some minimum number of neighbors. With this health check we will also use the details variable to get more details about the BGP neighborship state.

---
- hosts: ios
  gather_facts: false
  tasks:
    - name: Network BGP Manager
      ansible.builtin.include_role:
        name: network.bgp.run
      vars:
         ansible_network_os: cisco.ios.ios
         actions:
          - name: health_check
            vars:
              details: true
              checks:
                - name: min_neighbors_up
                  min_count: 1

Execute the Ansible Playbook with the ansible-navigator:

$ ansible-navigator run example.yaml

Here is the provided result:

TASK [network.bgp.run : BGP health checks] *************************************************************************
ok: [192.168.122.220] => {
    "failed_when_result": false,
    "health_checks": {
        "min_neighbors_up": {
            "check_status": "successful",
            "details": {
                "neighbors": [
                    {
                        "bgp_table_version": 3,
                        "input_queue": 0,
                        "msg_rcvd": 19169,
                        "msg_sent": 19183,
                        "output_queue": 0,
                        "peer": "12.0.0.1",
                        "peer_as": 500,
                        "peer_state": "Established",
                        "uptime": "1w5d",
                        "version": 4
                    }
                ]
            },
            "down": 1,
            "total": 2,
            "up": 1
        },
        "status": "successful"
    }
}
PLAY RECAP ***************************************************************
192.168.122.220              : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
…

This time, we have a successful health check, as we had one BGP neighbor in the Established state, and also we have detailed neighbor attributes like version, uptime, etc.

Takeaways & Next Steps

As shown above, with the help of the Network BGP validated content, we can enhance the experience of resource module consumption by providing production-ready content. By using the persist, gather, detect, remediate and deploy actions, network engineers can gain much more flexibility and adopt platform Network BGP automation. We can also perform health checks on BGP neighborship with the health_check action.

If you want to learn more about the Red Hat 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

Browse by channel

automation icon

Automation

The latest on IT automation that spans tech, teams, and environments

AI icon

Artificial intelligence

Explore the platforms and partners building a faster path for AI

open hybrid cloud icon

Open hybrid cloud

Explore how we build a more flexible future with hybrid cloud

security icon

Security

Explore how we reduce risks across environments and technologies

edge icon

Edge computing

Updates on the solutions that simplify infrastructure at the edge

Infrastructure icon

Infrastructure

Stay up to date on the world’s leading enterprise Linux platform

application development icon

Applications

The latest on our solutions to the toughest application challenges

Original series icon

Original shows

Entertaining stories from the makers and leaders in enterprise tech