Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 75 additions & 60 deletions tests/storage/storage_migration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
Comment thread
Ahmad-Hafe marked this conversation as resolved.
import shlex

import pytest
Expand All @@ -14,8 +15,9 @@
from tests.storage.storage_migration.constants import (
CONTENT,
FILE_BEFORE_STORAGE_MIGRATION,
HOTPLUGGED_DEVICE,
MOUNT_HOTPLUGGED_DEVICE_PATH,
HOTPLUGGED_DEVICES,
MOUNT_HOTPLUGGED_DEVICE_PATHS,
NUM_HOTPLUG_DISKS,
WINDOWS_FILE_WITH_PATH,
WINDOWS_TEST_DIRECTORY_PATH,
)
Expand All @@ -41,7 +43,6 @@
)
from utilities.virt import (
VirtualMachineForTests,
fedora_vm_body,
get_vm_boot_time,
running_vm,
vm_instance_from_template,
Expand Down Expand Up @@ -276,83 +277,97 @@ def deleted_old_dvs_of_stopped_vms(unprivileged_client, namespace):


@pytest.fixture(scope="class")
def blank_disk_dv_for_storage_migration(unprivileged_client, namespace, source_storage_class):
with create_dv(
source="blank",
dv_name="blank-dv-for-hotplug",
client=unprivileged_client,
namespace=namespace.name,
size=DEFAULT_DV_SIZE,
storage_class=source_storage_class,
consume_wffc=False,
) as dv:
yield dv
def blank_disk_dvs_for_storage_migration(unprivileged_client, namespace, source_storage_class):
Comment thread
Ahmad-Hafe marked this conversation as resolved.
with contextlib.ExitStack() as stack:
dvs = []
for idx in range(NUM_HOTPLUG_DISKS):
dv = stack.enter_context(
cm=create_dv(
source="blank",
dv_name=f"blank-dv-for-hotplug-{idx}",
client=unprivileged_client,
namespace=namespace.name,
size=DEFAULT_DV_SIZE,
storage_class=source_storage_class,
consume_wffc=False,
)
)
dvs.append(dv)
yield dvs


@pytest.fixture(scope="class")
def fedora_vm_for_hotplug_and_storage_migration(unprivileged_client, namespace, cpu_for_migration):
name = "fedora-volume-hotplug-vm"
def fedora_vm_for_hotplug_and_storage_migration(
unprivileged_client, namespace, fedora_data_source_scope_module, source_storage_class, cpu_for_migration
):
with VirtualMachineForTests(
name=name,
name="fedora-volume-hotplug-vm",
namespace=namespace.name,
body=fedora_vm_body(name=name),
cpu_model=cpu_for_migration,
client=unprivileged_client,
vm_instance_type=VirtualMachineClusterInstancetype(name=U1_SMALL, client=unprivileged_client),
vm_preference=VirtualMachineClusterPreference(name=OS_FLAVOR_FEDORA, client=unprivileged_client),
data_volume_template=data_volume_template_with_source_ref_dict(
data_source=fedora_data_source_scope_module,
storage_class=source_storage_class,
),
cpu_model=cpu_for_migration,
) as vm:
running_vm(vm=vm)
yield vm


@pytest.fixture(scope="class")
def vm_for_storage_class_migration_with_hotplugged_volume(
namespace, blank_disk_dv_for_storage_migration, fedora_vm_for_hotplug_and_storage_migration
def vm_for_storage_class_migration_with_hotplugged_volumes(
namespace, blank_disk_dvs_for_storage_migration, fedora_vm_for_hotplug_and_storage_migration
):
with virtctl_volume(
action="add",
namespace=namespace.name,
vm_name=fedora_vm_for_hotplug_and_storage_migration.name,
volume_name=blank_disk_dv_for_storage_migration.name,
persist=True,
) as res:
status, out, err = res
assert status, f"Failed to add volume to VM, out: {out}, err: {err}."
wait_for_vm_volume_ready(
vm=fedora_vm_for_hotplug_and_storage_migration,
volume_name=blank_disk_dv_for_storage_migration.name,
)
with contextlib.ExitStack() as stack:
for dv in blank_disk_dvs_for_storage_migration:
status, out, err = stack.enter_context(
cm=virtctl_volume(
action="add",
namespace=namespace.name,
vm_name=fedora_vm_for_hotplug_and_storage_migration.name,
volume_name=dv.name,
persist=True,
)
)
assert status, f"Failed to add volume {dv.name} to VM, out: {out}, err: {err}."
wait_for_vm_volume_ready(
vm=fedora_vm_for_hotplug_and_storage_migration,
volume_name=dv.name,
)
yield fedora_vm_for_hotplug_and_storage_migration


@pytest.fixture(scope="class")
def vm_with_mounted_hotplugged_disk(vm_for_storage_class_migration_with_hotplugged_volume):
# Mount the disk to the VM
run_ssh_commands(
host=vm_for_storage_class_migration_with_hotplugged_volume.ssh_exec,
commands=[
shlex.split(cmd)
for cmd in [
f"sudo mkfs.ext4 {HOTPLUGGED_DEVICE}",
f"sudo mkdir {MOUNT_HOTPLUGGED_DEVICE_PATH}",
f"sudo mount {HOTPLUGGED_DEVICE} {MOUNT_HOTPLUGGED_DEVICE_PATH}",
]
],
wait_timeout=TIMEOUT_2MIN,
sleep=TIMEOUT_5SEC,
)
yield vm_for_storage_class_migration_with_hotplugged_volume
def vm_with_mounted_hotplugged_disks(vm_for_storage_class_migration_with_hotplugged_volumes):
for device, mount_path in zip(HOTPLUGGED_DEVICES, MOUNT_HOTPLUGGED_DEVICE_PATHS, strict=True):
run_ssh_commands(
host=vm_for_storage_class_migration_with_hotplugged_volumes.ssh_exec,
commands=[
shlex.split(cmd)
for cmd in [
f"sudo mkfs.ext4 {device}",
f"sudo mkdir -p {mount_path}",
f"sudo mount {device} {mount_path}",
]
],
wait_timeout=TIMEOUT_2MIN,
sleep=TIMEOUT_5SEC,
)
yield vm_for_storage_class_migration_with_hotplugged_volumes
Comment thread
coderabbitai[bot] marked this conversation as resolved.


@pytest.fixture(scope="class")
def written_file_to_the_mounted_hotplugged_disk(vm_with_mounted_hotplugged_disk):
run_ssh_commands(
host=vm_with_mounted_hotplugged_disk.ssh_exec,
commands=shlex.split(
f"echo '{CONTENT}' | sudo tee {MOUNT_HOTPLUGGED_DEVICE_PATH}/{FILE_BEFORE_STORAGE_MIGRATION}"
),
wait_timeout=TIMEOUT_2MIN,
sleep=TIMEOUT_5SEC,
)
yield vm_with_mounted_hotplugged_disk
def written_files_to_mounted_hotplugged_disks(vm_with_mounted_hotplugged_disks):
for mount_path in MOUNT_HOTPLUGGED_DEVICE_PATHS:
run_ssh_commands(
host=vm_with_mounted_hotplugged_disks.ssh_exec,
commands=shlex.split(f"echo '{CONTENT}' | sudo tee {mount_path}/{FILE_BEFORE_STORAGE_MIGRATION}"),
wait_timeout=TIMEOUT_2MIN,
sleep=TIMEOUT_5SEC,
)
yield vm_with_mounted_hotplugged_disks


@pytest.fixture(scope="class")
Expand Down
5 changes: 3 additions & 2 deletions tests/storage/storage_migration/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
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}"

HOTPLUGGED_DEVICE = "/dev/sda"
MOUNT_HOTPLUGGED_DEVICE_PATH = "/mnt/hotplug"
NUM_HOTPLUG_DISKS = 3
Comment thread
jpeimer marked this conversation as resolved.
HOTPLUGGED_DEVICES = [f"/dev/sd{chr(ord('a') + idx)}" for idx in range(NUM_HOTPLUG_DISKS)]
MOUNT_HOTPLUGGED_DEVICE_PATHS = [f"/mnt/hotplug-{idx}" for idx in range(NUM_HOTPLUG_DISKS)]
16 changes: 8 additions & 8 deletions tests/storage/storage_migration/test_storage_class_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
WINDOWS_FILE_WITH_PATH,
)
from tests.storage.storage_migration.utils import (
verify_file_in_hotplugged_disk,
verify_files_in_hotplugged_disks,
verify_storage_migration_succeeded,
verify_vm_storage_class_updated,
verify_vms_boot_time_after_storage_migration,
Expand Down Expand Up @@ -156,12 +156,13 @@ def test_vm_storage_class_migration_b_to_a_with_running_vms(
[
pytest.param(
{"source_storage_class": py_config[STORAGE_CLASS_A]},
{"vms_fixtures": ["vm_for_storage_class_migration_with_hotplugged_volume"]},
{"vms_fixtures": ["vm_for_storage_class_migration_with_hotplugged_volumes"]},
id="mig_volume_hotplug_source_a_target_b",
)
],
indirect=True,
)
@pytest.mark.conformance
class TestStorageClassMigrationWithVolumeHotplug:
@pytest.mark.dependency(
name=f"{TESTS_CLASS_NAME_VOLUME_HOTPLUG}::test_vm_storage_class_migration_with_hotplugged_volume"
Expand All @@ -178,11 +179,11 @@ class TestStorageClassMigrationWithVolumeHotplug:
],
indirect=True,
)
@pytest.mark.usefixtures("written_files_to_mounted_hotplugged_disks")
def test_vm_storage_class_migration_with_hotplugged_volume(
self,
source_storage_class,
target_storage_class,
written_file_to_the_mounted_hotplugged_disk,
written_file_to_vms_before_migration,
online_vms_for_storage_class_migration,
vms_boot_time_before_storage_migration,
Expand All @@ -200,12 +201,11 @@ def test_vm_storage_class_migration_with_hotplugged_volume(
@pytest.mark.dependency(
depends=[f"{TESTS_CLASS_NAME_VOLUME_HOTPLUG}::test_vm_storage_class_migration_with_hotplugged_volume"]
)
@pytest.mark.usefixtures("vms_for_storage_class_migration")
@pytest.mark.polarion("CNV-12002")
def test_hotplugged_volume_data_after_storage_migration(
self, vms_for_storage_class_migration, written_file_to_the_mounted_hotplugged_disk
):
verify_file_in_hotplugged_disk(
vm=written_file_to_the_mounted_hotplugged_disk,
def test_hotplugged_volume_data_after_storage_migration(self, written_files_to_mounted_hotplugged_disks):
verify_files_in_hotplugged_disks(
vm=written_files_to_mounted_hotplugged_disks,
file_name=FILE_BEFORE_STORAGE_MIGRATION,
file_content=CONTENT,
)
Expand Down
30 changes: 21 additions & 9 deletions tests/storage/storage_migration/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from tests.storage.storage_migration.constants import (
CONTENT,
FILE_BEFORE_STORAGE_MIGRATION,
MOUNT_HOTPLUGGED_DEVICE_PATH,
MOUNT_HOTPLUGGED_DEVICE_PATHS,
)
from tests.storage.utils import check_file_in_vm
from utilities.constants.timeouts import TIMEOUT_2MIN, TIMEOUT_5SEC, TIMEOUT_10MIN, TIMEOUT_10SEC
Expand Down Expand Up @@ -74,14 +74,26 @@ def verify_storage_migration_succeeded(
verify_vm_storage_class_updated(vm=vm, target_storage_class=target_storage_class)


def verify_file_in_hotplugged_disk(vm: VirtualMachineForTests, file_name: str, file_content: str) -> None:
output = run_ssh_commands(
host=vm.ssh_exec,
commands=shlex.split(f"cat {MOUNT_HOTPLUGGED_DEVICE_PATH}/{file_name}"),
wait_timeout=TIMEOUT_2MIN,
sleep=TIMEOUT_5SEC,
)[0]
assert output.strip() == file_content, f"'{output}' does not equal '{file_content}'"
def verify_files_in_hotplugged_disks(vm: VirtualMachineForTests, file_name: str, file_content: str) -> None:
"""Verify that a file exists with expected content on all hotplugged disk mount paths.

Args:
vm: The VM to check.
file_name: Name of the file to verify on each mount path.
file_content: Expected content of the file.
"""
mismatches = {}
for mount_path in MOUNT_HOTPLUGGED_DEVICE_PATHS:
output = run_ssh_commands(
host=vm.ssh_exec,
commands=shlex.split(f"cat {mount_path}/{file_name}"),
wait_timeout=TIMEOUT_2MIN,
sleep=TIMEOUT_5SEC,
)[0]
stripped_output = output.strip()
if stripped_output != file_content:
mismatches[mount_path] = f"'{stripped_output}' does not equal '{file_content}'"
assert not mismatches, f"Data mismatch on hotplugged disk(s): {mismatches}"


def wait_for_storage_migration_completed(
Expand Down