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
