]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard: Add DHCHAP controller to NVME "host add" command.
authorGil Bregman <gbregman@il.ibm.com>
Tue, 24 Feb 2026 17:53:43 +0000 (19:53 +0200)
committerGil Bregman <gbregman@il.ibm.com>
Wed, 25 Feb 2026 16:31:48 +0000 (18:31 +0200)
Fixes: https://tracker.ceph.com/issues/74939
Signed-off-by: Gil Bregman <gbregman@il.ibm.com>
src/pybind/mgr/dashboard/controllers/nvmeof.py
src/pybind/mgr/dashboard/model/nvmeof.py
src/pybind/mgr/dashboard/openapi.yaml

index 893560486ef0825254e26158dad6d35384bff66b..0ef375e5268744decbc11c1c920b902a73b89031 100644 (file)
@@ -1233,9 +1233,25 @@ else:
                 )
             )
 
+    def _get_dhchap_controller_key_origin_string(val):
+        if val == "no_key":
+            return "No Key"
+        elif val == "host_specific":
+            return "Host Specific"
+        elif val == "subsystem_implicit":
+            return "Subsystem Implicit"
+        return val
+
     def _update_hosts(hosts_info_resp):
         if hosts_info_resp.get('allow_any_host'):
             hosts_info_resp['hosts'].insert(0, {"nqn": "*"})
+        hosts = hosts_info_resp.get('hosts')
+        if not hosts:
+            hosts = []
+        for h in hosts:
+            orig = h.get("dhchap_controller_origin")
+            if orig:
+                h["dhchap_controller_origin"] = _get_dhchap_controller_key_origin_string(orig)
         return hosts_info_resp
 
     @APIRouter("/nvmeof/subsystem/{nqn}/host", Scope.NVME_OF)
@@ -1282,6 +1298,7 @@ else:
         @handle_nvmeof_error
         def create(
             self, nqn: str, host_nqn: str, dhchap_key: Optional[str] = None,
+            dhchap_controller_key: Optional[str] = None,
             psk: Optional[str] = None, gw_group: Optional[str] = None,
             server_address: Optional[str] = None
         ):
@@ -1291,7 +1308,9 @@ else:
             ).stub.add_host(
                 NVMeoFClient.pb2.add_host_req(
                     subsystem_nqn=nqn, host_nqn=host_nqn,
-                    dhchap_key=dhchap_key, psk=psk)
+                    dhchap_key=dhchap_key,
+                    dhchap_ctrlr_key=dhchap_controller_key,
+                    psk=psk)
             )
 
         @empty_response
@@ -1343,7 +1362,36 @@ else:
                 NVMeoFClient.pb2.change_host_key_req(
                     subsystem_nqn=nqn,
                     host_nqn=host_nqn,
-                    dhchap_key=dhchap_key)
+                    dhchap_key=dhchap_key,
+                    dhchap_ctrlr_key="-")
+            )
+
+        @empty_response
+        @NvmeofCLICommand("nvmeof host change_controller_key", model.RequestStatus)
+        @EndpointDoc(
+            "Change host DH-HMAC-CHAP controller key",
+            parameters={
+                "nqn": Param(str, "NVMeoF subsystem NQN"),
+                "host_nqn": Param(str, 'NVMeoF host NQN'),
+                "dhchap_controller_key": Param(str, 'Host DH-HMAC-CHAP controller key'),
+                "gw_group": Param(str, "NVMeoF gateway group", True, None),
+                "server_address": Param(str, "NVMeoF gateway address", True, None),
+            },
+        )
+        @convert_to_model(model.RequestStatus)
+        @handle_nvmeof_error
+        def change_controller_key(
+            self, nqn: str, host_nqn: str, dhchap_controller_key: str,
+            gw_group: Optional[str] = None, server_address: Optional[str] = None
+        ):
+            return NVMeoFClient(
+                gw_group=gw_group,
+                server_address=server_address
+            ).stub.change_host_key(
+                NVMeoFClient.pb2.change_host_key_req(subsystem_nqn=nqn,
+                                                     host_nqn=host_nqn,
+                                                     dhchap_key="-",
+                                                     dhchap_ctrlr_key=dhchap_controller_key)
             )
 
         @empty_response
