gNOI Operating System (OS) Service
SUMMARY Use the gNOI operating system (OS
) service to upgrade the software on the target network device.
You can use the gNOI OS
service to upgrade software on the target device. The proto definition file is located at https://github.com/openconfig/gnoi/blob/master/os/os.proto.
Software installation has three main steps, which correspond to the OS
service RPCs.
- Install
- Activate
- Verify
The Install()
RPC transfers the specified image to the /var/tmp/
directory on the target device. The destination filename is the value defined in the TransferRequest
message's version
field. The Activate()
RPC installs the image and reboots the device to activate the newly installed image. The Verify()
RPC validates the OS version on the device.
You can also use the gNOI system
service SetPackage()
RPC to install software on a device. For more information, see gNOI System Service.
Supported RPCs
RPC | Description | Introduced in Release |
---|---|---|
Activate() |
Set the OS version that is used at the next reboot.
Note:
Junos devices do not support the |
Junos OS Evolved 22.2R1 |
Install() |
Transfer a software image onto the target. Note:
Junos devices do not support the |
Junos OS Evolved 22.2R1 |
Verify() |
Check the running OS version. This RPC may be called multiple times while the target boots until successful. Note:
Junos devices do not support |
Junos OS Evolved 22.2R1 |
Network Device Configuration
Before you begin:
- Configure gRPC services on the network device as described in Configure gRPC Services.
- Configure the network management system to support gNOI operations as described in Configure gNOI Services.
No additional configuration is required to use the OS
service RPCs.
Example: Install and Activate
In this example, the client executes the gnoi_os_install_activate.py
Python application, which performs the following operations:
- Copies the software package from the local network management system to the network device.
- Installs the package on the network device.
- Reboots the network device, thus activating the new software image.
The application calls the Install()
RPC with the InstallRequest()
message to transfer the file. The application tracks the progress of the file transfer by emitting progress messages at each 10 percent transfer completion interval. If the file transfer is successful, the application then calls the Activate()
RPC to install the image and reboot the target.
The application imports the grpc_channel
module to establish the channel. The grpc_channel
module is described in Configure gNOI Services. The application's arguments are stored in the args_os_install_activate.txt
file. The application and argument files are as follows:
gnoi_os_install_activate.py
"""gRPC gNOI OS Install, Activate utility.""" from __future__ import print_function import argparse import logging import os from functools import partial from getpass import getpass import os_pb2 import os_pb2_grpc from grpc_channel import grpc_authenticate_channel_mutual MAX_BYTES = 65536 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.') parser.add_argument('--no_reboot', dest='no_reboot', type=int, default=0, help='Reboot immediately or not. Default 0 (Reboot immediately)') parser.add_argument('--source_package', dest='source_package', type=str, default='', help='Full path of the source file. Default ""') parser.add_argument('--timeout', dest='timeout', type=int, default=600, help='Timeout in seconds. Default 600') parser.add_argument('--version', dest='version', type=str, default='', help='OS version to activate. Default is ""') args = parser.parse_args() return args def send_rpc(channel, metadata, args): print("Executing GNOI::OS::Install") stub = os_pb2_grpc.OSStub(channel) it = [] # Create file transfer request req = os_pb2.InstallRequest() req.transfer_request.version = args.version it.append(req) # Read source package and add to request source_package_bytes = os.path.getsize(args.source_package) with open(args.source_package, "rb") as file: # Read data in 64 KB chunks and calculate checksum and data messages for data in iter(partial(file.read, MAX_BYTES), b''): req = os_pb2.InstallRequest() req.transfer_content = data it.append(req) req = os_pb2.InstallRequest() req.transfer_end.SetInParent() it.append(req) next_pct = 0 transfer_percent = 0 validated = False activated = False try: responses = stub.Install( iter(it), metadata=metadata, timeout=args.timeout) print("OS Install start\n") for response in responses: rsp_type = response.WhichOneof('response') if rsp_type == 'install_error': print("%s: %s -- %s\n" % (rsp_type, response.install_error.type, response.install_error.detail)) raise Exception("Install Error") elif rsp_type == 'transfer_ready': print("%s: %s\n" % (rsp_type, response.transfer_ready)) elif rsp_type == 'transfer_progress': transfer_percent = int(float( response.transfer_progress.bytes_received) / float(source_package_bytes) * 100) if 0 == (transfer_percent % 10) and transfer_percent != next_pct: next_pct = transfer_percent print("Transfer percent complete: %s%%" % transfer_percent) logging.info('Transferring file %s%%', transfer_percent) elif rsp_type == 'validated': print("%s: %s -- %s\n" % (rsp_type, response.validated.version, response.validated.description)) logging.info('Validated: %s', response.validated.version) validated = True if transfer_percent > 0 and validated: print("Executing GNOI::OS::Activate") req = os_pb2.ActivateRequest() req.version = args.version req.no_reboot = args.no_reboot activate_response = stub.Activate( req, metadata=metadata, timeout=args.timeout) rsp_type = activate_response.WhichOneof('response') if rsp_type == 'activate_ok': activated = True except Exception as e: logging.error('Error installing package: %s', e) print(e) else: if activated: logging.info('Installation complete: %s', args.version) print('Installation complete for %s' % args.version) def main(): parser = argparse.ArgumentParser(fromfile_prefix_chars='@') 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, args) except Exception as e: logging.error('Received error: %s', e) print(e) if __name__ == '__main__': logging.basicConfig(filename='gnoi-install.log', format='%(asctime)s %(levelname)-8s %(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S') main()
args_os_install_activate.txt
--root_ca_cert=/etc/pki/certs/serverRootCA.crt --client_key=/home/lab/certs/client.key --client_cert=/home/lab/certs/client.crt --server=10.53.52.169 --port=32767 --user_id=gnoi-user --source_package=/home/lab/images/junos-evo-install-ptx-x86-64-22.3R1.9-EVO.iso --timeout=1800 --version=22.3R1.9-EVO
Starting in Junos OS Evolved Release 23.4R1, the version
field in the Activate()
, Install()
, and
Verify()
RPCs uses the software version string (as
displayed in /system/state/software-version
) instead of the
package name.
Execute the Application
When the client executes the application, the application copies the package from the local device to the /var/tmp
directory on the network device, installs the package, and then reboots the device to complete the installation.
lab@gnoi-client:~/src/gnoi/proto$ python3 gnoi_os_install_activate.py @args_os_install_activate.txt gRPC server password for executing RPCs: Creating channel Executing GNOI::OS::Install OS Install response transfer_ready: Transfer percent complete: 10% Transfer percent complete: 20% Transfer percent complete: 30% Transfer percent complete: 40% Transfer percent complete: 50% Transfer percent complete: 60% Transfer percent complete: 70% Transfer percent complete: 80% Transfer percent complete: 90% Transfer percent complete: 100% validated: 22.3R1.9-EVO -- Use Activate to Validate and Integrity Check the installed Image Executing GNOI::OS::Activate Installation complete for 22.3R1.9-EVO
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.
version
field in the Activate()
,
Install()
, and Verify()
RPCs uses the
software version string (as displayed in
/system/state/software-version
) instead of the package
name.