Network Automation using YANG Models across XE, XR, & NX

Configure BGP with YDK-Python on XR


Now that you understand the some of the basics of how to use YDK providers in conjunction with models and NETCONF, let's work through a more practical example where we configure BGP peering between our devices.

In this exercise, we will configure two eBGP peers on our XRv device using YDK, YANG, and OpenConfig BGP models.

Create New Python File

Return to Visual Studio Code and create a new Python file called ydk_xr_bgp_conf.py. You can copy this file name below for ease.


ydk_xr_bgp_conf.py

Imports Required

You will need to import the same CRUDService, NetconfServiceProver, and openconfig_bgp model as before. In addition, for the full configuration sequence openconfig_bgp_types is also required.

        
            from ydk.services import CRUDService
            from ydk.providers import NetconfServiceProvider
            from ydk.models.openconfig import openconfig_bgp as oc_bgp
            from ydk.models.openconfig import openconfig_bgp_types as oc_bgp_types
            

Instantiate the NETCONF Provider

As we did in the previous module, you again need a NetConfServiceProvider, CRUD service, and instance of the BGP model instantiated, along with enabling and attaching to the debug logger for troubleshooting YDK should an issue arise.

        
            # Mapping of device names to IPs
            duts = {
                "xrv": '10.2.100.12',
            }

            # User the XRV for this simple exercise.
            ip = duts['xrv']

            # create NETCONF session
            provider = NetconfServiceProvider(address=ip, port=830, username='admin', password='cisco.123', protocol='ssh')

            # Attach to the YDK Logger
            import logging
            logger = logging.getLogger("ydk")
            logger.setLevel(logging.DEBUG)
            handler = logging.StreamHandler()
            formatter = logging.Formatter(("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
            handler.setFormatter(formatter)
            logger.addHandler(handler)

            # create CRUD service
            crud = CRUDService()

            # Create BGP model from OpenConfig
            bgp = oc_bgp.Bgp()
            

Global BGP Configuration

Using the instantiated BGP object from the OpenConfig model, configure the following global BGP options as seen below that include the AS/ASN, router-id, and IPv4 address-family. Like you saw when dealing with raw XML, this dotted notation is referencing the leaf nodes within the top-level BGP container.

        
            # global configuration
            bgp.global_.config.as_ = 65002
            bgp.global_.config.router_id = '2.2.2.2'
            afi_safi = bgp.global_.afi_safis.AfiSafi()
            afi_safi.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.enabled = True
            bgp.global_.afi_safis.afi_safi.append(afi_safi)
            

Configure Peer Groups

Now, you're going to use peer groups, so lets configure those for this exercise that also specifies the BGP address-family and respective remote BGP ASNs:

        
            # Configure eBGP peer group for the XE
            peer_group = bgp.peer_groups.PeerGroup()
            peer_group.peer_group_name = "eBGP-XE"
            peer_group.config.peer_group_name = "eBGP-XE"
            peer_group.config.peer_as = 65001
            afi_safi = peer_group.afi_safis.AfiSafi()
            afi_safi.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.enabled = True
            peer_group.afi_safis.afi_safi.append(afi_safi)
            bgp.peer_groups.peer_group.append(peer_group)

            # Configure eBGP peer group for the NX
            peer_group = bgp.peer_groups.PeerGroup()
            peer_group.peer_group_name = "eBGP-NX"
            peer_group.config.peer_group_name = "eBGP-NX"
            peer_group.config.peer_as = 65003
            afi_safi = peer_group.afi_safis.AfiSafi()
            afi_safi.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.enabled = True
            peer_group.afi_safis.afi_safi.append(afi_safi)
            bgp.peer_groups.peer_group.append(peer_group)
            

Configure BGP Neighbors

You still need to add the XE and NX devices as neighbors using the respective peer groups. Lets continue to work with our BGP instance and add the desired neighbor objects, again this is setting leaf node within the neighbors list per the defined YANG model using object oriented dot-notation.

        
            # Add the XE neighbor
            neighbor = bgp.neighbors.Neighbor()
            neighbor.neighbor_address = "10.1.1.1"
            neighbor.config.neighbor_address = "10.1.1.1"
            neighbor.config.peer_group = "eBGP-XE"
            bgp.neighbors.neighbor.append(neighbor)

            # Add the NX neighbor
            neighbor = bgp.neighbors.Neighbor()
            neighbor.neighbor_address = "10.2.2.1"
            neighbor.config.neighbor_address = "10.2.2.1"
            neighbor.config.peer_group = "eBGP-NX"
            bgp.neighbors.neighbor.append(neighbor)
            

Commit the Changes

So far in your code, all that has been done is populate the local model instance with the desired global properties and attributes that are desired to have reflected on the device in the running-config; you have not actually altered the device state yet. To actually push the BGP configuration changes to you XRv, you will use the same CRUDService that was instantiated earlier:

        
            # Update our remote system
            result = crud.update(provider, bgp)
            


And that's it! You have now built a Python script using YDK to configure BGP by setting up two eBGP peers.

The Full Script

At this point, your script should look as follows:

        
            from ydk.services import CRUDService
            from ydk.providers import NetconfServiceProvider
            from ydk.models.openconfig import openconfig_bgp as oc_bgp
            from ydk.models.openconfig import openconfig_bgp_types as oc_bgp_types

            # Mapping of device names to IPs
            duts = {
                "xrv": '10.2.100.12',
            }

            # User the XRV for this simple exercise.
            ip = duts['xrv']

            # create NETCONF session
            provider = NetconfServiceProvider(address=ip, port=830, username='admin', password='cisco.123', protocol='ssh')

            # Attach to the YDK Logger
            import logging
            logger = logging.getLogger("ydk")
            logger.setLevel(logging.DEBUG)
            handler = logging.StreamHandler()
            formatter = logging.Formatter(("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
            handler.setFormatter(formatter)
            logger.addHandler(handler)

            # create CRUD service
            crud = CRUDService()

            # Create BGP model from OpenConfig
            bgp = oc_bgp.Bgp()

            # global configuration
            bgp.global_.config.as_ = 65002
            bgp.global_.config.router_id = '2.2.2.2'
            afi_safi = bgp.global_.afi_safis.AfiSafi()
            afi_safi.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.enabled = True
            bgp.global_.afi_safis.afi_safi.append(afi_safi)

            # Configure EBGP peer group for the CSRv
            peer_group = bgp.peer_groups.PeerGroup()
            peer_group.peer_group_name = "EBGP-CSR"
            peer_group.config.peer_group_name = "EBGP-CSR"
            peer_group.config.peer_as = 65001
            afi_safi = peer_group.afi_safis.AfiSafi()
            afi_safi.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.enabled = True
            peer_group.afi_safis.afi_safi.append(afi_safi)
            bgp.peer_groups.peer_group.append(peer_group)

            # Configure EBGP peer group for the NXv
            peer_group = bgp.peer_groups.PeerGroup()
            peer_group.peer_group_name = "EBGP-NXV"
            peer_group.config.peer_group_name = "EBGP-NXV"
            peer_group.config.peer_as = 65003
            afi_safi = peer_group.afi_safis.AfiSafi()
            afi_safi.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.afi_safi_name = oc_bgp_types.IPV4UNICAST()
            afi_safi.config.enabled = True
            peer_group.afi_safis.afi_safi.append(afi_safi)
            bgp.peer_groups.peer_group.append(peer_group)

            # Add the XE neighbor
            neighbor = bgp.neighbors.Neighbor()
            neighbor.neighbor_address = "10.1.1.1"
            neighbor.config.neighbor_address = "10.1.1.1"
            neighbor.config.peer_group = "EBGP-CSR"
            bgp.neighbors.neighbor.append(neighbor)

            # Add the NX neighbor
            neighbor = bgp.neighbors.Neighbor()
            neighbor.neighbor_address = "10.2.2.1"
            neighbor.config.neighbor_address = "10.2.2.1"
            neighbor.config.peer_group = "EBGP-NXV"
            bgp.neighbors.neighbor.append(neighbor)

            # Update our remote system
            result = crud.update(provider, bgp)
        
    

Execute Python Script

Remember to save your new YDK Python script using Ctrl+s. Return to your container in your Terminal window. Execute your new YDK Python script. Like in the example that introduced you to YDK Python, because debug logging is enabled, you will see a lot of logs. These are good, especially in a development environment to help with troubleshooting as you not only get helpful logs, but you can actually see the raw XML RPC just as you did before when working with Ansible and ncclient.

        
            cd /workspace/
            python3.6 ydk_xr_bgp_conf.py
        
    

Verify Configuration on XR

You can log back into your XRv device using xr and issue show run router bgp to verify the configuration pushed using the YDK library and NETCONF:

Issue in container:

        
            xr
        
    

Issue on XR device:

        
            show run router bgp
        
    

Your output should look similar to the below:

        
            RP/0/RP0/CPU0:Pod00-XRv#show run router bgp
            Tue May 29 14:13:21.519 UTC
            router bgp 65002
             bgp router-id 2.2.2.2
             address-family ipv4 unicast
             !
             neighbor-group eBGP-NX
              remote-as 65003
              address-family ipv4 unicast
              !
             !
             neighbor-group eBGP-XE
              remote-as 65001
              address-family ipv4 unicast
              !
             !
             neighbor 10.1.1.1
              use neighbor-group eBGP-XE
             !
             neighbor 10.2.2.1
              use neighbor-group eBGP-NX
             !
            !

            RP/0/RP0/CPU0:Pod00-XRv#
        
    

For an indepth look at OpenConfig BGP with Cisco IOS XR, check out this CiscoDevNet GitHub reference.