Juniper Operational Automation

Tools required for Juniper operational automation

Table of Contents

What is network operational automation?

As a network engineer, you could be confirming the state of BGP after a change, installing a new device and confirming connectivity, or just carrying out a routine health check. They all have one thing in common; operational states using show commands. These commands will be familiar to many network engineers, i.e.,

  • show bgp summary
  • show interfaces terse
  • show system uptime

You could save time by automating some of these steps; using Junos’s operational RPCs. There’s nothing stopping you from using RPCs for configuration, but Junos PyEZ provides a config module simplifying some of the steps.


What is an RPC?

A Remote Procedure Call (RPC) is the start of your Junos automation. Think of an RPC as an equivalent to command-line interface (CLI) show, set, and commit commands. The RPC mechanism uses a standardised communication channel (NETCONF) and uses a standard format for transferring structured data Extensible Markup Language (XML).


What is structured data?

Examples of structured data are, i.e., XML, YAML, and JSON. Junos software supports two out of the three, XML and JavaScript Object Notation (JSON). However, the Junos management API is fundamentally an XML API. When you issue an operational request in the CLI, the CLI converts the command into XML for processing.

The Junos OS CLI and the Junos OS infrastructure communicate using XML. When you issue an operational mode command in the CLI, the CLI converts the command into XML format for processing.


Can I use JSON?

The Junos software sends and receives requests in XML format. Junos OS does not accept RPC requests in JSON format, but you can get responses in JSON. However, it is not native, meaning it first produces the XML output and then converts the XML output as JSON.

JSON headphone image.png


What does an RPC message contain?

An RPC request is enclosed in <rpc> open and </rpc> close tags, with the content placed in-between the two tags. If you wanted to get the equivalent of the cli command show version, you would use <get-software-information/>. A response message from the Junos device would be placed inside <rpc-reply> tags. An example of an RPC session can be found below:

Request

<rpc>
    <get-software-information/>
</rpc>

Response

<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
    xmlns:junos="http://xml.juniper.net/junos/19.4R0/junos">
    <software-information>
        <host-name>srx300</host-name>
        <product-model>srx300</product-model>
        <product-name>srx300</product-name>
        <jsr/>
        <junos-version>19.4R2.6</junos-version>
        <package-information>
            <name>junos</name>
            <comment>JUNOS Software Release [19.4R2.6]</comment>
        </package-information>
    </software-information>
</rpc-reply>
]]>]]>

How do I get a response in JSON?

It's the same set of commands with the additional attribute format included in the RPC request.

Request

<rpc>
<get-software-information format="json"/>
</rpc>

Response snippet


<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
            xmlns:junos="http://xml.juniper.net/junos/19.4R0/junos">
{
    "software-information" : [
    {
        "host-name" : [
        {
            "data" : "srx300"
        }
        ], 
        "product-model" : [
        {
            "data" : "srx300"
        }
...

As you can see from the output, JSON is human-readable, making it easier for you to read. But, there is a drawback to producing this output. It's CPU intensive! Just this simple output caused a delay due to the conversion from XML to JSON. Imagine a much larger return or multiple commands of the same scale; the time will start to add up.

XML image.png


How do I discover an RPC request command?

If you noticed, the show version is not the same as the RPC request equivalent. As the Junos OS is XML in the backend, there is a simple command to discover the correct syntax. Once logged into the Juniper device, as usual, using ssh, in operational mode, enter show version | display xml rpc it will output the XML request version. The element after <rpc> is what you would use in your request.

dre@srx300> show version | display xml rpc 
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/19.4R0/junos">
    <rpc>
        <get-software-information>
        </get-software-information>
    </rpc>
    <cli>
        <banner></banner>
    </cli>
</rpc-reply>

How do you start a NETCONF session?

Logged into a Juniper device, in the operational mode, you can enter netconf. To start a session from a Linux terminal, enter user@10.0.20.2 -p 830 -s netconf.

Junos PyEZ.png


Is there an easier way?

Yes, this is where Junos PyEZ starts to shine. They have already thought of most of these scenarios and created methods, eliminating the need to interact with NETCONF directly. But you still need to understand the fundamentals of XML. It will be used for parsing the returned data. If you read the previous blog Installing Junos PyEZ, the configuration of the connect.py module, found in my GitHub repository, will be used as a base configuration. Start by copying the connect.py to rpc_connect.py into the same directory and open it up.

cp connect.py rpc_connect.py
vim rpc_connect.py

The new code will be inserted beneath the print("Are we.. statement on the eleventh line. The rpc method can be initiated from the Device class object, which in this case is dev. For instance, you would call the RPC <get-software-information/> using the PyEZ equivalent method dev.rpc.get_software_information(). It's the same command, except the - is replaced with _.

Let's have a look at the code below:

try:
    with Device(host=ipadd, user=username, password=password) as dev:
        print('Are we connected?', dev.connected)
        software = dev.rpc.get_software_information()
        host_name = software.findtext("host-name")
        model = software.findtext("product-model")
        version = software.findtext("package-information/comment")
        print("*" * 70,
                "Operational checks".center(70),
                f"\n\nHost_name: {hostname}",
                f"Model: {model}",
                f"Version: {version}",
                "*" * 70, sep="\n")

What does the code do?
  • software = dev.get_software_information(): stores the RPC returned data as a Python object;
  • host_name = software.findtext("host-name"): finds the XPath location and returns the text data; host_name is stored as a Python string. The other two variables model and version are also stored the same way.

XPath

XPath is a query language used in XML.

Styling the output
  • print("*" * 70, "Operational checks".center(70)...: uses a number of different methods to style the output i.e.,
    • "*" * 70: multiples prints * 70 times;
    • .center(70): centers "Operational checks" based on a width of 70;
    • \n and \t: are escape characters for newline and tab, respectively.
The final product

At the click of a button, we can now obtain the information formatted to our desire.

rpc_connect.py output.png

If the Junos PyEZ package doesn't fulfil your requirements due to functionality, you could always create functions using a combination of the lxml Python XML library, "I will discuss this in future blogs". That's the beauty of being a Network Automation Engineer; the opportunities are endless!