定义用于解析非结构化输出的 Junos PyEZ 操作表
创建自定义表,用于从 CLI 或 vty 命令输出中选择数据,以从 Junos 设备提取操作信息。
用于非结构化输出的 Junos PyEZ 操作 (op) 表可以从以下文本输出中提取数据:
-
在 Junos 设备上执行的 CLI 命令
-
在给定灵活 PIC 集中器 (FPC) 上执行的 vty 命令
然后将提取的数据转换为 JSON。非结构化输出的 Junos PyEZ op 表使您能够快速检索和分析设备的操作状态信息。当需要解析无法以结构化格式(如 XML)检索的命令输出时,这些表特别有用。
本主题讨论表的不同组件。
用于解析非结构化输出的运算表中的参数汇总
Junos PyEZ 表使用 YAML 进行格式化。运算表定义可以包括许多必需和可选参数。 表 1 总结了参数。
|
表参数名称 |
表参数 |
描述 |
|---|---|---|
|
表名称 |
– |
表的用户定义标识符。 |
|
命令 |
|
要执行的 CLI 或 vty 命令。 |
|
命令参数 |
|
(选答)当您将命令定义为 Jinja 模板时, |
|
目标 FPC |
|
(选答)执行 vty 命令的 FPC。 |
|
表项 |
|
(选答)定义如何将输出拆分为多个部分的字符串或正则表达式。这些部分成为关联视图的可迭代参考。 指定 '*' 以提取并匹配整个字符串而不是单个行。 |
|
表项键 |
|
(选答)定义一个或多个唯一标识每个表项的键的字符串或字符串列表。 |
|
选定的键 |
|
(选答)要返回数据的一个或多个表项键的列表。 |
|
章节标题 |
|
(选答)选择包含要解析的数据的输出部分的字符串。 |
|
字段分隔符 |
|
(选答)定义如何在由键值对组成的命令输出中拆分数据的分隔符。提取的数据作为键值对存储在字典中。 |
|
评估表达式 |
|
(选答)一个或多个键值对的关联数组或字典,用于将用户定义的键映射到包含数学表达式的字符串。检索数据时,将评估表达式。键和计算值将添加到表和视图返回的最终数据中。 |
|
表视图 |
|
(选答)用于从表项中提取字段数据的视图。 |
|
TextFSM 模板 |
|
(选答)布尔值,指定是否使用 TextFSM 模板来分析数据。 |
|
TextFSM 模板平台标识符 |
|
(选答)使用 TextFSM 模板时,请指定模板的平台。 |
表名称
表名称是表的用户定义标识符。YAML 文件或字符串可以包含一个或多个表。YAML 文档的开头必须保持对齐。以下示例定义了一个名为 ChassisFanTable:
--- ChassisFanTable: command: show chassis fan key: fan-name view: ChassisFanView
命令
用于非结构化输出的 Junos PyEZ 操作表从 CLI 或 vty 命令的文本输出中提取数据。您必须在表定义中包含该 command 属性,以指定要在设备上执行的 CLI 命令或要在给定 FPC 上执行的 vty 命令。您可以将命令定义为简单字符串或 Jinja 模板。
例如,下表在 show chassis fan 设备上执行命令。
--- ChassisFanTable: command: show chassis fan key: fan-name view: ChassisFanView
下表在目标FPC上执行vty show cmerror module brief 命令。
--- CMErrorTable: command: show cmerror module brief target: fpc1 key: module view: CMErrorView
将命令定义为 Jinja 模板时,还必须提供args参数。该args参数是键值对的字典,用于将模板中的变量映射到渲染模板时使用的值。有关将命令定义为 Jinja 模板的信息,请参阅命令参数 (参数)。
命令参数(参数)
您可以将参数的 command CLI 或 vty 命令定义为 Jinja 模板,用于替换命令参数的变量。使用 Jinja 模板时,还必须定义参数 args 。该 args 参数是键值对的字典,用于将 Jinja 模板中的变量名称映射到渲染模板时使用的值。您可以在表定义中为模板变量提供默认值,也可以在 Junos PyEZ 应用程序中定义这些值。
要定义模板变量的默认值,请在表定义中包括 args 该参数,并将每个模板变量映射到其默认值。下表定义了使用具有一个变量 . protocol该 args 参数定义 的默认值 protocol。当您在脚本中调用 get() 该方法时,应用程序使用默认值,并且不提供替代该默认值的参数。
---
DdosPolicerStatsTable:
command: show ddos policer stats {{ protocol }}
args:
protocol: ospf
target: Null
title: "DDOS Policer Statistics:"
key: location
view: DdosPolicerStatsView
此外,您可以将 args 参数定义为 Table get() 方法中的字典,以:
-
为表中未定义默认值的任何模板变量定义一个值
-
覆盖表中为一个或多个模板变量定义的默认值
以下示例使用协议“bgp”而不是默认值“ospf”执行上表中的命令。
from jnpr.junos import Device from jnpr.junos.command.pfe_ddos_policer import DdosPolicerStatsTable from pprint import pprint import json with Device(host='router1.example.com') as dev: stats = DdosPolicerStatsTable(dev) stats.get(target='fpc0', args={'protocol':'bgp'}) pprint(json.loads(stats.to_json()))
目标 FPC (FPC)
Junos PyEZ 操作表可以在特定的 FPC 上执行 vty 命令。使用 vty 命令时,Table 必须包含用于target定义目标 FPC 的参数。您可以设置为targetNull并强制用户在应用程序中指定目标 FPC。或者,您可以设置为target默认 FPC,用户可以选择在应用程序中覆盖此值。
下表执行 show memory vty 命令,但将 target: Null.因此,用户必须在 Junos PyEZ 应用程序中指定目标 FPC:
---
FpcMemory:
command: show memory
target: Null
key: ID
key_items:
- 0
- 1
view: FPCMemoryView
下表在 FPC 1 上执行 show memory vty 命令,除非用户在 Junos PyEZ 应用程序中覆盖此值。
---
FpcMemory:
command: show memory
target: fpc1
key: ID
key_items:
- 0
- 1
view: FPCMemoryView
在 Junos PyEZ 应用程序中,您可以定义目标 FPC 或覆盖表中定义的默认 FPC。要指定 FPC,请将 Table 方法get()中的参数设置为target所需的 FPC,例如:
from jnpr.junos import Device from jnpr.junos.command.fpc_memory import FpcMemory from pprint import pprint import json with Device(host='router.example.com') as dev: stats = FpcMemory(dev) stats.get(target='fpc0') pprint(json.loads(stats.to_json()))
表项(项)
可选的 Table item 属性是一个字符串或正则表达式,用于定义如何拆分命令输出以进行解析。如果输出具有相似的重复数据集,则可以定义以匹配 item 和提取数据的每个迭代。例如, show interfaces 为多个接口返回一组类似的数据。或者,您可以定义 item: '*' 何时需要将数据提取为单个文本块。
请考虑 vty 命令的 show devices local 以下输出:
TSEC Ethernet Device Driver: .le1, Control 0x4296c218, (1000Mbit)
HW reg base 0xff724000
[0]: TxBD base 0x7853ce20, RxBD Base 0x7853d640
[1]: TxBD base 0x7853d860, RxBD Base 0x7853e080
[2]: TxBD base 0x7853e2a0, RxBD Base 0x785422c0
[3]: TxBD base 0x785426e0, RxBD Base 0x78544700
Receive:
185584608 bytes, 2250212 packets, 0 FCS errors, 0 multicast packets
107271 broadcast packets, 0 control frame packets
0 PAUSE frame packets, 0 unknown OP codes
0 alignment errors, 0 frame length errors
0 code errors, 0 carrier sense errors
0 undersize packets, 0 oversize packets
0 fragments, 0 jabbers, 0 drops
Receive per queue:
[0]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
[1]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
[2]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
[3]: 203586808 bytes, 2250219 packets, 0 dropped
0 jumbo, 0 truncated jumbo
Transmit:
288184646 bytes, 2038370 packets, 0 multicast packets
106531 broadcast packets, 0 PAUSE control frames
0 deferral packets, 0 excessive deferral packets
0 single collision packets, 0 multiple collision packets
0 late collision packets, 0 excessive collision packets
0 total collisions, 0 drop frames, 0 jabber frames
0 FCS errors, 0 control frames, 0 oversize frames
0 undersize frames, 0 fragments frames
Transmit per queue:
[0]: 10300254 bytes, 72537 packets
0 dropped, 0 fifo errors
[1]: 4474302 bytes, 106531 packets
0 dropped, 0 fifo errors
[2]: 260203538 bytes, 1857137 packets
0 dropped, 0 fifo errors
[3]: 199334 bytes, 2179 packets
0 dropped, 0 fifo errors
TSEC status counters:
kernel_dropped:0, rx_large:0 rx_short: 0
rx_nonoctet: 0, rx_crcerr: 0, rx_overrun: 0
rx_bsy: 0,rx_babr:0, rx_trunc: 0
rx_length_errors: 0, rx_frame_errors: 0 rx_crc_errors: 0
rx_errors: 0, rx_ints: 2250110, collisions: 0
eberr:0, tx_babt: 0, tx_underrun: 0
tx_timeout: 0, tx_timeout: 0,tx_window_errors: 0
tx_aborted_errors: 0, tx_ints: 2038385, resets: 1
TSEC Ethernet Device Driver: .le3, Control 0x42979220, (1000Mbit)
HW reg base 0xff726000
[0]: TxBD base 0x78545720, RxBD Base 0x78545f40
[1]: TxBD base 0x78546160, RxBD Base 0x78546980
[2]: TxBD base 0x78546ba0, RxBD Base 0x7854abc0
[3]: TxBD base 0x7854afe0, RxBD Base 0x7854d000
Receive:
0 bytes, 0 packets, 0 FCS errors, 0 multicast packets
0 broadcast packets, 0 control frame packets
0 PAUSE frame packets, 0 unknown OP codes
0 alignment errors, 0 frame length errors
0 code errors, 0 carrier sense errors
0 undersize packets, 0 oversize packets
0 fragments, 0 jabbers, 0 drops
Receive per queue:
[0]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
[1]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
[2]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
[3]: 0 bytes, 0 packets, 0 dropped
0 jumbo, 0 truncated jumbo
Transmit:
6817984 bytes, 106531 packets, 0 multicast packets
106531 broadcast packets, 0 PAUSE control frames
0 deferral packets, 0 excessive deferral packets
0 single collision packets, 0 multiple collision packets
0 late collision packets, 0 excessive collision packets
0 total collisions, 0 drop frames, 0 jabber frames
0 FCS errors, 0 control frames, 0 oversize frames
0 undersize frames, 0 fragments frames
Transmit per queue:
[0]: 0 bytes, 0 packets
0 dropped, 0 fifo errors
[1]: 4474302 bytes, 106531 packets
0 dropped, 0 fifo errors
[2]: 0 bytes, 0 packets
0 dropped, 0 fifo errors
[3]: 0 bytes, 0 packets
0 dropped, 0 fifo errors
TSEC status counters:
kernel_dropped:0, rx_large:0 rx_short: 0
rx_nonoctet: 0, rx_crcerr: 0, rx_overrun: 0
rx_bsy: 0,rx_babr:0, rx_trunc: 0
rx_length_errors: 0, rx_frame_errors: 0 rx_crc_errors: 0
rx_errors: 0, rx_ints: 0, collisions: 0
eberr:0, tx_babt: 0, tx_underrun: 0
tx_timeout: 0, tx_timeout: 0,tx_window_errors: 0
tx_aborted_errors: 0, tx_ints: 106531, resets: 1
下表提取了以 开头 TSEC Ethernet Device Driver:的输出的每个部分。在这种情况下,的 key: name 值派生自 中定义 item的正则表达式中的捕获组。
---
DevicesLocalTable:
command: show devices local
target: fpc1
item: 'TSEC Ethernet Device Driver: (\.?\w+),'
key: name
view: DevicesLocalView
DevicesLocalView:
fields:
TSEC_status_counters: _TSECStatusCountersTable
receive_counters: _ReceiveTable
transmit_per_queue: _TransmitQueueTable
如果要匹配输出的整个部分而不是匹配每一行,也可以定义item为星号 ('*')。在大多数情况下,如果包含 item: '*',还必须包含该title参数来指定要提取的输出部分的标题。当您将参数包含在regex视图中并希望每个表达式与整个文本字符串匹配时,提取item: '*'输出非常有用。否则,regex将组合表达式并针对每一行进行匹配。
下表提取标题 Receive: 下的文本块,并将每个正则表达式与整个文本字符串进行匹配:
_ReceiveTable:
item: '*'
title: 'Receive:'
view: _ReceiveView
_ReceiveView:
regex:
bytes: '(\d+) bytes'
packets: '(\d+) packets'
FCS_errors: '(\d+) FCS errors'
broadcast_packets: '(\d+) broadcast packets'
表项键(键)
optional key 属性定义用于唯一标识 Table 项的输出字段。您可以使用单个键或键列表来标识表项。如果表和视图返回迭代数据,则该 key 值必须引用视图中定义的变量或字段名称。
考虑以下 show chassis fan 输出:
Item Status RPM Measurement
Fan 1 OK 5280 Spinning at normal speed
Fan 2 OK 5280 Spinning at normal speed
Fan 3 OK 5280 Spinning at normal speed
Fan 4 OK 5280 Spinning at normal speed
Fan 5 OK 5280 Spinning at normal speed
下表将 Table 项键定义为 fan-name,该键映射到输出中列 Item 下的值。
ChassisFanTable:
command: show chassis fan
key: fan-name
view: ChassisFanView
ChassisFanView:
columns:
fan-name: Item
fan-status: Status
fan-rpm: RPM
fan-measurement: Measurement
在 Junos PyEZ 应用程序中检索和打印数据时,生成的字典中的每个项都使用此字段的值作为其键。
dict_keys(['Fan 1', 'Fan 2', 'Fan 3', 'Fan 4', 'Fan 5'])
您还可以定义 key 为列表,以使用复合键标识表项。例如:
---
FPCIPV4AddressTable:
command: show ipv4 address
target: fpc1
key:
- name
- addr
view: FPCIPV4AddressView
FPCIPV4AddressView:
columns:
index: Index
addr: Address
name: Name
选定的键 (key_items)
该 key 参数定义唯一标识表项的输出字段。在表中包括 key 该参数时,可以使用可选 key_items 参数仅返回某些键值的数据。 key_items 定义要检索数据的表项的键或键列表。您可以在表定义或 Junos PyEZ 应用程序中定义 key_items 该参数。
考虑以下 show chassis fan 输出:
Item Status RPM Measurement
Fan 1 OK 5280 Spinning at normal speed
Fan 2 OK 5280 Spinning at normal speed
Fan 3 OK 5280 Spinning at normal speed
Fan 4 OK 5280 Spinning at normal speed
Fan 5 OK 5280 Spinning at normal speed
下表将 Table 项键定义为 fan-name ,并且仅检索键值 Fan 1等于 的 Table 项的数据。
ChassisFanTable:
command: show chassis fan
key: fan-name
key_items:
- Fan 1
view: ChassisFanView
ChassisFanView:
columns:
fan-name: Item
fan-status: Status
fan-rpm: RPM
fan-measurement: Measurement
在 Junos PyEZ 应用程序中,您可以定义返回,key_items也可以覆盖表中定义的。key_items将 Table 方法get()中的参数设置为key_items所需项的列表或元组。例如:
from jnpr.junos import Device from jnpr.junos.command.chassis_fan import ChassisFanTable from pprint import pprint import json with Device(host='router.example.com') as dev: fans = ChassisFanTable(dev) fans.get(key_items=['Fan 1', 'Fan 2']) pprint(json.loads(fans.to_json()))
user@host:~$ python3 junos-pyez-get-fan-data.py
{'Fan 1': {'fan-measurement': 'Spinning at normal speed',
'fan-name': 'Fan 1',
'fan-rpm': 5280,
'fan-status': 'OK'},
'Fan 2': {'fan-measurement': 'Spinning at normal speed',
'fan-name': 'Fan 2',
'fan-rpm': 5280,
'fan-status': 'OK'}}
章节标题(标题)
表可以包括可选 title 参数,用于定义命令输出中要从中提取和解析数据的部分的起点。当“表”定义 item: '*'时,必须包含 title 以指定要提取的输出部分的标题
例如,考虑以下命令输出,它包含在一组更大的输出中:
... TSEC status counters: kernel_dropped:0, rx_large:0 rx_short: 0 rx_nonoctet: 0, rx_crcerr: 0, rx_overrun: 0 rx_bsy: 0,rx_babr:0, rx_trunc: 0 rx_length_errors: 0, rx_frame_errors: 0 rx_crc_errors: 0 rx_errors: 0, rx_ints: 2250110, collisions: 0 eberr:0, tx_babt: 0, tx_underrun: 0 tx_timeout: 0, tx_timeout: 0,tx_window_errors: 0 tx_aborted_errors: 0, tx_ints: 2038385, resets: 1 ...
下表使用该 title 参数从输出部分提取 TSEC status counters 和分析数据。在这种情况下,Table 定义 item 为 '*',它将数据视为单个文本字符串。
_TSECStatusCountersTable:
item: '*'
title: 'TSEC status counters:'
view: _TSECStatusCountersView
_TSECStatusCountersView:
regex:
kernel_dropped: 'kernel_dropped:(\d+)'
rx_large: 'rx_large:(\d+)'
字段分隔符(分隔符)
某些操作命令返回的输出仅由键值对组成。如果只想检索整组数据并提取每个键值对,则可以使用该 delimiter 参数而不是定义单独的视图。该 delimiter 参数定义如何拆分每个数据对。Junos PyEZ 使用分隔符在指定边界处拆分数据,并将每个键值对存储在字典中。
请考虑 vty 命令的 show link stats 以下输出。
PPP LCP/NCP: 0 HDLC keepalives: 0 RSVP: 0 ISIS: 0 OSPF Hello: 539156 OAM: 0 BFD: 15 UBFD: 0 LMI: 0 LACP: 0 ETHOAM: 0 SYNCE: 0 PTP: 0 L2TP: 0 LNS-PPP: 0 ARP: 4292 ELMI: 0 VXLAN MRESOLVE: 0 Unknown protocol: 42
下表将分隔符定义为冒号 (:) 字符:
--- FPCLinkStatTable: command: show link stats target: fpc1 delimiter: ":"
在 Junos PyEZ 应用程序中检索数据时,该表会在分隔符处拆分每行输出,并将键值对存储在字典中。
{'ARP': 4292, 'ELMI': 0, 'SYNCE': 0, 'ISIS': 0, 'BFD': 15, 'PPP LCP/NCP': 0,
'OAM': 0, 'ETHOAM': 0, 'LACP': 0, 'LMI': 0, 'Unknown protocol': 42,
'UBFD': 0, 'L2TP': 0, 'HDLC keepalives': 0, 'LNS-PPP': 0,
'OSPF Hello': 539156, 'RSVP': 0, 'VXLAN MRESOLVE': 0, 'PTP': 0}
评估表达式 (eval)
您可以使用可选 eval 参数在表和视图返回的最终数据中添加或修改键值对。该 eval 参数将键名映射到包含数学表达式的字符串。您可以在表和视图中包含该 eval 参数,并且 eval 可以定义和计算多个值。
在表中使用时eval,它会引用完整的数据字典进行计算。键和计算值将作为单个附加项添加到字典中。在视图中使用时eval,将在数据的每次迭代时计算表达式。计算值将添加到该迭代的数据中。如果键名称与视图中定义的键匹配,eval则eval将该键的值替换为计算值。如果键名称与视图中定义的键不匹配,eval则eval将新键和计算值添加到数据中。
表达 eval 式可以引用 data 视图返回的字典。表达式必须使用 Jinja 模板变量进行引用 data ,以便 Junos PyEZ 可以在计算表达式时使用字典替换该变量。
从 Junos PyEZ 2.8.1 版开始,表和视图 eval 语句中使用的表达式将使用受限实现进行评估,以降低代码执行安全风险。在计算之前,Junos PyEZ 会根据一组受支持的 Python 语法、函数、方法和运算来解析和验证每个表达式。包含不受支持或不安全元素的表达式将被拒绝并显示 UnsafeExpressionError 错误。 表 2 概述了支持的表达式。
| 类别 | 支持的语法 | 示例 |
|---|---|---|
|
算术 |
+ - * / // % ** |
|
|
布尔逻辑 |
|
|
|
文字 |
整数、浮点数 |
|
|
字符串文字 |
|
|
|
字典文字 |
|
|
|
列出文字 |
|
|
|
设置文字 |
|
|
|
元组文字 |
|
|
|
比较 |
|
|
|
词典 |
|
|
|
列表 |
|
|
|
设置 |
|
{k for k in {{ data }}.keys()} |
|
条件表达式 |
|
|
|
功能 |
|
|
|
发电机 |
|
|
|
索引 |
|
|
|
会员 |
|
|
|
方法 |
|
|
|
切片 |
|
|
|
一元运算符 |
|
|
以下示例 eval 在表定义中使用,以在数据字典中包含一个附加条目。添加项的键是 total_interrupts,其值是中断次数的总和。
---
CChipLiInterruptStatsTable:
command: show xmchip {{ chip_instance }} li interrupt-stats
target: NULL
args:
chip_instance: 0
key:
- li_block
- name
eval:
total_interrupts: "sum([v['interrupts'] for k,v in {{ data }}.items() if isinstance(v, dict) and 'cookie_sz_err' in v['name']])"
view: CChipLiInterruptStatsView
CChipLiInterruptStatsView:
columns:
li_block: LI Block
name: Interrupt Name
interrupts: Number of Interrupts
last_occurance: Last Occurrence
您还可以在表中定义 eval 以计算和添加多个键值对,例如:
---
CChipDRDErrTable:
command: show xmchip {{ instance }} drd error-stats
args:
instance: 0
target: NULL
key: Interrupt Name
item: '*'
eval:
cchip_drd_wan_errors: sum([v['interrupt_count'] for k, v in {{ data }}.items() if k.endswith('_0')])
cchip_drd_fab_errors: sum([v['interrupt_count'] for k, v in {{ data }}.items() if k.endswith('_1')])
view: CChipDRDErrView
CChipDRDErrView:
regex:
cchip_drd_wan_timeouts: 'Total WAN reorder ID timeout errors:\s+(\d+)'
cchip_drd_fab_timeouts: 'Total fabric reorder ID timeout errors:\s+(\d+)'
columns:
interrupt_name: Interrupt Name
interrupt_count: Number of Interrupts
filters:
- interrupt_count
有关在视图中使用的信息eval,请参阅评估表达式 (eval)。
表格视图(视图)
该 view 属性将 Table 定义与特定视图相关联。视图定义应如何解析表输出,并将用户定义的 Python 变量名称映射到所选表项中的输出字段。您可以自定义“视图”以仅从“表”项中选择某些字段。
如果输出仅包含键值对,则可以使用 Table 的 delimiter 参数提取数据并将键值对存储在字典中。在这种情况下,无需定义单独的视图。
TextFSM 模板(平台和use_textfsm)
Junos PyEZ 表可以引用 TextFSM 模板来解析来自瞻博网络设备或其他供应商设备的命令输出。您必须在 Junos PyEZ 服务器或虚拟环境中安装该 ntc-templates 库,才能在表中使用 TextFSM 模板。
要使用 TextFSM 模板解析命令输出,请包含在use_textfsm: True表中。您可以仅使用 TextFSM 模板,也可以将该模板与 Junos PyEZ 视图结合使用。Junos PyEZ 使用和platformcommand值来确定模板的文件名。
例如,下表使用 juniper_junos_show_arp_no-resolve.textfsm 模板来解析来自 瞻博网络 Junos 设备的命令输出:
--- ArpTableTextFSM: command: show arp no-resolve platform: juniper_junos key: MAC use_textfsm: True
有关将 Junos PyEZ 表与 TextFSM 模板配合使用的详细信息,请参阅将 Junos PyEZ 表与 TextFSM 模板配合使用。
变更历史表
是否支持某项功能取决于您使用的平台和版本。使用 功能资源管理器 确定您的平台是否支持某个功能。
eval 语句中使用的表达式将使用受限实现进行评估。