定义 Junos 设备自定义 YANG RPC 中的不同输出级别
在自定义 YANG RPC 中定义不同级别的输出
您可以使用 YANG 为 Junos 设备定义自定义 RPC。RPC 输出可定制为发出不同的数据和 CLI 格式,具体取决于 RPC 输入。这使您能够为同一 RPC 创建不同样式或输出级别。
当您调用 RPC 时,您可以通过为输入参数包含适当的值来请求所需的样式。操作脚本必须处理此参数并发出请求样式的 XML 输出。然后,Junos OS 会将 XML 转换为 YANG 模块中为该样式定义的相应 CLI 输出。本主题中介绍的 RPC 模板具有两种样式: brief
和 detail
。
要为 RPC 的输出创建不同样式:
以下代码概述了 RPC 和密闭模块的一般结构。当您在 CLI 中调用 RPC 并包含输入参数 level
并指定 brief
,或者 detail
,Junos OS 将呈现为该样式定义的输出。
module module-name { namespace "http://yang.juniper.net/yang/1.1/jrpc"; prefix jrpc; import junos-extension { prefix junos; } import junos-extension-odl { prefix junos-odl; } organization "Juniper Networks, Inc."; description "Junos OS YANG module for custom RPCs"; rpc rpc-name { description "RPC description"; junos:command "cli-command" { junos:action-execute { junos:script "action-script-filename"; } } input { leaf level { type enumeration { enum brief { description "Display brief output"; } enum detail { description "Display detailed output"; } } } } output { container output-container { // leaf definitions junos-odl:style brief { junos-odl:format output-container-format-brief { // formatting for brief output } } junos-odl:style detail { junos-odl:format output-container-format-detail { // formatting for detailed output } } } } } }
要在 CLI 中执行 RPC,请发出语句定义的 junos:command
命令,并通过包括相应的命令行论点(在此示例中为 level
) 来指定样式。相应的操作脚本将处理输入参数,并发出请求样式的输出。
user@host> cli-command level brief
示例:定义不同级别的输出
此示例提供了简单的自定义 YANG RPC 和操作脚本,用于确定是否可访问主机,并根据用户输入打印不同级别的输出。
要求
此示例使用以下硬件和软件组件:
-
运行 Junos OS 17.3R1 或更高版本的设备,支持加载自定义 YANG 数据模型。
RPC 和操作脚本概述
此示例中的 YANG 模块定义了用于对指定主机进行 ping 的自定义 RPC,并根据用户的输入使用不同级别的输出返回结果。YANG 模块 rpc-style-test
保存在 rpc 式 test.yang 文件中。该模块导入 Junos OS 扩展模块,提供在设备上执行自定义 RPC 和自定义 CLI 输出所需的扩展。
该模块定义 get-host-status
了 RPC。请求 <get-host-status>
标记用于在设备上远程执行 RPC。在 RPC 定义中,语 junos:command
句定义用于在 CLI 中执行 RPC 的命令,在此情况下是 show host-status
。
rpc get-host-status { description "RPC example to retrieve host status"; junos:command "show host-status" { junos:action-execute { junos:script "rpc-style-test.py"; } } ...
junos:script
和junos:action-execute
语句定义执行 RPC 时调用的操作脚本。此示例使用名为 rpc-style-test.py 的 Python 操作脚本检索 RPC 所需的信息。该脚本返回 RPC 语句中定义的每个输出级别的 output
XML 输出元素。
从 Junos OS 17.3 版开始,该 action-execute
语句是以下部分的子状态 command
。在早期版本中 action-execute
,和 command
语句放置在同一级别,并且语 command
句是可选的。
RPC 有两个输入参数,hostip
以及 level
。该hostip
参数是用于检查可访问性的主机。该level
参数选择 RPC 输出的样式。执行 RPC 时,将包括目标主机的 IP 地址和级别,brief
或者 detail
。操作脚本将默认值定义为level
'brief'
,因此如果省略此参数,RPC 将打印对应于简要样式的输出。
input { leaf hostip { description "Host IP address"; type string; } leaf level { type enumeration { enum brief { description "Display brief output"; } enum detail { description "Display detailed output"; } } } }
RPC 还定义了相应操作脚本必须发出的输出节点。根节点是<host-status-information>
一个元素,它括起或<detail>
包含<brief>
该元素,具体取决于用户输入,以及为每个输出级别指定的儿童输出节点。这两个级别的输出都包括<hostip>
和<status>
儿童元素,但<detail>
元素还包括<date>
儿童元素。语junos-odl:format
句定义了 CLI 中显示的输出的格式。此节点不会在输出 XML 树中发出。
output { container host-status-information { ... junos-odl:style brief { junos-odl:format host-status-information-format-brief { ... } } junos-odl:style detail { junos-odl:format host-status-information-format-detail { ... } } } }
操作脚本会对主机进行 ping,以确定是否可访问,并根据结果设置状态。然后,脚本根据指定 level
的参数构建并打印 RPC 输出的 XML。XML 树必须与 RPC 中定义的层次结构完全匹配。
包含 RPC 和操作脚本文件的模块作为名为 rpc-style-test
的全新 YANG 软件包的一部分添加到设备中。
YANG 模块和操作脚本
YANG 模块
YANG 模块 rpc 式 test.yang 定义了 RPC、用于在 CLI 中执行 RPC 的命令,以及执行 RPC 时要调用的操作脚本名称。文件的基本名称必须与模块名称匹配。
/* * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. */ module rpc-style-test { namespace "http://yang.juniper.net/yang/1.1/jrpc"; prefix jrpc; import junos-extension-odl { prefix junos-odl; } import junos-extension { prefix junos; } organization "Juniper Networks, Inc."; description "Junos OS YANG module for RPC example"; rpc get-host-status { description "RPC example to retrieve host status"; junos:command "show host-status" { junos:action-execute { junos:script "rpc-style-test.py"; } } input { leaf hostip { description "Host IP address"; type string; } leaf level { type enumeration { enum brief { description "Display brief output"; } enum detail { description "Display detailed output"; } } } } output { container host-status-information { leaf hostip { type string; description "Host IP"; } leaf status { type string; description "Operational status"; } leaf date { type string; description "Date information"; } junos-odl:style brief { junos-odl:format host-status-information-format-brief { junos-odl:header "Brief output\n"; junos-odl:picture "@<<<<<<<<<<<< @"; junos-odl:space; junos-odl:line { junos-odl:field "hostip"; junos-odl:field "status"; } } } junos-odl:style detail { junos-odl:format host-status-information-format-detail { junos-odl:header "Detail output\n"; junos-odl:picture "@<<<<<<<<<<<< @<<<<<<<<<<<< @"; junos-odl:space; junos-odl:line { junos-odl:field "hostip"; junos-odl:field "status"; junos-odl:field "date"; } } } } } } }
操作脚本
对应的操作脚本 rpc-style-test.py。操作脚本根据用户提供的参数值打印不同级别的level
输出。脚本定义了该参数的'brief'
level
默认值,以便如果用户省略了该参数,脚本将返回简要的输出样式。此示例提供了两个版本的操作脚本,可适当处理不同版本的脚本命令行参数。
操作脚本(Junos OS 版本 21.2R1 和更高版本)
#!/usr/bin/python3 # Junos OS Release 21.2R1 and later import os import argparse parser = argparse.ArgumentParser(description='This is a demo script.') parser.add_argument('--hostip', required=True) parser.add_argument('--level', required=False, default='brief') parser.add_argument('--rpc_name', required=True) args = parser.parse_args() f = os.popen('date') now = f.read() # Ping target host and set the status response = os.system('ping -c 1 ' + args.hostip + ' > /dev/null') if response == 0: pingstatus = "Host is Active" else: pingstatus = "Host is Inactive" # Print RPC XML for the given style print ("<host-status-information>") print ("<{}>".format(args.level)) print ("<hostip>{}</hostip>".format(args.hostip)) print ("<status>{}</status>".format(pingstatus)) if args.level == "detail": print ("<date>{}</date>".format(now)) print ("</{}>".format(args.level)) print ("</host-status-information>")
操作脚本(Junos OS 版本 21.1 和更低版本)
#!/usr/bin/python # Junos OS Release 21.1 and earlier import sys import os args = {'hostip': None, 'level': 'brief'} # Retrieve user input and store the values in the args dictionary for arg in args.keys(): if arg in sys.argv: index = sys.argv.index(arg) args[arg] = sys.argv[index+1] f = os.popen('date') now = f.read() # Ping target host and set the status if args['hostip'] is not None: response = os.system('ping -c 1 ' + args['hostip'] + ' > /dev/null') if response == 0: pingstatus = "Host is Active" else: pingstatus = "Host is Inactive" else: pingstatus = "Invalid host" # Print RPC XML for the given style print ("<host-status-information>") print ("<{}>".format(args['level'])) print ("<hostip>{}</hostip>".format(args['hostip'])) print ("<status>{}</status>".format(pingstatus)) if args['level'] == "detail": print ("<date>{}</date>".format(now)) print ("</{}>".format(args['level'])) print ("</host-status-information>")
配置
支持执行 Python 脚本
要使设备能够执行未签名的 Python 脚本:
-
language python
根据适合 Junos OS 版本配置或language python3
语句。[edit] user@host# set system scripts language (python | python3)
注意:从 Junos OS 20.2R1 版和 Junos OS Evolved 版本 22.3R1 开始,设备使用 Python 3 执行 YANG 操作和转换脚本。在早期版本中,Junos OS 仅使用 Python 2.7 执行这些脚本,而 Junos OS Evolved 默认使用 Python 2.7 执行脚本。
-
提交配置。
[edit] user@host# commit and-quit
在设备上加载 RPC
要将 RPC 和操作脚本添加到设备上的 Junos 模式:
-
将 YANG 模块和操作脚本下载到 Junos 设备。
-
确保 Python 操作脚本满足以下要求:
-
文件所有者在 Junos OS
super-user
登录类中为 root 或用户。 -
只有文件所有者才有为该文件写入许可。
-
脚本包括 Junos 设备上的 YANG RPC 创建操作脚本中概述的相应解释器指令行。
-
-
(可选)验证 YANG 模块和操作脚本的语法。
user@host> request system yang validate module /var/tmp/rpc-style-test.yang action-script /var/tmp/rpc-style-test.py YANG modules validation : START YANG modules validation : SUCCESS Scripts syntax validation : START Scripts syntax validation : SUCCESS
-
将 YANG 模块和操作脚本添加到新的 YANG 包中。
user@host> request system yang add package rpc-style-test module /var/tmp/rpc-style-test.yang action-script /var/tmp/rpc-style-test.py YANG modules validation : START YANG modules validation : SUCCESS Scripts syntax validation : START Scripts syntax validation : SUCCESS TLV generation: START TLV generation: SUCCESS Building schema and reloading /config/juniper.conf.gz ... Restarting mgd ...
-
当系统提示您重新启动 Junos OS CLI 时,按下
Enter
接受默认值,yes
或键入 yes 并按下Enter
。WARNING: cli has been replaced by an updated version: ... Restart cli using the new version ? [yes,no] (yes) yes Restarting cli ...
验证 RPC
目的
验证 RPC 是否可根据预期工作。
行动
在操作模式下,在 CLI 中执行 RPC,方法是发出由 RPC 定义中的语句定义的 junos:command
命令。 hostip
包括输入参数,并包括 level
各不同级别输出的参数。
user@host> show host-status hostip 198.51.100.1 level brief Brief output 198.51.100.1 Host is Active
您可通过附加 | display xml
到 命令来查看相应的 XML。
user@host> show host-status hostip 198.51.100.1 level brief | display xml <rpc-reply xmlns:junos="http://xml.juniper.net/junos/18.3R1/junos"> <host-status-information> <brief> <hostip> 198.51.100.1 </hostip> <status> Host is Active </status> </brief> </host-status-information> <cli> <banner></banner> </cli> </rpc-reply>
同样,有关详细输出:
user@host> show host-status hostip 198.51.100.10 level detail Detail output 198.51.100.10 Host is Inactive Fri Feb 8 11:55:54 PST 2019
user@host> show host-status hostip 198.51.100.10 level detail | display xml <rpc-reply xmlns:junos="http://xml.juniper.net/junos/18.3R1/junos"> <host-status-information> <detail> <hostip> 198.51.100.10 </hostip> <status> Host is Inactive </status> <date> Fri Feb 8 16:03:35 PST 2019 </date> </detail> </host-status-information> <cli> <banner></banner> </cli> </rpc-reply>
意义
执行 RPC 时,设备将调用操作脚本。该操作脚本将按照 RPC output
语句中定义的给定输出级别打印 XML 层次结构。在 CLI 中执行 RPC 时,设备使用 RPC 中定义的 CLI 格式将 XML 输出转换为显示的 CLI 输出。