diff --git a/nvme_gw_cli.py b/nvme_gw_cli.py index 594813c8..5b3d2b75 100644 --- a/nvme_gw_cli.py +++ b/nvme_gw_cli.py @@ -9,6 +9,7 @@ import argparse import grpc +import json import nvme_gw_pb2_grpc as pb2_grpc import nvme_gw_pb2 as pb2 import nvme_gw_config @@ -54,7 +55,7 @@ def decorator(func): # attribute to point to the subcommand's associated function for arg in args: parser.add_argument(*arg[0], **arg[1]) - parser.set_defaults(func=func) + parser.set_defaults(func=func) return func return decorator @@ -152,6 +153,21 @@ def create_bdev(self, args): except Exception as error: self.logger.error(f"Failed to create bdev: \n {error}") + @cli.cmd([ + argument("-b", "--bdev", help="Bdev name", required=True), + ]) + def delete_bdev(self, args): + """Deletes a bdev.""" + + try: + delete_req = pb2.bdev_delete_req( + bdev_name=args.bdev, + ) + ret = self.stub.bdev_rbd_delete(delete_req) + self.logger.info(f"Deleted bdev: {delete_req.bdev_name}") + except Exception as error: + self.logger.error(f"Failed to delete bdev: \n {error}") + @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), argument("-s", "--serial", help="Serial number", required=True), @@ -167,6 +183,19 @@ def create_subsystem(self, args): except Exception as error: self.logger.error(f"Failed to create subsystem: \n {error}") + @cli.cmd([ + argument("-n", "--subnqn", help="Subsystem NQN", required=True), + ]) + def delete_subsystem(self, args): + """Deletes a new subsystem.""" + + try: + delete_req = pb2.subsystem_delete_req(subsystem_nqn=args.subnqn) + ret = self.stub.nvmf_delete_subsystem(delete_req) + self.logger.info(f"Deleted subsystem: {delete_req.subsystem_nqn}") + except Exception as error: + self.logger.error(f"Failed to delete subsystem: \n {error}") + @cli.cmd([ argument("-n", "--subnqn", help="Subsystem NQN", required=True), argument("-b", "--bdev", help="Bdev name", required=True), @@ -230,6 +259,20 @@ def create_listener(self, args): self.logger.error(f"Failed to create listener: \n {error}") + @cli.cmd() + def get_subsystems(self, args): + """Get subsystems.""" + + try: + get_req = pb2.subsystems_get_req() + ret = self.stub.nvmf_get_subsystems(get_req) + subsystems = json.loads(ret.subsystems) + formatted_subsystems = json.dumps(subsystems, indent=4) + self.logger.info(f"Get subsystems:\n{formatted_subsystems}") + except Exception as error: + self.logger.error(f"Failed to get subsystems: \n {error}") + + def main(): client = GatewayClient() args = client.cli.parser.parse_args() diff --git a/nvme_gw_server.py b/nvme_gw_server.py index 84abba61..ec8a5d11 100644 --- a/nvme_gw_server.py +++ b/nvme_gw_server.py @@ -16,6 +16,7 @@ import nvme_gw_pb2 as pb2 import nvme_gw_config import argparse +import json class GWService(pb2_grpc.NVMEGatewayServicer): @@ -93,6 +94,26 @@ def bdev_rbd_create(self, request, context): return pb2.bdev_info(bdev_name=bdev_name) + def bdev_rbd_delete(self, request, context): + # Delete bdev + self.logger.info({ + f"Received request to delete bdev: {request.bdev_name}", + }) + try: + return_string = self.spdk_rpc.bdev.bdev_rbd_delete( + self.client, + request.bdev_name, + ) + self.logger.info(f"Deleted bdev {request.bdev_name}") + + except Exception as ex: + self.logger.error(f"bdev delete failed with: \n {ex}") + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(f"{ex}") + return pb2.req_status() + + return pb2.req_status(status=return_string) + def nvmf_create_subsystem(self, request, context): # Create an NVMe Subsystem self.logger.info({ @@ -117,6 +138,26 @@ def nvmf_create_subsystem(self, request, context): return pb2.subsystem_info(subsystem_nqn=request.subsystem_nqn, created=return_status) + def nvmf_delete_subsystem(self, request, context): + # Delete an NVMe Subsystem + self.logger.info({ + f"Received request to delete: {request.subsystem_nqn}", + }) + + try: + return_string = self.spdk_rpc.nvmf.nvmf_delete_subsystem( + self.client, + nqn=request.subsystem_nqn, + ) + self.logger.info(f"returned with status: {return_string}") + except Exception as ex: + self.logger.error(f"delete_subsystem failed with: \n {ex}") + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(f"{ex}") + return pb2.req_status() + + return pb2.req_status(status=return_string) + def nvmf_subsystem_add_ns(self, request, context): # Add given NS to a given subsystem self.logger.info({ @@ -214,6 +255,24 @@ def nvmf_subsystem_add_listener(self, request, context): return pb2.req_status(status=return_string) + def nvmf_get_subsystems(self, request, context): + # Get NVMe Subsystems + self.logger.info({ + f"Received request to get subsystems", + }) + + try: + ret = self.spdk_rpc.nvmf.nvmf_get_subsystems( + self.client, + ) + self.logger.info(f"returned with: {ret}") + except Exception as ex: + self.logger.error(f"get_subsystems failed with: \n {ex}") + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(f"{ex}") + return pb2.subsystems_info() + + return pb2.subsystems_info(subsystems=json.dumps(ret)) def serve(gw_config_filename): diff --git a/proto/nvme_gw.proto b/proto/nvme_gw.proto index 8319497c..8e6c7ecf 100644 --- a/proto/nvme_gw.proto +++ b/proto/nvme_gw.proto @@ -11,29 +11,38 @@ syntax = "proto3"; service NVMEGateway { - //start the SPDK target - rpc start_spdk(spdk_start_req) returns(spdk_status){} + // start the SPDK target + rpc start_spdk(spdk_start_req) returns(spdk_status) {} - //Create Transport + // Create Transport rpc nvmf_create_transport(create_transport_req) returns(req_status) {} // Create bdev/ NVMe Namespace from an RBD image rpc bdev_rbd_create(bdev_create_req) returns (bdev_info) {} - //Create NVMf Subsystem + // Delete RBD bdev + rpc bdev_rbd_delete(bdev_delete_req) returns (req_status) {} + + // Create NVMf Subsystem rpc nvmf_create_subsystem(subsystem_create_req) returns(subsystem_info) {} + // Delete NVMf Subsystem + rpc nvmf_delete_subsystem(subsystem_delete_req) returns(req_status) {} + // Add NVMf namespace to nvme subsystem rpc nvmf_subsystem_add_ns(subsystem_add_ns_req) returns(nsid) {} - //Add Host to a subsystem (so all namespaces in that subsystem) + // Add Host to a subsystem (so all namespaces in that subsystem) rpc nvmf_subsystem_add_host(subsystem_add_host_req) returns (req_status) {} - //Allow any host access to given subsystem. #ifdef TEST + // Allow any host access to given subsystem. #ifdef TEST rpc nvmf_subsystem_allow_any_host(subsystem_allow_any_host_req) returns (req_status) {} - //Add an SPDK-NVMf listener at a given IP addr/ tcp port + // Add an SPDK-NVMf listener at a given IP addr/ tcp port rpc nvmf_subsystem_add_listener(subsystem_add_listener_req) returns(req_status) {} + + // Get NVMf Subsystems + rpc nvmf_get_subsystems(subsystems_get_req) returns(subsystems_info) {} } message spdk_start_req { @@ -46,7 +55,7 @@ message spdk_status { message bdev_create_req { - optional string bdev_name = 1; + optional string bdev_name = 1; optional string user_id = 2; string ceph_pool_name = 3; //required string rbd_name = 4; //required @@ -57,6 +66,10 @@ message bdev_info { string bdev_name = 1; } +message bdev_delete_req { + string bdev_name = 1; +} + message subsystem_create_req { string subsystem_nqn = 1; //required optional string tgt_name = 2; //parent NVMeoF target name @@ -71,11 +84,15 @@ message subsystem_info { bool created = 2; //Status of the create request } +message subsystem_delete_req { + string subsystem_nqn = 1; +} + message subsystem_add_ns_req { string subsystem_nqn = 1; //required optional int32 nsid = 2; //Default: automaticaly assigned nsid string bdev_name = 3; //required. Name of bdev to expose as namespace - optional string nguid = 4; + optional string nguid = 4; optional string euid = 5; optional string uuid = 6; optional string ptpl_file = 7; //file path to store/ restore persistent reservation info @@ -87,13 +104,13 @@ message nsid { } message subsystem_add_host_req { - string subsystem_nqn = 1; //subsystem to which host is being added + string subsystem_nqn = 1; //subsystem to which host is being added string host_nqn = 2; //nqn of host requesting access optional string tgt_name = 3; //Parent NVMe-oF target name } message req_status { - bool status = 1; + bool status = 1; } message subsystem_allow_any_host_req { @@ -108,10 +125,17 @@ message create_transport_req { message subsystem_add_listener_req { string nqn = 1; //subsystem for which listener is being added - optional string tgt_name = 2; + optional string tgt_name = 2; string trtype = 3; string adrfam = 4; string traddr = 5; - string trsvcid = 6; + string trsvcid = 6; +} + +message subsystems_get_req { +} + +message subsystems_info { + string subsystems = 1; }