@@ -1369,9 +1417,48 @@ else:
             ).stub.change_host_key(
                 NVMeoFClient.pb2.change_host_key_req(subsystem_nqn=nqn,
                                                      host_nqn=host_nqn,
-                                                     dhchap_key=None)
+                                                     dhchap_key=None,
+                                                     dhchap_ctrlr_key="-")
             )
 
+        @empty_response
+        @NvmeofCLICommand("nvmeof host del_controller_key", model.RequestStatus)
+        @EndpointDoc(
+            "Delete host DH-HMAC-CHAP controller key",
+            parameters={
+                "nqn": Param(str, "NVMeoF subsystem NQN"),
+                "host_nqn": Param(str, 'NVMeoF host NQN.'),
+                "gw_group": Param(str, "NVMeoF gateway group", True, None),
+                "server_address": Param(str, "NVMeoF gateway address", True, None),
+            },
+        )
+        @convert_to_model(model.RequestStatus)
+        @handle_nvmeof_error
+        def del_controller_key(
+            self, nqn: str, host_nqn: str, gw_group: Optional[str] = None,
+            server_address: Optional[str] = None
+        ):
+            return NVMeoFClient(
+                gw_group=gw_group,
+                server_address=server_address
+            ).stub.change_host_key(
+                NVMeoFClient.pb2.change_host_key_req(subsystem_nqn=nqn,
+                                                     host_nqn=host_nqn,
+                                                     dhchap_key="-",
+                                                     dhchap_ctrlr_key=None)
+            )
+
+    def _update_connections(connection_list_resp):
+        conns = hosts_info_resp.get('connections')
+        if not conns:
+            conns = []
+        for con in conns:
+            orig = con.get("dhchap_controller_origin")
+            if orig:
+                con["dhchap_controller_origin"] = _get_dhchap_controller_key_origin_string(
+                    orig)
+        return connection_list_resp
+
     @APIRouter("/nvmeof/subsystem/{nqn}/connection", Scope.NVME_OF)
     @APIDoc("NVMe-oF Subsystem Connection Management API", "NVMe-oF Subsystem Connection")
     class NVMeoFConnection(RESTController):
@@ -1385,7 +1472,7 @@ else:
                 "server_address": Param(str, "NVMeoF gateway address", True, None),
             },
         )
-        @convert_to_model(model.ConnectionList)
+        @convert_to_model(model.ConnectionList, finalize=_update_connections)
         @handle_nvmeof_error
         def list(self, nqn: Optional[str] = None,
                  gw_group: Optional[str] = None, server_address: Optional[str] = None):
index 04b0551d21b3775e613892fcd0af5d237be2d6f1..c4ea09d8ee4265c96b8d668d234b3fc3fc3aa6d3 100644 (file)
@@ -97,6 +97,7 @@ class SubsystemStatus(NamedTuple):
 
 
 class Connection(NamedTuple):
+    nqn: str
     traddr: str
     trsvcid: int
     trtype: str
@@ -106,6 +107,7 @@ class Connection(NamedTuple):
     controller_id: int
     use_psk: Optional[bool]
     use_dhchap: Optional[bool]
+    dhchap_controller_origin: Optional[str]
     subsystem: Optional[str]
     disconnected_due_to_keepalive_timeout: Optional[bool]
 
@@ -201,6 +203,7 @@ class Host(NamedTuple):
     nqn: str
     use_psk: Optional[bool]
     use_dhchap: Optional[bool]
+    dhchap_controller_origin: Optional[str]
     disconnected_due_to_keepalive_timeout: Annotated[Optional[bool], CliFlags.DROP]
 
 
index 5e1fc41fb3ae3b512953ea433be4714317b2f24b..2caf3b4fd8f8a4e2e4e2a75cb8a83b02798404cd 100755 (executable)
@@ -13176,6 +13176,8 @@ paths:
           application/json:
             schema:
               properties:
+                dhchap_controller_key:
+                  type: string
                 dhchap_key:
                   type: string
                 gw_group: