From: Shweta Bhosale Date: Mon, 10 Mar 2025 08:10:34 +0000 (+0530) Subject: mgr/nfs: Add cluster level qos status to export get qos command X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8acf8ce64a05501bbb9268a9b90c4f66c0fe326e;p=ceph.git mgr/nfs: Add cluster level qos status to export get qos command fixes: https://tracker.ceph.com/issues/69458 Signed-off-by: Shweta Bhosale --- diff --git a/src/pybind/mgr/nfs/export.py b/src/pybind/mgr/nfs/export.py index 41e0d029e2b0..5961eba06f52 100644 --- a/src/pybind/mgr/nfs/export.py +++ b/src/pybind/mgr/nfs/export.py @@ -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) diff --git a/src/pybind/mgr/nfs/export_utils.py b/src/pybind/mgr/nfs/export_utils.py index f5c45c3f4433..b5c31b5e931a 100644 --- a/src/pybind/mgr/nfs/export_utils.py +++ b/src/pybind/mgr/nfs/export_utils.py @@ -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) diff --git a/src/pybind/mgr/nfs/tests/test_nfs.py b/src/pybind/mgr/nfs/tests/test_nfs.py index ed38cbc56585..97fb151d8192 100644 --- a/src/pybind/mgr/nfs/tests/test_nfs.py +++ b/src/pybind/mgr/nfs/tests/test_nfs.py @@ -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