From 0f6001f1ef555a3f4f8f7c58ac918a2fb638acfb Mon Sep 17 00:00:00 2001 From: Artsiom Koltun Date: Thu, 8 Feb 2024 11:46:31 +0100 Subject: [PATCH 1/2] feat(storage): add NvmeRemoteController class Signed-off-by: Artsiom Koltun --- pydpu/storage.py | 107 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/pydpu/storage.py b/pydpu/storage.py index 504b143..83188f4 100644 --- a/pydpu/storage.py +++ b/pydpu/storage.py @@ -6,7 +6,13 @@ import grpc from google.protobuf import field_mask_pb2, wrappers_pb2 -from .proto.v1 import frontend_nvme_pb2, frontend_nvme_pb2_grpc, opicommon_pb2 +from .proto.v1 import ( + backend_nvme_pb2, + backend_nvme_pb2_grpc, + frontend_nvme_pb2, + frontend_nvme_pb2_grpc, + opicommon_pb2, +) class NvmeSubsystem: @@ -333,3 +339,102 @@ def stats(self, address): ) ) return res + + +class NvmeRemoteController: + """An object representing Nvme remote controller. + Args: + multipath: multipath mode: + backend_nvme_pb2.NVME_MULTIPATH_DISABLE, + backend_nvme_pb2.NVME_MULTIPATH_FAILOVER, + backend_nvme_pb2.NVME_MULTIPATH_MULTIPATH + hdgst: header digest + ddgst: data digest + """ + + def __repr__(self) -> str: + return ( + f"{type(self).__name__}({str(self.id)}, " + + f"multipath={str(self.multipath)}, hdgst={str(self.hdgst)}, " + + f"ddgst={str(self.ddgst)})" + ) + + def __init__(self, multipath: int, hdgst: bool, ddgst: bool) -> None: + self.id = "opi-" + str(uuid.uuid1()) + self.multipath = multipath + self.hdgst = hdgst + self.ddgst = ddgst + self.name = "nvmeRemoteControllers/{}".format(self.id) + + def create(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.CreateNvmeRemoteController( + request=backend_nvme_pb2.CreateNvmeRemoteControllerRequest( + nvme_remote_controller_id=self.id, + nvme_remote_controller=backend_nvme_pb2.NvmeRemoteController( + multipath=self.multipath, + tcp=backend_nvme_pb2.TcpController( + hdgst=self.hdgst, + ddgst=self.ddgst, + ), + ), + ) + ) + return res + + def update(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.UpdateNvmeRemoteController( + request=backend_nvme_pb2.UpdateNvmeRemoteControllerRequest( + update_mask=field_mask_pb2.FieldMask(paths=["*"]), + nvme_remote_controller=backend_nvme_pb2.NvmeRemoteController( + name=self.name, + multipath=self.multipath, + tcp=backend_nvme_pb2.TcpController( + hdgst=self.hdgst, + ddgst=self.ddgst, + ), + ), + ) + ) + return res + + def list(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.ListNvmeRemoteControllers( + request=backend_nvme_pb2.ListNvmeRemoteControllersRequest() + ) + return res + + def delete(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.DeleteNvmeRemoteController( + request=backend_nvme_pb2.DeleteNvmeRemoteControllerRequest( + name=self.name, + ) + ) + return res + + def get(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.GetNvmeRemoteController( + request=backend_nvme_pb2.GetNvmeRemoteControllerRequest( + name=self.name, + ) + ) + return res + + def stats(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.StatsNvmeRemoteController( + request=backend_nvme_pb2.StatsNvmeRemoteControllerRequest( + name=self.name, + ) + ) + return res From 0a602cef379bec6a7a3b7a0012207313a252addb Mon Sep 17 00:00:00 2001 From: Artsiom Koltun Date: Thu, 8 Feb 2024 11:46:46 +0100 Subject: [PATCH 2/2] feat(storage): add NvmePath class Signed-off-by: Artsiom Koltun --- pydpu/storage.py | 125 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/pydpu/storage.py b/pydpu/storage.py index 83188f4..1d5d445 100644 --- a/pydpu/storage.py +++ b/pydpu/storage.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 Dell Inc, or its subsidiaries. +import ipaddress import uuid import grpc @@ -438,3 +439,127 @@ def stats(self, address): ) ) return res + + +ip_to_grpc_version = { + 4: opicommon_pb2.NVME_ADDRESS_FAMILY_IPV4, + 6: opicommon_pb2.NVME_ADDRESS_FAMILY_IPV6, +} + + +class NvmeTcpPath: + """An object representing Nvme TCP path. + Args: + ip: ip address to target controller + port: port of target controller + subnqn: subsystem nqn + hostnqn: host nqn + """ + + def __repr__(self) -> str: + return ( + f"{type(self).__name__}({str(self.id)}, ip={str(self.ip)}, " + + f"adrfam={str(self.adrfam)}, port={str(self.port)}), " + + f"subnqn={str(self.subnqn)}, hostnqn={str(self.hostnqn)}" + ) + + def __init__( + self, + remote_controller: NvmeRemoteController, + ip: str, + port: int, + subnqn: str, + hostnqn: str = "", + ) -> None: + self.id = "opi-" + str(uuid.uuid1()) + self.controller = remote_controller + self.ip = ip + self.port = port + self.subnqn = subnqn + self.hostnqn = hostnqn + self.name = "nvmeRemoteControllers/{}/nvmePaths/{}".format( + remote_controller.id, self.id + ) + self.adrfam = ip_to_grpc_version[ipaddress.ip_address(self.ip).version] + + def create(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.CreateNvmePath( + request=backend_nvme_pb2.CreateNvmePathRequest( + parent=self.controller.name, + nvme_path_id=self.id, + nvme_path=backend_nvme_pb2.NvmePath( + trtype=opicommon_pb2.NVME_TRANSPORT_TYPE_TCP, + traddr=self.ip, + fabrics=backend_nvme_pb2.FabricsPath( + trsvcid=self.port, + subnqn=self.subnqn, + adrfam=self.adrfam, + hostnqn=self.hostnqn, + ), + ), + ) + ) + return res + + def update(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.UpdateNvmePath( + request=backend_nvme_pb2.UpdateNvmePathRequest( + update_mask=field_mask_pb2.FieldMask(paths=["*"]), + nvme_path=backend_nvme_pb2.NvmePath( + name=self.name, + trtype=opicommon_pb2.NVME_TRANSPORT_TYPE_TCP, + traddr=self.ip, + fabrics=backend_nvme_pb2.FabricsPath( + trsvcid=self.port, + subnqn=self.subnqn, + adrfam=self.adrfam, + hostnqn=self.hostnqn, + ), + ), + ) + ) + return res + + def list(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.ListNvmePaths( + request=backend_nvme_pb2.ListNvmePathsRequest( + parent=self.controller.name + ) + ) + return res + + def delete(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.DeleteNvmePath( + request=backend_nvme_pb2.DeleteNvmePathRequest( + name=self.name, + ) + ) + return res + + def get(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.GetNvmePath( + request=backend_nvme_pb2.GetNvmePathRequest( + name=self.name, + ) + ) + return res + + def stats(self, address): + with grpc.insecure_channel(address) as channel: + stub = backend_nvme_pb2_grpc.NvmeRemoteControllerServiceStub(channel) + res = stub.StatsNvmePath( + request=backend_nvme_pb2.StatsNvmePathRequest( + name=self.name, + ) + ) + return res