test_lvm2.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import os
  2. import subprocess
  3. import infra.basetest
  4. class TestLvm2(infra.basetest.BRTest):
  5. # This test creates a lvm2 volume. A specific Kernel need to be
  6. # built with a config fragment enabling this support. This test
  7. # also uses resize2fs from e2fsprogs.
  8. kernel_fragment = \
  9. infra.filepath("tests/package/test_lvm2/linux-lvm2.fragment")
  10. config = \
  11. f"""
  12. BR2_aarch64=y
  13. BR2_TOOLCHAIN_EXTERNAL=y
  14. BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
  15. BR2_LINUX_KERNEL=y
  16. BR2_LINUX_KERNEL_CUSTOM_VERSION=y
  17. BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.77"
  18. BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
  19. BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
  20. BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{kernel_fragment}"
  21. BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
  22. BR2_PACKAGE_E2FSPROGS=y
  23. BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
  24. BR2_PACKAGE_LVM2=y
  25. BR2_TARGET_ROOTFS_CPIO=y
  26. BR2_TARGET_ROOTFS_CPIO_GZIP=y
  27. # BR2_TARGET_ROOTFS_TAR is not set
  28. """
  29. def get_free_disk_space(self, path):
  30. out, ret = self.emulator.run(f"df -k {path}")
  31. self.assertEqual(ret, 0)
  32. return int(out[1].split()[3])
  33. def test_run(self):
  34. # Test configuration:
  35. storage_devs = ["/dev/vda", "/dev/vdb", "/dev/vdc"]
  36. storage_size = 16 # Mega Bytes
  37. lvm_vg = "br_vg" # Volume Group name
  38. lvm_lv = "br_lv" # Logical Volume name
  39. lv_dev = f"/dev/{lvm_vg}/{lvm_lv}" # Logical Volume dev name
  40. mnt_pt = "/mnt/lvm2-storage"
  41. data_file = f"{mnt_pt}/data.bin"
  42. qemu_storage_opts = []
  43. for i in range(len(storage_devs)):
  44. disk_file = os.path.join(self.builddir, "images", f"disk{i}.img")
  45. self.emulator.logfile.write(f"Creating disk image: {disk_file}\n")
  46. self.emulator.logfile.flush()
  47. subprocess.check_call(
  48. ["dd", "if=/dev/zero", f"of={disk_file}",
  49. "bs=1M", f"count={storage_size}"],
  50. stdout=self.emulator.logfile,
  51. stderr=self.emulator.logfile)
  52. opts = ["-drive", f"file={disk_file},if=virtio,format=raw"]
  53. qemu_storage_opts += opts
  54. img = os.path.join(self.builddir, "images", "rootfs.cpio.gz")
  55. kern = os.path.join(self.builddir, "images", "Image")
  56. self.emulator.boot(arch="aarch64",
  57. kernel=kern,
  58. kernel_cmdline=["console=ttyAMA0"],
  59. options=["-M", "virt", "-cpu", "cortex-a57", "-m", "256M",
  60. "-initrd", img] + qemu_storage_opts)
  61. self.emulator.login()
  62. # Test the program can execute.
  63. self.assertRunOk("lvm version")
  64. # We did not created any Physical Volume yet. We should NOT
  65. # see any of our storage devices in a pvscan.
  66. out, ret = self.emulator.run("pvscan")
  67. self.assertEqual(ret, 0)
  68. for dev in storage_devs:
  69. self.assertNotIn(dev, "\n".join(out))
  70. # We initialize our Physical Volumes (PVs).
  71. pv_devs = " ".join(storage_devs)
  72. self.assertRunOk(f"pvcreate {pv_devs}")
  73. # We run few diagnostic commands related to PVs.
  74. self.assertRunOk(f"pvck {pv_devs}")
  75. self.assertRunOk(f"pvdisplay {pv_devs}")
  76. self.assertRunOk("pvs")
  77. # Now we initialized the PVs, we should see them in a pvscan.
  78. out, ret = self.emulator.run("pvscan")
  79. self.assertEqual(ret, 0)
  80. for dev in storage_devs:
  81. self.assertIn(dev, "\n".join(out))
  82. # We create a Volume Group (VG) including two of our three
  83. # PVs.
  84. cmd = f"vgcreate {lvm_vg} {storage_devs[0]} {storage_devs[1]}"
  85. self.assertRunOk(cmd)
  86. # We run few diagnostic commands related to VGs.
  87. self.assertRunOk(f"vgck {lvm_vg}")
  88. self.assertRunOk(f"vgdisplay {lvm_vg}")
  89. self.assertRunOk("vgscan")
  90. self.assertRunOk("vgs")
  91. # We create a Logical Volume (LV) in our VG.
  92. self.assertRunOk(f"lvcreate -l 100%FREE -n {lvm_lv} {lvm_vg}")
  93. # We check LVM created the LV device.
  94. self.assertRunOk(f"ls -al {lv_dev}")
  95. # We run few diagnostic commands related to LVs.
  96. self.assertRunOk("lvscan")
  97. self.assertRunOk("lvs")
  98. # We create a ext4 filesystem on our LV.
  99. self.assertRunOk(f"mkfs.ext4 {lv_dev}")
  100. # We create a mount point directory and mount the device.
  101. self.assertRunOk(f"mkdir -p {mnt_pt}")
  102. self.assertRunOk(f"mount {lv_dev} {mnt_pt}")
  103. # We create a data file in our new filesystem. Note: this file
  104. # is slightly larger than a single PV. This data file should
  105. # span over the two PVs in the VG.
  106. data_size = storage_size + 4
  107. cmd = f"dd if=/dev/urandom of={data_file} bs=1M count={data_size}"
  108. self.assertRunOk(cmd)
  109. # We compute the hash of our data, and save it for later.
  110. hash_cmd = f"sha256sum {data_file}"
  111. out, ret = self.emulator.run(hash_cmd)
  112. self.assertEqual(ret, 0)
  113. data_sha256 = out[0]
  114. # We compute the free space of the mount point.
  115. fs_free_space = self.get_free_disk_space(mnt_pt)
  116. # We extend of VG with our third PV.
  117. self.assertRunOk(f"vgextend {lvm_vg} {storage_devs[2]}")
  118. # We grow the LV to use all the space of the VG.
  119. self.assertRunOk(f"lvresize -l +100%FREE {lvm_vg}/{lvm_lv}")
  120. # We resize the filesystem to use all the LV space.
  121. self.assertRunOk(f"resize2fs {lv_dev}")
  122. # Now we grew the LV and resized the filesystem, we recompute
  123. # the free space and check we have more.
  124. fs2_free_space = self.get_free_disk_space(mnt_pt)
  125. self.assertGreater(fs2_free_space, fs_free_space)
  126. # With all those on-the-fly operations on the mounted
  127. # filesystem, the data file should be intact. We should
  128. # recompute the same data checksum as before.
  129. out, ret = self.emulator.run(hash_cmd)
  130. self.assertEqual(ret, 0)
  131. self.assertEqual(out[0], data_sha256)
  132. # Finally, we unmount the filesystem. It should not contain
  133. # any error.
  134. self.assertRunOk(f"umount {mnt_pt}")
  135. self.assertRunOk(f"e2fsck -f -n {lv_dev}")