From 45b365fd42a9030efcdde54aae8a62074b53ba34 Mon Sep 17 00:00:00 2001 From: Jenia Peimer Date: Wed, 29 Apr 2026 12:13:55 +0300 Subject: [PATCH 1/4] [CCLM] Add cross-storage cross-cluster migration tests Signed-off-by: Jenia Peimer --- tests/storage/constants.py | 12 +++ .../cross_cluster_live_migration/conftest.py | 54 +++++++++-- .../cross_cluster_live_migration/test_cclm.py | 94 ++++++++++++++++++- tests/storage/storage_migration/conftest.py | 3 +- tests/storage/storage_migration/constants.py | 12 --- .../test_storage_class_migration.py | 3 +- tests/storage/storage_migration/utils.py | 13 --- tests/storage/utils.py | 13 +++ 8 files changed, 162 insertions(+), 42 deletions(-) diff --git a/tests/storage/constants.py b/tests/storage/constants.py index 7b110c3e17..4b223f9452 100644 --- a/tests/storage/constants.py +++ b/tests/storage/constants.py @@ -22,3 +22,15 @@ TEST_FILE_NAME = "test-file.txt" TEST_FILE_CONTENT = "test-content" + +STORAGE_CLASS_A = "storage_class_a" +STORAGE_CLASS_B = "storage_class_b" + +NO_STORAGE_CLASS_FAILURE_MESSAGE = ( + f"Test failed: {'{storage_class}'} storage class is not deployed. " + f"Available storage classes: {'{cluster_storage_classes_names}'}. " + "Ensure the correct storage_class is set in the global_config, " + "or override it with the pytest params: " + f"--tc={STORAGE_CLASS_A}: " + f"--tc={STORAGE_CLASS_B}:" +) diff --git a/tests/storage/cross_cluster_live_migration/conftest.py b/tests/storage/cross_cluster_live_migration/conftest.py index e62305a044..2b7b75ac41 100644 --- a/tests/storage/cross_cluster_live_migration/conftest.py +++ b/tests/storage/cross_cluster_live_migration/conftest.py @@ -18,6 +18,7 @@ from ocp_resources.resource import get_client from ocp_resources.route import Route from ocp_resources.secret import Secret +from ocp_resources.storage_class import StorageClass from ocp_resources.storage_map import StorageMap from ocp_resources.virtual_machine_cluster_instancetype import ( VirtualMachineClusterInstancetype, @@ -33,6 +34,7 @@ configure_hco_live_migration_network, get_vm_boot_id_via_console, ) +from tests.storage.utils import get_storage_class_for_storage_migration from utilities.artifactory import ( get_artifactory_config_map, get_artifactory_secret, @@ -344,8 +346,35 @@ def local_cluster_mtv_provider_for_local_cluster(admin_client, mtv_namespace): @pytest.fixture(scope="module") +def remote_cluster_storage_classes_names(remote_admin_client): + return [sc.name for sc in list(StorageClass.get(client=remote_admin_client))] + + +@pytest.fixture(scope="class") +def remote_cluster_source_storage_class(request, remote_cluster_storage_classes_names): + # Storage class for the original VMs creation in the remote cluster + return get_storage_class_for_storage_migration( + storage_class=request.param["source_storage_class"], + cluster_storage_classes_names=remote_cluster_storage_classes_names, + ) + + +@pytest.fixture(scope="class") +def local_cluster_target_storage_class(request, cluster_storage_classes_names): + # Storage class for the target VMs in the local cluster + return get_storage_class_for_storage_migration( + storage_class=request.param["target_storage_class"], cluster_storage_classes_names=cluster_storage_classes_names + ) + + +@pytest.fixture(scope="class") def local_cluster_mtv_storage_map( - admin_client, local_cluster_mtv_provider_for_local_cluster, local_cluster_mtv_provider_for_remote_cluster + admin_client, + local_cluster_mtv_provider_for_local_cluster, + local_cluster_mtv_provider_for_remote_cluster, + unique_suffix, + remote_cluster_source_storage_class, + local_cluster_target_storage_class, ): """ Create a StorageMap resource for MTV migration. @@ -353,13 +382,13 @@ def local_cluster_mtv_storage_map( """ mapping = [ { - "source": {"name": py_config["default_storage_class"]}, - "destination": {"storageClass": py_config["default_storage_class"]}, + "source": {"name": remote_cluster_source_storage_class}, + "destination": {"storageClass": local_cluster_target_storage_class}, } ] with StorageMap( client=admin_client, - name="storage-map", + name=f"storage-map-{unique_suffix}", namespace=local_cluster_mtv_provider_for_local_cluster.namespace, source_provider_name=local_cluster_mtv_provider_for_remote_cluster.name, source_provider_namespace=local_cluster_mtv_provider_for_remote_cluster.namespace, @@ -428,7 +457,10 @@ def remote_cluster_rhel10_data_source(remote_admin_client, remote_cluster_golden @pytest.fixture(scope="class") def vm_for_cclm_from_template_with_data_source( - remote_admin_client, remote_cluster_source_test_namespace, remote_cluster_rhel10_data_source + remote_admin_client, + remote_cluster_source_test_namespace, + remote_cluster_rhel10_data_source, + remote_cluster_source_storage_class, ): with VirtualMachineForTests( name="vm-from-template-and-data-source", @@ -437,7 +469,7 @@ def vm_for_cclm_from_template_with_data_source( os_flavor=OS_FLAVOR_RHEL, data_volume_template=data_volume_template_with_source_ref_dict( data_source=remote_cluster_rhel10_data_source, - storage_class=py_config["default_storage_class"], + storage_class=remote_cluster_source_storage_class, ), memory_guest=Images.Rhel.DEFAULT_MEMORY_SIZE, ) as vm: @@ -447,7 +479,10 @@ def vm_for_cclm_from_template_with_data_source( @pytest.fixture(scope="class") def vm_for_cclm_with_instance_type( - remote_admin_client, remote_cluster_source_test_namespace, remote_cluster_rhel10_data_source + remote_admin_client, + remote_cluster_source_test_namespace, + remote_cluster_rhel10_data_source, + remote_cluster_source_storage_class, ): with VirtualMachineForTests( name="vm-with-instance-type", @@ -458,7 +493,7 @@ def vm_for_cclm_with_instance_type( vm_preference=VirtualMachineClusterPreference(name=RHEL10_PREFERENCE, client=remote_admin_client), data_volume_template=data_volume_template_with_source_ref_dict( data_source=remote_cluster_rhel10_data_source, - storage_class=py_config["default_storage_class"], + storage_class=remote_cluster_source_storage_class, ), ) as vm: vm.start() @@ -489,6 +524,7 @@ def remote_cluster_artifactory_config_map_scope_class(remote_admin_client, remot def vm_for_cclm_windows_with_instance_type( remote_admin_client, remote_cluster_source_test_namespace, + remote_cluster_source_storage_class, remote_cluster_artifactory_secret_scope_class, remote_cluster_artifactory_config_map_scope_class, ): @@ -499,7 +535,7 @@ def vm_for_cclm_windows_with_instance_type( api_name="storage", source="registry", size=Images.Windows.CONTAINER_DISK_DV_SIZE, - storage_class=py_config["default_storage_class"], + storage_class=remote_cluster_source_storage_class, url=f"{get_test_artifact_server_url(schema='registry')}/{WINDOWS_2022[CONTAINER_DISK_IMAGE_PATH_STR]}", secret=remote_cluster_artifactory_secret_scope_class, cert_configmap=remote_cluster_artifactory_config_map_scope_class.name, diff --git a/tests/storage/cross_cluster_live_migration/test_cclm.py b/tests/storage/cross_cluster_live_migration/test_cclm.py index ab0442b2ce..3146c4d76f 100644 --- a/tests/storage/cross_cluster_live_migration/test_cclm.py +++ b/tests/storage/cross_cluster_live_migration/test_cclm.py @@ -1,6 +1,7 @@ import pytest +from pytest_testconfig import config as py_config -from tests.storage.constants import TEST_FILE_CONTENT, TEST_FILE_NAME +from tests.storage.constants import STORAGE_CLASS_A, STORAGE_CLASS_B, TEST_FILE_CONTENT, TEST_FILE_NAME from tests.storage.cross_cluster_live_migration.utils import ( assert_vms_are_stopped, assert_vms_can_be_deleted, @@ -13,6 +14,8 @@ TESTS_CLASS_NAME_SEVERAL_VMS = "TestCCLMSeveralVMs" TESTS_CLASS_NAME_WINDOWS_VM = "TestCCLMWindowsWithVTPM" +TESTS_CLASS_NAME_STORAGE_A_TO_B = "TestCCLMFromStorageAtoB" +TESTS_CLASS_NAME_STORAGE_B_TO_A = "TestCCLMFromStorageBtoA" pytestmark = [ pytest.mark.cclm, @@ -25,9 +28,11 @@ @pytest.mark.parametrize( - "vms_for_cclm", + "remote_cluster_source_storage_class, local_cluster_target_storage_class, vms_for_cclm", [ pytest.param( + {"source_storage_class": py_config[STORAGE_CLASS_B]}, + {"target_storage_class": py_config[STORAGE_CLASS_B]}, { "vms_fixtures": [ "vm_for_cclm_from_template_with_data_source", @@ -38,6 +43,7 @@ ], indirect=True, ) +@pytest.mark.usefixtures("remote_cluster_source_storage_class", "local_cluster_target_storage_class") class TestCCLMSeveralVMs: @pytest.mark.polarion("CNV-11995") @pytest.mark.dependency(name=f"{TESTS_CLASS_NAME_SEVERAL_VMS}::test_migrate_vm_from_remote_to_local_cluster") @@ -93,16 +99,18 @@ def test_target_vms_can_be_deleted(self, local_vms_after_cclm_migration): @pytest.mark.parametrize( - "dv_wait_timeout, vms_for_cclm", + "remote_cluster_source_storage_class, local_cluster_target_storage_class, dv_wait_timeout, vms_for_cclm", [ pytest.param( + {"source_storage_class": py_config[STORAGE_CLASS_B]}, + {"target_storage_class": py_config[STORAGE_CLASS_B]}, {"dv_wait_timeout": TIMEOUT_50MIN}, {"vms_fixtures": ["vm_for_cclm_windows_with_instance_type"]}, ) ], indirect=True, ) -@pytest.mark.usefixtures("dv_wait_timeout") +@pytest.mark.usefixtures("remote_cluster_source_storage_class", "local_cluster_target_storage_class", "dv_wait_timeout") class TestCCLMWindowsWithVTPM: @pytest.mark.dependency(name=f"{TESTS_CLASS_NAME_WINDOWS_VM}::test_migrate_windows_vm_from_remote_to_local_cluster") @pytest.mark.polarion("CNV-11999") @@ -139,3 +147,81 @@ def test_source_vms_can_be_deleted(self, vms_for_cclm): @pytest.mark.polarion("CNV-15236") def test_target_vms_can_be_deleted(self, local_vms_after_cclm_migration): assert_vms_can_be_deleted(vms=local_vms_after_cclm_migration) + + +@pytest.mark.parametrize( + "remote_cluster_source_storage_class, local_cluster_target_storage_class, vms_for_cclm", + [ + pytest.param( + {"source_storage_class": py_config[STORAGE_CLASS_A]}, + {"target_storage_class": py_config[STORAGE_CLASS_B]}, + { + "vms_fixtures": [ + "vm_for_cclm_with_instance_type", + ] + }, + ) + ], + indirect=True, +) +@pytest.mark.usefixtures("remote_cluster_source_storage_class", "local_cluster_target_storage_class") +class TestCCLMFromStorageAtoB: + @pytest.mark.polarion("CNV-15955") + @pytest.mark.dependency(name=f"{TESTS_CLASS_NAME_STORAGE_A_TO_B}::test_migrate_vm_from_remote_to_local_cluster") + def test_migrate_vm_from_remote_to_local_cluster( + self, + written_file_to_vms_before_cclm, + vms_boot_id_before_cclm, + mtv_migration, + ): + mtv_migration.wait_for_condition( + condition=mtv_migration.Condition.Type.SUCCEEDED, + status=mtv_migration.Condition.Status.TRUE, + timeout=TIMEOUT_10MIN, + stop_condition=mtv_migration.Status.FAILED, + ) + + @pytest.mark.dependency( + depends=[f"{TESTS_CLASS_NAME_STORAGE_A_TO_B}::test_migrate_vm_from_remote_to_local_cluster"] + ) + @pytest.mark.polarion("CNV-15956") + def test_verify_vms_not_rebooted_after_migration(self, local_vms_after_cclm_migration, vms_boot_id_before_cclm): + verify_vms_boot_id_after_cross_cluster_live_migration( + local_vms=local_vms_after_cclm_migration, initial_boot_id=vms_boot_id_before_cclm + ) + + @pytest.mark.dependency( + depends=[f"{TESTS_CLASS_NAME_STORAGE_A_TO_B}::test_migrate_vm_from_remote_to_local_cluster"] + ) + @pytest.mark.polarion("CNV-15957") + def test_verify_file_persisted_after_migration(self, local_vms_after_cclm_migration): + for vm in local_vms_after_cclm_migration: + check_file_in_vm( + vm=vm, + file_name=TEST_FILE_NAME, + file_content=TEST_FILE_CONTENT, + username=vm.username, + password=vm.password, + ) + + @pytest.mark.dependency( + depends=[f"{TESTS_CLASS_NAME_STORAGE_A_TO_B}::test_migrate_vm_from_remote_to_local_cluster"] + ) + @pytest.mark.polarion("CNV-15958") + def test_source_vms_are_stopped_after_cclm(self, vms_for_cclm): + assert_vms_are_stopped(vms=vms_for_cclm) + + @pytest.mark.dependency( + depends=[f"{TESTS_CLASS_NAME_STORAGE_A_TO_B}::test_migrate_vm_from_remote_to_local_cluster"] + ) + @pytest.mark.polarion("CNV-15954") + def test_compute_live_migrate_vms_after_cclm(self, local_vms_after_cclm_migration): + verify_compute_live_migration_after_cclm(local_vms=local_vms_after_cclm_migration) + + @pytest.mark.polarion("CNV-15959") + def test_source_vms_can_be_deleted(self, vms_for_cclm): + assert_vms_can_be_deleted(vms=vms_for_cclm) + + @pytest.mark.polarion("CNV-15960") + def test_target_vms_can_be_deleted(self, local_vms_after_cclm_migration): + assert_vms_can_be_deleted(vms=local_vms_after_cclm_migration) diff --git a/tests/storage/storage_migration/conftest.py b/tests/storage/storage_migration/conftest.py index ae877c0d4b..3e78012b03 100644 --- a/tests/storage/storage_migration/conftest.py +++ b/tests/storage/storage_migration/conftest.py @@ -21,10 +21,9 @@ ) from tests.storage.storage_migration.utils import ( build_namespaces_spec_for_storage_migration, - get_storage_class_for_storage_migration, wait_for_storage_migration_completed, ) -from tests.storage.utils import create_windows_directory +from tests.storage.utils import create_windows_directory, get_storage_class_for_storage_migration from utilities.artifactory import get_http_image_url from utilities.constants import ( OS_FLAVOR_FEDORA, diff --git a/tests/storage/storage_migration/constants.py b/tests/storage/storage_migration/constants.py index 976e991f5f..965639523a 100644 --- a/tests/storage/storage_migration/constants.py +++ b/tests/storage/storage_migration/constants.py @@ -4,17 +4,5 @@ WINDOWS_FILE_BEFORE_STORAGE_MIGRATION = f"{FILE_BEFORE_STORAGE_MIGRATION}.txt" WINDOWS_FILE_WITH_PATH = f"{WINDOWS_TEST_DIRECTORY_PATH}\\{WINDOWS_FILE_BEFORE_STORAGE_MIGRATION}" -STORAGE_CLASS_A = "storage_class_a" -STORAGE_CLASS_B = "storage_class_b" - -NO_STORAGE_CLASS_FAILURE_MESSAGE = ( - f"Test failed: {'{storage_class}'} storage class is not deployed. " - f"Available storage classes: {'{cluster_storage_classes_names}'}. " - "Ensure the correct storage_class is set in the global_config, " - "or override it with the pytest params: " - f"--tc={STORAGE_CLASS_A}: " - f"--tc={STORAGE_CLASS_B}:" -) - HOTPLUGGED_DEVICE = "/dev/sda" MOUNT_HOTPLUGGED_DEVICE_PATH = "/mnt/hotplug" diff --git a/tests/storage/storage_migration/test_storage_class_migration.py b/tests/storage/storage_migration/test_storage_class_migration.py index 874166b98a..e19e8b252b 100644 --- a/tests/storage/storage_migration/test_storage_class_migration.py +++ b/tests/storage/storage_migration/test_storage_class_migration.py @@ -2,11 +2,10 @@ from pytest_testconfig import config as py_config from tests.os_params import FEDORA_LATEST, FEDORA_LATEST_LABELS +from tests.storage.constants import STORAGE_CLASS_A, STORAGE_CLASS_B from tests.storage.storage_migration.constants import ( CONTENT, FILE_BEFORE_STORAGE_MIGRATION, - STORAGE_CLASS_A, - STORAGE_CLASS_B, WINDOWS_FILE_WITH_PATH, ) from tests.storage.storage_migration.utils import ( diff --git a/tests/storage/storage_migration/utils.py b/tests/storage/storage_migration/utils.py index 7ae133d447..414ad9b73d 100644 --- a/tests/storage/storage_migration/utils.py +++ b/tests/storage/storage_migration/utils.py @@ -1,6 +1,5 @@ import shlex -import pytest from ocp_resources.multi_namespace_virtual_machine_storage_migration import MultiNamespaceVirtualMachineStorageMigration from ocp_resources.persistent_volume_claim import PersistentVolumeClaim from pyhelper_utils.shell import run_ssh_commands @@ -10,7 +9,6 @@ CONTENT, FILE_BEFORE_STORAGE_MIGRATION, MOUNT_HOTPLUGGED_DEVICE_PATH, - NO_STORAGE_CLASS_FAILURE_MESSAGE, ) from tests.storage.utils import check_file_in_vm from utilities.constants import TIMEOUT_2MIN, TIMEOUT_5SEC, TIMEOUT_10MIN, TIMEOUT_10SEC @@ -76,17 +74,6 @@ def verify_storage_migration_succeeded( verify_vm_storage_class_updated(vm=vm, target_storage_class=target_storage_class) -def get_storage_class_for_storage_migration(storage_class: str, cluster_storage_classes_names: list[str]) -> str: - if storage_class in cluster_storage_classes_names: - return storage_class - else: - pytest.fail( - NO_STORAGE_CLASS_FAILURE_MESSAGE.format( - storage_class=storage_class, cluster_storage_classes_names=cluster_storage_classes_names - ) - ) - - def verify_file_in_hotplugged_disk(vm: VirtualMachineForTests, file_name: str, file_content: str) -> None: output = run_ssh_commands( host=vm.ssh_exec, diff --git a/tests/storage/utils.py b/tests/storage/utils.py index 79f7789c35..c356eccc4a 100644 --- a/tests/storage/utils.py +++ b/tests/storage/utils.py @@ -4,6 +4,7 @@ from collections.abc import Generator from contextlib import contextmanager +import pytest import requests from kubernetes.dynamic import DynamicClient from ocp_resources.cluster_role import ClusterRole @@ -23,6 +24,7 @@ from pytest_testconfig import config as py_config from timeout_sampler import TimeoutExpiredError, TimeoutSampler +from tests.storage.constants import NO_STORAGE_CLASS_FAILURE_MESSAGE from utilities import console from utilities.artifactory import ( cleanup_artifactory_secret_and_config_map, @@ -524,3 +526,14 @@ def check_file_in_vm( vm_console.expect(pattern=file_name, timeout=TIMEOUT_20SEC) vm_console.sendline(f"cat {file_name}") vm_console.expect(pattern=file_content, timeout=TIMEOUT_20SEC) + + +def get_storage_class_for_storage_migration(storage_class: str, cluster_storage_classes_names: list[str]) -> str: + if storage_class in cluster_storage_classes_names: + return storage_class + + pytest.fail( + NO_STORAGE_CLASS_FAILURE_MESSAGE.format( + storage_class=storage_class, cluster_storage_classes_names=cluster_storage_classes_names + ) + ) From 4165c05148d590bc4ee6057d70400d4ec2a5e141 Mon Sep 17 00:00:00 2001 From: Jenia Peimer Date: Wed, 29 Apr 2026 13:32:22 +0300 Subject: [PATCH 2/4] [CCLM] Add type hints and docstrings to cross-storage fixtures - Add type hints to remote_cluster_storage_classes_names fixture - Add type hints to remote_cluster_source_storage_class fixture - Add type hints to local_cluster_target_storage_class fixture - Add docstring to get_storage_class_for_storage_migration() - Add docstrings to all three new fixtures - Fix line length in local_cluster_target_storage_class - Remove unused constant TESTS_CLASS_NAME_STORAGE_B_TO_A Assisted-by: Claude Signed-off-by: Jenia Peimer --- .../cross_cluster_live_migration/conftest.py | 17 +++++++++++------ .../cross_cluster_live_migration/test_cclm.py | 1 - tests/storage/utils.py | 12 ++++++++++++ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/storage/cross_cluster_live_migration/conftest.py b/tests/storage/cross_cluster_live_migration/conftest.py index 2b7b75ac41..613fb58352 100644 --- a/tests/storage/cross_cluster_live_migration/conftest.py +++ b/tests/storage/cross_cluster_live_migration/conftest.py @@ -6,6 +6,7 @@ import pytest import requests import yaml +from kubernetes.dynamic import DynamicClient from kubernetes.dynamic.exceptions import NotFoundError from ocp_resources.data_source import DataSource from ocp_resources.datavolume import DataVolume @@ -346,13 +347,16 @@ def local_cluster_mtv_provider_for_local_cluster(admin_client, mtv_namespace): @pytest.fixture(scope="module") -def remote_cluster_storage_classes_names(remote_admin_client): +def remote_cluster_storage_classes_names(remote_admin_client: DynamicClient) -> list[str]: + """Get list of all storage class names available in the remote cluster.""" return [sc.name for sc in list(StorageClass.get(client=remote_admin_client))] @pytest.fixture(scope="class") -def remote_cluster_source_storage_class(request, remote_cluster_storage_classes_names): - # Storage class for the original VMs creation in the remote cluster +def remote_cluster_source_storage_class( + request: pytest.FixtureRequest, remote_cluster_storage_classes_names: list[str] +) -> str: + """Storage class for creating VMs in the remote cluster before migration.""" return get_storage_class_for_storage_migration( storage_class=request.param["source_storage_class"], cluster_storage_classes_names=remote_cluster_storage_classes_names, @@ -360,10 +364,11 @@ def remote_cluster_source_storage_class(request, remote_cluster_storage_classes_ @pytest.fixture(scope="class") -def local_cluster_target_storage_class(request, cluster_storage_classes_names): - # Storage class for the target VMs in the local cluster +def local_cluster_target_storage_class(request: pytest.FixtureRequest, cluster_storage_classes_names: list[str]) -> str: + """Storage class for migrated VMs in the local cluster.""" return get_storage_class_for_storage_migration( - storage_class=request.param["target_storage_class"], cluster_storage_classes_names=cluster_storage_classes_names + storage_class=request.param["target_storage_class"], + cluster_storage_classes_names=cluster_storage_classes_names, ) diff --git a/tests/storage/cross_cluster_live_migration/test_cclm.py b/tests/storage/cross_cluster_live_migration/test_cclm.py index 3146c4d76f..374a4d6164 100644 --- a/tests/storage/cross_cluster_live_migration/test_cclm.py +++ b/tests/storage/cross_cluster_live_migration/test_cclm.py @@ -15,7 +15,6 @@ TESTS_CLASS_NAME_SEVERAL_VMS = "TestCCLMSeveralVMs" TESTS_CLASS_NAME_WINDOWS_VM = "TestCCLMWindowsWithVTPM" TESTS_CLASS_NAME_STORAGE_A_TO_B = "TestCCLMFromStorageAtoB" -TESTS_CLASS_NAME_STORAGE_B_TO_A = "TestCCLMFromStorageBtoA" pytestmark = [ pytest.mark.cclm, diff --git a/tests/storage/utils.py b/tests/storage/utils.py index c356eccc4a..0f728498a0 100644 --- a/tests/storage/utils.py +++ b/tests/storage/utils.py @@ -529,6 +529,18 @@ def check_file_in_vm( def get_storage_class_for_storage_migration(storage_class: str, cluster_storage_classes_names: list[str]) -> str: + """Validate that the requested storage class exists in the cluster. + + Args: + storage_class: Name of the storage class to validate. + cluster_storage_classes_names: List of available storage class names in the cluster. + + Returns: + The validated storage class name if it exists. + + Raises: + pytest.Failed: If the storage class is not found in the cluster. + """ if storage_class in cluster_storage_classes_names: return storage_class From d3868aaa0d956406ca3e73339d756b1ff77aa1aa Mon Sep 17 00:00:00 2001 From: Jenia Peimer Date: Sun, 14 Jun 2026 11:38:35 +0300 Subject: [PATCH 3/4] Add Jira epic link docstring to test_cclm.py Assisted-by: Claude Signed-off-by: Jenia Peimer --- tests/storage/cross_cluster_live_migration/test_cclm.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/storage/cross_cluster_live_migration/test_cclm.py b/tests/storage/cross_cluster_live_migration/test_cclm.py index 374a4d6164..91e5531cd4 100644 --- a/tests/storage/cross_cluster_live_migration/test_cclm.py +++ b/tests/storage/cross_cluster_live_migration/test_cclm.py @@ -1,3 +1,9 @@ +""" +Cross-cluster live migration tests. + +Jira epic: https://redhat.atlassian.net/browse/CNV-50823 +""" + import pytest from pytest_testconfig import config as py_config From c8d00583cbf6b3a09a725b66fb118f951e1d0e8c Mon Sep 17 00:00:00 2001 From: Jenia Peimer Date: Sun, 14 Jun 2026 11:56:04 +0300 Subject: [PATCH 4/4] Add skip-jira-utils-check for CNV-50823 epic link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Jira link is an epic tracker, not a bug — skip the verify-bugs-are-open check so it is not flagged as unresolved. Assisted-by: Claude Signed-off-by: Jenia Peimer --- tests/storage/cross_cluster_live_migration/test_cclm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/storage/cross_cluster_live_migration/test_cclm.py b/tests/storage/cross_cluster_live_migration/test_cclm.py index 91e5531cd4..ae988b91a5 100644 --- a/tests/storage/cross_cluster_live_migration/test_cclm.py +++ b/tests/storage/cross_cluster_live_migration/test_cclm.py @@ -1,7 +1,7 @@ """ Cross-cluster live migration tests. -Jira epic: https://redhat.atlassian.net/browse/CNV-50823 +Jira epic: https://redhat.atlassian.net/browse/CNV-50823 # """ import pytest