TextFSM Value Key
Today, thanks to a question from a listener, I decided to figure out what Value Key
means in TextFSM templates. Previously, for some reason, I thought that this was
to check the uniqueness of the value, but a quick check showed that this was not the case.
Key can be used to create a link between multiple templates and combine the data into a single data structure.
As far as I understand it only works with clitable
Basic Example
For example, we have the output of two show commands: the first shows the IP address and MAC address, and the second shows vlan, mac and port.
IP address Hardware address
---------------- --------------------
192.168.100.1 00:11:22:33:44:01
192.168.100.2 00:11:22:33:44:02
192.168.100.3 00:11:22:33:44:03
192.168.100.4 00:11:22:33:44:04
#sh mac address-table
Vlan Mac Address Port Type
------------ --------------------- ---------- ----------
1 00:11:22:33:44:01 Po1 dynamic
2 00:11:22:33:44:02 Po2 dynamic
3 00:11:22:33:44:03 Po3 dynamic
4 00:11:22:33:44:04 Po4 dynamic
5 00:11:22:33:44:05 Po5 dynamic
From these two outputs, you need to get the following data.
[['192.168.100.1', '00:11:22:33:44:01', '1', 'Po1'],
['192.168.100.2', '00:11:22:33:44:02', '2', 'Po2'],
['192.168.100.3', '00:11:22:33:44:03', '3', 'Po3'],
['192.168.100.4', '00:11:22:33:44:04', '4', 'Po4']]
IP address and MAC address from the first output are combined with the corresponding VLAN and port from the second output. Data is combined based on MAC address match.
Of course, this can be done with Python by making separate TextFSM templates for each output, but as it turns out, this can also be achieved by TextFSM itself.
Magic
You need to create templates for each output, but with one caveat - mac must be marked as Key.
templates/1.txt:
Value ip ([\d.]+)
Value Key mac (\S+)
Start
^${ip} +${mac} -> Record
templates/2.txt:
Value vlan (\S+)
Value Key mac ([\w:]+)
Value port (\S+)
Start
^ *${vlan} +${mac} +${port} +\S+$$ -> Record
In the index file, both templates must be written in the first column separated by a colon (templates/index file):
Template, Hostname, Vendor, Command
sh_ip_int_br.txt, .*, cisco_ios, sh[[ow]] ip int[[erface]] br[[ief]]
1.txt:2.txt, .*, cisco_ios, sh[[ow]] mac
For comparison, an example of a regular template specification is shown (sh_ip_int_br.txt).
Basically, that’s all. We write code to use clitable and get the result:
from pprint import pprint
from textfsm import clitable
def parse_output_textfsm(output, attributes_dict, pth="templates", index="index"):
cli = clitable.CliTable(index, pth)
cli.ParseCmd(output, attributes_dict)
data = [list(item) for item in cli]
return data
if __name__ == "__main__":
with open("output_sh_mac.txt") as f:
output = f.read()
pprint(parse_output_textfsm(output, {"Command": "sh mac"}))
Output
[['192.168.100.1', '00:11:22:33:44:01', '1', 'Po1'],
['192.168.100.2', '00:11:22:33:44:02', '2', 'Po2'],
['192.168.100.3', '00:11:22:33:44:03', '3', 'Po3'],
['192.168.100.4', '00:11:22:33:44:04', '4', 'Po4']]
Sources
stackoverflow
Use a captured value as row identifier