From ec8e187f67d436881cdc794804f93e09beac1bcf Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Fri, 27 Oct 2023 13:28:50 +0200 Subject: [PATCH 01/24] ci: Update default branch for Packit to 3.9-devel/release --- .packit.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.packit.yaml b/.packit.yaml index 24d364dd4..66c389f24 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -4,7 +4,7 @@ actions: - 'git config user.email "blivet-ci@example.com"' - 'git config user.name "Blivet CI"' # merge the release branch to get correct version in spec - - 'git merge --ff origin/3.8-release' + - 'git merge --ff origin/3.9-release' get-current-version: - "python3 ./setup.py --version" create-archive: @@ -28,7 +28,7 @@ jobs: trigger: commit owner: "@storage" project: blivet-daily - branch: 3.8-devel + branch: 3.9-devel preserve_project: true srpm_build_deps: From 8ca3d5545a353f054d4e1d22491a182c48f30f9d Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 11:40:45 +0200 Subject: [PATCH 02/24] Remove support for ReiserFS ReiserFs support is scheluded to be removed from the kernel and the userspace tools were removed in Fedora 35. This removes only support for creating and managing ReiserFS, we will still recognize the filesystem. --- blivet/flags.py | 2 -- blivet/formats/fs.py | 20 ------------------- blivet/tasks/availability.py | 3 --- blivet/tasks/fsinfo.py | 5 ----- blivet/tasks/fslabeling.py | 9 --------- blivet/tasks/fsmkfs.py | 13 ------------ blivet/tasks/fssize.py | 4 ---- blivet/tasks/fsuuid.py | 6 ------ blivet/tasks/fswritelabel.py | 8 -------- blivet/tasks/fswriteuuid.py | 8 -------- doc/api/formats.rst | 1 - tests/storage_tests/formats_test/fs_test.py | 4 ---- .../formats_test/labeling_test.py | 9 --------- tests/storage_tests/formats_test/uuid_test.py | 16 ++------------- 14 files changed, 2 insertions(+), 106 deletions(-) diff --git a/blivet/flags.py b/blivet/flags.py index 716f0df47..be4eaa899 100644 --- a/blivet/flags.py +++ b/blivet/flags.py @@ -51,7 +51,6 @@ def __init__(self): self.gfs2 = True self.jfs = True - self.reiserfs = True # for this flag to take effect, # blockdev.mpath.set_friendly_names(flags.multipath_friendly_names) must @@ -113,7 +112,6 @@ def update_from_boot_cmdline(self): self.noiswmd = "noiswmd" in self.boot_cmdline self.gfs2 = "gfs2" in self.boot_cmdline self.jfs = "jfs" in self.boot_cmdline - self.reiserfs = "reiserfs" in self.boot_cmdline flags = Flags() diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index acc1f9cb9..b2cbe8ca6 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1077,27 +1077,7 @@ class ReiserFS(FS): """ reiserfs filesystem """ _type = "reiserfs" - _labelfs = fslabeling.ReiserFSLabeling() - _uuidfs = fsuuid.ReiserFSUUID() - _modules = ["reiserfs"] - _max_size = Size("16 TiB") - _formattable = True _linux_native = True - _dump = True - _check = True - _packages = ["reiserfs-utils"] - _info_class = fsinfo.ReiserFSInfo - _mkfs_class = fsmkfs.ReiserFSMkfs - _size_info_class = fssize.ReiserFSSize - _writelabel_class = fswritelabel.ReiserFSWriteLabel - _writeuuid_class = fswriteuuid.ReiserFSWriteUUID - _metadata_size_factor = 0.98 # reiserfs metadata may take 2% of space - parted_system = fileSystemType["reiserfs"] - - @property - def supported(self): - """ Is this filesystem a supported type? """ - return self.utils_available if flags.reiserfs else self._supported register_device_format(ReiserFS) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 4b947d6cd..ffbc6b087 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -500,7 +500,6 @@ def available_resource(name): DOSFSTOOLS_VERSION = VersionMethod(DOSFSTOOLS_INFO) # applications -DEBUGREISERFS_APP = application("debugreiserfs") DF_APP = application("df") DOSFSCK_APP = application("dosfsck") DOSFSLABEL_APP = application("dosfslabel") @@ -521,13 +520,11 @@ def available_resource(name): MKFS_JFS_APP = application("mkfs.jfs") MKFS_XFS_APP = application("mkfs.xfs") MKNTFS_APP = application("mkntfs") -MKREISERFS_APP = application("mkreiserfs") MLABEL_APP = application("mlabel") MULTIPATH_APP = application("multipath") NTFSINFO_APP = application("ntfsinfo") NTFSLABEL_APP = application("ntfslabel") NTFSRESIZE_APP = application("ntfsresize") -REISERFSTUNE_APP = application("reiserfstune") RESIZE2FS_APP = application_by_version("resize2fs", E2FSPROGS_VERSION) TUNE2FS_APP = application_by_version("tune2fs", E2FSPROGS_VERSION) XFSADMIN_APP = application("xfs_admin") diff --git a/blivet/tasks/fsinfo.py b/blivet/tasks/fsinfo.py index b5432e9ce..af35af5ab 100644 --- a/blivet/tasks/fsinfo.py +++ b/blivet/tasks/fsinfo.py @@ -88,11 +88,6 @@ class NTFSInfo(FSInfo): options = ["-m"] -class ReiserFSInfo(FSInfo): - ext = availability.DEBUGREISERFS_APP - options = [] - - class XFSInfo(FSInfo): ext = availability.XFSDB_APP options = ["-c", "sb 0", "-c", "p dblocks", "-c", "p blocksize", "-r"] diff --git a/blivet/tasks/fslabeling.py b/blivet/tasks/fslabeling.py index 5bc0111d1..1a1c4b841 100644 --- a/blivet/tasks/fslabeling.py +++ b/blivet/tasks/fslabeling.py @@ -74,15 +74,6 @@ def label_format_ok(cls, label): return len(label) < 17 -class ReiserFSLabeling(FSLabeling): - - default_label = "" - - @classmethod - def label_format_ok(cls, label): - return len(label) < 17 - - class XFSLabeling(FSLabeling): default_label = "" diff --git a/blivet/tasks/fsmkfs.py b/blivet/tasks/fsmkfs.py index 408b0ef7a..832be49d4 100644 --- a/blivet/tasks/fsmkfs.py +++ b/blivet/tasks/fsmkfs.py @@ -316,19 +316,6 @@ def args(self): return ["-F", "-f"] -class ReiserFSMkfs(FSMkfs): - ext = availability.MKREISERFS_APP - label_option = "-l" - nodiscard_option = None - - def get_uuid_args(self, uuid): - return ["-u", uuid] - - @property - def args(self): - return ["-f", "-f"] - - class XFSMkfs(FSMkfs): ext = availability.MKFS_XFS_APP label_option = "-L" diff --git a/blivet/tasks/fssize.py b/blivet/tasks/fssize.py index 31b8d6174..6b3b86723 100644 --- a/blivet/tasks/fssize.py +++ b/blivet/tasks/fssize.py @@ -115,10 +115,6 @@ class NTFSSize(FSSize): tags = _Tags(size="Cluster Size:", count="Volume Size in Clusters:") -class ReiserFSSize(FSSize): - tags = _Tags(size="Blocksize:", count="Count of blocks on the device:") - - class XFSSize(FSSize): tags = _Tags(size="blocksize =", count="dblocks =") diff --git a/blivet/tasks/fsuuid.py b/blivet/tasks/fsuuid.py index 79dd07fc1..3c7c932a5 100644 --- a/blivet/tasks/fsuuid.py +++ b/blivet/tasks/fsuuid.py @@ -60,12 +60,6 @@ def uuid_format_ok(cls, uuid): return cls._check_rfc4122_uuid(uuid) -class ReiserFSUUID(FSUUID): - @classmethod - def uuid_format_ok(cls, uuid): - return cls._check_rfc4122_uuid(uuid) - - class XFSUUID(FSUUID): @classmethod def uuid_format_ok(cls, uuid): diff --git a/blivet/tasks/fswritelabel.py b/blivet/tasks/fswritelabel.py index 1f032c435..6fee83f36 100644 --- a/blivet/tasks/fswritelabel.py +++ b/blivet/tasks/fswritelabel.py @@ -99,14 +99,6 @@ def args(self): return [self.fs.device, self.fs.label] -class ReiserFSWriteLabel(FSWriteLabel): - ext = availability.REISERFSTUNE_APP - - @property - def args(self): - return ["-l", self.fs.label, self.fs.device] - - class XFSWriteLabel(FSWriteLabel): ext = availability.XFSADMIN_APP diff --git a/blivet/tasks/fswriteuuid.py b/blivet/tasks/fswriteuuid.py index 406bf7e45..c040ed76c 100644 --- a/blivet/tasks/fswriteuuid.py +++ b/blivet/tasks/fswriteuuid.py @@ -65,14 +65,6 @@ def args(self): return ["--new-serial=" + self.fs.uuid, self.fs.device] -class ReiserFSWriteUUID(FSWriteUUID): - ext = availability.REISERFSTUNE_APP - - @property - def args(self): - return ["-u", self.fs.uuid, self.fs.device] - - class XFSWriteUUID(FSWriteUUID): ext = availability.XFSADMIN_APP diff --git a/doc/api/formats.rst b/doc/api/formats.rst index 5fec17b4a..08b1a39ef 100644 --- a/doc/api/formats.rst +++ b/doc/api/formats.rst @@ -84,7 +84,6 @@ formats * :class:`~blivet.formats.fs.NoDevFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.NTFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.ProcFS` (see :ref:`inherited public API `) - * :class:`~blivet.formats.fs.ReiserFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.SELinuxFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.SysFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.TmpFS` (see :ref:`inherited public API `) diff --git a/tests/storage_tests/formats_test/fs_test.py b/tests/storage_tests/formats_test/fs_test.py index 66bd6c1a2..ce44a218a 100644 --- a/tests/storage_tests/formats_test/fs_test.py +++ b/tests/storage_tests/formats_test/fs_test.py @@ -89,10 +89,6 @@ class JFSTestCase(fstesting.FSAsRoot): _fs_class = fs.JFS -class ReiserFSTestCase(fstesting.FSAsRoot): - _fs_class = fs.ReiserFS - - class XFSTestCase(fstesting.FSAsRoot): _fs_class = fs.XFS _DEVICE_SIZE = Size("500 MiB") diff --git a/tests/storage_tests/formats_test/labeling_test.py b/tests/storage_tests/formats_test/labeling_test.py index 0702260ab..22a4e569c 100644 --- a/tests/storage_tests/formats_test/labeling_test.py +++ b/tests/storage_tests/formats_test/labeling_test.py @@ -28,10 +28,6 @@ def test_labels(self): self.assertFalse(fs.JFS().label_format_ok("root___filesystem")) self.assertTrue(fs.JFS().label_format_ok("root__filesystem")) - # ReiserFS has a maximum length of 16 - self.assertFalse(fs.ReiserFS().label_format_ok("root___filesystem")) - self.assertTrue(fs.ReiserFS().label_format_ok("root__filesystem")) - # XFS has a maximum length 12 and does not allow spaces self.assertFalse(fs.XFS().label_format_ok("root_filesyst")) self.assertFalse(fs.XFS().label_format_ok("root file")) @@ -80,11 +76,6 @@ class JFSTestCase(fslabeling.LabelingWithRelabeling): _invalid_label = "root___filesystem" -class ReiserFSTestCase(fslabeling.LabelingWithRelabeling): - _fs_class = fs.ReiserFS - _invalid_label = "root___filesystem" - - class HFSTestCase(fslabeling.LabelingAsRoot): _fs_class = fs.HFS _invalid_label = "n" * 28 diff --git a/tests/storage_tests/formats_test/uuid_test.py b/tests/storage_tests/formats_test/uuid_test.py index af35c0ee6..b183c56f8 100644 --- a/tests/storage_tests/formats_test/uuid_test.py +++ b/tests/storage_tests/formats_test/uuid_test.py @@ -15,7 +15,7 @@ def test_uuids(self): """Initialize some filesystems with valid and invalid UUIDs.""" # File systems that accept real UUIDs (RFC 4122) - for fscls in [fs.Ext2FS, fs.JFS, fs.ReiserFS, fs.XFS, fs.HFSPlus]: + for fscls in [fs.Ext2FS, fs.JFS, fs.XFS, fs.HFSPlus]: uuid = "0invalid-uuid-with-righ-tlength00000" self.assertFalse(fscls().uuid_format_ok(uuid)) uuid = "01234567-12341234123401234567891a" @@ -42,7 +42,7 @@ def test_uuids(self): def test_generate_new_uuid(self): """Test that newly generated UUIDs are considered valid""" - for fscls in (fs.Ext2FS, fs.JFS, fs.ReiserFS, fs.XFS, fs.HFSPlus, + for fscls in (fs.Ext2FS, fs.JFS, fs.XFS, fs.HFSPlus, fs.FATFS, fs.NTFS): an_fs = fscls() for _i in range(100): @@ -87,18 +87,6 @@ class JFSTestCase(fsuuid.SetUUIDAfterMkFs): _valid_uuid = "ac54f987-b371-45d9-8846-7d6204081e5c" -class ReiserFSTestCase(fsuuid.SetUUIDWithMkFs): - _fs_class = fs.ReiserFS - _invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456" - _valid_uuid = "1761023e-bab8-4919-a2cb-f26c89fe1cfe" - - -class ReiserFSAfterTestCase(fsuuid.SetUUIDAfterMkFs): - _fs_class = fs.ReiserFS - _invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456" - _valid_uuid = "1761023e-bab8-4919-a2cb-f26c89fe1cfe" - - class HFSPlusTestCase(fsuuid.SetUUIDAfterMkFs): _fs_class = fs.HFSPlus _invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456" From 9353fedf807aae0a3aa33ec1f9f5a4eeec830c15 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 14:16:30 +0200 Subject: [PATCH 03/24] Remove JFS support JFS is still supported but isn't really used or actively developed anymore. It also isn't packaged for CentOS/RHEL and not supported by libblockdev. --- blivet/flags.py | 2 -- blivet/formats/fs.py | 19 ------------------- blivet/tasks/availability.py | 2 -- blivet/tasks/fsinfo.py | 5 ----- blivet/tasks/fslabeling.py | 9 --------- blivet/tasks/fsmkfs.py | 11 ----------- blivet/tasks/fssize.py | 4 ---- blivet/tasks/fsuuid.py | 6 ------ blivet/tasks/fswritelabel.py | 8 -------- blivet/tasks/fswriteuuid.py | 8 -------- doc/api/formats.rst | 1 - tests/storage_tests/formats_test/fs_test.py | 4 ---- .../formats_test/labeling_test.py | 9 --------- tests/storage_tests/formats_test/uuid_test.py | 10 ++-------- 14 files changed, 2 insertions(+), 96 deletions(-) diff --git a/blivet/flags.py b/blivet/flags.py index be4eaa899..e1f2279b2 100644 --- a/blivet/flags.py +++ b/blivet/flags.py @@ -50,7 +50,6 @@ def __init__(self): self.noiswmd = False self.gfs2 = True - self.jfs = True # for this flag to take effect, # blockdev.mpath.set_friendly_names(flags.multipath_friendly_names) must @@ -111,7 +110,6 @@ def update_from_boot_cmdline(self): self.multipath = "nompath" not in self.boot_cmdline self.noiswmd = "noiswmd" in self.boot_cmdline self.gfs2 = "gfs2" in self.boot_cmdline - self.jfs = "jfs" in self.boot_cmdline flags = Flags() diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index b2cbe8ca6..cca0b907a 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1048,26 +1048,7 @@ class JFS(FS): """ JFS filesystem """ _type = "jfs" - _modules = ["jfs"] - _labelfs = fslabeling.JFSLabeling() - _uuidfs = fsuuid.JFSUUID() - _max_size = Size("8 TiB") - _formattable = True _linux_native = True - _dump = True - _check = True - _info_class = fsinfo.JFSInfo - _mkfs_class = fsmkfs.JFSMkfs - _size_info_class = fssize.JFSSize - _writelabel_class = fswritelabel.JFSWriteLabel - _writeuuid_class = fswriteuuid.JFSWriteUUID - _metadata_size_factor = 0.99 # jfs metadata may take 1% of space - parted_system = fileSystemType["jfs"] - - @property - def supported(self): - """ Is this filesystem a supported type? """ - return self.utils_available if flags.jfs else self._supported register_device_format(JFS) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index ffbc6b087..d5a6e87dc 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -508,7 +508,6 @@ def available_resource(name): E2LABEL_APP = application_by_version("e2label", E2FSPROGS_VERSION) FSCK_HFSPLUS_APP = application("fsck.hfsplus") HFORMAT_APP = application("hformat") -JFSTUNE_APP = application("jfs_tune") KPARTX_APP = application("kpartx") LVMDEVICES = application("lvmdevices") MKDOSFS_APP = application("mkdosfs") @@ -517,7 +516,6 @@ def available_resource(name): MKFS_BTRFS_APP = application("mkfs.btrfs") MKFS_GFS2_APP = application("mkfs.gfs2") MKFS_HFSPLUS_APP = application("mkfs.hfsplus") -MKFS_JFS_APP = application("mkfs.jfs") MKFS_XFS_APP = application("mkfs.xfs") MKNTFS_APP = application("mkntfs") MLABEL_APP = application("mlabel") diff --git a/blivet/tasks/fsinfo.py b/blivet/tasks/fsinfo.py index af35af5ab..e91c2cb60 100644 --- a/blivet/tasks/fsinfo.py +++ b/blivet/tasks/fsinfo.py @@ -78,11 +78,6 @@ class Ext2FSInfo(FSInfo): options = ["-h"] -class JFSInfo(FSInfo): - ext = availability.JFSTUNE_APP - options = ["-l"] - - class NTFSInfo(FSInfo): ext = availability.NTFSINFO_APP options = ["-m"] diff --git a/blivet/tasks/fslabeling.py b/blivet/tasks/fslabeling.py index 1a1c4b841..a76db1d37 100644 --- a/blivet/tasks/fslabeling.py +++ b/blivet/tasks/fslabeling.py @@ -65,15 +65,6 @@ def label_format_ok(cls, label): return len(label) < 12 -class JFSLabeling(FSLabeling): - - default_label = "" - - @classmethod - def label_format_ok(cls, label): - return len(label) < 17 - - class XFSLabeling(FSLabeling): default_label = "" diff --git a/blivet/tasks/fsmkfs.py b/blivet/tasks/fsmkfs.py index 832be49d4..f4d0b3834 100644 --- a/blivet/tasks/fsmkfs.py +++ b/blivet/tasks/fsmkfs.py @@ -293,17 +293,6 @@ def args(self): return [] -class JFSMkfs(FSMkfs): - ext = availability.MKFS_JFS_APP - label_option = "-L" - nodiscard_option = None - get_uuid_args = None - - @property - def args(self): - return ["-q"] - - class NTFSMkfs(FSMkfs): ext = availability.MKNTFS_APP label_option = "-L" diff --git a/blivet/tasks/fssize.py b/blivet/tasks/fssize.py index 6b3b86723..138c86229 100644 --- a/blivet/tasks/fssize.py +++ b/blivet/tasks/fssize.py @@ -107,10 +107,6 @@ class Ext2FSSize(FSSize): tags = _Tags(size="Block size:", count="Block count:") -class JFSSize(FSSize): - tags = _Tags(size="Physical block size:", count="Aggregate size:") - - class NTFSSize(FSSize): tags = _Tags(size="Cluster Size:", count="Volume Size in Clusters:") diff --git a/blivet/tasks/fsuuid.py b/blivet/tasks/fsuuid.py index 3c7c932a5..ce48b999f 100644 --- a/blivet/tasks/fsuuid.py +++ b/blivet/tasks/fsuuid.py @@ -54,12 +54,6 @@ def uuid_format_ok(cls, uuid): for char in (uuid[:4] + uuid[5:])) -class JFSUUID(FSUUID): - @classmethod - def uuid_format_ok(cls, uuid): - return cls._check_rfc4122_uuid(uuid) - - class XFSUUID(FSUUID): @classmethod def uuid_format_ok(cls, uuid): diff --git a/blivet/tasks/fswritelabel.py b/blivet/tasks/fswritelabel.py index 6fee83f36..7f4203f60 100644 --- a/blivet/tasks/fswritelabel.py +++ b/blivet/tasks/fswritelabel.py @@ -83,14 +83,6 @@ def args(self): return [self.fs.device, self.fs.label] -class JFSWriteLabel(FSWriteLabel): - ext = availability.JFSTUNE_APP - - @property - def args(self): - return ["-L", self.fs.label, self.fs.device] - - class NTFSWriteLabel(FSWriteLabel): ext = availability.NTFSLABEL_APP diff --git a/blivet/tasks/fswriteuuid.py b/blivet/tasks/fswriteuuid.py index c040ed76c..dddb03b03 100644 --- a/blivet/tasks/fswriteuuid.py +++ b/blivet/tasks/fswriteuuid.py @@ -49,14 +49,6 @@ def args(self): return ["-U", self.fs.uuid, self.fs.device] -class JFSWriteUUID(FSWriteUUID): - ext = availability.JFSTUNE_APP - - @property - def args(self): - return ["-U", self.fs.uuid, self.fs.device] - - class NTFSWriteUUID(FSWriteUUID): ext = availability.NTFSLABEL_APP diff --git a/doc/api/formats.rst b/doc/api/formats.rst index 08b1a39ef..a77dc1571 100644 --- a/doc/api/formats.rst +++ b/doc/api/formats.rst @@ -77,7 +77,6 @@ formats * :class:`~blivet.formats.fs.HFSPlus` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.Iso9660FS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.UDFFS` (see :ref:`inherited public API `) - * :class:`~blivet.formats.fs.JFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.MacEFIFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.NFS` (see :ref:`inherited public API `) * :class:`~blivet.formats.fs.NFSv4` (see :ref:`inherited public API `) diff --git a/tests/storage_tests/formats_test/fs_test.py b/tests/storage_tests/formats_test/fs_test.py index ce44a218a..3ff5161e2 100644 --- a/tests/storage_tests/formats_test/fs_test.py +++ b/tests/storage_tests/formats_test/fs_test.py @@ -85,10 +85,6 @@ class GFS2TestCase(fstesting.FSAsRoot): _fs_class = fs.GFS2 -class JFSTestCase(fstesting.FSAsRoot): - _fs_class = fs.JFS - - class XFSTestCase(fstesting.FSAsRoot): _fs_class = fs.XFS _DEVICE_SIZE = Size("500 MiB") diff --git a/tests/storage_tests/formats_test/labeling_test.py b/tests/storage_tests/formats_test/labeling_test.py index 22a4e569c..9f48e3078 100644 --- a/tests/storage_tests/formats_test/labeling_test.py +++ b/tests/storage_tests/formats_test/labeling_test.py @@ -24,10 +24,6 @@ def test_labels(self): self.assertFalse(fs.FATFS().label_format_ok("rtfilesystem")) self.assertTrue(fs.FATFS().label_format_ok("rfilesystem")) - # JFS has a maximum length of 16 - self.assertFalse(fs.JFS().label_format_ok("root___filesystem")) - self.assertTrue(fs.JFS().label_format_ok("root__filesystem")) - # XFS has a maximum length 12 and does not allow spaces self.assertFalse(fs.XFS().label_format_ok("root_filesyst")) self.assertFalse(fs.XFS().label_format_ok("root file")) @@ -71,11 +67,6 @@ class Ext2FSTestCase(fslabeling.CompleteLabelingAsRoot): _invalid_label = "root___filesystem" -class JFSTestCase(fslabeling.LabelingWithRelabeling): - _fs_class = fs.JFS - _invalid_label = "root___filesystem" - - class HFSTestCase(fslabeling.LabelingAsRoot): _fs_class = fs.HFS _invalid_label = "n" * 28 diff --git a/tests/storage_tests/formats_test/uuid_test.py b/tests/storage_tests/formats_test/uuid_test.py index b183c56f8..31f1f42c3 100644 --- a/tests/storage_tests/formats_test/uuid_test.py +++ b/tests/storage_tests/formats_test/uuid_test.py @@ -15,7 +15,7 @@ def test_uuids(self): """Initialize some filesystems with valid and invalid UUIDs.""" # File systems that accept real UUIDs (RFC 4122) - for fscls in [fs.Ext2FS, fs.JFS, fs.XFS, fs.HFSPlus]: + for fscls in [fs.Ext2FS, fs.XFS, fs.HFSPlus]: uuid = "0invalid-uuid-with-righ-tlength00000" self.assertFalse(fscls().uuid_format_ok(uuid)) uuid = "01234567-12341234123401234567891a" @@ -42,7 +42,7 @@ def test_uuids(self): def test_generate_new_uuid(self): """Test that newly generated UUIDs are considered valid""" - for fscls in (fs.Ext2FS, fs.JFS, fs.XFS, fs.HFSPlus, + for fscls in (fs.Ext2FS, fs.XFS, fs.HFSPlus, fs.FATFS, fs.NTFS): an_fs = fscls() for _i in range(100): @@ -81,12 +81,6 @@ class Ext2FSAfterTestCase(fsuuid.SetUUIDAfterMkFs): _valid_uuid = "bad19a10-075a-4e99-8922-e4638722a567" -class JFSTestCase(fsuuid.SetUUIDAfterMkFs): - _fs_class = fs.JFS - _invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456" - _valid_uuid = "ac54f987-b371-45d9-8846-7d6204081e5c" - - class HFSPlusTestCase(fsuuid.SetUUIDAfterMkFs): _fs_class = fs.HFSPlus _invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456" From 7a2c5c22e27228e32d430546b652e8f5e62891d5 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 14:49:41 +0200 Subject: [PATCH 04/24] availability: Do not check e2fsprogs version The minimum required version 1.41 was released 8 years ago, we can now safely assume it is available everywhere. --- blivet/tasks/availability.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index d5a6e87dc..c5730b10b 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -482,16 +482,6 @@ def available_resource(name): BLOCKDEV_MPATH_PLUGIN = blockdev_plugin("libblockdev mpath plugin", BLOCKDEV_MPATH_TECH) BLOCKDEV_SWAP_PLUGIN = blockdev_plugin("libblockdev swap plugin", BLOCKDEV_SWAP_TECH) -# applications with versions -# we need e2fsprogs newer than 1.41 and we are checking the version by running -# the "e2fsck" tool and parsing its ouput for version number -E2FSPROGS_INFO = AppVersionInfo(app_name="e2fsck", - required_version="1.41.0", - version_opt="-V", - version_regex=r"e2fsck ([0-9+\.]+)[\-rc0-9+]* .*") -E2FSPROGS_VERSION = VersionMethod(E2FSPROGS_INFO) - - # new version of dosftools changed behaviour of many tools DOSFSTOOLS_INFO = AppVersionInfo(app_name="mkdosfs", required_version="4.2", @@ -503,16 +493,16 @@ def available_resource(name): DF_APP = application("df") DOSFSCK_APP = application("dosfsck") DOSFSLABEL_APP = application("dosfslabel") -DUMPE2FS_APP = application_by_version("dumpe2fs", E2FSPROGS_VERSION) -E2FSCK_APP = application_by_version("e2fsck", E2FSPROGS_VERSION) -E2LABEL_APP = application_by_version("e2label", E2FSPROGS_VERSION) +DUMPE2FS_APP = application("dumpe2fs") +E2FSCK_APP = application("e2fsck") +E2LABEL_APP = application("e2label") FSCK_HFSPLUS_APP = application("fsck.hfsplus") HFORMAT_APP = application("hformat") KPARTX_APP = application("kpartx") LVMDEVICES = application("lvmdevices") MKDOSFS_APP = application("mkdosfs") MKDOSFS_NEW_APP = application_by_version("mkdosfs", DOSFSTOOLS_VERSION) -MKE2FS_APP = application_by_version("mke2fs", E2FSPROGS_VERSION) +MKE2FS_APP = application("mke2fs") MKFS_BTRFS_APP = application("mkfs.btrfs") MKFS_GFS2_APP = application("mkfs.gfs2") MKFS_HFSPLUS_APP = application("mkfs.hfsplus") @@ -523,8 +513,8 @@ def available_resource(name): NTFSINFO_APP = application("ntfsinfo") NTFSLABEL_APP = application("ntfslabel") NTFSRESIZE_APP = application("ntfsresize") -RESIZE2FS_APP = application_by_version("resize2fs", E2FSPROGS_VERSION) -TUNE2FS_APP = application_by_version("tune2fs", E2FSPROGS_VERSION) +RESIZE2FS_APP = application("resize2fs") +TUNE2FS_APP = application("tune2fs") XFSADMIN_APP = application("xfs_admin") XFSDB_APP = application("xfs_db") XFSFREEZE_APP = application("xfs_freeze") From 9cb3b73f060be5bfb8a0ae8bbc737b0b711609f5 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 14:54:20 +0200 Subject: [PATCH 05/24] availability: Simplify checks for LVM VDO and shared LVM support We now require libblockdev >= 3.0 which will always have these technologies. --- blivet/tasks/availability.py | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index c5730b10b..cad6b0c11 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -419,23 +419,17 @@ def available_resource(name): blockdev.LVMTechMode.MODIFY)}) BLOCKDEV_LVM_TECH = BlockDevMethod(BLOCKDEV_LVM) -if hasattr(blockdev.LVMTech, "VDO"): - BLOCKDEV_LVM_VDO = BlockDevTechInfo(plugin_name="lvm", - check_fn=blockdev.lvm_is_tech_avail, - technologies={blockdev.LVMTech.VDO: (blockdev.LVMTechMode.CREATE | - blockdev.LVMTechMode.REMOVE | - blockdev.LVMTechMode.QUERY)}) - BLOCKDEV_LVM_TECH_VDO = BlockDevMethod(BLOCKDEV_LVM_VDO) -else: - BLOCKDEV_LVM_TECH_VDO = _UnavailableMethod(error_msg="Installed version of libblockdev doesn't support LVM VDO technology") - -if hasattr(blockdev.LVMTech, "SHARED"): - BLOCKDEV_LVM_SHARED = BlockDevTechInfo(plugin_name="lvm", - check_fn=blockdev.lvm_is_tech_avail, - technologies={blockdev.LVMTech.SHARED: blockdev.LVMTechMode.MODIFY}) # pylint: disable=no-member - BLOCKDEV_LVM_TECH_SHARED = BlockDevMethod(BLOCKDEV_LVM_SHARED) -else: - BLOCKDEV_LVM_TECH_SHARED = _UnavailableMethod(error_msg="Installed version of libblockdev doesn't support shared LVM technology") +BLOCKDEV_LVM_VDO = BlockDevTechInfo(plugin_name="lvm", + check_fn=blockdev.lvm_is_tech_avail, + technologies={blockdev.LVMTech.VDO: (blockdev.LVMTechMode.CREATE | + blockdev.LVMTechMode.REMOVE | + blockdev.LVMTechMode.QUERY)}) +BLOCKDEV_LVM_TECH_VDO = BlockDevMethod(BLOCKDEV_LVM_VDO) + +BLOCKDEV_LVM_SHARED = BlockDevTechInfo(plugin_name="lvm", + check_fn=blockdev.lvm_is_tech_avail, + technologies={blockdev.LVMTech.SHARED: blockdev.LVMTechMode.MODIFY}) +BLOCKDEV_LVM_TECH_SHARED = BlockDevMethod(BLOCKDEV_LVM_SHARED) # libblockdev mdraid plugin required technologies and modes BLOCKDEV_MD_ALL_MODES = (blockdev.MDTechMode.CREATE | From a188402579a15e2d68020975db066a63dd081840 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 15:02:43 +0200 Subject: [PATCH 06/24] availability: Remove unused "mlabel" application --- blivet/tasks/availability.py | 1 - 1 file changed, 1 deletion(-) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index cad6b0c11..a20f6b3a0 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -502,7 +502,6 @@ def available_resource(name): MKFS_HFSPLUS_APP = application("mkfs.hfsplus") MKFS_XFS_APP = application("mkfs.xfs") MKNTFS_APP = application("mkntfs") -MLABEL_APP = application("mlabel") MULTIPATH_APP = application("multipath") NTFSINFO_APP = application("ntfsinfo") NTFSLABEL_APP = application("ntfslabel") From 8333ede2af109f5069df20e0c4c43eef6df48be8 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 15:32:44 +0200 Subject: [PATCH 07/24] Add libblockdev filesystem plugin to the list of required plugins --- README.md | 2 +- blivet/__init__.py | 4 ++-- blivet/tasks/availability.py | 15 +++++++++++++++ python-blivet.spec | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7986a84fb..b0655f625 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ To install these dependencies use following commands: # dnf install python3-blockdev libblockdev-plugins-all python3-bytesize libbytesize python3-pyparted parted libselinux-python3 * On Debian and Ubuntu based distributions: - # apt-get install python3-blockdev python3-bytesize python3-parted python3-selinux gir1.2-blockdev-3.0 libblockdev-lvm3 libblockdev-btrfs3 libblockdev-swap3 libblockdev-loop3 libblockdev-crypto3 libblockdev-mpath3 libblockdev-dm3 libblockdev-mdraid3 libblockdev-nvdimm3 + # apt-get install python3-blockdev python3-bytesize python3-parted python3-selinux gir1.2-blockdev-3.0 libblockdev-lvm3 libblockdev-btrfs3 libblockdev-swap3 libblockdev-loop3 libblockdev-crypto3 libblockdev-mpath3 libblockdev-dm3 libblockdev-mdraid3 libblockdev-nvdimm3 libblockdev-fs3 ### Development diff --git a/blivet/__init__.py b/blivet/__init__.py index 0253cc61c..7582bb73b 100644 --- a/blivet/__init__.py +++ b/blivet/__init__.py @@ -63,9 +63,9 @@ def log_bd_message(level, msg): from gi.repository import GLib from gi.repository import BlockDev as blockdev if arch.is_s390(): - _REQUESTED_PLUGIN_NAMES = set(("lvm", "btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "s390", "nvdimm", "nvme")) + _REQUESTED_PLUGIN_NAMES = set(("lvm", "btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "s390", "nvdimm", "nvme", "fs")) else: - _REQUESTED_PLUGIN_NAMES = set(("lvm", "btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm", "nvme")) + _REQUESTED_PLUGIN_NAMES = set(("lvm", "btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm", "nvme", "fs")) _requested_plugins = blockdev.plugin_specs_from_names(_REQUESTED_PLUGIN_NAMES) try: diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index a20f6b3a0..29c9bf79d 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -459,6 +459,20 @@ def available_resource(name): technologies={blockdev.SwapTech.SWAP: BLOCKDEV_SWAP_ALL_MODES}) BLOCKDEV_SWAP_TECH = BlockDevMethod(BLOCKDEV_SWAP) +# libblockdev fs plugin required technologies +# no modes, we will check for specific functionality separately +BLOCKDEV_FS = BlockDevTechInfo(plugin_name="fs", + check_fn=blockdev.fs_is_tech_avail, + technologies={blockdev.FSTech.GENERIC: 0, + blockdev.FSTech.MOUNT: 0, + blockdev.FSTech.EXT2: 0, + blockdev.FSTech.EXT3: 0, + blockdev.FSTech.EXT4: 0, + blockdev.FSTech.XFS: 0, + blockdev.FSTech.VFAT: 0, + blockdev.FSTech.NTFS: 0}) +BLOCKDEV_FS_TECH = BlockDevMethod(BLOCKDEV_FS) + # libblockdev plugins # we can't just check if the plugin is loaded, we also need to make sure # that all technologies required by us our supported (some may be missing @@ -475,6 +489,7 @@ def available_resource(name): BLOCKDEV_MDRAID_PLUGIN = blockdev_plugin("libblockdev mdraid plugin", BLOCKDEV_MD_TECH) BLOCKDEV_MPATH_PLUGIN = blockdev_plugin("libblockdev mpath plugin", BLOCKDEV_MPATH_TECH) BLOCKDEV_SWAP_PLUGIN = blockdev_plugin("libblockdev swap plugin", BLOCKDEV_SWAP_TECH) +BLOCKDEV_FS_PLUGIN = blockdev_plugin("libblockdev fs plugin", BLOCKDEV_FS_TECH) # new version of dosftools changed behaviour of many tools DOSFSTOOLS_INFO = AppVersionInfo(app_name="mkdosfs", diff --git a/python-blivet.spec b/python-blivet.spec index d94874fd0..a22c746f8 100644 --- a/python-blivet.spec +++ b/python-blivet.spec @@ -60,6 +60,7 @@ Requires: python3-blockdev >= %{libblockdevver} Recommends: libblockdev-btrfs >= %{libblockdevver} Recommends: libblockdev-crypto >= %{libblockdevver} Recommends: libblockdev-dm >= %{libblockdevver} +Recommends: libblockdev-fs >= %{libblockdevver} Recommends: libblockdev-loop >= %{libblockdevver} Recommends: libblockdev-lvm >= %{libblockdevver} Recommends: libblockdev-mdraid >= %{libblockdevver} From 7dcdbc911ee24b3142bbadfd1783f14727b4583d Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 24 Oct 2023 15:34:17 +0200 Subject: [PATCH 08/24] Use libblockdev for the filesystem sync operation libblockdev uses the FIFREEZE and FITHAW ioctls directly so we no longer need to require the command line tool. --- blivet/tasks/availability.py | 1 - blivet/tasks/fssync.py | 26 +++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 29c9bf79d..7c366353e 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -525,7 +525,6 @@ def available_resource(name): TUNE2FS_APP = application("tune2fs") XFSADMIN_APP = application("xfs_admin") XFSDB_APP = application("xfs_db") -XFSFREEZE_APP = application("xfs_freeze") XFSRESIZE_APP = application("xfs_growfs") XFSREPAIR_APP = application("xfs_repair") diff --git a/blivet/tasks/fssync.py b/blivet/tasks/fssync.py index e6690c281..85cac3b03 100644 --- a/blivet/tasks/fssync.py +++ b/blivet/tasks/fssync.py @@ -24,12 +24,15 @@ from six import add_metaclass from ..errors import FSError -from .. import util from . import availability from . import fstask from . import task +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev + @add_metaclass(abc.ABCMeta) class FSSync(task.BasicApplication, fstask.FSTask): @@ -47,7 +50,7 @@ class XFSSync(FSSync): """ Sync application for XFS. """ - ext = availability.XFSFREEZE_APP + ext = availability.BLOCKDEV_FS_PLUGIN def _get_mountpoint(self, root=None): mountpoint = self.fs.system_mountpoint @@ -59,12 +62,6 @@ def _get_mountpoint(self, root=None): return mountpoint - def _freeze_command(self, root=None): - return [str(self.ext), "-f", self._get_mountpoint(root=root)] - - def _unfreeze_command(self, root=None): - return [str(self.ext), "-u", self._get_mountpoint(root=root)] - def do_task(self, root="/"): # pylint: disable=arguments-differ error_msgs = self.availability_errors @@ -72,17 +69,16 @@ def do_task(self, root="/"): raise FSError("\n".join(error_msgs)) error_msg = None + mountpoint = self._get_mountpoint(root=root) try: - rc = util.run_program(self._freeze_command(root=root), root=root) - except OSError as e: + BlockDev.fs.freeze(mountpoint) + except BlockDev.FSError as e: error_msg = "failed to sync filesytem: %s" % e - error_msg = error_msg or rc try: - rc = util.run_program(self._unfreeze_command(root=root), root=root) - except OSError as e: - error_msg = error_msg or "failed to sync filesystem: %s" % e - error_msg = error_msg or rc + BlockDev.fs.unfreeze(mountpoint) + except BlockDev.FSError as e: + error_msg = "failed to sync filesytem: %s" % e if error_msg: raise FSError(error_msg) From 7bf0c4dcd27db86b3bdaf2253b4c45b31f676163 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Wed, 25 Oct 2023 08:51:05 +0200 Subject: [PATCH 09/24] swap: Simplify creating swap with UUID BlockDev.swap.mkswap supports the UUID parameter directly since 3.0. --- blivet/formats/swap.py | 19 ++++++------------- .../unit_tests/formats_tests/methods_test.py | 4 +++- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/blivet/formats/swap.py b/blivet/formats/swap.py index 03aa3cc68..47dd687cf 100644 --- a/blivet/formats/swap.py +++ b/blivet/formats/swap.py @@ -228,19 +228,12 @@ def _teardown(self, **kwargs): def _create(self, **kwargs): log_method_call(self, device=self.device, type=self.type, status=self.status) - if self.uuid is None: - try: - blockdev.swap.mkswap(self.device, label=self.label) - except blockdev.SwapError as err: - raise SwapSpaceError(str(err)) - else: - if not self.uuid_format_ok(self.uuid): - raise FSWriteUUIDError("bad UUID format for swap filesystem") - try: - blockdev.swap.mkswap(self.device, label=self.label, - extra={"-U": self.uuid}) - except blockdev.SwapError as err: - raise SwapSpaceError(str(err)) + if self.uuid and not self.uuid_format_ok(self.uuid): + raise FSWriteUUIDError("bad UUID format for swap filesystem") + try: + blockdev.swap.mkswap(self.device, label=self.label, uuid=self.uuid) + except blockdev.SwapError as err: + raise SwapSpaceError(str(err)) register_device_format(SwapSpace) diff --git a/tests/unit_tests/formats_tests/methods_test.py b/tests/unit_tests/formats_tests/methods_test.py index 4f33c0952..17253e699 100644 --- a/tests/unit_tests/formats_tests/methods_test.py +++ b/tests/unit_tests/formats_tests/methods_test.py @@ -428,7 +428,9 @@ def set_patches(self): def _test_create_backend(self): self.format.exists = False self.format.create() - self.patches["blockdev"].swap.mkswap.assert_called_with(self.format.device, label=self.format.label) # pylint: disable=no-member + self.patches["blockdev"].swap.mkswap.assert_called_with(self.format.device, + label=self.format.label, # pylint: disable=no-member + uuid=self.format.uuid) def _test_setup_backend(self): self.format.setup() From affcc5169e6ed564cb477747b2ba73a3ee0d1584 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Wed, 25 Oct 2023 09:41:49 +0200 Subject: [PATCH 10/24] Use libblockdev for setting and checking filesystem label and UUID --- blivet/tasks/availability.py | 60 ++++++++++++++--- blivet/tasks/fslabeling.py | 40 +++++------- blivet/tasks/fsuuid.py | 26 +++++--- blivet/tasks/fswritelabel.py | 64 +++++-------------- blivet/tasks/fswriteuuid.py | 52 +++++---------- .../storage_tests/formats_test/fslabeling.py | 14 ++-- tests/storage_tests/formats_test/fstesting.py | 5 +- .../formats_test/labeling_test.py | 7 +- tests/storage_tests/formats_test/uuid_test.py | 10 +-- 9 files changed, 143 insertions(+), 135 deletions(-) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 7c366353e..39db81a74 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -251,6 +251,43 @@ def availability_errors(self, resource): return [] +class BlockDevFSMethod(Method): + + """ Methods for when application is actually a libblockdev FS plugin functionality. """ + + def __init__(self, check_fn, fstype): + """ Initializer. + + :param check_fn: function used to check for support availability + :param fstype: filesystem type to check for the support availability + """ + self.check_fn = check_fn + self.fstype = fstype + self._availability_errors = None + + def availability_errors(self, resource): + """ Returns [] if the plugin is loaded and functionality available. + + :param resource: a libblockdev plugin + :type resource: :class:`ExternalResource` + + :returns: [] if the name of the plugin is loaded + :rtype: list of str + """ + if "fs" not in blockdev.get_available_plugin_names(): + return ["libblockdev fs plugin not loaded"] + else: + try: + avail, utility = self.check_fn(self.fstype) + except blockdev.FSError as e: + return [str(e)] + if not avail: + return ["libblockdev fs plugin is loaded but some required runtime " + "dependencies are not available: %s" % utility] + else: + return [] + + class DBusMethod(Method): """ Methods for when application is actually a DBus service. """ @@ -334,6 +371,11 @@ def blockdev_plugin(name, blockdev_method): return ExternalResource(blockdev_method, name) +def blockdev_fs_plugin(blockdev_fs_method): + """ Construct an external resource that is a libblockdev FS plugin functionality. """ + return ExternalResource(blockdev_fs_method, "libblockdev FS plugin method") + + def dbus_service(name, dbus_method): """ Construct an external resource that is a DBus service. """ return ExternalResource(dbus_method, name) @@ -473,6 +515,16 @@ def available_resource(name): blockdev.FSTech.NTFS: 0}) BLOCKDEV_FS_TECH = BlockDevMethod(BLOCKDEV_FS) +# libblockdev fs plugin methods +BLOCKDEV_EXT_UUID = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_uuid, "ext2")) +BLOCKDEV_XFS_UUID = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_uuid, "xfs")) +BLOCKDEV_NTFS_UUID = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_uuid, "ntfs")) + +BLOCKDEV_EXT_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "ext2")) +BLOCKDEV_XFS_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "xfs")) +BLOCKDEV_VFAT_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "vfat")) +BLOCKDEV_NTFS_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "ntfs")) + # libblockdev plugins # we can't just check if the plugin is loaded, we also need to make sure # that all technologies required by us our supported (some may be missing @@ -491,13 +543,6 @@ def available_resource(name): BLOCKDEV_SWAP_PLUGIN = blockdev_plugin("libblockdev swap plugin", BLOCKDEV_SWAP_TECH) BLOCKDEV_FS_PLUGIN = blockdev_plugin("libblockdev fs plugin", BLOCKDEV_FS_TECH) -# new version of dosftools changed behaviour of many tools -DOSFSTOOLS_INFO = AppVersionInfo(app_name="mkdosfs", - required_version="4.2", - version_opt="--help", - version_regex=r"mkfs\.fat ([0-9+\.]+) .*") -DOSFSTOOLS_VERSION = VersionMethod(DOSFSTOOLS_INFO) - # applications DF_APP = application("df") DOSFSCK_APP = application("dosfsck") @@ -510,7 +555,6 @@ def available_resource(name): KPARTX_APP = application("kpartx") LVMDEVICES = application("lvmdevices") MKDOSFS_APP = application("mkdosfs") -MKDOSFS_NEW_APP = application_by_version("mkdosfs", DOSFSTOOLS_VERSION) MKE2FS_APP = application("mke2fs") MKFS_BTRFS_APP = application("mkfs.btrfs") MKFS_GFS2_APP = application("mkfs.gfs2") diff --git a/blivet/tasks/fslabeling.py b/blivet/tasks/fslabeling.py index a76db1d37..e1a75330a 100644 --- a/blivet/tasks/fslabeling.py +++ b/blivet/tasks/fslabeling.py @@ -23,7 +23,9 @@ from six import add_metaclass -from . import availability +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev @add_metaclass(abc.ABCMeta) @@ -32,9 +34,6 @@ class FSLabeling(object): """An abstract class that represents filesystem labeling actions. """ - default_label = abc.abstractproperty( - doc="Default label set on this filesystem at creation.") - @classmethod @abc.abstractmethod def label_format_ok(cls, label): @@ -46,38 +45,39 @@ def label_format_ok(cls, label): """ raise NotImplementedError + @classmethod + def _blockdev_check_label(cls, fstype, label): + try: + BlockDev.fs.check_label(fstype, label) + except BlockDev.FSError: + return False + else: + return True -class Ext2FSLabeling(FSLabeling): - default_label = "" +class Ext2FSLabeling(FSLabeling): @classmethod def label_format_ok(cls, label): - return len(label) < 17 + return cls._blockdev_check_label("ext2", label) class FATFSLabeling(FSLabeling): - default_label = "" if availability.MKDOSFS_NEW_APP.available else "NO NAME" - @classmethod def label_format_ok(cls, label): - return len(label) < 12 + return cls._blockdev_check_label("vfat", label) class XFSLabeling(FSLabeling): - default_label = "" - @classmethod def label_format_ok(cls, label): - return ' ' not in label and len(label) < 13 + return cls._blockdev_check_label("xfs", label) class HFSLabeling(FSLabeling): - default_label = "Untitled" - @classmethod def label_format_ok(cls, label): return ':' not in label and len(label) < 28 and len(label) > 0 @@ -85,8 +85,6 @@ def label_format_ok(cls, label): class HFSPlusLabeling(FSLabeling): - default_label = "Untitled" - @classmethod def label_format_ok(cls, label): return ':' not in label and 0 < len(label) < 129 @@ -94,17 +92,13 @@ def label_format_ok(cls, label): class NTFSLabeling(FSLabeling): - default_label = "" - @classmethod def label_format_ok(cls, label): - return len(label) < 129 + return cls._blockdev_check_label("ntfs", label) class F2FSLabeling(FSLabeling): - default_label = "" - @classmethod def label_format_ok(cls, label): - return len(label) < 513 + return cls._blockdev_check_label("f2fs", label) diff --git a/blivet/tasks/fsuuid.py b/blivet/tasks/fsuuid.py index ce48b999f..849d7d975 100644 --- a/blivet/tasks/fsuuid.py +++ b/blivet/tasks/fsuuid.py @@ -2,6 +2,10 @@ from six import add_metaclass +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev + @add_metaclass(abc.ABCMeta) class FSUUID(object): @@ -38,26 +42,32 @@ def _check_rfc4122_uuid(cls, uuid): if all(char in "0123456789abcdef" for char in chunk)] return chunklens == [8, 4, 4, 4, 12] + @classmethod + def _blockdev_check_uuid(cls, fstype, uuid): + try: + BlockDev.fs.check_uuid(fstype, uuid) + except BlockDev.FSError: + return False + else: + return True + class Ext2FSUUID(FSUUID): @classmethod def uuid_format_ok(cls, uuid): - return cls._check_rfc4122_uuid(uuid) + return cls._blockdev_check_uuid("ext2", uuid) class FATFSUUID(FSUUID): @classmethod def uuid_format_ok(cls, uuid): - if len(uuid) != 9 or uuid[4] != '-': - return False - return all(char in "0123456789ABCDEF" - for char in (uuid[:4] + uuid[5:])) + return cls._blockdev_check_uuid("vfat", uuid) class XFSUUID(FSUUID): @classmethod def uuid_format_ok(cls, uuid): - return cls._check_rfc4122_uuid(uuid) + return cls._blockdev_check_uuid("xfs", uuid) class HFSPlusUUID(FSUUID): @@ -69,6 +79,4 @@ def uuid_format_ok(cls, uuid): class NTFSUUID(FSUUID): @classmethod def uuid_format_ok(cls, uuid): - if len(uuid) != 16: - return False - return all(char in "0123456789ABCDEF" for char in uuid) + return cls._blockdev_check_uuid("ntfs", uuid) diff --git a/blivet/tasks/fswritelabel.py b/blivet/tasks/fswritelabel.py index 7f4203f60..afea2fc1b 100644 --- a/blivet/tasks/fswritelabel.py +++ b/blivet/tasks/fswritelabel.py @@ -19,84 +19,54 @@ # # Red Hat Author(s): Anne Mulhern -import abc - -from six import add_metaclass - -from .. import util from ..errors import FSWriteLabelError from . import availability from . import fstask from . import task +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev -@add_metaclass(abc.ABCMeta) -class FSWriteLabel(task.BasicApplication, fstask.FSTask): +class FSWriteLabel(task.BasicApplication, fstask.FSTask): """ An abstract class that represents writing a label for a filesystem. """ description = "write filesystem label" - - args = abc.abstractproperty(doc="arguments for writing a label") + fstype = None # IMPLEMENTATION methods - @property - def _set_command(self): - """Get the command to label the filesystem. - - :return: the command - :rtype: list of str - """ - return [str(self.ext)] + self.args - def do_task(self): # pylint: disable=arguments-differ error_msgs = self.availability_errors if error_msgs: raise FSWriteLabelError("\n".join(error_msgs)) - rc = util.run_program(self._set_command) - if rc: - raise FSWriteLabelError("label failed") + try: + BlockDev.fs.set_label(self.fs.device, self.fs.label, self.fstype) + except BlockDev.FSError as e: + raise FSWriteLabelError(str(e)) class DosFSWriteLabel(FSWriteLabel): - ext = availability.DOSFSLABEL_APP - - @property - def args(self): - if availability.MKDOSFS_NEW_APP.available: - if self.fs.label: - return [self.fs.device, self.fs.label] - else: - return [self.fs.device, "--reset"] - else: - return [self.fs.device, self.fs.label] + fstype = "vfat" + ext = availability.BLOCKDEV_VFAT_LABEL class Ext2FSWriteLabel(FSWriteLabel): - ext = availability.E2LABEL_APP - - @property - def args(self): - return [self.fs.device, self.fs.label] + fstype = "ext2" + ext = availability.BLOCKDEV_EXT_LABEL class NTFSWriteLabel(FSWriteLabel): - ext = availability.NTFSLABEL_APP - - @property - def args(self): - return [self.fs.device, self.fs.label] + fstype = "ntfs" + ext = availability.BLOCKDEV_NTFS_LABEL class XFSWriteLabel(FSWriteLabel): - ext = availability.XFSADMIN_APP - - @property - def args(self): - return ["-L", self.fs.label if self.fs.label != "" else "--", self.fs.device] + fstype = "xfs" + ext = availability.BLOCKDEV_XFS_LABEL class UnimplementedFSWriteLabel(fstask.UnimplementedFSTask): diff --git a/blivet/tasks/fswriteuuid.py b/blivet/tasks/fswriteuuid.py index dddb03b03..8168f856e 100644 --- a/blivet/tasks/fswriteuuid.py +++ b/blivet/tasks/fswriteuuid.py @@ -1,68 +1,46 @@ -import abc - -from six import add_metaclass - -from .. import util from ..errors import FSWriteUUIDError from . import availability from . import fstask from . import task +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev -@add_metaclass(abc.ABCMeta) -class FSWriteUUID(task.BasicApplication, fstask.FSTask): +class FSWriteUUID(task.BasicApplication, fstask.FSTask): """ An abstract class that represents writing an UUID for a filesystem. """ description = "write filesystem UUID" - - args = abc.abstractproperty(doc="arguments for writing a UUID") + fstype = None # IMPLEMENTATION methods - @property - def _set_command(self): - """Get the command to set UUID of the filesystem. - - :return: the command - :rtype: list of str - """ - return [str(self.ext)] + self.args - def do_task(self): # pylint: disable=arguments-differ error_msgs = self.availability_errors if error_msgs: raise FSWriteUUIDError("\n".join(error_msgs)) - rc = util.run_program(self._set_command) - if rc: - msg = "setting UUID via {} failed".format(self._set_command) - raise FSWriteUUIDError(msg) + try: + BlockDev.fs.set_uuid(self.fs.device, self.fs.uuid, self.fstype) + except BlockDev.FSError as e: + raise FSWriteUUIDError(str(e)) class Ext2FSWriteUUID(FSWriteUUID): - ext = availability.TUNE2FS_APP - - @property - def args(self): - return ["-U", self.fs.uuid, self.fs.device] + fstype = "ext2" + ext = availability.BLOCKDEV_EXT_UUID class NTFSWriteUUID(FSWriteUUID): - ext = availability.NTFSLABEL_APP - - @property - def args(self): - return ["--new-serial=" + self.fs.uuid, self.fs.device] + fstype = "ntfs" + ext = availability.BLOCKDEV_NTFS_UUID class XFSWriteUUID(FSWriteUUID): - ext = availability.XFSADMIN_APP - - @property - def args(self): - return ["-U", self.fs.uuid, self.fs.device] + fstype = "xfs" + ext = availability.BLOCKDEV_XFS_UUID class UnimplementedFSWriteUUID(fstask.UnimplementedFSTask): diff --git a/tests/storage_tests/formats_test/fslabeling.py b/tests/storage_tests/formats_test/fslabeling.py index ebe0b70a2..80bb048b0 100644 --- a/tests/storage_tests/formats_test/fslabeling.py +++ b/tests/storage_tests/formats_test/fslabeling.py @@ -131,11 +131,14 @@ def test_labeling(self): if an_fs._readlabel.availability_errors or not an_fs.relabels(): self.skipTest("can not read or write label for filesystem %s" % an_fs.name) self.assertIsNone(an_fs.create()) - self.assertEqual(an_fs.read_label(), an_fs._labelfs.default_label) + self.assertEqual(an_fs.read_label(), self._default_label) an_fs.label = "an_fs" self.assertIsNone(an_fs.write_label()) - self.assertEqual(an_fs.read_label(), an_fs.label) + if an_fs.type in ("vfat", "efi"): + self.assertEqual(an_fs.read_label(), an_fs.label.upper()) + else: + self.assertEqual(an_fs.read_label(), an_fs.label) an_fs.label = "" self.assertIsNone(an_fs.write_label()) @@ -157,7 +160,10 @@ def test_creating(self): if an_fs._readlabel.availability_errors: self.skipTest("can not read label for filesystem %s" % an_fs.name) self.assertIsNone(an_fs.create()) - self.assertEqual(an_fs.read_label(), "start") + if an_fs.type in ("vfat", "efi"): + self.assertEqual(an_fs.read_label(), "START") + else: + self.assertEqual(an_fs.read_label(), "start") def test_creating_none(self): """Create a filesystem with the label None. @@ -167,7 +173,7 @@ def test_creating_none(self): if an_fs._readlabel.availability_errors: self.skipTest("can not read label for filesystem %s" % an_fs.name) self.assertIsNone(an_fs.create()) - self.assertEqual(an_fs.read_label(), an_fs._labelfs.default_label) + self.assertEqual(an_fs.read_label(), self._default_label) def test_creating_empty(self): """Create a filesystem with an empty label. diff --git a/tests/storage_tests/formats_test/fstesting.py b/tests/storage_tests/formats_test/fstesting.py index e34584d88..42090a30e 100644 --- a/tests/storage_tests/formats_test/fstesting.py +++ b/tests/storage_tests/formats_test/fstesting.py @@ -132,7 +132,10 @@ def test_labeling(self): self.assertIsNone(an_fs.create()) try: label = an_fs.read_label() - self.assertEqual(label, "label") + if an_fs.type in ("vfat", "efi"): + self.assertEqual(label, "LABEL") + else: + self.assertEqual(label, "label") except FSError: pass diff --git a/tests/storage_tests/formats_test/labeling_test.py b/tests/storage_tests/formats_test/labeling_test.py index 9f48e3078..f5d655f02 100644 --- a/tests/storage_tests/formats_test/labeling_test.py +++ b/tests/storage_tests/formats_test/labeling_test.py @@ -54,33 +54,38 @@ def test_labels(self): class XFSTestCase(fslabeling.CompleteLabelingAsRoot): _fs_class = fs.XFS _invalid_label = "root filesystem" + _default_label = "" _DEVICE_SIZE = Size("500 MiB") class FATFSTestCase(fslabeling.CompleteLabelingAsRoot): _fs_class = fs.FATFS _invalid_label = "root___filesystem" + _default_label = "" class Ext2FSTestCase(fslabeling.CompleteLabelingAsRoot): _fs_class = fs.Ext2FS _invalid_label = "root___filesystem" + _default_label = "" class HFSTestCase(fslabeling.LabelingAsRoot): _fs_class = fs.HFS _invalid_label = "n" * 28 + _default_label = "Untitled" class HFSPlusTestCase(fslabeling.LabelingAsRoot): _fs_class = fs.HFSPlus _invalid_label = "n" * 129 + _default_label = "Untitled" -@unittest.skip("Unable to create NTFS filesystem.") class NTFSTestCase(fslabeling.CompleteLabelingAsRoot): _fs_class = fs.NTFS _invalid_label = "n" * 129 + _default_label = "" class LabelingSwapSpaceTestCase(loopbackedtestcase.LoopBackedTestCase): diff --git a/tests/storage_tests/formats_test/uuid_test.py b/tests/storage_tests/formats_test/uuid_test.py index 31f1f42c3..d397cd499 100644 --- a/tests/storage_tests/formats_test/uuid_test.py +++ b/tests/storage_tests/formats_test/uuid_test.py @@ -28,14 +28,14 @@ def test_uuids(self): self.assertTrue(fscls().uuid_format_ok(uuid)) self.assertFalse(fs.FATFS().uuid_format_ok("1234-56789")) - self.assertFalse(fs.FATFS().uuid_format_ok("abcd-ef00")) - self.assertFalse(fs.FATFS().uuid_format_ok("12345678")) + self.assertTrue(fs.FATFS().uuid_format_ok("abcd-ef00")) + self.assertTrue(fs.FATFS().uuid_format_ok("12345678")) self.assertTrue(fs.FATFS().uuid_format_ok("1234-5678")) self.assertTrue(fs.FATFS().uuid_format_ok("ABCD-EF01")) self.assertFalse(fs.NTFS().uuid_format_ok("12345678901234567")) self.assertFalse(fs.NTFS().uuid_format_ok("abcdefgh")) - self.assertFalse(fs.NTFS().uuid_format_ok("abcdefabcdefabcd")) + self.assertTrue(fs.NTFS().uuid_format_ok("abcdefabcdefabcd")) self.assertTrue(fs.NTFS().uuid_format_ok("1234567890123456")) self.assertTrue(fs.NTFS().uuid_format_ok("ABCDEFABCDEFABCD")) @@ -65,7 +65,7 @@ class XFSAfterTestCase(fsuuid.SetUUIDAfterMkFs): class FATFSTestCase(fsuuid.SetUUIDWithMkFs): _fs_class = fs.FATFS - _invalid_uuid = "c87ab0e1" + _invalid_uuid = "z87ab0e1" _valid_uuid = "DEAD-BEEF" @@ -89,7 +89,7 @@ class HFSPlusTestCase(fsuuid.SetUUIDAfterMkFs): class NTFSTestCase(fsuuid.SetUUIDAfterMkFs): _fs_class = fs.NTFS - _invalid_uuid = "b22193477ac947fb" + _invalid_uuid = "z22193477ac947fb" _valid_uuid = "BC3B34461B8344A6" From fbd2e6296bbb981925a9d31936814a37b064552c Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Wed, 25 Oct 2023 14:39:34 +0200 Subject: [PATCH 11/24] Use libblockdev for filesystem resizing --- blivet/formats/fs.py | 2 +- blivet/tasks/availability.py | 38 +++++++--- blivet/tasks/fsresize.py | 143 +++++++---------------------------- 3 files changed, 55 insertions(+), 128 deletions(-) diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index cca0b907a..4aa2c1bd4 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1438,7 +1438,7 @@ def _size_option(self, size): This is not impossible, since a special option for mounting is size=%. """ - return "size=%s" % (self._resize.size_fmt % size.convert_to(self._resize.unit)) + return "size=%sm" % size.convert_to(self._resize.unit) def _get_options(self): # Returns the regular mount options with the special size option, diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 39db81a74..8037328e8 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -255,12 +255,14 @@ class BlockDevFSMethod(Method): """ Methods for when application is actually a libblockdev FS plugin functionality. """ - def __init__(self, check_fn, fstype): + def __init__(self, operation, check_fn, fstype): """ Initializer. + :param operation: operation to check for support availability :param check_fn: function used to check for support availability :param fstype: filesystem type to check for the support availability """ + self.operation = operation self.check_fn = check_fn self.fstype = fstype self._availability_errors = None @@ -278,7 +280,10 @@ def availability_errors(self, resource): return ["libblockdev fs plugin not loaded"] else: try: - avail, utility = self.check_fn(self.fstype) + if self.operation in (FSOperation.UUID, FSOperation.LABEL): + avail, utility = self.check_fn(self.fstype) + elif self.operation == FSOperation.RESIZE: + avail, _mode, utility = self.check_fn(self.fstype) except blockdev.FSError as e: return [str(e)] if not avail: @@ -371,7 +376,7 @@ def blockdev_plugin(name, blockdev_method): return ExternalResource(blockdev_method, name) -def blockdev_fs_plugin(blockdev_fs_method): +def blockdev_fs_plugin_operation(blockdev_fs_method): """ Construct an external resource that is a libblockdev FS plugin functionality. """ return ExternalResource(blockdev_fs_method, "libblockdev FS plugin method") @@ -515,15 +520,26 @@ def available_resource(name): blockdev.FSTech.NTFS: 0}) BLOCKDEV_FS_TECH = BlockDevMethod(BLOCKDEV_FS) + # libblockdev fs plugin methods -BLOCKDEV_EXT_UUID = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_uuid, "ext2")) -BLOCKDEV_XFS_UUID = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_uuid, "xfs")) -BLOCKDEV_NTFS_UUID = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_uuid, "ntfs")) - -BLOCKDEV_EXT_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "ext2")) -BLOCKDEV_XFS_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "xfs")) -BLOCKDEV_VFAT_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "vfat")) -BLOCKDEV_NTFS_LABEL = blockdev_fs_plugin(BlockDevFSMethod(blockdev.fs.can_set_label, "ntfs")) +class FSOperation(): + UUID = 0 + LABEL = 1 + RESIZE = 2 + + +BLOCKDEV_EXT_UUID = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.UUID, blockdev.fs.can_set_uuid, "ext2")) +BLOCKDEV_XFS_UUID = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.UUID, blockdev.fs.can_set_uuid, "xfs")) +BLOCKDEV_NTFS_UUID = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.UUID, blockdev.fs.can_set_uuid, "ntfs")) + +BLOCKDEV_EXT_LABEL = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.LABEL, blockdev.fs.can_set_label, "ext2")) +BLOCKDEV_XFS_LABEL = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.LABEL, blockdev.fs.can_set_label, "xfs")) +BLOCKDEV_VFAT_LABEL = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.LABEL, blockdev.fs.can_set_label, "vfat")) +BLOCKDEV_NTFS_LABEL = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.LABEL, blockdev.fs.can_set_label, "ntfs")) + +BLOCKDEV_EXT_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "ext2")) +BLOCKDEV_XFS_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "xfs")) +BLOCKDEV_NTFS_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "ntfs")) # libblockdev plugins # we can't just check if the plugin is loaded, we also need to make sure diff --git a/blivet/tasks/fsresize.py b/blivet/tasks/fsresize.py index e101e6096..e420fe966 100644 --- a/blivet/tasks/fsresize.py +++ b/blivet/tasks/fsresize.py @@ -19,16 +19,8 @@ # # Red Hat Author(s): Anne Mulhern -import abc -import os -import tempfile - -from contextlib import contextmanager -from six import add_metaclass - from ..errors import FSError -from ..size import B, KiB, MiB, GiB, KB, MB, GB -from ..import util +from ..size import B, MiB from . import availability from . import task @@ -38,36 +30,23 @@ import logging log = logging.getLogger("blivet") +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev + -@add_metaclass(abc.ABCMeta) class FSResizeTask(fstask.FSTask): """ The abstract properties that any resize task must have. """ - size_fmt = abc.abstractproperty(doc="Size format string.") - -@add_metaclass(abc.ABCMeta) class FSResize(task.BasicApplication, FSResizeTask): """ An abstract class for resizing a filesystem. """ description = "resize filesystem" - args = abc.abstractproperty(doc="Resize arguments.") - # IMPLEMENTATION methods - @abc.abstractmethod - def size_spec(self): - """ Returns a string specification for the target size of the command. - :returns: size specification - :rtype: str - """ - raise NotImplementedError() - - def _resize_command(self): - return [str(self.ext)] + self.args - def do_task(self): # pylint: disable=arguments-differ """ Resize the device. @@ -78,118 +57,50 @@ def do_task(self): # pylint: disable=arguments-differ raise FSError("\n".join(error_msgs)) try: - ret = util.run_program(self._resize_command()) - except OSError as e: - raise FSError(e) - - if ret: - raise FSError("resize failed: %s" % ret) + BlockDev.fs.resize(self.fs.device, self.fs.target_size.convert_to(B), self.fs.type) + except BlockDev.FSError as e: + raise FSError(str(e)) class Ext2FSResize(FSResize): - ext = availability.RESIZE2FS_APP + ext = availability.BLOCKDEV_EXT_RESIZE unit = MiB - # No bytes specification is described in the man pages. A number without - # any suffix is interpreted as indicating the number of filesystem blocks. - # A suffix of "s" specifies a 512 byte sector. It is omitted here because - # the lookup is only by standard binary units. - size_fmt = {KiB: "%dK", MiB: "%dM", GiB: "%dG"}[unit] - - def size_spec(self): - return self.size_fmt % self.fs.target_size.convert_to(self.unit) - - @property - def args(self): - return ["-p", self.fs.device, self.size_spec()] - class NTFSResize(FSResize): - ext = availability.NTFSRESIZE_APP + ext = availability.BLOCKDEV_NTFS_RESIZE unit = B - size_fmt = {B: "%d", KB: "%dK", MB: "%dM", GB: "%dG"}[unit] - - def size_spec(self): - return self.size_fmt % self.fs.target_size.convert_to(self.unit) - - @property - def args(self): - return [ - "-ff", # need at least two 'f's to fully suppress interaction - "-s", self.size_spec(), - self.fs.device - ] class XFSResize(FSResize): - ext = availability.XFSRESIZE_APP + ext = availability.BLOCKDEV_XFS_RESIZE unit = B - size_fmt = None - - @contextmanager - def _do_temp_mount(self): - if self.fs.status: - yield - else: - dev_name = os.path.basename(self.fs.device) - tmpdir = tempfile.mkdtemp(prefix="xfs-tempmount-%s" % dev_name) - log.debug("mounting XFS on '%s' to '%s' for resize", self.fs.device, tmpdir) - try: - self.fs.mount(mountpoint=tmpdir) - except FSError as e: - raise FSError("Failed to mount XFS filesystem for resize: %s" % str(e)) - - try: - yield - finally: - util.umount(mountpoint=tmpdir) - os.rmdir(tmpdir) - - def _get_block_size(self): - if self.fs._current_info: - # this should be set by update_size_info() - for line in self.fs._current_info.split("\n"): - if line.startswith("blocksize ="): - return int(line.split("=")[-1]) - - raise FSError("Failed to get XFS filesystem block size for resize") - - def size_spec(self): - # size for xfs_growfs is in blocks - return str(self.fs.target_size.convert_to(self.unit) / self._get_block_size()) - - @property - def args(self): - return [self.fs.system_mountpoint, "-D", self.size_spec()] - - def do_task(self): # pylint: disable=arguments-differ - """ Resizes the XFS format. """ - - with self._do_temp_mount(): - super(XFSResize, self).do_task() class TmpFSResize(FSResize): - - ext = availability.MOUNT_APP + ext = availability.BLOCKDEV_FS_PLUGIN unit = MiB - size_fmt = {KiB: "%dk", MiB: "%dm", GiB: "%dg"}[unit] - def size_spec(self): - return "size=%s" % (self.size_fmt % self.fs.target_size.convert_to(self.unit)) + def do_task(self): # pylint: disable=arguments-differ + """ Resize the device. + + :raises FSError: on failure + """ + error_msgs = self.availability_errors + if error_msgs: + raise FSError("\n".join(error_msgs)) - @property - def args(self): # This is too closely mixed in w/ TmpFS object, due to the # fact that resizing is done by mounting and that the options are # therefore mount options. The situation is hard to avoid, though. opts = self.fs.mountopts or ",".join(self.fs._mount.options) - options = ("remount", opts, self.size_spec()) - return ['-o', ",".join(options), self.fs._type, self.fs.system_mountpoint] + options = ("remount", opts, "size=%dm" % self.fs.target_size.convert_to(MiB)) + try: + BlockDev.fs.mount(device=None, mountpoint=self.fs.system_mountpoint, fstype=self.fs._type, options=",".join(options)) + except BlockDev.FSError as e: + raise FSError(str(e)) -class UnimplementedFSResize(dfresize.UnimplementedDFResize, FSResizeTask): - @property - def size_fmt(self): - raise NotImplementedError() +class UnimplementedFSResize(dfresize.UnimplementedDFResize, FSResizeTask): + unit = B From 7fee5e0638831331a017f0fbcc19e900077d4918 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Thu, 26 Oct 2023 11:01:11 +0200 Subject: [PATCH 12/24] Use libblockdev for getting filesystem info and size --- blivet/tasks/availability.py | 7 ++++- blivet/tasks/fsinfo.py | 50 ++++++++++++++++------------------- blivet/tasks/fsminsize.py | 10 +------ blivet/tasks/fssize.py | 51 ++++++++---------------------------- 4 files changed, 41 insertions(+), 77 deletions(-) diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 8037328e8..1d6c42086 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -280,7 +280,7 @@ def availability_errors(self, resource): return ["libblockdev fs plugin not loaded"] else: try: - if self.operation in (FSOperation.UUID, FSOperation.LABEL): + if self.operation in (FSOperation.UUID, FSOperation.LABEL, FSOperation.INFO): avail, utility = self.check_fn(self.fstype) elif self.operation == FSOperation.RESIZE: avail, _mode, utility = self.check_fn(self.fstype) @@ -526,6 +526,7 @@ class FSOperation(): UUID = 0 LABEL = 1 RESIZE = 2 + INFO = 3 BLOCKDEV_EXT_UUID = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.UUID, blockdev.fs.can_set_uuid, "ext2")) @@ -541,6 +542,10 @@ class FSOperation(): BLOCKDEV_XFS_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "xfs")) BLOCKDEV_NTFS_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "ntfs")) +BLOCKDEV_EXT_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "ext2")) +BLOCKDEV_XFS_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "xfs")) +BLOCKDEV_NTFS_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "ntfs")) + # libblockdev plugins # we can't just check if the plugin is loaded, we also need to make sure # that all technologies required by us our supported (some may be missing diff --git a/blivet/tasks/fsinfo.py b/blivet/tasks/fsinfo.py index e91c2cb60..ea092b0e3 100644 --- a/blivet/tasks/fsinfo.py +++ b/blivet/tasks/fsinfo.py @@ -24,12 +24,15 @@ from six import add_metaclass from ..errors import FSError -from .. import util from . import availability from . import fstask from . import task +import gi +gi.require_version("BlockDev", "3.0") +from gi.repository import BlockDev + @add_metaclass(abc.ABCMeta) class FSInfo(task.BasicApplication, fstask.FSTask): @@ -38,17 +41,9 @@ class FSInfo(task.BasicApplication, fstask.FSTask): description = "filesystem info" - options = abc.abstractproperty( - doc="Options for invoking the application.") - - @property - def _info_command(self): - """ Returns the command for reading filesystem information. - - :returns: a list of appropriate options - :rtype: list of str - """ - return [str(self.ext)] + self.options + [self.fs.device] + @abc.abstractmethod + def _get_info(self): + raise NotImplementedError def do_task(self): # pylint: disable=arguments-differ """ Returns information from the command. @@ -61,31 +56,32 @@ def do_task(self): # pylint: disable=arguments-differ if error_msgs: raise FSError("\n".join(error_msgs)) - error_msg = None try: - (rc, out) = util.run_program_and_capture_output(self._info_command) - if rc: - error_msg = "failed to gather fs info: %s" % rc - except OSError as e: - error_msg = "failed to gather fs info: %s" % e - if error_msg: - raise FSError(error_msg) - return out + info = self._get_info() + except BlockDev.FSError as e: + raise FSError("failed to gather fs info: %s" % e) + return info class Ext2FSInfo(FSInfo): - ext = availability.DUMPE2FS_APP - options = ["-h"] + ext = availability.BLOCKDEV_EXT_INFO + + def _get_info(self): + return BlockDev.fs.ext2_get_info(self.fs.device) class NTFSInfo(FSInfo): - ext = availability.NTFSINFO_APP - options = ["-m"] + ext = availability.BLOCKDEV_NTFS_INFO + + def _get_info(self): + return BlockDev.fs.ntfs_get_info(self.fs.device) class XFSInfo(FSInfo): - ext = availability.XFSDB_APP - options = ["-c", "sb 0", "-c", "p dblocks", "-c", "p blocksize", "-r"] + ext = availability.BLOCKDEV_XFS_INFO + + def _get_info(self): + return BlockDev.fs.xfs_get_info(self.fs.device) class UnimplementedFSInfo(fstask.UnimplementedFSTask): diff --git a/blivet/tasks/fsminsize.py b/blivet/tasks/fsminsize.py index 620b91f73..eac2fe567 100644 --- a/blivet/tasks/fsminsize.py +++ b/blivet/tasks/fsminsize.py @@ -91,15 +91,7 @@ def _extract_block_size(self): if self.fs._current_info is None: return None - block_size = None - for line in (l.strip() for l in self.fs._current_info.splitlines() if l.startswith("Block size:")): - try: - block_size = int(line.split(" ")[-1]) - break - except ValueError: - continue - - return Size(block_size) if block_size else None + return Size(self.fs._current_info.block_size) def _extract_num_blocks(self, info): """ Extract the number of blocks from the resizefs info. diff --git a/blivet/tasks/fssize.py b/blivet/tasks/fssize.py index 138c86229..79ceda5e0 100644 --- a/blivet/tasks/fssize.py +++ b/blivet/tasks/fssize.py @@ -20,7 +20,6 @@ # Red Hat Author(s): Anne Mulhern import abc -from collections import namedtuple import six @@ -32,9 +31,6 @@ from . import fstask from . import task -_tags = ("count", "size") -_Tags = namedtuple("_Tags", _tags) - @six.add_metaclass(abc.ABCMeta) class FSSize(fstask.FSTask): @@ -42,9 +38,6 @@ class FSSize(fstask.FSTask): """ An abstract class that represents size information extraction. """ description = "current filesystem size" - tags = abc.abstractproperty( - doc="Strings used for extracting components of size.") - # TASK methods @property @@ -55,6 +48,10 @@ def _availability_errors(self): def depends_on(self): return [self.fs._info] + @abc.abstractmethod + def _get_size(self): + raise NotImplementedError + # IMPLEMENTATION methods def do_task(self): # pylint: disable=arguments-differ @@ -71,48 +68,22 @@ def do_task(self): # pylint: disable=arguments-differ if self.fs._current_info is None: raise FSError("No info available for size computation.") - # Setup initial values - values = {} - for k in _tags: - values[k] = None - - # Attempt to set values from info - for line in (l.strip() for l in self.fs._current_info.splitlines()): - key = six.next((k for k in _tags if line.startswith(getattr(self.tags, k))), None) - if not key: - continue - - if values[key] is not None: - raise FSError("found two matches for key %s" % key) - - # Look for last numeric value in matching line - fields = line.split() - fields.reverse() - for field in fields: - try: - values[key] = int(field) - break - except ValueError: - continue - - # Raise an error if a value is missing - missing = six.next((k for k in _tags if values[k] is None), None) - if missing is not None: - raise FSError("Failed to parse info for %s." % missing) - - return values["count"] * Size(values["size"]) + return self._get_size() class Ext2FSSize(FSSize): - tags = _Tags(size="Block size:", count="Block count:") + def _get_size(self): + return Size(self.fs._current_info.block_size * self.fs._current_info.block_count) class NTFSSize(FSSize): - tags = _Tags(size="Cluster Size:", count="Volume Size in Clusters:") + def _get_size(self): + return Size(self.fs._current_info.size) class XFSSize(FSSize): - tags = _Tags(size="blocksize =", count="dblocks =") + def _get_size(self): + return Size(self.fs._current_info.block_size * self.fs._current_info.block_count) class TmpFSSize(task.BasicApplication, fstask.FSTask): From ffa9d7bb20da14b1ea960afe167d30f15231f6c2 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Thu, 26 Oct 2023 11:14:21 +0200 Subject: [PATCH 13/24] Use libblockdev for reading filesystem label We can now use the FSInfo task to get the filesystem label too. --- blivet/formats/fs.py | 7 ++++ blivet/tasks/availability.py | 1 + blivet/tasks/fsreadlabel.py | 70 ++++++------------------------------ 3 files changed, 18 insertions(+), 60 deletions(-) diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 4aa2c1bd4..4e30a9475 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -661,6 +661,13 @@ def read_label(self): if not self._readlabel.available: raise FSReadLabelError("can not read label for filesystem %s" % self.type) + + try: + if self._info.available: + self._current_info = self._info.do_task() + except FSError as e: + log.info("Failed to obtain info for device %s: %s", self.device, e) + return self._readlabel.do_task() def write_label(self, dry_run=False): diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index 1d6c42086..4c823f59a 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -545,6 +545,7 @@ class FSOperation(): BLOCKDEV_EXT_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "ext2")) BLOCKDEV_XFS_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "xfs")) BLOCKDEV_NTFS_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "ntfs")) +BLOCKDEV_VFAT_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "vfat")) # libblockdev plugins # we can't just check if the plugin is loaded, we also need to make sure diff --git a/blivet/tasks/fsreadlabel.py b/blivet/tasks/fsreadlabel.py index 6f2c8a021..5c6003a36 100644 --- a/blivet/tasks/fsreadlabel.py +++ b/blivet/tasks/fsreadlabel.py @@ -20,12 +20,10 @@ # Red Hat Author(s): Anne Mulhern import abc -import re from six import add_metaclass from ..errors import FSReadLabelError -from .. import util from . import availability from . import fstask @@ -38,36 +36,11 @@ class FSReadLabel(task.BasicApplication, fstask.FSTask): """ An abstract class that represents reading a filesystem's label. """ description = "read filesystem label" - label_regex = abc.abstractproperty( - doc="Matches the string output by the reading application.") - - args = abc.abstractproperty(doc="arguments for reading a label.") - - # IMPLEMENTATION methods - @property - def _read_command(self): - """Get the command to read the filesystem label. - - :return: the command - :rtype: list of str - """ - return [str(self.ext)] + self.args - - def _extract_label(self, labelstr): - """Extract the label from an output string. - - :param str labelstr: the string containing the label information + def depends_on(self): + return [self.fs._info] - :return: the label - :rtype: str - - Raises an FSReadLabelError if the label can not be extracted. - """ - match = re.match(self.label_regex, labelstr) - if match is None: - raise FSReadLabelError("Unknown format for application %s" % self.ext) - return match.group('label') + # IMPLEMENTATION methods def do_task(self): # pylint: disable=arguments-differ """ Get the label. @@ -79,49 +52,26 @@ def do_task(self): # pylint: disable=arguments-differ if error_msgs: raise FSReadLabelError("\n".join(error_msgs)) - (rc, out) = util.run_program_and_capture_output(self._read_command) - if rc != 0: - raise FSReadLabelError("read label failed") - - label = out.strip() + if self.fs._current_info is None: + raise FSReadLabelError("No info available for size computation.") - return label if label == "" else self._extract_label(label) + return self.fs._current_info.label class DosFSReadLabel(FSReadLabel): - ext = availability.DOSFSLABEL_APP - label_regex = r'(?P