gNOI File Service
SUMMARY Use the gNOI File
service to manage files on a network device.
Use the File
service RPCs to transfer and delete files or retrieve information
about files. The proto definition file is located at https://github.com/openconfig/gnoi/blob/master/file/file.proto.
Supported RPCs
RPC | Description | Introduced in Release |
---|---|---|
Get() |
Read and stream the contents of a file from the target. The file is streamed by sequential messages, each message containing up to 64KB of data. A final message is sent prior to closing the stream that contains the hash of the data sent. The operation returns an error if the file does not exist or there is an error reading the file. |
Junos OS Evolved 22.2R1 |
Put() |
Stream data to a file on the target. The file is sent in sequential messages, each message containing up to 64KB of data. A final message must be sent that includes the hash of the data. The operation returns an error if the location does not exist or there is an error writing the data. If no checksum is received, the target removes the partially transmitted file. A failure will not alter any existing file of the same name. |
Junos OS Evolved 22.2R1 |
Remove() |
Remove the specified file from the target. The operation returns an error if the file does not exist, if the file path resolves to a directory, or if the remove operation encounters an error. |
Junos OS Evolved 22.2R1 |
Stat() |
Return metadata about a file on the target device. The operation returns an error if the file does not exist or there is an error accessing the metadata. |
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.
Example: Get File
This example provides a simple Python application, gnoi_file_get.py
, to download a file from the target device to the local network management system.
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_file_get.txt
file. The application and argument files are presented here.
gnoi_file_get.py
"""gNOI Get File utility.""" from __future__ import print_function import argparse import hashlib import logging from getpass import getpass import file_pb2 import file_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.') parser.add_argument('--dest_file', dest='dest_file', type=str, default='', help='Full path for destination file. Default ""') parser.add_argument('--source_file', dest='source_file', type=str, default='', help='Full path of source file to retrieve. Default ""') args = parser.parse_args() return args def send_rpc(channel, metadata, args): stub = file_pb2_grpc.FileStub(channel) print("Executing GNOI::File::Get") # Prepare hash generator gen_hash = hashlib.sha256() # Get File req = file_pb2.GetRequest() req.remote_file = args.source_file hashvalue = None hm = None count = 1 with open(args.dest_file, "wb") as file: # Read data in 64 KB chunks and calculate checksum and data messages print("Retrieving file") try: for msg in stub.Get(req, metadata=metadata, timeout=120): if msg.WhichOneof('response') == "contents": count = count + 1 file.write(msg.contents) gen_hash.update(msg.contents) else: hashvalue = msg.hash.hash hm = msg.hash.method print("File transfer complete: ", args.dest_file) except Exception as e: logging.error("Get() operation error. %s", e) print(e) else: file.close() ehashvalue = gen_hash.hexdigest().encode() if (ehashvalue != hashvalue): raise ValueError( 'Hash value mismatch. Expected "%s", got "%s"' % (ehashvalue, hashvalue)) if (hm != 1): raise ValueError( 'Hash method mismatch. Expected "1", got "%s"' % (hm)) logging.info("Downloaded file: %s", args.dest_file) 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) send_rpc(channel, metadata, args) 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()
args_file_get.txt
--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 --source_file=/var/log/messages --dest_file=downloads/10.53.52.169-messages
Execute the Application
When the client executes the application, it transfers the specified file from the target device to the local device.
lab@gnoi-client:~/src/gnoi/proto$ python3 gnoi_file_get.py @args_file_get.txt gRPC server password for executing RPCs: Creating channel Executing GNOI::File::Get Retrieving file File transfer complete: downloads/10.53.52.169-messages
Example: Put File
This example provides a simple Python application, gnoi_file_put.py
, to upload a file from the local network management system to the target device.
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_file_put.txt
file. The application and argument files are presented here.
gnoi_file_put.py
"""gNOI Put File utility.""" from __future__ import print_function import argparse import hashlib import logging import sys from functools import partial from getpass import getpass import file_pb2 import file_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('--dest_file', dest='dest_file', type=str, default='', help='Full path for destination file. Default ""') parser.add_argument('--dest_file_mode', dest='dest_file_mode', type=int, default=600, help='Destination file mode (file permissions in octal). Default 600') parser.add_argument('--hash_method', dest='hash_method', type=str, default='unspecified', help='Hash method. Valid values are md5, sha256, sha512, or unspecified. Default: unspecified') parser.add_argument('--source_file', dest='source_file', type=str, default='', help='Full path of source file to transfer. Default ""') args = parser.parse_args() return args def send_rpc(channel, metadata, args): stub = file_pb2_grpc.FileStub(channel) print("Executing GNOI::File::Put") # Prepare hash generator if args.hash_method == "sha256": gen_hash = hashlib.sha256() hm = 1 elif args.hash_method == "sha512": gen_hash = hashlib.sha512() hm = 2 elif args.hash_method == "md5": gen_hash = hashlib.md5() hm = 3 else: print("Unsupported hash method:", args.hash_method) sys.exit(1) # Put File req = file_pb2.PutRequest() req.open.remote_file = args.dest_file req.open.permissions = args.dest_file_mode it = [] it.append(req) # Read source file and add to request with open(args.source_file, "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 = file_pb2.PutRequest() req.contents = data it.append(req) gen_hash.update(data) # Checksum message req = file_pb2.PutRequest() req.hash.hash = gen_hash.hexdigest().encode() req.hash.method = hm it.append(req) # Send PutRequest try: print("Sending file.") response = stub.Put(iter(it), metadata=metadata, timeout=120) except Exception as e: logging.error("Error uploading source file %s to %s. Error: %s", args.source_file, args.dest_file, e) print(e) else: print("File transfer complete: ", args.dest_file) logging.info("Uploaded file: %s", args.dest_file) 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) send_rpc(channel, metadata, args) 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()
args_file_put.txt
--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 --source_file=scripts/op/ospf-summary.slax --dest_file=/var/db/scripts/op/ospf-summary.slax --dest_file_mode=644 --hash_method=sha256
Execute the Application
When the client executes the application, it transfers the specified file from the local device to the target device and sets the file permissions according to the dest_file_mode
value.
lab@gnoi-client:~/src/gnoi/proto$ python3 gnoi_file_put.py @args_file_put.txt gRPC server password for executing RPCs: Creating channel Executing GNOI::File::Put Sending file. File transfer complete: /var/db/scripts/op/ospf-summary.slax