Help us improve your experience.

Let us know what you think.

Do you have time for a two-minute survey?

Creating Action Scripts for YANG RPCs on Devices Running Junos OS

 

You can add YANG data models that define custom remote procedure calls (RPCs) on supported devices running Junos OS. When you add a nonnative YANG RPC to a device, you must also supply an action script that serves as the RPC’s handler. Action scripts are Python or Stylesheet Language Alternative SyntaX (SLAX) scripts that retrieve the information and perform the operations required by the RPC and return any necessary XML output elements as defined in the RPC output statement. The RPC definition references the action script, which is invoked when the RPC is executed.

Action scripts can be written in SLAX or Python. SLAX action scripts are similar to SLAX op scripts and can perform any function available through the RPCs supported by the Junos XML management protocol and the Junos XML API. Python action scripts can leverage all of the features and constructs in the Python language, which provides increased flexibility over SLAX scripts. In addition, Python action scripts support Junos PyEZ APIs, which facilitate executing RPCs and performing operational and configuration tasks on devices running Junos OS. Python scripts can also leverage the lxml library, which simplifies XPath handling.

This topic discusses how to create an action script, including how to parse the RPC input arguments, emit the XML output, access operational and configuration data in the script, and how to validate and load the script on a device.

Action Script Boilerplate

SLAX action scripts must include the necessary boilerplate for both basic script functionality as well as any optional functionality used within the script such as the Junos OS extension functions and named templates. In addition, the script must declare all RPC input parameters using the param statement. The SLAX action script boilerplate is as follows:

Python action scripts must include an interpreter directive line and import any objects that are used by the script. Python action scripts that include the import jcs statement can use Junos OS extension functions and supported named template functionality in the script. If the script uses Junos PyEZ, it must import the necessary classes from the jnpr.junos module.

Parsing RPC Input Arguments

An RPC can define input parameters using the optional input statement. When you execute an RPC and provide input arguments, Junos OS invokes the RPC’s action script and passes those arguments to the script. In a Python or SLAX action script, you can access the RPC input arguments in the same manner as you would access command-line arguments for a normal Python script or a Junos OS SLAX op script, respectively.

Consider the following input statement for the get-host-status RPC:

The RPC can be executed in the CLI or through a NETCONF or Junos XML protocol session. For example:

Note

Starting in Junos OS Release 19.2R1, custom YANG RPCs support input parameters of type empty when executing the RPC’s command in the Junos OS CLI, and the value passed to the action script is the parameter name. In earlier releases, input parameters of type empty are only supported when executing the RPC in a NETCONF or Junos XML protocol session, and the value passed to the action script is the string 'none'.

In SLAX action scripts, you must declare input parameters using the param statement. The script assigns the value for each passed argument to the corresponding parameter, which can then be referenced throughout the script. If a parameter is type empty, the parameter name is passed in as its value. You must include the dollar sign ($) symbol both when you declare the parameter and when you access its value.

Note

For more information about SLAX parameters, see SLAX Parameters Overview in the Automation Scripting Feature Guide.

For Python action scripts:

  • The first argument passed to the script is always the action script file path.

  • The next arguments in the list are the name and value for each user-supplied input parameter.

    Note

    When you execute the RPC’s command in the CLI, the arguments are passed to the script in the order given on the command line. In a NETCONF or Junos XML protocol session, the order of arguments in the XML is arbitrary, so the arguments are passed to the script in the order that they are declared in the RPC input statement.

  • The last two arguments in the list, which are supplied by the system and not the user, are 'rpc_name' and the name of the RPC.

In a Python script, you can access the input arguments through the sys.argv list. For the previous example, the sys.argv input argument list is:

The following sample Python code demonstrates one way to extract the value for each argument from the sys.arv list for the example RPC. The example first defines a dictionary containing the possible argument names as keys and a default value for each argument. The code then checks for each key in the sys.argv argument list and retrieves the index of the argument name in the list, if present. The code then extracts the argument’s value at the adjacent index position, and stores it in the dictionary for the appropriate key. This method ensures that if the arguments are passed to the script in a different order during execution, the correct values are retrieved.

Retrieving Operational and Configuration Data

Action scripts can retrieve operational and configuration data from a device running Junos OS and then parse the data for necessary information. SLAX action scripts can retrieve information from the device by executing RPCs supported by the Junos XML management protocol and the Junos XML API. Python action scripts can retrieve operational and configuration information by using Junos PyEZ APIs or by using the cli -c 'command' to execute CLI commands in the action script as you would from the shell. To retrieve operational information with the cli -c method, include the desired operational command. To retrieve configuration information, use the show configuration command.

The following SLAX snippet executes the show interfaces command on the local device by using the equivalent <get-interface-information> request tag:

The following Python code uses Junos PyEZ to execute the show interfaces command by using the equivalent Junos PyEZ get_interface_information RPC:

Note

For information about using Junos PyEZ to execute RPCs on devices running Junos OS, see Using Junos PyEZ to Execute RPCs on Devices Running Junos OS.

The following Python code executes the show interfaces | display xml command and converts the string output into an XML tree that can be parsed for the required data using XPath constructs:

Emitting the RPC XML Output

An RPC can define output elements using the optional output statement. The action script must define and emit any necessary XML elements for the RPC output. The XML hierarchy emitted by the script should reflect the tree defined by the containers and leaf statements in the definition of the RPC output statement. To return the XML output, the action script must emit the RPC output hierarchy, and only the output hierarchy. SLAX scripts must use the copy-of statement to emit the XML, and Python scripts can use print statements.

For example, consider the following YANG RPC output statement:

The action script must generate and emit the corresponding XML output, for example:

After retrieving the values for the required output elements, a Python script might emit the XML output hierarchy by using the following code:

Similarly, a SLAX action script might use the following:

Validating and Loading Action Scripts on a Device

In your YANG RPC definition, you specify the RPC’s action script by including the junos:command and junos:action-execute statements and the junos:script substatement, which takes the action script’s filename as its value. You must define one and only one action script for each RPC. For example:

Note

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.

Note

YANG modules that define RPCs for devices running Junos OS must import the Junos OS DDL extensions module.

Python action scripts must meet the following requirements before you can execute the scripts on devices running Junos OS.

  • 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 an interpreter directive line such as #!/usr/bin/env python.

  • The language python statement is configured at the [edit system scripts] hierarchy level.

Note

Users can only execute unsigned Python scripts on devices running Junos OS when the script's file permissions include read permission for the first class that the user falls within, in the order of user, group, or others.

You can validate the syntax of an action script in the Junos OS CLI by issuing the request system yang validate action-script command and providing the path to the script. For example:

user@host> request system yang validate action-script /var/tmp/sw-info.py

To use an action script, you must load it onto the device with the YANG module that contains the corresponding RPC. You use the request system yang add or request system yang update commands to add YANG modules and their associated action scripts to a new or existing YANG package on the device. After you add the modules and action scripts to the device, you can execute your custom RPCs. When you execute an RPC, the device invokes the referenced script.

Release History Table
Release
Description
Starting in Junos OS Release 19.2R1, custom YANG RPCs support input parameters of type empty when executing the RPC’s command in the Junos OS CLI, and the value passed to the action script is the parameter name.
Starting in Junos OS Release 17.3, the action-execute statement is a substatement to command.