diff mbox series

[1/1] support/testing: add lvm2 runtime test

Message ID 20240213204915.27898-1-ju.o@free.fr
State Accepted
Headers show
Series [1/1] support/testing: add lvm2 runtime test | expand

Commit Message

Julien Olivain Feb. 13, 2024, 8:49 p.m. UTC
Signed-off-by: Julien Olivain <ju.o@free.fr>
---
 DEVELOPERS                                    |   2 +
 support/testing/tests/package/test_lvm2.py    | 163 ++++++++++++++++++
 .../package/test_lvm2/linux-lvm2.fragment     |   2 +
 3 files changed, 167 insertions(+)
 create mode 100644 support/testing/tests/package/test_lvm2.py
 create mode 100644 support/testing/tests/package/test_lvm2/linux-lvm2.fragment

Comments

Arnout Vandecappelle April 2, 2024, 7:53 p.m. UTC | #1
On 13/02/2024 21:49, Julien Olivain wrote:
> Signed-off-by: Julien Olivain <ju.o@free.fr>

  Applied to master, thanks.

[snip]
> diff --git a/support/testing/tests/package/test_lvm2/linux-lvm2.fragment b/support/testing/tests/package/test_lvm2/linux-lvm2.fragment
> new file mode 100644
> index 0000000000..0fade167a3
> --- /dev/null
> +++ b/support/testing/tests/package/test_lvm2/linux-lvm2.fragment
> @@ -0,0 +1,2 @@
> +CONFIG_MD=y
> +CONFIG_BLK_DEV_DM=y

  Perhaps these should be enabled by lvm2 itself (using LVM2_LINUX_CONFIG_FIXUPS)?

  Regards,
  Arnout
diff mbox series

Patch

diff --git a/DEVELOPERS b/DEVELOPERS
index 0d12c3abcb..e6d79f3675 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -1810,6 +1810,8 @@  F:	support/testing/tests/package/test_libgpgme.py
 F:	support/testing/tests/package/test_libjxl.py
 F:	support/testing/tests/package/test_lrzip.py
 F:	support/testing/tests/package/test_ltrace.py
+F:	support/testing/tests/package/test_lvm2.py
+F:	support/testing/tests/package/test_lvm2/
 F:	support/testing/tests/package/test_lzip.py
 F:	support/testing/tests/package/test_lsof.py
 F:	support/testing/tests/package/test_lz4.py
