使用 Junos PyEZ 在 Junos 设备上执行 RPC
总结 使用该Device
rpc
属性在 Junos 设备上执行操作 RPC。
您可以使用 Junos PyEZ 在 Junos 设备上按需执行远程过程调用 (RPC)。创建类的 Device
实例后,可以将 RPC 作为实例的属性 Device
执行。您可以使用 Junos PyEZ 执行可在 CLI 中执行的大多数相同操作命令。
Junos XML API 是 Junos OS 配置语句和操作模式命令的 XML 表示形式。它为 Junos OS 配置层次结构中的所有语句以及在 CLI 操作模式下发出的许多命令定义等效的 XML。每个带有 Junos XML 对应项的操作模式命令都会映射到请求标记元素,如有必要,还会映射到响应标记元素。请求标记用于 NETCONF 或 Junos XML 协议会话中的 RPC 中,以从 Junos 设备请求信息。服务器使用包含在响应标记元素内的 Junos XML 元素返回响应。
使用 Junos PyEZ 执行 RPC 时,会将请求标记名称映射到方法名称。本主题概述了如何将 CLI 命令映射到 Junos PyEZ RPC、如何使用 Junos PyEZ 执行 RPC,以及如何自定义 RPC 回复中返回的数据。
将 Junos OS 命令映射到 Junos PyEZ RPC
具有 Junos XML 对应项的所有操作命令都列在 Junos XML API 资源管理器中。您还可以在 CLI 上或使用 Junos PyEZ 显示具有 Junos XML 对应项的任何操作模式命令的 Junos XML 请求标记元素。获取请求标记后,可以将其映射到 Junos PyEZ RPC 方法名称。
要在 CLI 中显示命令的 Junos XML 请求标记,请在命令后包含 | display xml rpc
该选项。以下示例显示命令的请求 show route
标记:
user@router> show route | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1R1/junos"> <rpc> <get-route-information> </get-route-information> </rpc> </rpc-reply>
您还可以使用 Junos PyEZ 显示命令的 Junos XML 请求标记。若要显示请求标记,请调用 Device
实例 display_xml_rpc()
方法,并将命令字符串和 format='text'
作为参数包含在内。例如:
from jnpr.junos import Device with Device(host='router.example.com') as dev: print (dev.display_xml_rpc('show route', format='text'))
执行程序将返回命令的请求 show route
标记。
<get-route-information> </get-route-information>
您可以将操作命令的请求标签映射到 Junos PyEZ RPC 方法名称。若要派生 RPC 方法名称,请将请求标记中的任何连字符替换为下划线 (_),并删除括起来的尖括号。例如, <get-route-information>
请求标记映射到 get_route_information()
方法名称。
将 RPC 作为设备实例的属性执行
的每个 Device
实例都有一个 rpc
属性,可用于执行通过 Junos XML API 提供的任何 RPC。在 Junos PyEZ 应用程序中,与设备建立连接后,可以通过将属性和 RPC 方法名称追加 rpc
到设备实例来执行 RPC,如以下示例所示:
from jnpr.junos import Device from lxml import etree with Device(host='dc1a.example.com') as dev: #invoke the RPC equivalent to "show version" sw = dev.rpc.get_software_information() print(etree.tostring(sw, encoding='unicode'))
返回值是从标记下 <rpc-reply>
的第一个元素开始的 XML 对象。在这种情况下, get_software_information()
RPC 返回元素 <software-information>
。
<software-information> <host-name>dc1a</host-name> ... </software-information>
Junos OS 命令可以具有没有值的固定格式选项。例如,命令 show interfaces terse
的 Junos XML 等效项指示该 terse
元素为空。
user@router> show interfaces terse | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1R1/junos"> <rpc> <get-interface-information> <terse/> </get-interface-information> </rpc> </rpc-reply>
若要执行 RPC 并包含不采用值的命令选项,请将该选项添加到 RPC 方法的参数列表中,将选项名称中的任何短划线更改为下划线,并将其设置为等于 True。以下代码执行与命令 show interfaces terse
等效的 Junos PyEZ RPC:
rsp = dev.rpc.get_interface_information(terse=True)
Junos OS 命令也可以包含需要值的选项。例如,在以下输出中,元素 interface-name
需要一个值,该值是要为其返回信息的接口的名称:
user@router> show interfaces ge-0/0/0 | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1R1/junos"> <rpc> <get-interface-information> <interface-name>ge-0/0/0</interface-name> </get-interface-information> </rpc> </rpc-reply>
若要执行 RPC 并包含需要值的命令选项,请将该选项添加到 RPC 方法的参数列表中,将选项名称中的任何短划线更改为下划线,然后将其设置为等于适当的值。以下示例执行与命令等效的 show interfaces ge-0/0/0
Junos PyEZ RPC:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0')
指定 RPC 输出的格式
默认情况下,RPC 返回值是从标记下<rpc-reply>
的第一个元素开始的 XML 对象。还可以通过将 or {'format':'json'}
字典作为 RPC 方法的第一个参数包含或字典,以{'format':'text'}
文本或 JavaScript 对象表示法 (JSON) 格式返回 RPC 输出。
从 Junos OS 14.2R1 版开始,支持 JSON 格式的 RPC 输出。
下面的示例以文本格式返回 RPC 的 get_software_information()
输出,该输出与为 CLI 中的命令发出的 show version
输出相同,只是 RPC 输出包含在元素中 <output>
。
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.com') as dev: sw_info_text = dev.rpc.get_software_information({'format':'text'}) print(etree.tostring(sw_info_text))
user@server:~$ python3 junos-pyez-rpc-text-format.py <output> Hostname: router1 Model: mx104 Junos: 18.3R1.9 JUNOS Base OS boot [18.3R1.9] JUNOS Base OS Software Suite [18.3R1.9] JUNOS Crypto Software Suite [18.3R1.9] JUNOS Packet Forwarding Engine Support (TRIO) [18.3R1.9] JUNOS Web Management [18.3R1.9] JUNOS Online Documentation [18.3R1.9] JUNOS SDN Software Suite [18.3R1.9] JUNOS Services Application Level Gateways [18.3R1.9] JUNOS Services COS [18.3R1.9] JUNOS Services Jflow Container package [18.3R1.9] JUNOS Services Stateful Firewall [18.3R1.9] JUNOS Services NAT [18.3R1.9] JUNOS Services RPM [18.3R1.9] JUNOS Services Captive Portal and Content Delivery Container package [18.3R1.9] JUNOS Macsec Software Suite [18.3R1.9] JUNOS Services Crypto [18.3R1.9] JUNOS Services IPSec [18.3R1.9] JUNOS DP Crypto Software Software Suite [18.3R1.9] JUNOS py-base-powerpc [18.3R1.9] JUNOS py-extensions-powerpc [18.3R1.9] JUNOS jsd [powerpc-18.3R1.9-jet-1] JUNOS Kernel Software Suite [18.3R1.9] JUNOS Routing Software Suite [18.3R1.9] <output>
以下示例以 JSON 格式返回 RPC 的 get_software_information()
输出。
from jnpr.junos import Device from pprint import pprint with Device(host='router1.example.com') as dev: sw_info_json = dev.rpc.get_software_information({'format':'json'}) pprint(sw_info_json)
user@server:~$ python3 junos-pyez-rpc-json-format.py {u'software-information': [{u'host-name': [{u'data': u'router1'}], u'junos-version': [{u'data': u'18.3R1.9'}], u'package-information': [{u'comment': [{u'data': u'JUNOS Base OS boot [18.3R1.9]'}], u'name': [{u'data': u'junos'}]}, {u'comment': [{u'data': u'JUNOS Base OS Software Suite [18.3R1.9]'}], u'name': [{u'data': u'jbase'}]}, ...
指定要返回的数据范围
您可以使用 Junos PyEZ 执行 RPC,以便从 Junos 设备检索操作信息。从 Junos PyEZ 2.3.0 版开始,当您请求 XML 输出时,可以过滤回复以仅返回特定元素。当您有大量操作输出时,筛选输出是有益的,但您只需要处理数据的子集。
若要筛选 RPC 回复以仅返回特定标记,请包含 RPC 方法的 filter_xml
参数。该 filter_xml
参数采用一个字符串,其中包含子树筛选器,该筛选器选择要返回的元素。子树筛选器返回与选择条件匹配的数据。
以下 Junos PyEZ 示例执行 <get-interface-information>
RPC 并筛选输出,以仅 <name>
检索回复中每个 <physical-interface>
元素的元素:
from jnpr.junos import Device from lxml import etree with Device(host='router.example.com', use_filter=True) as dev: filter = '<interface-information><physical-interface><name/></physical-interface></interface-information>' result = dev.rpc.get_interface_information(filter_xml=filter) print (etree.tostring(result, encoding='unicode'))
执行脚本时,它会显示每个物理接口的名称元素。
user@server:~$ python3 junos-pyez-get-interface-names.py <interface-information style="normal"><physical-interface><name> lc-0/0/0 </name></physical-interface><physical-interface><name> pfe-0/0/0 </name></physical-interface><physical-interface><name> pfh-0/0/0 </name></physical-interface><physical-interface><name> xe-0/0/0 </name></physical-interface><physical-interface><name> xe-0/1/0 </name></physical-interface><physical-interface><name> ge-1/0/0 </name></physical-interface> ... </interface-information>
指定 RPC 超时
RPC 执行时间可能因 RPC 和设备而异。默认情况下,NETCONF RPC 在 30 秒后超时。可以通过在执行 RPC 时包含 dev_timeout=seconds
参数来延长超时值,以确保 RPC 在执行过程中不会超时。 dev_timeout
仅为该单个 RPC 操作调整设备超时。
dev.rpc.get_route_information(table='inet.0', dev_timeout=55)
规范化 XML RPC 回复
执行 RPC 时,RPC 回复可以包含换行符包装的数据或包含其他多余的空格。不必要的空格会使使用 基于文本的搜索分析 XML 和查找信息变得困难。您可以规范化 RPC 回复,这将去除所有前导和尾随空格,并将内部空格字符序列替换为单个空格。
表 1 将默认 RPC 回复与规范化版本进行了比较。默认 RPC 答复包括规范化答复中不存在的许多换行符。
默认 RPC 回复 |
规范化 RPC 回复 |
---|---|
<interface-information style="terse"> <logical-interface> <name>\nge-0/0/0.0\n</name> <admin-status>\nup\n</admin-status> <oper-status>\nup\n</oper-status> <filter-information>\n</filter-information> <address-family> <address-family-name>\ninet\n</address-family-name> <interface-address> <ifa-local emit="emit">\n198.51.100.1/24\n</ifa-local> </interface-address> </address-family> </logical-interface> </interface-information> |
<interface-information style="terse"> <logical-interface> <name>ge-0/0/0.0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> <filter-information/> <address-family> <address-family-name>inet</address-family-name> <interface-address> <ifa-local emit="emit">198.51.100.1/24</ifa-local> </interface-address> </address-family> </logical-interface> </interface-information> |
您可以在与设备的会话期间启用规范化,也可以在执行 RPC 时规范化单个 RPC 回复。若要为整个设备会话启用规范化,请在 normalize=True
创建设备实例或使用该方法连接到 open()
设备时包含在参数列表中。
dev = Device(host='router1.example.com', user='root', normalize=True) # or dev.open(normalize=True)
若要规范化单个 RPC 回复,请包含在 normalize=True
该 RPC 方法的参数列表中。
dev.rpc.rpc_method(normalize=True)
例如:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True)
如果不规范化 RPC 回复,则在使用引用特定节点或值的 XPath 表达式时,必须考虑任何空格。以下示例为逻辑接口选择 IPv4 地址。在 XPath 表达式中,指定家族的 inet
谓词必须考虑额外的空格,搜索才能成功。结果值包括前导换行符和尾随换行符。
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True) print (rsp.xpath('.// \ address-family[normalize-space(address-family-name)="inet"]/ \ interface-address/ifa-local')[0].text)
'\n198.51.100.1/24\n'
规范化 RPC 回复时,将删除任何前导和尾随空格,这使得基于文本的搜索更加直接。
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True) print (rsp.xpath('.//address-family[address-family-name="inet"]/ \ interface-address/ifa-local')[0].text)
'198.51.100.1/24'