From c9547db3926cbcb5a7c7b0e33c062d7b5c6737f3 Mon Sep 17 00:00:00 2001 From: Rushikesh Jadhav Date: Mon, 7 Jul 2025 16:09:23 +0530 Subject: [PATCH 1/5] tests/storage/ext: Updated ext to handle both vhd and qcow2 vdi image format Signed-off-by: Rushikesh Jadhav --- tests/storage/ext/conftest.py | 9 +++++++-- tests/storage/ext/test_ext_sr.py | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/storage/ext/conftest.py b/tests/storage/ext/conftest.py index d0fb452a9..64af17d69 100644 --- a/tests/storage/ext/conftest.py +++ b/tests/storage/ext/conftest.py @@ -11,10 +11,15 @@ from lib.sr import SR @pytest.fixture(scope='package') -def ext_sr(host: Host, unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]]) -> Generator[SR]: +def ext_sr(host: Host, + unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str + ) -> Generator[SR]: """ An EXT SR on first host. """ sr_disk = unused_512B_disks[host][0]["name"] - sr = host.sr_create('ext', "EXT-local-SR-test", {'device': '/dev/' + sr_disk}) + sr = host.sr_create('ext', "EXT-local-SR-test", + {'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format}) yield sr # teardown sr.destroy() diff --git a/tests/storage/ext/test_ext_sr.py b/tests/storage/ext/test_ext_sr.py index 572102b66..e298a5fda 100644 --- a/tests/storage/ext/test_ext_sr.py +++ b/tests/storage/ext/test_ext_sr.py @@ -28,10 +28,15 @@ class TestEXTSRCreateDestroy: def test_create_sr_with_missing_device(self, host): try_to_create_sr_with_missing_device('ext', 'EXT-local-SR-test', host) - def test_create_and_destroy_sr(self, host: Host, unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]]) -> None: + def test_create_and_destroy_sr(self, host: Host, + unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str + ) -> None: # Create and destroy tested in the same test to leave the host as unchanged as possible sr_disk = unused_512B_disks[host][0]["name"] - sr = host.sr_create('ext', "EXT-local-SR-test", {'device': '/dev/' + sr_disk}, verify=True) + sr = host.sr_create('ext', "EXT-local-SR-test", + {'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format}, verify=True) # import a VM in order to detect vm import issues here rather than in the vm_on_xfs_fixture used in # the next tests, because errors in fixtures break teardown vm = host.import_vm(vm_image('mini-linux-x86_64-bios'), sr_uuid=sr.uuid) @@ -47,6 +52,13 @@ def test_quicktest(self, ext_sr): def test_vdi_is_not_open(self, vdi_on_ext_sr): assert not vdi_is_open(vdi_on_ext_sr) + def test_vdi_image_format(self, vdi_on_ext_sr: VDI, image_format: str): + fmt = vdi_on_ext_sr.get_image_format() + # feature-detect: if the SM doesn't report image-format, skip this check + if not fmt: + pytest.skip("SM does not report sm-config:image-format; skipping format check") + assert fmt == image_format + @pytest.mark.small_vm # run with a small VM to test the features @pytest.mark.big_vm # and ideally with a big VM to test it scales def test_start_and_shutdown_VM(self, vm_on_ext_sr): From 7ad889e5bc001b1f0f013ce7770e3ff05894153e Mon Sep 17 00:00:00 2001 From: Rushikesh Jadhav Date: Mon, 7 Jul 2025 18:23:00 +0530 Subject: [PATCH 2/5] tests/storage/lvm: Updated lvm to handle both vhd and qcow2 vdi image format Signed-off-by: Rushikesh Jadhav --- tests/storage/lvm/conftest.py | 9 +++++++-- tests/storage/lvm/test_lvm_sr.py | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/storage/lvm/conftest.py b/tests/storage/lvm/conftest.py index fb6845f88..d26a6f213 100644 --- a/tests/storage/lvm/conftest.py +++ b/tests/storage/lvm/conftest.py @@ -11,10 +11,15 @@ from lib.sr import SR @pytest.fixture(scope='package') -def lvm_sr(host: Host, unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]]) -> Generator[SR]: +def lvm_sr(host: Host, + unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str + ) -> Generator[SR]: """ An LVM SR on first host. """ sr_disk = unused_512B_disks[host][0]["name"] - sr = host.sr_create('lvm', "LVM-local-SR-test", {'device': '/dev/' + sr_disk}) + sr = host.sr_create('lvm', "LVM-local-SR-test", + {'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format}) yield sr # teardown sr.destroy() diff --git a/tests/storage/lvm/test_lvm_sr.py b/tests/storage/lvm/test_lvm_sr.py index 63aa79c88..d3f2fcfc9 100644 --- a/tests/storage/lvm/test_lvm_sr.py +++ b/tests/storage/lvm/test_lvm_sr.py @@ -28,10 +28,16 @@ class TestLVMSRCreateDestroy: def test_create_sr_with_missing_device(self, host): try_to_create_sr_with_missing_device('lvm', 'LVM-local-SR-test', host) - def test_create_and_destroy_sr(self, host: Host, unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]]) -> None: + def test_create_and_destroy_sr(self, host: Host, + unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str + ) -> None: sr_disk = unused_512B_disks[host][0]["name"] # Create and destroy tested in the same test to leave the host as unchanged as possible - sr = host.sr_create('lvm', "LVM-local-SR-test", {'device': '/dev/' + sr_disk}, verify=True) + sr = host.sr_create('lvm', "LVM-local-SR-test", { + 'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format + }, verify=True) # import a VM in order to detect vm import issues here rather than in the vm_on_xfs_fixture used in # the next tests, because errors in fixtures break teardown vm = host.import_vm(vm_image('mini-linux-x86_64-bios'), sr_uuid=sr.uuid) @@ -47,6 +53,13 @@ def test_quicktest(self, lvm_sr): def test_vdi_is_not_open(self, vdi_on_lvm_sr): assert not vdi_is_open(vdi_on_lvm_sr) + def test_vdi_image_format(self, vdi_on_lvm_sr: VDI, image_format: str): + fmt = vdi_on_lvm_sr.get_image_format() + # feature-detect: if the SM doesn't report image-format, skip this check + if not fmt: + pytest.skip("SM does not report sm-config:image-format; skipping format check") + assert fmt == image_format + @pytest.mark.small_vm # run with a small VM to test the features @pytest.mark.big_vm # and ideally with a big VM to test it scales def test_start_and_shutdown_VM(self, vm_on_lvm_sr): From 9454cff9c26b6873d06ee677d60d9ca2be65b23f Mon Sep 17 00:00:00 2001 From: Rushikesh Jadhav Date: Mon, 7 Jul 2025 21:11:07 +0530 Subject: [PATCH 3/5] tests/storage/xfs: Updated xfs to handle both vhd and qcow2 vdi image format Signed-off-by: Rushikesh Jadhav --- tests/storage/xfs/conftest.py | 14 +++++++++++--- tests/storage/xfs/test_xfs_sr.py | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/storage/xfs/conftest.py b/tests/storage/xfs/conftest.py index 806a5a8cb..0858d9381 100644 --- a/tests/storage/xfs/conftest.py +++ b/tests/storage/xfs/conftest.py @@ -10,8 +10,12 @@ from lib.host import Host from lib.sr import SR +# NOTE: @pytest.mark.usefixtures does not parametrize this fixture. +# To recreate host_with_xfsprogs for each image_format value, accept +# image_format in the fixture arguments. +# ref https://docs.pytest.org/en/7.1.x/how-to/fixtures.html#use-fixtures-in-classes-and-modules-with-usefixtures @pytest.fixture(scope='package') -def host_with_xfsprogs(host): +def host_with_xfsprogs(host: Host, image_format: str): assert not host.file_exists('/usr/sbin/mkfs.xfs'), \ "xfsprogs must not be installed on the host at the beginning of the tests" host.yum_save_state() @@ -21,11 +25,15 @@ def host_with_xfsprogs(host): host.yum_restore_saved_state() @pytest.fixture(scope='package') -def xfs_sr(unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], host_with_xfsprogs: Host +def xfs_sr(unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], + host_with_xfsprogs: Host, + image_format: str ) -> Generator[SR]: """ A XFS SR on first host. """ sr_disk = unused_512B_disks[host_with_xfsprogs][0]["name"] - sr = host_with_xfsprogs.sr_create('xfs', "XFS-local-SR-test", {'device': '/dev/' + sr_disk}) + sr = host_with_xfsprogs.sr_create('xfs', "XFS-local-SR-test", + {'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format}) yield sr # teardown sr.destroy() diff --git a/tests/storage/xfs/test_xfs_sr.py b/tests/storage/xfs/test_xfs_sr.py index 2d567bee7..4c0b0dd99 100644 --- a/tests/storage/xfs/test_xfs_sr.py +++ b/tests/storage/xfs/test_xfs_sr.py @@ -13,6 +13,7 @@ if TYPE_CHECKING: from lib.host import Host + from lib.vdi import VDI # Requirements: # - one XCP-ng host >= 8.2 with an additional unused disk for the SR @@ -27,7 +28,8 @@ class TestXFSSRCreateDestroy: def test_create_xfs_sr_without_xfsprogs(self, host: Host, - unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]] + unused_512B_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str ) -> None: # This test must be the first in the series in this module assert not host.file_exists('/usr/sbin/mkfs.xfs'), \ @@ -35,7 +37,10 @@ def test_create_xfs_sr_without_xfsprogs(self, sr_disk = unused_512B_disks[host][0]["name"] sr = None try: - sr = host.sr_create('xfs', "XFS-local-SR-test", {'device': '/dev/' + sr_disk}) + sr = host.sr_create('xfs', "XFS-local-SR-test", { + 'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format + }) except Exception: logging.info("SR creation failed, as expected.") if sr is not None: @@ -65,6 +70,13 @@ def test_quicktest(self, xfs_sr): def test_vdi_is_not_open(self, vdi_on_xfs_sr): assert not vdi_is_open(vdi_on_xfs_sr) + def test_vdi_image_format(self, vdi_on_xfs_sr: VDI, image_format: str): + fmt = vdi_on_xfs_sr.get_image_format() + # feature-detect: if the SM doesn't report image-format, skip this check + if not fmt: + pytest.skip("SM does not report sm-config:image-format; skipping format check") + assert fmt == image_format + @pytest.mark.small_vm # run with a small VM to test the features @pytest.mark.big_vm # and ideally with a big VM to test it scales def test_start_and_shutdown_VM(self, vm_on_xfs_sr): From e34bb061a6afc2d6a24d81fa2edaa08580b9e427 Mon Sep 17 00:00:00 2001 From: Rushikesh Jadhav Date: Tue, 8 Jul 2025 01:35:15 +0530 Subject: [PATCH 4/5] tests/storage/zfs: Updated zfs to handle both vhd and qcow2 vdi image format Signed-off-by: Rushikesh Jadhav --- tests/storage/zfs/conftest.py | 24 +++++++++++++++++++++--- tests/storage/zfs/test_zfs_sr.py | 29 +++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/tests/storage/zfs/conftest.py b/tests/storage/zfs/conftest.py index 2cd61925b..62a9334e0 100644 --- a/tests/storage/zfs/conftest.py +++ b/tests/storage/zfs/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest import logging @@ -5,6 +7,12 @@ # Explicitly import package-scoped fixtures (see explanation in pkgfixtures.py) from pkgfixtures import host_with_saved_yum_state, sr_disk_wiped +from typing import TYPE_CHECKING, Generator + +if TYPE_CHECKING: + from lib.host import Host + from lib.sr import SR + POOL_NAME = 'pool0' POOL_PATH = '/' + POOL_NAME @@ -13,8 +21,15 @@ def host_without_zfs(host): assert not host.file_exists('/usr/sbin/zpool'), \ "zfs must not be installed on the host at the beginning of the tests" +# NOTE: @pytest.mark.usefixtures does not parametrize this fixture. +# To recreate host_with_zfs for each image_format value, accept +# image_format in the fixture arguments. +# ref https://docs.pytest.org/en/7.1.x/how-to/fixtures.html#use-fixtures-in-classes-and-modules-with-usefixtures @pytest.fixture(scope='package') -def host_with_zfs(host_without_zfs, host_with_saved_yum_state): +def host_with_zfs(host_without_zfs: Host, + host_with_saved_yum_state: Host, + image_format: str + ) -> Generator[Host]: host = host_with_saved_yum_state host.yum_install(['zfs']) host.ssh(['modprobe', 'zfs']) @@ -28,9 +43,12 @@ def zpool_vol0(sr_disk_wiped, host_with_zfs): host_with_zfs.ssh(['zpool', 'destroy', POOL_NAME]) @pytest.fixture(scope='package') -def zfs_sr(host, zpool_vol0): +def zfs_sr(host: Host, image_format: str, zpool_vol0: None) -> Generator[SR]: """ A ZFS SR on first host. """ - sr = host.sr_create('zfs', "ZFS-local-SR-test", {'location': POOL_PATH}) + sr = host.sr_create('zfs', "ZFS-local-SR-test", { + 'location': POOL_PATH, + 'preferred-image-formats': image_format + }, verify=True) yield sr # teardown sr.destroy() diff --git a/tests/storage/zfs/test_zfs_sr.py b/tests/storage/zfs/test_zfs_sr.py index 64ac862d6..6852c3299 100755 --- a/tests/storage/zfs/test_zfs_sr.py +++ b/tests/storage/zfs/test_zfs_sr.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest import logging @@ -7,6 +9,12 @@ from lib.common import vm_image, wait_for from tests.storage import vdi_is_open +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from lib.host import Host + from lib.vdi import VDI + from .conftest import POOL_NAME, POOL_PATH # Requirements: @@ -21,13 +29,16 @@ class TestZFSSRCreateDestroy: and VM import. """ - def test_create_zfs_sr_without_zfs(self, host): + def test_create_zfs_sr_without_zfs(self, host: Host, image_format: str) -> None: # This test must be the first in the series in this module assert not host.file_exists('/usr/sbin/zpool'), \ "zfs must not be installed on the host at the beginning of the tests" sr = None try: - sr = host.sr_create('zfs', "ZFS-local-SR-test", {'location': POOL_PATH}) + sr = host.sr_create('zfs', "ZFS-local-SR-test", { + 'location': POOL_PATH, + 'preferred-image-formats': image_format + }, verify=True) except Exception: logging.info("SR creation failed, as expected.") if sr is not None: @@ -35,9 +46,12 @@ def test_create_zfs_sr_without_zfs(self, host): assert False, "SR creation should not have succeeded!" @pytest.mark.usefixtures("zpool_vol0") - def test_create_and_destroy_sr(self, host): + def test_create_and_destroy_sr(self, host: Host, image_format: str) -> None: # Create and destroy tested in the same test to leave the host as unchanged as possible - sr = host.sr_create('zfs', "ZFS-local-SR-test", {'location': POOL_PATH}, verify=True) + sr = host.sr_create('zfs', "ZFS-local-SR-test", { + 'location': POOL_PATH, + 'preferred-image-formats': image_format + }, verify=True) # import a VM in order to detect vm import issues here rather than in the vm_on_xfs_fixture used in # the next tests, because errors in fixtures break teardown vm = host.import_vm(vm_image('mini-linux-x86_64-bios'), sr_uuid=sr.uuid) @@ -53,6 +67,13 @@ def test_quicktest(self, zfs_sr): def test_vdi_is_not_open(self, vdi_on_zfs_sr): assert not vdi_is_open(vdi_on_zfs_sr) + def test_vdi_image_format(self, vdi_on_zfs_sr: VDI, image_format: str): + fmt = vdi_on_zfs_sr.get_image_format() + # feature-detect: if the SM doesn't report image-format, skip this check + if not fmt: + pytest.skip("SM does not report sm-config:image-format; skipping format check") + assert fmt == image_format + @pytest.mark.small_vm # run with a small VM to test the features @pytest.mark.big_vm # and ideally with a big VM to test it scales def test_start_and_shutdown_VM(self, vm_on_zfs_sr): From 9f1a8993bae094785aeea9898b5a36881651ba3c Mon Sep 17 00:00:00 2001 From: Rushikesh Jadhav Date: Wed, 9 Jul 2025 16:36:52 +0530 Subject: [PATCH 5/5] tests/storage/largeblock: Updated largeblock to handle both vhd and qcow2 vdi image format Signed-off-by: Rushikesh Jadhav --- tests/storage/largeblock/conftest.py | 8 ++++++-- tests/storage/largeblock/test_largeblock_sr.py | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/storage/largeblock/conftest.py b/tests/storage/largeblock/conftest.py index 58702a757..854ed0665 100644 --- a/tests/storage/largeblock/conftest.py +++ b/tests/storage/largeblock/conftest.py @@ -11,10 +11,14 @@ from lib.sr import SR @pytest.fixture(scope='package') -def largeblock_sr(host: Host, unused_4k_disks: dict[Host, list[Host.BlockDeviceInfo]]) -> Generator[SR]: +def largeblock_sr(host: Host, + unused_4k_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str) -> Generator[SR]: """ A LARGEBLOCK SR on first host. """ sr_disk = unused_4k_disks[host][0]["name"] - sr = host.sr_create('largeblock', "LARGEBLOCK-local-SR-test", {'device': '/dev/' + sr_disk}) + sr = host.sr_create('largeblock', "LARGEBLOCK-local-SR-test", + {'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format}) yield sr # teardown sr.destroy() diff --git a/tests/storage/largeblock/test_largeblock_sr.py b/tests/storage/largeblock/test_largeblock_sr.py index c2683283e..581c6f9ff 100644 --- a/tests/storage/largeblock/test_largeblock_sr.py +++ b/tests/storage/largeblock/test_largeblock_sr.py @@ -9,6 +9,7 @@ if TYPE_CHECKING: from lib.host import Host + from lib.vdi import VDI # Requirements: # - one XCP-ng host with an additional unused 4KiB disk for the SR @@ -23,10 +24,14 @@ class TestLARGEBLOCKSRCreateDestroy: def test_create_sr_with_missing_device(self, host): try_to_create_sr_with_missing_device('largeblock', 'LARGEBLOCK-local-SR-test', host) - def test_create_and_destroy_sr(self, host: Host, unused_4k_disks: dict[Host, list[Host.BlockDeviceInfo]]) -> None: + def test_create_and_destroy_sr(self, host: Host, + unused_4k_disks: dict[Host, list[Host.BlockDeviceInfo]], + image_format: str) -> None: # Create and destroy tested in the same test to leave the host as unchanged as possible sr_disk = unused_4k_disks[host][0]["name"] - sr = host.sr_create('largeblock', "LARGEBLOCK-local-SR-test", {'device': '/dev/' + sr_disk}, verify=True) + sr = host.sr_create('largeblock', "LARGEBLOCK-local-SR-test", + {'device': '/dev/' + sr_disk, + 'preferred-image-formats': image_format}, verify=True) # import a VM in order to detect vm import issues here rather than in the vm_on_xfs_fixture used in # the next tests, because errors in fixtures break teardown vm = host.import_vm(vm_image('mini-linux-x86_64-bios'), sr_uuid=sr.uuid) @@ -42,6 +47,13 @@ def test_quicktest(self, largeblock_sr): def test_vdi_is_not_open(self, vdi_on_largeblock_sr): assert not vdi_is_open(vdi_on_largeblock_sr) + def test_vdi_image_format(self, vdi_on_largeblock_sr: VDI, image_format: str): + fmt = vdi_on_largeblock_sr.get_image_format() + # feature-detect: if the SM doesn't report image-format, skip this check + if not fmt: + pytest.skip("SM does not report sm-config:image-format; skipping format check") + assert fmt == image_format + @pytest.mark.small_vm # run with a small VM to test the features @pytest.mark.big_vm # and ideally with a big VM to test it scales def test_start_and_shutdown_VM(self, vm_on_largeblock_sr):