From 9b0af94f307fde64fedc9980a2f060fad480af80 Mon Sep 17 00:00:00 2001 From: Harishacharya-redhat Date: Wed, 8 Jan 2025 13:51:52 +0530 Subject: [PATCH 01/50] adding earmark feature tests Signed-off-by: Harishacharya-redhat --- suites/squid/nfs/tier1-nfs-ganesha.yaml | 45 +++++++++ tests/nfs/test_earmark_feature.py | 126 ++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 tests/nfs/test_earmark_feature.py diff --git a/suites/squid/nfs/tier1-nfs-ganesha.yaml b/suites/squid/nfs/tier1-nfs-ganesha.yaml index b4359fb9033..26635c1f6b4 100644 --- a/suites/squid/nfs/tier1-nfs-ganesha.yaml +++ b/suites/squid/nfs/tier1-nfs-ganesha.yaml @@ -143,6 +143,51 @@ tests: nfs_version: 4.1 clients: 1 + - test: + name: Delete the old earmark and set the "nfs". Create NFS export out of it + desc: Delete the old earmark and set the "nfs". Create NFS export out of it + module: test_earmark_feature.py + # polarion-id: + config: + cephfs_volume: cephfs + subvolume_group: nfsgroup + earmark: smb + operation: rename_earmark + + - test: + name: creating volume and setting earmark + desc: creating volume and setting earmark + module: test_earmark_feature.py + # polarion-id: + config: + cephfs_volume: cephfs + subvolume_group: nfsgroup + earmark: nfs + operation: verify_earmark + + - test: + name: Override the earmark and try to create nfs export. It should fail + desc: Override the earmark and try to create nfs export. It should fail + module: test_earmark_feature.py + # polarion-id: + config: + cephfs_volume: cephfs + subvolume_group: nfsgroup + earmark: nfs + operation: override_earmark + + - test: + name: Set the earmark as "smb" and try to use the same subvolume for nfs export + desc: Set the earmark as "smb" and try to use the same subvolume for nfs export + module: test_earmark_feature.py + # polarion-id: + config: + cephfs_volume: cephfs + subvolume_group: nfsgroup + nfs_version: 4.1 + earmark: smb + operation: wrong_earmark + - test: name: Verify owner of a symbolic link and the owner of the target file can be different users module: nfs_verify_symbolic_links_users.py diff --git a/tests/nfs/test_earmark_feature.py b/tests/nfs/test_earmark_feature.py new file mode 100644 index 00000000000..dcee0635929 --- /dev/null +++ b/tests/nfs/test_earmark_feature.py @@ -0,0 +1,126 @@ +from time import sleep + +from cli.ceph.ceph import Ceph +from tests.cephfs.cephfs_utilsV1 import FsUtils +from tests.nfs.nfs_operations import check_nfs_daemons_removed +from tests.nfs.nfs_test_multiple_filesystem_exports import create_nfs_export +from utility.log import Log +log = Log(__name__) + + +def run(ceph_cluster, **kw): + """Verify readdir ops + Args: + **kw: Key/value pairs of configuration information to be used in the test. + """ + fs_util = FsUtils(ceph_cluster) + config = kw.get("config") + nfs_nodes = ceph_cluster.get_nodes("nfs") + clients = ceph_cluster.get_nodes("client") + nfs_node = nfs_nodes[0] + operation = config.get("operation") + fs_name = config.get("cephfs_volume", "ceph_fs") + nfs_name = "cephfs-nfs" + nfs_export = "/export" + nfs_server_name = nfs_node.hostname + subvolume_group = "ganeshagroup" + subvolume_name = "subvolume" + earmark = config.get("earmark") + + fs_util.create_subvolumegroup(client=clients[0], + vol_name=fs_name, + group_name=subvolume_group) + fs_util.create_subvolume(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, validate=True, + group_name=subvolume_group) + fs_util.set_subvolume_earmark(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + group_name=subvolume_group, + earmark=earmark) + + subvolume_earmark = fs_util.get_subvolume_earmark(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + group_name=subvolume_group) + + if operation == "verify_earmark": + if earmark not in subvolume_earmark: + log.error(f"earmark \"{earmark}\" not found on subvolume {subvolume_name}") + # raise OperationFailedError(f"earmark \"{earmark}\" not found on subvolume {subvolume_name}") + return 1 + + log.info(f"earmark \"{earmark}\" found on subvolume {subvolume_name}") + return 0 + + if operation == "rename_earmark": + earmark2 = "nfs" + fs_util.remove_subvolume_earmark(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + group_name=subvolume_group) + + fs_util.set_subvolume_earmark(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + group_name=subvolume_group, + earmark=earmark2) + + try: + # Setup nfs cluster + Ceph(clients[0]).nfs.cluster.create( + name=nfs_name, nfs_server=nfs_server_name, ha=False, vip=None + ) + sleep(3) + + if operation == "override_earmark": + earmark2 = "smb" + fs_util.set_subvolume_earmark(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + group_name=subvolume_group, + earmark=earmark2) + + log.info(f"subvolume earmark is {subvolume_earmark}") + + sub_volume_path = fs_util.get_subvolume_info(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + group_name=subvolume_group).get("path") + + try: + create_nfs_export(clients[0], + fs_name, + nfs_name, + nfs_export, + sub_volume_path, '') + log.info(f"nfs export {nfs_export} has been created for subvolume path {nfs_export}") + + Ceph(clients[0]).nfs.export.delete(nfs_name, nfs_export) + log.info(f"nfs export {nfs_export} has been deleted for subvolume path {nfs_export}") + return 0 + + except Exception as e: + # The export should fail earmark has already been set by smb + if ("earmark has already been set by smb" in e.args[0] and operation in + ["override_earmark", "wrong_earmark"]): + log.info(f"expected, failed earmark has already been set by smb {e}") + return 0 + else: + log.error(f"Unexpected {e}") + + except Exception as e: + log.error(f"unable to create nfs cluster {nfs_name} with error {e}") + return 1 + finally: + log.info("Cleaning up in progress") + fs_util.remove_subvolume(client=clients[0], + vol_name=fs_name, + subvol_name=subvolume_name, + validate=True, + group_name=subvolume_group) + log.info(f"Removed the subvolume {subvolume_name} from group {subvolume_group}") + Ceph(clients[0]).nfs.cluster.delete(nfs_name) + sleep(30) + check_nfs_daemons_removed(clients[0]) From 3c57d46f0d4f0aeb87c9d903af5fcad58eb8816d Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Sun, 17 Nov 2024 20:03:56 +0530 Subject: [PATCH 02/50] Switch test parallel module to use process pool. This commits switches to use ProcessPoolExecutor to allow parallel test modules to spins threads inside their own process. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- tests/parallel/test_parallel.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/parallel/test_parallel.py b/tests/parallel/test_parallel.py index 22c4b40823f..3cd445b0a29 100644 --- a/tests/parallel/test_parallel.py +++ b/tests/parallel/test_parallel.py @@ -35,8 +35,16 @@ def run(**kwargs): def run(**kwargs): results = {} parallel_tests = kwargs["parallel"] - - with parallel() as p: + max_time = kwargs.get("config", {}).get("max_time", None) + wait_till_complete = kwargs.get("config", {}).get("wait_till_complete", True) + cancel_pending = kwargs.get("config", {}).get("cancel_pending", False) + + with parallel( + thread_pool=False, + timeout=max_time, + shutdown_wait=wait_till_complete, + shutdown_cancel_pending=cancel_pending, + ) as p: for test in parallel_tests: p.spawn(execute, test, kwargs, results) sleep(1) From 7e5a24b96d6c8f2fbb2e114c8c2a231e6c825f74 Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Sun, 17 Nov 2024 18:18:48 +0530 Subject: [PATCH 03/50] Remove gevent from requirements This commit helps us to decouple from gevent module and removes the package installation. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- setup.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.py b/setup.py index 2f4a95d37c6..133b973794f 100644 --- a/setup.py +++ b/setup.py @@ -17,8 +17,6 @@ "apache-libcloud>=3.3.0", "cryptography", "docopt", - "gevent", - "greenlet", "htmllistparse", "ibm-cloud-sdk-core==3.15.0 ; python_version<'3.7'", "ibm-cloud-sdk-core ; python_version>='3.7'", From 7f44c88064479fcfaf621f6bf2e2eb0112beb2c7 Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Sun, 17 Nov 2024 18:17:28 +0530 Subject: [PATCH 04/50] Remove gvent sleep As the next steps, removing methods used from gevent. Sleep in between threads was used and this commit uses time sleep now instead of gevent's method. This helps to move out of gevent. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- ceph/utils.py | 3 +-- utility/psi_volume_cleanup.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ceph/utils.py b/ceph/utils.py index 49489178234..ce60ca4e6a1 100644 --- a/ceph/utils.py +++ b/ceph/utils.py @@ -5,11 +5,10 @@ import time import traceback from json import loads -from time import mktime +from time import mktime, sleep import requests import yaml -from gevent import sleep from htmllistparse import fetch_listing from libcloud.common.exceptions import BaseHTTPError from libcloud.compute.providers import get_driver diff --git a/utility/psi_volume_cleanup.py b/utility/psi_volume_cleanup.py index f27471fbbdc..b7b112d91b7 100755 --- a/utility/psi_volume_cleanup.py +++ b/utility/psi_volume_cleanup.py @@ -1,10 +1,8 @@ #!/usr/bin/env python3 """Utility to remove orphaned volumes.""" -from gevent import monkey, sleep - -monkey.patch_all() import sys from datetime import datetime, timedelta +from time import sleep import yaml from docopt import docopt From 7f70f7b8ece81c6d0fa402663702d0e80a8f401c Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Sun, 17 Nov 2024 17:53:04 +0530 Subject: [PATCH 05/50] RHCEPHQE-16740 - Move to concurrent.futures In this PR, parallel is refactored to use concurrent.futures instead of gvent. This allows us to use threads or processes. Along with the introduction of timeouts at the parallel phase. It also allows to avoid the dependency on gvent. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- ceph/parallel.py | 221 ++++++++++++++++++++++++----------------------- run.py | 7 +- 2 files changed, 112 insertions(+), 116 deletions(-) diff --git a/ceph/parallel.py b/ceph/parallel.py index b3249d64b6c..7e6cb10fe55 100644 --- a/ceph/parallel.py +++ b/ceph/parallel.py @@ -1,121 +1,122 @@ -import sys - -import gevent.pool -import gevent.queue - -from utility.log import Log - -log = Log(__name__) - - -class ExceptionHolder(object): - def __init__(self, exc_info): - self.exc_info = exc_info - - -def capture_traceback(func, *args, **kwargs): - """ - Utility function to capture tracebacks of any exception func - raises. - """ - try: - return func(*args, **kwargs) - except Exception: - return ExceptionHolder(sys.exc_info()) - - -def resurrect_traceback(exc): - if isinstance(exc, ExceptionHolder): - exc_info = exc.exc_info - elif isinstance(exc, BaseException): - exc_info = (type(exc), exc, None) - else: - return - - raise exc_info[0](exc_info[1]).with_traceback(exc_info[2]) - - -class parallel(object): - """ - This class is a context manager for running functions in parallel. - - You add functions to be run with the spawn method:: - - with parallel() as p: - for foo in bar: - p.spawn(quux, foo, baz=True) - - You can iterate over the results (which are in arbitrary order):: - - with parallel() as p: - for foo in bar: - p.spawn(quux, foo, baz=True) - for result in p: - print result - - If one of the spawned functions throws an exception, it will be thrown - when iterating over the results, or when the with block ends. - - At the end of the with block, the main thread waits until all - spawned functions have completed, or, if one exited with an exception, - kills the rest and raises the exception. - """ - - def __init__(self): - self.group = gevent.pool.Group() - self.results = gevent.queue.Queue() - self.count = 0 - self.any_spawned = False - self.iteration_stopped = False - - def spawn(self, func, *args, **kwargs): - self.count += 1 - self.any_spawned = True - greenlet = self.group.spawn(capture_traceback, func, *args, **kwargs) - greenlet.link(self._finish) +# -*- code: utf-8 -*- +""" +This module provides a context manager for running methods concurrently. + +For backward compatability, spawn method is leveraged however one can also +choose to move submit. Likewise, thread pool executor is the default executor. + +Timeout is an inherited feature provided by concurrent futures. Additionally, +one wait for all the threads/process to complete even when on thread or process +encounters an exception. This is useful when multiple test modules are +executing different test scenarios. + +When a test module controls the threads then it can forcefully terminate all +threads when an exception is encountered. + +Changelog: + Version 1.0 used gevent module for parallel method execution. + Version 2.0 uses concurrent.futures module instead of gevent. + +You add functions to be run with the spawn method:: + + with parallel() as p: + for foo in bar: + p.spawn(quux, foo, baz=True) + +You can iterate over the results (which are in arbitrary order):: + + with parallel() as p: + for foo in bar: + p.spawn(quux, foo, baz=True) + for result in p: + print result + +In version 2, you can choose whether to use threads or processes by + + with parallel(thread_pool=False, timeout=10) as p: + _r = [p.spawn(quux, x) for name in names] + +If one of the spawned functions throws an exception, it will be thrown +when iterating over the results, or when the with block ends. + +At the end of the with block, the main thread waits until all +spawned functions have completed, or, if one exited with an exception, +kills the rest and raises the exception. +""" +import logging +from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed + +logger = logging.getLogger(__name__) + + +class parallel: + """This class is a context manager for concurrent method execution.""" + + def __init__( + self, + thread_pool=True, + timeout=None, + shutdown_wait=True, + shutdown_cancel_pending=False, + ): + """Object initialization method. + + Args: + thread_pool (bool) Whether to use threads or processes. + timeout (int | float) Maximum allowed time. + shutdown_wait (bool) If disabled, it would not wait for executing + threads/process to complete. + shutdown_cancel_pending (bool) If enabled, it would cancel pending tasks. + """ + self._executor = ThreadPoolExecutor() if thread_pool else ProcessPoolExecutor() + self._timeout = timeout + self._shutdown_wait = shutdown_wait + self._cancel_pending = shutdown_cancel_pending + self._futures = list() + self._results = list() + + def spawn(self, fun, *args, **kwargs): + """Triggers the first class method. + + Args: + func: Function to be executed. + args: A list of variables to be passed to the function. + kwargs A dictionary of named variables. + + Returns: + None + """ + _future = self._executor.submit(fun, *args, **kwargs) + self._futures.append(_future) def __enter__(self): return self - def __exit__(self, type_, value, traceback): - self.group.join() + def __exit__(self, exc_type, exc_value, trackback): + _exceptions = [] + exception_count = 0 + + for _f in as_completed(self._futures, timeout=self._timeout): + try: + self._results.append(_f.result()) + except Exception as e: + logger.exception(e) + _exceptions.append(e) + exception_count += 1 + + if exception_count > 0 and not self._shutdown_wait: + # At this point we are ignoring results + self._executor.shutdown(wait=False, cancel_futures=self._cancel_pending) + raise _exceptions[0] - if value is not None: - return False + if len(_exceptions) > 0: + raise _exceptions[0] - try: - # raises if any greenlets exited with an exception - for result in self: - log.debug("result is %s", repr(result)) - pass - except Exception: - # Emit message here because traceback gets stomped when we re-raise - log.exception("Exception in parallel execution") - raise - return True + return False if exception_count == 0 else True def __iter__(self): return self def __next__(self): - if not self.any_spawned or self.iteration_stopped: - raise StopIteration() - result = self.results.get() - - try: - resurrect_traceback(result) - except StopIteration: - self.iteration_stopped = True - raise - - return result - - def _finish(self, greenlet): - if greenlet.successful(): - self.results.put(greenlet.value) - else: - self.results.put(greenlet.exception) - - self.count -= 1 - if self.count <= 0: - self.results.put(StopIteration()) + for r in self._results: + yield r diff --git a/run.py b/run.py index 13ea2c2c277..366fab9d032 100755 --- a/run.py +++ b/run.py @@ -1,9 +1,4 @@ -#!/usr/bin/env python - -# Allow parallelized behavior of gevent. It has to be the first line. -from gevent import monkey - -monkey.patch_all() +#!/usr/bin/env python3 import datetime import importlib From ab668197712d6e53b0b67398d188222d27c6bdb8 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Tue, 3 Dec 2024 13:23:08 +0530 Subject: [PATCH 06/50] Implemented review comments Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat From c095e2c48cb814ce99d7633725c8fec832ecffd5 Mon Sep 17 00:00:00 2001 From: Amarnath K Date: Fri, 29 Nov 2024 11:38:37 +0530 Subject: [PATCH 07/50] Refactoring log format and Enhancing parallel executions Signed-off-by: Amarnath K Signed-off-by: Harishacharya-redhat --- run.py | 35 +++-- tests/parallel/test_parallel.py | 254 +++++++++++++++++++++----------- utility/log.py | 196 +++++++----------------- 3 files changed, 241 insertions(+), 244 deletions(-) diff --git a/run.py b/run.py index 366fab9d032..4eb2914d605 100755 --- a/run.py +++ b/run.py @@ -822,17 +822,30 @@ def fetch_test_details(var) -> dict: # Initialize the cluster with the expected rhcs_version ceph_cluster_dict[cluster_name].rhcs_version = _rhcs_version if mod_file_name not in skip_tc_list or do_not_skip_test: - rc = test_mod.run( - ceph_cluster=ceph_cluster_dict[cluster_name], - ceph_nodes=ceph_cluster_dict[cluster_name], - config=config, - parallel=parallel, - test_data=ceph_test_data, - ceph_cluster_dict=ceph_cluster_dict, - clients=clients, - run_config=run_config, - ) - + if parallel: + parallel_tcs, rc = test_mod.run( + ceph_cluster=ceph_cluster_dict[cluster_name], + ceph_nodes=ceph_cluster_dict[cluster_name], + config=config, + parallel=parallel, + test_data=ceph_test_data, + ceph_cluster_dict=ceph_cluster_dict, + clients=clients, + run_config=run_config, + tc=tc, + ) + tcs.extend(parallel_tcs) + else: + rc = test_mod.run( + ceph_cluster=ceph_cluster_dict[cluster_name], + ceph_nodes=ceph_cluster_dict[cluster_name], + config=config, + parallel=parallel, + test_data=ceph_test_data, + ceph_cluster_dict=ceph_cluster_dict, + clients=clients, + run_config=run_config, + ) else: rc = -1 diff --git a/tests/parallel/test_parallel.py b/tests/parallel/test_parallel.py index 3cd445b0a29..49b483973ec 100644 --- a/tests/parallel/test_parallel.py +++ b/tests/parallel/test_parallel.py @@ -1,104 +1,184 @@ -""" -The purpose of this test module is to run the test in a suite parallely - -Syntax: - - tests: - -test: - name: Parallel run - module: test_parallel.py - parallel: - - test: - ... - - test: - ... - desc: Running tests parallely - -Requirement parameters - ceph_nodes: The list of node participating in the RHCS environment. - config: The test configuration - parallel: Consist of test which needs to be executed parallely - -Entry Point: - def run(**kwargs): -""" - +import copy +import datetime +import glob import importlib +import logging import os +import string +from multiprocessing import Manager +from random import random from time import sleep +from ceph.ceph import CommandFailed from ceph.parallel import parallel -from utility.log import Log +from utility.log import LOG_FORMAT, Log +from utility.utils import magna_url -log = Log(__name__) +parallel_log = Log(__name__) +polarion_default_url = ( + "https://polarion.engineering.redhat.com/polarion/#/project/CEPH/workitem?id=" +) -def run(**kwargs): - results = {} - parallel_tests = kwargs["parallel"] - max_time = kwargs.get("config", {}).get("max_time", None) - wait_till_complete = kwargs.get("config", {}).get("wait_till_complete", True) - cancel_pending = kwargs.get("config", {}).get("cancel_pending", False) - - with parallel( - thread_pool=False, - timeout=max_time, - shutdown_wait=wait_till_complete, - shutdown_cancel_pending=cancel_pending, - ) as p: - for test in parallel_tests: - p.spawn(execute, test, kwargs, results) - sleep(1) - - test_rc = 0 - for key, value in results.items(): - log.info(f"{key} test result is {'PASS' if value == 0 else 'FAILED'}") - if value != 0: - test_rc = value - - return test_rc - - -def execute(test, args, results: dict): - """ - Executes the test under parallel in module named 'Parallel run' parallely. +class MultiModuleFilter(logging.Filter): + """Custom filter to log only messages from specific modules.""" - It involves the following steps - - Importing of test module based on test - - Running the test module + def __init__(self, module_names): + super().__init__() + self.module_names = module_names + + def filter(self, record): + """Filter logs to include only those from the specified modules.""" + return any(module_name in record.module for module_name in self.module_names) + + +# Add a filter for `test_parallel` to parallel_log +module_filter = MultiModuleFilter(["test_parallel", "run"]) + +# Ensure the filter is applied to all handlers of parallel_log +for handler in parallel_log.logger.handlers: + handler.addFilter(module_filter) - Args: - test: The test module which needs to be executed - cluster: Ceph cluster participating in the test. - config: The key/value pairs passed by the tester. - results: results in dictionary - Returns: - int: non-zero on failure, zero on pass +def run(**kwargs): + """Main function to run parallel tests.""" + # Use a Manager dictionary for shared state across processes + with Manager() as manager: + results = manager.dict() + parallel_tests = kwargs["parallel"] + parallel_tcs = manager.list() + max_time = kwargs.get("config", {}).get("max_time", None) + wait_till_complete = kwargs.get("config", {}).get("wait_till_complete", True) + cancel_pending = kwargs.get("config", {}).get("cancel_pending", False) + parallel_log.info(kwargs) + + with parallel( + thread_pool=False, + timeout=max_time, + shutdown_wait=wait_till_complete, + shutdown_cancel_pending=cancel_pending, + ) as p: + for test in parallel_tests: + p.spawn(execute, test, kwargs, results, parallel_tcs) + sleep(1) # Avoid overloading processes + + # Convert results to a regular dictionary to inspect + results = dict(results) + parallel_log.info(f"Final test results: {results}") + parallel_log.info(f"Parallel test cases: {parallel_tcs}") + test_rc = 0 + + for key, value in results.items(): + parallel_log.info( + f"{key} test result is {'PASS' if value == 0 else 'FAILED'}" + ) + if value != 0: + test_rc = value + + return list(parallel_tcs), test_rc + + +def execute(test, args, results, parallel_tcs): """ + Executes the test in parallel. + Args: + test: The test module to execute. + args: Arguments passed to the test. + results: Shared dictionary to store test results. + parallel_tcs: Shared list to store test case details. + """ test = test.get("test") - if "clusters" in test: - log.info("Its a multisite setup") - cluster = test["clusters"].get( - "ceph-rgw1", test["clusters"][list(test["clusters"].keys())[0]] - ) - config = cluster["config"] + test_name = test.get("name", "unknown_test") + module_name = os.path.splitext(test.get("module"))[0] + run_dir = args["run_config"]["log_dir"] + url_base = ( + magna_url + run_dir.split("/")[-1] + if "/ceph/cephci-jenkins" in run_dir + else run_dir + ) + if not args.get("tc"): + raise CommandFailed(f"Test case is not passed as part of args : {args}") + tc = copy.deepcopy(args["tc"]) + if test.get("polarion-id"): + tc["polarion-id-link"] = f"{polarion_default_url}/{test.get('polarion-id')}" + test_name = test_name.replace(" ", "_") + _log_matches = glob.glob(os.path.join(run_dir, f"{test_name}.*")) + if _log_matches: + _prefix = "".join(random.choices(string.ascii_letters + string.digits, k=4)) + file_name = f"{test_name}-{_prefix}" else: - config = test.get("config", dict()) - config.update(args["config"]) - file_name = test.get("module") - mod_file_name = os.path.splitext(file_name)[0] - test_mod = importlib.import_module(mod_file_name) - testcase_name = test.get("name", "Test Case Unknown") - - rc = test_mod.run( - ceph_cluster=args["ceph_cluster"], - ceph_nodes=args["ceph_nodes"], - config=config, - test_data=args["test_data"], - ceph_cluster_dict=args["ceph_cluster_dict"], - clients=args["clients"], + file_name = f"{test_name}" + log_url = f"{url_base}/{file_name}.log" + log_file = os.path.join(run_dir, f"{file_name}.log") + parallel_log.info(f"Log File location for test {test_name}: {log_url}") + + # Configure logger for this test + test_logger = Log(module_name) + for handler in logging.getLogger().handlers[:]: + logging.getLogger().removeHandler(handler) + logging.basicConfig( + handlers=[logging.FileHandler(log_file)], level=logging.INFO, format=LOG_FORMAT ) + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + console_handler.setFormatter(logging.Formatter(test_logger.log_format)) + if not any( + isinstance(h, logging.StreamHandler) for h in test_logger.logger.handlers + ): + test_logger.logger.addHandler(console_handler) + err_logfile = os.path.join(run_dir, f"{file_name}.err") + error_handler = logging.FileHandler(err_logfile) + error_handler.setFormatter(logging.Formatter(LOG_FORMAT)) + error_handler.setLevel(logging.ERROR) # This ensures only errors are logged + test_logger.logger.addHandler(error_handler) + + test_logger.info(f"Starting test: {test_name}") + try: + # Import and execute the test module + mod_file_name = os.path.splitext(test.get("module"))[0] + test_mod = importlib.import_module(mod_file_name) + run_config = { + "log_dir": run_dir, + "run_id": args["run_config"]["run_id"], + } + start = datetime.datetime.now() + + # Merging configurations safely + test_config = args.get("config", {}).copy() + test_config.update(test.get("config", {})) + tc["name"] = test.get("name") + tc["desc"] = test.get("desc") + tc["log-link"] = log_url + rc = test_mod.run( + ceph_cluster=args.get("ceph_cluster"), + ceph_nodes=args.get("ceph_nodes"), + config=test_config, + parallel=args.get("parallel"), + test_data=args.get("test_data"), + ceph_cluster_dict=args.get("ceph_cluster_dict"), + clients=args.get("clients"), + run_config=run_config, + ) + elapsed = datetime.datetime.now() - start + tc["duration"] = str(elapsed) + results[test_name] = rc - file_string = f"{testcase_name}" - results.update({file_string: rc}) + test_logger.info( + f"Test {test_name} completed with result: {'PASS' if rc == 0 else 'FAILED'}" + ) + tc["status"] = "Pass" if rc == 0 else "Failed" + if rc == -1: + tc["status"] = "Skipped" + + parallel_tcs.append(tc) + except KeyError as e: + parallel_log.error(f"Missing required argument: {e}") + raise + except Exception as e: + test_logger.error(f"Test {test_name} failed with error: {e}") + results[test_name] = 1 + finally: + # Reset root logger configuration to avoid conflicts + for handler in logging.getLogger().handlers[:]: + logging.getLogger().removeHandler(handler) diff --git a/utility/log.py b/utility/log.py index 902c304ce27..8e4de8d2581 100644 --- a/utility/log.py +++ b/utility/log.py @@ -1,66 +1,57 @@ -# -*- coding: utf-8 -*- -""" -Implements CephCI logging interface. - -In this module, we implement a singleton LOG object that can be used by all components -of CephCI. It supports the below logging methods - - - error - - warning - - info - - debug - -Along with the above, it provides support for pushing events to - - - local file - - logstash server - -Initial Log format will be 'datetime - level - message' -later updating log format with 'datetime - level -filename:line_number - message' -""" -import inspect import logging import logging.handlers import os -from copy import deepcopy -from typing import Any, Dict +from typing import Dict from .config import TestMetaData -LOG_FORMAT = "%(asctime)s (%(name)s) [%(levelname)s] - %(message)s" +LOG_FORMAT = ( + "%(asctime)s - %(name)s - %(modname)s:%(lineno)d - [%(levelname)s] - %(message)s" +) + magna_server = "http://magna002.ceph.redhat.com" magna_url = f"{magna_server}/cephci-jenkins/" -class LoggerInitializationException: +class LoggerInitializationException(Exception): + """Exception raised for logger initialization errors.""" + pass -class Log: +class Log(logging.Logger): """CephCI Logger object to help streamline logging.""" def __init__(self, name=None) -> None: - """Initializes the logging mechanism based on the inputs provided.""" - self._logger = logging.getLogger("cephci") + """ + Initializes the logging mechanism. + Args: + name (str): Logger name (module name or other identifier). + """ + super().__init__(name) logging.basicConfig(format=LOG_FORMAT, level=logging.INFO) + # self._logger = logging.getLogger(name) + self._logger = logging.getLogger("cephci") + # Set logger name if name: - self._logger.name = f"cephci.{name}" + self.name = f"cephci.{name}" - self._log_level = self._logger.getEffectiveLevel() + # Additional attributes + self._log_level = self.getEffectiveLevel() self._log_dir = None - self._log_errors = [] self.log_format = LOG_FORMAT + self._log_errors = [] + self.info = self._logger.info + self.debug = self._logger.debug + self.warning = self._logger.warning + self.error = self._logger.error + self.exception = self._logger.exception @property def rp_logger(self): return self.config.get("rp_logger") - @property - def logger(self) -> logging.Logger: - """Return the logger.""" - return self._logger - @property def log_dir(self) -> str: """Return the absolute path to the logging folder.""" @@ -71,6 +62,11 @@ def log_level(self) -> int: """Return the logging level.""" return self._log_level + @property + def logger(self) -> logging.Logger: + """Return the logger.""" + return self._logger + @property def config(self) -> Dict: """Return the CephCI run configuration.""" @@ -94,113 +90,17 @@ def metadata(self) -> Dict: } ) - def _log(self, level: str, message: Any, *args, **kwargs) -> None: + def log_error(self, message: str) -> None: """ - Log the given message using the provided level along with the metadata. - updating LOG_FORMAT with filename:line_number - message - ex: 2022-11-15 11:37:00,346 - DEBUG - cephci.utility.log.py:227 - Completed log configuration - - *Args: - level (str): Log level - message (Any): The message that needs to be logged - **kwargs: - metadata (dict): Extra information to be appended to logstash - - Returns: - None. - """ - log = { - "info": self._logger.info, - "debug": self._logger.debug, - "warning": self._logger.warning, - "error": self._logger.error, - "exception": self._logger.exception, - } - extra = deepcopy(self.metadata) - extra.update(kwargs.get("metadata", {})) - calling_frame = inspect.stack()[2].frame - trace = inspect.getframeinfo(calling_frame) - file_path = trace.filename.split("/") - files = file_path if len(file_path) == 1 else file_path[5:] - extra.update({"LINENUM": trace.lineno, "FILENAME": ".".join(files)}) - log[level]( - f"cephci.{extra['FILENAME']}:{extra['LINENUM']} - {message}", - *args, - extra=extra, - **kwargs, - ) - - def info(self, message: Any, *args, **kwargs) -> None: - """Log with info level the provided message and extra data. + Logs an error and appends it to the internal error tracker. Args: - message (Any): The message to be logged. - args (Any): Dynamic list of supported arguments. - kwargs (Any): Dynamic list of supported keyword arguments. - - Returns: - None - """ - self._log("info", message, *args, **kwargs) - - def debug(self, message: Any, *args, **kwargs) -> None: - """Log with debug level the provided message and extra data. - - Args: - message (str): The message to be logged. - args (Any): Dynamic list of supported arguments. - kwargs (Any): Dynamic list of supported keyword arguments. - - Returns: - None - """ - - self._log("debug", message, *args, **kwargs) - - def warning(self, message: Any, *args, **kwargs) -> None: - """Log with warning level the provided message and extra data. - - Args: - message (Any): The message to be logged. - args (Any): Dynamic list of supported arguments. - kwargs (Any): Dynamic list of supported keyword arguments. - - Returns: - None + message (str): The error message to log and track. """ - self._log("warning", message, *args, **kwargs) - - def error(self, message: Any, *args, **kwargs) -> None: - """Log with error level the provided message and extra data. - - Args: - message (Any): The message to be logged. - args (Any): Dynamic list of supported arguments. - kwargs (Any): Dynamic list of supported keyword arguments. - - Returns: - None - """ - if self.rp_logger: - self.rp_logger.log(message=message, level="ERROR") - - self._log("error", message, *args, **kwargs) self._log_errors.append(message) + self.error(message) - def exception(self, message: Any, *args, **kwargs) -> None: - """Log the given message under exception log level. - - Args: - message (Any): Message or record to be emitted. - args (Any): Dynamic list of supported arguments. - kwargs (Any): Dynamic list of supported keyword arguments. - Returns: - None - """ - kwargs["exc_info"] = kwargs.get("exc_info", True) - self._log("exception", message, *args, **kwargs) - - def configure_logger(self, test_name, run_dir, disable_console_log): + def configure_logger(self, test_name, run_dir, disable_console_log, **kwargs): """ Configures a new FileHandler for the root logger. Args: @@ -218,7 +118,7 @@ def configure_logger(self, test_name, run_dir, disable_console_log): log_format = logging.Formatter(self.log_format) full_log_name = f"{test_name}.log" test_logfile = os.path.join(run_dir, full_log_name) - self.info(f"Test logfile: {test_logfile}") + self._logger.info(f"Test logfile: {test_logfile}") if disable_console_log: self._logger.propagate = False _handler = logging.FileHandler(test_logfile) @@ -236,24 +136,28 @@ def configure_logger(self, test_name, run_dir, disable_console_log): _err_handler.setLevel(logging.ERROR) self._logger.addHandler(_err_handler) + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + console_handler.setFormatter(log_format) + if not any(isinstance(h, logging.StreamHandler) for h in self._logger.handlers): + self._logger.addHandler(console_handler) + url_base = ( magna_url + run_dir.split("/")[-1] if "/ceph/cephci-jenkins" in run_dir else run_dir ) log_url = f"{url_base}/{full_log_name}" - self.debug("Completed log configuration") + self._logger.debug("Completed log configuration") return log_url def close_and_remove_filehandlers(self): """ - Close FileHandlers and then remove them from the loggers handlers list. - Returns: - None + Close FileHandlers and then remove them from the logger's handlers list. """ handlers = self._logger.handlers[:] - for h in handlers: - if isinstance(h, logging.FileHandler): - h.close() - self._logger.removeHandler(h) + for handler in handlers: + if isinstance(handler, logging.FileHandler): + handler.close() + self._logger.removeHandler(handler) From d535ac56e8e7d1ce5f6179083d886ca06bfa4846 Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Fri, 13 Dec 2024 10:24:12 +0530 Subject: [PATCH 08/50] Fix ValueError - formatting field modname The right parameter is module. This commit modifies the log format. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- utility/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/log.py b/utility/log.py index 8e4de8d2581..fb1af66333e 100644 --- a/utility/log.py +++ b/utility/log.py @@ -6,7 +6,7 @@ from .config import TestMetaData LOG_FORMAT = ( - "%(asctime)s - %(name)s - %(modname)s:%(lineno)d - [%(levelname)s] - %(message)s" + "%(asctime)s - %(name)s - %(module)s:%(lineno)d - %(levelname)s - %(message)s" ) magna_server = "http://magna002.ceph.redhat.com" From 29f6bfdfdceef8ad283173170636f6497bf5b175 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Tue, 3 Dec 2024 13:23:08 +0530 Subject: [PATCH 09/50] Implemented review comments Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat From c11b15cf7ada548b8da7226460f045aee74eb208 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Tue, 3 Dec 2024 13:23:08 +0530 Subject: [PATCH 10/50] Implemented review comments Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat From 9239b2f32d996a4c619dbf6cf64cb1f18bed7057 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Tue, 3 Dec 2024 13:23:08 +0530 Subject: [PATCH 11/50] Implemented review comments Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat From 88074e1488a7253eeae194e227dc89a31968d5d6 Mon Sep 17 00:00:00 2001 From: tintumathew10 Date: Fri, 20 Dec 2024 17:28:08 +0530 Subject: [PATCH 12/50] Updating service account psi-ceph-jenkins user to ceph-qe-sa user Signed-off-by: tintumathew10 Signed-off-by: Harishacharya-redhat --- pipeline/rhos_scripts/quota-template.html | 2 +- pipeline/vars/common.groovy | 2 +- pipeline/vars/lib.groovy | 4 ++-- pipeline/vars/upload_results.groovy | 2 +- pipeline/vars/v3.groovy | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pipeline/rhos_scripts/quota-template.html b/pipeline/rhos_scripts/quota-template.html index 4cf6bf312c3..875f2e882c2 100644 --- a/pipeline/rhos_scripts/quota-template.html +++ b/pipeline/rhos_scripts/quota-template.html @@ -69,7 +69,7 @@

Consolidated Quota Usage Summary for Projects