diff --git a/support/testing/tests/package/test_lvm2.py b/support/testing/tests/package/test_lvm2.py
new file mode 100644
index 0000000000..bdbae7a4ec
--- /dev/null
+++ b/support/testing/tests/package/test_lvm2.py
@@ -0,0 +1,163 @@ 
+import os
+import subprocess
+
+import infra.basetest
+
+
+class TestLvm2(infra.basetest.BRTest):
+    # This test creates a lvm2 volume. A specific Kernel need to be
+    # built with a config fragment enabling this support. This test
+    # also uses resize2fs from e2fsprogs.
+    kernel_fragment = \
+        infra.filepath("tests/package/test_lvm2/linux-lvm2.fragment")
+    config = \
+        f"""
+        BR2_aarch64=y
+        BR2_TOOLCHAIN_EXTERNAL=y
+        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
+        BR2_LINUX_KERNEL=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.77"
+        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
+        BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{kernel_fragment}"
+        BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+        BR2_PACKAGE_E2FSPROGS=y
+        BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
+        BR2_PACKAGE_LVM2=y
+        BR2_TARGET_ROOTFS_CPIO=y
+        BR2_TARGET_ROOTFS_CPIO_GZIP=y
+        # BR2_TARGET_ROOTFS_TAR is not set
+        """
+
+    def get_free_disk_space(self, path):
+        out, ret = self.emulator.run(f"df -k {path}")
+        self.assertEqual(ret, 0)
+        return int(out[1].split()[3])
+
+    def test_run(self):
+        # Test configuration:
+        storage_devs = ["/dev/vda", "/dev/vdb", "/dev/vdc"]
+        storage_size = 16                       # Mega Bytes
+        lvm_vg = "br_vg"                        # Volume Group name
+        lvm_lv = "br_lv"                        # Logical Volume name
+        lv_dev = f"/dev/{lvm_vg}/{lvm_lv}"      # Logical Volume dev name
+        mnt_pt = "/mnt/lvm2-storage"
+        data_file = f"{mnt_pt}/data.bin"
+
+        qemu_storage_opts = []
+        for i in range(len(storage_devs)):
+            disk_file = os.path.join(self.builddir, "images", f"disk{i}.img")
+            self.emulator.logfile.write(f"Creating disk image: {disk_file}\n")
+            self.emulator.logfile.flush()
+            subprocess.check_call(
+                ["dd", "if=/dev/zero", f"of={disk_file}",
+                 "bs=1M", f"count={storage_size}"],
+                stdout=self.emulator.logfile,
+                stderr=self.emulator.logfile)
+            opts = ["-drive", f"file={disk_file},if=virtio,format=raw"]
+            qemu_storage_opts += opts
+
+        img = os.path.join(self.builddir, "images", "rootfs.cpio.gz")
+        kern = os.path.join(self.builddir, "images", "Image")
+        self.emulator.boot(arch="aarch64",
+                           kernel=kern,
+                           kernel_cmdline=["console=ttyAMA0"],
+                           options=["-M", "virt", "-cpu", "cortex-a57", "-m", "256M",
+                                    "-initrd", img] + qemu_storage_opts)
+        self.emulator.login()
+
+        # Test the program can execute.
+        self.assertRunOk("lvm version")
+
+        # We did not created any Physical Volume yet. We should NOT
+        # see any of our storage devices in a pvscan.
+        out, ret = self.emulator.run("pvscan")
+        self.assertEqual(ret, 0)
+        for dev in storage_devs:
+            self.assertNotIn(dev, "\n".join(out))
+
+        # We initialize our Physical Volumes (PVs).
+        pv_devs = " ".join(storage_devs)
+        self.assertRunOk(f"pvcreate {pv_devs}")
+
+        # We run few diagnostic commands related to PVs.
+        self.assertRunOk(f"pvck {pv_devs}")
+        self.assertRunOk(f"pvdisplay {pv_devs}")
+        self.assertRunOk("pvs")
+
+        # Now we initialized the PVs, we should see them in a pvscan.
+        out, ret = self.emulator.run("pvscan")
+        self.assertEqual(ret, 0)
+        for dev in storage_devs:
+            self.assertIn(dev, "\n".join(out))
+
+        # We create a Volume Group (VG) including two of our three
+        # PVs.
+        cmd = f"vgcreate {lvm_vg} {storage_devs[0]} {storage_devs[1]}"
+        self.assertRunOk(cmd)
+
+        # We run few diagnostic commands related to VGs.
+        self.assertRunOk(f"vgck {lvm_vg}")
+        self.assertRunOk(f"vgdisplay {lvm_vg}")
+        self.assertRunOk("vgscan")
+        self.assertRunOk("vgs")
+
+        # We create a Logical Volume (LV) in our VG.
+        self.assertRunOk(f"lvcreate -l 100%FREE -n {lvm_lv} {lvm_vg}")
+
+        # We check LVM created the LV device.
+        self.assertRunOk(f"ls -al {lv_dev}")
+
+        # We run few diagnostic commands related to LVs.
+        self.assertRunOk("lvscan")
+        self.assertRunOk("lvs")
+
+        # We create a ext4 filesystem on our LV.
+        self.assertRunOk(f"mkfs.ext4 {lv_dev}")
+
+        # We create a mount point directory and mount the device.
+        self.assertRunOk(f"mkdir -p {mnt_pt}")
+        self.assertRunOk(f"mount {lv_dev} {mnt_pt}")
+
+        # We create a data file in our new filesystem. Note: this file
+        # is slightly larger than a single PV. This data file should
+        # span over the two PVs in the VG.
+        data_size = storage_size + 4
+        cmd = f"dd if=/dev/urandom of={data_file} bs=1M count={data_size}"
+        self.assertRunOk(cmd)
+
+        # We compute the hash of our data, and save it for later.
+        hash_cmd = f"sha256sum {data_file}"
+        out, ret = self.emulator.run(hash_cmd)
+        self.assertEqual(ret, 0)
+        data_sha256 = out[0]
+
+        # We compute the free space of the mount point.
+        fs_free_space = self.get_free_disk_space(mnt_pt)
+
+        # We extend of VG with our third PV.
+        self.assertRunOk(f"vgextend {lvm_vg} {storage_devs[2]}")
+
+        # We grow the LV to use all the space of the VG.
+        self.assertRunOk(f"lvresize -l +100%FREE {lvm_vg}/{lvm_lv}")
+
+        # We resize the filesystem to use all the LV space.
+        self.assertRunOk(f"resize2fs {lv_dev}")
+
+        # Now we grew the LV and resized the filesystem, we recompute
+        # the free space and check we have more.
+        fs2_free_space = self.get_free_disk_space(mnt_pt)
+        self.assertGreater(fs2_free_space, fs_free_space)
+
+        # With all those on-the-fly operations on the mounted
+        # filesystem, the data file should be intact. We should
+        # recompute the same data checksum as before.
+        out, ret = self.emulator.run(hash_cmd)
+        self.assertEqual(ret, 0)
+        self.assertEqual(out[0], data_sha256)
+
+        # Finally, we unmount the filesystem. It should not contain
+        # any error.
+        self.assertRunOk(f"umount {mnt_pt}")
+        self.assertRunOk(f"e2fsck -f -n {lv_dev}")
diff --git a/support/testing/tests/package/test_lvm2/linux-lvm2.fragment b/support/testing/tests/package/test_lvm2/linux-lvm2.fragment
new file mode 100644
index 0000000000..0fade167a3
--- /dev/null
+++ b/support/testing/tests/package/test_lvm2/linux-lvm2.fragment
@@ -0,0 +1,2 @@ 
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y