]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/nfs: Add cluster level qos status to export get qos command
authorShweta Bhosale <Shweta.Bhosale1@ibm.com>
Mon, 10 Mar 2025 08:10:34 +0000 (13:40 +0530)
committerShweta Bhosale <Shweta.Bhosale1@ibm.com>
Mon, 27 Apr 2026 12:49:14 +0000 (18:19 +0530)
fixes: https://tracker.ceph.com/issues/69458
Signed-off-by: Shweta Bhosale <Shweta.Bhosale1@ibm.com>
src/pybind/mgr/nfs/export.py
src/pybind/mgr/nfs/export_utils.py
src/pybind/mgr/nfs/tests/test_nfs.py

index 41e0d029e2b02a3f32fbfde55b93278184a1c55e..5961eba06f524917c1bb0c0690978a1b49f77fec 100644 (file)
@@ -28,8 +28,12 @@ from .ganesha_conf import (
     GaneshaConfParser,
     RGWFSAL,
     format_block)
-from .qos_conf import QOS, QOSBandwidthControl, QOSOpsControl
-from .export_utils import export_qos_bw_checks, export_dict_qos_bw_ops_checks, export_qos_ops_checks
+from .qos_conf import QOS, QOSBandwidthControl, QOSOpsControl, QOSParams
+from .export_utils import (
+    export_qos_bw_checks,
+    export_dict_qos_bw_ops_checks,
+    export_qos_ops_checks,
+    get_cluster_qos_config)
 from .exception import NFSException, NFSInvalidOperation, FSNotFound, NFSObjectNotFound
 from .utils import (
     EXPORT_PREFIX,
@@ -939,8 +943,21 @@ class ExportMgr:
 
     def get_export_qos(self, cluster_id: str, pseudo_path: str, ret_bw_in_bytes: bool = False) -> Dict[str, int]:
         try:
+            clust_qos_obj = get_cluster_qos_config(cluster_id, self.mgr)
+            clust_qos_conf = {}
+            if clust_qos_obj:
+                clust_qos_conf[f'cluster_{QOSParams.enable_qos.value}'] = clust_qos_obj.enable_qos
+                if clust_qos_obj.bw_obj:
+                    clust_qos_conf[f'cluster_{QOSParams.enable_bw_ctrl.value}'] = clust_qos_obj.bw_obj.enable_bw_ctrl
+                if clust_qos_obj.ops_obj:
+                    clust_qos_conf[f'cluster_{QOSParams.enable_iops_ctrl.value}'] = clust_qos_obj.ops_obj.enable_iops_ctrl
+
             export_obj = self.get_export_obj(cluster_id, pseudo_path)
-            return export_obj.qos_block.to_dict(ret_bw_in_bytes) if export_obj.qos_block else {}
+            if export_obj.qos_block:
+                qos_block = export_obj.qos_block.to_dict(ret_bw_in_bytes)
+                qos_block.update(clust_qos_conf)
+                return qos_block
+            return {}
         except Exception as e:
             log.exception(f"Failed to get QOS configuration for {pseudo_path} of {cluster_id}")
             raise ErrorResponse.wrap(e)
index f5c45c3f44334158523918027d7dd362879902ab..b5c31b5e931ab170b06c40600f4ab666d0a3210e 100644 (file)
@@ -1,7 +1,7 @@
-from typing import Any
+from typing import Any, Optional
 
 from .cluster import NFSCluster
-from .qos_conf import QOSType, QOSParams, QOSBandwidthControl, QOSOpsControl
+from .qos_conf import QOSType, QOSParams, QOSBandwidthControl, QOSOpsControl, QOS
 
 
 def export_dict_bw_checks(cluster_id: str,
@@ -109,3 +109,8 @@ def export_qos_ops_checks(cluster_id: str,
         if clust_qos_obj.qos_type == QOSType.PerClient:
             raise Exception(f'Export-level QoS IOPS control cannot be enabled if the QoS type at the cluster {cluster_id} level is set to PerClient.')
         ops_obj.qos_ops_checks(clust_qos_obj.qos_type)
+
+
+def get_cluster_qos_config(cluster_id: str, mgr_obj: Any) -> Optional[QOS]:
+    nfs_clust_obj = NFSCluster(mgr_obj)
+    return nfs_clust_obj.get_cluster_qos_config(cluster_id)
index ed38cbc56585fb2623b86240560006415c8f1834..97fb151d8192013b42aa221f6f76ba98e7c7573f 100644 (file)
@@ -1540,7 +1540,7 @@ EXPORT {
             assert str(e) == 'To configure bandwidth control for export, you must first enable bandwidth control at the cluster level for foo.'
         bw_obj = QOSBandwidthControl(True, clust_combined_bw_ctrl, **clust_params)
         cluster.enable_cluster_qos_bw(self.cluster_id, qos_type, bw_obj)
-
+        clust_qos_conf = {'cluster_enable_qos': True, 'cluster_enable_bw_control': True, 'cluster_enable_iops_control': False}
         # set export qos
         try:
             bw_obj = QOSBandwidthControl(True, export_combined_bw_ctrl, **export_params)
@@ -1558,10 +1558,12 @@ EXPORT {
         expected_out = {"enable_bw_control": True, "enable_qos": True, "combined_rw_bw_control": export_combined_bw_ctrl}
         for key in export_params:
             expected_out[QOSParams[key].value] = bytes_to_human(with_units_to_int(export_params[key]))
+        expected_out.update(clust_qos_conf)
         assert out == expected_out
         export_mgr.disable_export_qos_bw(self.cluster_id, '/cephfs_a/')
         out = export_mgr.get_export_qos(self.cluster_id, '/cephfs_a/')
-        assert out == {"enable_bw_control": False, "enable_qos": False, "combined_rw_bw_control": False}
+        clust_qos_conf.update({"enable_bw_control": False, "enable_qos": False, "combined_rw_bw_control": False})
+        assert out == clust_qos_conf
 
 
     @pytest.mark.parametrize("qos_type, clust_combined_bw_ctrl, clust_params", [
@@ -1631,7 +1633,7 @@ EXPORT {
             assert str(e) == 'To configure IOPS control for export, you must first enable IOPS control at the cluster level foo.'
         ops_obj = QOSOpsControl(True, **clust_params)
         cluster.enable_cluster_qos_ops(self.cluster_id, qos_type, ops_obj)
-
+        clust_qos_conf = {'cluster_enable_qos': True, 'cluster_enable_bw_control': False, 'cluster_enable_iops_control': True}
         # set export qos
         try:
             ops_obj = QOSOpsControl(True, **export_params)
@@ -1646,10 +1648,12 @@ EXPORT {
         expected_out = {"enable_iops_control": True, "enable_qos": True}
         for key in export_params:
             expected_out[QOSParams[key].value] = export_params[key]
+        expected_out.update(clust_qos_conf)
         assert out == expected_out
         export_mgr.disable_export_qos_ops(self.cluster_id, '/cephfs_a/')
         out = export_mgr.get_export_qos(self.cluster_id, '/cephfs_a/')
-        assert out == {"enable_iops_control": False, "enable_qos": False}
+        clust_qos_conf.update({"enable_iops_control": False, "enable_qos": False})
+        assert out == clust_qos_conf
 
     @pytest.mark.parametrize("qos_type, clust_params", [
         (QOSType['PerShare'], {'max_export_iops': 10000}),
@@ -1744,6 +1748,7 @@ EXPORT {
             export_mgr.enable_export_qos_bw(self.cluster_id, '/cephfs_a/', bw_obj)
             ops_obj = QOSOpsControl(True, **export_ops_params)
             export_mgr.enable_export_qos_ops(self.cluster_id, '/cephfs_a/', ops_obj)
+            clust_qos_conf = {'cluster_enable_qos': True, 'cluster_enable_bw_control': True, 'cluster_enable_iops_control': True}
         except Exception:
             req = QOS_REQ_BW_PARAMS['combined_bw_disabled'][qos_type.name]
             if sorted(export_bw_params.keys()) != sorted(req):
@@ -1763,16 +1768,19 @@ EXPORT {
             ops_out[QOSParams[key].value] = export_ops_params[key]
         expected_out.update(bw_out)
         expected_out.update(ops_out)
+        expected_out.update(clust_qos_conf)
         assert out == expected_out
         # disable bandwidth control of export
         export_mgr.disable_export_qos_bw(self.cluster_id, '/cephfs_a/')
         out = export_mgr.get_export_qos(self.cluster_id, '/cephfs_a/')
         ops_out.update({"enable_bw_control": False, "enable_qos": True, "combined_rw_bw_control": False, "enable_iops_control": True})
+        ops_out.update(clust_qos_conf)
         assert out == ops_out
         # disable ops control of export
         export_mgr.disable_export_qos_ops(self.cluster_id, '/cephfs_a/')
         out = export_mgr.get_export_qos(self.cluster_id, '/cephfs_a/')
-        assert out == {"enable_bw_control": False, "enable_qos": False, "combined_rw_bw_control": False, "enable_iops_control": False}
+        clust_qos_conf.update({"enable_bw_control": False, "enable_qos": False, "combined_rw_bw_control": False, "enable_iops_control": False})
+        assert out == clust_qos_conf
 
     @pytest.mark.parametrize("qos_type, clust_bw_params, clust_ops_params", [
         # positive TCs