Help us improve your experience.

Let us know what you think.

Do you have time for a two-minute survey?

Announcement: Try the Ask AI chatbot for answers to your technical questions about Juniper products and solutions.

close
header-navigation
keyboard_arrow_up
close
keyboard_arrow_left
gRPC Network Services User Guide
Table of Contents Expand all
list Table of Contents
file_download PDF
{ "lLangCode": "en", "lName": "English", "lCountryCode": "us", "transcode": "en_US" }
English
keyboard_arrow_right

Configure gNOI Services

date_range 21-May-24

Configure the remote network management system as a gRPC client that can execute gNOI operations on network devices.

The gRPC Network Operations Interface (gNOI) uses the gRPC Remote Procedure Call (gRPC) framework to perform operations on a network device. The network management system must have the gRPC stack installed.

OpenConfig defines proto definition files for gNOI services. Proto definition files define the operations (RPCs) and the data structures (messages) for a given service. The definitions are language agnostic. gRPC supports using many different languages to execute service operations. You must compile the proto definition files for your language of choice. You then create applications that use the objects (classes, functions, methods, etc) in the compiled files to connect to the gRPC server on the network device and execute the desired operations.

For information about using gRPC with the different supported languages, consult the gRPC documentation. The following sections provide sample commands for setting up a gRPC client and downloading and compiling the gNOI proto definition files for Python. You must use the commands that are appropriate for your operating system, environment, and gRPC language of choice.

Before you configure the gRPC client, configure the gRPC server as defined in Configure gRPC Services.

Set up the gRPC Client

gNOI uses the gRPC framework to perform operations on a network device. gRPC supports using many different languages. Before you can perform gNOI operations using your language of choice, you must install the gRPC stack on the network management system.

For example, to install the gRPC stack for Python on a network management system running Ubuntu 20.04 LTS (use sudo where appropriate):

  1. Install pip for Python 3.
    content_copy zoom_out_map
    user@nms:~$ sudo apt install python3-pip
  2. Install the grpcio package for Python.
    content_copy zoom_out_map
    user@nms:~$ sudo pip3 install grpcio
  3. Install the grpcio-tools package for Python.
    content_copy zoom_out_map
    user@nms:~$ sudo pip3 install grpcio-tools

Compile the Proto Definiton Files

gRPC supports using many languages. In order to perform gRPC operations on network devices, you must compile the respective proto definition files for your language of choice. OpenConfig provides the necessary proto definition files in the OpenConfig GitHub repository. You use the protocol buffer compiler (protoc or equivalent application) to compile the .proto files.

For this setup, we execute a script that copies all the desired .proto files into a directory, updates the files to use relative import statements, and then compiles the files.

To download and compile the gNOI proto definition files for Python:

  1. Create the temporary directory for the original source files.
    content_copy zoom_out_map
    user@nms:~$ mkdir -p src/github.com/openconfig/gnoi
    
  2. Clone the gNOI GitHub repository to the local device.
    content_copy zoom_out_map
    user@nms:~$ git clone https://github.com/openconfig/gnoi.git src/github.com/openconfig/gnoi
  3. Compile the .proto files for your language, which in this example is Python.

    The sample shell script performs the following operations:

    • Creates the src/proto directory.
    • Copies the desired proto files into the new directory.
    • Updates the import statement in each proto file to use a relative path.
    • Compiles each proto file in the specified list for use with Python.
    content_copy zoom_out_map
    user@nms:~$ cat compile-proto.sh
    content_copy zoom_out_map
    #!/usr/bin/env bash
    
    src=src/proto
    
    gnoiFileList="types common cert diag file layer2 os system"
    
    echo "Updating proto file source location and import statements"
    mkdir -p $src
    
    for p in $gnoiFileList; do
        cp src/github.com/openconfig/gnoi/$p/$p.proto $src
        python3 -c "
    import re
    with open('$src/$p.proto', 'r') as fd:
        data = fd.read()
    data1 = re.sub(r'github\.com\/openconfig\/gnoi\/.*\/(.*.proto)', r'\g<1>', data)
    with open('$src/$p.proto', 'w') as fd:
        fd.write(data1)    "
    done
    
    
    echo "Compiling proto files"
    for p in $gnoiFileList; do
        python3 -m grpc_tools.protoc --proto_path=$src --python_out=$src --grpc_python_out=$src $p.proto
    done
    

    To compile the files using the script, execute the script from the parent directory that contains the src directory.

    content_copy zoom_out_map
    user@nms:~$ sh compile-proto.sh
    Updating proto file source location and import statements
    Compiling proto files
    
    Note:

    The script compiles only the subset of proto files (as defined in gnoiFileList) that have services supported on Junos devices. To compile other services as they become available, you can update the variables to include those services.

  4. Verify that the proto files are compiled by viewing the output files in the target directory.

    The file list should include the compiled files, which for Python have _pb2 and pb2_grpc in the output filenames.

    content_copy zoom_out_map
    user@nms:~$ ls src/proto
    cert_pb2_grpc.py    diag_pb2.py         layer2.proto        types_pb2_grpc.py
    cert_pb2.py         diag.proto          os_pb2_grpc.py      types_pb2.py
    cert.proto          file_pb2_grpc.py    os_pb2.py           types.proto
    common_pb2_grpc.py  file_pb2.py         os.proto            version_pb2_grpc.py
    common_pb2.py       file.proto          system_pb2_grpc.py  version_pb2.py
    common.proto        layer2_pb2_grpc.py  system_pb2.py       version.proto
    diag_pb2_grpc.py    layer2_pb2.py       system.proto
    

