]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/mgr: send MDS commands through cephfs client
authorPatrick Donnelly <pdonnell@ibm.com>
Wed, 5 Feb 2025 16:22:08 +0000 (11:22 -0500)
committerPatrick Donnelly <pdonnell@ibm.com>
Mon, 17 Mar 2025 19:43:22 +0000 (15:43 -0400)
To avoid linking to the CephFS client statically, use the dynamically-linked
`cephfs` module to send commands to the MDS.

Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
(cherry picked from commit f7329814c917f290df54807d16a31b3108223b9f)

src/pybind/mgr/mgr_module.py

index 60c9ce06ca998ccc05a864d4e39c4ca6dd9449c8..38acb514c6febe1578d3d4c5afc89e9ae8753b48 100644 (file)
@@ -9,6 +9,7 @@ if TYPE_CHECKING:
     else:
         from typing_extensions import Literal
 
+import cephfs
 import inspect
 import logging
 import errno
@@ -1067,6 +1068,8 @@ class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
         # Keep a librados instance for those that need it.
         self._rados: Optional[rados.Rados] = None
 
+        self._cephfs: Optional[cephfs.LibCephFS] = None
+
         # this does not change over the lifetime of an active mgr
         self._mgr_ips: Optional[str] = None
 
@@ -1794,6 +1797,18 @@ class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
 
         return (rc, stdout, stderr)
 
+    class _CommandResultWrapper:
+        def __init__(self, module: 'MgrModule', tag: Optional[str], result: CommandResult):
+            if tag is None:
+                tag = ""
+            self.module = module
+            self.tag = tag
+            self.result = result
+
+        def complete(self, r: int, outb: bytes, outs: bytes) -> None:
+            self.result.complete(r, outb.decode('utf-8'), outs.decode('utf-8'))
+            self.module._ceph_notify_all("command", self.tag)
+
     def send_command(
             self,
             result: CommandResult,
@@ -1827,7 +1842,13 @@ class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
         :param bool one_shot: a keyword-only param to make the command abort
             with EPIPE when the target resets or refuses to reconnect
         """
-        self._ceph_send_command(result, svc_type, svc_id, command, tag, inbuf, one_shot=one_shot)
+
+        if svc_type == "mds":
+            wrapped_result = self._CommandResultWrapper(self, tag, result)
+            self.log.info(f"do mds_command: mds.{svc_id} {command}")
+            self.cephfs.mds_command2(wrapped_result, svc_id, command, inbuf, one_shot=one_shot)
+        else:
+            self._ceph_send_command(result, svc_type, svc_id, command, tag, inbuf, one_shot=one_shot)
 
     def tool_exec(
         self,
@@ -2267,6 +2288,19 @@ class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
         self._ceph_register_client(None, self._rados.get_addrs(), False)
         return self._rados
 
+    @property
+    def cephfs(self) -> cephfs.LibCephFS:
+        """
+        An (unmounted) cephfs instance to be shared by any classes within this
+        mgr module that want one.
+        """
+        if self._cephfs:
+            return self._cephfs
+
+        self._cephfs = cephfs.LibCephFS(rados_inst=self.rados)
+        self._cephfs.init()
+        return self._cephfs
+
     @staticmethod
     def can_run() -> Tuple[bool, str]:
         """