定义 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 输出。