配置 gNOI 服务
总结 将远程网络管理系统配置为可在网络设备上执行 gNOI 操作的 gRPC 客户端。
gRPC 网络操作接口 (gNOI) 使用 gRPC 远程过程调用 (gRPC) 框架在网络设备上执行操作。网络管理系统必须安装 gRPC 堆栈。
OpenConfig 为 gNOI 服务定义了原型定义文件。原型定义文件定义给定服务的操作 (RPC) 和数据结构(消息)。这些定义与语言无关。gRPC 支持使用许多不同的语言来执行服务操作。您必须为所选语言编译原型定义文件。然后,创建使用已编译文件中的对象(类、函数、方法等)的应用程序,以连接到网络设备上的 gRPC 服务器并执行所需的操作。
有关将 gRPC 与不同的受支持语言一起使用的信息,请参阅 gRPC 文档。以下部分提供了用于设置 gRPC 客户端以及下载和编译 Python 的 gNOI 原型定义文件的示例命令。必须使用适用于所选操作系统、环境和 gRPC 语言的命令。
在配置 gRPC 客户端之前,请按照 配置 gRPC 服务中的定义配置 gRPC 服务器。
设置 gRPC 客户端
gNOI 使用 gRPC 框架在网络设备上执行操作。gRPC 支持使用许多不同的语言。在使用所选语言执行 gNOI 操作之前,必须在网络管理系统上安装 gRPC 堆栈。
例如,要在运行 Ubuntu 20.04 LTS 的网络管理系统上安装 Python 的 gRPC 堆栈(在适当的情况下使用 sudo
):
编译原型定义文件
gRPC 支持使用多种语言。若要在网络设备上执行 gRPC 操作,必须针对所选语言编译相应的原型定义文件。OpenConfig 在 OpenConfig GitHub 存储库中提供了必要的原型定义文件。您可以使用协议缓冲区编译器(protoc
或等效应用程序)来编译 .proto
文件。
对于此设置,我们执行一个脚本,将所有所需的 .proto
文件复制到目录中,更新文件以使用相对导入语句,然后编译文件。
要下载并编译 Python 的 gNOI 原型定义文件,请执行以下操作:
创建 gNOI 应用程序
编译原型定义文件后,将创建使用已编译文件中的对象的应用程序。应用程序连接到网络设备上的 gRPC 服务器并执行所需的操作。本节提供了两个示例 Python 模块,它们在各自的部分中进行了介绍。
grpc_channel.py
Python grpc_channel.py
模块提供了示例函数,这些函数使用为所选身份验证方法(仅限服务器或相互)提供的参数创建 gRPC 通道。
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
gnoi_connect_cert_auth_mutual.py
Python 应用程序与给定的 gRPC 服务器建立 gRPC 通道,并执行简单的 gNOI System
服务操作。用户提供必要的连接和相互身份验证信息作为应用程序的输入。应用程序调用模块中的grpc_channel.py
相应函数,以在客户端和服务器之间建立 gRPC 通道。如果应用程序成功建立了 gRPC 通道,它将执行一个简单的系统服务 RPC 以从网络设备检索时间。
"""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=50051, help='The server port. Default is 50051') 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()
执行应用程序
创建应用程序以执行 gNOI 服务操作后,可以执行应用程序并提供任何必要的参数。下面的示例使用上一节中提供的脚本连接到网络设备上的 gRPC 服务器并请求时间。gRPC 服务器配置为需要并验证客户端的证书。
-
对于相互身份验证,除了服务器的 IP 地址、gRPC 端口和根 CA 证书外,客户端还提供自己的密钥和 PEM 格式的 X.509 公钥证书。客户端还提供用于 RPC 调用的凭据:
user_id
参数提供用户名,应用程序提示输入用户密码。lab@gnoi-client:~/src/proto$ python3 gnoi_connect_cert_auth_mutual.py --server 10.53.52.169 --port 50051 --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