Define Different Levels of Output in Custom YANG RPCs for Junos Devices
Defining Different Levels of Output in Custom YANG RPCs
You can define custom RPCs for Junos devices using YANG. The RPC output can be customized to emit different data and CLI formatting depending on the RPC input. This enables you to create different styles, or levels of output, for the same RPC.
You can request the desired style by including the appropriate value for the input argument when
you invoke the RPC. The action script must process this argument and emit the XML
output for the requested style. Junos OS then translates the XML into the
corresponding CLI output defined for that style in the YANG module. The RPC template
presented in this topic creates two styles: brief
and
detail
.
To create different styles for the output of an RPC:
The following code outlines the general structure of the RPC and enclosing module.
When you invoke the RPC in the CLI and include the input argument
level
and specify either brief
or
detail
, Junos OS renders the output defined for that style.
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 } } } } } }
To execute the RPC in the CLI, issue the command defined by the
junos:command
statement, and specify the style by including the
appropriate command-line argument, which in this example is level
.
The corresponding action script processes the input argument and emits the output for
the requested style.
user@host> cli-command level brief
Example: Defining Different Levels of Output
This example presents a simple custom YANG RPC and action script that determine if a host is reachable and print different levels of output depending on the user input.
- Requirements
- Overview of the RPC and Action Script
- YANG Module and Action Script
- Configuration
- Verify the RPC
Requirements
This example uses the following hardware and software components:
-
Device running Junos OS Release 17.3R1 or later that supports loading custom YANG data models.
Overview of the RPC and Action Script
The YANG module in this example defines a custom RPC to ping the specified host and
return the result using different levels of output based on the user’s input. The
YANG module rpc-style-test
is saved in the
rpc-style-test.yang file. The module imports the Junos OS
extension modules, which provide the extensions required to execute custom RPCs on
the device and to customize the CLI output.
The module defines the get-host-status
RPC. The
<get-host-status>
request tag is used to remotely execute
the RPC on the device. In the RPC definition, the junos:command
statement defines the command that is used to execute the RPC in the CLI, which in
this case is 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"; } } ...
The junos:action-execute
and junos:script
statements define the action script that is invoked when you execute the RPC. This
example uses a Python action script named rpc-style-test.py to
retrieve the information required by the RPC. The script returns the XML output
elements for each level of output as defined in the RPC's output
statement.
Starting in Junos OS Release 17.3, the action-execute
statement
is a substatement to command
. In earlier releases, the
action-execute
and command
statements are
placed at the same level, and the command
statement is
optional.
The RPC has two input parameters, hostip
and level
.
The hostip
parameter is the host to check for reachability. The
level
parameter selects the style for the RPC's output. When you
execute the RPC, you include the target host’s IP address and a level,
brief
or detail
. The action script defines the
default value for level
as 'brief'
, so if you omit
this argument, the RPC prints the output corresponding to the brief style.
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"; } } } }
The RPC also defines the output nodes that must be emitted by the corresponding
action script. The root node is the <host-status-information>
element, which encloses either the <brief>
or the
<detail>
element, depending on the user input, along with
the child output nodes specified for each level of output. Both levels of output
include the <hostip>
and <status>
child
elements, but the <detail>
element also includes the
<date>
child element. The junos-odl:format
statements define the formatting for the output that is displayed in the CLI. This
node is not emitted in the output XML tree.
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 { ... } } } }
The action script pings the host to determine if it is reachable and sets the status
based on the results. The script then constructs and prints the XML for the RPC
output based on the specified level
argument. The XML tree must
exactly match the hierarchy defined in the RPC.
The module containing the RPC and the action script file are added to the device as
part of a new YANG package named rpc-style-test
.
YANG Module and Action Script
YANG Module
The YANG module, rpc-style-test.yang, defines the RPC, the command used to execute the RPC in the CLI, and the name of the action script to invoke when the RPC is executed. The base name of the file must match the module name.
/* * 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"; } } } } } } }
Action Script
The corresponding action script is rpc-style-test.py. The
action script prints different levels of output based on the value of the
level
argument provided by the user. The script defines a
default value of 'brief'
for the level
argument
so that if the user omits the argument, the script returns the brief style of
output. This example provides two versions of the action script, which
appropriately handle the script's command-line arguments for the different
releases.
Action Script (Junos OS Release 21.2R1 and later)
#!/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>")
Action Script (Junos OS Release 21.1 and earlier)
#!/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>")
Configuration
Enable Execution of Python Scripts
To enable the device to execute unsigned Python scripts:
-
Configure the
language python
orlanguage python3
statement, as appropriate for the Junos OS release.[edit] user@host# set system scripts language (python | python3)
Note:Starting in Junos OS Release 20.2R1 and Junos OS Evolved Release 22.3R1, the device uses Python 3 to execute YANG action and translation scripts. In earlier releases, Junos OS only uses Python 2.7 to execute these scripts, and Junos OS Evolved uses Python 2.7 by default to execute the scripts.
-
Commit the configuration.
[edit] user@host# commit and-quit
Load the RPC on the Device
To add the RPC and action script to the Junos schema on the device:
-
Download the YANG module and action script to the Junos device.
-
Ensure that the Python action script meets the following requirements:
-
File owner is either root or a user in the Junos OS
super-user
login class. -
Only the file owner has write permission for the file.
-
Script includes the appropriate interpreter directive line as outlined in Create Action Scripts for YANG RPCs on Junos Devices.
-
-
(Optional) Validate the syntax for the YANG module and action script.
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
-
Add the YANG module and action script to a new YANG package.
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 ...
-
When the system prompts you to restart the Junos OS CLI, press
Enter
to accept the default value ofyes
, or type yes and pressEnter
.WARNING: cli has been replaced by an updated version: ... Restart cli using the new version ? [yes,no] (yes) yes Restarting cli ...
Verify the RPC
Purpose
Verify that the RPC works as expected.
Action
From operational mode, execute the RPC in the CLI by issuing the command defined by the
junos:command
statement in the RPC definition. Include the
hostip
input argument, and include the level
argument for each different level of output.
user@host> show host-status hostip 198.51.100.1 level brief Brief output 198.51.100.1 Host is Active
You can view the corresponding XML by appending | display xml
to the command.
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>
Similarly, for the detailed output:
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>
Meaning
When you execute the RPC, the device invokes the action script. The action script prints the XML
hierarchy for the given level of output as defined in the RPC
output
statement. When the RPC is executed in the CLI, the
device uses the CLI formatting defined in the RPC to convert the XML output into
the displayed CLI output.
Change History Table
Feature support is determined by the platform and release you are using. Use Feature Explorer to determine if a feature is supported on your platform.