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.