From: Nizamudeen A Date: Wed, 28 Aug 2024 13:03:19 +0000 (+0530) Subject: mgr/dashboard: add gw_groups support to nvmeof api X-Git-Tag: v20.0.0~1080^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=47f57d434d1690cc3c29dd048ec4cdedf618571f;p=ceph.git mgr/dashboard: add gw_groups support to nvmeof api Introduces a gw_group query-param to gateway and subsystem requests. Modified the dashboard config to support adding more than one gateway to the list. Fixes: https://tracker.ceph.com/issues/67774 Signed-off-by: Nizamudeen A --- diff --git a/src/pybind/mgr/cephadm/services/nvmeof.py b/src/pybind/mgr/cephadm/services/nvmeof.py index b91427dcace0f..a9b26816efbb7 100644 --- a/src/pybind/mgr/cephadm/services/nvmeof.py +++ b/src/pybind/mgr/cephadm/services/nvmeof.py @@ -144,7 +144,8 @@ class NvmeofService(CephService): cmd_dicts.append({ 'prefix': 'dashboard nvmeof-gateway-add', 'inbuf': service_url, - 'name': service_name + 'name': service_name, + 'group': spec.group }) return cmd_dicts diff --git a/src/pybind/mgr/dashboard/controllers/nvmeof.py b/src/pybind/mgr/dashboard/controllers/nvmeof.py index b40690d8380c7..db54ac4616221 100644 --- a/src/pybind/mgr/dashboard/controllers/nvmeof.py +++ b/src/pybind/mgr/dashboard/controllers/nvmeof.py @@ -30,8 +30,8 @@ else: @EndpointDoc("Get information about the NVMeoF gateway") @map_model(model.GatewayInfo) @handle_nvmeof_error - def list(self): - return NVMeoFClient().stub.get_gateway_info( + def list(self, gw_group: Optional[str] = None): + return NVMeoFClient(gw_group=gw_group).stub.get_gateway_info( NVMeoFClient.pb2.get_gateway_info_req() ) @@ -41,8 +41,8 @@ else: @EndpointDoc("List all NVMeoF subsystems") @map_collection(model.Subsystem, pick="subsystems") @handle_nvmeof_error - def list(self): - return NVMeoFClient().stub.list_subsystems( + def list(self, gw_group: Optional[str] = None): + return NVMeoFClient(gw_group=gw_group).stub.list_subsystems( NVMeoFClient.pb2.list_subsystems_req() ) @@ -52,8 +52,8 @@ else: ) @map_model(model.Subsystem, first="subsystems") @handle_nvmeof_error - def get(self, nqn: str): - return NVMeoFClient().stub.list_subsystems( + def get(self, nqn: str, gw_group: Optional[str] = None): + return NVMeoFClient(gw_group=gw_group).stub.list_subsystems( NVMeoFClient.pb2.list_subsystems_req(subsystem_nqn=nqn) ) @@ -67,8 +67,9 @@ else: ) @empty_response @handle_nvmeof_error - def create(self, nqn: str, enable_ha: bool, max_namespaces: int = 1024): - return NVMeoFClient().stub.create_subsystem( + def create(self, nqn: str, enable_ha: bool, max_namespaces: int = 1024, + gw_group: Optional[str] = None): + return NVMeoFClient(gw_group=gw_group).stub.create_subsystem( NVMeoFClient.pb2.create_subsystem_req( subsystem_nqn=nqn, max_namespaces=max_namespaces, enable_ha=enable_ha ) @@ -83,8 +84,8 @@ else: ) @empty_response @handle_nvmeof_error - def delete(self, nqn: str, force: Optional[str] = "false"): - return NVMeoFClient().stub.delete_subsystem( + def delete(self, nqn: str, force: Optional[str] = "false", gw_group: Optional[str] = None): + return NVMeoFClient(gw_group=gw_group).stub.delete_subsystem( NVMeoFClient.pb2.delete_subsystem_req( subsystem_nqn=nqn, force=str_to_bool(force) ) diff --git a/src/pybind/mgr/dashboard/openapi.yaml b/src/pybind/mgr/dashboard/openapi.yaml index 1b95c1d220354..41d90cfe7b731 100644 --- a/src/pybind/mgr/dashboard/openapi.yaml +++ b/src/pybind/mgr/dashboard/openapi.yaml @@ -8182,7 +8182,12 @@ paths: - NFS-Ganesha /api/nvmeof/gateway: get: - parameters: [] + parameters: + - allowEmptyValue: true + in: query + name: gw_group + schema: + type: string responses: '200': content: @@ -8205,7 +8210,12 @@ paths: - NVMe-oF Gateway /api/nvmeof/subsystem: get: - parameters: [] + parameters: + - allowEmptyValue: true + in: query + name: gw_group + schema: + type: string responses: '200': content: @@ -8236,6 +8246,8 @@ paths: enable_ha: description: Enable high availability type: boolean + gw_group: + type: string max_namespaces: default: 1024 description: Maximum number of namespaces @@ -8287,6 +8299,11 @@ paths: name: force schema: type: boolean + - allowEmptyValue: true + in: query + name: gw_group + schema: + type: string responses: '202': content: @@ -8320,6 +8337,11 @@ paths: required: true schema: type: string + - allowEmptyValue: true + in: query + name: gw_group + schema: + type: string responses: '200': content: diff --git a/src/pybind/mgr/dashboard/services/nvmeof_cli.py b/src/pybind/mgr/dashboard/services/nvmeof_cli.py index 75a121a48d6e6..2974fa0010db2 100644 --- a/src/pybind/mgr/dashboard/services/nvmeof_cli.py +++ b/src/pybind/mgr/dashboard/services/nvmeof_cli.py @@ -19,13 +19,13 @@ def list_nvmeof_gateways(_): @CLIWriteCommand('dashboard nvmeof-gateway-add') @CLICheckNonemptyFileInput(desc='NVMe-oF gateway configuration') -def add_nvmeof_gateway(_, inbuf, name: str): +def add_nvmeof_gateway(_, inbuf, name: str, group: str): ''' Add NVMe-oF gateway configuration. Gateway URL read from -i ''' service_url = inbuf try: - NvmeofGatewaysConfig.add_gateway(name, service_url) + NvmeofGatewaysConfig.add_gateway(name, service_url, group) return 0, 'Success', '' except NvmeofGatewayAlreadyExists as ex: return -errno.EEXIST, '', str(ex) diff --git a/src/pybind/mgr/dashboard/services/nvmeof_client.py b/src/pybind/mgr/dashboard/services/nvmeof_client.py index 019ecf0267c81..d6b126500b0dd 100644 --- a/src/pybind/mgr/dashboard/services/nvmeof_client.py +++ b/src/pybind/mgr/dashboard/services/nvmeof_client.py @@ -22,13 +22,24 @@ else: class NVMeoFClient(object): pb2 = pb2 - def __init__(self): + def __init__(self, gw_group: Optional[str] = None): logger.info("Initiating nvmeof gateway connection...") - service_name, self.gateway_addr = NvmeofGatewaysConfig.get_service_info() + try: + if not gw_group: + service_name, self.gateway_addr = NvmeofGatewaysConfig.get_service_info() + else: + service_name, self.gateway_addr = NvmeofGatewaysConfig.get_service_info( + gw_group + ) + except TypeError as e: + raise DashboardException( + f'Unable to retrieve the gateway info: {e}' + ) root_ca_cert = NvmeofGatewaysConfig.get_root_ca_cert(service_name) - client_key = NvmeofGatewaysConfig.get_client_key(service_name) - client_cert = NvmeofGatewaysConfig.get_client_cert(service_name) + if root_ca_cert: + client_key = NvmeofGatewaysConfig.get_client_key(service_name) + client_cert = NvmeofGatewaysConfig.get_client_cert(service_name) if root_ca_cert and client_key and client_cert: logger.info('Securely connecting to: %s', self.gateway_addr) diff --git a/src/pybind/mgr/dashboard/services/nvmeof_conf.py b/src/pybind/mgr/dashboard/services/nvmeof_conf.py index 3f076d7b216ad..7e015ae83acf4 100644 --- a/src/pybind/mgr/dashboard/services/nvmeof_conf.py +++ b/src/pybind/mgr/dashboard/services/nvmeof_conf.py @@ -51,11 +51,19 @@ class NvmeofGatewaysConfig(object): return cls._load_config_from_store() @classmethod - def add_gateway(cls, name, service_url): + def add_gateway(cls, name, service_url, group): config = cls.get_gateways_config() - if name in config: - raise NvmeofGatewayAlreadyExists(name) - config['gateways'][name] = {'service_url': service_url} + + if name in config.get('gateways', {}): + existing_gateways = config['gateways'][name] + if any(gateway['service_url'] == service_url for gateway in existing_gateways): + return + + if name in config.get('gateways', {}): + config['gateways'][name].append({'service_url': service_url, 'group': group}) + else: + config['gateways'][name] = [{'service_url': service_url, 'group': group}] + cls._save_config(config) @classmethod @@ -67,12 +75,23 @@ class NvmeofGatewaysConfig(object): cls._save_config(config) @classmethod - def get_service_info(cls): + def get_service_info(cls, group=None): try: config = cls.get_gateways_config() - service_name = list(config['gateways'].keys())[0] - addr = config['gateways'][service_name]['service_url'] - return service_name, addr + gateways = config.get('gateways', {}) + if not gateways: + return None + + if group: + for service_name, entries in gateways.items(): + if group in service_name: + entry = next((entry for entry in entries if entry['group'] == group), None) + if entry['group'] == group: # type: ignore + return service_name, entry['service_url'] # type: ignore + return None + + service_name = list(gateways.keys())[0] + return service_name, config['gateways'][service_name][0]['service_url'] except (KeyError, IndexError) as e: raise DashboardException( msg=f'NVMe-oF configuration is not set: {e}',