Create gNOI Applications

After you compile the proto definition files, you create applications that use the objects in the compiled files. The applications connect to the gRPC server on the network device and perform the desired operations. This section provides two sample Python modules, which are described in their respective sections.

grpc_channel.py

The grpc_channel.py Python module provides sample functions that create a gRPC channel using the arguments provided for the selected method of authentication, server-only or mutual.

content_copy zoom_out_map
import grpc
from os.path import isfile


def grpc_authenticate_channel_mutual(server, port, root_ca_cert="", client_key="", client_cert=""):
    if not isfile(root_ca_cert):
        raise Exception("Error: root_ca_cert file does not exist")
    if (client_key == "") or (not isfile(client_key)):
        raise Exception(
            "Error: client_key option is missing or target file does not exist")
    elif (client_cert == "") or (not isfile(client_cert)):
        raise Exception(
            "Error: client_cert option is empty or target file does not exist")

    print("Creating channel")
    creds = grpc.ssl_channel_credentials(open(root_ca_cert, 'rb').read(),
                                         open(client_key, 'rb').read(),
                                         open(client_cert, 'rb').read())
    channel = grpc.secure_channel('%s:%s' % (server, port), creds)

    return channel


def grpc_authenticate_channel_server_only(server, port, root_ca_cert=""):
    if isfile(root_ca_cert):
        print("Creating channel")
        creds = grpc.ssl_channel_credentials(open(root_ca_cert, 'rb').read(),
                                             None,
                                             None)
        channel = grpc.secure_channel('%s:%s' % (server, port), creds)
        return channel
    else:
        raise Exception("root_ca_cert file does not exist")

gnoi_connect_cert_auth_mutual.py

The gnoi_connect_cert_auth_mutual.py Python application establishes a gRPC channel with the given gRPC server and executes a simple gNOI System service operation. The user provides the necessary connection and mutual authentication information as input to the application. The application invokes the appropriate function in the grpc_channel.py module to establish the gRPC channel between the client and the server. If the application successfully establishes a gRPC channel, it then executes a simple system service RPC to retrieve the time from the network device.

content_copy zoom_out_map
"""gRPC gNOI Time request utility."""

from __future__ import print_function
import argparse
import logging
from getpass import getpass

import system_pb2
import system_pb2_grpc

from grpc_channel import grpc_authenticate_channel_mutual


def get_args(parser):
    parser.add_argument('--server',
                        dest='server',
                        type=str,
                        default='localhost',
                        help='Server IP or name.  Default is localhost')

    parser.add_argument('--port',
                        dest='port',
                        nargs='?',
                        type=int,
                        default=32767,
                        help='The server port. Default is 32767')

    parser.add_argument('--client_key',
                        dest='client_key',
                        type=str,
                        default='',
                        help='Full path of the client private key.  Default ""')

    parser.add_argument('--client_cert',
                        dest='client_cert',
                        type=str,
                        default='',
                        help='Full path of the client certificate.  Default ""')

    parser.add_argument('--root_ca_cert',
                        dest='root_ca_cert',
                        required=True,
                        type=str,
                        help='Full path of the Root CA certificate.')

    parser.add_argument('--user_id',
                        dest='user_id',
                        required=True,
                        type=str,
                        help='User ID for RPC call credentials.')

    args = parser.parse_args()
    return args


def send_rpc(channel, metadata):
    stub = system_pb2_grpc.SystemStub(channel)
    print("Executing GNOI::System::Time RPC")
    req = system_pb2.TimeRequest()
    try:
        response = stub.Time(request=req, metadata=metadata, timeout=60)
    except Exception as e:
        logging.error('Error executing RPC: %s', e)
        print(e)
    else:
        logging.info('Received message: %s', response)
        return response


def main():
    parser = argparse.ArgumentParser()
    args = get_args(parser)

    grpc_server_password = getpass("gRPC server password for executing RPCs: ")
    metadata = [('username', args.user_id),
                ('password', grpc_server_password)]

    try:
        # Establish grpc channel to network device
        channel = grpc_authenticate_channel_mutual(
            args.server, args.port, args.root_ca_cert, args.client_key, args.client_cert)
        response = send_rpc(channel, metadata)
        print("Response received: time since last epoch in nanoseconds is ", str(response))
    except Exception as e:
        logging.error('Received error: %s', e)
        print(e)


if __name__ == '__main__':
    logging.basicConfig(filename='gnoi-testing.log',
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        level=logging.INFO,
                        datefmt='%Y-%m-%d %H:%M:%S')
    main()

Execute the Application

After you create applications to perform gNOI service operations, you execute the applications and provide any necessary arguments. The following example uses the scripts provided in the previous section to connect to the gRPC server on the network device and request the time. The gRPC server is configured to require and verify the client's certificate.

  • For mutual authentication, the client provides their own key and X.509 public key certificate in PEM format in addition to the server's IP address, gRPC port, and root CA certificate. The client also provides the credentials for RPC calls: the user_id argument supplies the username, and the application prompts for the user password.

    content_copy zoom_out_map
    lab@gnoi-client:~/src/proto$ python3 gnoi_connect_cert_auth_mutual.py --server 10.53.52.169 --port 32767 --root_ca_cert /etc/pki/certs/serverRootCA.crt --client_key /home/lab/certs/client.key --client_cert /home/lab/certs/client.crt --user_id gnoi-user
    gRPC server password for executing RPCs: 
    Creating channel
    Executing GNOI::System::Time RPC
    Response received: time since last epoch in nanoseconds is  time: 1650061065769701762
footer-navigation