diff --git a/tests/storage/cdi_clone/conftest.py b/tests/storage/cdi_clone/conftest.py index 7647297a4d..972040eef2 100644 --- a/tests/storage/cdi_clone/conftest.py +++ b/tests/storage/cdi_clone/conftest.py @@ -1,9 +1,11 @@ import pytest from ocp_resources.datavolume import DataVolume +from tests.storage.cdi_clone.constants import WINDOWS_CLONE_TIMEOUT from tests.storage.constants import QUAY_FEDORA_CONTAINER_IMAGE -from utilities.constants import REGISTRY_STR, Images -from utilities.storage import create_dv, data_volume +from tests.utils import create_windows2022_dv_from_registry +from utilities.constants import REGISTRY_STR, WIN_2K22, Images +from utilities.storage import create_dummy_first_consumer_pod, create_dv, data_volume, sc_volume_binding_mode_is_wffc @pytest.fixture() @@ -59,3 +61,42 @@ def fedora_dv_with_block_volume_mode( ) as dv: dv.wait_for_dv_success() yield dv + + +@pytest.fixture(scope="class") +def source_dv_windows_registry_scope_class( + unprivileged_client, + namespace, + storage_class_name_scope_class, +): + """Fixture that creates a Windows 2022 DataVolume from registry.""" + with create_windows2022_dv_from_registry( + dv_name=f"dv-source-{WIN_2K22}-registry", + namespace=namespace.name, + client=unprivileged_client, + storage_class=storage_class_name_scope_class, + ) as dv: + if sc_volume_binding_mode_is_wffc(sc=storage_class_name_scope_class, client=unprivileged_client): + create_dummy_first_consumer_pod(dv=dv) + dv.wait_for_dv_success(timeout=WINDOWS_CLONE_TIMEOUT) + yield dv + + +@pytest.fixture(scope="class") +def cloned_windows_dv_scope_class( + unprivileged_client, + source_dv_windows_registry_scope_class, +): + """Fixture that creates a cloned DataVolume from registry source.""" + source_dv_spec = source_dv_windows_registry_scope_class.instance.spec + with create_dv( + client=unprivileged_client, + source="pvc", + dv_name=f"dv-target-{WIN_2K22}-clone", + namespace=source_dv_windows_registry_scope_class.namespace, + size=Images.Windows.CONTAINER_DISK_DV_SIZE, + source_pvc=source_dv_windows_registry_scope_class.name, + storage_class=source_dv_spec.storage.storageClassName, + ) as cdv: + cdv.wait_for_dv_success(timeout=WINDOWS_CLONE_TIMEOUT) + yield cdv diff --git a/tests/storage/cdi_clone/constants.py b/tests/storage/cdi_clone/constants.py new file mode 100644 index 0000000000..d58196af1e --- /dev/null +++ b/tests/storage/cdi_clone/constants.py @@ -0,0 +1,7 @@ +""" +Constants for CDI clone tests. +""" + +from utilities.constants import TIMEOUT_40MIN + +WINDOWS_CLONE_TIMEOUT = TIMEOUT_40MIN diff --git a/tests/storage/cdi_clone/test_clone.py b/tests/storage/cdi_clone/test_clone.py index a6667224e9..55b2e84a0c 100644 --- a/tests/storage/cdi_clone/test_clone.py +++ b/tests/storage/cdi_clone/test_clone.py @@ -5,19 +5,20 @@ import pytest from ocp_resources.datavolume import DataVolume -from tests.os_params import FEDORA_LATEST, WINDOWS_11, WINDOWS_11_TEMPLATE_LABELS +from tests.os_params import FEDORA_LATEST from tests.storage.utils import ( assert_pvc_snapshot_clone_annotation, assert_use_populator, - create_windows_vm_validate_guest_agent_info, ) +from tests.utils import create_windows2022_vm_from_dv_with_vtpm from utilities.constants import ( OS_FLAVOR_FEDORA, OS_FLAVOR_WINDOWS, TIMEOUT_1MIN, - TIMEOUT_40MIN, + WIN_2K22, Images, ) +from utilities.ssp import validate_os_info_vmi_vs_windows_os from utilities.storage import ( check_disk_count_in_vm, create_dv, @@ -33,8 +34,6 @@ running_vm, ) -WINDOWS_CLONE_TIMEOUT = TIMEOUT_40MIN - def create_vm_from_clone_dv_template( vm_name, @@ -64,38 +63,6 @@ def create_vm_from_clone_dv_template( running_vm(vm=vm) -@pytest.mark.tier3 -@pytest.mark.parametrize( - "data_volume_multi_storage_scope_function", - [ - pytest.param( - { - "dv_name": "dv-source", - "image": f"{Images.Windows.DIR}/{Images.Windows.WIN11_IMG}", - "dv_size": Images.Windows.DEFAULT_DV_SIZE, - }, - marks=(pytest.mark.polarion("CNV-1892")), - ), - ], - indirect=True, -) -@pytest.mark.s390x -def test_successful_clone_of_large_image( - namespace, - data_volume_multi_storage_scope_function, -): - with create_dv( - source="pvc", - dv_name="dv-target", - namespace=namespace.name, - size=data_volume_multi_storage_scope_function.size, - source_pvc=data_volume_multi_storage_scope_function.name, - storage_class=data_volume_multi_storage_scope_function.storage_class, - client=namespace.client, - ) as cdv: - cdv.wait_for_dv_success(timeout=WINDOWS_CLONE_TIMEOUT) - - @pytest.mark.sno @pytest.mark.polarion("CNV-2148") @pytest.mark.gating() @@ -144,50 +111,65 @@ def test_successful_vm_restart_with_cloned_dv( @pytest.mark.tier3 -@pytest.mark.parametrize( - ("data_volume_multi_storage_scope_function", "vm_params"), - [ - pytest.param( - { - "dv_name": "dv-source", - "source": "http", - "image": f"{Images.Windows.DIR}/{Images.Windows.WIN11_IMG}", - "dv_size": Images.Windows.DEFAULT_DV_SIZE, - }, - { - "vm_name": f"vm-win-{WINDOWS_11.get('os_version')}", - "template_labels": WINDOWS_11_TEMPLATE_LABELS, - "os_version": WINDOWS_11.get("os_version"), - "ssh": True, - }, - marks=pytest.mark.polarion("CNV-3638"), - ), - ], - indirect=["data_volume_multi_storage_scope_function"], -) -def test_successful_vm_from_cloned_dv_windows( - unprivileged_client, - data_volume_multi_storage_scope_function, - vm_params, - namespace, -): - with create_dv( - client=unprivileged_client, - source="pvc", - dv_name="dv-target", - namespace=data_volume_multi_storage_scope_function.namespace, - size=data_volume_multi_storage_scope_function.size, - source_pvc=data_volume_multi_storage_scope_function.name, - storage_class=data_volume_multi_storage_scope_function.storage_class, - ) as cdv: - cdv.wait_for_dv_success(timeout=WINDOWS_CLONE_TIMEOUT) - create_windows_vm_validate_guest_agent_info( - dv=cdv, - namespace=namespace, - unprivileged_client=unprivileged_client, - vm_params=vm_params, +@pytest.mark.incremental +class TestWindowsClonedDv: + """ + Tests for Windows 2022 DV cloning from registry and VM creation with vTPM. + + Preconditions: + - Windows Server 2022 DataVolume imported from registry + - Cloned DataVolume created from the source DataVolume (PVC clone) + """ + + @pytest.mark.polarion("CNV-1892") + def test_clone_dv_windows(self, cloned_windows_dv_scope_class): + """ + Test that a Windows 2022 DataVolume can be cloned from a registry source. + + Preconditions: + - Cloned DataVolume created from the source DataVolume (PVC clone) + + Steps: + 1. Verify the cloned DataVolume status + + Expected: + - Cloned DataVolume status is "Succeeded" + """ + assert cloned_windows_dv_scope_class.status == DataVolume.Status.SUCCEEDED, ( + f"Cloned DV status is {cloned_windows_dv_scope_class.status}, expected {DataVolume.Status.SUCCEEDED}" ) + @pytest.mark.polarion("CNV-3638") + def test_vm_from_cloned_dv_windows( + self, + unprivileged_client, + namespace, + modern_cpu_for_migration, + cloned_windows_dv_scope_class, + ): + """ + Test that a Windows 2022 VM with vTPM boots from a cloned DataVolume. + + Preconditions: + - Cloned DataVolume created from the source DataVolume (PVC clone) + + Steps: + 1. Create a Windows 2022 VM with vTPM from the cloned DataVolume using instance type and preference + 2. Wait for the VM to reach Running state + 3. Wait for Windows OS to be ready inside the VM + + Expected: + - VM OS info reported by VMI matches the expected Windows OS parameters + """ + with create_windows2022_vm_from_dv_with_vtpm( + dv=cloned_windows_dv_scope_class, + namespace=namespace.name, + client=unprivileged_client, + vm_name=f"vm-{WIN_2K22}", + cpu_model=modern_cpu_for_migration, + ) as vm: + validate_os_info_vmi_vs_windows_os(vm=vm) + @pytest.mark.parametrize( "data_volume_snapshot_capable_storage_scope_function", diff --git a/tests/storage/conftest.py b/tests/storage/conftest.py index 80f0e5bcca..d8e4309460 100644 --- a/tests/storage/conftest.py +++ b/tests/storage/conftest.py @@ -43,7 +43,10 @@ is_hpp_cr_legacy, ) from tests.utils import create_cirros_vm -from utilities.artifactory import get_artifactory_config_map, get_artifactory_secret +from utilities.artifactory import ( + get_artifactory_config_map, + get_artifactory_secret, +) from utilities.constants import ( CDI_OPERATOR, CDI_UPLOADPROXY, @@ -66,7 +69,11 @@ INTERNAL_HTTP_SERVER_ADDRESS, ExecCommandOnPod, ) -from utilities.storage import data_volume_template_with_source_ref_dict, get_downloaded_artifact, write_file_via_ssh +from utilities.storage import ( + data_volume_template_with_source_ref_dict, + get_downloaded_artifact, + write_file_via_ssh, +) from utilities.virt import VirtualMachineForTests, running_vm LOGGER = logging.getLogger(__name__) diff --git a/tests/storage/test_hotplug.py b/tests/storage/test_hotplug.py index 9a85843336..a77f4ddf90 100644 --- a/tests/storage/test_hotplug.py +++ b/tests/storage/test_hotplug.py @@ -11,7 +11,7 @@ from ocp_resources.storage_profile import StorageProfile from tests.storage.utils import assert_disk_bus -from tests.utils import create_windows2022_dv_from_registry, create_windows2022_vm_with_vtpm_from_registry +from tests.utils import create_windows2022_dv_template_from_registry, create_windows2022_vm_from_template_with_vtpm from utilities.constants import HOTPLUG_DISK_SCSI_BUS, HOTPLUG_DISK_SERIAL, HOTPLUG_DISK_VIRTIO_BUS, Images from utilities.hco import ResourceEditorValidateHCOReconcile from utilities.jira import is_jira_open @@ -78,7 +78,7 @@ def windows_dv_from_registry_scope_class( storage_class_matrix__class__, ): """Creates a Windows 2022 DataVolume from registry container disk.""" - with create_windows2022_dv_from_registry( + with create_windows2022_dv_template_from_registry( dv_name="dv-windows-2022-hotplug", namespace=namespace.name, client=unprivileged_client, @@ -95,8 +95,8 @@ def vm_instance_from_template_multi_storage_scope_class( windows_dv_from_registry_scope_class, ): """Creates a Windows 2022 VM with vTPM from registry container disk.""" - with create_windows2022_vm_with_vtpm_from_registry( - dv_dict=windows_dv_from_registry_scope_class, + with create_windows2022_vm_from_template_with_vtpm( + dv_template=windows_dv_from_registry_scope_class, namespace=namespace.name, client=unprivileged_client, vm_name="vm-win-2022-hotplug", diff --git a/tests/utils.py b/tests/utils.py index 874dcc7633..38492ba5ba 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -710,6 +710,48 @@ def create_windows2022_dv_from_registry( namespace: str, client: DynamicClient, storage_class: str, +) -> Generator[DataVolume]: + """ + Creates a Windows Server 2022 DataVolume from registry container disk. + + Args: + dv_name: Name for the DataVolume + namespace: Kubernetes namespace + client: Kubernetes client + storage_class: Storage class name + + Yields: + dict: DataVolume template dictionary with metadata and spec + """ + artifactory_secret = get_artifactory_secret(namespace=namespace, client=client) + artifactory_config_map = get_artifactory_config_map(namespace=namespace, client=client) + + try: + with DataVolume( + name=dv_name, + namespace=namespace, + storage_class=storage_class, + source="registry", + url=f"{get_test_artifact_server_url(schema='registry')}/{get_windows_container_disk_path(os_value=WIN_2K22)}", + size=Images.Windows.CONTAINER_DISK_DV_SIZE, + client=client, + api_name="storage", + secret=artifactory_secret, + cert_configmap=artifactory_config_map.name, + ) as dv: + yield dv + finally: + cleanup_artifactory_secret_and_config_map( + artifactory_secret=artifactory_secret, artifactory_config_map=artifactory_config_map + ) + + +@contextmanager +def create_windows2022_dv_template_from_registry( + dv_name: str, + namespace: str, + client: DynamicClient, + storage_class: str, ) -> Generator[dict]: """ Creates a Windows Server 2022 DataVolume from registry container disk. @@ -723,8 +765,8 @@ def create_windows2022_dv_from_registry( Yields: dict: DataVolume template dictionary with metadata and spec """ - artifactory_secret = get_artifactory_secret(namespace=namespace) - artifactory_config_map = get_artifactory_config_map(namespace=namespace) + artifactory_secret = get_artifactory_secret(namespace=namespace, client=client) + artifactory_config_map = get_artifactory_config_map(namespace=namespace, client=client) dv = DataVolume( name=dv_name, @@ -749,18 +791,18 @@ def create_windows2022_dv_from_registry( @contextmanager -def create_windows2022_vm_with_vtpm_from_registry( - dv_dict: dict, +def create_windows2022_vm_from_dv_with_vtpm( namespace: str, client: DynamicClient, vm_name: str, cpu_model: str | None, + dv: DataVolume | None = None, ) -> Generator[VirtualMachineForTests]: """ - Creates a Windows Server 2022 VM with vTPM from registry container disk. + Creates a Windows Server 2022 VM with vTPM. Args: - dv_dict: DataVolume template dictionary with metadata and spec + dv_template: DataVolume template dictionary with metadata and spec namespace: Kubernetes namespace client: Kubernetes client vm_name: Name for the VirtualMachine @@ -769,6 +811,44 @@ def create_windows2022_vm_with_vtpm_from_registry( Yields: VirtualMachineForTests: Running Windows 2022 VM with vTPM """ + + with VirtualMachineForTests( + name=vm_name, + namespace=namespace, + client=client, + os_flavor=OS_FLAVOR_WIN_CONTAINER_DISK, + vm_instance_type=VirtualMachineClusterInstancetype(name=U1_LARGE, client=client), + vm_preference=VirtualMachineClusterPreference(name=WINDOWS_2K22_PREFERENCE, client=client), + data_volume=dv, + cpu_model=cpu_model, + ) as vm: + running_vm(vm=vm) + wait_for_windows_vm(vm=vm, version="2022") + yield vm + + +@contextmanager +def create_windows2022_vm_from_template_with_vtpm( + namespace: str, + client: DynamicClient, + vm_name: str, + cpu_model: str | None, + dv_template: dict | None = None, +) -> Generator[VirtualMachineForTests]: + """ + Creates a Windows Server 2022 VM with vTPM from dv template. + + Args: + dv_template: DataVolume template dictionary with metadata and spec + namespace: Kubernetes namespace + client: Kubernetes client + vm_name: Name for the VirtualMachine + cpu_model: CPU model specification (can be None) + + Yields: + VirtualMachineForTests: Running Windows 2022 VM with vTPM + """ + with VirtualMachineForTests( name=vm_name, namespace=namespace, @@ -776,7 +856,7 @@ def create_windows2022_vm_with_vtpm_from_registry( os_flavor=OS_FLAVOR_WIN_CONTAINER_DISK, vm_instance_type=VirtualMachineClusterInstancetype(name=U1_LARGE, client=client), vm_preference=VirtualMachineClusterPreference(name=WINDOWS_2K22_PREFERENCE, client=client), - data_volume_template=dv_dict, + data_volume_template=dv_template, cpu_model=cpu_model, ) as vm: running_vm(vm=vm)