]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add gw_groups support to nvmeof api
authorNizamudeen A <nia@redhat.com>
Wed, 28 Aug 2024 13:03:19 +0000 (18:33 +0530)
committerNizamudeen A <nia@redhat.com>
Wed, 11 Sep 2024 07:47:20 +0000 (13:17 +0530)
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 <nia@redhat.com>
src/pybind/mgr/cephadm/services/nvmeof.py
src/pybind/mgr/dashboard/controllers/nvmeof.py
src/pybind/mgr/dashboard/openapi.yaml
src/pybind/mgr/dashboard/services/nvmeof_cli.py
src/pybind/mgr/dashboard/services/nvmeof_client.py
src/pybind/mgr/dashboard/services/nvmeof_conf.py

index b91427dcace0f1d142da143b429b6231cc0690fe..a9b26816efbb7049e0b4b01f953ec8924ece2b58 100644 (file)
@@ -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
 
index b40690d8380c7a1b49920a53738f25441ccaf15d..db54ac46162212c32e97690005bee09d5c8232e9 100644 (file)
@@ -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)
                 )
index 1b95c1d22035499988d16a55096c351be6d4456c..41d90cfe7b731ac2dc558d0a6f5d9b60a4d7973a 100644 (file)
@@ -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:
index 75a121a48d6e66f3106aa9dfd4a30d82567cf32c..2974fa0010db2ad32c2e6f9fb7fee6575bbcde64 100644 (file)
@@ -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 <file>
     '''
     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)
index 019ecf0267c81d65e86dcda644246eae796049bc..d6b126500b0ddbf7c428a7146147d3fafc31e830 100644 (file)
@@ -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)
index 3f076d7b216ad069d502faded95259df9cb96ceb..7e015ae83acf47f96b850e21bbdec323ae67bd24 100644 (file)
@@ -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}',