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
.
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:
The actual output in the fw02 cisco ASA: