Skip to content
Open
48 changes: 30 additions & 18 deletions tests/storage/snapshots/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@
from tests.storage.snapshots.constants import WINDOWS_DIRECTORY_PATH
from tests.storage.utils import (
assert_windows_directory_existence,
create_windows19_vm,
create_windows_directory,
set_permissions,
)
from tests.utils import create_windows2022_vm_with_data_volume_template

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Execution Plan

  • Run smoke tests: False — verified smoke-marked files do not use the changed Windows snapshot fixtures or removed create_windows19_vm helper; no parent conftest.py introduces this dependency.
  • Run gating tests: False — verified gating-marked files do not use the changed fixture graph.

Affected tests to run

  • tests/storage/snapshots/test_snapshots.py::test_online_windows_vm_successful_restore (tier3) — exercises windows_vm_with_vtpm_for_snapshot → Windows 2022 DataSource/DV template → directory creation → online snapshot → directory deletion → VM restore.
  • tests/storage/snapshots/test_snapshots.py::test_write_to_file_while_snapshot (tier3) — exercises the same vTPM Windows 2022 fixture path while writing during snapshot completion and restoring the VM.

Real tests (cluster required)

Error/fix path (snapshot preserves the directory removed after the snapshot):
pytest -s -o log_cli=true --jira tests/storage/snapshots/test_snapshots.py::test_online_windows_vm_successful_restore -m tier3

Happy path (write during snapshot remains restorable):
pytest -s -o log_cli=true --jira tests/storage/snapshots/test_snapshots.py::test_write_to_file_while_snapshot -m tier3

These require a real cluster because the changed fixtures provision the Windows VM and DataVolume, use SSH, and create/restore VirtualMachineSnapshot resources.

from utilities.constants.pytest import UNPRIVILEGED_USER
from utilities.constants.timeouts import TIMEOUT_2MIN, TIMEOUT_5SEC, TIMEOUT_10MIN
from utilities.constants.timeouts import (
TIMEOUT_2MIN,
TIMEOUT_5SEC,
TIMEOUT_10MIN,
)
from utilities.storage import data_volume_template_with_source_ref_dict

LOGGER = logging.getLogger(__name__)

Expand All @@ -46,66 +51,73 @@ def permissions_for_dv(namespace, admin_client):


@pytest.fixture()
def windows_vm_for_snapshot(
def windows_vm_with_vtpm_for_snapshot(
request,
namespace,
unprivileged_client,
modern_cpu_for_migration,
windows_validation_os_images_data_source_scope_session,
storage_class_matrix_snapshot_matrix__module__,
):
with create_windows19_vm(
dv_name=request.param["dv_name"],
with create_windows2022_vm_with_data_volume_template(
dv_template=data_volume_template_with_source_ref_dict(
data_source=windows_validation_os_images_data_source_scope_session,
storage_class=next(iter(storage_class_matrix_snapshot_matrix__module__)),
),
namespace=namespace.name,
client=unprivileged_client,
vm_name=request.param["vm_name"],
cpu_model=modern_cpu_for_migration,
storage_class=[*storage_class_matrix_snapshot_matrix__module__][0],
) as vm:
yield vm


@pytest.fixture()
def snapshot_windows_directory(windows_vm_for_snapshot):
create_windows_directory(windows_vm=windows_vm_for_snapshot, directory_path=WINDOWS_DIRECTORY_PATH)
def snapshot_windows_directory(windows_vm_with_vtpm_for_snapshot):
create_windows_directory(windows_vm=windows_vm_with_vtpm_for_snapshot, directory_path=WINDOWS_DIRECTORY_PATH)


@pytest.fixture()
def windows_snapshot(
snapshot_windows_directory,
windows_vm_for_snapshot,
windows_vm_with_vtpm_for_snapshot,
):
with VirtualMachineSnapshot(
name="windows-snapshot",
namespace=windows_vm_for_snapshot.namespace,
vm_name=windows_vm_for_snapshot.name,
namespace=windows_vm_with_vtpm_for_snapshot.namespace,
vm_name=windows_vm_with_vtpm_for_snapshot.name,
) as snapshot:
yield snapshot


@pytest.fixture()
def snapshot_dirctory_removed(windows_vm_for_snapshot, windows_snapshot):
def snapshot_dirctory_removed(windows_vm_with_vtpm_for_snapshot, windows_snapshot):
windows_snapshot.wait_ready_to_use(timeout=TIMEOUT_10MIN)
cmd = shlex.split(
f'powershell -command "Remove-Item -Path {WINDOWS_DIRECTORY_PATH} -Recurse"',
)
run_ssh_commands(host=windows_vm_for_snapshot.ssh_exec, commands=cmd, wait_timeout=TIMEOUT_2MIN, sleep=TIMEOUT_5SEC)
run_ssh_commands(
host=windows_vm_with_vtpm_for_snapshot.ssh_exec, commands=cmd, wait_timeout=TIMEOUT_2MIN, sleep=TIMEOUT_5SEC
)
assert_windows_directory_existence(
expected_result=False,
windows_vm=windows_vm_for_snapshot,
windows_vm=windows_vm_with_vtpm_for_snapshot,
directory_path=WINDOWS_DIRECTORY_PATH,
)
windows_vm_for_snapshot.stop(wait=True)
windows_vm_with_vtpm_for_snapshot.stop(wait=True)


@pytest.fixture()
def file_created_during_snapshot(windows_vm_for_snapshot, windows_snapshot):
def file_created_during_snapshot(windows_vm_with_vtpm_for_snapshot, windows_snapshot):
file = f"{WINDOWS_DIRECTORY_PATH}\\file.txt"
cmd = shlex.split(
f'powershell -command "for($i=1; $i -le 100; $i++){{$i| Out-File -FilePath {file} -Append}}"',
)
run_ssh_commands(host=windows_vm_for_snapshot.ssh_exec, commands=cmd, wait_timeout=TIMEOUT_2MIN, sleep=TIMEOUT_5SEC)
run_ssh_commands(
host=windows_vm_with_vtpm_for_snapshot.ssh_exec, commands=cmd, wait_timeout=TIMEOUT_2MIN, sleep=TIMEOUT_5SEC
)
windows_snapshot.wait_snapshot_done(timeout=TIMEOUT_10MIN)
windows_vm_for_snapshot.stop(wait=True)
windows_vm_with_vtpm_for_snapshot.stop(wait=True)


@pytest.fixture()
Expand Down
28 changes: 15 additions & 13 deletions tests/storage/snapshots/test_snapshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,54 +441,56 @@ def test_fail_to_snapshot_with_unprivileged_client_dv_permissions(
)


@pytest.mark.tier3
@pytest.mark.parametrize(
"windows_vm_for_snapshot",
"windows_vm_with_vtpm_for_snapshot",
[
pytest.param(
{"dv_name": "dv-8307", "vm_name": "vm-8307"},
{"vm_name": "vm-8307"},
marks=pytest.mark.polarion("CNV-8307"),
),
],
indirect=True,
)
def test_online_windows_vm_successful_restore(
windows_vm_for_snapshot,
windows_vm_with_vtpm_for_snapshot,
windows_snapshot,
snapshot_dirctory_removed,
):
with VirtualMachineRestore(
name="restore-vm",
namespace=windows_vm_for_snapshot.namespace,
vm_name=windows_vm_for_snapshot.name,
namespace=windows_vm_with_vtpm_for_snapshot.namespace,
vm_name=windows_vm_with_vtpm_for_snapshot.name,
snapshot_name=windows_snapshot.name,
) as restore:
start_windows_vm_after_restore(vm_restore=restore, windows_vm=windows_vm_for_snapshot)
start_windows_vm_after_restore(vm_restore=restore, windows_vm=windows_vm_with_vtpm_for_snapshot)
assert_windows_directory_existence(
expected_result=True,
windows_vm=windows_vm_for_snapshot,
windows_vm=windows_vm_with_vtpm_for_snapshot,
directory_path=WINDOWS_DIRECTORY_PATH,
)


@pytest.mark.tier3
@pytest.mark.parametrize(
"windows_vm_for_snapshot",
"windows_vm_with_vtpm_for_snapshot",
[
pytest.param(
{"dv_name": "dv-8536", "vm_name": "vm-8536"},
{"vm_name": "vm-8536"},
marks=pytest.mark.polarion("CNV-8536"),
),
],
indirect=True,
)
def test_write_to_file_while_snapshot(
windows_vm_for_snapshot,
windows_vm_with_vtpm_for_snapshot,
windows_snapshot,
file_created_during_snapshot,
):
with VirtualMachineRestore(
name="restore-vm",
namespace=windows_vm_for_snapshot.namespace,
vm_name=windows_vm_for_snapshot.name,
namespace=windows_vm_with_vtpm_for_snapshot.namespace,
vm_name=windows_vm_with_vtpm_for_snapshot.name,
snapshot_name=windows_snapshot.name,
) as restore:
start_windows_vm_after_restore(vm_restore=restore, windows_vm=windows_vm_for_snapshot)
start_windows_vm_after_restore(vm_restore=restore, windows_vm=windows_vm_with_vtpm_for_snapshot)
44 changes: 0 additions & 44 deletions tests/storage/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,13 @@
from ocp_resources.service import Service
from ocp_resources.storage_class import StorageClass
from ocp_resources.storage_profile import StorageProfile
from ocp_resources.template import Template
from ocp_resources.upload_token_request import UploadTokenRequest
from pyhelper_utils.shell import run_ssh_commands
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,
get_artifactory_config_map,
get_artifactory_secret,
get_http_image_url,
)
from utilities.constants import Images
from utilities.constants.cluster import LS_COMMAND
from utilities.constants.components import CDI_UPLOADPROXY
Expand All @@ -43,14 +36,11 @@
from utilities.ssp import validate_os_info_vmi_vs_windows_os
from utilities.storage import (
PodWithPVC,
construct_datavolume_source_dict,
create_dv,
get_containers_for_pods_with_pvc,
)
from utilities.virt import (
VirtualMachineForTests,
VirtualMachineForTestsFromTemplate,
running_vm,
vm_instance_from_template,
wait_for_windows_vm,
)
Expand Down Expand Up @@ -353,40 +343,6 @@ def get_hpp_daemonset(hco_namespace, hpp_cr_suffix, admin_client):
return daemonset


@contextmanager
def create_windows19_vm(dv_name, namespace, client, vm_name, cpu_model, storage_class):
artifactory_secret = get_artifactory_secret(namespace=namespace)
artifactory_config_map = get_artifactory_config_map(namespace=namespace)
dv = DataVolume(
name=dv_name,
namespace=namespace,
storage_class=storage_class,
source_dict=construct_datavolume_source_dict(
source="http",
url=get_http_image_url(image_directory=Images.Windows.UEFI_WIN_DIR, image_name=Images.Windows.WIN2k19_IMG),
secret_name=artifactory_secret.name,
cert_configmap_name=artifactory_config_map.name,
),
size=Images.Windows.DEFAULT_DV_SIZE,
client=client,
api_name="storage",
)
dv.to_dict()
with VirtualMachineForTestsFromTemplate(
name=vm_name,
namespace=namespace,
client=client,
labels=Template.generate_template_labels(**py_config["latest_windows_os_dict"]["template_labels"]),
cpu_model=cpu_model,
data_volume_template={"metadata": dv.res["metadata"], "spec": dv.res["spec"]},
) as vm:
running_vm(vm=vm)
yield vm
cleanup_artifactory_secret_and_config_map(
artifactory_secret=artifactory_secret, artifactory_config_map=artifactory_config_map
)


def check_snapshot_indication(snapshot, is_online):
snapshot_indications = snapshot.instance.status.indications
online = "Online"
Expand Down