[python]Convert TextFSM nested list data into dictionary

Introduction

Reference: http://gratuitousarp.info/a-quick-example-of-using-textfsm-to-parse-data-from-cisco-show-commands/

The reference article alluded a method known as value_map, I immediately knew it is possible to change to dictionary easily when I saw the output of value_map.
nor34
This is how the output of value_map looks like, and this explains how the variable maps to the regex, if you are using re module “neat” and wish to convert the results into dictionary then the output of value_map is exactly what you need to write, then you call the re.groupdict, you can read this post which has a python code example at the end of the post to understand more.

Netmiko does not have textfsm template to match show int ip brief

One thing about Cisco’s network products is its command line structure is not consistent. Cisco ASA’s OS commands are different from Cisco IOS XE commands, such as show ip int brief on IOS XE and show int ip brief on ASA OS. Netmiko has a readily made template to match show ip int brief but does not have one template for the ASA, this is when understanding how to use TextFSM becomes important.

TextFSM template to match Cisco ASA’s show int ip bri

This is the TextFSM template which worked:

Value interface (\S+)
Value ip_address (\d+\.\d+\.\d+\.\d+|unassigned)
Value admin_status (administratively down|down|up)
Value proto_status (up|down)


Start
 ^\s*${interface}\s+${ip_address}\s+YES\s+CONFIG\s+${admin_status}\s+${proto_status} -> Record

Convert TextFSM output to dictionary

Refer to the above TextFSM template for show int ip brief, each variable defined by the keyword Value is group with a prefix of ?p, each of this group is actually known as “header” in TextFSM’s context, you can enumerate these values with the header method for example:

with open("../network/templates/show_int_ip_brief.textfsm", "r") as t:
    template = TextFSM(t)
print(template.header)

which looks like this:
['interface', 'ip_address', 'admin_status', 'proto_status']

In python you can group two lists together by using zip function. You can convert the zip object into another list or tuple or dictionary.

The TextFSM output after parsed is a nested list which looks like this:
[['Management0/0', '192.168.100.30', 'up', 'up']]

So by using list comprehension we can concatenate the dict together to get a list of dictionary. See this code:

from network.ciscoasa import connect_asa_host
from textfsm import TextFSM
from nornir.plugins.tasks.networking import netmiko_send_command
from pprint import pprint


fw02 = connect_asa_host(hostname="fw02")
response = fw02.run(task=netmiko_send_command, command_string="sh interface ip brief")
with open("../network/templates/show_int_ip_brief.textfsm", "r") as t:
    """
    Create a template object from the template file.
    """
    template = TextFSM(t)

result_for_parsing = response["fw02"][0].result

# parsed_result is a nested list
parsed_result = template.ParseText(result_for_parsing)

# the TextFSM object has a value_map method.
#pprint(template.value_map)

# combine the template.header and pr with zip, then change the zip object into dict object.
# pr is obtained from list comprehension, template.header is list of Value defined in template.
collection_of_results = [dict(zip(template.header, pr)) for pr in parsed_result]
pprint(collection_of_results)

The output will be like this:
nor37

The actual output in the fw02 cisco ASA:
nor36

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s