Verify that Barebox can parse the metadata of a PV and activate an LV
discontinuously spread over two PVs.

Official LVM tooling only works on block devices, so guestfish(1) is
leveraged to create the test image. Since it is a bit finicky to run
on some platforms (e.g., Ubuntu installs kernels as 0600, which means
users can't run guestfish by default), we opt for checking in a
compressed version along with the script used to generate it.

Signed-off-by: Tobias Waldekranz <[email protected]>
---
 .../boards/configs/enable_dm_testing.config   |   2 +
 scripts/lvm-pvs.guestfish                     |  53 ++++++++++++
 test/py/test_lvm.py                           |  76 ++++++++++++++++++
 test/testdata/lvm-pvs.disk.xz                 | Bin 0 -> 2956 bytes
 4 files changed, 131 insertions(+)
 create mode 100755 scripts/lvm-pvs.guestfish
 create mode 100644 test/py/test_lvm.py
 create mode 100644 test/testdata/lvm-pvs.disk.xz

diff --git a/common/boards/configs/enable_dm_testing.config 
b/common/boards/configs/enable_dm_testing.config
index 16c3f702c1..eda2fc41a3 100644
--- a/common/boards/configs/enable_dm_testing.config
+++ b/common/boards/configs/enable_dm_testing.config
@@ -3,7 +3,9 @@ CONFIG_DISK=y
 CONFIG_DM_BLK=y
 CONFIG_DM_BLK_LINEAR=y
 CONFIG_DM_BLK_VERITY=y
+CONFIG_DM_LVM=y
 CONFIG_CMD_DMSETUP=y
 CONFIG_CMD_VERITYSETUP=y
+CONFIG_CMD_LVM=y
 CONFIG_CMD_MD5SUM=y
 CONFIG_CMD_READF=y
diff --git a/scripts/lvm-pvs.guestfish b/scripts/lvm-pvs.guestfish
new file mode 100755
index 0000000000..c8d31385f3
--- /dev/null
+++ b/scripts/lvm-pvs.guestfish
@@ -0,0 +1,53 @@
+#!/usr/bin/guestfish -f
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Create a single disk image that holds two LVM PVs. This is used by
+# the LVM labgrid tests.
+
+alloc lvm-pvs.disk 8M
+launch
+
+part-init /dev/sda gpt
+part-add /dev/sda p 34 8191
+part-add /dev/sda p 8192 -34
+
+# Keep sizes reasonably small
+debug sh "lvm pvcreate --metadatasize 4k /dev/sda1"
+debug sh "lvm pvcreate --metadatasize 4k --pvmetadatacopies 2 /dev/sda2"
+debug sh "lvm vgcreate -s 4k testvg /dev/sda1 /dev/sda2"
+
+# Create an LV with three segments that span both PVs
+debug sh "lvm lvcreate -y -n testlv -l 8 testvg /dev/sda1:8-15"
+debug sh "lvm lvextend -l +8 testvg/testlv /dev/sda2:0-7"
+debug sh "lvm lvextend -l +8 testvg/testlv /dev/sda1:0-7"
+
+debug sh "lvm lvs -o lv_name,seg_le_ranges --segments testvg"
+
+mkfs vfat /dev/testvg/testlv
+mount /dev/testvg/testlv /
+
+# Generate a test file that:
+# 1. Is big enough to be spread over all three segments
+# 2. Contains data that is sensitvie to reordering
+# 3. Compresses well, since we're checking it in
+debug sh "printf \'0%*s0\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'1%*s1\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'2%*s2\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'3%*s3\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'4%*s4\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'5%*s5\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'6%*s6\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'7%*s7\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'8%*s8\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'9%*s9\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'a%*sa\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'b%*sb\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'c%*sc\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'d%*sd\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'e%*se\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'f%*sf\' 4094 >>/sysroot/bigfile"
+debug sh "printf \'g%*sg\' 4094 >>/sysroot/bigfile"
+debug sh "md5sum </sysroot/bigfile >/sysroot/bigfile.md5sum"
+
+umount /
+
diff --git a/test/py/test_lvm.py b/test/py/test_lvm.py
new file mode 100644
index 0000000000..c148571780
--- /dev/null
+++ b/test/py/test_lvm.py
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import hashlib
+import lzma
+import os
+import pytest
+import shutil
+
+from .helper import skip_disabled
+
+
[email protected](scope="module")
+def lvm_testdata(testfs):
+    """Extract checked in disk image containing two LVM PVs
+
+    The disk image was created using the standard LVM tooling, see
+    test/testdata/lvm-pvs.guestfish.
+    """
+    path = os.path.join(testfs, "lvm")
+    os.makedirs(path, exist_ok=True)
+
+    diskxz = os.path.join(os.path.dirname(__file__), os.pardir, "testdata",
+                          "lvm-pvs.disk.xz")
+    disk = os.path.join(path, "lvm-pvs.disk")
+    dmtable = os.path.join(path, "lvm-pvs.disk.dm")
+
+    diskblks = 0
+    with lzma.open(diskxz) as src:
+        with open(disk, "wb") as dst:
+            dst.write(src.read())
+            diskblks = dst.tell() // 512
+
+    with open(dmtable, "w") as f:
+        f.write(f"0 {diskblks} linear lvm-pvs.disk 0\n")
+
+    yield {
+        "disk": disk,
+        "dmtable": dmtable,
+    }
+
+    shutil.rmtree(path)
+
+
[email protected](autouse=True)
+def cleanup(barebox, barebox_config):
+    skip_disabled(barebox_config,
+                  "CONFIG_CMD_LVM",
+                  "CONFIG_CMD_DMSETUP")
+    yield
+    barebox.run("umount /mnt/testvg-testlv")
+    barebox.run("dmsetup remove testvg-testlv")
+    barebox.run("dmsetup remove pvs")
+    barebox.run("cd")
+
+
+def test_lvm(barebox, barebox_config, lvm_testdata):
+    barebox.run_check("cd /mnt/9p/testfs/lvm")
+
+    # LVM only operates on block devices. Create a linear mapping over
+    # the full disk image to accomplish the equivalent of `losetup`.
+    barebox.run_check("dmsetup create pvs lvm-pvs.disk.dm")
+
+    out = "\n".join(barebox.run_check("lvm info"))
+    for line in ("VG \"testvg\"",
+                 "#PV:     2",
+                 "#LV:     1",
+                 "LV \"testlv\"",
+                 "Type:  linear"):
+        assert line in out, f"Expected \"{line}\" in output of 'lvm info'"
+
+    barebox.run_check("lvm activate testvg testlv")
+    barebox.run_check("mount testvg-testlv")
+
+    bigsum = barebox.run_check("md5sum 
/mnt/testvg-testlv/bigfile")[0].split()[0]
+    bigexp = barebox.run_check("cat 
/mnt/testvg-testlv/bigfile.md5sum")[0].split()[0]
+    assert bigsum == bigexp, "Expected md5sum of bigfile to match 
bigfile.md5sum"
diff --git a/test/testdata/lvm-pvs.disk.xz b/test/testdata/lvm-pvs.disk.xz
new file mode 100644
index 
0000000000000000000000000000000000000000..589747a41ce43850e4bcf110a6e0aad95b31a3aa
GIT binary patch
literal 2956
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
WMbRgAdCfKw?jC`D%>eYah`#`qRJ~LH

literal 0
HcmV?d00001

-- 
2.43.0


Reply via email to