Volume Used in GB <% for (user in quota["User Stats"]) { %> - <% if (user.User == "psi-ceph-jenkins") { continue; } %> + <% if (user.User == "ceph-qe-sa") { continue; } %> <% u_range = user["Instance Count"].intValue() %> <% if (u_range > user_range[0]) { %> <% color = "F1948A" %> diff --git a/pipeline/vars/common.groovy b/pipeline/vars/common.groovy index ef8c3474b42..999b28ca52b 100644 --- a/pipeline/vars/common.groovy +++ b/pipeline/vars/common.groovy @@ -12,7 +12,7 @@ def prepareNode() { */ withCredentials([ usernamePassword( - credentialsId: 'psi-ceph-jenkins', + credentialsId: 'ceph-qe-sa', usernameVariable: 'OSPUSER', passwordVariable: 'OSPCRED' ) diff --git a/pipeline/vars/lib.groovy b/pipeline/vars/lib.groovy index 62c93181ad0..57a70b547bf 100644 --- a/pipeline/vars/lib.groovy +++ b/pipeline/vars/lib.groovy @@ -23,7 +23,7 @@ def prepareNode(def listener=0, def project="ceph-jenkins") { */ withCredentials([ usernamePassword( - credentialsId: 'psi-ceph-jenkins', + credentialsId: 'ceph-qe-sa', usernameVariable: 'OSPUSER', passwordVariable: 'OSPCRED' ) @@ -723,7 +723,7 @@ def uploadTestResults(def sourceDir, def credPreproc, def runProperties) { // Upload test result to polarion using xUnit Xml file withCredentials([ usernamePassword( - credentialsId: 'psi-ceph-jenkins', + credentialsId: 'ceph-qe-sa', usernameVariable: 'OSPUSER', passwordVariable: 'OSPCRED' ) diff --git a/pipeline/vars/upload_results.groovy b/pipeline/vars/upload_results.groovy index 2da8eafe758..9183b338232 100644 --- a/pipeline/vars/upload_results.groovy +++ b/pipeline/vars/upload_results.groovy @@ -67,7 +67,7 @@ def uploadTestResults(def sourceDir, def credPreproc, def runProperties, def sta // Upload test result to polarion using xUnit Xml file withCredentials([ usernamePassword( - credentialsId: 'psi-ceph-jenkins', + credentialsId: 'ceph-qe-sa', usernameVariable: 'OSPUSER', passwordVariable: 'OSPCRED' ) diff --git a/pipeline/vars/v3.groovy b/pipeline/vars/v3.groovy index 3d537af53ef..899bd89e342 100644 --- a/pipeline/vars/v3.groovy +++ b/pipeline/vars/v3.groovy @@ -488,7 +488,7 @@ def uploadTestResults(def sourceDir, def credPreproc, def runProperties, def sta // Upload test result to polarion using xUnit Xml file withCredentials([ usernamePassword( - credentialsId: 'psi-ceph-jenkins', + credentialsId: 'ceph-qe-sa', usernameVariable: 'OSPUSER', passwordVariable: 'OSPCRED' ) @@ -531,7 +531,7 @@ def prepareNode(def listener=0, def project="ceph-jenkins") { */ withCredentials([ usernamePassword( - credentialsId: 'psi-ceph-jenkins', + credentialsId: 'ceph-qe-sa', usernameVariable: 'OSPUSER', passwordVariable: 'OSPCRED' ) From 8c460566b60e00554b04a576960550ff5f1949a4 Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Mon, 23 Dec 2024 09:53:19 +0530 Subject: [PATCH 13/50] Switch mergify to support main branch The default branch is main hence modifying mergify to work with main instead of master branch. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- .github/mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/mergify.yml b/.github/mergify.yml index 72d30439383..552d3e4e567 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -4,7 +4,7 @@ pull_request_rules: conditions: - label!=DNM - label!=work-in-progress - - base=master + - base=main - "approved-reviews-by=@red-hat-storage/cephci-top-level-reviewers" - "check-success=tox (3.9.18)" - check-success=WIP From 668f4a49b004f9d2bc848805a574d79a29b4419d Mon Sep 17 00:00:00 2001 From: Vidushi Mishra Date: Mon, 16 Dec 2024 10:28:46 +0530 Subject: [PATCH 14/50] Changing the test suite for transition tests to 3 way ms in reef as well Signed-off-by: Vidushi Mishra Signed-off-by: Harishacharya-redhat --- .../reef/rgw/tier-2_rgw_3_way_multisite.yaml | 32 +++++++++++++++++++ .../tier-2_rgw_singlesite_to_multisite.yaml | 30 ----------------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/suites/reef/rgw/tier-2_rgw_3_way_multisite.yaml b/suites/reef/rgw/tier-2_rgw_3_way_multisite.yaml index ca1805860c8..22c3dc14e78 100644 --- a/suites/reef/rgw/tier-2_rgw_3_way_multisite.yaml +++ b/suites/reef/rgw/tier-2_rgw_3_way_multisite.yaml @@ -552,3 +552,35 @@ tests: run-on-haproxy: true monitor-consistency-bucket-stats: true # verify-io-on-site: ["ceph-sec"] as there is an io file issue, once its fixed need to uncomment + - test: + clusters: + ceph-pri: + config: + script-name: test_bucket_lifecycle_object_expiration_transition.py + config-file-name: test_lc_cloud_transition_ibm_retain_false.yaml + desc: test LC cloud transition to IBM cos with retain false + polarion-id: CEPH-83581973 #CEPH-83581975 + module: sanity_rgw_multisite.py + name: test LC cloud transition to IBM cos with retain false + + - test: + clusters: + ceph-pri: + config: + script-name: test_sts_using_boto.py + config-file-name: test_sts_multisite.yaml + desc: test assume role at secondary, with s3 ops + polarion-id: CEPH-83575592 + module: sanity_rgw_multisite.py + name: test assume role at secondary, with s3 ops + + - test: + clusters: + ceph-pri: + config: + script-name: test_bucket_lifecycle_object_expiration_transition.py + config-file-name: test_lc_cloud_transition_ibm_retain_true.yaml + desc: test LC cloud transition to IBM cos with retain true + polarion-id: CEPH-83581972 #CEPH-83575498 + module: sanity_rgw_multisite.py + name: test LC cloud transition to IBM cos with retain true diff --git a/suites/reef/rgw/tier-2_rgw_singlesite_to_multisite.yaml b/suites/reef/rgw/tier-2_rgw_singlesite_to_multisite.yaml index 0070d22287f..1c80404ac60 100644 --- a/suites/reef/rgw/tier-2_rgw_singlesite_to_multisite.yaml +++ b/suites/reef/rgw/tier-2_rgw_singlesite_to_multisite.yaml @@ -512,36 +512,6 @@ tests: config: script-name: test_bucket_request_payer.py config-file-name: test_bucket_request_payer.yaml - - test: - clusters: - ceph-pri: - config: - script-name: test_bucket_lifecycle_object_expiration_transition.py - config-file-name: test_lc_cloud_transition_ibm_retain_false.yaml - desc: test LC cloud transition to IBM cos with retain false - polarion-id: CEPH-83581973 #CEPH-83581975 - module: sanity_rgw_multisite.py - name: test LC cloud transition to IBM cos with retain false - - test: - clusters: - ceph-pri: - config: - script-name: test_sts_using_boto.py - config-file-name: test_sts_multisite.yaml - desc: test assume role at secondary, with s3 ops - polarion-id: CEPH-83575592 - module: sanity_rgw_multisite.py - name: test assume role at secondary, with s3 ops - - test: - clusters: - ceph-pri: - config: - script-name: test_bucket_lifecycle_object_expiration_transition.py - config-file-name: test_lc_cloud_transition_ibm_retain_true.yaml - desc: test LC cloud transition to IBM cos with retain true - polarion-id: CEPH-83581972 #CEPH-83575498 - module: sanity_rgw_multisite.py - name: test LC cloud transition to IBM cos with retain true # please include test cases before below rename testcase as the process is disruptive currently # - test: From 30a6c2e051e103b862902b21ef1fc05c41bc877a Mon Sep 17 00:00:00 2001 From: Tejas Chandramouli Date: Thu, 19 Dec 2024 01:02:19 +0530 Subject: [PATCH 15/50] CI Integration for 2 tests, CRLF Injection using Curl and higher than default shard DBR Signed-off-by: Tejas Chandramouli Signed-off-by: Harishacharya-redhat --- suites/reef/rgw/tier-2_rgw_regression_test.yaml | 10 ++++++++++ suites/reef/rgw/tier-2_ssl_rgw_regression_test.yaml | 11 +++++++++++ suites/squid/rgw/tier-2_rgw_regression_test.yaml | 10 ++++++++++ suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml | 11 +++++++++++ 4 files changed, 42 insertions(+) diff --git a/suites/reef/rgw/tier-2_rgw_regression_test.yaml b/suites/reef/rgw/tier-2_rgw_regression_test.yaml index ac2cdc1ff13..bd3c01d1333 100644 --- a/suites/reef/rgw/tier-2_rgw_regression_test.yaml +++ b/suites/reef/rgw/tier-2_rgw_regression_test.yaml @@ -599,3 +599,13 @@ tests: run-on-rgw: true script-name: ../s3cmd/test_rate_limit.py config-file-name: ../../s3cmd/configs/test_rate_limit.yaml + + - test: + name: Test CRLF Injection + desc: Test CRLF Injection + polarion-id: CEPH-83574745 + module: sanity_rgw.py + config: + run-on-rgw: true + script-name: ../curl/test_cors_using_curl.py + config-file-name: ../../curl/configs/test_crlf_injection_curl.yaml diff --git a/suites/reef/rgw/tier-2_ssl_rgw_regression_test.yaml b/suites/reef/rgw/tier-2_ssl_rgw_regression_test.yaml index 02bf1f987f0..da84503ecef 100644 --- a/suites/reef/rgw/tier-2_ssl_rgw_regression_test.yaml +++ b/suites/reef/rgw/tier-2_ssl_rgw_regression_test.yaml @@ -249,6 +249,17 @@ tests: script-name: test_dynamic_bucket_resharding.py config-file-name: test_dbr_with_custom_objs_per_shard_max_dynamic_shard_and_reshard_thread_interval.yaml + - test: + name: DBR tests with higher than default shard limit + desc: Resharding test - dynamic + polarion-id: CEPH-83573601 + module: sanity_rgw.py + config: + run-on-rgw: true + script-name: test_dynamic_bucket_resharding.py + config-file-name: test_dbr_high_default_limit.yaml + timeout: 6000 + - test: name: Bucket setlifeycle with invalid date in LC conf desc: Setlifeycle to bucket with invalid date format in Lifecycle configuration diff --git a/suites/squid/rgw/tier-2_rgw_regression_test.yaml b/suites/squid/rgw/tier-2_rgw_regression_test.yaml index c7af2b49579..29cd7d46f6f 100644 --- a/suites/squid/rgw/tier-2_rgw_regression_test.yaml +++ b/suites/squid/rgw/tier-2_rgw_regression_test.yaml @@ -622,3 +622,13 @@ tests: run-on-rgw: true script-name: ../curl/test_cors_using_curl.py config-file-name: ../../curl/configs/test_cors_using_curl.yaml + + - test: + name: Test CRLF Injection + desc: Test CRLF Injection + polarion-id: CEPH-83574745 + module: sanity_rgw.py + config: + run-on-rgw: true + script-name: ../curl/test_cors_using_curl.py + config-file-name: ../../curl/configs/test_crlf_injection_curl.yaml diff --git a/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml index fc063d5e74f..b81a33fb3a8 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml @@ -249,6 +249,17 @@ tests: script-name: test_dynamic_bucket_resharding.py config-file-name: test_dbr_with_custom_objs_per_shard_max_dynamic_shard_and_reshard_thread_interval.yaml + - test: + name: DBR tests with higher than default shard limit + desc: Resharding test - dynamic + polarion-id: CEPH-83573601 + module: sanity_rgw.py + config: + run-on-rgw: true + script-name: test_dynamic_bucket_resharding.py + config-file-name: test_dbr_high_default_limit.yaml + timeout: 6000 + - test: name: Bucket setlifeycle with invalid date in LC conf desc: Setlifeycle to bucket with invalid date format in Lifecycle configuration From 40b7eb2e2cfabb9546c4a55d067754a1c49a801c Mon Sep 17 00:00:00 2001 From: Suma R Date: Fri, 20 Dec 2024 19:13:38 +0530 Subject: [PATCH 16/50] TFA fix for CG quiesce tests Signed-off-by: Suma R Signed-off-by: Harishacharya-redhat --- .../cephfs/tier-1_cephfs_cg_quiesce.yaml | 35 ++++++++++++++----- tests/cephfs/snapshot_clone/cephfs_cg_io.py | 13 ++++++- .../snapshot_clone/cg_snap_system_test.py | 2 +- tests/cephfs/snapshot_clone/cg_snap_utils.py | 18 ++++------ 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/suites/squid/cephfs/tier-1_cephfs_cg_quiesce.yaml b/suites/squid/cephfs/tier-1_cephfs_cg_quiesce.yaml index 10d5da6511c..43509f8fc30 100644 --- a/suites/squid/cephfs/tier-1_cephfs_cg_quiesce.yaml +++ b/suites/squid/cephfs/tier-1_cephfs_cg_quiesce.yaml @@ -153,23 +153,33 @@ tests: - test: abort-on-fail: false - desc: "Verify quiesce lifecycle with and without --await" + desc: "Verify CG quiesce on pre-provisioned quiesce set" destroy-cluster: false module: snapshot_clone.cg_snap_test.py - name: "cg_snap_func_workflow_1" - polarion-id: CEPH-83581467 + name: "cg_snap_func_workflow_3" + polarion-id: CEPH-83590253 config: - test_name: cg_snap_func_workflow_1 + test_name: cg_snap_func_workflow_3 - test: abort-on-fail: false - desc: "Verify CG quiesce on pre-provisioned quiesce set" + desc: "Enable ceph debug logs" + module: cephfs_logs_util.py + name: cephfs-enable-logs + config: + ENABLE_LOGS : 1 + daemon_list : ['mds','client'] + daemon_dbg_level : {'mds':20,'client':20} + - + test: + abort-on-fail: false + desc: "Verify quiesce lifecycle with and without --await" destroy-cluster: false module: snapshot_clone.cg_snap_test.py - name: "cg_snap_func_workflow_3" - polarion-id: CEPH-83590253 + name: "cg_snap_func_workflow_1" + polarion-id: CEPH-83581467 config: - test_name: cg_snap_func_workflow_3 + test_name: cg_snap_func_workflow_1 - test: abort-on-fail: false @@ -181,3 +191,12 @@ tests: config: test_name: cg_snap_interop_workflow_1 comments: product bug bz-2273569 + - + test: + abort-on-fail: false + desc: "Disable ceph debug logs" + module: cephfs_logs_util.py + name: cephfs-disable-logs + config: + DISABLE_LOGS : 1 + daemon_list : ['mds','client'] diff --git a/tests/cephfs/snapshot_clone/cephfs_cg_io.py b/tests/cephfs/snapshot_clone/cephfs_cg_io.py index 20dbe5aa3d9..58ae5f67174 100644 --- a/tests/cephfs/snapshot_clone/cephfs_cg_io.py +++ b/tests/cephfs/snapshot_clone/cephfs_cg_io.py @@ -1331,7 +1331,18 @@ def cg_linux_cmds_read(self, client, mnt_pt): while retry_cnt > 0: file_name = random.choice(files) retry_cnt -= 1 - if ("_copy" not in file_name) and ("dir" not in file_name): + cmd = f"ls {dir_path}/{file_name}" + file_exists = 0 + try: + out, _ = client.exec_command(sudo=True, cmd=cmd, timeout=15) + file_exists = 1 + except BaseException as ex: + log.info(ex) + if ( + ("_copy" not in file_name) + and ("dir" not in file_name) + and file_exists + ): retry_cnt = 0 client_name = client.node.hostname client_name_1 = f"{client_name[0: -1]}" diff --git a/tests/cephfs/snapshot_clone/cg_snap_system_test.py b/tests/cephfs/snapshot_clone/cg_snap_system_test.py index 6f59fdad219..89baaa93fdf 100644 --- a/tests/cephfs/snapshot_clone/cg_snap_system_test.py +++ b/tests/cephfs/snapshot_clone/cg_snap_system_test.py @@ -676,7 +676,7 @@ def cg_stress(cg_test_params): check_ec=False, ) log.info(f"Reset the quiesce set - {qs_set}") - cg_snap_util.cg_quiesce_reset(client, qs_id_val, qs_set) + cg_snap_util.cg_quiesce_reset(client, qs_id_val, qs_set, cmd_timeout=600) client.exec_command( sudo=True, cmd="ceph config set mds log_to_file false", diff --git a/tests/cephfs/snapshot_clone/cg_snap_utils.py b/tests/cephfs/snapshot_clone/cg_snap_utils.py index 500e78a798c..16f3e6f789e 100644 --- a/tests/cephfs/snapshot_clone/cg_snap_utils.py +++ b/tests/cephfs/snapshot_clone/cg_snap_utils.py @@ -147,10 +147,8 @@ def cg_quiesce( cmd += f" --timeout {kw_args['timeout']}" if kw_args.get("expiration"): cmd += f" --expiration {kw_args['expiration']}" - out, rc = client.exec_command( - sudo=True, - cmd=cmd, - ) + cmd_timeout = kw_args.get("cmd_timeout", 300) + out, rc = client.exec_command(sudo=True, cmd=cmd, timeout=cmd_timeout) if kw_args.get("qs_id"): log.info(f"Quiesce cmd response for qs_id {kw_args['qs_id']} : {out}") else: @@ -195,10 +193,8 @@ def cg_quiesce_release( cmd += " --await" if kw_args.get("if_version"): cmd += f" --if_version {kw_args['if_version']}" - out, rc = client.exec_command( - sudo=True, - cmd=cmd, - ) + cmd_timeout = kw_args.get("cmd_timeout", 300) + out, rc = client.exec_command(sudo=True, cmd=cmd, timeout=cmd_timeout) qs_output = json.loads(out) if kw_args.get("task_validate", True): for qs_id in qs_output["sets"]: @@ -438,10 +434,8 @@ def cg_quiesce_reset( cmd = f"ceph fs quiesce {fs_name} --set-id {qs_id} --reset {qs_member_str} --format json" if if_await: cmd += " --await" - out, rc = client.exec_command( - sudo=True, - cmd=cmd, - ) + cmd_timeout = kw_args.get("cmd_timeout", 300) + out, rc = client.exec_command(sudo=True, cmd=cmd, timeout=cmd_timeout) qs_output = json.loads(out) if kw_args.get("task_validate", True): for qs_id in qs_output["sets"]: From e0efac081d291b9c479c7faf9ae9e8852961d2e5 Mon Sep 17 00:00:00 2001 From: Amarnath K Date: Tue, 17 Dec 2024 00:38:12 +0530 Subject: [PATCH 17/50] Adding Validation for subvolume info for cloned Volumes Signed-off-by: Amarnath K Signed-off-by: Harishacharya-redhat --- .../cephfs/snapshot_clone/clone_attributes.py | 183 ++++++++++++++++-- 1 file changed, 163 insertions(+), 20 deletions(-) diff --git a/tests/cephfs/snapshot_clone/clone_attributes.py b/tests/cephfs/snapshot_clone/clone_attributes.py index 7be488eb240..5e619f5d61b 100644 --- a/tests/cephfs/snapshot_clone/clone_attributes.py +++ b/tests/cephfs/snapshot_clone/clone_attributes.py @@ -1,7 +1,10 @@ +import json import random import string import traceback +from ceph.ceph import CommandFailed +from ceph.parallel import parallel from tests.cephfs.cephfs_utilsV1 import FsUtils from utility.log import Log @@ -101,14 +104,30 @@ def run(ceph_cluster, **kw): ) fs_util.set_quota_attrs(clients[0], 9999, 999, kernel_mounting_dir_1) quota_attrs = fs_util.get_quota_attrs(clients[0], kernel_mounting_dir_1) - snapshot = { + snapshot_1 = { "vol_name": default_fs, "subvol_name": "subvol_clone_attr_vol", "snap_name": "snap_1", "group_name": "subvolgroup_clone_attr_vol_1", } - fs_util.create_snapshot(client1, **snapshot) - client1.exec_command(sudo=True, cmd=f"mkdir -p /tmp/{mounting_dir}") + fs_util.create_snapshot(client1, **snapshot_1) + client1.exec_command( + sudo=True, cmd=f"mkdir -p {kernel_mounting_dir_1}/iteration_2" + ) + client1.exec_command( + sudo=True, + cmd=f"python3 /home/cephuser/smallfile/smallfile_cli.py --operation create --threads 10 --file-size 400 " + f"--files 100 --files-per-dir 10 --dirs-per-dir 1 --top " + f"{kernel_mounting_dir_1}/iteration_2", + long_running=True, + ) + snapshot_2 = { + "vol_name": default_fs, + "subvol_name": "subvol_clone_attr_vol", + "snap_name": "snap_2", + "group_name": "subvolgroup_clone_attr_vol_1", + } + fs_util.create_snapshot(client1, **snapshot_2) log.info("Clone a subvolume from snapshot") clone_attr_vol_1 = { @@ -124,23 +143,100 @@ def run(ceph_cluster, **kw): sudo=True, cmd=f"ceph fs subvolume getpath {default_fs} {clone_attr_vol_1['target_subvol_name']}", ) - fuse_mounting_dir_2 = f"/mnt/cephfs_fuse{mounting_dir}_2/" - fs_util.fuse_mount( - [client1], - fuse_mounting_dir_2, - extra_params=f" -r {clonevol_path.strip()} --client_fs {default_fs}", - ) - quota_attrs_clone = fs_util.get_quota_attrs(clients[0], fuse_mounting_dir_2) - client1.exec_command( - sudo=True, cmd=f"diff -qr {kernel_mounting_dir_1} {fuse_mounting_dir_2}" - ) - if quota_attrs_clone != quota_attrs: - log.info(f"attributes of cloned volumes{quota_attrs_clone}") - log.info(f"attributes of volumes{quota_attrs}") - log.error( - "Quota attributes of the clone is not matching with quota attributes of subvolume" + clone_attr_vol_2 = { + "vol_name": default_fs, + "subvol_name": "subvol_clone_attr_vol", + "snap_name": "snap_2", + "target_subvol_name": "clone_attr_vol_2", + "group_name": "subvolgroup_clone_attr_vol_1", + } + with parallel() as p: + log.info("Start Writing IO on the subvolume") + p.spawn( + fs_util.run_ios_V1, + client=client1, + mounting_dir=kernel_mounting_dir_1, + run_time=2, + io_tools=["dd"], ) - return 1 + fs_util.create_clone(client1, **clone_attr_vol_2) + fs_util.validate_clone_state(client1, clone_attr_vol_2) + subvol_1_info, rc = client1.exec_command( + sudo=True, + cmd=f"ceph fs subvolume info {default_fs} subvol_clone_attr_vol subvolgroup_clone_attr_vol_1", + ) + clonevol_1_info, rc = client1.exec_command( + sudo=True, + cmd=f"ceph fs subvolume info {default_fs} {clone_attr_vol_1['target_subvol_name']}", + ) + clonevol_2_info, rc = client1.exec_command( + sudo=True, + cmd=f"ceph fs subvolume info {default_fs} {clone_attr_vol_2['target_subvol_name']}", + ) + subvol_1_info = json.loads(subvol_1_info) + clonevol_1_info = json.loads(clonevol_1_info) + clonevol_2_info = json.loads(clonevol_2_info) + compare_json( + clonevol_1_info, + subvol_1_info, + keys_to_check=[ + "atime", + "bytes_quota", + "data_pool", + "features", + "flavor", + "gid", + "mode", + "mon_addrs", + "uid", + ], + ) + compare_json( + clonevol_2_info, + subvol_1_info, + keys_to_check=[ + "atime", + "bytes_quota", + "data_pool", + "features", + "flavor", + "gid", + "mode", + "mon_addrs", + "uid", + ], + ) + fuse_mounting_dir_2 = f"/mnt/cephfs_fuse{mounting_dir}_2/" + fs_util.fuse_mount( + [client1], + fuse_mounting_dir_2, + extra_params=f" -r {clonevol_path.strip()} --client_fs {default_fs}", + ) + + clonevol_2_path, rc = client1.exec_command( + sudo=True, + cmd=f"ceph fs subvolume getpath {default_fs} {clone_attr_vol_2['target_subvol_name']}", + ) + fuse_mounting_dir_3 = f"/mnt/cephfs_fuse{mounting_dir}_3/" + fs_util.fuse_mount( + [client1], + fuse_mounting_dir_3, + extra_params=f" -r {clonevol_2_path.strip()} --client_fs {default_fs}", + ) + quota_attrs_clone = fs_util.get_quota_attrs(clients[0], fuse_mounting_dir_2) + quota_attrs_clone_1 = fs_util.get_quota_attrs( + clients[0], fuse_mounting_dir_3 + ) + + if quota_attrs_clone != quota_attrs and quota_attrs_clone_1 != quota_attrs: + log.info(f"attributes of cloned volumes{quota_attrs_clone}") + log.info(f"attributes of volumes{quota_attrs}") + log.error( + "Quota attributes of the clone is not matching with quota attributes of subvolume" + ) + return 1 + log.info("Validate the subvolume GID and UID attributes") + return 0 except Exception as e: log.info(e) @@ -150,10 +246,57 @@ def run(ceph_cluster, **kw): log.info("Clean Up in progess") rmclone_list = [ {"vol_name": default_fs, "subvol_name": "clone_attr_vol_1"}, + {"vol_name": default_fs, "subvol_name": "clone_attr_vol_2"}, ] for clone_vol in rmclone_list: fs_util.remove_subvolume(client1, **clone_vol) - fs_util.remove_snapshot(client1, **snapshot, validate=False, check_ec=False) + fs_util.remove_snapshot(client1, **snapshot_1, validate=False, check_ec=False) + fs_util.remove_snapshot(client1, **snapshot_2, validate=False, check_ec=False) fs_util.remove_subvolume(client1, **subvolume, validate=False, check_ec=False) for subvolumegroup in subvolumegroup_list: fs_util.remove_subvolumegroup(client1, **subvolumegroup, force=True) + + +def compare_json(subvol_info_1, subvol_info_2, keys_to_check=None): + """ + Compares specified keys in two JSON strings for equality. + + Args: + subvol_info_1 (str): First JSON string. + subvol_info_2 (str): Second JSON string. + keys_to_check (list): List of keys to compare. Defaults to a predefined set of keys. + + Returns: + tuple: (bool, dict) where the bool indicates if all keys match, + and dict contains mismatched keys with their respective values. + """ + # Default keys to check + default_keys = [ + "atime", + "bytes_quota", + "bytes_used", + "data_pool", + "features", + "flavor", + "gid", + "mode", + "mon_addrs", + "uid", + ] + keys_to_check = keys_to_check or default_keys + + # Load JSON data + + mismatches = {} + + for key in keys_to_check: + if subvol_info_1.get(key) != subvol_info_2.get(key): + mismatches[key] = { + "value1": subvol_info_1.get(key), + "value2": subvol_info_2.get(key), + } + + # Return True if no mismatches, otherwise return mismatches + if not len(mismatches) == 0: + raise CommandFailed(f"clone attributes are mismatching {mismatches}") + # return (len(mismatches) == 0), mismatches From 790eaad3aceea9b71e913bf23acdb9279ec7b32b Mon Sep 17 00:00:00 2001 From: Sunil Angadi Date: Mon, 23 Dec 2024 12:44:07 +0530 Subject: [PATCH 18/50] test backported to pacific Signed-off-by: Sunil Angadi Signed-off-by: Harishacharya-redhat --- suites/pacific/rbd/tier-2_rbd_regression.yaml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/suites/pacific/rbd/tier-2_rbd_regression.yaml b/suites/pacific/rbd/tier-2_rbd_regression.yaml index c0d1852f682..fdee96eb145 100755 --- a/suites/pacific/rbd/tier-2_rbd_regression.yaml +++ b/suites/pacific/rbd/tier-2_rbd_regression.yaml @@ -213,3 +213,28 @@ tests: module: test_rbd_python_module.py polarion-id: CEPH-83574791 name: Test image creation, write and read data using python rbd module + + - test: + desc: Verify RBD image with zero size + config: + resize_to: 0 + rep_pool_config: + num_pools: 1 + num_images: 2 + images: + image_1024: + size: 1024 + image_zero: + size: 0 + ec_pool_config: + num_pools: 1 + num_images: 2 + images_ec: + data_pool: rbd_ec_data_pool + image_1024: + size: 1024 + image_zero: + size: 0 + module: test_rbd_image_zero_size.py + name: Test to verify RBD image with zero size + polarion-id: CEPH-83597243 From a3be92d6ea0c1b090eeac9963f4a94638d86e4b2 Mon Sep 17 00:00:00 2001 From: tintumathew10 Date: Mon, 23 Dec 2024 17:39:13 +0530 Subject: [PATCH 19/50] Replacing master branch with main branch in cephci Signed-off-by: tintumathew10 Signed-off-by: Harishacharya-redhat --- pipeline/rhcs_delete.groovy | 2 +- pipeline/rhcs_deploy.groovy | 2 +- pipeline/rhos_scripts/Jenkinsfile-cleanup-cloud-volumes.groovy | 2 +- pipeline/rhos_scripts/Jenkinsfile-cleanup-env.groovy | 2 +- pipeline/rhos_scripts/Jenkinsfile-quota.groovy | 2 +- pipeline/signed-compose-listener.groovy | 2 +- pipeline/signed-container-image-listener.groovy | 2 +- pipeline/unsigned-compose-listener.groovy | 2 +- pipeline/unsigned-container-image-listener.groovy | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pipeline/rhcs_delete.groovy b/pipeline/rhcs_delete.groovy index 22a5c404079..ffab04362b2 100644 --- a/pipeline/rhcs_delete.groovy +++ b/pipeline/rhcs_delete.groovy @@ -11,7 +11,7 @@ node("rhel-9-medium || ceph-qe-ci") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: 'origin/master']], + branches: [[name: 'origin/main']], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/rhcs_deploy.groovy b/pipeline/rhcs_deploy.groovy index 0256e1cb651..2637ac6e6b2 100644 --- a/pipeline/rhcs_deploy.groovy +++ b/pipeline/rhcs_deploy.groovy @@ -41,7 +41,7 @@ node ("rhel-9-medium || ceph-qe-ci") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: 'origin/master']], + branches: [[name: 'origin/main']], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/rhos_scripts/Jenkinsfile-cleanup-cloud-volumes.groovy b/pipeline/rhos_scripts/Jenkinsfile-cleanup-cloud-volumes.groovy index 4d94a3d4bfa..e854f7d549b 100644 --- a/pipeline/rhos_scripts/Jenkinsfile-cleanup-cloud-volumes.groovy +++ b/pipeline/rhos_scripts/Jenkinsfile-cleanup-cloud-volumes.groovy @@ -10,7 +10,7 @@ node("rhel-8-medium") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: "origin/master"]], + branches: [[name: "origin/main"]], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/rhos_scripts/Jenkinsfile-cleanup-env.groovy b/pipeline/rhos_scripts/Jenkinsfile-cleanup-env.groovy index 50322c48747..46de9cf03ae 100644 --- a/pipeline/rhos_scripts/Jenkinsfile-cleanup-env.groovy +++ b/pipeline/rhos_scripts/Jenkinsfile-cleanup-env.groovy @@ -10,7 +10,7 @@ node("rhel-9-medium") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: "origin/master"]], + branches: [[name: "origin/main"]], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/rhos_scripts/Jenkinsfile-quota.groovy b/pipeline/rhos_scripts/Jenkinsfile-quota.groovy index 4c4d8eb47a3..1b4c0c94ba7 100644 --- a/pipeline/rhos_scripts/Jenkinsfile-quota.groovy +++ b/pipeline/rhos_scripts/Jenkinsfile-quota.groovy @@ -10,7 +10,7 @@ node("rhel-9-medium") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: "origin/master"]], + branches: [[name: "origin/main"]], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/signed-compose-listener.groovy b/pipeline/signed-compose-listener.groovy index 6b5f615a378..8d84db67fa4 100644 --- a/pipeline/signed-compose-listener.groovy +++ b/pipeline/signed-compose-listener.groovy @@ -17,7 +17,7 @@ node("rhel-9-medium || ceph-qe-ci") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: 'origin/master']], + branches: [[name: 'origin/main']], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/signed-container-image-listener.groovy b/pipeline/signed-container-image-listener.groovy index a0c5c47ed40..dda967f6b17 100644 --- a/pipeline/signed-container-image-listener.groovy +++ b/pipeline/signed-container-image-listener.groovy @@ -20,7 +20,7 @@ node("rhel-9-medium || ceph-qe-ci") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: 'origin/master']], + branches: [[name: 'origin/main']], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/unsigned-compose-listener.groovy b/pipeline/unsigned-compose-listener.groovy index 99d3cad3834..185392cc4cd 100644 --- a/pipeline/unsigned-compose-listener.groovy +++ b/pipeline/unsigned-compose-listener.groovy @@ -20,7 +20,7 @@ node("rhel-9-medium || ceph-qe-ci") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: 'origin/master']], + branches: [[name: 'origin/main']], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true diff --git a/pipeline/unsigned-container-image-listener.groovy b/pipeline/unsigned-container-image-listener.groovy index 1c9325b1aba..922d602289a 100644 --- a/pipeline/unsigned-container-image-listener.groovy +++ b/pipeline/unsigned-container-image-listener.groovy @@ -18,7 +18,7 @@ node("rhel-9-medium || ceph-qe-ci") { checkout( scm: [ $class: 'GitSCM', - branches: [[name: 'origin/master']], + branches: [[name: 'origin/main']], extensions: [[ $class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true From f0e065ba9148e54d5c95884d67e2b7f6843e7962 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Tue, 24 Dec 2024 09:43:35 +0530 Subject: [PATCH 20/50] Fix for unmap device with encryption Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat --- ceph/rbd/workflows/cleanup.py | 2 ++ ceph/rbd/workflows/krbd_io_handler.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ceph/rbd/workflows/cleanup.py b/ceph/rbd/workflows/cleanup.py index 5eb82536359..9bcd7d40eb4 100644 --- a/ceph/rbd/workflows/cleanup.py +++ b/ceph/rbd/workflows/cleanup.py @@ -144,6 +144,8 @@ def device_cleanup(rbd, client, **kw): "image-snap-or-device-spec": kw["device_name"], "device-type": kw.get("device_type", "nbd"), } + if kw.get("options"): + map_config.update({"options": kw.get("options")}) _, err = rbd.device.unmap(**map_config) else: diff --git a/ceph/rbd/workflows/krbd_io_handler.py b/ceph/rbd/workflows/krbd_io_handler.py index 0274bacadd7..9717680d46f 100644 --- a/ceph/rbd/workflows/krbd_io_handler.py +++ b/ceph/rbd/workflows/krbd_io_handler.py @@ -196,6 +196,8 @@ def krbd_io_handler(**kw): cleanup_config.update( {"device-type": config.get("device_type", "nbd")} ) + if config.get("encryption_config"): + cleanup_config.update({"options": options}) return_flag = device_cleanup(**cleanup_config) kw["config"]["device_names"] = device_names return return_flag, "" From f5f1e50669667c77101821ab721af1e090c2c2b9 Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Sun, 22 Dec 2024 13:01:42 -0500 Subject: [PATCH 21/50] rebase Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- .../tier-2_cephfs_test-volume-management.yaml | 358 +++++++++++++++++ .../tier-2_cephfs_test-volume-management.yaml | 355 +++++++++++++++++ ...-2_cephfs_test-volume-management_arch.yaml | 7 + tests/cephfs/cephfs_utilsV1.py | 372 ++++++++++++++++++ .../cephfs_vol_mgmt_test_volume.py | 307 +++++++++++++++ 5 files changed, 1399 insertions(+) create mode 100644 suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml create mode 100644 suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml create mode 100644 tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py diff --git a/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml b/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml new file mode 100644 index 00000000000..4b69b731293 --- /dev/null +++ b/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml @@ -0,0 +1,358 @@ +--- +#=============================================================================================== +# Tier-level: 2 +# Test-Suite: tier-2_cephfs_test-volume-management.yaml +# Conf file : conf/pacific/cephfs/tier-2_cephfs_9-node-cluster.yaml +# Test-Case Covered: +# CEPH-83574164 : Create cephfs subvolumegroup with desired data pool_layout +# CEPH-83574193 - cephfs subvolume size expansion test +# CEPH-83574166 - Create cephfs subvolumegroup with specific uid,gid test //TO DO +# CEPH-83574182 - Delete subvolume name that does not exist +# CEPH-83574169 - Remove subvolume group name does not exist with force option +# CEPH-83574168 - Delete_non_exist_subvol_group +# CEPH-83573637 - Verify if the FS data can be moved from an existing Replicated Datapool to EC datapool +# CEPH-83574158 - arbitary pool removal on volume deletion test +# CEPH-83573428 - cephfs_vol_mgmt_create_vol_component_exist_name +# CEPH-83574162 - cephfs_vol_mgmt_non_exist_subvol_group_deletetion +# CEPH-83573528 - cephfs_vol_mgmt_pool_name_option_test +# CEPH-83574161 - Checking default subvolume group gid and uid +# CEPH-83574181 - Checking default subvolume gid and uid +# CEPH-83574163 - cephfs_vol_mgmt_invalid_pool_layout +# CEPH-83574190 - Volume default and different permission test +# CEPH-83574192 - Subvolume creation with invalid pool_layout +# CEPH-83574187 - Subvolume creation with isolated_namespace option +# CEPH-83574165 - Create cephfs subvolumegroup with desired permissions test +# CEPH-83574331 - Adding new data pools to cephfs which has existing data pool. +# CEPH-83573428 - cephfs_vol_mgmt_volume_with_exist_names +# CEPH-83574188 - Testing auto-cleanup cephfs subvolume after creation failure +# CEPH-83574187: Subvolume metadata creation, delete, and modifying test. +# CEPH-83571330: Test FS volume deletion when mon_allow_pool_delete is false. +# CEPH-11333: CephFS volume management - FS life cycle. +# CEPH-83603354 - volume related scenarios(delete,rename) +# CEPH-83604097 - Basic info validation after volume creation and deletion +#=============================================================================================== +tests: + - test: + name: setup install pre-requisistes + desc: Setup phase to deploy the required pre-requisites for running the tests. + module: install_prereq.py + abort-on-fail: true + - test: + name: cluster deployment + desc: Execute the cluster deployment workflow. + module: test_cephadm.py + polarion-id: + config: + verify_cluster_health: true + steps: + - config: + command: bootstrap + service: cephadm + base_cmd_args: + verbose: true + args: + registry-url: registry.redhat.io + mon-ip: node1 + orphan-initial-daemons: true + skip-monitoring-stack: true + - config: + command: add_hosts + service: host + args: + attach_ip_address: true + labels: apply-all-labels + - config: + command: apply + service: mgr + args: + placement: + label: mgr + - config: + command: apply + service: mon + args: + placement: + label: mon + - config: + command: apply + service: osd + args: + all-available-devices: true + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - volume + - create + - cephfs + - config: + command: shell + args: + - ceph + - osd + - pool + - create + - cephfs-data-ec + - "64" + - erasure + - config: + command: shell + args: + - ceph + - osd + - pool + - create + - cephfs-metadata + - "64" + - config: + command: shell + args: + - ceph + - osd + - pool + - set + - cephfs-data-ec + - allow_ec_overwrites + - "true" + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - new + - cephfs-ec + - cephfs-metadata + - cephfs-data-ec + - --force + - config: + command: apply + service: mds + base_cmd_args: # arguments to ceph orch + verbose: true + pos_args: + - cephfs # name of the filesystem + args: + placement: + label: mds + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - set + - cephfs + - max_mds + - "2" + destroy-cluster: false + abort-on-fail: true + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.1 + install_packages: + - ceph-common + - ceph-fuse + node: node8 + desc: "Configure the Cephfs client system 1" + destroy-cluster: false + module: test_client.py + name: "configure client" + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.2 + install_packages: + - ceph-common + - ceph-fuse + node: node9 + desc: "Configure the Cephfs client system 2" + destroy-cluster: false + module: test_client.py + name: "configure client" + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.3 + install_packages: + - ceph-common + - ceph-fuse + node: node10 + desc: "Configure the Cephfs client system 3" + destroy-cluster: false + module: test_client.py + name: "configure client" + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.4 + install_packages: + - ceph-common + - ceph-fuse + node: node11 + desc: "Configure the Cephfs client system 4" + destroy-cluster: false + module: test_client.py + name: "configure client" + - test: + name: subvolumegroup creation on desired data pool + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_pool_layout.py + polarion-id: CEPH-83574164 + desc: subvolumegroup creation with desired data pool_layout + abort-on-fail: false + - test: + name: Subvolume Resize + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_resize.py + polarion-id: CEPH-83574193 + desc: subvolume resize + abort-on-fail: false + - test: + name: Delete subvolume name that does not exist + module: cephfs_vol_management.cephfs_vol_mgmt_non_exist_subvolume.py + polarion-id: CEPH-83574182 + desc: Delete subvolume_group name that does not exist + abort-on-fail: false + - test: + name: Remove subvolume group name does not exist with force option + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_group_force.py + polarion-id: CEPH-83574169 + desc: Remove subvolume group name does not exist with force option + abort-on-fail: false + - test: + name: delete_non_exist_subvol_group + module: cephfs_vol_management.cephfs_vol_mgmt_delete_non_exist_subvol_group.py + polarion-id: CEPH-83574168 + desc: delete_non_exist_subvol_group + abort-on-fail: false + - test: + name: delete_non_exist_subvol_group + module: cephfs_vol_management.cephfs_vol_mgmt_non_exist_subvol_group.py + polarion-id: CEPH-83574162 + desc: delete_non_exist_subvol_group + abort-on-fail: false + - test: + name: Verify data movement bw FS created on Replicated Pool and EC Pool + module: cephfs_vol_management.cephfs_vol_mgmt_data_migrate.py + polarion-id: CEPH-83573637 + desc: Verify if the FS data can be moved from an existing Replicated Datapool to EC datapool + abort-on-fail: false + - test: + name: Arbitrary pool removal on cephfs volume deletion + module: cephfs_vol_management.cephfs_vol_mgmt_arbitrary_pool_removal.py + polarion-id: CEPH-83574158 + desc: Verify if the arbitraty pool is also deleted upon volume deletion + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_create_vol_component_exist_name + module: cephfs_vol_management.cephfs_vol_mgmt_create_vol_component_exist_name.py + polarion-id: CEPH-83573428 + desc: cephfs_vol_mgmt_create_vol_component_exist_name + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_pool_name_option_test + module: cephfs_vol_management.cephfs_vol_mgmt_pool_name_option_test.py + polarion-id: CEPH-83573528 + desc: cephfs_vol_mgmt_pool_name_option_test + abort-on-fail: false + - test: + name: Checking default subvolume group gid and uid + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_gid_uid.py + polarion-id: CEPH-83574181 + desc: Checking default subvolume group gid and uid + abort-on-fail: false + - test: + name: Checking default subvolume group gid and uid + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_gid_uid.py + polarion-id: CEPH-83574161 + desc: Checking default subvolume group gid and uid + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_invalid_pool_layout + module: cephfs_vol_management.cephfs_vol_mgmt_invalid_pool_layout.py + polarion-id: CEPH-83574163 + desc: cephfs_vol_mgmt_invalid_pool_layout + abort-on-fail: false + - test: + name: volume_permission_test + module: cephfs_vol_management.cephfs_vol_mgmt_volume_permissions.py + polarion-id: CEPH-83574190 + desc: volume_permission_test + abort-on-fail: false + - test: + name: subvolume_creation_invalid_pool_layout + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_invalid_pool_layout.py + polarion-id: CEPH-83574192 + desc: subvolume_creation_invalid_pool_layout + abort-on-fail: false + - test: + name: subvolume_isolated_namespace + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_isolated_namespace.py + polarion-id: CEPH-83574187 + desc: subvolume_isolated_namespace + abort-on-fail: false + - test: + name: Create cephfs subvolumegroup with desired permissions test + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_octal_modes.py + polarion-id: CEPH-83574165 + desc: cephfs subvolumegroup with different octal modes + abort-on-fail: false + - test: + name: add datapools to existing FS + module: cephfs_vol_management.cephfs_vol_mgmt_add_datapool_to_existing_fs.py + polarion-id: CEPH-83574331 + desc: add datapools to existing FS + abort-on-fail: false + - test: + name: Creating fs volume,sub-volume,sub-volume group with existing names + module: cephfs_vol_management.cephfs_vol_mgmt_volume_with_exist_names.py + polarion-id: CEPH-83574331 + desc: Creating fs volume,sub-volume,sub-volume group with existing names + abort-on-fail: false + - test: + name: Subvolume Auto clean up after failed creating subvolume + module: cephfs_vol_management.cephfs_vol_mgmt_auto_clean_up.py + polarion-id: CEPH-83574188 + desc: Subvolume Auto clean up after failed creating subvolume + abort-on-fail: false + - test: + name: Subvolume metadata creation, delete and modifying test + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_metadata.py + polarion-id: CEPH-83575032 + desc: Subvolume metadata creation, delete and modifying test + abort-on-fail: false + - test: + name: Test fs volume deletion when mon_allow_pool_delete is false + module: cephfs_vol_management.fs_del_allow_pool_false.py + polarion-id: CEPH-83574159 + desc: Test fs volume deletion when mon_allow_pool_delete is false + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_fs_life_cycle + module: cephfs_vol_management.cephfs_vol_mgmt_fs_life_cycle.py + polarion-id: CEPH-11333 + desc: File system life cycle + abort-on-fail: false + - test: + name: volume related scenarios(delete,rename) + module: cephfs_vol_management.cephfs_vol_mgmt_volume_scenarios.py + polarion-id: CEPH-83603354 + desc: volume related scenarios(delete,rename) + abort-on-fail: false + - test: + name: Basic info validation after volume creation and deletion + module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py + polarion-id: CEPH-83604097 + desc: Basic info validation after volume creation and deletion + abort-on-fail: true \ No newline at end of file diff --git a/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml b/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml new file mode 100644 index 00000000000..1ce0441ddd6 --- /dev/null +++ b/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml @@ -0,0 +1,355 @@ +--- +#=============================================================================================== +# Tier-level: 2 +# Test-Suite: tier-2_cephfs_test-volume-management.yaml +# Conf file : conf/pacific/cephfs/tier-2_cephfs_9-node-cluster.yaml +# Test-Case Covered: +# CEPH-83574164 : Create cephfs subvolumegroup with desired data pool_layout +# CEPH-83574193 - cephfs subvolume size expansion test +# CEPH-83574166 - Create cephfs subvolumegroup with specific uid,gid test //TO DO +# CEPH-83574182 - Delete subvolume name that does not exist +# CEPH-83574169 - Remove subvolume group name does not exist with force option +# CEPH-83574168 - Delete_non_exist_subvol_group +# CEPH-83573637 - Verify if the FS data can be moved from an existing Replicated Datapool to EC datapool +# CEPH-83574158 - arbitary pool removal on volume deletion test +# CEPH-83573428 - cephfs_vol_mgmt_create_vol_component_exist_name +# CEPH-83574162 - cephfs_vol_mgmt_non_exist_subvol_group_deletetion +# CEPH-83573528 - cephfs_vol_mgmt_pool_name_option_test +# CEPH-83574161 - Checking default subvolume group gid and uid +# CEPH-83574181 - Checking default subvolume gid and uid +# CEPH-83574163 - cephfs_vol_mgmt_invalid_pool_layout +# CEPH-83574190 - Volume default and different permission test +# CEPH-83574192 - Subvolume creation with invalid pool_layout +# CEPH-83574187 - Subvolume creation with isolated_namespace option +# CEPH-83574165 - Create cephfs subvolumegroup with desired permissions test +# CEPH-83574331 - Adding new data pools to cephfs which has existing data pool. +# CEPH-83573428 - cephfs_vol_mgmt_volume_with_exist_names +# CEPH-83574188 - Testing auto-cleanup cephfs subvolume after creation failure +# CEPH-83603354 - volume related scenarios(delete,rename) +# CEPH-83604097 - Basic info validation after volume creation and deletion +#=============================================================================================== +tests: + - test: + name: setup install pre-requisistes + desc: Setup phase to deploy the required pre-requisites for running the tests. + module: install_prereq.py + abort-on-fail: true + - test: + name: cluster deployment + desc: Execute the cluster deployment workflow. + module: test_cephadm.py + polarion-id: + config: + verify_cluster_health: true + steps: + - config: + command: bootstrap + service: cephadm + base_cmd_args: + verbose: true + args: + registry-url: registry.redhat.io + mon-ip: node1 + orphan-initial-daemons: true + skip-monitoring-stack: true + - config: + command: add_hosts + service: host + args: + attach_ip_address: true + labels: apply-all-labels + - config: + command: apply + service: mgr + args: + placement: + label: mgr + - config: + command: apply + service: mon + args: + placement: + label: mon + - config: + command: apply + service: osd + args: + all-available-devices: true + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - volume + - create + - cephfs + - config: + command: shell + args: + - ceph + - osd + - pool + - create + - cephfs-data-ec + - "64" + - erasure + - config: + command: shell + args: + - ceph + - osd + - pool + - create + - cephfs-metadata + - "64" + - config: + command: shell + args: + - ceph + - osd + - pool + - set + - cephfs-data-ec + - allow_ec_overwrites + - "true" + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - new + - cephfs-ec + - cephfs-metadata + - cephfs-data-ec + - --force + - config: + command: apply + service: mds + base_cmd_args: # arguments to ceph orch + verbose: true + pos_args: + - cephfs # name of the filesystem + args: + placement: + label: mds + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - set + - cephfs + - max_mds + - "2" + destroy-cluster: false + abort-on-fail: true + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.1 + install_packages: + - ceph-common + - ceph-fuse + node: node8 + desc: "Configure the Cephfs client system 1" + destroy-cluster: false + module: test_client.py + name: "configure client" + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.2 + install_packages: + - ceph-common + - ceph-fuse + node: node9 + desc: "Configure the Cephfs client system 2" + destroy-cluster: false + module: test_client.py + name: "configure client" + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.3 + install_packages: + - ceph-common + - ceph-fuse + node: node10 + desc: "Configure the Cephfs client system 3" + destroy-cluster: false + module: test_client.py + name: "configure client" + - + test: + abort-on-fail: true + config: + command: add + copy_admin_keyring: true + id: client.4 + install_packages: + - ceph-common + - ceph-fuse + node: node11 + desc: "Configure the Cephfs client system 4" + destroy-cluster: false + module: test_client.py + name: "configure client" + - test: + name: subvolumegroup creation on desired data pool + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_pool_layout.py + polarion-id: CEPH-83574164 + desc: subvolumegroup creation with desired data pool_layout + abort-on-fail: false + - test: + name: Subvolume Resize + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_resize.py + polarion-id: CEPH-83574193 + desc: subvolume resize + abort-on-fail: false + - test: + name: Delete subvolume name that does not exist + module: cephfs_vol_management.cephfs_vol_mgmt_non_exist_subvolume.py + polarion-id: CEPH-83574182 + desc: Delete subvolume_group name that does not exist + abort-on-fail: false + - test: + name: Remove subvolume group name does not exist with force option + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_group_force.py + polarion-id: CEPH-83574169 + desc: Remove subvolume group name does not exist with force option + abort-on-fail: false + - test: + name: delete_non_exist_subvol_group + module: cephfs_vol_management.cephfs_vol_mgmt_delete_non_exist_subvol_group.py + polarion-id: CEPH-83574168 + desc: delete_non_exist_subvol_group + abort-on-fail: false + - test: + name: delete_non_exist_subvol_group + module: cephfs_vol_management.cephfs_vol_mgmt_non_exist_subvol_group.py + polarion-id: CEPH-83574162 + desc: delete_non_exist_subvol_group + abort-on-fail: false + - test: + name: Verify data movement bw FS created on Replicated Pool and EC Pool + module: cephfs_vol_management.cephfs_vol_mgmt_data_migrate.py + polarion-id: CEPH-83573637 + desc: Verify if the FS data can be moved from an existing Replicated Datapool to EC datapool + abort-on-fail: false + - test: + name: Arbitrary pool removal on cephfs volume deletion + module: cephfs_vol_management.cephfs_vol_mgmt_arbitrary_pool_removal.py + polarion-id: CEPH-83574158 + desc: Verify if the arbitraty pool is also deleted upon volume deletion + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_create_vol_component_exist_name + module: cephfs_vol_management.cephfs_vol_mgmt_create_vol_component_exist_name.py + polarion-id: CEPH-83573428 + desc: cephfs_vol_mgmt_create_vol_component_exist_name + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_pool_name_option_test + module: cephfs_vol_management.cephfs_vol_mgmt_pool_name_option_test.py + polarion-id: CEPH-83573528 + desc: cephfs_vol_mgmt_pool_name_option_test + abort-on-fail: false + - test: + name: Checking default subvolume group gid and uid + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_gid_uid.py + polarion-id: CEPH-83574181 + desc: Checking default subvolume group gid and uid + abort-on-fail: false + - test: + name: Checking default subvolume group gid and uid + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_gid_uid.py + polarion-id: CEPH-83574161 + desc: Checking default subvolume group gid and uid + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_invalid_pool_layout + module: cephfs_vol_management.cephfs_vol_mgmt_invalid_pool_layout.py + polarion-id: CEPH-83574163 + desc: cephfs_vol_mgmt_invalid_pool_layout + abort-on-fail: false + - test: + name: volume_permission_test + module: cephfs_vol_management.cephfs_vol_mgmt_volume_permissions.py + polarion-id: CEPH-83574190 + desc: volume_permission_test + abort-on-fail: false + - test: + name: subvolume_creation_invalid_pool_layout + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_invalid_pool_layout.py + polarion-id: CEPH-83574192 + desc: subvolume_creation_invalid_pool_layout + abort-on-fail: false + - test: + name: subvolume_isolated_namespace + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_isolated_namespace.py + polarion-id: CEPH-83574187 + desc: subvolume_isolated_namespace + abort-on-fail: false + - test: + name: Create cephfs subvolumegroup with desired permissions test + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_octal_modes.py + polarion-id: CEPH-83574165 + desc: cephfs subvolumegroup with different octal modes + abort-on-fail: false + - test: + name: add datapools to existing FS + module: cephfs_vol_management.cephfs_vol_mgmt_add_datapool_to_existing_fs.py + polarion-id: CEPH-83574331 + desc: add datapools to existing FS + abort-on-fail: false + - test: + name: Creating fs volume,sub-volume,sub-volume group with existing names + module: cephfs_vol_management.cephfs_vol_mgmt_volume_with_exist_names.py + polarion-id: CEPH-83574331 + desc: Creating fs volume,sub-volume,sub-volume group with existing names + abort-on-fail: false + - test: + name: Subvolume Auto clean up after failed creating subvolume + module: cephfs_vol_management.cephfs_vol_mgmt_auto_clean_up.py + polarion-id: CEPH-83574188 + desc: Subvolume Auto clean up after failed creating subvolume + abort-on-fail: false + - test: + name: Subvolume metadata creation, delete and modifying test + module: cephfs_vol_management.cephfs_vol_mgmt_subvolume_metadata.py + polarion-id: CEPH-83575032 + desc: Subvolume metadata creation, delete and modifying test + abort-on-fail: false + - test: + name: Test fs volume deletion when mon_allow_pool_delete is false + module: cephfs_vol_management.fs_del_allow_pool_false.py + polarion-id: CEPH-83574159 + desc: Test fs volume deletion when mon_allow_pool_delete is false + abort-on-fail: false + - test: + name: cephfs_vol_mgmt_fs_life_cycle + module: cephfs_vol_management.cephfs_vol_mgmt_fs_life_cycle.py + polarion-id: CEPH-11333 + desc: File system life cycle + abort-on-fail: false + - test: + name: volume related scenarios(delete,rename) + module: cephfs_vol_management.cephfs_vol_mgmt_volume_scenarios.py + polarion-id: CEPH-83603354 + desc: volume related scenarios(delete,rename) + abort-on-fail: false + - test: + name: Basic info validation after volume creation and deletion + module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py + polarion-id: CEPH-83604097 + desc: Basic info validation after volume creation and deletion + abort-on-fail: true \ No newline at end of file diff --git a/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml b/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml index 7f41334ba61..e353999849f 100644 --- a/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml +++ b/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml @@ -26,6 +26,7 @@ # CEPH-83573428 - cephfs_vol_mgmt_volume_with_exist_names # CEPH-83574188 - Testing auto-cleanup cephfs subvolume after creation failure # CEPH-83603354 - volume related scenarios(delete,rename) +# CEPH-83604097 - Basic info validation after volume creation and deletion #=============================================================================================== tests: - test: @@ -358,3 +359,9 @@ tests: polarion-id: CEPH-83604184 desc: cephfs subvolume idempoence earmark abort-on-fail: false + - test: + name: Basic info validation after volume creation and deletion + module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py + polarion-id: CEPH-83604097 + desc: Basic info validation after volume creation and deletion + abort-on-fail: true diff --git a/tests/cephfs/cephfs_utilsV1.py b/tests/cephfs/cephfs_utilsV1.py index 97b710bedf5..0e5a474eb94 100644 --- a/tests/cephfs/cephfs_utilsV1.py +++ b/tests/cephfs/cephfs_utilsV1.py @@ -652,6 +652,25 @@ def validate_fs_info(self, client, fs_name="cephfs"): return False return True + def get_fs_info_dump(self, client, fs_name, **kwargs): + """ + Dumps output of fs info command. + Command: ceph fs volume info + Args: + fs_name : Name of the fs volume for which we need the status + human_readable: If the output needs to be human readble set it to True + Return: + returns ceph fs volume info dump in json format + """ + if fs_name: + fs_info_cmd = f"ceph fs volume info {fs_name} --format json" + if kwargs.get("human_readable"): + fs_info_cmd += " --human-readable" + + out, _ = client.exec_command(sudo=True, cmd=fs_info_cmd) + fs_info = json.loads(out) + return fs_info + def get_fs_details(self, client, **kwargs): """ Gets all filesystems information @@ -5098,6 +5117,24 @@ def get_mds_config(self, client, fs_name): mds_config = parsed_data.get("mdsmap") return mds_config + def get_fs_status_dump(self, client, **kwargs): + """ + Gets the overall info about fs + Args: + client: client node + **kwargs: + vol_name : Name of the fs volume for which we need the status + Return: + returns ceph fs ls dump in json format + """ + fs_status_cmd = "ceph fs status" + if kwargs.get("vol_name"): + fs_status_cmd += f" {kwargs.get('vol_name')}" + fs_status_cmd += " --format json" + out, rc = client.exec_command(sudo=True, cmd=fs_status_cmd) + fs_status = json.loads(out) + return fs_status + def get_mds_standby_replay_pair(self, client, fs_name, mds_config): mds_pair_info = {} for mds in mds_config: @@ -5279,3 +5316,338 @@ def remove_subvolume_earmark(self, client, vol_name, subvol_name, group_name=Non log.info(f"Earmark removed for subvolume: {out}") log.info(f"Eearmark removed for subvolume:[{subvol_name}] successful") return 0 + def get_fs_dump(self, client): + """ + Gets the dump output of fs + Args: + client: client node + Return: + returns ceph fs dump in json format + """ + fs_dump_cmd = "ceph fs dump --format json" + out, _ = client.exec_command(sudo=True, cmd=fs_dump_cmd) + fs_dump_output = json.loads(out) + return fs_dump_output + + def fetch_value_from_json_output(self, **kwargs): + """ + Recursive function to iteratively check the nested list of dictionaries + Args: + search_list: Accepts lists, list of dictionary + match_key: Provide a match_key, match_value pair to select the list that is expected from multiple list + match_value: Provide a match_key, match_value pair to select the list that is expected from multiple list + target_key: To figure out the value of particular key + Return: + If success, returns the value of the target_key + If no key found, return None + Usage: + fetch_value_from_json_output(search_list=[{node1: "node1", node2: "node2"}], match_key="name", match_value="cephfs1", target_key="status") + Explanation: This will basically try to fetch the list where the value of "name" matches with ".*cephfs1.*" from the search_list and gives us the value of key "status" from the list + """ + if all(value is not None for value in kwargs.values()): + for item in kwargs.get("search_list"): + if isinstance(item, dict): + # If 'name' exists and matches partially, return the desired key + if kwargs.get("match_value") in item.get( + kwargs.get("match_key"), "" + ): + return item.get(kwargs.get("target_key")) + + if ( + kwargs.get("target_key") == "fs_name" + and kwargs.get("target_key") in item + and any( + kwargs.get("match_value") + in info_item.get(kwargs.get("match_key"), "") + for info_item in item["info"].values() + ) + ): + return item["fs_name"] + + if ( + kwargs.get("target_key") == "id" + and kwargs.get("target_key") in item + and any( + kwargs.get("match_value") + in info_item.get(kwargs.get("match_key"), "") + for info_item in item["mdsmap"]["info"].values() + ) + ): + return item["id"] + + # Traverse nested dictionaries + for value in item.values(): + if isinstance(value, (dict, list)): + result = self.fetch_value_from_json_output( + search_list=( + [value] if isinstance(value, dict) else value + ), + match_key=kwargs.get("match_key"), + match_value=kwargs.get("match_value"), + target_key=kwargs.get("target_key"), + ) + if result is not None: + return result + return None + else: + return log.error( + "One or more values are none. Expected Key-Value pair: search_list, match_key, match_value, target_key" + ) + + def collect_fs_status_data_for_validation(self, client, fs_name): + """ + Gets the output using fs status and collect required info + Args: + client: client node + fs_name: File system name + Return: + returns status,data_avail,data_used,meta_avail,meta_used and mds name from ceph fs status in dict format + """ + fs_status_dict = {} + fs_status_info = self.get_fs_status_dump(client) + log.debug(f"Output: {fs_status_info}") + + status = self.fetch_value_from_json_output( + search_list=fs_status_info["mdsmap"], + match_key="name", + match_value=fs_name, + target_key="state", + ) + data_avail = self.fetch_value_from_json_output( + search_list=fs_status_info["pools"], + match_key="name", + match_value=fs_name + ".data", + target_key="avail", + ) + data_used = self.fetch_value_from_json_output( + search_list=fs_status_info["pools"], + match_key="name", + match_value=fs_name + ".data", + target_key="used", + ) + meta_avail = self.fetch_value_from_json_output( + search_list=fs_status_info["pools"], + match_key="name", + match_value=fs_name + ".meta", + target_key="avail", + ) + meta_used = self.fetch_value_from_json_output( + search_list=fs_status_info["pools"], + match_key="name", + match_value=fs_name + ".meta", + target_key="used", + ) + for entry in fs_status_info["mdsmap"]: + for key, value in entry.items(): + if key == "state" and value == "active" and fs_name in entry["name"]: + mds_name = entry["name"] + + fs_status_dict.update( + { + "status": status, + "data_avail": data_avail, + "data_used": data_used, + "meta_avail": meta_avail, + "meta_used": meta_used, + "mds_name": mds_name, + } + ) + return fs_status_dict + + def collect_fs_volume_info_for_validation(self, client, fs_name): + """ + Gets the output using fs volume info and collected required info + Args: + client: client node + fs_name: File system name + Return: + returns data_avail,data_used,meta_avail,meta_used and mon addrs from ceph fs volume info in dict format + """ + fs_volume_info_dict = {} + fs_vol_info = self.get_fs_info_dump(client, fs_name, human_readable=False) + log.debug(f"Output: {fs_vol_info}") + + data_avail = self.fetch_value_from_json_output( + search_list=[fs_vol_info], + match_key="name", + match_value=fs_name + ".data", + target_key="avail", + ) + data_used = self.fetch_value_from_json_output( + search_list=[fs_vol_info], + match_key="name", + match_value=fs_name + ".data", + target_key="used", + ) + meta_avail = self.fetch_value_from_json_output( + search_list=[fs_vol_info], + match_key="name", + match_value=fs_name + ".meta", + target_key="avail", + ) + meta_used = self.fetch_value_from_json_output( + search_list=[fs_vol_info], + match_key="name", + match_value=fs_name + ".meta", + target_key="used", + ) + mon_addrs = fs_vol_info["mon_addrs"] + + fs_volume_info_dict.update( + { + "data_avail": data_avail, + "data_used": data_used, + "meta_avail": meta_avail, + "meta_used": meta_used, + "mon_addrs": mon_addrs, + } + ) + return fs_volume_info_dict + + def collect_fs_dump_for_validation(self, client, fs_name): + """ + Gets the output using fs dump and collected required info + Args: + client: client node + fs_name: File system name + Return: + returns status, fs_name, fsid, rank and mds name from ceph fs dump in dict format + """ + fs_dump_info_dict = {} + fs_dump = self.get_fs_dump(client) + log.debug(fs_dump) + + status = ( + self.fetch_value_from_json_output( + search_list=fs_dump["filesystems"], + match_key="name", + match_value=fs_name, + target_key="state", + ) + ).split(":", 1)[1] + fsname = self.fetch_value_from_json_output( + search_list=fs_dump["filesystems"], + match_key="name", + match_value=fs_name, + target_key="fs_name", + ) + fsid = self.fetch_value_from_json_output( + search_list=fs_dump["filesystems"], + match_key="name", + match_value=fs_name, + target_key="id", + ) + rank = self.fetch_value_from_json_output( + search_list=fs_dump["filesystems"], + match_key="name", + match_value=fs_name, + target_key="rank", + ) + mds_name = self.fetch_value_from_json_output( + search_list=fs_dump["filesystems"], + match_key="name", + match_value=fs_name, + target_key="name", + ) + + fs_dump_info_dict.update( + { + "status": status, + "fsname": fsname, + "fsid": fsid, + "rank": rank, + "mds_name": mds_name, + } + ) + return fs_dump_info_dict + + def collect_fs_get_for_validation(self, client, fs_name): + """ + Gets the output using fs get and collected required info + Args: + client: client node + fs_name: File system name + Return: + returns status, fs_name, fsid, rank and mds name from ceph fs get in dict format + """ + fs_get_info_dict = {} + fs_get_output = self.get_fsmap(client, fs_name) + log.debug(fs_get_output) + + status = ( + self.fetch_value_from_json_output( + search_list=[fs_get_output], + match_key="name", + match_value=fs_name, + target_key="state", + ) + ).split(":", 1)[1] + fsname = self.fetch_value_from_json_output( + search_list=[fs_get_output], + match_key="name", + match_value=fs_name, + target_key="fs_name", + ) + fsid = self.fetch_value_from_json_output( + search_list=[fs_get_output], + match_key="name", + match_value=fs_name, + target_key="id", + ) + rank = self.fetch_value_from_json_output( + search_list=[fs_get_output], + match_key="name", + match_value=fs_name, + target_key="rank", + ) + mds_name = self.fetch_value_from_json_output( + search_list=[fs_get_output], + match_key="name", + match_value=fs_name, + target_key="name", + ) + + fs_get_info_dict.update( + { + "status": status, + "fsname": fsname, + "fsid": fsid, + "rank": rank, + "mds_name": mds_name, + } + ) + return fs_get_info_dict + + def validate_dicts(self, dicts, keys_to_check): + """ + Validate values of specific keys across multiple dictionaries. + + Parameters: + dicts (list): List of dictionaries to compare. + keys_to_check (list): List of keys to check for validation. + + Returns: + dict: Validation results for each key. + """ + + for key in keys_to_check: + # Find dictionaries that contain the key + dicts_with_key = [d for d in dicts if key in d] + + if len(dicts_with_key) == 0: + log.error(f"Key '{key}' not found in any dictionary") + return False + elif len(dicts_with_key) == 1: + log.error(f"Key '{key}' found in only one dictionary, cannot validate") + return False + else: + # Compare values of the key across the dictionaries + values = set(d[key] for d in dicts_with_key) + if len(values) == 1: + log.info( + f"Key '{key}' validated across {len(dicts_with_key)} dictionaries with the value {values}" + ) + else: + log.error(f"Key '{key}' mismatch: Values = {values}") + return False + return True diff --git a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py new file mode 100644 index 00000000000..6c72cc7aa68 --- /dev/null +++ b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py @@ -0,0 +1,307 @@ +import json +import random +import string +import time +import traceback + +from ceph.ceph import CommandFailed +from tests.cephfs.cephfs_utilsV1 import FsUtils +from utility.log import Log +from utility.retry import retry + +log = Log(__name__) + + +def run(ceph_cluster, **kw): + """ + Test Cases Covered: + CEPH-83604097 - Basic info validation after volume creation and deletion + + Pre-requisites : + 1. We need atleast one client node to execute this test case + + Test Case Flow: + 1. Create a file system with default value + 2. Validate the volume creation using ceph fs status, ceph fs volume info , ceph fs dump, ceph fs get + 3. Create second volume cephfs2 + 4. Validate volume is created by following validation step 2 + 5. Delete second volume without "--yes-i-really-mean-it" + 6. Delete second volume by having typo in "--yes-i-really-mean-it" + 7. Delete second volume with "--yes-i-really-mean-it" + 8. Validate the commands mentioned in point2 + 9. Delete cephfs1 + """ + + def update_dict_from_b_gb(input_dict, keys_to_be_converted): + """ + Checks for the specified keys and convert the Bytes to GB for validation + + Parameters: + input_dict (dict): Dictionary to consider the keys + keys_to_be_converted (list): List of keys whose values need to converted + + Returns: + dict: Returns dict with the updated value + """ + for keys_bytes in keys_to_be_converted: + if keys_bytes in input_dict: + input_dict[keys_bytes] = ( + f"{round(int(input_dict[keys_bytes]) / (1024 ** 3), 1)}G" # Convert to GB and round to 1 decimal places + ) + return input_dict + + try: + tc = "CEPH-83604097" + log.info(f"Running CephFS tests for BZ-{tc}") + test_data = kw.get("test_data") + fs_util = FsUtils(ceph_cluster, test_data=test_data) + config = kw.get("config") + build = config.get("build", config.get("rhbuild")) + clients = ceph_cluster.get_ceph_objects("client") + client1 = clients[0] + fs_util.auth_list([client1]) + fs_util.prepare_clients(clients, build) + rand = "".join( + random.choice(string.ascii_lowercase + string.digits) + for _ in list(range(5)) + ) + + log.info("checking Pre-requisites") + if not clients: + log.error( + f"This test requires minimum 1 client nodes.This has only {len(clients)} clients" + ) + return 1 + + fs_name_1 = f"cephfs_83604097_1_{rand}" + fs_name_2 = f"cephfs_83604097_2_{rand}" + + log.info( + "\n" + "\n---------------***************-------------------------------------------------------" + "\n Scenario 1: Create a File System and Validate from different command output" + "\n---------------***************-------------------------------------------------------" + "\n" + ) + + # Creation of FS + fs_util.create_fs(client1, fs_name_1) + fs_util.wait_for_mds_process(client1, fs_name_1) + + # Get ceph fs volume info of specific volume + fs_volume_dict = fs_util.collect_fs_volume_info_for_validation( + client1, fs_name_1 + ) + keys_to_convert = ["data_avail", "meta_avail", "data_used", "meta_used"] + fs_volume_dict = update_dict_from_b_gb(fs_volume_dict, keys_to_convert) + log.debug(f"Output of FS_1 volume: {fs_volume_dict}") + + # Get ceph fs dump output + fs_dump_dict = fs_util.collect_fs_dump_for_validation(client1, fs_name_1) + log.debug(f"Output of FS_1 dump: {fs_dump_dict}") + + # Get ceph fs get of specific volume + fs_get_dict = fs_util.collect_fs_get_for_validation(client1, fs_name_1) + log.debug(f"Output of FS_1 get: {fs_get_dict}") + + # Get ceph fs status + fs_status_dict = fs_util.collect_fs_status_data_for_validation( + client1, fs_name_1 + ) + fs_status_dict = update_dict_from_b_gb(fs_status_dict, keys_to_convert) + log.debug(f"Output of FS_1 status: {fs_status_dict}") + + # Validation + keys_to_be_validated = [ + "status", + "fsname", + "fsid", + "rank", + "mds_name", + "data_avail", + "data_used", + "meta_avail", + "meta_used", + ] + rc = fs_util.validate_dicts( + [fs_status_dict, fs_volume_dict, fs_dump_dict, fs_get_dict], + keys_to_be_validated, + ) + + if rc: + log.info(f"Validation of {fs_name_1} is successsful") + else: + log.error(f"Validation of {fs_name_1} failed") + return 1 + + log.info( + "\n" + "\n---------------***************---------------" + "\n Scenario 1 Completed Successfully " + "\n---------------***************---------------" + "\n" + ) + + log.info( + "\n" + "\n---------------***************---------------------------------------------------------" + "\n Scenario 2: Create 2nd File System and Validate from different command output" + "\n---------------***************---------------------------------------------------------" + "\n" + ) + + # Creation of 2nd FS + fs_util.create_fs(client1, fs_name_2) + fs_util.wait_for_mds_process(client1, fs_name_2) + + # Get ceph fs volume info of specific volume + fs_volume_dict_2 = fs_util.collect_fs_volume_info_for_validation( + client1, fs_name_2 + ) + fs_volume_dict_2 = update_dict_from_b_gb(fs_volume_dict_2, keys_to_convert) + log.debug(f"Output of FS_2 volume: {fs_volume_dict_2}") + + # Get ceph fs dump output + fs_dump_dict_2 = fs_util.collect_fs_dump_for_validation(client1, fs_name_2) + log.debug(f"Output of FS_2 dump: {fs_dump_dict_2}") + + # Get ceph fs get of specific volume + fs_get_dict_2 = fs_util.collect_fs_get_for_validation(client1, fs_name_2) + log.debug(f"Output of FS_2 get: {fs_get_dict_2}") + + # Get ceph fs status + fs_status_dict_2 = fs_util.collect_fs_status_data_for_validation( + client1, fs_name_2 + ) + fs_status_dict_2 = update_dict_from_b_gb(fs_status_dict_2, keys_to_convert) + log.debug(f"Output of FS_2 status: {fs_status_dict_2}") + + # Validation + keys_to_be_validated = [ + "status", + "fsname", + "fsid", + "rank", + "mds_name", + "data_avail", + "data_used", + "meta_avail", + "meta_used", + ] + rc = fs_util.validate_dicts( + [fs_status_dict_2, fs_volume_dict_2, fs_dump_dict_2, fs_get_dict_2], + keys_to_be_validated, + ) + + if rc: + log.info(f"Validation of {fs_name_2} is successsful") + else: + log.error(f"Validation of {fs_name_2} failed") + return 1 + log.info( + "\n" + "\n---------------***************---------------" + "\n Scenario 2 Completed Successfully " + "\n---------------***************---------------" + "\n" + ) + log.info( + "\n" + "\n---------------***************---------------------------------------------------------" + "\n Scenario 3: Delete 2nd File System using negative testing" + "\n---------------***************---------------------------------------------------------" + "\n" + ) + + client1.exec_command( + sudo=True, cmd="ceph config set mon mon_allow_pool_delete true" + ) + + test_commands = [ + f"ceph fs volume rm {fs_name_2}", + f"ceph fs volume rm {fs_name_2} --yes-i-really-men-it", + f"ceph fs volume rm {fs_name_2} -yes-i-really-mean-it", + f"ceph fs volume rm {fs_name_2} --yes-i-rally-mean-it", + ] + for fail_cmd in test_commands: + try: + client1.exec_command(sudo=True, cmd=fail_cmd) + # Handling the error gracefully. Expected to fail + except Exception as e: + log.info(f"Exception: {fail_cmd} is expected to fail") + log.info(f"Error: {e}") + log.info( + "\n" + "\n---------------***************---------------" + "\n Scenario 3 Completed Successfully " + "\n---------------***************---------------" + "\n" + ) + + # log.info( + # "\n" + # "\n---------------***************---------------------------------------------------------------" + # "\n Scenario 4: Delete 2nd File System and validate the result based on previous result" + # "\n---------------***************---------------------------------------------------------------" + # "\n" + # ) + # fs_util.remove_fs(client1, fs_name_2) + + # # Get ceph fs volume info of specific volume + # fs_volume_dict_3 = fs_util.collect_fs_volume_info_for_validation(client1, fs_name_1) + # fs_volume_dict_3 = update_dict_from_b_gb(fs_volume_dict_3, keys_to_convert) + # log.info(f"Dict: {fs_volume_dict_3}") + + # # Get ceph fs dump output + # fs_dump_dict_3 = fs_util.collect_fs_dump_for_validation(client1, fs_name_1) + # log.info(f"Dict: {fs_dump_dict_3}") + + # # Get ceph fs get of specific volume + # fs_get_dict_3 = fs_util.collect_fs_get_for_validation(client1, fs_name_1) + # log.info(f"Dict: {fs_get_dict_3}") + + # #Get ceph fs status + # fs_status_dict_3 = fs_util.collect_fs_status_data_for_validation(client1, fs_name_1) + # fs_status_dict_3 = update_dict_from_b_gb(fs_status_dict_3, keys_to_convert) + # log.info(f"Dict: {fs_status_dict_3}") + + # # Excluding the validation of mds_name, data_avail, meta avail + # # Following it up with dev folks + # # To be updated validation list: validation_list = ["fs_status_dict == fs_status_dict_3", "fs_volume_dict == fs_volume_dict_3", "fs_dump_dict == fs_dump_dict_3", "fs_get_dict == fs_get_dict_3"] + # fs_dump_dict.pop("mds_name", None) + # fs_dump_dict_3.pop("mds_name", None) + # fs_get_dict.pop("mds_name", None) + # fs_get_dict_3.pop("mds_name", None) + + # log.info(f"fs_volume_dict: {fs_volume_dict}") + # log.info(f"fs_volume_dict_3: {fs_volume_dict_3}") + # log.info(f"fs_dump_dict: {fs_dump_dict}") + # log.info(f"fs_dump_dict_3: {fs_dump_dict_3}") + # log.info(f"fs_get_dict: {fs_get_dict}") + # log.info(f"fs_get_dict_3: {fs_get_dict_3}") + + # validation_list = ["fs_volume_dict == fs_volume_dict_3", "fs_dump_dict == fs_dump_dict_3", "fs_get_dict == fs_get_dict_3"] + # for val in validation_list: + # if eval(val): + # log.info("Values are identical even after adding and deleting a volume") + # else: + # log.error(f"Values are not identical for dict {val}") + # return 1 + + # log.info( + # "\n" + # "\n---------------***************---------------" + # "\n Scenario 4 Completed Successfully " + # "\n---------------***************---------------" + # "\n" + # ) + return 0 + except Exception as e: + log.error(e) + log.error(traceback.format_exc()) + return 1 + + finally: + fs_util.remove_fs(client1, fs_name_1) + fs_util.remove_fs(client1, fs_name_2) + return 0 From 34541c24aae78ad024a441037d1a39bb5ca6d9e6 Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Sun, 22 Dec 2024 13:48:33 -0500 Subject: [PATCH 22/50] fix validating mon addrs Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- tests/cephfs/cephfs_utilsV1.py | 33 ++++++++++++++----- .../cephfs_vol_mgmt_test_volume.py | 25 ++++---------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/tests/cephfs/cephfs_utilsV1.py b/tests/cephfs/cephfs_utilsV1.py index 0e5a474eb94..0a1039b70c3 100644 --- a/tests/cephfs/cephfs_utilsV1.py +++ b/tests/cephfs/cephfs_utilsV1.py @@ -5620,7 +5620,7 @@ def collect_fs_get_for_validation(self, client, fs_name): def validate_dicts(self, dicts, keys_to_check): """ - Validate values of specific keys across multiple dictionaries. + Validate values of specific keys across multiple dictionaries and dictionary of list. Parameters: dicts (list): List of dictionaries to compare. @@ -5641,13 +5641,28 @@ def validate_dicts(self, dicts, keys_to_check): log.error(f"Key '{key}' found in only one dictionary, cannot validate") return False else: - # Compare values of the key across the dictionaries - values = set(d[key] for d in dicts_with_key) - if len(values) == 1: - log.info( - f"Key '{key}' validated across {len(dicts_with_key)} dictionaries with the value {values}" - ) + # Collect values for the key + values = [d[key] for d in dicts_with_key] + + # Check if values are lists + if all(isinstance(v, list) for v in values): + # Compare list contents + if all(sorted(v) == sorted(values[0]) for v in values): + log.info( + f"Key '{key}' validated across {len(dicts_with_key)} dictionaries with the list value {values[0]}" + ) + else: + log.error(f"Key '{key}' mismatch: List values = {values}") + return False else: - log.error(f"Key '{key}' mismatch: Values = {values}") - return False + # Compare values of the key across the dictionaries + # Rewriting values using set for single value + values = set(d[key] for d in dicts_with_key) + if len(values) == 1: + log.info( + f"Key '{key}' validated across {len(dicts_with_key)} dictionaries with the value {values}" + ) + else: + log.error(f"Key '{key}' mismatch: Values = {values}") + return False return True diff --git a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py index 6c72cc7aa68..68a9efa2b38 100644 --- a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py +++ b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py @@ -1,10 +1,7 @@ -import json import random import string -import time import traceback -from ceph.ceph import CommandFailed from tests.cephfs.cephfs_utilsV1 import FsUtils from utility.log import Log from utility.retry import retry @@ -75,6 +72,8 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): fs_name_1 = f"cephfs_83604097_1_{rand}" fs_name_2 = f"cephfs_83604097_2_{rand}" + mon_node_ips = {"mon_addrs": fs_util.get_mon_node_ips()} + log.info(mon_node_ips) log.info( "\n" @@ -94,6 +93,7 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): ) keys_to_convert = ["data_avail", "meta_avail", "data_used", "meta_used"] fs_volume_dict = update_dict_from_b_gb(fs_volume_dict, keys_to_convert) + fs_volume_dict['mon_addrs'] = [addr.replace(':6789', '') for addr in fs_volume_dict['mon_addrs']] log.debug(f"Output of FS_1 volume: {fs_volume_dict}") # Get ceph fs dump output @@ -122,9 +122,10 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): "data_used", "meta_avail", "meta_used", + "mon_addrs" ] rc = fs_util.validate_dicts( - [fs_status_dict, fs_volume_dict, fs_dump_dict, fs_get_dict], + [fs_status_dict, fs_volume_dict, fs_dump_dict, fs_get_dict, mon_node_ips], keys_to_be_validated, ) @@ -159,6 +160,7 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): client1, fs_name_2 ) fs_volume_dict_2 = update_dict_from_b_gb(fs_volume_dict_2, keys_to_convert) + fs_volume_dict_2['mon_addrs'] = [addr.replace(':6789', '') for addr in fs_volume_dict_2['mon_addrs']] log.debug(f"Output of FS_2 volume: {fs_volume_dict_2}") # Get ceph fs dump output @@ -176,20 +178,8 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): fs_status_dict_2 = update_dict_from_b_gb(fs_status_dict_2, keys_to_convert) log.debug(f"Output of FS_2 status: {fs_status_dict_2}") - # Validation - keys_to_be_validated = [ - "status", - "fsname", - "fsid", - "rank", - "mds_name", - "data_avail", - "data_used", - "meta_avail", - "meta_used", - ] rc = fs_util.validate_dicts( - [fs_status_dict_2, fs_volume_dict_2, fs_dump_dict_2, fs_get_dict_2], + [fs_status_dict_2, fs_volume_dict_2, fs_dump_dict_2, fs_get_dict_2, mon_node_ips], keys_to_be_validated, ) @@ -295,7 +285,6 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): # "\n---------------***************---------------" # "\n" # ) - return 0 except Exception as e: log.error(e) log.error(traceback.format_exc()) From c4b6d23104bd8f35862f911e4abd6776c0c349ae Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Mon, 23 Dec 2024 01:40:31 -0500 Subject: [PATCH 23/50] fix tox issue Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- tests/cephfs/cephfs_utilsV1.py | 1 + .../cephfs_vol_mgmt_test_volume.py | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/cephfs/cephfs_utilsV1.py b/tests/cephfs/cephfs_utilsV1.py index 0a1039b70c3..2e1e9154413 100644 --- a/tests/cephfs/cephfs_utilsV1.py +++ b/tests/cephfs/cephfs_utilsV1.py @@ -5316,6 +5316,7 @@ def remove_subvolume_earmark(self, client, vol_name, subvol_name, group_name=Non log.info(f"Earmark removed for subvolume: {out}") log.info(f"Eearmark removed for subvolume:[{subvol_name}] successful") return 0 + def get_fs_dump(self, client): """ Gets the dump output of fs diff --git a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py index 68a9efa2b38..04aa087d448 100644 --- a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py +++ b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py @@ -4,7 +4,6 @@ from tests.cephfs.cephfs_utilsV1 import FsUtils from utility.log import Log -from utility.retry import retry log = Log(__name__) @@ -93,7 +92,9 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): ) keys_to_convert = ["data_avail", "meta_avail", "data_used", "meta_used"] fs_volume_dict = update_dict_from_b_gb(fs_volume_dict, keys_to_convert) - fs_volume_dict['mon_addrs'] = [addr.replace(':6789', '') for addr in fs_volume_dict['mon_addrs']] + fs_volume_dict["mon_addrs"] = [ + addr.replace(":6789", "") for addr in fs_volume_dict["mon_addrs"] + ] log.debug(f"Output of FS_1 volume: {fs_volume_dict}") # Get ceph fs dump output @@ -122,7 +123,7 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): "data_used", "meta_avail", "meta_used", - "mon_addrs" + "mon_addrs", ] rc = fs_util.validate_dicts( [fs_status_dict, fs_volume_dict, fs_dump_dict, fs_get_dict, mon_node_ips], @@ -160,7 +161,9 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): client1, fs_name_2 ) fs_volume_dict_2 = update_dict_from_b_gb(fs_volume_dict_2, keys_to_convert) - fs_volume_dict_2['mon_addrs'] = [addr.replace(':6789', '') for addr in fs_volume_dict_2['mon_addrs']] + fs_volume_dict_2["mon_addrs"] = [ + addr.replace(":6789", "") for addr in fs_volume_dict_2["mon_addrs"] + ] log.debug(f"Output of FS_2 volume: {fs_volume_dict_2}") # Get ceph fs dump output @@ -179,7 +182,13 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): log.debug(f"Output of FS_2 status: {fs_status_dict_2}") rc = fs_util.validate_dicts( - [fs_status_dict_2, fs_volume_dict_2, fs_dump_dict_2, fs_get_dict_2, mon_node_ips], + [ + fs_status_dict_2, + fs_volume_dict_2, + fs_dump_dict_2, + fs_get_dict_2, + mon_node_ips, + ], keys_to_be_validated, ) From 45e56ec1833ce28e9896678bb89e0b87d163ba87 Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Mon, 23 Dec 2024 02:14:04 -0500 Subject: [PATCH 24/50] fix tox issue Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- tests/cephfs/cephfs_utilsV1.py | 9 ++++--- .../cephfs_vol_mgmt_test_volume.py | 25 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/cephfs/cephfs_utilsV1.py b/tests/cephfs/cephfs_utilsV1.py index 2e1e9154413..681e666f8d9 100644 --- a/tests/cephfs/cephfs_utilsV1.py +++ b/tests/cephfs/cephfs_utilsV1.py @@ -5342,8 +5342,10 @@ def fetch_value_from_json_output(self, **kwargs): If success, returns the value of the target_key If no key found, return None Usage: - fetch_value_from_json_output(search_list=[{node1: "node1", node2: "node2"}], match_key="name", match_value="cephfs1", target_key="status") - Explanation: This will basically try to fetch the list where the value of "name" matches with ".*cephfs1.*" from the search_list and gives us the value of key "status" from the list + fetch_value_from_json_output(search_list=[{node1: "node1", node2: "node2"}], + match_key="name", match_value="cephfs1", target_key="status") + Explanation: This will basically try to fetch the list where the value of "name" matches with + ".*cephfs1.*" from the search_list and gives us the value of key "status" from the list """ if all(value is not None for value in kwargs.values()): for item in kwargs.get("search_list"): @@ -5650,7 +5652,8 @@ def validate_dicts(self, dicts, keys_to_check): # Compare list contents if all(sorted(v) == sorted(values[0]) for v in values): log.info( - f"Key '{key}' validated across {len(dicts_with_key)} dictionaries with the list value {values[0]}" + f"Key '{key}' validated across {len(dicts_with_key)} + dictionaries with the list value {values[0]}" ) else: log.error(f"Key '{key}' mismatch: List values = {values}") diff --git a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py index 04aa087d448..ea55c7564d7 100644 --- a/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py +++ b/tests/cephfs/cephfs_vol_management/cephfs_vol_mgmt_test_volume.py @@ -18,7 +18,8 @@ def run(ceph_cluster, **kw): Test Case Flow: 1. Create a file system with default value - 2. Validate the volume creation using ceph fs status, ceph fs volume info , ceph fs dump, ceph fs get + 2. Validate the volume creation using ceph fs status, ceph fs volume info , ceph fs dump, + ceph fs get 3. Create second volume cephfs2 4. Validate volume is created by following validation step 2 5. Delete second volume without "--yes-i-really-mean-it" @@ -42,7 +43,8 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): for keys_bytes in keys_to_be_converted: if keys_bytes in input_dict: input_dict[keys_bytes] = ( - f"{round(int(input_dict[keys_bytes]) / (1024 ** 3), 1)}G" # Convert to GB and round to 1 decimal places + f"{round(int(input_dict[keys_bytes]) / (1024 ** 3), 1)}G" + # Convert to GB and round to 1 decimal places ) return input_dict @@ -247,7 +249,9 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): # fs_util.remove_fs(client1, fs_name_2) # # Get ceph fs volume info of specific volume - # fs_volume_dict_3 = fs_util.collect_fs_volume_info_for_validation(client1, fs_name_1) + # fs_volume_dict_3 = fs_util.collect_fs_volume_info_for_validation( + # client1, fs_name_1 + # ) # fs_volume_dict_3 = update_dict_from_b_gb(fs_volume_dict_3, keys_to_convert) # log.info(f"Dict: {fs_volume_dict_3}") @@ -259,14 +263,17 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): # fs_get_dict_3 = fs_util.collect_fs_get_for_validation(client1, fs_name_1) # log.info(f"Dict: {fs_get_dict_3}") - # #Get ceph fs status - # fs_status_dict_3 = fs_util.collect_fs_status_data_for_validation(client1, fs_name_1) + # # Get ceph fs status + # fs_status_dict_3 = fs_util.collect_fs_status_data_for_validation( + # client1, fs_name_1 + # ) # fs_status_dict_3 = update_dict_from_b_gb(fs_status_dict_3, keys_to_convert) # log.info(f"Dict: {fs_status_dict_3}") # # Excluding the validation of mds_name, data_avail, meta avail # # Following it up with dev folks - # # To be updated validation list: validation_list = ["fs_status_dict == fs_status_dict_3", "fs_volume_dict == fs_volume_dict_3", "fs_dump_dict == fs_dump_dict_3", "fs_get_dict == fs_get_dict_3"] + # # To be updated validation list: validation_list = ["fs_status_dict == fs_status_dict_3", + # "fs_volume_dict == fs_volume_dict_3", "fs_dump_dict == fs_dump_dict_3", "fs_get_dict == fs_get_dict_3"] # fs_dump_dict.pop("mds_name", None) # fs_dump_dict_3.pop("mds_name", None) # fs_get_dict.pop("mds_name", None) @@ -279,7 +286,11 @@ def update_dict_from_b_gb(input_dict, keys_to_be_converted): # log.info(f"fs_get_dict: {fs_get_dict}") # log.info(f"fs_get_dict_3: {fs_get_dict_3}") - # validation_list = ["fs_volume_dict == fs_volume_dict_3", "fs_dump_dict == fs_dump_dict_3", "fs_get_dict == fs_get_dict_3"] + # validation_list = [ + # "fs_volume_dict == fs_volume_dict_3", + # "fs_dump_dict == fs_dump_dict_3", + # "fs_get_dict == fs_get_dict_3", + # ] # for val in validation_list: # if eval(val): # log.info("Values are identical even after adding and deleting a volume") From 896425ef6f77b476d6ff8996b882983ade1958b3 Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Mon, 23 Dec 2024 02:18:36 -0500 Subject: [PATCH 25/50] fix tox issue - new line character Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- tests/cephfs/cephfs_utilsV1.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cephfs/cephfs_utilsV1.py b/tests/cephfs/cephfs_utilsV1.py index 681e666f8d9..ed68aac6277 100644 --- a/tests/cephfs/cephfs_utilsV1.py +++ b/tests/cephfs/cephfs_utilsV1.py @@ -5342,9 +5342,9 @@ def fetch_value_from_json_output(self, **kwargs): If success, returns the value of the target_key If no key found, return None Usage: - fetch_value_from_json_output(search_list=[{node1: "node1", node2: "node2"}], + fetch_value_from_json_output(search_list=[{node1: "node1", node2: "node2"}], match_key="name", match_value="cephfs1", target_key="status") - Explanation: This will basically try to fetch the list where the value of "name" matches with + Explanation: This will basically try to fetch the list where the value of "name" matches with ".*cephfs1.*" from the search_list and gives us the value of key "status" from the list """ if all(value is not None for value in kwargs.values()): @@ -5652,7 +5652,7 @@ def validate_dicts(self, dicts, keys_to_check): # Compare list contents if all(sorted(v) == sorted(values[0]) for v in values): log.info( - f"Key '{key}' validated across {len(dicts_with_key)} + f"Key '{key}' validated across {len(dicts_with_key)} \ dictionaries with the list value {values[0]}" ) else: From d940c5923ada353c69b96e1fd916dae0d5816c14 Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Mon, 23 Dec 2024 03:34:28 -0500 Subject: [PATCH 26/50] fix test suite Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- .../cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml | 6 ++++++ .../cephfs/tier-2_cephfs_test-volume-management.yaml | 11 +++++------ .../cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml | 6 ++++++ .../cephfs/tier-2_cephfs_test-volume-management.yaml | 11 +++++------ .../cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml | 12 ++++++++++++ .../tier-2_cephfs_test-volume-management_arch.yaml | 6 ------ 6 files changed, 34 insertions(+), 18 deletions(-) diff --git a/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml index 3a5ac1ef37f..cf5bef9db89 100644 --- a/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml +++ b/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml @@ -476,3 +476,9 @@ tests: module: cephfs_nfs.nfs_multiple_export_using_single_conf.py name: "nfs_multiple_export_using_single_conf" polarion-id: "CEPH-83575082" + - test: + name: Basic info validation after volume creation and deletion + module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py + polarion-id: CEPH-83604097 + desc: Basic info validation after volume creation and deletion + abort-on-fail: true \ No newline at end of file diff --git a/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml b/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml index 4b69b731293..44a5ba854a9 100644 --- a/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml +++ b/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml @@ -29,7 +29,6 @@ # CEPH-83571330: Test FS volume deletion when mon_allow_pool_delete is false. # CEPH-11333: CephFS volume management - FS life cycle. # CEPH-83603354 - volume related scenarios(delete,rename) -# CEPH-83604097 - Basic info validation after volume creation and deletion #=============================================================================================== tests: - test: @@ -351,8 +350,8 @@ tests: desc: volume related scenarios(delete,rename) abort-on-fail: false - test: - name: Basic info validation after volume creation and deletion - module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py - polarion-id: CEPH-83604097 - desc: Basic info validation after volume creation and deletion - abort-on-fail: true \ No newline at end of file + name: cephfs subvolumegroup scenarios + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_scenarios.py + polarion-id: CEPH-83604079 + desc: cephfs subvolumegroup scenarios + abort-on-fail: false \ No newline at end of file diff --git a/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml index 3a5ac1ef37f..cf5bef9db89 100644 --- a/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml +++ b/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml @@ -476,3 +476,9 @@ tests: module: cephfs_nfs.nfs_multiple_export_using_single_conf.py name: "nfs_multiple_export_using_single_conf" polarion-id: "CEPH-83575082" + - test: + name: Basic info validation after volume creation and deletion + module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py + polarion-id: CEPH-83604097 + desc: Basic info validation after volume creation and deletion + abort-on-fail: true \ No newline at end of file diff --git a/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml b/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml index 1ce0441ddd6..e5690c313e8 100644 --- a/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml +++ b/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml @@ -26,7 +26,6 @@ # CEPH-83573428 - cephfs_vol_mgmt_volume_with_exist_names # CEPH-83574188 - Testing auto-cleanup cephfs subvolume after creation failure # CEPH-83603354 - volume related scenarios(delete,rename) -# CEPH-83604097 - Basic info validation after volume creation and deletion #=============================================================================================== tests: - test: @@ -348,8 +347,8 @@ tests: desc: volume related scenarios(delete,rename) abort-on-fail: false - test: - name: Basic info validation after volume creation and deletion - module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py - polarion-id: CEPH-83604097 - desc: Basic info validation after volume creation and deletion - abort-on-fail: true \ No newline at end of file + name: cephfs subvolumegroup scenarios + module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_scenarios.py + polarion-id: CEPH-83604079 + desc: cephfs subvolumegroup scenarios + abort-on-fail: false \ No newline at end of file diff --git a/suites/squid/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/squid/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml index 3a5ac1ef37f..e2465b896ad 100644 --- a/suites/squid/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml +++ b/suites/squid/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml @@ -476,3 +476,15 @@ tests: module: cephfs_nfs.nfs_multiple_export_using_single_conf.py name: "nfs_multiple_export_using_single_conf" polarion-id: "CEPH-83575082" + - test: + name: cephfs subvolume idempoence earmark + module: cephfs_vol_management.cephfs_vol_mgmt_subvol_idempotence_earmark.py + polarion-id: CEPH-83604184 + desc: cephfs subvolume idempoence earmark + abort-on-fail: false + - test: + name: Basic info validation after volume creation and deletion + module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py + polarion-id: CEPH-83604097 + desc: Basic info validation after volume creation and deletion + abort-on-fail: true diff --git a/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml b/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml index e353999849f..dd57879135b 100644 --- a/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml +++ b/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml @@ -359,9 +359,3 @@ tests: polarion-id: CEPH-83604184 desc: cephfs subvolume idempoence earmark abort-on-fail: false - - test: - name: Basic info validation after volume creation and deletion - module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py - polarion-id: CEPH-83604097 - desc: Basic info validation after volume creation and deletion - abort-on-fail: true From 186365c6fa904cc3201d4371536522630e0cc66c Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Mon, 23 Dec 2024 03:47:30 -0500 Subject: [PATCH 27/50] fix new line EOF Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml | 2 +- suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml | 2 +- suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml | 2 +- suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml | 2 +- .../squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml index cf5bef9db89..ca1ae6c5ff7 100644 --- a/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml +++ b/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml @@ -481,4 +481,4 @@ tests: module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py polarion-id: CEPH-83604097 desc: Basic info validation after volume creation and deletion - abort-on-fail: true \ No newline at end of file + abort-on-fail: true diff --git a/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml b/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml index 44a5ba854a9..8401082d211 100644 --- a/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml +++ b/suites/quincy/cephfs/tier-2_cephfs_test-volume-management.yaml @@ -354,4 +354,4 @@ tests: module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_scenarios.py polarion-id: CEPH-83604079 desc: cephfs subvolumegroup scenarios - abort-on-fail: false \ No newline at end of file + abort-on-fail: false diff --git a/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml index cf5bef9db89..ca1ae6c5ff7 100644 --- a/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml +++ b/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml @@ -481,4 +481,4 @@ tests: module: cephfs_vol_management.cephfs_vol_mgmt_test_volume.py polarion-id: CEPH-83604097 desc: Basic info validation after volume creation and deletion - abort-on-fail: true \ No newline at end of file + abort-on-fail: true diff --git a/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml b/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml index e5690c313e8..ba91789483f 100644 --- a/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml +++ b/suites/reef/cephfs/tier-2_cephfs_test-volume-management.yaml @@ -351,4 +351,4 @@ tests: module: cephfs_vol_management.cephfs_vol_mgmt_subvolgroup_scenarios.py polarion-id: CEPH-83604079 desc: cephfs subvolumegroup scenarios - abort-on-fail: false \ No newline at end of file + abort-on-fail: false diff --git a/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml b/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml index dd57879135b..7f41334ba61 100644 --- a/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml +++ b/suites/squid/cephfs/tier-2_cephfs_test-volume-management_arch.yaml @@ -26,7 +26,6 @@ # CEPH-83573428 - cephfs_vol_mgmt_volume_with_exist_names # CEPH-83574188 - Testing auto-cleanup cephfs subvolume after creation failure # CEPH-83603354 - volume related scenarios(delete,rename) -# CEPH-83604097 - Basic info validation after volume creation and deletion #=============================================================================================== tests: - test: From 09e0a8a67ab1f63a731a6ee017196b37cfddf4dc Mon Sep 17 00:00:00 2001 From: Manimaran M Date: Mon, 23 Dec 2024 04:14:48 -0500 Subject: [PATCH 28/50] fix suite name and script Signed-off-by: Manimaran M Signed-off-by: Harishacharya-redhat --- ... => tier-2_file-dir-lay_vol-mgmt_nfs.yaml} | 0 ... => tier-2_file-dir-lay_vol-mgmt_nfs.yaml} | 0 ... => tier-2_file-dir-lay_vol-mgmt_nfs.yaml} | 0 .../fs_del_allow_pool_false.py | 23 +++++++++++-------- 4 files changed, 13 insertions(+), 10 deletions(-) rename suites/quincy/cephfs/{teir-2_file-dir-lay_vol-mgmt_nfs.yaml => tier-2_file-dir-lay_vol-mgmt_nfs.yaml} (100%) rename suites/reef/cephfs/{teir-2_file-dir-lay_vol-mgmt_nfs.yaml => tier-2_file-dir-lay_vol-mgmt_nfs.yaml} (100%) rename suites/squid/cephfs/{teir-2_file-dir-lay_vol-mgmt_nfs.yaml => tier-2_file-dir-lay_vol-mgmt_nfs.yaml} (100%) diff --git a/suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/quincy/cephfs/tier-2_file-dir-lay_vol-mgmt_nfs.yaml similarity index 100% rename from suites/quincy/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml rename to suites/quincy/cephfs/tier-2_file-dir-lay_vol-mgmt_nfs.yaml diff --git a/suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/reef/cephfs/tier-2_file-dir-lay_vol-mgmt_nfs.yaml similarity index 100% rename from suites/reef/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml rename to suites/reef/cephfs/tier-2_file-dir-lay_vol-mgmt_nfs.yaml diff --git a/suites/squid/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml b/suites/squid/cephfs/tier-2_file-dir-lay_vol-mgmt_nfs.yaml similarity index 100% rename from suites/squid/cephfs/teir-2_file-dir-lay_vol-mgmt_nfs.yaml rename to suites/squid/cephfs/tier-2_file-dir-lay_vol-mgmt_nfs.yaml diff --git a/tests/cephfs/cephfs_vol_management/fs_del_allow_pool_false.py b/tests/cephfs/cephfs_vol_management/fs_del_allow_pool_false.py index 9b6dc0cc54d..968757e65f1 100644 --- a/tests/cephfs/cephfs_vol_management/fs_del_allow_pool_false.py +++ b/tests/cephfs/cephfs_vol_management/fs_del_allow_pool_false.py @@ -1,6 +1,5 @@ import traceback -from ceph.ceph import CommandFailed from tests.cephfs.cephfs_utilsV1 import FsUtils from utility.log import Log @@ -36,23 +35,27 @@ def run(ceph_cluster, **kw): client1 = clients[0] cephfs_name = "cephfs_new" fs_util.create_fs(client1, cephfs_name) + client1.exec_command( sudo=True, cmd="ceph config set mon mon_allow_pool_delete false" ) - out, rc = fs_util.remove_fs( - client1, cephfs_name, validate=False, check_ec=False - ) - if rc == 0: - raise CommandFailed( + rmvolume_cmd = f"ceph fs volume rm {cephfs_name} --yes-i-really-mean-it" + + try: + client1.exec_command(sudo=True, cmd=rmvolume_cmd) + log.error( "We are able to delete filesystems even after setting mon_allow_pool_delete to false" ) - log.info( - "We are not able to delete filesystems even after setting mon_allow_pool_delete to false as expected" - ) - return 0 + return 1 + # Handling the error gracefully. Expected to fail + except Exception as e: + log.info(f"Exception: {rmvolume_cmd} is expected to fail") + log.info(f"Error: {e}") + except Exception as e: log.info(e) log.info(traceback.format_exc()) return 1 finally: fs_util.remove_fs(client1, cephfs_name, validate=True, check_ec=False) + return 0 From 4a2750fcbb8da0672b9ca6bbb84e191bf7c4bc53 Mon Sep 17 00:00:00 2001 From: Srinivasa Bharath Kanta Date: Mon, 23 Dec 2024 20:03:34 -0500 Subject: [PATCH 29/50] [TFA-Fix]- Reducing the execution time of scheduled scrub test suite Signed-off-by: Srinivasa Bharath Kanta Signed-off-by: Harishacharya-redhat --- .../rados/tier-2_rados_test-scrubbing.yaml | 7 ++ .../rados/tier-2_rados_test-scrubbing.yaml | 8 +- .../rados/tier-2_rados_test-scrubbing.yaml | 8 +- .../rados/tier-2_rados_test-scrubbing.yaml | 10 ++- tests/rados/scheduled_scrub_scenarios.py | 73 ++++++++++++++++--- 5 files changed, 92 insertions(+), 14 deletions(-) diff --git a/suites/pacific/rados/tier-2_rados_test-scrubbing.yaml b/suites/pacific/rados/tier-2_rados_test-scrubbing.yaml index 9daf98f2b1f..f946dd96025 100644 --- a/suites/pacific/rados/tier-2_rados_test-scrubbing.yaml +++ b/suites/pacific/rados/tier-2_rados_test-scrubbing.yaml @@ -102,6 +102,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "default" + debug_enable: False delete_pools: - scrub_pool @@ -116,6 +117,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "begin_end_time_equal" + debug_enable: False delete_pools: - scrub_pool - test: @@ -129,6 +131,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "beginTime gt endTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -142,6 +145,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "beginTime gt endTime lt currentTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -155,6 +159,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "beginTime and endTime gt currentTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -168,6 +173,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "decreaseTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -181,5 +187,6 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "unsetScrub" + debug_enable: False delete_pools: - scrub_pool diff --git a/suites/quincy/rados/tier-2_rados_test-scrubbing.yaml b/suites/quincy/rados/tier-2_rados_test-scrubbing.yaml index 403edbd5f64..202d5ad34b1 100644 --- a/suites/quincy/rados/tier-2_rados_test-scrubbing.yaml +++ b/suites/quincy/rados/tier-2_rados_test-scrubbing.yaml @@ -102,6 +102,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "default" + debug_enable: False delete_pools: - scrub_pool @@ -116,6 +117,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "begin_end_time_equal" + debug_enable: False delete_pools: - scrub_pool @@ -130,6 +132,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "beginTime gt endTime" + debug_enable: False delete_pools: - scrub_pool @@ -144,6 +147,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "beginTime gt endTime lt currentTime" + debug_enable: False delete_pools: - scrub_pool @@ -158,9 +162,9 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "beginTime and endTime gt currentTime" + debug_enable: False delete_pools: - scrub_pool - comments: Active Bug#2312538 - test: name: Decrease scrub time polarion-id: CEPH-9371 @@ -172,6 +176,7 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "decreaseTime" + debug_enable: False delete_pools: - scrub_pool @@ -186,5 +191,6 @@ tests: pool_name: scrub_pool pg_num: 1 scenario: "unsetScrub" + debug_enable: False delete_pools: - scrub_pool diff --git a/suites/reef/rados/tier-2_rados_test-scrubbing.yaml b/suites/reef/rados/tier-2_rados_test-scrubbing.yaml index 64ef648c527..a316d103ff9 100644 --- a/suites/reef/rados/tier-2_rados_test-scrubbing.yaml +++ b/suites/reef/rados/tier-2_rados_test-scrubbing.yaml @@ -117,6 +117,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "default" + debug_enable: False delete_pools: - scrub_pool - test: @@ -131,6 +132,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "begin_end_time_equal" + debug_enable: False delete_pools: - scrub_pool - test: @@ -145,6 +147,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "beginTime gt endTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -159,6 +162,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "beginTime gt endTime lt currentTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -173,9 +177,9 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "beginTime and endTime gt currentTime" + debug_enable: False delete_pools: - scrub_pool - comments: Active Bug#2312538 - test: name: Decrease scrub time polarion-id: CEPH-9371 @@ -188,6 +192,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "decreaseTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -202,6 +207,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "unsetScrub" + debug_enable: False delete_pools: - scrub_pool diff --git a/suites/squid/rados/tier-2_rados_test-scrubbing.yaml b/suites/squid/rados/tier-2_rados_test-scrubbing.yaml index 893a881d1d9..2757c22f0a6 100644 --- a/suites/squid/rados/tier-2_rados_test-scrubbing.yaml +++ b/suites/squid/rados/tier-2_rados_test-scrubbing.yaml @@ -1,6 +1,6 @@ # Suite contains tests for replica-1 non-resilient pool # conf: conf/squid/rados/7-node-cluster.yaml -# RHOS-d run duration: 700 mins +# RHOS-d run duration: 200 mins # move from tier-2 to tier-3 and move to weekly tests: @@ -121,6 +121,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "default" + debug_enable: False delete_pools: - scrub_pool - test: @@ -135,6 +136,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "begin_end_time_equal" + debug_enable: False delete_pools: - scrub_pool - test: @@ -149,6 +151,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "beginTime gt endTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -163,6 +166,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "beginTime gt endTime lt currentTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -177,9 +181,9 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "beginTime and endTime gt currentTime" + debug_enable: False delete_pools: - scrub_pool - comments: Active Bug#2312538 - test: name: Decrease scrub time polarion-id: CEPH-9371 @@ -192,6 +196,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "decreaseTime" + debug_enable: False delete_pools: - scrub_pool - test: @@ -206,6 +211,7 @@ tests: pg_num: 1 disable_pg_autoscale: true scenario: "unsetScrub" + debug_enable: False delete_pools: - scrub_pool diff --git a/tests/rados/scheduled_scrub_scenarios.py b/tests/rados/scheduled_scrub_scenarios.py index bbdc8cbdc1f..cc993daa2fb 100644 --- a/tests/rados/scheduled_scrub_scenarios.py +++ b/tests/rados/scheduled_scrub_scenarios.py @@ -18,9 +18,9 @@ def run(ceph_cluster, **kw): - osd_scrub_min_interval = 60 - osd_scrub_max_interval = 3600 - osd_deep_scrub_interval = 3600 + osd_scrub_min_interval = 10 + osd_scrub_max_interval = 300 + osd_deep_scrub_interval = 300 log.info(run.__doc__) config = kw["config"] @@ -29,16 +29,22 @@ def run(ceph_cluster, **kw): mon_obj = MonConfigMethods(rados_obj=rados_obj) test_scenarios = ["scrub", "deep-scrub"] + # test_scenarios = ["deep-scrub"] for test_input in test_scenarios: # Creating replicated pool rp_config = config.get("replicated_pool") pool_name = rp_config["pool_name"] + log.info(f"===Start the validation of the {test_input}=======") + if config.get("debug_enable"): + log.info("Set the OSD logs to 20") + mon_obj.set_config(section="osd", name="debug_osd", value="20/20") if not rados_obj.create_pool(name=pool_name, **rp_config): log.error("Failed to create the Pool") return 1 - rados_obj.bench_write(pool_name=pool_name, rados_write_duration=10) + rados_obj.bench_write(pool_name=pool_name, byte_size="5K", max_objs=200) + # rados_obj.bench_write(pool_name=, rados_write_duration=5) pg_id = rados_obj.get_pgid(pool_name=pool_name) log.info(f"The pg id is -{pg_id}") flag = wait_for_clean_pg_sets(rados_obj) @@ -47,6 +53,12 @@ def run(ceph_cluster, **kw): "The cluster did not reach active + Clean state after add capacity" ) return 1 + leader_mon_daemon = rados_obj.run_ceph_command(cmd="ceph mon stat")["leader"] + mon_host = rados_obj.fetch_host_node( + daemon_type="mon", daemon_id=leader_mon_daemon + ) + init_time, _ = mon_host.exec_command(cmd="date '+%Y-%m-%d %H:%M:%S'", sudo=True) + log.info(f"The cluster time before testing is - {init_time}") try: ( scrub_begin_hour, @@ -85,10 +97,7 @@ def run(ceph_cluster, **kw): # set begin hour and end hour greater than current time # CEPH-9367 & CEPH 9368 - if ( - config.get("scenario") == "beginTime and endTime gt currentTime" - or config.get("scenario") == "decreaseTime" - ): + if config.get("scenario") == "beginTime and endTime gt currentTime": ( scrub_begin_hour, scrub_begin_weekday, @@ -98,6 +107,10 @@ def run(ceph_cluster, **kw): log.info( f'{"Setting scrub start is greater then end_hour and current time is greater than end hour"}' ) + osd_scrub_min_interval = 86400 + osd_scrub_max_interval = 604800 + osd_deep_scrub_interval = 604800 + # unset the scrub.CEPH-9374 if config.get("scenario") == "unsetScrub": rados_obj.set_osd_flags("set", "noscrub") @@ -141,7 +154,14 @@ def run(ceph_cluster, **kw): ) rados_obj.set_osd_configuration("osd_scrub_end_hour", scrub_end_hour) + # Printing the scrub parameter values + get_parameter_configuration(mon_obj) status = chk_scrub_or_deepScrub_status(rados_obj, test_input, pg_id[-1]) + end_time, _ = mon_host.exec_command( + cmd="date '+%Y-%m-%d %H:%M:%S'", sudo=True + ) + log.info(f"The cluster time after testing is - {end_time}") + # Checking the failure case if status is False and ( config.get("scenario") == "default" @@ -159,6 +179,7 @@ def run(ceph_cluster, **kw): ) and status is True: log.info(f"{test_input} validation Failed") return 1 + log.info(f"Deletion of the pool after the {test_input} validation") method_should_succeed(rados_obj.delete_pool, pool_name) time.sleep(10) flag = wait_for_clean_pg_sets(rados_obj) @@ -167,6 +188,7 @@ def run(ceph_cluster, **kw): "The cluster did not reach active + Clean state after add capacity" ) return 1 + log.info(f"===End of the validation of the {test_input}=======") except Exception as err: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] @@ -179,11 +201,18 @@ def run(ceph_cluster, **kw): log.info( "\n \n ************** Execution of finally block begins here *************** \n \n" ) + mon_obj.remove_config(section="osd", name="debug_osd") method_should_succeed(rados_obj.delete_pool, pool_name) remove_parameter_configuration(mon_obj) rados_obj.set_osd_flags("unset", "noscrub") rados_obj.set_osd_flags("unset", "nodeep-scrub") time.sleep(10) + flag = wait_for_clean_pg_sets(rados_obj) + if not flag: + log.error( + "The cluster did not reach active + Clean state after add capacity" + ) + return 1 # log cluster health rados_obj.log_cluster_health() log.error(f'{"Schedule scrub & deep-scrub validation success"}') @@ -220,7 +249,7 @@ def chk_scrub_or_deepScrub_status(rados_object, action, pg_id): if action == "scrub": try: status = rados_object.start_check_scrub_complete( - pg_id=pg_id, user_initiated=False, wait_time=5400 + pg_id=pg_id, user_initiated=False, wait_time=900 ) log.info("Verification of the scrub is completed") except Exception as err: @@ -229,10 +258,34 @@ def chk_scrub_or_deepScrub_status(rados_object, action, pg_id): else: try: status = rados_object.start_check_deep_scrub_complete( - pg_id=pg_id, user_initiated=False, wait_time=5400 + pg_id=pg_id, user_initiated=False, wait_time=900 ) log.info("Verification of the deep-scrub is completed") except Exception as err: log.error(f"The error is-{err}") status = False return status + + +def get_parameter_configuration(mon_obj): + """ + Used to get the osd scrub parameter change values + Args: + mon_obj: monitor object + Returns : None + """ + log.info("The scrub parameter values are: ") + out_put = mon_obj.get_config(section="osd", param="osd_scrub_min_interval") + log.info(f"The osd_scrub_min_interval parameter value is - {out_put}") + out_put = mon_obj.get_config(section="osd", param="osd_scrub_max_interval") + log.info(f"The osd_scrub_max_interval parameter value is - {out_put}") + out_put = mon_obj.get_config(section="osd", param="osd_deep_scrub_interval") + log.info(f"The osd_deep_scrub_interval parameter value is - {out_put}") + out_put = mon_obj.get_config(section="osd", param="osd_scrub_begin_week_day") + log.info(f"The osd_scrub_begin_week_day parameter value is - {out_put}") + out_put = mon_obj.get_config(section="osd", param="osd_scrub_end_week_day") + log.info(f"The osd_scrub_end_week_day parameter value is - {out_put}") + out_put = mon_obj.get_config(section="osd", param="osd_scrub_begin_hour") + log.info(f"The osd_scrub_begin_hour parameter value is - {out_put}") + out_put = mon_obj.get_config(section="osd", param="osd_scrub_end_hour") + log.info(f"The osd_scrub_end_hour parameter value is - {out_put}") From 8cbb13c5432a493c55fdb025f62c4e93e5dee908 Mon Sep 17 00:00:00 2001 From: Harsh Kumar Date: Tue, 24 Dec 2024 09:47:13 +0530 Subject: [PATCH 30/50] [RADOS] Add ceph-bluestore-tool coverage for live OSDs Signed-off-by: Harsh Kumar Signed-off-by: Harishacharya-redhat --- tests/rados/test_bluestoretool_workflows.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/rados/test_bluestoretool_workflows.py b/tests/rados/test_bluestoretool_workflows.py index e93336c98e3..c1d680f9bf8 100644 --- a/tests/rados/test_bluestoretool_workflows.py +++ b/tests/rados/test_bluestoretool_workflows.py @@ -51,6 +51,7 @@ def run(ceph_cluster, **kw): cephadm = CephAdmin(cluster=ceph_cluster, **config) rados_obj = RadosOrchestrator(node=cephadm) bluestore_obj = BluestoreToolWorkflows(node=cephadm) + bluestore_obj_live = BluestoreToolWorkflows(node=cephadm, nostop=True) client = ceph_cluster.get_nodes(role="client")[0] bench_obj = RadosBench(mon_node=cephadm, clients=client) service_obj = ServiceabilityMethods(cluster=ceph_cluster, **config) @@ -552,9 +553,19 @@ def run(ceph_cluster, **kw): assert "device size" in out and "Expanding" in out # Execute ceph-bluestore-tool show-label + osd_id = random.choice(osd_list) log.info( f"\n --------------------" - f"\n Dump label content for block device for OSD {osd_id}" + f"\n Dump label content for block device for live OSD {osd_id}" + f"\n --------------------" + ) + out = bluestore_obj_live.show_label(osd_id=osd_id) + log.info(out) + assert f"/var/lib/ceph/osd/ceph-{osd_id}/" in out + + log.info( + f"\n --------------------" + f"\n Dump label content for block device for stopped OSD {osd_id}" f"\n --------------------" ) out = bluestore_obj.show_label(osd_id=osd_id) @@ -601,6 +612,8 @@ def run(ceph_cluster, **kw): f"that can start up a BlueStore OSD for OSD {osd_id}" f"\n --------------------" ) + out = bluestore_obj_live.generate_prime_osd_dir(osd_id=osd_id, device=dev) + log.info(out) out = bluestore_obj.generate_prime_osd_dir(osd_id=osd_id, device=dev) log.info(out) From c97b59693bf5bac2902d874b7e89ff6e8038f419 Mon Sep 17 00:00:00 2001 From: Harsh Kumar Date: Thu, 26 Dec 2024 11:18:34 +0530 Subject: [PATCH 31/50] TFA fix for ceph-volume workflow & variable type casting Signed-off-by: Harsh Kumar Signed-off-by: Harishacharya-redhat --- tests/rados/test_cephdf.py | 10 +++++++--- tests/rados/test_cephvolume_workflows.py | 6 +----- tests/rados/test_replica1.py | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/rados/test_cephdf.py b/tests/rados/test_cephdf.py index c38f1f37aa9..8e4898cf69b 100644 --- a/tests/rados/test_cephdf.py +++ b/tests/rados/test_cephdf.py @@ -354,9 +354,13 @@ def bytes_to_gb(val): for node in ["node12", "node13"]: # create 10G LVMs on backup nodes node_obj = node12_obj if node == "node12" else node13_obj - empty_devices = rados_obj.get_available_devices( - node_name=node_obj.hostname, device_type="hdd" - ) + for _ in range(3): + empty_devices = rados_obj.get_available_devices( + node_name=node_obj.hostname, device_type="hdd" + ) + if empty_devices: + break + time.sleep(15) if len(empty_devices) < 1: log.error( f"Need at least 1 spare disk available on host {node_obj.hostname}" diff --git a/tests/rados/test_cephvolume_workflows.py b/tests/rados/test_cephvolume_workflows.py index fd06e23ede5..bd5a889b530 100644 --- a/tests/rados/test_cephvolume_workflows.py +++ b/tests/rados/test_cephvolume_workflows.py @@ -52,11 +52,9 @@ def run(ceph_cluster, **kw): volumeobject = CephVolumeWorkflows(node=cephadm) try: - if config.get("zap_with_destroy_flag") or config.get( "zap_without_destroy_flag" ): - options_list = [ ["device"], ["osd_id"], @@ -70,7 +68,6 @@ def run(ceph_cluster, **kw): options_list = [option + ["--destroy"] for option in options_list] for option in options_list: - if ( config.get("zap_without_destroy_flag") and len(option) == 1 @@ -193,7 +190,6 @@ def run(ceph_cluster, **kw): ) if config.get("zap_without_destroy_flag"): - log.info( f"Proceeding to check if file system is removed from OSD {osd_id}" ) @@ -320,7 +316,7 @@ def run(ceph_cluster, **kw): host=osd_host, ) - wait_for_osd_daemon_state(osd_host, osd_id, "up") + wait_for_osd_daemon_state(rados_obj.client, osd_id, "up") log.info( f"Successfully added back osd {osd_id} to cluster\n" diff --git a/tests/rados/test_replica1.py b/tests/rados/test_replica1.py index c0458edf950..f3ceb9b3b3e 100644 --- a/tests/rados/test_replica1.py +++ b/tests/rados/test_replica1.py @@ -89,7 +89,7 @@ class for all others. # divide OSDs into different device classes(replicated) replicated_osd = " ".join( - [osd_id for osd_id in osd_list if int(osd_id) % 2 != 0] + [str(osd_id) for osd_id in osd_list if int(osd_id) % 2 != 0] ) cephadm.shell( [f"ceph osd crush set-device-class replicated {replicated_osd}"] From c82da923ad80c85632eab704950779546409e858 Mon Sep 17 00:00:00 2001 From: julpark Date: Mon, 23 Dec 2024 14:59:26 -0800 Subject: [PATCH 32/50] adding tier-1 kernel suite to squid Signed-off-by: julpark Signed-off-by: Harishacharya-redhat --- suites/squid/cephfs/tier-1_fs_kernel.yaml | 235 ++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 suites/squid/cephfs/tier-1_fs_kernel.yaml diff --git a/suites/squid/cephfs/tier-1_fs_kernel.yaml b/suites/squid/cephfs/tier-1_fs_kernel.yaml new file mode 100644 index 00000000000..ad6f7ce32db --- /dev/null +++ b/suites/squid/cephfs/tier-1_fs_kernel.yaml @@ -0,0 +1,235 @@ +tests: + - test: + name: setup install pre-requisistes + desc: Setup phase to deploy the required pre-requisites for running the tests. + module: install_prereq.py + abort-on-fail: true + - test: + name: cluster deployment + desc: Deploy cluster with enforcing mode(default mode). + module: test_cephadm.py + polarion-id: CEPH-83573740 + config: + verify_cluster_health: true + steps: + - config: + command: bootstrap + service: cephadm + base_cmd_args: + verbose: true + args: + registry-url: registry.redhat.io + mon-ip: node1 + orphan-initial-daemons: true + skip-monitoring-stack: true + - config: + command: add_hosts + service: host + args: + attach_ip_address: true + labels: apply-all-labels + - config: + command: apply + service: mgr + args: + placement: + label: mgr + - config: + command: apply + service: mon + args: + placement: + label: mon + - config: + command: apply + service: osd + args: + all-available-devices: true + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - volume + - create + - cephfs + - config: + command: shell + args: + - ceph + - osd + - pool + - create + - cephfs-data-ec + - "64" + - erasure + - config: + command: shell + args: + - ceph + - osd + - pool + - create + - cephfs-metadata + - "64" + - config: + command: shell + args: + - ceph + - osd + - pool + - set + - cephfs-data-ec + - allow_ec_overwrites + - "true" + - config: + command: shell + args: # arguments to ceph orch + - ceph + - fs + - new + - cephfs-ec + - cephfs-metadata + - cephfs-data-ec + - --force + - config: + command: apply + service: mds + base_cmd_args: # arguments to ceph orch + verbose: true + pos_args: + - cephfs # name of the filesystem + args: + placement: + label: mds + - config: + args: + - ceph + - fs + - set + - cephfs + - max_mds + - "2" + command: shell + destroy-cluster: false + abort-on-fail: true + - test: + abort-on-fail: true + desc: "kernel update for CephFS kernel bugs" + module: kernel_update.py + name: kernel update + polarion-id: "CEPH-83575404" + - test: + abort-on-fail: true + config: + command: add + id: client.1 + node: node8 + install_packages: + - ceph-common + copy_admin_keyring: true + desc: Configure the Cephfs client system 1 + destroy-cluster: false + module: test_client.py + name: configure client + - test: + abort-on-fail: true + config: + command: add + id: client.2 + node: node9 + install_packages: + - ceph-common + copy_admin_keyring: true + desc: Configure the Cephfs client system 2 + destroy-cluster: false + module: test_client.py + name: configure client + - test: + abort-on-fail: true + config: + command: add + id: client.3 + node: node10 + install_packages: + - ceph-common + copy_admin_keyring: true + desc: Configure the Cephfs client system 3 + destroy-cluster: false + module: test_client.py + name: configure client + - test: + abort-on-fail: true + config: + command: add + id: client.4 + node: node11 + install_packages: + - ceph-common + copy_admin_keyring: true + desc: Configure the Cephfs client system 4 + destroy-cluster: false + module: test_client.py + name: configure client + - test: + name: Run fsstress on kernel and fuse mounts + module: cephfs_bugs.test_fsstress_on_kernel_and_fuse.py + polarion-id: CEPH-83575623 + desc: Run fsstress on kernel and fuse mounts + abort-on-fail: false + - test: + name: Run xfs test on kernel + module: xfs_test.py + polarion-id: CEPH-83575623 + desc: Run xfs test on kernel + abort-on-fail: false + - test: + name: cephfs_volume_management + module: cephfs_volume_management.py + polarion-id: CEPH-83573445 + desc: cephfs volume management + abort-on-fail: false + - test: + name: cephfs_snapshot_management + module: cephfs_snapshot_management.py + polarion-id: CEPH-83571366 + desc: cephfs snapshot management + abort-on-fail: false + - test: + name: cephfs_tier1_ops + module: cephfs_tier1_ops.py + polarion-id: CEPH-83573447 + desc: cephfs tier1 operations + abort-on-fail: false + - test: + name: cephfs_client_authorize + module: client_authorize.py + polarion-id: CEPH-83574483 + desc: client authorize test for cephfs + abort-on-fail: false + - test: + name: cephfs-mdsfailover-pinning-io + module: dir_pinning.py + config: + num_of_dirs: 200 + polarion-id: CEPH-11227 + desc: MDSfailover on active-active mdss,performing client IOs with no pinning at the first,later pin 10 dirs with IOs + abort-on-fail: false + - test: + name: cephfs subvolume authorize test + desc: Test cephfs subvolume client authorize + module: subvolume_authorize.py + polarion-id: CEPH-83574596 + abort-on-fail: false + - test: + name: no recover session mount + module: no_recover_session_mount.py + polarion-id: CEPH-11260 + desc: test no recover session mount by blocking the client node + abort-on-fail: false + - test: + name: Clone Operations + module: bug-1980920.py + desc: Cancel the clone operation and validate error message + polarion-id: CEPH-83574681 + abort-on-fail: false From 147710674b00fe3725bf20d6f413dec42727256e Mon Sep 17 00:00:00 2001 From: Vidushi Mishra Date: Fri, 27 Dec 2024 10:48:06 +0530 Subject: [PATCH 33/50] Fixing the TFA in reef for rgw accounts and adding support for topic creation in account Signed-off-by: Vidushi Mishra Signed-off-by: Harishacharya-redhat --- suites/squid/rgw/tier-2_rgw_regression_extended.yaml | 7 ++++--- tests/rgw/test_s3.py | 10 ++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/suites/squid/rgw/tier-2_rgw_regression_extended.yaml b/suites/squid/rgw/tier-2_rgw_regression_extended.yaml index 1722b620ffc..55ec9040822 100644 --- a/suites/squid/rgw/tier-2_rgw_regression_extended.yaml +++ b/suites/squid/rgw/tier-2_rgw_regression_extended.yaml @@ -249,11 +249,12 @@ tests: - test: abort-on-fail: false config: - role: "client" commands: - - "radosgw-admin account create --account-id RGW11111111111111111 --account-name Account1 --email account1@ceph.com" - "radosgw-admin account create --account-id RGW22222222222222222 --account-name Account2 --email account2@ceph.com" - + - "radosgw-admin account create --account-id RGW11111111111111111 --account-name Account1 --email account1@ceph.com" + - "radosgw-admin zone modify --enable-feature notification_v2" + - "radosgw-admin zonegroup modify --enable-feature notification_v2" + - "ceph orch restart rgw.rgw.1" desc: Create 2 rgw accounts module: exec.py name: Create 2 rgw accounts diff --git a/tests/rgw/test_s3.py b/tests/rgw/test_s3.py index 6bede6a2690..1892654e7b0 100644 --- a/tests/rgw/test_s3.py +++ b/tests/rgw/test_s3.py @@ -351,6 +351,7 @@ def create_s3_user(node: CephNode, user_prefix: str, data: Dict) -> None: """ uid = binascii.hexlify(os.urandom(32)).decode() display_name = f"{user_prefix}-user" + log.info(f" the display name is {display_name} ") log.info("Creating user: {display_name}".format(display_name=display_name)) if display_name == "iamrootalt-user": cmd = ( @@ -371,7 +372,7 @@ def create_s3_user(node: CephNode, user_prefix: str, data: Dict) -> None: out, err = node.exec_command(sudo=True, cmd=cmd) user_info = json.loads(out) - + log.info(f" the user info for {display_name} is {user_info} ") data[user_prefix] = { "id": user_info["keys"][0]["user"], "access_key": user_info["keys"][0]["access_key"], @@ -379,7 +380,7 @@ def create_s3_user(node: CephNode, user_prefix: str, data: Dict) -> None: "name": user_info["display_name"], "email": user_info["email"], } - if display_name == "iamrootalt-user" or "iamroot-user": + if display_name in ("iamrootalt-user", "iamroot-user"): data[user_prefix] = { "id": user_info["keys"][0]["user"], "access_key": user_info["keys"][0]["access_key"], @@ -429,8 +430,9 @@ def create_s3_conf( create_s3_user(node=rgw_node, user_prefix="alt", data=data) create_s3_user(node=rgw_node, user_prefix="tenant", data=data) create_s3_user(node=rgw_node, user_prefix="iam", data=data) - create_s3_user(node=rgw_node, user_prefix="iamroot", data=data) - create_s3_user(node=rgw_node, user_prefix="iamrootalt", data=data) + if build.split(".")[0] >= "8": + create_s3_user(node=rgw_node, user_prefix="iamroot", data=data) + create_s3_user(node=rgw_node, user_prefix="iamrootalt", data=data) if kms_keyid: data["main"]["kms_keyid"] = kms_keyid From 197f01d09654d916e3615785ad832ce9be323d70 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Fri, 27 Dec 2024 17:23:31 +0530 Subject: [PATCH 34/50] Addressed review comment Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat --- ceph/rbd/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ceph/rbd/utils.py b/ceph/rbd/utils.py index 575a911e8d9..191d306553a 100644 --- a/ceph/rbd/utils.py +++ b/ceph/rbd/utils.py @@ -69,7 +69,9 @@ def get_md5sum_rbd_image(**kw): log.error(f"Export failed for image {kw.get('image_spec')}") return None return exec_cmd( - output=True, cmd="md5sum {}".format(kw.get("file_path")), node=kw.get("client") + output=True, + cmd=f"md5sum {kw['file_path']} && rm -f {kw['file_path']}", + node=kw.get("client"), ).split()[0] From 6658c4d100e0e61e807099293e3575027699a596 Mon Sep 17 00:00:00 2001 From: Amarnath K Date: Fri, 27 Dec 2024 11:12:43 +0530 Subject: [PATCH 35/50] Adding cluster configs to test_parallel Signed-off-by: Amarnath K Signed-off-by: Harishacharya-redhat --- tests/parallel/test_parallel.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/parallel/test_parallel.py b/tests/parallel/test_parallel.py index 49b483973ec..2c6e7cd13ab 100644 --- a/tests/parallel/test_parallel.py +++ b/tests/parallel/test_parallel.py @@ -4,9 +4,9 @@ import importlib import logging import os +import random import string from multiprocessing import Manager -from random import random from time import sleep from ceph.ceph import CommandFailed @@ -147,6 +147,13 @@ def execute(test, args, results, parallel_tcs): # Merging configurations safely test_config = args.get("config", {}).copy() test_config.update(test.get("config", {})) + if "clusters" in test: + clusters_config = test.get("clusters", {}) + for cluster_name, cluster_data in clusters_config.items(): + # Extract and merge the cluster-specific configurations into the root + if "config" in cluster_data: + test_config.update(cluster_data["config"]) + test_logger.info(test_config) tc["name"] = test.get("name") tc["desc"] = test.get("desc") tc["log-link"] = log_url From 3e24cb565fdff79a87f666594da5c3a4d86dd5c2 Mon Sep 17 00:00:00 2001 From: Vipin M S Date: Wed, 18 Dec 2024 09:27:06 +0530 Subject: [PATCH 36/50] Improvements to monitor election strategy Signed-off-by: Vipin M S Signed-off-by: Harishacharya-redhat --- ceph/rados/monitor_workflows.py | 13 + tests/rados/monitor_configurations.py | 4 +- tests/rados/test_election_strategies.py | 567 +++++++++++++++++++++++- 3 files changed, 581 insertions(+), 3 deletions(-) diff --git a/ceph/rados/monitor_workflows.py b/ceph/rados/monitor_workflows.py index c2df33ba898..91b46537c16 100644 --- a/ceph/rados/monitor_workflows.py +++ b/ceph/rados/monitor_workflows.py @@ -260,6 +260,19 @@ def get_mon_quorum_hosts(self) -> list: quorum = self.rados_obj.run_ceph_command(cmd) return [entry["name"] for entry in quorum["quorum"]] + def get_mon_quorum(self) -> dict: + """ + Fetches mon details and returns the names of monitors present in the quorum + Returns: dictionary with mon names as keys and Rank as value + eg: {'magna045': 0, 'magna046': 1, 'magna047': 2} + """ + cmd = "ceph mon stat" + quorum = self.rados_obj.run_ceph_command(cmd, client_exec=True) + mon_members = {} + for entry in quorum["quorum"]: + mon_members.setdefault(entry["name"], entry["rank"]) + return mon_members + def set_tiebreaker_mon(self, host) -> bool: """ Sets the passed host mon as the new tiebreaker mon daemon in stretch mode diff --git a/tests/rados/monitor_configurations.py b/tests/rados/monitor_configurations.py index 79209c90c21..e58bdd457b6 100644 --- a/tests/rados/monitor_configurations.py +++ b/tests/rados/monitor_configurations.py @@ -47,7 +47,7 @@ def set_disallow_mon(self, mon): Returns: True -> Pass, False -> fail """ cmd = f" ceph mon add disallowed_leader {mon}" - self.rados_obj.node.shell([cmd]) + self.rados_obj.node.shell([cmd], pretty_print=True) # Checking if the mon is successfully added to list if mon not in self.get_disallowed_mon_list(): @@ -65,7 +65,7 @@ def remove_disallow_mon(self, mon): Returns: True -> Pass, False -> fail """ cmd = f" ceph mon rm disallowed_leader {mon}" - self.rados_obj.node.shell([cmd]) + self.rados_obj.node.shell([cmd], pretty_print=True) # Checking if the mon is successfully removed to list if mon in self.get_disallowed_mon_list(): diff --git a/tests/rados/test_election_strategies.py b/tests/rados/test_election_strategies.py index c7fc99ddb34..bdab4cf87e9 100644 --- a/tests/rados/test_election_strategies.py +++ b/tests/rados/test_election_strategies.py @@ -3,6 +3,7 @@ from ceph.ceph_admin import CephAdmin from ceph.rados.core_workflows import RadosOrchestrator +from ceph.rados.monitor_workflows import MonitorWorkflows from tests.rados.monitor_configurations import MonElectionStrategies from utility.log import Log @@ -21,6 +22,8 @@ def run(ceph_cluster, **kw): rados_obj = RadosOrchestrator(node=cephadm) mon_obj = MonElectionStrategies(rados_obj=rados_obj) installer_node = ceph_cluster.get_nodes(role="installer")[0] + mon_workflow_obj = MonitorWorkflows(node=cephadm) + rados_obj = RadosOrchestrator(node=cephadm) # Collecting the number of mons in the quorum before the test mon_init_count = len(mon_obj.get_mon_quorum().keys()) @@ -113,7 +116,42 @@ def run(ceph_cluster, **kw): ) return 1 - # Changing strategy to 2. i.e. disallowed mode + log.info( + "\n -------------------------------------------" + "\nValidating error generated when Mon is added to disallow list in classic mode" + "\n -------------------------------------------" + ) + leader_mon = mon_obj.get_mon_quorum_leader() + try: + if mon_obj.set_disallow_mon(mon=leader_mon): + log.error( + f"Mon {leader_mon} added to disallow list in classic Mode" + ) + return 1 + except Exception as e: + expected_err_msg = "Error EINVAL: You cannot disallow monitors in your current election mode" + generated_err_msg = e.args[0] + log.info( + f"\nExpected error: {expected_err_msg}" + f"\nGenerated error: {generated_err_msg}" + ) + if expected_err_msg not in generated_err_msg: + log.error( + "Expected error not in generated error when Mon added to disallow list in classic mode\n" + ) + return 1 + log.info( + "\n -------------------------------------------" + "\nSuccessfully validated expected error in generated error " + "when Mon is added to disallow list in classic mode" + "\n -------------------------------------------" + ) + + check_rank_after_mon_removal( + mon_workflow_obj=mon_workflow_obj, rados_obj=rados_obj + ) + + # # Changing strategy to 2. i.e. disallowed mode if not mon_obj.set_election_strategy(mode="disallow"): log.error("could not set election strategy to disallow mode") return 1 @@ -148,6 +186,24 @@ def run(ceph_cluster, **kw): # sleeping for 2 seconds for new elections to be triggered and new leader to be elected time.sleep(2) + add_all_mons_to_disallow_list( + mon_obj=mon_obj, mon_workflow_obj=mon_workflow_obj + ) + + disallowed_leader_checks( + mon_obj=mon_obj, + mon_workflow_obj=mon_workflow_obj, + election_strategy="classic", + ) + + check_rank_after_mon_removal( + mon_workflow_obj=mon_workflow_obj, rados_obj=rados_obj + ) + + if not mon_obj.set_election_strategy(mode="connectivity"): + log.error("could not set election strategy to connectivity mode") + return 1 + # Changing strategy to 3. i.e Connectivity mode. if not mon_obj.set_election_strategy(mode="connectivity"): log.error("could not set election strategy to connectivity mode") @@ -160,6 +216,26 @@ def run(ceph_cluster, **kw): f"Connectivity score of all daemons in the cluster: \n {mon_conn_score}" ) + add_all_mons_to_disallow_list( + mon_obj=mon_obj, mon_workflow_obj=mon_workflow_obj + ) + + disallowed_leader_checks( + mon_obj=mon_obj, + mon_workflow_obj=mon_workflow_obj, + election_strategy="classic", + ) + + disallowed_leader_checks( + mon_obj=mon_obj, + mon_workflow_obj=mon_workflow_obj, + election_strategy="disallow", + ) + + check_rank_after_mon_removal( + mon_workflow_obj=mon_workflow_obj, rados_obj=rados_obj + ) + # Changing strategy to default if not mon_obj.set_election_strategy(mode="classic"): log.error("could not set election strategy to classic mode") @@ -181,6 +257,7 @@ def run(ceph_cluster, **kw): "There are less mons in the quorum at the end than there before" ) return 1 + except Exception as e: log.error(f"Failed with exception: {e.__doc__}") log.exception(e) @@ -222,3 +299,491 @@ def check_mon_status(rados_obj, mon_obj): return False log.info(f"Mon {mon} is in healthy state: {status} | {desc}") return True + + +def add_all_mons_to_disallow_list(mon_obj, mon_workflow_obj) -> None: + """Method to validate last Mon cannot be added to disallowed leaders list + + Steps: + - Get list of all Mons from the cluster + - Add all Mons to disallowed leaders list + - Validate last allowed Mon cannot be added to disallow list + - Revert cluster back to original state by removing all Mons from disallow list + + Args: + mon_obj: object MonElectionStrategies + mon_workflow_obj: Object of MonitorWorkflows + Returns: + Raises Exception when test fails + Example: + + """ + log.info( + "\n -------------------------------------------" + "\n Starting validation:" + "\n `last allowed Mon` cannot be added to disallow list" + "\n -------------------------------------------" + ) + + mons = list(mon_workflow_obj.get_mon_quorum().keys()) + last_allowed_mon = mons.pop() + + for mon in mons: + log.info(f"Adding mon {mon} to disallow list") + if not mon_obj.set_disallow_mon(mon=mon): + raise AssertionError(f"could not add Mon {mon} to disallowed list") + log.info(f"Successfully added mon {mon} to disallow list") + + log.info( + f"Adding last remaining allowed mon {last_allowed_mon} to disallow list\n" + "Proceeding to validate error generation when last allowed mon is added to disallow list" + ) + try: + if mon_obj.set_disallow_mon(mon=last_allowed_mon): + raise AssertionError( + f"Last allowed mon {last_allowed_mon} added to disallow list" + ) + + except AssertionError as ae: + raise AssertionError(ae.args[0]) + + except Exception as e: + expected_err_msg = f"Error EINVAL: mon.{last_allowed_mon} is the only remaining allowed leader!" + generated_err_msg = e.args[0] + log.info( + f"\nExpected error: {expected_err_msg}" + f"\nGenerated error: {generated_err_msg}" + ) + if expected_err_msg not in generated_err_msg: + raise AssertionError( + "Expected error not in generated error when adding all mons to disallow list\n" + ) + log.info( + "Successfully validated all Mons cannot not be added to disallow list\n" + ) + + log.info( + "Successfully validated Last remaining Mon cannot be added to disallow list\n" + "Reverting cluster back to original state\n" + f"Proceeding to remove mons {mons} from disallow list" + ) + + for mon in mons: + log.info(f"Removing mon {mon} from disallow list") + if not mon_obj.remove_disallow_mon(mon=mon): + raise AssertionError(f"could not remove Mon {mon} from disallowed list") + log.info(f"Successfully removed Mon {mon} from disallow list") + + log.info( + "\n -------------------------------------------" + "\n Completed validation:" + "\n `last allowed Mon` cannot be added to disallow list" + "\n -------------------------------------------" + ) + + +def check_rank_after_mon_removal(mon_workflow_obj, rados_obj): + """Method to remove and add Mon back to the cluster and perform checks on Mon rank + + Steps: + - Select Monitor daemon + - Set Monitor service to unmanaged + - Remove Monitor daemon + - Add back removed Monitor daemon + - Set Monitor service to managed + - perform validations for rank change described in check_rank_change() + - Repeat steps for Monitor with least rank, middle rank and highest rank + + Args: + mon_workflow_obj: Object of MonitorWorkflows + rados_obj: Object of RadosOrchestrator + Returns: + Raises exception if any of the checks fail + Example: + check_rank_after_mon_removal(mon_workflow_obj=mon_workflow_obj, rados_obj=rados_obj) + """ + + def check_rank_change( + quorum_before_mon_removal: dict, + quorum_after_mon_removal: dict, + removed_mon_rank: str, + ) -> bool: + """Method to validate Mon ranks are updated after Mon removal and addition. + + Example: + # ceph mon dump + 0: [v2:10.0.66.26:3300/0,v1:10.0.66.26:6789/0] mon.node0 + 1: [v2:10.0.67.217:3300/0,v1:10.0.67.217:6789/0] mon.node1 + 2: [v2:10.0.67.245:3300/0,v1:10.0.67.245:6789/0] mon.node2 + 3: [v2:10.0.67.243:3300/0,v1:10.0.67.243:6789/0] mon.node3 + 4: [v2:10.0.67.220:3300/0,v1:10.0.67.220:6789/0] mon.node4 + + Method validates below scenarios based on removed_mon_rank: + + If mon.node0 is removed and added back + - all Mons with rank {1,2,3,4} should move up by 1 rank + - Mon node0 is added back with rank 4 + If Mon node2 is removed and added back + - all Mons with rank {3,4} should move up by 1 rank + - Mon node2 is added back with rank 4 + - Mons with rank {0,1} should remain as it is + If Mon node4 is removed and added back + - Ranks of Mons remain unchanged + + Args: + quorum_before_mon_removal: Mon details before removal and Addition of Mon + quorum_after_mon_removal: Mon details after removal and Addition of Mon + removed_mon_rank: Rank of Mon removed from cluster + Returns: + True: Validation completed + False: Validation failed + Usage: + check_rank_change(mons={"node1":0, "node2":1, "node3":2}, removed_mon_rank="0") + """ + + log.info( + "Starting to validate Mon rank changes" + f"Rank of Mon removed and added back: {removed_mon_rank}" + f"\nQuorum before Monitor removal: {quorum_before_mon_removal}" + f"\nQuorum after Monitor removal: {quorum_after_mon_removal}" + ) + + expected_quorum_after_mon_removal = dict() + # generate expected_quorum_after_mon_removal dict + for mon_name, mon_rank in quorum_before_mon_removal.items(): + if mon_rank == removed_mon_rank: + expected_quorum_after_mon_removal[mon_name] = ( + len(quorum_before_mon_removal) - 1 + ) + elif mon_rank > removed_mon_rank: + expected_quorum_after_mon_removal[mon_name] = ( + quorum_before_mon_removal[mon_name] - 1 + ) + else: + expected_quorum_after_mon_removal[mon_name] = quorum_before_mon_removal[ + mon_name + ] + + log.info( + f"\nExpected quorum after Monitor removal: {expected_quorum_after_mon_removal}" + ) + + for mon_name, mon_rank in quorum_after_mon_removal.items(): + if ( + quorum_after_mon_removal[mon_name] + != expected_quorum_after_mon_removal[mon_name] + ): + log.error( + "Ranks of Mons has not updated after Mon removal and addition" + f"Expected rank of removed Mon after adding it back {mon_name} " + f"=> {expected_quorum_after_mon_removal[mon_name]}" + "Current rank of removed Mon after adding it back " + f"{mon_name} => {quorum_after_mon_removal[mon_name]}" + ) + return False + + log.info( + "\nCompleted validations for Mon rank change" + f"\nQuorum before Monitor removal: {quorum_before_mon_removal}" + f"\nQuorum after Monitor removal: {quorum_after_mon_removal}" + f"\nExpected quorum after Monitor removal: {expected_quorum_after_mon_removal}" + ) + return True + + log.info( + "\n -------------------------------------------" + "\n Starting validation:" + "\n Rank update on removing and adding Mon" + "\n -------------------------------------------" + ) + + n = len(mon_workflow_obj.get_mon_quorum()) + # Selects lowest ranked Mon, middle ranked Mon and highest ranked Mon from `ceph mon dump` command + for index in [0, n // 2, -1]: + + log.info(f"Collecting details of Mon for Index {index}") + quorum_before_mon_removal = mon_workflow_obj.get_mon_quorum() + mon_names = list(quorum_before_mon_removal.keys()) + mon_name = mon_names[index] + mon_rank = quorum_before_mon_removal[mon_name] + mon_host = rados_obj.get_host_object(hostname=mon_name) + + log.info(f"Mon ranks before Mon removal: {quorum_before_mon_removal}") + log.info( + "\nValidating rank update when Mon is removed and added back" + f"\nMon name: {mon_name}" + f"\nMon rank: {mon_rank}" + ) + + if not mon_workflow_obj.set_mon_service_managed_type(unmanaged=True): + log.error("Could not set the mon service to unmanaged") + raise Exception("mon service not unmanaged error") + + log.info(f"Removing and adding Mon {mon_rank} back to cluster") + if not mon_workflow_obj.remove_mon_service(host=mon_name): + log.error("Could not remove the Data site mon daemon") + raise Exception("mon service not removed error") + + if not mon_workflow_obj.add_mon_service(host=mon_host): + log.error("Could not add mon service") + raise Exception("mon service not added error") + + if not mon_workflow_obj.set_mon_service_managed_type(unmanaged=False): + log.error("Could not set the mon service to unmanaged") + raise Exception("mon service not unmanaged error") + + quorum_after_mon_removal = mon_workflow_obj.get_mon_quorum() + + log.info(f"Mon ranks before Mon removal: {quorum_before_mon_removal}") + log.info("Proceeding to validate rank changes after Mon removal and addition") + if not check_rank_change( + quorum_before_mon_removal, quorum_after_mon_removal, mon_rank + ): + raise AssertionError("Mon ranks are not updated") + log.info( + f"Completed validation of rank changes when Mon with rank {mon_rank} is removed and added back" + ) + + log.info( + "\n -------------------------------------------" + "\n Completed validation:" + "\n Rank update on removing and adding Mon" + "\n -------------------------------------------" + ) + + +def disallowed_leader_checks(mon_obj, mon_workflow_obj, election_strategy: str) -> bool: + """Module to perform validations of election strategy changes when Mon in disallow list. + + **Note Test module not supported with classic mode, since adding Mons to disallow list is not supported + in classic mode + + Detailed test steps: + - Add lowest ranked Mon to disallowed leaders list + - Check Mon is not leader, Mon is in quorum and Mon is in disallowed leaders list + - Change election strategy + - Scenario 1: disallow -> classic + > Mon becomes leader + > Mon is part of Quorum + - Scenario 2: connectivity -> classic + > Mon becomes leader + > Mon is part of Quorum + - Scenario 3: connectivity -> disallow + > Mon does not become leader + > Mon is part of Quorum + > Mon is still in disallowed leaders list + - Switch back to previous election strategy + - Check Mon is not leader, Mon is in quorum and Mon is in disallowed leaders list + - Remove lowest ranked Mon from disallowed leaders list + - If original strategy was disallow, Check lowest ranked Mon becomes leader. + Check Mon is in Quorum and Mon is removed from disallowed leaders list + + Args: + mon_obj: Object of MonElectionStrategies + election_strategy: disallow or connectivity + mon_workflow_obj: Object of MonitorWorkflows + Example: + Scenario 1: disallow -> classic + check_disallowed_leaders_election_strategy(mon_obj, election_strategy="classic") + Scenario 2: connectivity -> classic + check_disallowed_leaders_election_strategy(mon_obj, election_strategy="classic") + Scenario 3: connectivity -> disallow + check_disallowed_leaders_election_strategy(mon_obj, election_strategy="disallow") + Returns: + None + Raises exception when tests fail + """ + + def _validations(mon, mon_election_obj, mon_workflow_obj) -> None: + """ + validation module to check below scenarios: + - Mon should not be leader + - Mon is in disallowed leaders list + - Mon is part of Quorum + Args: + mon: Monitor to perform validations + mon_election_obj: Object of MonElectionStrategies + mon_workflow_obj: Object of MonitorWorkflows + Returns: + None + Raises exception when validations fail + Usage: + _validations(mon=lowest_ranked_mon, mon_election_obj=mon_obj, mon_workflow_obj=mon_workflow_obj) + """ + log.info( + f"Validating Mon {mon} is not elected leader after adding Mon to disallow list" + ) + + leader = mon_election_obj.get_mon_quorum_leader() + if mon == leader: + raise AssertionError( + f"Mon with rank 0 [{mon}] was added to disallow list," + "but was elected as leader in disallow mode" + ) + + log.info( + f"Successfully validated Mon {mon} is not leader. Current leader is {leader}" + f"Validating Mon {mon} is part of disallowed list" + ) + + disallowed_list = mon_election_obj.get_disallowed_mon_list() + if mon not in disallowed_list: + raise AssertionError( + f"Mon with rank 0 [{mon}] was added to disallow list," + "but not present in disallow list" + ) + + log.info( + f"Successfully validated Mon {mon} is part of disallow list" + f"Validating Mon {mon} is part of Monitor quorum" + ) + + quorum = list(mon_workflow_obj.get_mon_quorum().keys()) + if mon not in quorum: + raise AssertionError( + f"Mon with rank 0 [{mon}] was added to disallow list," + "but removed from quorum" + ) + + log.info( + f"Successfully validated Mon {mon} is still part of quorum" + f"Changing election strategy to Connectivity mode" + ) + + log.info( + f"\nVerified Mon {mon} is not elected leader" + f"\nVerified Mon {mon} is part of disallowed leaders list" + f"\nVerified Mon {mon} is part of Monitor quorum" + ) + + strategies = {1: "classic", 2: "disallow", 3: "connectivity"} + original_election_strategy = strategies[mon_obj.get_election_strategy()] + + if ( + original_election_strategy == 1 + or original_election_strategy == election_strategy + ): + log.error( + "Cannot perform test in classic election strategy and" + " election strategy to switch cannot be same as current strategy" + ) + return False + + log.info( + "\n -------------------------------------------" + "\n Starting validation:" + f"\n Changing election strategy from {original_election_strategy} mode " + f"to {election_strategy} mode when lowest ranked Mon in disallowed leader list" + "\n -------------------------------------------" + ) + + lowest_ranked_mon = list(mon_workflow_obj.get_mon_quorum())[0] + + log.info(f"Adding Mon {lowest_ranked_mon} to disallowed leaders list") + if not mon_obj.set_disallow_mon(mon=lowest_ranked_mon): + log.error(f"Could not add Mon {lowest_ranked_mon} to disallow list") + return False + + log.info(f"Proceeding to perform checks on disallowed Mon {lowest_ranked_mon}") + # Check Mon is not leader, Mon is in quorum and Mon is in disallow leaders list + _validations( + mon=lowest_ranked_mon, + mon_election_obj=mon_obj, + mon_workflow_obj=mon_workflow_obj, + ) + + log.info(f"Proceeding to set election strategy to {election_strategy}") + if not mon_obj.set_election_strategy(mode=election_strategy): + log.error(f"Could not set election strategy to {election_strategy} mode") + return False + + log.info("Proceeding to checks on lowest ranked Mon as disallowed leader") + if election_strategy == "classic": + # When switching election mode to classic from disallow/connectivity, + # If lowest ranked Mon is in disallowed leaders list + # - Mon should become leader + # - Mon should be in Quorum + current_leader = mon_workflow_obj.get_mon_quorum_leader() + if lowest_ranked_mon != current_leader: + log.error("Mon with lowest rank is not leader in classic mode") + return False + + if lowest_ranked_mon not in mon_workflow_obj.get_mon_quorum().keys(): + log.error("Mon with lowest rank is not in Quorum in classic mode") + return False + + elif election_strategy == "disallow": + # When switching election mode to disallow from connectivity, + # If lowest ranked Mon is in disallowed leaders list, + # - Mon should not become leader + # - Mon should still be in Quorum + # - Mon should still be in disallowed leaders list + _validations( + mon=lowest_ranked_mon, + mon_election_obj=mon_obj, + mon_workflow_obj=mon_workflow_obj, + ) + + log.info( + "Successfully completed validation of lowest ranked Mon as disallowed leader" + ) + log.info("Proceeding to revert back cluster to previous state") + log.info( + f"Proceeding to revert election strategy to original state {original_election_strategy}" + ) + if not mon_obj.set_election_strategy(mode=original_election_strategy): + raise AssertionError( + f"could not set election strategy to {original_election_strategy} mode" + ) + + log.info( + "Validate Mon is not leader, Mon is in quorum and Mon is in disallow leaders list " + "after reverting election strategy to original state" + ) + _validations( + mon=lowest_ranked_mon, + mon_election_obj=mon_obj, + mon_workflow_obj=mon_workflow_obj, + ) + + log.info( + f"Proceeding to revert disallowed leaders, removing Mon {lowest_ranked_mon} from list" + ) + if not mon_obj.remove_disallow_mon(mon=lowest_ranked_mon): + raise AssertionError( + f"could not remove Mon {lowest_ranked_mon} from disallowed list" + ) + + log.info( + "Proceeding to perform post test scenario validations\n" + "- Mon becomes leader if original election strategy is disallow\n" + "- Mon is part of Quorum\n" + "- Mon is not in disallowed leaders list" + ) + current_leader = mon_workflow_obj.get_mon_quorum_leader() + if original_election_strategy == "disallow" and lowest_ranked_mon != current_leader: + log.error( + "Mon with lowest rank is not leader after removal from disallowed leaders list" + ) + return False + + if lowest_ranked_mon not in mon_workflow_obj.get_mon_quorum().keys(): + log.error( + "Mon with lowest rank is not in Quorum after removal from disallowed leaders list" + ) + return False + + disallowed_list = mon_obj.get_disallowed_mon_list() + if lowest_ranked_mon in disallowed_list: + log.error( + "Mon with lowest rank is still in disallowed leaders list post removal" + ) + return False + + log.info( + "\n -------------------------------------------" + "\n Completed validation:" + f"\n Changing election strategy from {original_election_strategy} mode " + f"to {election_strategy} mode when lowest ranked Mon in disallowed leader list" + "\n -------------------------------------------" + ) From 5bfd47f4650419d3ccbc86d10cae8c47ea3fddc3 Mon Sep 17 00:00:00 2001 From: Hemanth Sai Maheswarla Date: Wed, 11 Dec 2024 11:01:37 +0530 Subject: [PATCH 37/50] adding support for testing rgw ssl deployment with cephadm generate_cert Signed-off-by: Hemanth Sai Maheswarla Signed-off-by: Harishacharya-redhat --- .../rgw/tier-2_rgw_ssl_cephadm_gen_cert.yaml | 349 ++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 suites/squid/rgw/tier-2_rgw_ssl_cephadm_gen_cert.yaml diff --git a/suites/squid/rgw/tier-2_rgw_ssl_cephadm_gen_cert.yaml b/suites/squid/rgw/tier-2_rgw_ssl_cephadm_gen_cert.yaml new file mode 100644 index 00000000000..9500b1fb7e2 --- /dev/null +++ b/suites/squid/rgw/tier-2_rgw_ssl_cephadm_gen_cert.yaml @@ -0,0 +1,349 @@ +# Test suite for evaluating RGW multi-site having SSL endpoints generated by cephadm. +# +# This suite deploys a single realm (India) spanning across two RHCS clusters. It has a +# zonegroup (shared) which also spans across the clusters. There exists a master (pri) +# and secondary (sec) zones within this group. The master zone is part of the pri +# cluster whereas the sec zone is part of the sec datacenter (cluster). + +# conf: conf/squid/rgw/rgw_multisite.yaml +# The deployment is evaluated by running IOs across the environments. +--- +tests: + + # Cluster deployment stage + + - test: + abort-on-fail: true + desc: Install software pre-requisites for cluster deployment. + module: install_prereq.py + name: setup pre-requisites + + - test: + abort-on-fail: true + clusters: + ceph-pri: + config: + verify_cluster_health: true + steps: + - config: + command: bootstrap + service: cephadm + args: + registry-url: registry.redhat.io + mon-ip: node1 + orphan-initial-daemons: true + initial-dashboard-password: admin@123 + dashboard-password-noupdate: true + - config: + command: add_hosts + service: host + args: + attach_ip_address: true + labels: apply-all-labels + - config: + command: apply + service: mgr + args: + placement: + label: mgr + - config: + command: apply + service: mon + args: + placement: + label: mon + - config: + command: apply + service: osd + args: + all-available-devices: true + - config: + command: apply_spec + service: orch + specs: + - service_type: rgw + service_id: shared.pri + spec: + generate_cert: true + ssl: true + zonegroup_hostnames: + - s3.example.com + placement: + nodes: + - node5 + ceph-sec: + config: + verify_cluster_health: true + steps: + - config: + command: bootstrap + service: cephadm + args: + registry-url: registry.redhat.io + mon-ip: node1 + orphan-initial-daemons: true + initial-dashboard-password: admin@123 + dashboard-password-noupdate: true + - config: + command: add_hosts + service: host + args: + attach_ip_address: true + labels: apply-all-labels + - config: + command: apply + service: mgr + args: + placement: + label: mgr + - config: + command: apply + service: mon + args: + placement: + label: mon + - config: + command: apply + service: osd + args: + all-available-devices: true + - config: + command: apply_spec + service: orch + specs: + - service_type: rgw + service_id: shared.sec + spec: + generate_cert: true + ssl: true + zonegroup_hostnames: + - s3.example.com + placement: + nodes: + - node5 + desc: RHCS cluster deployment and rgw deployment with ssl cert generation + polarion-id: CEPH-83575222 + destroy-cluster: false + module: test_cephadm.py + name: deploy cluster and rgw with ssl gen-cert + + - test: + abort-on-fail: true + clusters: + ceph-pri: + config: + command: add + id: client.1 + node: node6 + install_packages: + - ceph-common + copy_admin_keyring: true + ceph-sec: + config: + command: add + id: client.1 + node: node6 + install_packages: + - ceph-common + copy_admin_keyring: true + desc: Configure the RGW client system + polarion-id: CEPH-83573758 + destroy-cluster: false + module: test_client.py + name: configure client + + - test: + abort-on-fail: true + clusters: + ceph-pri: + config: + commands: + - "radosgw-admin realm create --rgw-realm india --default" + - "radosgw-admin zonegroup create --rgw-realm india --rgw-zonegroup shared --endpoints https://{node_ip:node5} --master --default" + - "radosgw-admin zone create --rgw-realm india --rgw-zonegroup shared --rgw-zone primary --endpoints https://{node_ip:node5} --master --default" + - "radosgw-admin period update --rgw-realm india --commit" + - "radosgw-admin user create --uid=repuser --display_name='Replication user' --access-key 21e86bce636c3aa0 --secret cf764951f1fdde5d --rgw-realm india --system" + - "radosgw-admin zone modify --rgw-realm india --rgw-zonegroup shared --rgw-zone primary --access-key 21e86bce636c3aa0 --secret cf764951f1fdde5d" + - "radosgw-admin period update --rgw-realm india --commit" + - "ceph config set client.rgw.{daemon_id:shared.pri} rgw_realm india" + - "ceph config set client.rgw.{daemon_id:shared.pri} rgw_zonegroup shared" + - "ceph config set client.rgw.{daemon_id:shared.pri} rgw_zone primary" + - "ceph config set client.rgw rgw_verify_ssl False" + - "ceph config set client.rgw.{daemon_id:shared.pri} rgw_verify_ssl False" + - "ceph orch restart {service_name:shared.pri}" + - "ceph orch cert-store get cert cephadm_root_ca_cert > /home/cephuser/cephadm-root-ca.crt" + - "sudo yum install -y sshpass" + - "sleep 20" + - "sshpass -p 'passwd' scp /home/cephuser/cephadm-root-ca.crt root@{node_ip:ceph-sec#node5}:/etc/pki/ca-trust/source/anchors/" + - "sshpass -p 'passwd' scp /home/cephuser/cephadm-root-ca.crt root@{node_ip:ceph-sec#node6}:/etc/pki/ca-trust/source/anchors/" + ceph-sec: + config: + commands: + - "sudo update-ca-trust" + - "ceph config set client.rgw rgw_verify_ssl False" + - "radosgw-admin realm pull --rgw-realm india --url https://{node_ip:ceph-pri#node5} --access-key 21e86bce636c3aa0 --secret cf764951f1fdde5d --default" + - "radosgw-admin period pull --url https://{node_ip:ceph-pri#node5} --access-key 21e86bce636c3aa0 --secret cf764951f1fdde5d" + - "radosgw-admin zone create --rgw-realm india --rgw-zonegroup shared --rgw-zone secondary --endpoints https://{node_ip:node5} --access-key 21e86bce636c3aa0 --secret cf764951f1fdde5d" + - "radosgw-admin period update --rgw-realm india --commit" + - "ceph config set client.rgw rgw_verify_ssl False" + - "ceph config set client.rgw.{daemon_id:shared.sec} rgw_verify_ssl False" + - "ceph config set client.rgw.{daemon_id:shared.sec} rgw_realm india" + - "ceph config set client.rgw.{daemon_id:shared.sec} rgw_zonegroup shared" + - "ceph config set client.rgw.{daemon_id:shared.sec} rgw_zone secondary" + - "ceph orch restart {service_name:shared.sec}" + - "sudo yum install -y sshpass" + - "sleep 120" + - "ceph orch cert-store get cert cephadm_root_ca_cert > /home/cephuser/cephadm-root-ca.crt" + - "sshpass -p 'passwd' scp /home/cephuser/cephadm-root-ca.crt root@{node_ip:ceph-pri#node5}:/etc/pki/ca-trust/source/anchors/" + - "sshpass -p 'passwd' scp /home/cephuser/cephadm-root-ca.crt root@{node_ip:ceph-pri#node6}:/etc/pki/ca-trust/source/anchors/" + desc: Setting up RGW multisite replication environment + module: exec.py + name: setup multisite + polarion-id: CEPH-10362 + + - test: + abort-on-fail: true + clusters: + ceph-pri: + config: + role: rgw + sudo: True + commands: + - "update-ca-trust" + ceph-sec: + config: + role: rgw + sudo: True + commands: + - "update-ca-trust" + desc: update-ca-trust on rgw nodes + polarion-id: CEPH-83575227 + module: exec.py + name: update-ca-trust on rgw nodes + + - test: + abort-on-fail: true + clusters: + ceph-pri: + config: + role: client + sudo: True + commands: + - "update-ca-trust" + ceph-sec: + config: + role: client + sudo: True + commands: + - "update-ca-trust" + desc: update-ca-trust on client nodes + polarion-id: CEPH-83575227 + module: exec.py + name: update-ca-trust on client nodes + + - test: + abort-on-fail: true + clusters: + ceph-pri: + config: + commands: + - "radosgw-admin sync status" + - "ceph -s" + - "radosgw-admin realm list" + - "radosgw-admin zonegroup list" + - "radosgw-admin zone list" + desc: Retrieve the configured environment details + polarion-id: CEPH-83575227 + module: exec.py + name: get shared realm info on primary + + - test: + abort-on-fail: true + clusters: + ceph-sec: + config: + commands: + - "radosgw-admin sync status" + - "ceph -s" + - "radosgw-admin realm list" + - "radosgw-admin zonegroup list" + - "radosgw-admin zone list" + desc: Retrieve the configured environment details + polarion-id: CEPH-83575227 + module: exec.py + name: get shared realm info on secondary + + + + # Test work flow + + - test: + clusters: + ceph-pri: + config: + set-env: true + script-name: user_create.py + config-file-name: non_tenanted_user.yaml + copy-user-info-to-site: ceph-sec + desc: create non-tenanted user + module: sanity_rgw_multisite.py + name: create non-tenanted user + polarion-id: CEPH-83575199 + + - test: + name: enable compression on secondary + desc: test_Mbuckets_with_Nobjects_compression on secondary + polarion-id: CEPH-11350 + module: sanity_rgw_multisite.py + clusters: + ceph-sec: + config: + script-name: test_Mbuckets_with_Nobjects.py + verify-io-on-site: ["ceph-pri"] + config-file-name: test_Mbuckets_with_Nobjects_compression.yaml + + - test: + name: download objects on secondary + desc: test_Mbuckets_with_Nobjects_download on secondary + polarion-id: CEPH-14237 + module: sanity_rgw_multisite.py + clusters: + ceph-sec: + config: + script-name: test_Mbuckets_with_Nobjects.py + verify-io-on-site: ["ceph-pri"] + config-file-name: test_Mbuckets_with_Nobjects_download.yaml + + - test: + name: test encryption on secondary + desc: test_Mbuckets_with_Nobjects_enc on secondary + polarion-id: CEPH-11358 # also applies to CEPH-11361 + module: sanity_rgw_multisite.py + clusters: + ceph-sec: + config: + script-name: test_Mbuckets_with_Nobjects.py + verify-io-on-site: ["ceph-pri"] + config-file-name: test_Mbuckets_with_Nobjects_enc.yaml + + - test: + name: Test rgw through CURL + desc: Test rgw through CURL + polarion-id: CEPH-83575572 + module: sanity_rgw.py + clusters: + ceph-pri: + config: + script-name: ../curl/test_rgw_using_curl.py + config-file-name: ../../curl/configs/test_rgw_using_curl.yaml + + - test: + name: Test Etag not empty for complete multipart upload in aws + desc: Test Etag not empty for complete multipart upload in aws + polarion-id: CEPH-9801 + module: sanity_rgw.py + clusters: + ceph-pri: + config: + script-name: ../aws/test_aws.py + config-file-name: ../../aws/configs/test_complete_multipart_upload_etag_not_empty.yaml From b4e893220ccb0803f5d5c2b423b9dac06c3fc10f Mon Sep 17 00:00:00 2001 From: YuvaTejaSreeGayam Date: Mon, 23 Dec 2024 15:33:30 +0530 Subject: [PATCH 38/50] Updated the conf file path in all test suites Signed-off-by: YuvaTejaSreeGayam Signed-off-by: Harishacharya-redhat --- suites/squid/rgw/tier-1_rgw_ms_datalog_and_crash.yaml | 1 + suites/squid/rgw/tier-1_rgw_ms_ecpool_regression_test.yaml | 1 + suites/squid/rgw/tier-2_rgw_3_way_multisite.yaml | 1 + suites/squid/rgw/tier-2_rgw_cloud_transition.yaml | 2 +- suites/squid/rgw/tier-2_rgw_ingress_multi_realm.yaml | 1 + suites/squid/rgw/tier-2_rgw_ms-archive.yaml | 1 + .../rgw/tier-2_rgw_ms-archive_resharding_granular_sync.yaml | 1 + suites/squid/rgw/tier-2_rgw_ms_async_data_notification.yaml | 1 + suites/squid/rgw/tier-2_rgw_ms_granular_sync_policy.yaml | 1 + suites/squid/rgw/tier-2_rgw_ms_regression_test.yaml | 1 + suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml | 2 +- suites/squid/rgw/tier-2_rgw_multisite_scenarios.yaml | 1 + suites/squid/rgw/tier-2_rgw_regression_test.yaml | 1 + suites/squid/rgw/tier-2_rgw_singlesite_to_multisite.yaml | 1 + suites/squid/rgw/tier-2_rgw_sts_aswi.yaml | 1 + .../rgw/tier-2_rgw_test_basic_sanity_with_d3n_enabled.yaml | 1 + suites/squid/rgw/tier-2_rgw_test_bucket_notifications.yaml | 1 + .../rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml | 2 +- .../rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml | 3 ++- suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml | 2 +- suites/squid/rgw/tier-2_ssl_rgw_ms_ecpool_test.yaml | 1 + suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml | 1 + suites/squid/rgw/tier-3_archive_zone_colocate_data_zone.yaml | 1 + suites/squid/rgw/tier-4-rgw.yaml | 2 +- 24 files changed, 25 insertions(+), 6 deletions(-) diff --git a/suites/squid/rgw/tier-1_rgw_ms_datalog_and_crash.yaml b/suites/squid/rgw/tier-1_rgw_ms_datalog_and_crash.yaml index 11df00ddd50..6c8edc5f8f3 100644 --- a/suites/squid/rgw/tier-1_rgw_ms_datalog_and_crash.yaml +++ b/suites/squid/rgw/tier-1_rgw_ms_datalog_and_crash.yaml @@ -7,6 +7,7 @@ # The deployment is evaluated by running IOs across the environments. # This particular yaml runs the tests on the primary/master and verifies IOs on the slave/secondary site. +# global-conf: conf/squid/rgw/rgw_multisite.yaml tests: diff --git a/suites/squid/rgw/tier-1_rgw_ms_ecpool_regression_test.yaml b/suites/squid/rgw/tier-1_rgw_ms_ecpool_regression_test.yaml index 34d876dedd7..63884cd111c 100644 --- a/suites/squid/rgw/tier-1_rgw_ms_ecpool_regression_test.yaml +++ b/suites/squid/rgw/tier-1_rgw_ms_ecpool_regression_test.yaml @@ -11,6 +11,7 @@ # secondary site. # In addition to the above, the data bucket is configured to use EC +# global-conf: conf/squid/rgw/ms-ec-profile-4+2-cluster.yaml --- tests: diff --git a/suites/squid/rgw/tier-2_rgw_3_way_multisite.yaml b/suites/squid/rgw/tier-2_rgw_3_way_multisite.yaml index 57ba49843f4..4e1751621fb 100644 --- a/suites/squid/rgw/tier-2_rgw_3_way_multisite.yaml +++ b/suites/squid/rgw/tier-2_rgw_3_way_multisite.yaml @@ -13,6 +13,7 @@ # In addition to the above, the data bucket is configured to use EC 2+2 # Sync IO rgws & Client IO rgws are sepearated +# global-conf: conf/squid/rgw/3-way-ms-ec-profile-2+2@4nodes.yaml --- tests: diff --git a/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml b/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml index baf029783aa..358761eab52 100644 --- a/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml +++ b/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml @@ -1,5 +1,5 @@ # Test suite for cloud transition workflow - +# global-conf: conf/squid/rgw/cloud_transition.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ingress_multi_realm.yaml b/suites/squid/rgw/tier-2_rgw_ingress_multi_realm.yaml index 8c9e200b604..5b22ce81196 100644 --- a/suites/squid/rgw/tier-2_rgw_ingress_multi_realm.yaml +++ b/suites/squid/rgw/tier-2_rgw_ingress_multi_realm.yaml @@ -3,6 +3,7 @@ # # This test suite evaluates the Ingress HAproxy deployment scenario wherein there exists more than one # RGW daemons configured with multiple realm, along with zones and zonegroups. +# global-conf: conf/squid/rgw/tier-1_rgw_multirealm.yaml tests: diff --git a/suites/squid/rgw/tier-2_rgw_ms-archive.yaml b/suites/squid/rgw/tier-2_rgw_ms-archive.yaml index 5cd81c06fe2..ea12ff2b06f 100644 --- a/suites/squid/rgw/tier-2_rgw_ms-archive.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms-archive.yaml @@ -1,3 +1,4 @@ +# global-conf: conf/squid/rgw/rgw_ms_archive.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ms-archive_resharding_granular_sync.yaml b/suites/squid/rgw/tier-2_rgw_ms-archive_resharding_granular_sync.yaml index e337948729b..4c7a8e8d695 100644 --- a/suites/squid/rgw/tier-2_rgw_ms-archive_resharding_granular_sync.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms-archive_resharding_granular_sync.yaml @@ -1,3 +1,4 @@ +# global-conf: conf/squid/rgw/rgw_ms_archive.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ms_async_data_notification.yaml b/suites/squid/rgw/tier-2_rgw_ms_async_data_notification.yaml index 495aa587eab..72819f6644b 100644 --- a/suites/squid/rgw/tier-2_rgw_ms_async_data_notification.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms_async_data_notification.yaml @@ -6,6 +6,7 @@ # cluster whereas the sec zone is part of the sec datacenter (cluster). # The deployment is evaluated by running IOs across the environments. +# global-conf: conf/squid/rgw/rgw_multisite.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ms_granular_sync_policy.yaml b/suites/squid/rgw/tier-2_rgw_ms_granular_sync_policy.yaml index 6e77ac2b46c..b02e1b3895d 100644 --- a/suites/squid/rgw/tier-2_rgw_ms_granular_sync_policy.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms_granular_sync_policy.yaml @@ -7,6 +7,7 @@ # The deployment is evaluated by running IOs across the environments. # feature ga'd in 6.1 +# global-conf: conf/squid/rgw/rgw_ms_archive.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ms_regression_test.yaml b/suites/squid/rgw/tier-2_rgw_ms_regression_test.yaml index 3ce07bf8924..85fe82cc4e6 100644 --- a/suites/squid/rgw/tier-2_rgw_ms_regression_test.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms_regression_test.yaml @@ -1,5 +1,6 @@ # This suites perform disabling and re enabling re-sharding feature and verifying DBR behavior # Verfies bucket generation +# global-conf: conf/squid/rgw/rgw_multisite.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml b/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml index f76c4b6fa2f..9baa323264f 100644 --- a/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml @@ -2,7 +2,7 @@ # Objective: Test bucket notifications with kafka endpoint # - with ack_type broker/none # - w/o persistent flag -# +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_multisite_scenarios.yaml b/suites/squid/rgw/tier-2_rgw_multisite_scenarios.yaml index 19a821c9d49..3efa2659bc9 100644 --- a/suites/squid/rgw/tier-2_rgw_multisite_scenarios.yaml +++ b/suites/squid/rgw/tier-2_rgw_multisite_scenarios.yaml @@ -9,6 +9,7 @@ # The deployment is evaluated by disabling sync and running IOs across the environments. # This particular yaml runs the tests on the primary and verifies no objects syncs on the # secondary site and vice versa +# global-conf: conf/squid/rgw/rgw_multisite.yaml --- tests: diff --git a/suites/squid/rgw/tier-2_rgw_regression_test.yaml b/suites/squid/rgw/tier-2_rgw_regression_test.yaml index 29cd7d46f6f..8be9610019d 100644 --- a/suites/squid/rgw/tier-2_rgw_regression_test.yaml +++ b/suites/squid/rgw/tier-2_rgw_regression_test.yaml @@ -4,6 +4,7 @@ # https://github.com/red-hat-storage/ceph-qe-scripts/tree/master/rgw # each script under the above repo has a yaml ( config defined ) which is actually a test # We are calling the script and associated yaml here. +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: diff --git a/suites/squid/rgw/tier-2_rgw_singlesite_to_multisite.yaml b/suites/squid/rgw/tier-2_rgw_singlesite_to_multisite.yaml index 24ff1f56cac..3c42e4ef23b 100644 --- a/suites/squid/rgw/tier-2_rgw_singlesite_to_multisite.yaml +++ b/suites/squid/rgw/tier-2_rgw_singlesite_to_multisite.yaml @@ -3,6 +3,7 @@ # ceph-pri is master/primary site # ceph-sec is slave/secondary site # CEPH-83575355 - [single-site to multi-site conversion] Test no recovering shards are seen ( Bug 2026101) +# global-conf: conf/squid/rgw/rgw_multisite.yaml tests: diff --git a/suites/squid/rgw/tier-2_rgw_sts_aswi.yaml b/suites/squid/rgw/tier-2_rgw_sts_aswi.yaml index f89f5d3661c..56fb9d226cd 100644 --- a/suites/squid/rgw/tier-2_rgw_sts_aswi.yaml +++ b/suites/squid/rgw/tier-2_rgw_sts_aswi.yaml @@ -4,6 +4,7 @@ # Requires a 5 node cluster layout having only one node with RGW role. +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: abort-on-fail: true diff --git a/suites/squid/rgw/tier-2_rgw_test_basic_sanity_with_d3n_enabled.yaml b/suites/squid/rgw/tier-2_rgw_test_basic_sanity_with_d3n_enabled.yaml index f73f06c97ac..1cba3448cfd 100644 --- a/suites/squid/rgw/tier-2_rgw_test_basic_sanity_with_d3n_enabled.yaml +++ b/suites/squid/rgw/tier-2_rgw_test_basic_sanity_with_d3n_enabled.yaml @@ -1,4 +1,5 @@ # Objective: Test basic sanity feature with d3n-cache enabled +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: abort-on-fail: true diff --git a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications.yaml b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications.yaml index a985aca60d7..033695bb3f9 100644 --- a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications.yaml +++ b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications.yaml @@ -3,6 +3,7 @@ # - with ack_type broker/none # - w/o persistent flag # +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: abort-on-fail: true diff --git a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml index b6988cdd366..0ae88f63fb8 100644 --- a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml +++ b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml @@ -4,7 +4,7 @@ # - with ack_type none and w/o persistent flag # - with SASL security type i.e., both SASL_PLAINTEXT and SASL_SSL # - with both mechanisms - PLAIN and SCRAM-SHA-256 - +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: abort-on-fail: true diff --git a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml index 26973c24ac3..d32491d4c64 100644 --- a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml +++ b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml @@ -1,8 +1,9 @@ # # Objective: Test bucket notifications with kafka endpoint # - with ack_type broker/none -## - w/o persistent flag +# - w/o persistent flag # - with SSL security type +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: diff --git a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml index 43d29db07b8..602a758231c 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml @@ -10,7 +10,7 @@ # role-id: # secret-id: # prefix: /v1/ -# +# global-conf: conf/squid/rgw/ec-profile-4+2-cluster.yaml --- tests: - test: diff --git a/suites/squid/rgw/tier-2_ssl_rgw_ms_ecpool_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_ms_ecpool_test.yaml index 823fd27e171..719b0c5408f 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_ms_ecpool_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_ms_ecpool_test.yaml @@ -7,6 +7,7 @@ # EC pool 4+2 configuration # The deployment is evaluated by running IOs across the environments. +# global-conf: conf/squid/rgw/ms-ec-profile-4+2-cluster.yaml --- tests: diff --git a/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml index b81a33fb3a8..65063b20878 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_regression_test.yaml @@ -4,6 +4,7 @@ # the test suite is to evaluate the STS functionality of RGW. # Requires a 5 node cluster layout having only one node with RGW role. +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: diff --git a/suites/squid/rgw/tier-3_archive_zone_colocate_data_zone.yaml b/suites/squid/rgw/tier-3_archive_zone_colocate_data_zone.yaml index 0c5dee56bfb..029d6a96761 100644 --- a/suites/squid/rgw/tier-3_archive_zone_colocate_data_zone.yaml +++ b/suites/squid/rgw/tier-3_archive_zone_colocate_data_zone.yaml @@ -7,6 +7,7 @@ # master zone - pri # secondary zone - sec # archive zone - arc +# global-conf: conf/squid/rgw/tier-3_archive_zone_colocate_data_zone_conf.yaml --- diff --git a/suites/squid/rgw/tier-4-rgw.yaml b/suites/squid/rgw/tier-4-rgw.yaml index b6738b68dc9..390e27ce0fc 100644 --- a/suites/squid/rgw/tier-4-rgw.yaml +++ b/suites/squid/rgw/tier-4-rgw.yaml @@ -1,5 +1,5 @@ # This suite executes Tier 4 RGW tests - +# global-conf: conf/squid/rgw/tier-0_rgw.yaml tests: - test: abort-on-fail: true From 18abe55c849143bc32beffafb418526b38d84100 Mon Sep 17 00:00:00 2001 From: YuvaTejaSreeGayam Date: Mon, 23 Dec 2024 15:44:27 +0530 Subject: [PATCH 39/50] adding conf for suites in rgw squid Signed-off-by: YuvaTejaSreeGayam Signed-off-by: Harishacharya-redhat --- suites/squid/rgw/tier-2_rgw_cloud_transition.yaml | 2 ++ suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml | 4 +++- .../rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml | 1 + .../rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml | 2 +- suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml | 1 + suites/squid/rgw/tier-4-rgw.yaml | 1 + 6 files changed, 9 insertions(+), 2 deletions(-) diff --git a/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml b/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml index 358761eab52..8111497fce0 100644 --- a/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml +++ b/suites/squid/rgw/tier-2_rgw_cloud_transition.yaml @@ -1,5 +1,7 @@ # Test suite for cloud transition workflow + # global-conf: conf/squid/rgw/cloud_transition.yaml + tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml b/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml index 9baa323264f..3fe0235da7a 100644 --- a/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml +++ b/suites/squid/rgw/tier-2_rgw_ms_test_bucket_notifications.yaml @@ -2,7 +2,9 @@ # Objective: Test bucket notifications with kafka endpoint # - with ack_type broker/none # - w/o persistent flag -# global-conf: conf/squid/rgw/tier-0_rgw.yaml +# +# global-conf: conf/squid/rgw/rgw_multisite.yaml + tests: # Cluster deployment stage diff --git a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml index 0ae88f63fb8..2614077a743 100644 --- a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml +++ b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_sasl.yaml @@ -5,6 +5,7 @@ # - with SASL security type i.e., both SASL_PLAINTEXT and SASL_SSL # - with both mechanisms - PLAIN and SCRAM-SHA-256 # global-conf: conf/squid/rgw/tier-0_rgw.yaml + tests: - test: abort-on-fail: true diff --git a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml index d32491d4c64..029f4022e9f 100644 --- a/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml +++ b/suites/squid/rgw/tier-2_rgw_test_bucket_notifications_kafka_ssl.yaml @@ -1,7 +1,7 @@ # # Objective: Test bucket notifications with kafka endpoint # - with ack_type broker/none -# - w/o persistent flag +## - w/o persistent flag # - with SSL security type # global-conf: conf/squid/rgw/tier-0_rgw.yaml diff --git a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml index 602a758231c..84148f885fc 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml @@ -10,6 +10,7 @@ # role-id: # secret-id: # prefix: /v1/ +# # global-conf: conf/squid/rgw/ec-profile-4+2-cluster.yaml --- tests: diff --git a/suites/squid/rgw/tier-4-rgw.yaml b/suites/squid/rgw/tier-4-rgw.yaml index 390e27ce0fc..d47d500ebf9 100644 --- a/suites/squid/rgw/tier-4-rgw.yaml +++ b/suites/squid/rgw/tier-4-rgw.yaml @@ -1,5 +1,6 @@ # This suite executes Tier 4 RGW tests # global-conf: conf/squid/rgw/tier-0_rgw.yaml + tests: - test: abort-on-fail: true From de52c3dc06fdf7937d89d47b580ac5c5f412f374 Mon Sep 17 00:00:00 2001 From: YuvaTejaSreeGayam Date: Mon, 23 Dec 2024 15:46:59 +0530 Subject: [PATCH 40/50] adding conf path for suites in rgw squid Signed-off-by: YuvaTejaSreeGayam Signed-off-by: Harishacharya-redhat --- suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml index 84148f885fc..799b40d1205 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml @@ -10,8 +10,8 @@ # role-id: # secret-id: # prefix: /v1/ -# # global-conf: conf/squid/rgw/ec-profile-4+2-cluster.yaml +# --- tests: - test: From 048d515e8e2f351eda3a0eee6266ffe8d4238d49 Mon Sep 17 00:00:00 2001 From: YuvaTejaSreeGayam Date: Mon, 23 Dec 2024 15:48:12 +0530 Subject: [PATCH 41/50] Changes to be committed: modified: suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml Signed-off-by: YuvaTejaSreeGayam Signed-off-by: Harishacharya-redhat --- suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml index 799b40d1205..8a151fe9cc5 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml @@ -10,8 +10,8 @@ # role-id: # secret-id: # prefix: /v1/ +# # global-conf: conf/squid/rgw/ec-profile-4+2-cluster.yaml -# --- tests: - test: From a659a986953bed9c604d02cb3784690c9e542ac6 Mon Sep 17 00:00:00 2001 From: YuvaTejaSreeGayam Date: Mon, 23 Dec 2024 15:51:05 +0530 Subject: [PATCH 42/50] Changes modified: suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml Signed-off-by: YuvaTejaSreeGayam Signed-off-by: Harishacharya-redhat --- suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml index 8a151fe9cc5..1632cb6305a 100644 --- a/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml +++ b/suites/squid/rgw/tier-2_ssl_rgw_ecpool_test.yaml @@ -10,7 +10,7 @@ # role-id: # secret-id: # prefix: /v1/ -# +# # global-conf: conf/squid/rgw/ec-profile-4+2-cluster.yaml --- tests: From 9376135a98a47f1ac832dbf68089d60b5abfe029 Mon Sep 17 00:00:00 2001 From: hkadam134 Date: Fri, 27 Dec 2024 05:24:53 -0500 Subject: [PATCH 43/50] TFA fix - increase timeout for selinux Signed-off-by: hkadam134 Signed-off-by: Harishacharya-redhat --- tests/cephfs/clients/test_selinux_relabel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cephfs/clients/test_selinux_relabel.py b/tests/cephfs/clients/test_selinux_relabel.py index 6abae885699..fce08888294 100644 --- a/tests/cephfs/clients/test_selinux_relabel.py +++ b/tests/cephfs/clients/test_selinux_relabel.py @@ -340,7 +340,9 @@ def apply_selinux_label(client, label, path): None """ try: - client.exec_command(sudo=True, cmd=f"chcon -R --type={label} {path}") + client.exec_command( + sudo=True, cmd=f"chcon -R --type={label} {path}", timeout=600 + ) log.info(f"Applied SELinux label {label} to {path}") except Exception as e: log.error(f"Failed to apply SELinux label {label} to {path}: {e}") From 5da393013bba06d05d2fabf7867eef86341745e4 Mon Sep 17 00:00:00 2001 From: Chaitanya Dommeti Date: Fri, 27 Dec 2024 16:39:18 +0530 Subject: [PATCH 44/50] Addressed review comments Signed-off-by: Chaitanya Dommeti Signed-off-by: Harishacharya-redhat --- suites/squid/rbd/tier-3_rbd_migration.yaml | 51 +- tests/rbd/test_rbd_live_migrate_encryption.py | 545 ++++++++++++++++++ 2 files changed, 594 insertions(+), 2 deletions(-) create mode 100644 tests/rbd/test_rbd_live_migrate_encryption.py diff --git a/suites/squid/rbd/tier-3_rbd_migration.yaml b/suites/squid/rbd/tier-3_rbd_migration.yaml index dfa71387fc2..c14fdd9ce64 100644 --- a/suites/squid/rbd/tier-3_rbd_migration.yaml +++ b/suites/squid/rbd/tier-3_rbd_migration.yaml @@ -1,6 +1,6 @@ tests: - # Setup the cluster + #Setup the cluster - test: abort-on-fail: true module: install_prereq.py @@ -63,7 +63,7 @@ tests: polarion-id: CEPH-83573758 - test: - desc: Install rbd-nbd and remove any epel packages + desc: Install rbd-nbd, qemu-img and remove any epel packages module: exec.py name: Install rbd-nbd config: @@ -71,6 +71,7 @@ tests: commands: - "rm -rf /etc/yum.repos.d/epel*" - "dnf install rbd-nbd -y" + - "dnf install qemu-img -y" - test: name: Test image migration with external qcow data format @@ -90,3 +91,49 @@ tests: fio: size: 100M polarion-id: CEPH-83584070 + + - test: + desc: Live migration of RAW format images with encryption + config: + encryption_type: + - luks1 + - luks2 + rep_pool_config: + num_pools: 1 + do_not_create_image: true + ec_pool_config: + num_pools: 1 + do_not_create_image: true + fio: + size: 10M + fs: ext4 + io: true + testconfig: + id: CEPH-83596444 + name: Live migration of raw format images with encryption + module: test_rbd_live_migrate_encryption.py + name: Live migration of RAW format images with encryption + polarion-id: CEPH-83596444 + + - test: + desc: Live migration of qcow2 format images with encryption + config: + encryption_type: + - luks1 + - luks2 + rep_pool_config: + num_pools: 1 + do_not_create_image: true + ec_pool_config: + num_pools: 1 + do_not_create_image: true + fio: + size: 10M + fs: ext4 + io: true + testconfig: + id: CEPH-83596588 + name: Live migration of qcow2 format images with encryption + module: test_rbd_live_migrate_encryption.py + name: Live migration of qcow2 format images with encryption + polarion-id: CEPH-83596588 diff --git a/tests/rbd/test_rbd_live_migrate_encryption.py b/tests/rbd/test_rbd_live_migrate_encryption.py new file mode 100644 index 00000000000..0bc8eab5110 --- /dev/null +++ b/tests/rbd/test_rbd_live_migrate_encryption.py @@ -0,0 +1,545 @@ +""" +Module to verify : + - Live migration of RAW format images with encryption + - Live migration of qcow2 format images with encryption + +Test case covered: +CEPH-83596444 - Live migration of RAW format images with encryption + +Pre-requisites : +1. Cluster must be up and running with capacity to create pool +2. We need atleast one client node with ceph-common package, + conf and keyring files + +Test Case Flow: +1. Deploy Ceph on version 8.0 or greater. +2. Create a Pool and RBD image in the pool. + ceph osd pool create pool 128 128 + rbd pool init pool + rbd create pool/image1 --size 1G +3. Format image to an encrypted format with LUKS1 + E.g: + rbd encryption format pool1/image1 luks1 /tmp/passphrase.bin +4. Write data to encrypted images and take md5sum + rbd device map -t nbd -o encryption-format=luks1,encryption-passphrase-file=/tmp/passphrase.bin pool1/image1; + mkfs -t ext4 -E nodiscard /dev/nbd1; mkdir /tmp/test1; mount /dev/nbd1 /tmp/test1; + cp /var/log/messages /tmp/test1/data1; df -h /tmp/test1/data1; md5sum /tmp/test1/data1 +5. Create RAW data of rbd image using rbd export + E.g: rbd export rep_pool/rimage1 /tmp/image1_raw +6. Create spec file raw data as below + cat /tmp/raw_spec1.json + { + "type": "raw", + "stream": { + "type": "file", + "file_path": "/tmp/image1_raw", + } + } +7. Make sure no client should holds that image before Initiate migration using + rbd migration prepare --import-only + E.g: rbd migration prepare --import-only --source-spec-path /tmp/raw_spec.json m_pool/mr_image1 +8. Execute and commit the migration + rbd migration execute pool/image + rbd migration commit pool/image +9. map that migrated image using rbd device map with encryption keys, + create mount directory and mount it and calculate md5sum and Cross-verify data consistency + E.g: rbd device map -t nbd -o encryption-format=luks2,encryption-passphrase-file=/tmp/passphrase.bin + m_pool/mr_image2 +10. Unmap the disk and cleanup the pools, namespace and image +11. Repeat the test on LUKS2 + + +Test case covered - +CEPH-83596588 - Live migration of qcow 2format images with encryption + +Pre-requisites : +1. Cluster must be up and running with capacity to create pool +2. We need atleast one client node with ceph-common package, + conf and keyring files + +Test Case Flow: +1. Deploy Ceph on version 8.0 or greater. +2. Create a Pool and RBD image in the pool. + ceph osd pool create pool 128 128 + rbd pool init pool + rbd create pool/image1 --size 1G +3. Format image to an encrypted format with LUKS1 + E.g: + rbd encryption format pool1/image1 luks1 /tmp/passphrase.bin +4. Write data to encrypted images and take md5sum + rbd device map -t nbd -o encryption-format=luks1,encryption-passphrase-file + =/tmp/passphrase.bin pool1/image1; + mkfs -t ext4 -E nodiscard /dev/nbd1; mkdir /tmp/test1; mount /dev/nbd1 /tmp/test1; + cp /var/log/messages /tmp/test1/data1; df -h /tmp/test1/data1; md5sum /tmp/test1/data1 +5. Unmap the encrypted disk using device unmap with proper keys + E.g: rbd device unmap -t nbd -o encryption-format=luks1,encryption-passphrase-file + =luks1_passphrase.bin pool1/qimage1 +6. Then map it without encryption + Using rbd map + E.g: rbd map pool1/qimage1 +7. Convert that raw disk data to qcow2 data format using qemu-img convert + E.g: qemu-img convert -f raw -O qcow2 /dev/rbd0 /tmp/qimage1.qcow2 + 8.Create spec file with qcow format data + [root@ceph-sangadi-bz-sqd86e-node4 tmp]# cat /tmp/qcow_spec.json + { + "type": "qcow", + "stream": { + "type": "file", + "file_path": "/tmp/qimage1.qcow2" + } + } +9. Make sure no client should holds that image before Initiate migration using + rbd migration prepare --import-only + E.g: rbd migration prepare --import-only --source-spec-path /tmp/qcow_spec.json m_pool/mr_image1 + 10. Execute and commit the migration + rbd migration execute pool/image + rbd migration commit pool/image +11. map that migrated image using rbd device map with encryption keys, + create mount directory and mount it and calculate md5sum and Cross-verify data consistency + E.g: rbd device map -t nbd -o encryption-format=luks2,encryption-passphrase-file= + /tmp/passphrase.bin m_pool/mr_image2 +12. Unmap the disk and cleanup the pools, namespace and image +13. Repeat the test on LUKS2 + +""" + +import tempfile +from copy import deepcopy + +from ceph.rbd.initial_config import initial_rbd_config +from ceph.rbd.utils import ( + check_data_integrity, + create_map_options, + getdict, + random_string, +) +from ceph.rbd.workflows.cleanup import cleanup +from ceph.rbd.workflows.encryption import create_passphrase_file +from ceph.rbd.workflows.krbd_io_handler import krbd_io_handler +from ceph.rbd.workflows.migration import verify_migration_state +from ceph.rbd.workflows.rbd import create_single_pool_and_images +from ceph.utils import get_node_by_id +from cli.rbd.rbd import Rbd +from utility.log import Log + +log = Log(__name__) + + +def migration_encrypted_raw_images(rbd_obj, client, **kw): + """ + Test to verify Live migration of raw format images with encryption + Args: + rbd_obj: RBD object + client : client node object + **kw: any other arguments + """ + + kw["client"] = client + rbd = rbd_obj.get("rbd") + + for pool_type in rbd_obj.get("pool_types"): + rbd_config = kw.get("config", {}).get(pool_type, {}) + multi_pool_config = deepcopy(getdict(rbd_config)) + + for pool, pool_config in multi_pool_config.items(): + kw["pool-name"] = pool + for encryption_type in kw.get("config", {}).get("encryption_type", {}): + kw.update({f"{pool}": {}}) + kw[pool].update({"encryption_type": encryption_type}) + kw[pool].update({"pool_type": pool_type}) + image = ( + "image_" + kw[pool]["encryption_type"] + "_" + random_string(len=3) + ) + kw[pool].update({"image": image}) + err = run_io_on_encryption_formatted_image(rbd, pool, image, **kw) + if err: + return 1 + + # Create spec file raw data + raw_file = tempfile.mktemp(prefix=f"{image}_", suffix=".raw") + rbd.export( + **{ + "source-image-or-snap-spec": f"{pool}/{image}", + "path-name": raw_file, + } + ) + raw_spec = { + "type": "raw", + "stream": {"type": "file", "file_path": f"{raw_file}"}, + } + + kw["cleanup_files"].append(raw_file) + + kw[pool].update({"spec": raw_spec}) + err = migrate_check_consistency(rbd, pool, image, **kw) + if err: + return 1 + + return 0 + + +def migration_encrypted_qcow_images(rbd_obj, client, **kw): + """ + Test to verify Live migration of qcow2 format images with encryption + Args: + rbd_obj: RBD object + client : client node object + **kw: any other arguments + """ + + kw["client"] = client + rbd = rbd_obj.get("rbd") + + for pool_type in rbd_obj.get("pool_types"): + rbd_config = kw.get("config", {}).get(pool_type, {}) + multi_pool_config = deepcopy(getdict(rbd_config)) + + for pool, pool_config in multi_pool_config.items(): + kw["pool-name"] = pool + for encryption_type in kw.get("config", {}).get("encryption_type", {}): + kw.update({f"{pool}": {}}) + kw[pool].update({"encryption_type": encryption_type}) + kw[pool].update({"pool_type": pool_type}) + image = ( + "image_" + kw[pool]["encryption_type"] + "_" + random_string(len=3) + ) + kw[pool].update({"image": image}) + + err = run_io_on_encryption_formatted_image(rbd, pool, image, **kw) + if err: + return 1 + + qcow_file = "/tmp/qcow_" + random_string(len=3) + ".qcow2" + out, err = client.exec_command( + sudo=True, + cmd=f"qemu-img convert -f raw -O qcow2 {kw[pool][image]["dev"]} {qcow_file}", + ) + if err: + log.error(f"Image convert to qcow2 failed with err {err}") + return 1 + else: + log.info("Successfully converted image to qcow2") + + kw["cleanup_files"].append(qcow_file) + qcow_spec = { + "type": "qcow", + "stream": {"type": "file", "file_path": f"{qcow_file}"}, + } + kw[pool].update({"spec": qcow_spec}) + err = migrate_check_consistency(rbd, pool, image, **kw) + if err: + return 1 + + return 0 + + +def run_io_on_encryption_formatted_image(rbd, pool, image, **kw): + """ + Function to carry out the following: + - Create source rbd image + - format the image with ecryption + - create passphrase file + - map, mount, write IO, unmount and unmap of source image + Args: + kw: rbd object, pool, image, test data + Returns: + int: The return value. 0 for success, 1 otherwise + + """ + + # Create an RBD image in pool + out, err = rbd.create(**{"image-spec": f"{pool}/{image}", "size": 1024}) + if err: + log.error(f"Create image {pool}/{image} failed with error {err}") + return 1 + else: + log.info(f"Successfully created image {pool}/{image}") + + # Format the image with encryption + passphrase = ( + f"{kw[pool]["encryption_type"]}_passphrase_" + random_string(len=3) + ".bin" + ) + create_passphrase_file(kw["client"], passphrase) + kw["cleanup_files"].append(passphrase) + out, err = rbd.encryption_format( + **{ + "image-spec": f"{pool}/{image}", + "format": kw[pool]["encryption_type"], + "passphrase-file": passphrase, + } + ) + if err: + log.error( + f"Encryption format with {kw[pool]["encryption_type"]} failed on {pool}/{image}" + ) + return 1 + else: + log.info( + f"Successfully formatted the image {pool}/{image} with encryption type {kw[pool]["encryption_type"]}" + ) + + # Map, mount and run IOs + fio = kw.get("config", {}).get("fio", {}) + io_config = { + "rbd_obj": rbd, + "client": kw["client"], + "size": fio["size"], + "do_not_create_image": True, + "config": { + "file_size": fio["size"], + "file_path": [f"/mnt/mnt_{random_string(len=3)}/file"], + "get_time_taken": True, + "image_spec": [f"{pool}/{image}"], + "operations": { + "fs": "ext4", + "io": True, + "mount": True, + "device_map": True, + }, + "cmd_timeout": 2400, + "io_type": "write", + }, + } + + # Include the encryption details in io config + encryption_config = list() + encryption_config.append({"encryption-format": kw[pool]["encryption_type"]}) + encryption_config.append({"encryption-passphrase-file": passphrase}) + io_config["config"]["encryption_config"] = encryption_config + kw[pool].update({"encryption_config": encryption_config}) + out, err = krbd_io_handler(**io_config) + if err: + log.error(f"Map, mount and run IOs failed for encrypted {pool}/{image}") + return 1 + else: + log.info(f"Map, mount and IOs successful for encrypted {pool}/{image}") + + out, err = rbd.map(**{"image-or-snap-spec": f"{pool}/{image}"}) + if err: + log.error(f"Failed to map the source image {pool}/{image} without encryption") + return 1 + else: + log.info( + f"Successfully mapped the source image {pool}/{image} without encryption" + ) + kw[pool].update({image: {}}) + kw[pool][image].update({"dev": out.strip()}) + + +def migrate_check_consistency(rbd, pool, image, **kw): + """ + Function to carry out the following: + - Create target pool and image + - Prepare, execute and commit migration + - Verify map an unmap migrated image + - verify md5sum of source image and target image for data consistency + Args: + kw: rbd object, pool, image, test data + Returns: + int: The return value. 0 for success, 1 otherwise + + """ + # Create a target pool where the encrypted image is to be migrated + is_ec_pool = True if "ec" in kw[pool]["pool_type"] else False + config = kw.get("config", {}) + target_pool = "target_pool_" + random_string(len=3) + target_pool_config = {} + if is_ec_pool: + data_pool_target = "data_pool_new_" + random_string(len=3) + target_pool_config["data_pool"] = data_pool_target + rc = create_single_pool_and_images( + config=config, + pool=target_pool, + pool_config=target_pool_config, + client=kw["client"], + cluster="ceph", + rbd=rbd, + ceph_version=int(config.get("rhbuild")[0]), + is_ec_pool=is_ec_pool, + is_secondary=False, + do_not_create_image=True, + ) + if rc: + log.error(f"Creation of target pool {target_pool} failed") + return rc + + # Adding the new pool details to config so that they are handled in cleanup + if kw[pool]["pool_type"] == "rep_pool_config": + kw["config"]["rep_pool_config"][target_pool] = {} + elif kw[pool]["pool_type"] == "ec_pool_config": + kw["config"]["ec_pool_config"][target_pool] = {"data_pool": data_pool_target} + + # Prepare Migration + target_image = "target_image_" + random_string(len=3) + out, err = rbd.migration.prepare( + source_spec=kw[pool]["spec"], + dest_spec=f"{target_pool}/{target_image}", + client_node=kw["client"], + ) + if err: + log.error(f"Migration prepare failed with error {err}") + return 1 + else: + log.info("Successfully prepared for migration") + + # Verify prepare migration status + if verify_migration_state( + action="prepare", + image_spec=f"{target_pool}/{target_image}", + **kw, + ): + log.error("Failed to prepare migration") + return 1 + else: + log.info("Migration prepare status verfied successfully") + + # execute migration + rbd.migration.action( + action="execute", + dest_spec=f"{target_pool}/{target_image}", + client_node=kw["client"], + ) + if err: + log.error(f"Migration execute failed with error {err}") + return 1 + else: + log.info("Successfully executed migration") + + # verify execute migration status + if verify_migration_state( + action="execute", + image_spec=f"{target_pool}/{target_image}", + **kw, + ): + log.error("Failed to execute migration") + return 1 + else: + log.info("Migration executed successfully") + + # commit migration + rbd.migration.action( + action="commit", + dest_spec=f"{target_pool}/{target_image}", + client_node=kw["client"], + ) + if err: + log.error(f"Migration Commit failed with error {err}") + return 1 + else: + log.info("Successfully committed migration") + + # verify commit migration status + if verify_migration_state( + action="commit", + image_spec=f"{target_pool}/{target_image}", + **kw, + ): + log.error("Failed to commit migration") + return 1 + else: + log.info("Migration committed successfully") + + map_config = { + "pool": target_pool, + "image": target_image, + "device-type": config.get("device_type", "nbd"), + } + options = create_map_options(kw[pool]["encryption_config"]) + map_config.update( + { + "options": options, + } + ) + out, err = rbd.device.map(**map_config) + + if err: + log.error(f"Failed to map migrated image {target_pool}/{target_image}") + return 1 + else: + log.info(f"Successfully mapped the migrated image {target_pool}/{target_image}") + + out, err = rbd.device.unmap(**map_config) + if err: + log.error(f"Failed to unmap migrated image {target_pool}/{target_image}") + return 1 + else: + log.info( + f"Successfully unmapped the migrated image {target_pool}/{target_image}" + ) + + data_integrity_spec = { + "first": { + "image_spec": f"{pool}/{image}", + "rbd": rbd, + "client": kw["client"], + "file_path": f"/tmp/{random_string(len=3)}", + }, + "second": { + "image_spec": f"{target_pool}/{target_image}", + "rbd": rbd, + "client": kw["client"], + "file_path": f"/tmp/{random_string(len=3)}", + }, + } + + rc = check_data_integrity(**data_integrity_spec) + if rc: + log.error(f"Data consistency check failed for {target_pool}/{target_image}") + return 1 + else: + log.info("Data is consistent between the source and target images.") + + +def run(**kw): + """ + This test verifies Live migration of qcow2 format images with encryption + Args: + kw: test data + Returns: + int: The return value. 0 for success, 1 otherwise + + """ + try: + + log.info( + f"{kw['config']['testconfig']['id']} - {kw['config']['testconfig']['name']}" + ) + + if kw.get("client_node"): + client = get_node_by_id(kw.get("ceph_cluster"), kw.get("client_node")) + else: + client = kw.get("ceph_cluster").get_nodes(role="client")[0] + rbd_obj = initial_rbd_config(**kw) + pool_types = rbd_obj.get("pool_types") + kw.update({"cleanup_files": []}) + if kw["config"]["testconfig"]["id"] == "CEPH-83596444": + func = migration_encrypted_raw_images + + elif kw["config"]["testconfig"]["id"] == "CEPH-83596588": + func = migration_encrypted_qcow_images + + if rbd_obj: + log.info("Executing test on Replicated and EC pool") + if func(rbd_obj, client, **kw): + return 1 + log.info(f"Test {kw['config']['testconfig']['name']} is successful") + + except Exception as e: + log.error(f"Test {kw['config']['testconfig']['name']} failed: {str(e)}") + return 1 + + finally: + try: + for file in kw["cleanup_files"]: + out, err = client.exec_command(sudo=True, cmd=f"rm -f {file}") + if err: + log.error(f"Failed to delete file {file}") + except Exception as e: + log.error(f"Failed to cleanup temp files with err {e}") + cluster_name = kw.get("ceph_cluster", {}).name + if "rbd_obj" not in locals(): + rbd_obj = Rbd(client) + obj = {cluster_name: rbd_obj} + cleanup(pool_types=pool_types, multi_cluster_obj=obj, **kw) + + return 0 From 123bc0cc1f3476b3e432661cac345517fb7a5ced Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Thu, 2 Jan 2025 18:00:31 +0530 Subject: [PATCH 45/50] Fix codeowners file Earlier cephci-top-reviewers had open permissions to merge code to any place. The teams mentioned for folders had no impact. This caused improper delegation of ownership. This change removes the top-reviewers group and sets the complete privileges to ceph-qe-ci and ceph-qe-admin groups. They have full access to merge. The delegation to each DFG is now done via specfic users with their managers having permissions to merge in their respective components. Going forward, anyone should be able to raise a PR to request for merge permissions with admin and ci teams having approval privileges. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- .github/CODEOWNERS | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2c6118ea46b..ae6d4fe5749 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,24 +1,29 @@ # These owners will be the default owners for everything in this repo. # all changes. -* @red-hat-storage/cephci-top-reviewers +* @red-hat-storage/ceph-qe-ci @red-hat-storage/ceph-qe-admin # for RGW -rgw/ @red-hat-storage/teams/cephci-rgw +rgw/ @mkasturi18 @ckulal @TejasC88 # for RBD team -rbd/ @red-hat-storage/teams/cephci-block -rbd_mirror/ @red-hat-storage/teams/cephci-block +rbd/ @Manohar-Murthy +rbd_mirror/ @Manohar-Murthy + +# for NVMe-oF +nvmeof/ @Manohar-Murthy @HaruChebrolu # for RADOS -rados/ @ed-hat-storage/teams/cephci-rados +rados/ @neha-gangadhar @pdhiran # for FS -cephfs/ @red-hat-storage/teams/cephci-fs +cephfs/ @neha-gangadhar @AmarnatReddy @Manimaran-MM + +# smb +smb/ @vdas-redhat @pranavprakash20 # for DMFG -ansible/ @red-hat-storage/teams/cephci-dm -upgrades/ @red-hat-storage/teams/cephci-dm -dashboard/ @red-hat-storage/teams/cephci-dm -cephadm/ @red-hat-storage/teams/cephci-dm -ceph_ansisble/ @red-hat-storage/teams/cephci-dm -ceph_installer/ @red-hat-storage/teams/cephci-dm +ceph_volume/ @vdas-redhat @pranavprakash20 +cephadm/ @vdas-redhat @pranavprakash20 +mgr/ @vdas-redhat @pranavprakash20 +nfs/ @vdas-redhat @pranavprakash20 +upgrades/ @vdas-redhat @pranavprakash20 From 4b8bfde94b4c2bd6851333dd1b3576ae98d7bd44 Mon Sep 17 00:00:00 2001 From: Amarnath K Date: Mon, 6 Jan 2025 23:00:00 +0530 Subject: [PATCH 46/50] Fixing method defnition Signed-off-by: Amarnath K Signed-off-by: Harishacharya-redhat --- .../cephfs_nfs/nfs_info_cluster_id_and_ls_export_detailed.py | 4 ++-- tests/cephfs/cephfs_utilsV1.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/cephfs/cephfs_nfs/nfs_info_cluster_id_and_ls_export_detailed.py b/tests/cephfs/cephfs_nfs/nfs_info_cluster_id_and_ls_export_detailed.py index 812730b3fd6..5b269a3e53c 100644 --- a/tests/cephfs/cephfs_nfs/nfs_info_cluster_id_and_ls_export_detailed.py +++ b/tests/cephfs/cephfs_nfs/nfs_info_cluster_id_and_ls_export_detailed.py @@ -60,7 +60,7 @@ def run(ceph_cluster, **kw): ) cluster_id = f"test-nfs_{rand}" path = "/" - export_id = "1" + fs_name = "cephfs" if not erasure else "cephfs-ec" fs_details = fs_util.get_fs_info(client1, fs_name) @@ -70,7 +70,7 @@ def run(ceph_cluster, **kw): user_id = ( f"nfs.{cluster_id}.{fs_name}" if int(build.split(".")[0]) == 7 - else f"nfs.{cluster_id}.{export_id}" + else f"nfs.{cluster_id}" ) passed = [] diff --git a/tests/cephfs/cephfs_utilsV1.py b/tests/cephfs/cephfs_utilsV1.py index ed68aac6277..a62a097e602 100644 --- a/tests/cephfs/cephfs_utilsV1.py +++ b/tests/cephfs/cephfs_utilsV1.py @@ -4986,7 +4986,6 @@ def runio_modify_max_mds( fs_name, clients, mount_paths, - mount_type, max_mds_value, ): """ From 9f88459a9b329584a7c816d53134d788440bb195 Mon Sep 17 00:00:00 2001 From: Harsh Kumar Date: Thu, 2 Jan 2025 10:02:02 +0530 Subject: [PATCH 47/50] RHCEPHQE-16887 | CEPH-83604474: Test to verify MAX_AVAIL updation upon OSD removal Signed-off-by: Harsh Kumar Signed-off-by: Harishacharya-redhat --- suites/quincy/rados/tier-4_rados_tests.yaml | 10 ++ suites/reef/rados/tier-4_rados_tests.yaml | 9 ++ suites/squid/rados/tier-4_rados_tests.yaml | 9 ++ tests/rados/test_cephdf.py | 145 ++++++++++++++++++++ 4 files changed, 173 insertions(+) diff --git a/suites/quincy/rados/tier-4_rados_tests.yaml b/suites/quincy/rados/tier-4_rados_tests.yaml index 290aa04e1b8..df462c3ebfb 100644 --- a/suites/quincy/rados/tier-4_rados_tests.yaml +++ b/suites/quincy/rados/tier-4_rados_tests.yaml @@ -189,6 +189,16 @@ tests: pool_name: test-max-avail obj_nums: 5 delete_pool: true + + - test: + name: Verify MAX_AVAIL variance when OSDs are removed + desc: MAX_AVAIL value update correctly when OSDs are removed + module: test_cephdf.py + polarion-id: CEPH-83604474 + config: + cephdf_max_avail_osd_rm: false + comments: bug to be fixed - BZ-2277857 + - test: name: Compression algorithms - modes module: rados_prep.py diff --git a/suites/reef/rados/tier-4_rados_tests.yaml b/suites/reef/rados/tier-4_rados_tests.yaml index 02ab5ea461e..5f8d4d6c34b 100644 --- a/suites/reef/rados/tier-4_rados_tests.yaml +++ b/suites/reef/rados/tier-4_rados_tests.yaml @@ -193,6 +193,15 @@ tests: config: cephdf_max_avail_osd_expand: true + - test: + name: Verify MAX_AVAIL variance when OSDs are removed + desc: MAX_AVAIL value update correctly when OSDs are removed + module: test_cephdf.py + polarion-id: CEPH-83604474 + config: + cephdf_max_avail_osd_rm: false + comments: bug to be fixed - BZ-2277178 + - test: name: Compression algorithms - modes module: rados_prep.py diff --git a/suites/squid/rados/tier-4_rados_tests.yaml b/suites/squid/rados/tier-4_rados_tests.yaml index a3c039f07b1..a0d15c34fd9 100644 --- a/suites/squid/rados/tier-4_rados_tests.yaml +++ b/suites/squid/rados/tier-4_rados_tests.yaml @@ -195,6 +195,15 @@ tests: # config: # cephdf_max_avail_osd_expand: true + - test: + name: Verify MAX_AVAIL variance when OSDs are removed + desc: MAX_AVAIL value update correctly when OSDs are removed + module: test_cephdf.py + polarion-id: CEPH-83604474 + config: + cephdf_max_avail_osd_rm: false + comments: bug to be fixed - BZ-2275995 + - test: name: Compression algorithms - modes module: rados_prep.py diff --git a/tests/rados/test_cephdf.py b/tests/rados/test_cephdf.py index 8e4898cf69b..6b5a493df46 100644 --- a/tests/rados/test_cephdf.py +++ b/tests/rados/test_cephdf.py @@ -4,8 +4,13 @@ 1. Verification of ceph df output upon creation & deletion of objects 2. MAX_AVAIL value should not change to an invalid value upon addition of osd with weight 0 +3. MAX AVAIL is displayed correctly for all the pools when OSD size is increased +4. MAX AVAIL is displayed correctly for all the pools when few OSDs are removed """ +import datetime +import math +import random import time from ceph.ceph_admin import CephAdmin @@ -538,3 +543,143 @@ def bytes_to_gb(val): "completed successfully" ) return 0 + + if config.get("cephdf_max_avail_osd_rm"): + desc = ( + "\n#CEPH-83604474" + "\nQuincy: BZ-2277857" + "\nReef: BZ-2277178" + "\nSquid: BZ-2275995" + "\nThis test is to verify that ceph df MAX AVAIL is displayed correctly for all the pools" + " when 25% of OSDs are removed from the cluster" + "\nSteps- \n" + "1. Creating a replicated and EC pool with default config\n" + "2. Log pool stats and verify max_avail \n" + "3. Remove 25% of OSDs from each OSD host\n" + "4. Log pool stats and verify max_avail \n" + "5. Re-deploy OSDs\n" + "6. Log pool stats and verify max_avail \n" + ) + + log.info(desc) + df_config = config.get("cephdf_max_avail_osd_rm") + pool_name = "test-osd-rm-ec" + + try: + # create default pool with given name + rados_obj.create_erasure_pool(pool_name=pool_name) + + init_osd_count = len(rados_obj.get_osd_list(status="up")) + + initial_pool_stat = rados_obj.get_cephdf_stats(pool_name=pool_name) + log.info(f"{pool_name} pool stat: {initial_pool_stat}") + + # execute max_avail check across the cluster + rados_obj.change_recovery_threads(config=config, action="set") + if not wait_for_clean_pg_sets(rados_obj, timeout=900): + log.error("Cluster cloud not reach active+clean state within 900 secs") + raise Exception("Cluster cloud not reach active+clean state") + + if not rados_obj.verify_max_avail(): + log.error("MAX_AVAIL deviates on the cluster more than expected") + raise Exception("MAX_AVAIL deviates on the cluster more than expected") + log.info("MAX_AVAIL on the cluster are as per expectation") + + # set osd service to unmanaged + utils.set_osd_devices_unmanaged(ceph_cluster, "1", unmanaged=True) + + # get OSD hosts + osd_hosts = ceph_cluster.get_nodes(role="osd") + + # remove OSDs from the cluster + for host in osd_hosts: + osd_list = rados_obj.collect_osd_daemon_ids(osd_node=host) + osd_rm_count = math.ceil(len(osd_list) * 0.25) + osds_rm = random.choices(osd_list, k=osd_rm_count) + for osd_id in osds_rm: + log.info(f"Removing OSD {osd_id} on host {host.hostname}") + dev_path = get_device_path(host=host, osd_id=osd_id) + assert utils.set_osd_out(ceph_cluster, osd_id=osd_id) + utils.osd_remove(ceph_cluster, osd_id=osd_id) + time.sleep(5) + assert utils.zap_device( + ceph_cluster, host=host.hostname, device_path=dev_path + ) + assert wait_for_device_rados( + host=host, osd_id=osd_id, action="remove", timeout=1000 + ) + + if not wait_for_clean_pg_sets(rados_obj, timeout=900): + log.error("Cluster cloud not reach active+clean state within 900 secs") + raise Exception("Cluster cloud not reach active+clean state") + + _pool_stat = rados_obj.get_cephdf_stats(pool_name=pool_name) + log.info(f"{pool_name} pool stat: {_pool_stat}") + + # execute max_avail check across the cluster after OSDs removal + if not rados_obj.verify_max_avail(): + log.error("MAX_AVAIL deviates on the cluster more than expected") + raise Exception("MAX_AVAIL deviates on the cluster more than expected") + log.info("MAX_AVAIL on the cluster are as per expectation") + + # set osd service to unmanaged False + utils.set_osd_devices_unmanaged(ceph_cluster, "1", unmanaged=False) + # wait for OSDs to get deployed, i.e. current UP OSD count == init UP OSD count + endtime = datetime.datetime.now() + datetime.timedelta(seconds=600) + while datetime.datetime.now() < endtime: + curr_osd_up = len( + rados_obj.run_ceph_command(cmd="ceph osd tree up", client_exec=True) + ) + if curr_osd_up != init_osd_count: + log.error( + "Current UP OSDs yet to reach original value, sleeping for 60 secs" + ) + time.sleep(60) + if datetime.datetime.now() > endtime: + raise Exception( + "Removed OSDs were not added back to the cluster within 10 mins" + ) + continue + log.info( + f"Current UP count [{curr_osd_up}] == Original UP OSD count [{init_osd_count}]" + ) + break + + if not wait_for_clean_pg_sets(rados_obj, timeout=900): + log.error("Cluster cloud not reach active+clean state within 900 secs") + raise Exception("Cluster cloud not reach active+clean state") + + _pool_stat = rados_obj.get_cephdf_stats(pool_name=pool_name) + log.info(f"{pool_name} pool stat: {_pool_stat}") + + # execute max_avail check across the cluster after OSDs addition + if not rados_obj.verify_max_avail(): + log.error("MAX_AVAIL deviates on the cluster more than expected") + raise Exception("MAX_AVAIL deviates on the cluster more than expected") + log.info("MAX_AVAIL on the cluster are as per expectation") + + except Exception as AE: + log.error(f"Failed with exception: {AE.__doc__}") + log.exception(AE) + return 1 + finally: + log.info("\n ************* Executing finally block **********\n") + rados_obj.delete_pool(pool=pool_name) + if not wait_for_clean_pg_sets(rados_obj, timeout=900): + log.error("Cluster cloud not reach active+clean state") + return 1 + rados_obj.change_recovery_threads(config=config, action="rm") + # set osd service to managed + utils.set_osd_devices_unmanaged(ceph_cluster, "1", unmanaged=False) + + # log cluster health + rados_obj.log_cluster_health() + # check for crashes after test execution + if rados_obj.check_crash_status(): + log.error("Test failed due to crash at the end of test") + return 1 + + log.info( + "ceph df MAX AVAIL stats verification upon OSDs removal completed successfully" + ) + return 0 From d8dc9496a3c48409cdcc7fb02c03f731945e6d83 Mon Sep 17 00:00:00 2001 From: Harsh Kumar Date: Fri, 3 Jan 2025 09:43:51 +0530 Subject: [PATCH 48/50] [RADOS] TFA: Exclude CBT qfsck and allocmap cmds for Pacific Signed-off-by: Harsh Kumar Signed-off-by: Harishacharya-redhat --- tests/rados/test_bluestoretool_workflows.py | 41 +++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/tests/rados/test_bluestoretool_workflows.py b/tests/rados/test_bluestoretool_workflows.py index c1d680f9bf8..52ff3bd05ac 100644 --- a/tests/rados/test_bluestoretool_workflows.py +++ b/tests/rados/test_bluestoretool_workflows.py @@ -464,27 +464,28 @@ def run(ceph_cluster, **kw): log.info(out) assert "success" in out - # Execute ceph-bluestore-tool qfsck --path - osd_id = random.choice(osd_list) - log.info( - f"\n --------------------" - f"\n Running quick consistency check for OSD {osd_id}" - f"\n --------------------" - ) - out = bluestore_obj.run_quick_consistency_check(osd_id=osd_id) - log.info(out) - assert "success" in out + if rhbuild.split(".")[0] >= "6": + # Execute ceph-bluestore-tool qfsck --path + osd_id = random.choice(osd_list) + log.info( + f"\n --------------------" + f"\n Running quick consistency check for OSD {osd_id}" + f"\n --------------------" + ) + out = bluestore_obj.run_quick_consistency_check(osd_id=osd_id) + log.info(out) + assert "success" in out - # Execute ceph-bluestore-tool allocmap --path - osd_id = random.choice(osd_list) - log.info( - f"\n --------------------" - f"\n Fetching allocmap for OSD {osd_id}" - f"\n ---------------------" - ) - out = bluestore_obj.fetch_allocmap(osd_id=osd_id) - log.info(out) - assert "success" in out + # Execute ceph-bluestore-tool allocmap --path + osd_id = random.choice(osd_list) + log.info( + f"\n --------------------" + f"\n Fetching allocmap for OSD {osd_id}" + f"\n ---------------------" + ) + out = bluestore_obj.fetch_allocmap(osd_id=osd_id) + log.info(out) + assert "success" in out # Execute ceph-bluestore-tool repair --path osd_id = random.choice(osd_list) From 8dd932d9438b069d7d3621bc6e5df16c1deda12f Mon Sep 17 00:00:00 2001 From: Harsh Kumar Date: Fri, 3 Jan 2025 09:54:33 +0530 Subject: [PATCH 49/50] [RADOS] Reduction execution time of tier-3_rados_test-4-node-ecpools test suite Signed-off-by: Harsh Kumar Signed-off-by: Harishacharya-redhat --- .../tier-3_rados_test-4-node-ecpools.yaml | 379 ++++++++--------- .../tier-3_rados_test-4-node-ecpools.yaml | 392 +++++++++-------- .../tier-3_rados_test-4-node-ecpools.yaml | 394 +++++++++--------- 3 files changed, 559 insertions(+), 606 deletions(-) diff --git a/suites/quincy/rados/tier-3_rados_test-4-node-ecpools.yaml b/suites/quincy/rados/tier-3_rados_test-4-node-ecpools.yaml index bc3096a9e26..62c5ef4310f 100644 --- a/suites/quincy/rados/tier-3_rados_test-4-node-ecpools.yaml +++ b/suites/quincy/rados/tier-3_rados_test-4-node-ecpools.yaml @@ -111,21 +111,6 @@ tests: mds: "allow *" mgr: "allow *" - - test: - name: Configure email alerts - module: rados_prep.py - polarion-id: CEPH-83574472 - config: - email_alerts: - smtp_host: smtp.corp.redhat.com - smtp_sender: ceph-iad2-c01-lab.mgr@redhat.com - smtp_port: 25 - interval: 10 - smtp_destination: - - pdhiran@redhat.com - smtp_from_name: EC 2+2@4 cluster alerts - desc: Configure email alerts on ceph cluster - - test: name: Enable logging to file module: rados_prep.py @@ -196,33 +181,33 @@ tests: delete_pool: true desc: Verify Recovery of EC pool with only "k" shards available - - test: - name: EC pool LC - module: rados_prep.py - polarion-id: CEPH-83571632 - config: - ec_pool: - create: true - pool_name: test_ec_pool - pg_num: 64 - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - disable_pg_autoscale: true - rados_write_duration: 50 - rados_read_duration: 30 - set_pool_configs: - pool_name: test_ec_pool - configurations: - pg_num: 32 - pgp_num: 32 - pg_autoscale_mode: 'on' - compression_mode: force - compression_algorithm: snappy - delete_pools: - - test_ec_pool - desc: Create, modify & delete EC pools and run IO +# - test: +# name: EC pool LC +# module: rados_prep.py +# polarion-id: CEPH-83571632 +# config: +# ec_pool: +# create: true +# pool_name: test_ec_pool +# pg_num: 64 +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# disable_pg_autoscale: true +# rados_write_duration: 50 +# rados_read_duration: 30 +# set_pool_configs: +# pool_name: test_ec_pool +# configurations: +# pg_num: 32 +# pgp_num: 32 +# pg_autoscale_mode: 'on' +# compression_mode: force +# compression_algorithm: snappy +# delete_pools: +# - test_ec_pool +# desc: Create, modify & delete EC pools and run IO - test: name: EC pool with Overwrites @@ -296,39 +281,39 @@ tests: byte_size: 10KB desc: Verification of the effect of compression on erasure coded pools - - test: - name: Autoscaler test - pool target size ratio - module: pool_tests.py - polarion-id: CEPH-83573424 - config: - verify_pool_target_ratio: - configurations: - pool-1: - profile_name: ec86_7 - pool_name: ec86_pool7 - pool_type: erasure - pg_num: 32 - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - target_size_ratio: 0.8 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - - test: - name: ceph-bluestore-tool utility - module: test_bluestoretool_workflows.py - polarion-id: CEPH-83571692 - desc: Verify ceph-bluestore-tool functionalities +# - test: +# name: Autoscaler test - pool target size ratio +# module: pool_tests.py +# polarion-id: CEPH-83573424 +# config: +# verify_pool_target_ratio: +# configurations: +# pool-1: +# profile_name: ec86_7 +# pool_name: ec86_pool7 +# pool_type: erasure +# pg_num: 32 +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# target_size_ratio: 0.8 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - test: - name: ceph-objectstore-tool utility - module: test_objectstoretool_workflows.py - polarion-id: CEPH-83581811 - desc: Verify ceph-objectstore-tool functionalities +# - test: +# name: ceph-bluestore-tool utility +# module: test_bluestoretool_workflows.py +# polarion-id: CEPH-83571692 +# desc: Verify ceph-bluestore-tool functionalities +# +# - test: +# name: ceph-objectstore-tool utility +# module: test_objectstoretool_workflows.py +# polarion-id: CEPH-83581811 +# desc: Verify ceph-objectstore-tool functionalities - test: name: Verify premerge PGS during PG split @@ -388,80 +373,80 @@ tests: pool_configs_path: "conf/quincy/rados/test-confs/pool-configurations.yaml" desc: Verify that scrub & deep-scrub logs are captured in OSD logs - - test: - name: Autoscaler test - pool target size ratio - module: pool_tests.py - polarion-id: CEPH-83573424 - config: - verify_pool_target_ratio: - configurations: - pool-1: - profile_name: ec86_10 - pool_name: ec86_pool10 - pool_type: erasure - pg_num: 32 - k: 2 - m: 2 - crush-failure-domain: host - plugin: jerasure - target_size_ratio: 0.8 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio +# - test: +# name: Autoscaler test - pool target size ratio +# module: pool_tests.py +# polarion-id: CEPH-83573424 +# config: +# verify_pool_target_ratio: +# configurations: +# pool-1: +# profile_name: ec86_10 +# pool_name: ec86_pool10 +# pool_type: erasure +# pg_num: 32 +# k: 2 +# m: 2 +# crush-failure-domain: host +# plugin: jerasure +# target_size_ratio: 0.8 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - test: - name: Autoscaler test - pool pg_num_min - module: pool_tests.py - polarion-id: CEPH-83573425 - config: - verify_pg_num_min: - configurations: - pool-1: - profile_name: ec86_11 - pool_name: ec86_pool11 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - pg_num_min: 16 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify pg_num_min +# - test: +# name: Autoscaler test - pool pg_num_min +# module: pool_tests.py +# polarion-id: CEPH-83573425 +# config: +# verify_pg_num_min: +# configurations: +# pool-1: +# profile_name: ec86_11 +# pool_name: ec86_pool11 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# pg_num_min: 16 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify pg_num_min - - test: - name: client pg access - module: test_client_pg_access.py - polarion-id: CEPH-83571713 - config: - verify_client_pg_access: - num_snapshots: 20 - num_objects: 250 - configurations: - pool-1: - profile_name: ec86_12 - pool_name: ec86_pool12 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - disable_pg_autoscale: true - desc: many clients clients accessing same PG with bluestore as backend +# - test: +# name: client pg access +# module: test_client_pg_access.py +# polarion-id: CEPH-83571713 +# config: +# verify_client_pg_access: +# num_snapshots: 20 +# num_objects: 250 +# configurations: +# pool-1: +# profile_name: ec86_12 +# pool_name: ec86_pool12 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# disable_pg_autoscale: true +# desc: many clients clients accessing same PG with bluestore as backend - - test: - name: Migrate data bw pools. - module: test_data_migration_bw_pools.py - polarion-id: CEPH-83574768 - config: - pool-1-type: replicated - pool-2-type: erasure - pool-1-conf: sample-pool-1 - pool-2-conf: sample-pool-4 - pool_configs_path: "conf/quincy/rados/test-confs/pool-configurations.yaml" - desc: Migrating data between different pools. Scenario-2. RE -> EC +# - test: +# name: Migrate data bw pools. +# module: test_data_migration_bw_pools.py +# polarion-id: CEPH-83574768 +# config: +# pool-1-type: replicated +# pool-2-type: erasure +# pool-1-conf: sample-pool-1 +# pool-2-conf: sample-pool-4 +# pool_configs_path: "conf/quincy/rados/test-confs/pool-configurations.yaml" +# desc: Migrating data between different pools. Scenario-2. RE -> EC - test: name: Migrate data bw pools. @@ -488,60 +473,60 @@ tests: desc: Migrating data between different pools. Scenario-4. Ec -> EC # Blocked due to BZ 2172795. Bugzilla fixed. - - test: - name: Verify cluster behaviour during PG autoscaler warn - module: pool_tests.py - polarion-id: CEPH-83573413 - config: - verify_pool_warnings: - pool_configs: - - type: erasure - conf: sample-pool-4 - pool_configs_path: "conf/quincy/rados/test-confs/pool-configurations.yaml" - desc: Verify alerts for large number of Objs per OSD during PG autoscaler warn +# - test: +# name: Verify cluster behaviour during PG autoscaler warn +# module: pool_tests.py +# polarion-id: CEPH-83573413 +# config: +# verify_pool_warnings: +# pool_configs: +# - type: erasure +# conf: sample-pool-4 +# pool_configs_path: "conf/quincy/rados/test-confs/pool-configurations.yaml" +# desc: Verify alerts for large number of Objs per OSD during PG autoscaler warn - - test: - name: Scrub enhancement - module: test_scrub_enhancement.py - desc: Verify scrub enhancement feature - polarion-id: CEPH-83575885 - config: - create_pools: - - create_pool: - pg_num: 1 - pg_num_max: 1 - profile_name: ec86_13 - pool_name: ec86_pool13 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - delete_pools: - - ec86_pool13 +# - test: +# name: Scrub enhancement +# module: test_scrub_enhancement.py +# desc: Verify scrub enhancement feature +# polarion-id: CEPH-83575885 +# config: +# create_pools: +# - create_pool: +# pg_num: 1 +# pg_num_max: 1 +# profile_name: ec86_13 +# pool_name: ec86_pool13 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# delete_pools: +# - ec86_pool13 - - test: - name: Limit slow request details to cluster log - module: test_slow_op_requests.py - desc: Limit slow request details to cluster log - polarion-id: CEPH-83574884 - config: - create_pools: - - create_pool: - profile_name: ec86_14 - pool_name: ec86_pool14 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - pg_num: 64 - rados_write_duration: 1000 - byte_size: 1024 - osd_max_backfills: 16 - osd_recovery_max_active: 16 - delete_pools: - - ec86_pool14 +# - test: +# name: Limit slow request details to cluster log +# module: test_slow_op_requests.py +# desc: Limit slow request details to cluster log +# polarion-id: CEPH-83574884 +# config: +# create_pools: +# - create_pool: +# profile_name: ec86_14 +# pool_name: ec86_pool14 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# pg_num: 64 +# rados_write_duration: 1000 +# byte_size: 1024 +# osd_max_backfills: 16 +# osd_recovery_max_active: 16 +# delete_pools: +# - ec86_pool14 - test: name: Robust rebalancing - in progress osd replacement diff --git a/suites/reef/rados/tier-3_rados_test-4-node-ecpools.yaml b/suites/reef/rados/tier-3_rados_test-4-node-ecpools.yaml index 30a503d18cf..8c4da143ff1 100644 --- a/suites/reef/rados/tier-3_rados_test-4-node-ecpools.yaml +++ b/suites/reef/rados/tier-3_rados_test-4-node-ecpools.yaml @@ -144,22 +144,6 @@ tests: mds: "allow *" mgr: "allow *" - - - test: - name: Configure email alerts - module: rados_prep.py - polarion-id: CEPH-83574472 - config: - email_alerts: - smtp_host: smtp.corp.redhat.com - smtp_sender: ceph-iad2-c01-lab.mgr@redhat.com - smtp_port: 25 - interval: 10 - smtp_destination: - - pdhiran@redhat.com - smtp_from_name: EC 2+2@4 cluster alerts - desc: Configure email alerts on ceph cluster - - test: name: Enable logging to file module: rados_prep.py @@ -230,33 +214,33 @@ tests: delete_pool: true desc: Verify Recovery of EC pool with only "k" shards available - - test: - name: EC pool LC - module: rados_prep.py - polarion-id: CEPH-83571632 - config: - ec_pool: - create: true - pool_name: test_ec_pool - pg_num: 64 - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - disable_pg_autoscale: true - rados_write_duration: 50 - rados_read_duration: 30 - set_pool_configs: - pool_name: test_ec_pool - configurations: - pg_num: 32 - pgp_num: 32 - pg_autoscale_mode: 'on' - compression_mode: force - compression_algorithm: snappy - delete_pools: - - test_ec_pool - desc: Create, modify & delete EC pools and run IO +# - test: +# name: EC pool LC +# module: rados_prep.py +# polarion-id: CEPH-83571632 +# config: +# ec_pool: +# create: true +# pool_name: test_ec_pool +# pg_num: 64 +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# disable_pg_autoscale: true +# rados_write_duration: 50 +# rados_read_duration: 30 +# set_pool_configs: +# pool_name: test_ec_pool +# configurations: +# pg_num: 32 +# pgp_num: 32 +# pg_autoscale_mode: 'on' +# compression_mode: force +# compression_algorithm: snappy +# delete_pools: +# - test_ec_pool +# desc: Create, modify & delete EC pools and run IO - test: name: EC pool with Overwrites @@ -330,39 +314,39 @@ tests: byte_size: 10KB desc: Verification of the effect of compression on erasure coded pools - - test: - name: Autoscaler test - pool target size ratio - module: pool_tests.py - polarion-id: CEPH-83573424 - config: - verify_pool_target_ratio: - configurations: - pool-1: - profile_name: ec86_7 - pool_name: ec86_pool7 - pool_type: erasure - pg_num: 32 - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - target_size_ratio: 0.8 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - - test: - name: ceph-bluestore-tool utility - module: test_bluestoretool_workflows.py - polarion-id: CEPH-83571692 - desc: Verify ceph-bluestore-tool functionalities - - - test: - name: ceph-objectstore-tool utility - module: test_objectstoretool_workflows.py - polarion-id: CEPH-83581811 - desc: Verify ceph-objectstore-tool functionalities +# - test: +# name: Autoscaler test - pool target size ratio +# module: pool_tests.py +# polarion-id: CEPH-83573424 +# config: +# verify_pool_target_ratio: +# configurations: +# pool-1: +# profile_name: ec86_7 +# pool_name: ec86_pool7 +# pool_type: erasure +# pg_num: 32 +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# target_size_ratio: 0.8 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio + +# - test: +# name: ceph-bluestore-tool utility +# module: test_bluestoretool_workflows.py +# polarion-id: CEPH-83571692 +# desc: Verify ceph-bluestore-tool functionalities +# +# - test: +# name: ceph-objectstore-tool utility +# module: test_objectstoretool_workflows.py +# polarion-id: CEPH-83581811 +# desc: Verify ceph-objectstore-tool functionalities - test: name: Verify premerge PGS during PG split @@ -422,80 +406,80 @@ tests: pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" desc: Verify that scrub & deep-scrub logs are captured in OSD logs - - test: - name: Autoscaler test - pool target size ratio - module: pool_tests.py - polarion-id: CEPH-83573424 - config: - verify_pool_target_ratio: - configurations: - pool-1: - profile_name: ec86_10 - pool_name: ec86_pool10 - pool_type: erasure - pg_num: 32 - k: 2 - m: 2 - crush-failure-domain: host - plugin: jerasure - target_size_ratio: 0.8 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - - test: - name: Autoscaler test - pool pg_num_min - module: pool_tests.py - polarion-id: CEPH-83573425 - config: - verify_pg_num_min: - configurations: - pool-1: - profile_name: ec86_11 - pool_name: ec86_pool11 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - pg_num_min: 16 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify pg_num_min - - - test: - name: client pg access - module: test_client_pg_access.py - polarion-id: CEPH-83571713 - config: - verify_client_pg_access: - num_snapshots: 20 - num_objects: 250 - configurations: - pool-1: - profile_name: ec86_12 - pool_name: ec86_pool12 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - disable_pg_autoscale: true - desc: many clients clients accessing same PG with bluestore as backend - - - test: - name: Migrate data bw pools. - module: test_data_migration_bw_pools.py - polarion-id: CEPH-83574768 - config: - pool-1-type: replicated - pool-2-type: erasure - pool-1-conf: sample-pool-1 - pool-2-conf: sample-pool-5 - pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" - desc: Migrating data between different pools. Scenario-2. RE -> EC +# - test: +# name: Autoscaler test - pool target size ratio +# module: pool_tests.py +# polarion-id: CEPH-83573424 +# config: +# verify_pool_target_ratio: +# configurations: +# pool-1: +# profile_name: ec86_10 +# pool_name: ec86_pool10 +# pool_type: erasure +# pg_num: 32 +# k: 2 +# m: 2 +# crush-failure-domain: host +# plugin: jerasure +# target_size_ratio: 0.8 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio + +# - test: +# name: Autoscaler test - pool pg_num_min +# module: pool_tests.py +# polarion-id: CEPH-83573425 +# config: +# verify_pg_num_min: +# configurations: +# pool-1: +# profile_name: ec86_11 +# pool_name: ec86_pool11 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# pg_num_min: 16 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify pg_num_min + +# - test: +# name: client pg access +# module: test_client_pg_access.py +# polarion-id: CEPH-83571713 +# config: +# verify_client_pg_access: +# num_snapshots: 20 +# num_objects: 250 +# configurations: +# pool-1: +# profile_name: ec86_12 +# pool_name: ec86_pool12 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# disable_pg_autoscale: true +# desc: many clients clients accessing same PG with bluestore as backend + +# - test: +# name: Migrate data bw pools. +# module: test_data_migration_bw_pools.py +# polarion-id: CEPH-83574768 +# config: +# pool-1-type: replicated +# pool-2-type: erasure +# pool-1-conf: sample-pool-1 +# pool-2-conf: sample-pool-5 +# pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" +# desc: Migrating data between different pools. Scenario-2. RE -> EC - test: name: Migrate data bw pools. @@ -522,60 +506,60 @@ tests: desc: Migrating data between different pools. Scenario-4. Ec -> EC # Blocked due to BZ 2172795. Bugzilla fixed. - - test: - name: Verify cluster behaviour during PG autoscaler warn - module: pool_tests.py - polarion-id: CEPH-83573413 - config: - verify_pool_warnings: - pool_configs: - - type: erasure - conf: sample-pool-5 - pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" - desc: Verify alerts for large number of Objs per OSD during PG autoscaler warn - - - test: - name: Scrub enhancement - module: test_scrub_enhancement.py - desc: Verify scrub enhancement feature - polarion-id: CEPH-83575885 - config: - create_pools: - - create_pool: - pg_num: 1 - pg_num_max: 1 - profile_name: ec86_13 - pool_name: ec86_pool13 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - delete_pools: - - ec86_pool13 - - - test: - name: Limit slow request details to cluster log - module: test_slow_op_requests.py - desc: Limit slow request details to cluster log - polarion-id: CEPH-83574884 - config: - create_pools: - - create_pool: - profile_name: ec86_14 - pool_name: ec86_pool14 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - pg_num: 64 - rados_write_duration: 1000 - byte_size: 1024 - osd_max_backfills: 16 - osd_recovery_max_active: 16 - delete_pools: - - ec86_pool14 +# - test: +# name: Verify cluster behaviour during PG autoscaler warn +# module: pool_tests.py +# polarion-id: CEPH-83573413 +# config: +# verify_pool_warnings: +# pool_configs: +# - type: erasure +# conf: sample-pool-5 +# pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" +# desc: Verify alerts for large number of Objs per OSD during PG autoscaler warn + +# - test: +# name: Scrub enhancement +# module: test_scrub_enhancement.py +# desc: Verify scrub enhancement feature +# polarion-id: CEPH-83575885 +# config: +# create_pools: +# - create_pool: +# pg_num: 1 +# pg_num_max: 1 +# profile_name: ec86_13 +# pool_name: ec86_pool13 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# delete_pools: +# - ec86_pool13 + +# - test: +# name: Limit slow request details to cluster log +# module: test_slow_op_requests.py +# desc: Limit slow request details to cluster log +# polarion-id: CEPH-83574884 +# config: +# create_pools: +# - create_pool: +# profile_name: ec86_14 +# pool_name: ec86_pool14 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# pg_num: 64 +# rados_write_duration: 1000 +# byte_size: 1024 +# osd_max_backfills: 16 +# osd_recovery_max_active: 16 +# delete_pools: +# - ec86_pool14 - test: name: Robust rebalancing - in progress osd replacement diff --git a/suites/squid/rados/tier-3_rados_test-4-node-ecpools.yaml b/suites/squid/rados/tier-3_rados_test-4-node-ecpools.yaml index 87339410fec..2b11a25e56c 100644 --- a/suites/squid/rados/tier-3_rados_test-4-node-ecpools.yaml +++ b/suites/squid/rados/tier-3_rados_test-4-node-ecpools.yaml @@ -144,22 +144,6 @@ tests: mds: "allow *" mgr: "allow *" - - - test: - name: Configure email alerts - module: rados_prep.py - polarion-id: CEPH-83574472 - config: - email_alerts: - smtp_host: smtp.corp.redhat.com - smtp_sender: ceph-iad2-c01-lab.mgr@redhat.com - smtp_port: 25 - interval: 10 - smtp_destination: - - pdhiran@redhat.com - smtp_from_name: EC 2+2@4 cluster alerts - desc: Configure email alerts on ceph cluster - - test: name: Enable logging to file module: rados_prep.py @@ -230,33 +214,33 @@ tests: delete_pool: true desc: Verify Recovery of EC pool with only "k" shards available - - test: - name: EC pool LC - module: rados_prep.py - polarion-id: CEPH-83571632 - config: - ec_pool: - create: true - pool_name: test_ec_pool - pg_num: 64 - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - disable_pg_autoscale: true - rados_write_duration: 50 - rados_read_duration: 30 - set_pool_configs: - pool_name: test_ec_pool - configurations: - pg_num: 32 - pgp_num: 32 - pg_autoscale_mode: 'on' - compression_mode: force - compression_algorithm: snappy - delete_pools: - - test_ec_pool - desc: Create, modify & delete EC pools and run IO +# - test: +# name: EC pool LC +# module: rados_prep.py +# polarion-id: CEPH-83571632 +# config: +# ec_pool: +# create: true +# pool_name: test_ec_pool +# pg_num: 64 +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# disable_pg_autoscale: true +# rados_write_duration: 50 +# rados_read_duration: 30 +# set_pool_configs: +# pool_name: test_ec_pool +# configurations: +# pg_num: 32 +# pgp_num: 32 +# pg_autoscale_mode: 'on' +# compression_mode: force +# compression_algorithm: snappy +# delete_pools: +# - test_ec_pool +# desc: Create, modify & delete EC pools and run IO - test: name: EC pool with Overwrites @@ -330,39 +314,39 @@ tests: byte_size: 10KB desc: Verification of the effect of compression on erasure coded pools - - test: - name: Autoscaler test - pool target size ratio - module: pool_tests.py - polarion-id: CEPH-83573424 - config: - verify_pool_target_ratio: - configurations: - pool-1: - profile_name: ec86_7 - pool_name: ec86_pool7 - pool_type: erasure - pg_num: 32 - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - target_size_ratio: 0.8 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - - test: - name: ceph-bluestore-tool utility - module: test_bluestoretool_workflows.py - polarion-id: CEPH-83571692 - desc: Verify ceph-bluestore-tool functionalities - - - test: - name: ceph-objectstore-tool utility - module: test_objectstoretool_workflows.py - polarion-id: CEPH-83581811 - desc: Verify ceph-objectstore-tool functionalities +# - test: +# name: Autoscaler test - pool target size ratio +# module: pool_tests.py +# polarion-id: CEPH-83573424 +# config: +# verify_pool_target_ratio: +# configurations: +# pool-1: +# profile_name: ec86_7 +# pool_name: ec86_pool7 +# pool_type: erasure +# pg_num: 32 +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# target_size_ratio: 0.8 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio + +# - test: +# name: ceph-bluestore-tool utility +# module: test_bluestoretool_workflows.py +# polarion-id: CEPH-83571692 +# desc: Verify ceph-bluestore-tool functionalities +# +# - test: +# name: ceph-objectstore-tool utility +# module: test_objectstoretool_workflows.py +# polarion-id: CEPH-83581811 +# desc: Verify ceph-objectstore-tool functionalities - test: name: Verify premerge PGS during PG split @@ -423,80 +407,80 @@ tests: pool_configs_path: "conf/squid/rados/test-confs/pool-configurations.yaml" desc: Verify that scrub & deep-scrub logs are captured in OSD logs - - test: - name: Autoscaler test - pool target size ratio - module: pool_tests.py - polarion-id: CEPH-83573424 - config: - verify_pool_target_ratio: - configurations: - pool-1: - profile_name: ec86_10 - pool_name: ec86_pool10 - pool_type: erasure - pg_num: 32 - k: 2 - m: 2 - crush-failure-domain: host - plugin: jerasure - target_size_ratio: 0.8 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio - - - test: - name: Autoscaler test - pool pg_num_min - module: pool_tests.py - polarion-id: CEPH-83573425 - config: - verify_pg_num_min: - configurations: - pool-1: - profile_name: ec86_11 - pool_name: ec86_pool11 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - pg_num_min: 16 - rados_write_duration: 50 - rados_read_duration: 50 - delete_pool: true - desc: Specifying pool bounds on pool Pgs - Verify pg_num_min - - - test: - name: client pg access - module: test_client_pg_access.py - polarion-id: CEPH-83571713 - config: - verify_client_pg_access: - num_snapshots: 20 - num_objects: 250 - configurations: - pool-1: - profile_name: ec86_12 - pool_name: ec86_pool12 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - disable_pg_autoscale: true - desc: many clients clients accessing same PG with bluestore as backend - - - test: - name: Migrate data bw pools. - module: test_data_migration_bw_pools.py - polarion-id: CEPH-83574768 - config: - pool-1-type: replicated - pool-2-type: erasure - pool-1-conf: sample-pool-1 - pool-2-conf: sample-pool-5 - pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" - desc: Migrating data between different pools. Scenario-2. RE -> EC +# - test: +# name: Autoscaler test - pool target size ratio +# module: pool_tests.py +# polarion-id: CEPH-83573424 +# config: +# verify_pool_target_ratio: +# configurations: +# pool-1: +# profile_name: ec86_10 +# pool_name: ec86_pool10 +# pool_type: erasure +# pg_num: 32 +# k: 2 +# m: 2 +# crush-failure-domain: host +# plugin: jerasure +# target_size_ratio: 0.8 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify target_size_ratio + +# - test: +# name: Autoscaler test - pool pg_num_min +# module: pool_tests.py +# polarion-id: CEPH-83573425 +# config: +# verify_pg_num_min: +# configurations: +# pool-1: +# profile_name: ec86_11 +# pool_name: ec86_pool11 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# pg_num_min: 16 +# rados_write_duration: 50 +# rados_read_duration: 50 +# delete_pool: true +# desc: Specifying pool bounds on pool Pgs - Verify pg_num_min + +# - test: +# name: client pg access +# module: test_client_pg_access.py +# polarion-id: CEPH-83571713 +# config: +# verify_client_pg_access: +# num_snapshots: 20 +# num_objects: 250 +# configurations: +# pool-1: +# profile_name: ec86_12 +# pool_name: ec86_pool12 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# disable_pg_autoscale: true +# desc: many clients clients accessing same PG with bluestore as backend + +# - test: +# name: Migrate data bw pools. +# module: test_data_migration_bw_pools.py +# polarion-id: CEPH-83574768 +# config: +# pool-1-type: replicated +# pool-2-type: erasure +# pool-1-conf: sample-pool-1 +# pool-2-conf: sample-pool-5 +# pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" +# desc: Migrating data between different pools. Scenario-2. RE -> EC - test: name: Migrate data bw pools. @@ -522,61 +506,61 @@ tests: pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" desc: Migrating data between different pools. Scenario-4. Ec -> EC -# Blocked due to BZ 2172795. Bugzilla fixed. - - test: - name: Verify cluster behaviour during PG autoscaler warn - module: pool_tests.py - polarion-id: CEPH-83573413 - config: - verify_pool_warnings: - pool_configs: - - type: erasure - conf: sample-pool-5 - pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" - desc: Verify alerts for large number of Objs per OSD during PG autoscaler warn - - - test: - name: Scrub enhancement - module: test_scrub_enhancement.py - desc: Verify scrub enhancement feature - polarion-id: CEPH-83575885 - config: - create_pools: - - create_pool: - pg_num: 1 - pg_num_max: 1 - profile_name: ec86_13 - pool_name: ec86_pool13 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - delete_pools: - - ec86_pool13 - - - test: - name: Limit slow request details to cluster log - module: test_slow_op_requests.py - desc: Limit slow request details to cluster log - polarion-id: CEPH-83574884 - config: - create_pools: - - create_pool: - profile_name: ec86_14 - pool_name: ec86_pool14 - pool_type: erasure - k: 2 - m: 2 - plugin: jerasure - crush-failure-domain: host - pg_num: 64 - rados_write_duration: 1000 - byte_size: 1024 - osd_max_backfills: 16 - osd_recovery_max_active: 16 - delete_pools: - - ec86_pool14 +## Blocked due to BZ 2172795. Bugzilla fixed. +# - test: +# name: Verify cluster behaviour during PG autoscaler warn +# module: pool_tests.py +# polarion-id: CEPH-83573413 +# config: +# verify_pool_warnings: +# pool_configs: +# - type: erasure +# conf: sample-pool-5 +# pool_configs_path: "conf/reef/rados/test-confs/pool-configurations.yaml" +# desc: Verify alerts for large number of Objs per OSD during PG autoscaler warn + +# - test: +# name: Scrub enhancement +# module: test_scrub_enhancement.py +# desc: Verify scrub enhancement feature +# polarion-id: CEPH-83575885 +# config: +# create_pools: +# - create_pool: +# pg_num: 1 +# pg_num_max: 1 +# profile_name: ec86_13 +# pool_name: ec86_pool13 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# delete_pools: +# - ec86_pool13 + +# - test: +# name: Limit slow request details to cluster log +# module: test_slow_op_requests.py +# desc: Limit slow request details to cluster log +# polarion-id: CEPH-83574884 +# config: +# create_pools: +# - create_pool: +# profile_name: ec86_14 +# pool_name: ec86_pool14 +# pool_type: erasure +# k: 2 +# m: 2 +# plugin: jerasure +# crush-failure-domain: host +# pg_num: 64 +# rados_write_duration: 1000 +# byte_size: 1024 +# osd_max_backfills: 16 +# osd_recovery_max_active: 16 +# delete_pools: +# - ec86_pool14 - test: name: Robust rebalancing - in progress osd replacement From 3ad94d54b4d667ee650c38ad36d0281ee1dd5ac0 Mon Sep 17 00:00:00 2001 From: Pragadeeswaran Sathyanarayanan Date: Tue, 7 Jan 2025 14:23:41 +0530 Subject: [PATCH 50/50] Fix mergify configuration With the fix of code owners, we removed the top level reviewers group. This enabled us to align with the purpose of codeowners file. After the fix merged, the mergify configuration was left unchanged resulting in a broken condition. This PR fixes the mergify conditions and moves the merge mechanism to queue. Signed-off-by: Pragadeeswaran Sathyanarayanan Signed-off-by: Harishacharya-redhat --- .github/mergify.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/mergify.yml b/.github/mergify.yml index 552d3e4e567..61ef090a768 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -5,12 +5,12 @@ pull_request_rules: - label!=DNM - label!=work-in-progress - base=main - - "approved-reviews-by=@red-hat-storage/cephci-top-level-reviewers" + - branch-protection-review-decision=approved - "check-success=tox (3.9.18)" - check-success=WIP actions: - merge: - method: merge + queue: + merge_method: merge - name: ask to resolve conflict conditions: - conflict