Repository: red-hat-storage/cephci
Pull request #4721: qos tests-cases for combained bandwidth parameters for bandwidth control
Author: login: Harishacharya-redhat
Labels: name: nfs-ganesha
name: 8.0
description: Squid Automation
name: 8.1
description: Ceph 8.1 feature automation
Created: 2025-04-24T09:13:24Z | Merged: 2025-04-30T06:21:57Z

qos tests-cases for combained bandwidth parameters for bandwidth control

logs: http://magna002.ceph.redhat.com/ceph-qe-logs/hacharya/qos_combined_bw/logs/

logs after changes: http://magna002.ceph.redhat.com/ceph-qe-logs/hacharya/qos_combined_bw/after_comments/logs




Diff:
diff --git a/cli/ceph/nfs/cluster/qos.py b/cli/ceph/nfs/cluster/qos.py
index 4674b1e1e98..97f838f077d 100644
--- a/cli/ceph/nfs/cluster/qos.py
+++ b/cli/ceph/nfs/cluster/qos.py
@@ -96,7 +96,7 @@ def _build_per_share_params(
         read_bw: str,
     ) -> list:
         if combined_bw:
-            return ["--max_export_combined_bw %s" % combined_bw]
+            return ["--combined-rw-bw-ctrl --max_export_combined_bw %s" % combined_bw]
         if write_bw and read_bw:
             return [
                 "--max_export_write_bw %s" % write_bw,
@@ -113,7 +113,7 @@ def _build_client_params(
         read_bw: str,
     ) -> list:
         if combined_bw:
-            return ["--max_client_combined_bw %s" % combined_bw]
+            return ["--combined-rw-bw-ctrl --max_client_combined_bw %s" % combined_bw]
         if write_bw and read_bw:
             return [
                 "--max_client_write_bw %s" % write_bw,
diff --git a/cli/ceph/nfs/export/qos.py b/cli/ceph/nfs/export/qos.py
index 4a69fc727d8..dab657b78b3 100644
--- a/cli/ceph/nfs/export/qos.py
+++ b/cli/ceph/nfs/export/qos.py
@@ -73,7 +73,7 @@ def _build_share_params(
         read_bw: str,
     ) -> list:
         if combined_bw:
-            return ["--max_export_combined_bw %s" % combined_bw]
+            return ["--combined-rw-bw-ctrl --max_export_combined_bw %s" % combined_bw]
         if write_bw and read_bw:
             return [
                 "--max_export_write_bw %s" % write_bw,
@@ -90,7 +90,7 @@ def _build_client_params(
         read_bw: str,
     ) -> list:
         if combined_bw:
-            return ["--max_client_combined_bw %s" % combined_bw]
+            return ["--combined-rw-bw-ctrl --max_client_combined_bw %s" % combined_bw]
         if write_bw and read_bw:
             return [
                 "--max_client_write_bw %s" % write_bw,
diff --git a/suites/squid/nfs/tier0-nfs-ganesha.yaml b/suites/squid/nfs/tier0-nfs-ganesha.yaml
index 31a914225d7..deebc840290 100644
--- a/suites/squid/nfs/tier0-nfs-ganesha.yaml
+++ b/suites/squid/nfs/tier0-nfs-ganesha.yaml
@@ -131,7 +131,7 @@ tests:
       desc: Configure the RGW,RBD client system
       destroy-cluster: false
       module: test_client.py
-      name: configure clients
+      name: configure client
 
   - test:
       name: Nfs Ganesha File Lock
@@ -403,47 +403,76 @@ tests:
         qos_type: PerShare
         operation: restart
 
-
   - test:
-      name: Qos enablement PerShare on export level with nfs service with dynamic update
+      name: Qos enablement PerShare-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos Pershare enablement on export level dynamic update
-      polarion-id: CEPH-83615833
+      desc: Verify qos PerShare-combined_bw value enablement on export level
+      polarion-id: CEPH-83616913
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_export_combined_bw: 8MB
         qos_type: PerShare
-        operation: dynamic_update
+        operation: restart
 
   - test:
-      name: Qos enablement PerShare_PerClient on export level with nfs service with dynamic update
+      name: Qos enablement PerShare_PerClient-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos PerShare_PerClient enablement on export level dynamic update
-      polarion-id: CEPH-83615834
+      desc: Verify qos PerShare_PerClient-combined_bw value enablement on export level
+      polarion-id: CEPH-83616914
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_client_combined_bw: 100MB
+            max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_client_combined_bw: 8MB
+            max_export_combined_bw: 8MB
         qos_type: PerShare_PerClient
-        operation: dynamic_update
+        operation: restart
+
+  - test:
+      name: Qos PerShare-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
+      desc: Verify qos PerShare-combined_bw enablement on cluster level
+      polarion-id: CEPH-83616910
+      abort-on-fail: false
+      config:
+        cephfs_volume : cephfs
+        cluster_name : cephfs-nfs
+        max_export_combined_bw: 8MB
+        qos_type : PerShare
+        operation : restart
+
+  - test:
+      name: Qos PerClient-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
+      desc: Verify qos PerClient-combined_bw enablement on cluster level
+      polarion-id: CEPH-83616911
+      abort-on-fail: false
+      config:
+        cephfs_volume: cephfs
+        cluster_name: cephfs-nfs
+        max_client_combined_bw: 8MB
+        qos_type: PerClient
+        operation: restart
+
+  - test:
+      name: Qos PerShare_PerClient-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
+      desc: Verify qos PerShare_PerClient-combined_bw enablement on cluster level
+      polarion-id: CEPH-83616912
+      abort-on-fail: false
+      config:
+        cephfs_volume: cephfs
+        cluster_name: cephfs-nfs
+        max_export_combined_bw: 8MB
+        max_client_combined_bw: 8MB
+        qos_type: PerShare_PerClient
+        operation: restart
diff --git a/tests/nfs/test_nfs_qos_on_cluster_level_enablement.py b/tests/nfs/test_nfs_qos_on_cluster_level_enablement.py
index 5280378e705..d00a3102010 100644
--- a/tests/nfs/test_nfs_qos_on_cluster_level_enablement.py
+++ b/tests/nfs/test_nfs_qos_on_cluster_level_enablement.py
@@ -17,31 +17,69 @@ def capture_copy_details(client, nfs_mount, file_name, size="100"):
     :param size: The size of the file to create (default is "100M").
     :return: A tuple containing (stdout, stderr) from the dd command.
     """
+
+    write_speed, read_speed = "", ""
     cmd = "touch {0}/{1}".format(nfs_mount, file_name)
     client.exec_command(
         sudo=True,
         cmd=cmd,
     )
 
-    cmd = "dd if=/dev/urandom of={0}/{1} bs={2}M count=1".format(
+    write_cmd = "dd if=/dev/urandom of={0}/{1} bs={2}M count=1".format(
         nfs_mount, file_name, size
     )
-    data = client.exec_command(sudo=True, cmd=cmd)
+    write_results = client.exec_command(sudo=True, cmd=write_cmd)[1]
 
     if (
-        re.search(r"(\d+\.\d+ MB/s)$", data[1])
-        or re.findall(r"(\d+ MB/s)$", data[1])[0]
+        re.search(r"(\d+\.\d+ MB/s)$", write_results)
+        or re.findall(r"(\d+ MB/s)$", write_results)[0]
     ):
-        speed = (
-            re.findall(r"(\d+\.\d+ MB/s)$", data[1])[0]
-            if re.search(r"(\d+\.\d+ MB/s)$", data[1])[0]
-            else re.findall(r"(\d+ MB/s)$", data[1])[0]
+        write_speed = (
+            re.findall(r"(\d+\.\d+ MB/s)$", write_results)[0]
+            if re.search(r"(\d+\.\d+ MB/s)$", write_results)
+            else re.findall(r"(\d+ MB/s)$", write_results)[0]
         )
         log.info("File created successfully on {0}".format(client.hostname))
-        return speed
+        log.info("write speed is {0}".format(write_speed))
+
+    # dropping cache
+    drop_cache_cmd = "echo 3 > /proc/sys/vm/drop_caches"
+    client.exec_command(
+        sudo=True,
+        cmd=drop_cache_cmd,
+    )
+    log.info("Cache dropped successfully")
+
+    read_cmd = "dd if={0}/{1} of=/dev/urandom".format(nfs_mount, file_name)
+    read_results = client.exec_command(sudo=True, cmd=read_cmd)[1]
+
+    if (
+        re.search(r"(\d+\.\d+ MB/s)$", read_results)
+        or re.findall(r"(\d+ MB/s)$", read_results)[0]
+    ):
+        read_speed = (
+            re.findall(r"(\d+\.\d+ MB/s)$", read_results)[0]
+            if re.search(r"(\d+\.\d+ MB/s)$", read_results)
+            else re.findall(r"(\d+ MB/s)$", read_results)[0]
+        )
+        log.info("read speed is {0}".format(read_speed))
+
+    rm_cmd = "rm -rf {0}/{1}".format(nfs_mount, file_name)
+    client.exec_command(
+        sudo=True,
+        cmd=rm_cmd,
+    )
+
+    if write_speed and read_speed:
+        log.info(
+            'Read and write speed captured successfully on {0} "write_speed": {1}, "read_speed": {2}'.format(
+                client.hostname, write_speed, read_speed
+            ),
+        )
+        return {"write_speed": write_speed, "read_speed": read_speed}
     else:
         raise OperationFailedError(
-            "Failed to run dd command on {0} : {1}".format(client.hostname, data)
+            "Failed to capture read/write speed on {0}".format(client.hostname)
         )
 
 
@@ -82,28 +120,58 @@ def enable_disable_qos_for_cluster(
     try:
         if enable_flag:
             if qos_type == "PerShare":
-                ceph_cluster_nfs_obj.qos.enable_per_share(
-                    qos_type=qos_type,
-                    cluster_id=cluster_name,
-                    max_export_read_bw=qos_parameters.get("max_export_read_bw"),
-                    max_export_write_bw=qos_parameters.get("max_export_write_bw"),
-                )
+                if "max_export_combined_bw" in qos_parameters:
+                    ceph_cluster_nfs_obj.qos.enable_per_share(
+                        qos_type=qos_type,
+                        cluster_id=cluster_name,
+                        max_export_combined_bw=qos_parameters.get(
+                            "max_export_combined_bw"
+                        ),
+                    )
+                else:
+                    ceph_cluster_nfs_obj.qos.enable_per_share(
+                        qos_type=qos_type,
+                        cluster_id=cluster_name,
+                        max_export_read_bw=qos_parameters.get("max_export_read_bw"),
+                        max_export_write_bw=qos_parameters.get("max_export_write_bw"),
+                    )
             elif qos_type == "PerClient":
-                ceph_cluster_nfs_obj.qos.enable_per_client(
-                    qos_type=qos_type,
-                    cluster_id=cluster_name,
-                    max_client_read_bw=qos_parameters.get("max_client_read_bw"),
-                    max_client_write_bw=qos_parameters.get("max_client_write_bw"),
-                )
+                if "max_client_combined_bw" in qos_parameters:
+                    ceph_cluster_nfs_obj.qos.enable_per_client(
+                        qos_type=qos_type,
+                        cluster_id=cluster_name,
+                        max_client_combined_bw=qos_parameters.get(
+                            "max_client_combined_bw"
+                        ),
+                    )
+                else:
+                    ceph_cluster_nfs_obj.qos.enable_per_client(
+                        qos_type=qos_type,
+                        cluster_id=cluster_name,
+                        max_client_read_bw=qos_parameters.get("max_client_read_bw"),
+                        max_client_write_bw=qos_parameters.get("max_client_write_bw"),
+                    )
             elif qos_type == "PerShare_PerClient":
-                ceph_cluster_nfs_obj.qos.enable_per_share_per_client(
-                    qos_type=qos_type,
-                    cluster_id=cluster_name,
-                    max_export_read_bw=qos_parameters.get("max_export_read_bw"),
-                    max_export_write_bw=qos_parameters.get("max_export_write_bw"),
-                    max_client_read_bw=qos_parameters.get("max_client_read_bw"),
-                    max_client_write_bw=qos_parameters.get("max_client_write_bw"),
-                )
+                if "max_client_combined_bw" in qos_parameters:
+                    ceph_cluster_nfs_obj.qos.enable_per_share_per_client(
+                        qos_type=qos_type,
+                        cluster_id=cluster_name,
+                        max_export_combined_bw=qos_parameters.get(
+                            "max_export_combined_bw"
+                        ),
+                        max_client_combined_bw=qos_parameters.get(
+                            "max_client_combined_bw"
+                        ),
+                    )
+                else:
+                    ceph_cluster_nfs_obj.qos.enable_per_share_per_client(
+                        qos_type=qos_type,
+                        cluster_id=cluster_name,
+                        max_export_read_bw=qos_parameters.get("max_export_read_bw"),
+                        max_export_write_bw=qos_parameters.get("max_export_write_bw"),
+                        max_client_read_bw=qos_parameters.get("max_client_read_bw"),
+                        max_client_write_bw=qos_parameters.get("max_client_write_bw"),
+                    )
         else:
             ceph_cluster_nfs_obj.qos.disable(cluster_id=cluster_name)
 
@@ -175,9 +243,9 @@ def run(ceph_cluster, **kw):
         # Process QoS operations
         enable_disable_qos_for_cluster(
             enable_flag=True,
+            qos_type=qos_type,
             ceph_cluster_nfs_obj=ceph_nfs_client.cluster,
             cluster_name=cluster_name,
-            qos_type=qos_type,
             **{
                 k: config[k]
                 for k in [
@@ -185,6 +253,8 @@ def run(ceph_cluster, **kw):
                     "max_export_read_bw",
                     "max_client_write_bw",
                     "max_client_read_bw",
+                    "max_export_combined_bw",
+                    "max_client_combined_bw",
                 ]
                 if k in config
             },
@@ -224,19 +294,51 @@ def run(ceph_cluster, **kw):
             )
         )
 
-        if float(re.findall(r"\d+", config["max_export_write_bw"])[0]) >= float(
-            re.findall(r"\d+\.\d+", speed)[0]
+        write_speed = speed.get("write_speed")
+        read_speed = speed.get("read_speed")
+
+        max_export_write_bw = config.get("max_export_write_bw")
+        max_export_read_bw = config.get("max_export_read_bw")
+        max_client_write_bw = config.get("max_client_write_bw")
+        max_client_read_bw = config.get("max_client_read_bw")
+        max_export_combined_bw = config.get("max_export_combined_bw")
+        if max_export_combined_bw:
+            max_export_write_bw = max_export_combined_bw
+            max_export_read_bw = max_export_combined_bw
+        max_client_combined_bw = config.get("max_client_combined_bw")
+        if max_client_combined_bw:
+            max_client_write_bw = max_client_combined_bw
+            max_client_read_bw = max_client_combined_bw
+
+        if (
+            (max_export_write_bw is not None and max_export_read_bw is not None)
+            and float(max_export_write_bw.replace("MB", ""))
+            >= float(write_speed.replace(" MB/s", ""))
+            and float(max_export_read_bw.replace("MB", ""))
+            >= float(read_speed.replace(" MB/s", ""))
+        ) or (
+            (max_client_write_bw is not None and max_client_read_bw is not None)
+            and float(max_client_write_bw.replace("MB", ""))
+            >= float(write_speed.replace(" MB/s", ""))
+            and float(max_client_read_bw.replace("MB", ""))
+            >= float(read_speed.replace(" MB/s", ""))
         ):
             log.info(
-                "Test passed: QoS {0} enabled successfully in cluster level".format(
-                    qos_type
+                "Test passed: QoS {0} enabled successfully in export level write speed is {1}"
+                " , max_export_write_bw is {2} and read speed is {3}"
+                " and max_export_read_bw is {4}".format(
+                    qos_type,
+                    write_speed,
+                    max_export_write_bw,
+                    read_speed,
+                    max_export_read_bw,
                 )
             )
         else:
             raise OperationFailedError(
-                "Test failed: QoS {0} enabled successfully in cluster level transfer speed is {1} "
-                "and max_export_write_bw is {2}".format(
-                    qos_type, speed, config["max_export_write_bw"]
+                "Test failed: QoS {0} enabled successfully in export level write speed is {1}"
+                " and read speed is {2} config is {3}".format(
+                    qos_type, write_speed, read_speed, config
                 )
             )
 
diff --git a/tests/nfs/test_nfs_qos_on_export_level_enablement.py b/tests/nfs/test_nfs_qos_on_export_level_enablement.py
index b1def6d0fe5..1c45a090ca7 100644
--- a/tests/nfs/test_nfs_qos_on_export_level_enablement.py
+++ b/tests/nfs/test_nfs_qos_on_export_level_enablement.py
@@ -32,28 +32,58 @@ def enable_disable_qos_for_export(
     try:
         if enable_flag:
             if qos_type == "PerShare":
-                ceph_export_nfs_obj.qos.enable_per_share(
-                    nfs_name=nfs_name,
-                    export=export,
-                    max_export_read_bw=qos_parameters.get("max_export_read_bw"),
-                    max_export_write_bw=qos_parameters.get("max_export_write_bw"),
-                )
+                if "max_export_combined_bw" in qos_parameters:
+                    ceph_export_nfs_obj.qos.enable_per_share(
+                        nfs_name=nfs_name,
+                        export=export,
+                        max_export_combined_bw=qos_parameters.get(
+                            "max_export_combined_bw"
+                        ),
+                    )
+                else:
+                    ceph_export_nfs_obj.qos.enable_per_share(
+                        nfs_name=nfs_name,
+                        export=export,
+                        max_export_read_bw=qos_parameters.get("max_export_read_bw"),
+                        max_export_write_bw=qos_parameters.get("max_export_write_bw"),
+                    )
             elif qos_type == "PerClient":
-                ceph_export_nfs_obj.qos.enable_per_client(
-                    nfs_name=nfs_name,
-                    export=export,
-                    max_client_read_bw=qos_parameters.get("max_client_read_bw"),
-                    max_client_write_bw=qos_parameters.get("max_client_write_bw"),
-                )
+                if "max_client_combined_bw" in qos_parameters:
+                    ceph_export_nfs_obj.qos.enable_per_client(
+                        nfs_name=nfs_name,
+                        export=export,
+                        max_client_combined_bw=qos_parameters.get(
+                            "max_client_combined_bw"
+                        ),
+                    )
+                else:
+                    ceph_export_nfs_obj.qos.enable_per_client(
+                        nfs_name=nfs_name,
+                        export=export,
+                        max_client_read_bw=qos_parameters.get("max_client_read_bw"),
+                        max_client_write_bw=qos_parameters.get("max_client_write_bw"),
+                    )
             elif qos_type == "PerShare_PerClient":
-                ceph_export_nfs_obj.qos.enable_per_share_per_client(
-                    nfs_name=nfs_name,
-                    export=export,
-                    max_export_read_bw=qos_parameters.get("max_export_read_bw"),
-                    max_export_write_bw=qos_parameters.get("max_export_write_bw"),
-                    max_client_read_bw=qos_parameters.get("max_client_read_bw"),
-                    max_client_write_bw=qos_parameters.get("max_client_write_bw"),
-                )
+                if "max_client_combined_bw" in qos_parameters:
+                    ceph_export_nfs_obj.qos.enable_per_share_per_client(
+                        nfs_name=nfs_name,
+                        export=export,
+                        max_export_combined_bw=qos_parameters.get(
+                            "max_export_combined_bw"
+                        ),
+                        max_client_combined_bw=qos_parameters.get(
+                            "max_client_combined_bw"
+                        ),
+                    )
+                else:
+                    ceph_export_nfs_obj.qos.enable_per_share_per_client(
+                        nfs_name=nfs_name,
+                        export=export,
+                        max_export_read_bw=qos_parameters.get("max_export_read_bw"),
+                        max_export_write_bw=qos_parameters.get("max_export_write_bw"),
+                        max_client_read_bw=qos_parameters.get("max_client_read_bw"),
+                        max_client_write_bw=qos_parameters.get("max_client_write_bw"),
+                    )
         else:
             ceph_export_nfs_obj.qos.disable(cluster_id=nfs_name, export=export)
         qos_data = ceph_export_nfs_obj.qos.get(nfs_name=nfs_name, export=export)
@@ -70,28 +100,6 @@ def enable_disable_qos_for_export(
         )
 
 
-def verify_bw_speed(client, nfs_mount, qos_type, export_bw):
-    speed = capture_copy_details(client, nfs_mount, "sample.txt")
-    log.info(
-        "Transfer speed is {0} for QoS {1} enabled in export level".format(
-            speed, qos_type
-        )
-    )
-    if float(re.findall(r"\d+", export_bw["max_export_write_bw"])[0]) >= float(
-        re.findall(r"\d+\.\d+", speed)[0]
-    ):
-        log.info(
-            "Test passed: QoS {0} enabled successfully in export level transfer speed is {1}"
-            " and max_export_write_bw is {2}".format(
-                qos_type, speed, export_bw["max_export_write_bw"]
-            )
-        )
-    else:
-        raise OperationFailedError(
-            "Test failed: QoS {0} enabled successfully in export level".format(qos_type)
-        )
-
-
 def run(ceph_cluster, **kw):
     """Verify QoS operations on NFS cluster"""
     config = kw.get("config")
@@ -144,9 +152,9 @@ def run(ceph_cluster, **kw):
         # Enable QoS with parameters
         enable_disable_qos_for_cluster(
             enable_flag=True,
+            qos_type=qos_type,
             ceph_cluster_nfs_obj=ceph_nfs_client.cluster,
             cluster_name=cluster_name,
-            qos_type=qos_type,
             **{
                 k: cluster_bw[k]
                 for k in [
@@ -154,6 +162,8 @@ def run(ceph_cluster, **kw):
                     "max_export_read_bw",
                     "max_client_write_bw",
                     "max_client_read_bw",
+                    "max_export_combined_bw",
+                    "max_client_combined_bw",
                 ]
                 if k in cluster_bw
             },
@@ -174,6 +184,8 @@ def run(ceph_cluster, **kw):
                     "max_export_read_bw",
                     "max_client_write_bw",
                     "max_client_read_bw",
+                    "max_export_combined_bw",
+                    "max_client_combined_bw",
                 ]
                 if k in export_bw
             },
@@ -204,57 +216,94 @@ def run(ceph_cluster, **kw):
             export_data_after_restart = json.loads(export_data_after_restart)
             log.info("export_data_after_restart: {0}".format(export_data_after_restart))
 
-            if float(
-                re.findall(
-                    r"\d+.\d+",
-                    export_data_after_restart["qos_block"]["max_export_write_bw"],
-                )[0]
-            ) == float(re.findall(r"\d+", export_bw["max_export_write_bw"])[0]):
-                log.info(
-                    "Qos data for {0} for export persists even after the nfs cluster restarted".format(
-                        qos_type
+            if export_data_after_restart["qos_block"].get("max_export_write_bw"):
+                if float(
+                    re.findall(
+                        r"\d+\.\d+",
+                        export_data_after_restart["qos_block"]["max_export_write_bw"],
+                    )[0]
+                ) == float(re.findall(r"\d+", export_bw["max_export_write_bw"])[0]):
+                    log.info(
+                        "Qos data for {0} for export persists even after the nfs cluster restarted".format(
+                            qos_type
+                        )
+                    )
+            elif export_data_after_restart["qos_block"].get("max_export_combined_bw"):
+                if float(
+                    re.findall(
+                        r"\d+\.\d+",
+                        export_data_after_restart["qos_block"][
+                            "max_export_combined_bw"
+                        ],
+                    )[0]
+                ) == float(re.findall(r"\d+", export_bw["max_export_combined_bw"])[0]):
+                    log.info(
+                        "Qos data for {0} for export persists even after the nfs cluster restarted".format(
+                            qos_type
+                        )
                     )
-                )
             else:
                 raise OperationFailedError(
-                    "Qos data for {0} did not persists after the nfs cluster restarted".format(
+                    "Qos data for {0} did not persist after the nfs cluster restarted".format(
                         qos_type
                     )
                 )
 
-        verify_bw_speed(client, nfs_mount, qos_type, export_bw)
+        speed = capture_copy_details(client, nfs_mount, "sample.txt")
+        log.info(
+            "Transfer speed is {0} for QoS {1} enabled in export level".format(
+                speed, qos_type
+            )
+        )
 
-        if operation == "dynamic_update":
-            # Update the qos parameters
-            export_bw = {
-                "max_client_read_bw": "6MB",
-                "max_client_write_bw": "6MB",
-                "max_export_read_bw": "6MB",
-                "max_export_write_bw": "6MB",
-            }
+        write_speed = speed.get("write_speed")
+        read_speed = speed.get("read_speed")
 
-            enable_disable_qos_for_export(
-                enable_flag=True,
-                ceph_export_nfs_obj=ceph_nfs_client.export,
-                cluster_name=cluster_name,
-                qos_type=qos_type,
-                nfs_name=nfs_name,
-                export=nfs_export,
-                **{
-                    k: export_bw[k]
-                    for k in [
-                        "max_export_write_bw",
-                        "max_export_read_bw",
-                        "max_client_write_bw",
-                        "max_client_read_bw",
-                    ]
-                    if k in export_bw
-                },
-            )
+        max_export_write_bw = export_bw.get("max_export_write_bw")
+        max_export_read_bw = export_bw.get("max_export_read_bw")
+        max_client_write_bw = export_bw.get("max_client_write_bw")
+        max_client_read_bw = export_bw.get("max_client_read_bw")
+        max_export_combined_bw = export_bw.get("max_export_combined_bw")
+        if max_export_combined_bw:
+            max_export_write_bw = max_export_combined_bw
+            max_export_read_bw = max_export_combined_bw
+        max_client_combined_bw = export_bw.get("max_client_combined_bw")
+        if max_client_combined_bw:
+            max_client_write_bw = max_client_combined_bw
+            max_client_read_bw = max_client_combined_bw
 
-        verify_bw_speed(client, nfs_mount, qos_type, export_bw)
+        if (
+            (max_export_write_bw is not None and max_export_read_bw is not None)
+            and float(max_export_write_bw.replace("MB", ""))
+            >= float(write_speed.replace(" MB/s", ""))
+            and float(max_export_read_bw.replace("MB", ""))
+            >= float(read_speed.replace(" MB/s", ""))
+        ) or (
+            (max_client_write_bw is not None and max_client_read_bw is not None)
+            and float(max_client_write_bw.replace("MB", ""))
+            >= float(write_speed.replace(" MB/s", ""))
+            and float(max_client_read_bw.replace("MB", ""))
+            >= float(read_speed.replace(" MB/s", ""))
+        ):
+            log.info(
+                "Test passed: QoS {0} enabled successfully in export level write speed is {1}"
+                " , max_export_write_bw is {2} and read speed is {3}"
+                " and max_export_read_bw is {4}".format(
+                    qos_type,
+                    write_speed,
+                    max_export_write_bw,
+                    read_speed,
+                    max_export_read_bw,
+                )
+            )
+        else:
+            raise OperationFailedError(
+                "Test failed: QoS {0} enabled successfully in export level write speed is {1}"
+                " and read speed is {2} config is {3}".format(
+                    qos_type, write_speed, read_speed, cluster_bw
+                )
+            )
 
-        # Disable QoS for export
         enable_disable_qos_for_export(
             enable_flag=False,
             nfs_name=nfs_name,


Reviews:
user: login: msainiRedhat
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T21:21:30Z
user: login: msainiRedhat
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T21:22:43Z
user: login: msainiRedhat
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T14:13:54Z
user: login: vdas-redhat
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T06:21:19Z

Review comments:
diff_hunk: @@ -403,47 +403,76 @@ tests:
         qos_type: PerShare
         operation: restart
 
-
   - test:
-      name: Qos enablement PerShare on export level with nfs service with dynamic update
+      name: Qos enablement PerShare-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos Pershare enablement on export level dynamic update
-      polarion-id: CEPH-83615833
+      desc: Verify qos PerShare-combined_bw value enablement on export level
+      polarion-id: CEPH-83616913
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_export_combined_bw: 8MB
         qos_type: PerShare
-        operation: dynamic_update
+        operation: restart
 
   - test:
-      name: Qos enablement PerShare_PerClient on export level with nfs service with dynamic update
+      name: Qos enablement PerShare_PerClient-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos PerShare_PerClient enablement on export level dynamic update
-      polarion-id: CEPH-83615834
+      desc: Verify qos PerShare_PerClient-combined_bw value enablement on export level
+      polarion-id: CEPH-83616914
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_client_combined_bw: 100MB
+            max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_client_combined_bw: 8MB
+            max_export_combined_bw: 8MB
         qos_type: PerShare_PerClient
-        operation: dynamic_update
+        operation: restart
+
+  - test:
+      name: Qos PerShare-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
path: suites/squid/nfs/tier0-nfs-ganesha.yaml
user: login: msainiRedhat
body: For combined bandwidth control, we also need to check the read operations are under limits. Modify it for all combined control cases

For example, for write --> dd if=/dev/urandom of=<nfs_mount>
For read --> dd if=<nfs_mount> of=/dev/urandom
created_at: 2025-04-24T21:19:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -403,47 +403,76 @@ tests:
         qos_type: PerShare
         operation: restart
 
-
   - test:
-      name: Qos enablement PerShare on export level with nfs service with dynamic update
+      name: Qos enablement PerShare-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos Pershare enablement on export level dynamic update
-      polarion-id: CEPH-83615833
+      desc: Verify qos PerShare-combined_bw value enablement on export level
+      polarion-id: CEPH-83616913
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_export_combined_bw: 8MB
         qos_type: PerShare
-        operation: dynamic_update
+        operation: restart
 
   - test:
-      name: Qos enablement PerShare_PerClient on export level with nfs service with dynamic update
+      name: Qos enablement PerShare_PerClient-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos PerShare_PerClient enablement on export level dynamic update
-      polarion-id: CEPH-83615834
+      desc: Verify qos PerShare_PerClient-combined_bw value enablement on export level
+      polarion-id: CEPH-83616914
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_client_combined_bw: 100MB
+            max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_client_combined_bw: 8MB
+            max_export_combined_bw: 8MB
         qos_type: PerShare_PerClient
-        operation: dynamic_update
+        operation: restart
+
+  - test:
+      name: Qos PerShare-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
+      desc: Verify qos PerShare-combined_bw enablement on cluster level
+      polarion-id: CEPH-83616910
+      abort-on-fail: false
+      config:
+        cephfs_volume : cephfs
+        cluster_name : cephfs-nfs
+        max_export_combined_bw: 8MB
+        qos_type : PerShare
+        operation : restart
+
+  - test:
+      name: Qos PerClient-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
+      desc: Verify qos PerClient-combined_bw enablement on cluster level
+      polarion-id: CEPH-83616911
+      abort-on-fail: false
+      config:
+        cephfs_volume: cephfs
+        cluster_name: cephfs-nfs
+        max_client_combined_bw: 8MB
+        qos_type: PerClient
+        operation: restart
+
+  - test:
+      name: Qos PerShare_PerClient-combined_bw enablement on Cluster level with nfs with service restart
path: suites/squid/nfs/tier0-nfs-ganesha.yaml
user: login: msainiRedhat
body: "combined-rw-bw-ctrl " should be set to once only..

Incorrect - ceph nfs cluster qos enable bandwidth_control cephfs-nfs PerShare_PerClient --combined-rw-bw-ctrl --max_export_combined_bw 8MB --combined-rw-bw-ctrl --max_client_combined_bw 8MB

Correct -- ceph nfs cluster qos enable bandwidth_control cephfs-nfs PerShare_PerClient --combined-rw-bw-ctrl --max_export_combined_bw 8MB  --max_client_combined_bw 8MB
created_at: 2025-04-24T21:20:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -403,47 +403,76 @@ tests:
         qos_type: PerShare
         operation: restart
 
-
   - test:
-      name: Qos enablement PerShare on export level with nfs service with dynamic update
+      name: Qos enablement PerShare-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos Pershare enablement on export level dynamic update
-      polarion-id: CEPH-83615833
+      desc: Verify qos PerShare-combined_bw value enablement on export level
+      polarion-id: CEPH-83616913
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_export_combined_bw: 8MB
         qos_type: PerShare
-        operation: dynamic_update
+        operation: restart
 
   - test:
-      name: Qos enablement PerShare_PerClient on export level with nfs service with dynamic update
+      name: Qos enablement PerShare_PerClient-combined_bw value for export level with nfs service with restart
       module: test_nfs_qos_on_export_level_enablement.py
-      desc: Verify qos PerShare_PerClient enablement on export level dynamic update
-      polarion-id: CEPH-83615834
+      desc: Verify qos PerShare_PerClient-combined_bw value enablement on export level
+      polarion-id: CEPH-83616914
       abort-on-fail: false
       config:
         cephfs_volume: cephfs
         cluster_name: cephfs-nfs
         cluster_bw:
-          - max_export_write_bw: 100MB
-            max_export_read_bw: 100MB
-            max_client_write_bw: 100MB
-            max_client_read_bw: 100MB
+          - max_client_combined_bw: 100MB
+            max_export_combined_bw: 100MB
         export_bw:
-          - max_export_write_bw: 8MB
-            max_export_read_bw: 8MB
-            max_client_write_bw: 8MB
-            max_client_read_bw: 8MB
+          - max_client_combined_bw: 8MB
+            max_export_combined_bw: 8MB
         qos_type: PerShare_PerClient
-        operation: dynamic_update
+        operation: restart
+
+  - test:
+      name: Qos PerShare-combined_bw enablement on Cluster level with nfs with service restart
+      module: test_nfs_qos_on_cluster_level_enablement.py
path: suites/squid/nfs/tier0-nfs-ganesha.yaml
user: login: msainiRedhat
body: Eg : https://bugzilla.redhat.com/show_bug.cgi?id=2350596#c0
created_at: 2025-04-24T21:22:43Z
author_association: CONTRIBUTOR

PR comments:
user: login: Harishacharya-redhat
created_at: 2025-04-29T09:53:13Z
body: Observed a product bug while testing the PR comments. BZ https://bugzilla.redhat.com/show_bug.cgi?id=2362861
author_association: CONTRIBUTOR
user: login: Harishacharya-redhat
created_at: 2025-04-29T13:40:18Z
body: @msainiRedhat Here's a logs after changes: http://magna002.ceph.redhat.com/ceph-qe-logs/hacharya/qos_combined_bw/after_comments/logs
author_association: CONTRIBUTOR