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 | 55 +++++++++++++ test/py/test_lvm.py | 75 ++++++++++++++++++ test/testdata/lvm-pvs.disk.xz | Bin 0 -> 2968 bytes 4 files changed, 132 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..2e9c368317 --- /dev/null +++ b/scripts/lvm-pvs.guestfish @@ -0,0 +1,55 @@ +#!/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 +part-set-name /dev/sda 1 pv1 +part-set-name /dev/sda 2 pv2 + +# 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 sensitive 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..096540e1fd --- /dev/null +++ b/test/py/test_lvm.py @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +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..844b33e066d06b39b97a925bf35adbf8033b7083 GIT binary patch literal 2968 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 literal 0 HcmV?d00001 -- 2.43.0
