Ease in Automation: Convert Router Output to Json Format

In this article we will be talking about converting the output from Cisco XR into a Json File for further utilization or automation. The following code can be used and can be redesigned to work with several other commands and output in other variants of Cisco XE, XR etc., as well as other vendor devices.

Requirements:
> Python3
> Netmiko
> TextFSM
> Json

Netmiko library is one of the most useful libraries made. We can use this library with several other vendors as defined on this website: https://ktbyers.github.io/netmiko/docs/netmiko/index.html

TextFSM library is made by Google. It is a state machine which uses regular expression to parse the output in a template defined by us.

Json library is required so that we dump the data in the json format. json.loads take a string as input and returns a dictionary as output. json.dumps take a dictionary as input and returns a string as output.

Let’s start:

Make sure to pip install netmiko and textfsm before proceeding with the below code:

from netmiko import ConnectHandler
import jtextfsm as textfsm
import json
IP="DEVICE IP"
username="YOURUSERNAME"
password="YOURPASS"
port=[PORT NUMBER]
dev=ConnectHandler(device_type='cisco_xr',ip=IP,username=username,password=password, port = port)
output=dev.send_command("show bgp summary")

#****Template Parser code*********#
template=open("showbgp.textfsm")
re_t=textfsm.TextFSM(template)
fsm_res=re_t.ParseText(output)
print(fsm_res)

#********json Template code********#
info={}
data={"Neighbors":info}
li=re_t.header  #this will get the headings we got from our output with above regex.c=len(fsm_res)
count=0
for i in fsm_res:
  count=count+1 
  id=count
  info[id]=dict(zip(li,i))
print(json.dumps(data,indent=4))
dev.disconnect()
print('done')

The above code is pretty normal and neat, we are getting the output in the “output” variable for show bgp summary and we are putting it in textfsm format and getting a list of list output, then converting the Multi-list which is stored in “fsm_res” to json format.

The next most important thing is writing a regex to filter-out the output that we want. The creation of this regex textfsm file is very easy and for testing purpose you can also use https://regex101.com/ to see if you are filtering out the output that you actually want. Make Sure to put both the files in the same directory before running this.

file : showbgp.textfsm

Value Neighbor (\d+.\d+.\d+.\d+.)
Value Spk (\d+)
Value AS (\d+)
Value MsgRcvd (\d+)
Value MsgSent (\d+)
Value TblVer (\d+)
Value InQ (\d+)
Value OutQ (\d+)
Value up_down (\d+:\d+:\d+)
Value St (\S+)

Start
  ^${Neighbor}\s+${Spk}+\s+${AS}+\s+${MsgRcvd}\s+${MsgSent}+\s+${TblVer}+\s+${InQ}\s+${OutQ}+\s+${up_down}+\s+${St} -> Record

EOF

Let’s go step by step to understand how we created this file:

The “Value” defines the variable name, now you can have anything defined under variable name, you can put the variable name anything you like. But here the most important part is the regex value that are defined after the variable. Example:

Value Neighbor (\d+.\d+.\d+.\d+.)

Value is a predefined Textfsm keyword which defines the variable and your regex.

Neighbor here is nothing but the variable name, which can be anything.

(\d+.\d+.\d+.\d+.) regex defines what type of information/value from the output, the Neighbor variable will carry. The regex (\d+.\d+.\d+.\d+.) means this is an IP address.

 

Now let’s look into the output that we are getting from the device and the output that we want:

BGP router identifier *.*.*.*, local AS number 198
BGP generic scan interval 60 secs
Non-stop routing is enabled
BGP table state: Active
Table ID: 0xe0000000 RD version: 10
BGP main routing table version 10
BGP NSR Initial initsync version 9 (Reached)
BGP NSR/ISSU Sync-Group versions 0/0
BGP scan interval 60 secs

BGP is operating in STANDALONE mode.

Process RcvTblVer bRIB/RIB LabelVer ImportVer SendTblVer StandbyVer
Speaker 10 10 10 10 10 0

Some configured eBGP neighbors (under default or non-default vrfs)
do not have both inbound and outbound policies configured for IPv4 Unicast
address family. These neighbors will default to sending and/or
receiving no routes and are marked with '!' in the output below.
Use the 'show bgp neighbor <nbr_address>' command for details.

Neighbor Spk AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down St/PfxRcd
10.10.20.20 0 13999 0 0 0 0 0 00:00:00 Idle!
192.168.1.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.2.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.3.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.4.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.5.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.6.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.7.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.8.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.9.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.10.2 0 199 0 0 0 0 0 00:00:00 Idle
192.168.11.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.12.2 0 199 0 0 0 0 0 00:00:00 Active
192.168.13.2 0 199 0 0 0 0 0 00:00:00 Active
198.0.0.1 0 198 0 0 0 0 0 00:00:00 Idle
198.18.58.54 0 22773 0 0 0 0 0 00:00:00 Idle
199.38.111.145 0 9644 6383 6383 0 0 0 3d09h Active


See we want output starting with first IP under Neighbor:
Neighbor Spk AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down St/PfxRcd
10.10.20.20 0 13999 0 0 0 0 0 00:00:00 Idle!
192.168.1.2 0 199 0 0 0 0 0 00:00:00 Active
...

So to get the output from neighbor ip which is actually IP (10.10.20.20), we need to create a regex which could cover IP address uptill Idle! value and these values will be stored in the Variables you have defined under the regex like varibale Neighbor will carry IP address, Spk will carry 0 and so on…

The working regex in our scenario is:
^(\d+.\d+.\d+.\d+.)\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+:\d+:\d+)\s+(\S+)

Use the above regex on website regex101, the link given above to verify if you selecting the correct values that you want.


Now the variables that you have defined above with the regex will substitute the value in :
^${Neighbor}\s+${Spk}+\s+${AS}+\s+${MsgRcvd}\s+${MsgSent}+\s+${TblVer}+\s+${InQ}\s+${OutQ}+\s+${up_down}+\s+${St} -> Record

When the textfsm will read the file after the Start value is defined.

Any output can be filtered out using the regex that you will create and this data can be written in any format of your liking.

I hope you find the above article helpful while automating your network.

%d bloggers like this: