将 Junos PyEZ 表与 TextFSM 模板配合使用
Junos PyEZ 操作 (op) 表可以单独引用 TextFSM 模板,也可以与 Junos PyEZ 视图一起使用引用 TextFSM 模板,以解析来自任何网络设备的 CLI 或 VTY 命令输出。
了解 TextFSM 模板
Junos PyEZ 操作表可以从网络设备的 CLI 或 VTY 命令输出中提取数据。表可以引用视图以将命令输出中的字段映射到 Python 对象。Junos PyEZ op 表还可以单独或与视图一起引用 TextFSM 模板来解析命令输出。Junos PyEZ op 表可以使用 TextFSM 模板来解析来自任何网络设备的命令输出,无论供应商、网络操作系统或命令如何。
TextFSM 是一个 Python 库,用于解析来自网络设备的半格式化 CLI 输出,例如 show 命令输出。它由 Google 开发,后来在 Apache 2.0 许可下发布。该模块需要一个模板和一些输入文本。该模板使用正则表达式来描述如何解析数据,您可以定义多个模板并将其应用于同一数据。
TextFSM的 CliTable 类使用户能够将给定平台上的命令映射到解析命令输出的模板。网络自动化公司 Network to Code 开发了 Python 包装器 CliTable 以及 用于网络设备的 TextFSM 模板存储库。您可以根据需要在 Junos PyEZ 服务器或虚拟环境中安装该 ntc-templates 库。然后引用 Junos PyEZ 表中的 NTC 模板和其他 TextFSM 模板。
NTC 模板可解析网络设备的 show 命令输出。每个 NTC 模板定义给定命令的预期输出字段,并为每个项将数据映射到标头。NTC 模板文件名标识平台(供应商和网络操作系统)和命令(带下划线),以便系统可以轻松确定要使用的模板。文件名格式使用以下语法:
platform_command.textfsm
例如,考虑 juniper_junos_show_arp_no-resolve.textfsm 模板。
Value Required MAC_ADDRESS ([A-Fa-f0-9\:]{17})
Value Required IP_ADDRESS ([A-Fa-f0-9:\.]+)
Value Required INTERFACE (\S+)
Value FLAGS (\S+)
Start
^MAC\s+Address\s+Address\s+Interface\s+Flags\s*$$
^${MAC_ADDRESS}\s+${IP_ADDRESS}\s+${INTERFACE}\s+${FLAGS} -> Record
^Total.*
^\s*$$
^{master:\d+}
^. -> Error
该模板可 show arp no-resolve 解析运行 Junos OS 或 Junos OS 演化版的瞻博网络设备的命令输出。
user@host> show arp no-resolve MAC Address Address Interface Flags 02:01:00:00:00:05 10.0.0.5 em0.0 none 30:7c:5e:48:4b:40 198.51.100.77 fxp0.0 none f8:c0:01:18:8b:67 198.51.100.254 fxp0.0 none 02:00:00:00:00:10 172.16.0.50 em0.0 none Total entries: 4
Junos PyEZ 操作表可以使用 NTC 模板或其他 TextFSM 模板来解析非结构化命令输出。该表通过定义以下字段来使用 TextFSM 模板。Junos PyEZ 使用和platformcommand值来确定模板的文件名。
-
command: command- 生成要解析的输出的命令。命令必须映射到 NTC 模板或其他 TextFSM 模板文件名中的命令字符串。 -
key: key- 在 TextFSM 模板或 Junos PyEZ 视图中定义的字段,用于唯一标识记录项。 -
platform: platform- TextFSM 模板的供应商和操作系统,例如juniper_junos。平台值必须与 NTC 模板或其他 TextFSM 模板文件名中的平台字符串匹配。 -
use_textfsm: True- 设置为True以使用给定平台和命令的 TextFSM 模板解析命令输出。
如何使用 TextFSM 模板解析命令输出
Junos PyEZ 表可以使用 TextFSM 模板(包括预定义的 NTC 模板)来解析 Junos 设备的 show 命令输出。
要在 Junos PyEZ 表中使用 TextFSM 模板,请执行以下操作:
-
在 Junos PyEZ 服务器或虚拟环境中安装该
ntc-templates库。user@host:~$ pip install ntc-templates
-
创建自定义 Junos PyEZ 表,其中包括
command、 、keyplatform和use_textfsm参数,以及操作所需的任何其他参数。--- ArpTableTextFSM: command: show arp no-resolve platform: juniper_junos key: MAC_ADDRESS use_textfsm: True
Junos PyEZ 应用程序使用 和
command值platform来确定模板的文件名,在本例中为 juniper_junos_show_arp_no-resolve.textfsm。该key值必须与模板中的标头匹配。 -
创建使用表检索数据的 Junos PyEZ 应用程序。
import json from pprint import pprint import yaml from yamlloader import ordereddict from jnpr.junos import Device from jnpr.junos.factory.factory_loader import FactoryLoader yaml_table = """ --- ArpTableTextFSM: command: show arp no-resolve platform: juniper_junos key: MAC_ADDRESS use_textfsm: True """ globals().update(FactoryLoader().load(yaml.load(yaml_table, Loader=ordereddict.Loader))) with Device(host='router1.example.net') as dev: arp_stats = ArpTableTextFSM(dev).get() pprint(json.loads(arp_stats.to_json()))
-
执行应用程序。
user@host:~$ python junos-pyez-arptable-textfsm.py {'02:00:00:00:00:10': {'FLAGS': 'none', 'INTERFACE': 'em0.0', 'IP_ADDRESS': '172.16.0.50'}, '02:01:00:00:00:05': {'FLAGS': 'none', 'INTERFACE': 'em0.0', 'IP_ADDRESS': '10.0.0.5'}, '30:7c:5e:48:4b:40': {'FLAGS': 'none', 'INTERFACE': 'fxp0.0', 'IP_ADDRESS': '198.51.100.77'}, 'f8:c0:01:18:8b:67': {'FLAGS': 'none', 'INTERFACE': 'fxp0.0', 'IP_ADDRESS': '198.51.100.254'}}该表使用 NTC 模板提取输出字段。对于每个表项,应用程序返回定义的键和每个字段的数据。
如何将 TextFSM 模板与 Junos PyEZ 视图配合使用来解析命令输出
Junos PyEZ 表可以组合 TextFSM 模板和 Junos PyEZ 视图来解析命令输出。TextFSM 模板将数据映射到标头。在视图中,您可以将变量名称映射到模板中定义的要返回的字段的标题。将模板和视图组合在一起,例如,当您想要使用与模板中定义的变量名称不同的变量名称时,或者当您想要返回不同的字段时。Junos PyEZ 仅返回 TextFSM 模板和 Junos PyEZ 视图通用的字段。
以下示例使用 juniper_junos_show_arp_no-resolve.textfsm 模板来解析命令输出。Junos PyEZ 视图将数据映射到新的变量名称,并仅返回字段的子集。要查看模板,请参阅 了解 TextFSM 模板。
要在 Junos PyEZ 表中使用 TextFSM 模板和视图:
-
创建自定义 Junos PyEZ 表,其中包括
command、key、platformuse_textfsm、 和view参数,以及操作所需的任何其他参数。--- ArpTableTextFSM2: command: show arp no-resolve platform: juniper_junos key: - ip - mac use_textfsm: True view: ArpViewTextFSM2 -
创建 Junos PyEZ 视图,定义要返回的模板字段以及每个字段的相应变量名称。
ArpViewTextFSM2: fields: mac: MAC_ADDRESS ip: IP_ADDRESS interface: INTERFACE在这种情况下,视图不会映射
FLAGSTextFSM 模板中定义的字段,并且解析的数据不包含此值。 -
创建使用表检索数据的 Junos PyEZ 应用程序。
import json from pprint import pprint import yaml from yamlloader import ordereddict from jnpr.junos import Device from jnpr.junos.factory.factory_loader import FactoryLoader yaml_table = """ --- ArpTableTextFSM2: command: show arp no-resolve platform: juniper_junos key: - ip - mac use_textfsm: True view: ArpViewTextFSM2 ArpViewTextFSM2: fields: mac: MAC_ADDRESS ip: IP_ADDRESS interface: INTERFACE """ globals().update(FactoryLoader().load(yaml.load(yaml_table, Loader=ordereddict.Loader))) with Device(host='router1.example.net') as dev: arp_stats = ArpTableTextFSM2(dev).get() pprint(json.loads(arp_stats.to_json()))
-
执行应用程序。
user@host:~$ python junos-pyez-arptable-textfsm2.py {"('10.0.0.5', '02:01:00:00:00:05')": {'interface': 'em0.0', 'ip': '10.0.0.5', 'mac': '02:01:00:00:00:05'}, "('172.16.0.50', '02:00:00:00:00:10')": {'interface': 'em0.0', 'ip': '172.16.0.50', 'mac': '02:00:00:00:00:10'}, "('198.51.100.254', 'f8:c0:01:18:8b:67')": {'interface': 'fxp0.0', 'ip': '198.51.100.254', 'mac': 'f8:c0:01:18:8b:67'}, "('198.51.100.77', '30:7c:5e:48:4b:40')": {'interface': 'fxp0.0', 'ip': '198.51.100.77', 'mac': '30:7c:5e:48:4b:40'}}该表使用 NTC 模板和 Junos PyEZ 视图来提取输出字段。对于每个表项,应用程序将返回“视图”中定义的字段的定义键和数据。
如何使用自定义 TextFSM 模板
Junos PyEZ 表可以使用作为软件包的一部分 ntc-templates 安装的 TextFSM 模板。它们还可以引用自定义 TextFSM 模板。要在 Junos PyEZ 应用程序中使用自定义 TextFSM 模板,必须先暂存模板。然后,当您在应用程序中定义 Table 实例时,指定模板目录的绝对路径。
要在 Junos PyEZ 表中使用自定义 TextFSM 模板,请执行以下操作:
-
为您的自定义模板创建目录。
user@host:~$ mkdir TextFSMTemplates
-
在 templates 目录中,创建模板并使用 .textfsm 文件名约定命名platform_command文件。
user@host:~$ vi TextFSMTemplates/my_platform_show_arp_no-resolve.textfsm
-
创建一个 Junos PyEZ 表,其定义与模板文件名相同的
platform和command值。--- ArpTableTextFSM3: command: show arp no-resolve platform: my_platform key: - MAC_ADDRESS - IP_ADDRESS use_textfsm: True -
在 Junos PyEZ 应用程序中,定义 Table 实例时,指定自定义模板目录的绝对路径。
import json from pprint import pprint import yaml from yamlloader import ordereddict from jnpr.junos import Device from jnpr.junos.factory.factory_loader import FactoryLoader yaml_table = """ --- ArpTableTextFSM3: command: show arp no-resolve platform: my_platform key: - MAC_ADDRESS - IP_ADDRESS use_textfsm: True """ globals().update(FactoryLoader().load(yaml.load(yaml_table, Loader=ordereddict.Loader))) with Device(host='router1.example.net') as dev: arp_stats = ArpTableTextFSM3(dev, template_dir='/home/user/TextFSMTemplates').get() pprint(json.loads(arp_stats.to_json()))
-
执行应用程序。
user@host:~$ python junos-pyez-arptable-textfsm3.py
如何使用带有 TextFSM 模板的 Junos PyEZ 表来解析任何供应商的命令输出
Junos PyEZ 表可以使用 TextFSM 模板来解析来自任何供应商网络设备的命令输出。Python 应用程序可以从设备检索输出,也可以从文件读取输出。然后,在创建 Junos PyEZ 表实例时,可以将命令输出字符串传递给表的 raw 参数,而不是传入 Device 实例。
例如,请考虑以下 TextFSM 模板:
user@host:~$ cat TextFSMTemplates/cisco_xr_show_alarms_detail.textfsm
Value Required description (.+?)
Value Required location (\S+)
Value aid (\S+)
Value tag (\S+)
Value module (\S+)
Start
# Match the timestamp at beginning of command output
^Active Alarms (Detail) for .+
^-+ -> Continue.Record
^Description:\s+${description}\s*$$
^Location:\s+${location}
^AID:\s+${aid}
^Tag String:\s+${tag}
^Module Name:\s+${module}
该模板将 show alarms detail 解析来自给定设备的命令输出。
RP/0/RP0/CPU0:host#show alarms detail Wed May 5 12:17:00.187 UTC -------------------------------------------------------------------------------- Active Alarms (Detail) for 0/RP0 -------------------------------------------------------------------------------- Description: hw_optics: RX LOS LANE-0 ALARM Location: 0/RP0/CPU0 AID: XR/HW_OPTICS/5 Tag String: DEV_SFP_OPTICS_PORT_RX_LOS_LANE0 Module Name: Optics0/0/0/31 EID: CHASSIS/LCC/1:CONTAINER/CC/1:PORT/OPTICS/31 Reporting Agent ID: 196713 Pending Sync: false Severity: Major Status: Set Group: Software Set Time: 04/27/2021 09:47:16 UTC Clear Time: - Service Affecting: NotServiceAffecting Transport Direction: NotSpecified Transport Source: NotSpecified Interface: N/A Alarm Name: OPTICS RX LOS LANE-0 -------------------------------------------------------------------------------- Description: hw_optics: RX LOS LANE-1 ALARM Location: 0/RP0/CPU0 AID: XR/HW_OPTICS/6 Tag String: DEV_SFP_OPTICS_PORT_RX_LOS_LANE1 Module Name: Optics0/0/0/31 EID: CHASSIS/LCC/1:CONTAINER/CC/1:PORT/OPTICS/31 Reporting Agent ID: 196713 Pending Sync: false Severity: Major Status: Set Group: Software Set Time: 04/27/2021 09:47:16 UTC Clear Time: - Service Affecting: NotServiceAffecting Transport Direction: NotSpecified Transport Source: NotSpecified Interface: N/A Alarm Name: OPTICS RX LOS LANE-1 ...
以下示例定义了一个Junos PyEZ 表,该表使用自定义 TextFSM 模板 cisco_xr_show_alarms_detail.textfsm 和 View 来解析 show alarms detail 命令输出。该示例使用库直接 netmiko 从设备检索数据。当应用程序创建 Table 实例时, raw 参数将传入命令输出,并且参数 template_dir 定义包含自定义模板的目录的路径。
import json from pprint import pprint import yaml from yamlloader import ordereddict from netmiko import ConnectHandler from jnpr.junos.factory.factory_loader import FactoryLoader yaml_table = """ --- XRAlarmsTable: command: show alarms detail key: - description - location platform: cisco_xr use_textfsm: True view: XRAlarmsView XRAlarmsView: fields: description: description location: location aid: aid tag: tag module: module severity: severity status: status group: group time: time affect: affect """ dev_credentials = { 'device_type': 'cisco_xr', 'host': '198.51.100.101', 'username': 'admin', 'password': 'password', } net_connect = ConnectHandler(**dev_credentials) output = net_connect.send_command('show alarms detail') globals().update(FactoryLoader().load(yaml.load(yaml_table, Loader=ordereddict.Loader))) stats = XRAlarmsTable(raw=output, template_dir='/home/user/TextFSMTemplates').get() pprint(json.loads(stats.to_json())) with open('show-alarms-detail.txt', 'w') as fp: fp.write(output)
当您执行应用程序时,它会从设备检索命令输出。然后,应用程序使用指定目录中的 TextFSM 模板以及 View 来解析输出。Junos PyEZ 仅返回 TextFSM 模板和 Junos PyEZ 视图通用的字段。应用程序会将命令输出保存到文件中,以便您稍后可以处理输出,如下一个示例所示。
user@host:~$ python junos-pyez-textfsm-alarms.py
{"('hw_optics: RX LOL LANE-0 ALARM', '0/RP0/CPU0')": {'aid': 'XR/HW_OPTICS/29',
'description': 'hw_optics: '
'RX LOL '
'LANE-0 '
'ALARM',
'location': '0/RP0/CPU0',
'module': 'Optics0/0/0/31',
'tag': 'DEV_SFP_OPTICS_PORT_RX_CDR_LOL_LANE0'},
"('hw_optics: RX LOL LANE-1 ALARM', '0/RP0/CPU0')": {'aid': 'XR/HW_OPTICS/30',
'description': 'hw_optics: '
'RX LOL '
'LANE-1 '
'ALARM',
'location': '0/RP0/CPU0',
'module': 'Optics0/0/0/31',
'tag': 'DEV_SFP_OPTICS_PORT_RX_CDR_LOL_LANE1'},
...
以下示例使用与上一个示例相同的 TextFSM 模板和 Junos PyEZ 视图,但在这种情况下,应用程序会从文件中读取命令输出。
import json from pprint import pprint import yaml from yamlloader import ordereddict from jnpr.junos.factory.factory_loader import FactoryLoader yaml_table = """ --- XRAlarmsTable: command: show alarms detail key: - description - location platform: cisco_xr use_textfsm: True view: XRAlarmsView XRAlarmsView: fields: description: description location: location aid: aid tag: tag module: module severity: severity status: status group: group time: time affect: affect """ with open('show-alarms-detail.txt') as fp: output = fp.read() globals().update(FactoryLoader().load(yaml.load(yaml_table, Loader=ordereddict.Loader))) stats = XRAlarmsTable(raw=output, template_dir='/home/user/TextFSMTemplates').get() pprint(json.loads(stats.to_json()))