Compare commits

..

No commits in common. "c10s-mod_pass_in_stratis_test" and "c8" have entirely different histories.

35 changed files with 3377 additions and 2169 deletions

167
.gitignore vendored
View File

@ -1,165 +1,2 @@
/blivet-0.4.tar.gz
/blivet-0.5.tar.gz
/blivet-0.6.tar.gz
/blivet-0.7.tar.gz
/blivet-0.8.tar.gz
/blivet-0.9.tar.gz
/blivet-0.10.tar.gz
/blivet-0.11.tar.gz
/blivet-0.12.tar.gz
/blivet-0.13.tar.gz
/blivet-0.14.tar.gz
/blivet-0.15.tar.gz
/blivet-0.16.tar.gz
/blivet-0.17.tar.gz
/blivet-0.18.tar.gz
/blivet-0.19.tar.gz
/blivet-0.20.tar.gz
/blivet-0.21.tar.gz
/blivet-0.22.tar.gz
/blivet-0.23.tar.gz
/blivet-0.24.tar.gz
/blivet-0.25.tar.gz
/blivet-0.26.tar.gz
/blivet-0.27.tar.gz
/blivet-0.28.tar.gz
/blivet-0.29.tar.gz
/blivet-0.30.tar.gz
/blivet-0.31.tar.gz
/blivet-0.32.tar.gz
/blivet-0.33.tar.gz
/blivet-0.34.tar.gz
/blivet-0.35.tar.gz
/blivet-0.36.tar.gz
/blivet-0.37.tar.gz
/blivet-0.38.tar.gz
/blivet-0.39.tar.gz
/blivet-0.40.tar.gz
/blivet-0.41.tar.gz
/blivet-0.42.tar.gz
/blivet-0.43.tar.gz
/blivet-0.44.tar.gz
/blivet-0.45.tar.gz
/blivet-0.46.tar.gz
/blivet-0.47.tar.gz
/blivet-0.48.tar.gz
/blivet-0.49.tar.gz
/blivet-0.50.tar.gz
/blivet-0.51.tar.gz
/blivet-0.52.tar.gz
/blivet-0.53.tar.gz
/blivet-0.54.tar.gz
/blivet-0.55.tar.gz
/blivet-0.56.tar.gz
/blivet-0.57.tar.gz
/blivet-0.58.tar.gz
/blivet-0.59.tar.gz
/blivet-0.60.tar.gz
/blivet-0.61.tar.gz
/blivet-0.62.tar.gz
/blivet-0.63.tar.gz
/blivet-0.64.tar.gz
/blivet-0.65.tar.gz
/blivet-0.66.tar.gz
/blivet-0.67.tar.gz
/blivet-0.68.tar.gz
/blivet-0.69.tar.gz
/blivet-0.70.tar.gz
/blivet-0.71.tar.gz
/blivet-0.72.tar.gz
/blivet-0.73.tar.gz
/blivet-0.74.tar.gz
/blivet-0.75.tar.gz
/blivet-0.76.tar.gz
/blivet-1.0.tar.gz
/blivet-1.1.tar.gz
/blivet-1.2.tar.gz
/blivet-1.3.tar.gz
/blivet-1.4.tar.gz
/blivet-1.5.tar.gz
/blivet-1.6.tar.gz
/blivet-1.7.tar.gz
/blivet-1.8.tar.gz
/blivet-1.9.tar.gz
/blivet-1.10.tar.gz
/blivet-1.11.tar.gz
/blivet-1.12.tar.gz
/blivet-1.13.tar.gz
/blivet-1.14.tar.gz
/blivet-1.15.tar.gz
/blivet-1.16.tar.gz
/blivet-1.17.tar.gz
/blivet-1.18.tar.gz
/blivet-1.19.tar.gz
/blivet-2.0.1.tar.gz
/blivet-2.0.2.tar.gz
/blivet-2.0.3.tar.gz
/blivet-2.1.0.tar.gz
/blivet-2.1.1.tar.gz
/blivet-2.1.2.tar.gz
/blivet-2.1.3.tar.gz
/blivet-2.1.4.tar.gz
/blivet-2.1.5.tar.gz
/blivet-2.1.6.tar.gz
/blivet-2.1.7.tar.gz
/blivet-2.1.8.tar.gz
/blivet-2.1.9.tar.gz
/blivet-2.1.10.tar.gz
/blivet-2.1.11.tar.gz
/blivet-3.0.0.b1.tar.gz
/blivet-3.1.0.b1.tar.gz
/blivet-3.1.0.b2.tar.gz
/blivet-3.1.0.tar.gz
/blivet-3.1.1.tar.gz
/blivet-3.1.2.tar.gz
/blivet-3.1.3.tar.gz
/blivet-3.1.4-tests.tar.gz
/blivet-3.1.4.tar.gz
/blivet-3.1.5-tests.tar.gz
/blivet-3.1.5.tar.gz
/blivet-3.1.6.tar.gz
/blivet-3.1.6-tests.tar.gz
/blivet-3.2.0-tests.tar.gz
/blivet-3.2.0.tar.gz
/blivet-3.2.1-tests.tar.gz
/blivet-3.2.1.tar.gz
/blivet-3.2.2.tar.gz
/blivet-3.2.2-tests.tar.gz
/blivet-3.3.0.tar.gz
/blivet-3.3.0-tests.tar.gz
/blivet-3.3.1.tar.gz
/blivet-3.3.1-tests.tar.gz
/blivet-3.3.2-tests.tar.gz
/blivet-3.3.2.tar.gz
/blivet-3.3.3-tests.tar.gz
/blivet-3.3.3.tar.gz
/blivet-3.4.0.tar.gz
/blivet-3.4.0-tests.tar.gz
/blivet-3.4.1.tar.gz
/blivet-3.4.1-tests.tar.gz
/blivet-3.4.2.tar.gz
/blivet-3.4.2-tests.tar.gz
/blivet-3.4.3-tests.tar.gz
/blivet-3.4.3.tar.gz
/blivet-3.4.4-tests.tar.gz
/blivet-3.4.4.tar.gz
/blivet-3.5.0-tests.tar.gz
/blivet-3.5.0.tar.gz
/blivet-3.6.0.tar.gz
/blivet-3.6.0-tests.tar.gz
/blivet-3.6.1-tests.tar.gz
/blivet-3.6.1.tar.gz
/blivet-3.7.0-tests.tar.gz
/blivet-3.7.0.tar.gz
/blivet-3.7.1.tar.gz
/blivet-3.7.1-tests.tar.gz
/blivet-3.8.0-tests.tar.gz
/blivet-3.8.0.tar.gz
/blivet-3.8.1.tar.gz
/blivet-3.8.1-tests.tar.gz
/blivet-3.8.2.tar.gz
/blivet-3.8.2-tests.tar.gz
/blivet-3.9.0-tests.tar.gz
/blivet-3.9.0.tar.gz
/blivet-3.10.0.tar.gz
/blivet-3.10.0-tests.tar.gz
SOURCES/blivet-3.6.0-tests.tar.gz
SOURCES/blivet-3.6.0.tar.gz

View File

@ -1,28 +0,0 @@
From 8b527ee85b6594d506d445ff4c30579cccef8ae6 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 11 Nov 2020 13:24:55 +0100
Subject: [PATCH] Remove btrfs from requested libblockdev plugins
---
blivet/__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/__init__.py b/blivet/__init__.py
index 14bd5c61..1410d78e 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -63,9 +63,9 @@ gi.require_version("BlockDev", "3.0")
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", "nvme", "fs"))
+ _REQUESTED_PLUGIN_NAMES = set(("lvm", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "s390", "nvme", "fs"))
else:
- _REQUESTED_PLUGIN_NAMES = set(("lvm", "btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvme", "fs"))
+ _REQUESTED_PLUGIN_NAMES = set(("lvm", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvme", "fs"))
_requested_plugins = blockdev.plugin_specs_from_names(_REQUESTED_PLUGIN_NAMES)
try:
--
2.26.2

View File

@ -1,49 +0,0 @@
From 95f565d56d21dd7e0d9033236a20be735665e0af Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Tue, 14 May 2024 12:35:12 +0200
Subject: [PATCH] Fix skipping btrfs calls when libblockdev btrfs plugin is
missing
We need to check for the btrfs plugin in the set of available
plugins, not in the missing plugins, because on RHEL the plugin is
not missing, it's not even requested.
---
blivet/devices/btrfs.py | 4 ++--
tests/unit_tests/devices_test/btrfs_test.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/blivet/devices/btrfs.py b/blivet/devices/btrfs.py
index c446e7e59..0cbaa44d9 100644
--- a/blivet/devices/btrfs.py
+++ b/blivet/devices/btrfs.py
@@ -40,7 +40,7 @@
from ..formats import get_format, DeviceFormat
from ..size import Size
from ..mounts import mounts_cache
-from .. import missing_plugs
+from .. import avail_plugs
import logging
log = logging.getLogger("blivet")
@@ -382,7 +382,7 @@ def _list_subvolumes(self, mountpoint, snapshots_only=False):
def list_subvolumes(self, snapshots_only=False):
subvols = []
- if "btrfs" in missing_plugs:
+ if "btrfs" not in avail_plugs:
log.debug("not listing btrfs subvolumes, libblockdev btrfs plugin is missing")
return subvols
diff --git a/tests/unit_tests/devices_test/btrfs_test.py b/tests/unit_tests/devices_test/btrfs_test.py
index 785afd209..41731e91e 100644
--- a/tests/unit_tests/devices_test/btrfs_test.py
+++ b/tests/unit_tests/devices_test/btrfs_test.py
@@ -83,7 +83,7 @@ def test_btrfs_list_subvolumes(self):
# mounted but libblockdev btrfs plugin not available
blockdev.reset_mock()
- with patch("blivet.devices.btrfs.missing_plugs", new={"btrfs"}):
+ with patch("blivet.devices.btrfs.avail_plugs", new={"lvm"}):
vol.list_subvolumes()
blockdev.list_subvolumes.assert_not_called()
blockdev.get_default_subvolume_id.assert_not_called()

View File

@ -1,32 +0,0 @@
From b7940496b4f8efdccb9b4097b496b0d9b2af1eea Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Tue, 18 Jun 2024 14:47:39 +0200
Subject: [PATCH] tests: Try waiting after partition creation for XFS resize
test
The test randomly fails to find the newly created partition so
lets try waiting a bit with udev settle.
---
tests/storage_tests/formats_test/fs_test.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/storage_tests/formats_test/fs_test.py b/tests/storage_tests/formats_test/fs_test.py
index f3c9fef5a..5da4a9339 100644
--- a/tests/storage_tests/formats_test/fs_test.py
+++ b/tests/storage_tests/formats_test/fs_test.py
@@ -11,6 +11,7 @@
from blivet.devices import PartitionDevice, DiskDevice
from blivet.flags import flags
from blivet.util import capture_output
+from blivet import udev
from .loopbackedtestcase import LoopBackedTestCase
@@ -149,6 +150,7 @@ def _create_partition(self, disk, size):
pend = pstart + int(Size(size) / disk.format.parted_device.sectorSize)
disk.format.add_partition(pstart, pend, parted.PARTITION_NORMAL)
disk.format.parted_disk.commit()
+ udev.settle()
part = disk.format.parted_disk.getPartitionBySector(pstart)
device = PartitionDevice(os.path.basename(part.path))

View File

@ -1,43 +0,0 @@
From 52c9699ecad592e35e0cd3841744f8cb8e2b2364 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 12 Jun 2024 16:51:43 +0200
Subject: [PATCH] Run mkfs.xfs with the force (-f) option by default
We stopped adding the force option when switching to libblockdev
in fa3add214ba8edf1965bc851b85f2f2a6a3ea107. This was not
intentional and the missing force option is already causing issues
when running mkfs.xfs on misaligned devices.
---
blivet/tasks/fsmkfs.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/blivet/tasks/fsmkfs.py b/blivet/tasks/fsmkfs.py
index 096b02295..45314ea89 100644
--- a/blivet/tasks/fsmkfs.py
+++ b/blivet/tasks/fsmkfs.py
@@ -241,6 +241,7 @@ class FSBlockDevMkfs(task.BasicApplication, FSMkfsTask, metaclass=abc.ABCMeta):
can_set_uuid = False
can_label = False
fstype = None
+ force = False
def do_task(self, options=None, label=False, set_uuid=False, nodiscard=False):
"""Create the format on the device and label if possible and desired.
@@ -277,7 +278,8 @@ def do_task(self, options=None, label=False, set_uuid=False, nodiscard=False):
try:
bd_options = BlockDev.FSMkfsOptions(label=self.fs.label if label else None,
uuid=self.fs.uuid if set_uuid else None,
- no_discard=self.fs._mkfs_nodiscard if nodiscard else False)
+ no_discard=self.fs._mkfs_nodiscard if nodiscard else False,
+ force=self.force)
BlockDev.fs.mkfs(self.fs.device, self.fstype, bd_options, extra={k: '' for k in create_options})
except BlockDev.FSError as e:
raise FSError(str(e))
@@ -331,6 +333,7 @@ class XFSMkfs(FSBlockDevMkfs):
can_nodiscard = True
can_set_uuid = True
can_label = True
+ force = True
class F2FSMkfs(FSBlockDevMkfs):

View File

@ -1,742 +0,0 @@
From 492122f34fe0ee5d0c7bce7f3dd2ce0ca6e3e9f2 Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Fri, 27 Jan 2023 22:01:23 +0100
Subject: [PATCH 1/7] blivet/zfcp: drop modprobe alias, which is superfluous
since udev in RHEL6
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/zfcp.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index a2b7facb..cd765d82 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -555,9 +555,6 @@ class zFCP:
f.write("%s\n" % (d,))
f.close()
- f = open(root + "/etc/modprobe.conf", "a")
- f.write("alias scsi_hostadapter zfcp\n")
- f.close()
# Create ZFCP singleton
--
2.45.2
From a49fdf291acad957675472f5c27be9e5269c199a Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Tue, 28 Feb 2023 17:23:32 +0100
Subject: [PATCH 2/7] blivet/zfcp: remove code broken since zfcp automatic LUN
scan
The old existing test preceding the removed code was only designed for the
old zfcp before it got automatic LUN scan. Hence, the test is incomplete.
With zfcp auto LUN scan, zfcp can just have SCSI devices without any
zfcp unit representation in sysfs.
Do not bother cleaning up an unused FCP device and just remove the code.
Note: Do not confuse zfcp auto port scan with zfcp auto LUN scan.
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/zfcp.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index cd765d82..e2c0dc2d 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -384,9 +384,6 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
self.devnum, luns[0])
return True
- # no other WWPNs/LUNs exists for this device number, it's safe to bring it offline
- self._set_zfcp_device_offline()
-
return True
--
2.45.2
From 19285bb785ccbfcd72fd1f3242c56e9d06ba74d8 Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Fri, 27 Jan 2023 22:17:45 +0100
Subject: [PATCH 3/7] blivet/zfcp: drop old zfcp port handling gone from the
kernel long ago
Gone since 2008 Linux kernel v2.6.27 commit 235f7f25f492 ("[SCSI] zfcp:
Remove sysfs attribute port_add").
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/zfcp.py | 65 --------------------------------------------------
1 file changed, 65 deletions(-)
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index e2c0dc2d..82751382 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -240,7 +240,6 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
super().online_device()
- portadd = "%s/%s/port_add" % (zfcpsysfs, self.devnum)
portdir = "%s/%s/%s" % (zfcpsysfs, self.devnum, self.wwpn)
unitadd = "%s/unit_add" % (portdir)
unitdir = "%s/%s" % (portdir, self.fcplun)
@@ -253,31 +252,6 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
log.warning("zFCP device %s in NPIV mode brought online. All LUNs will be activated "
"automatically although WWPN and LUN have been provided.", self.devnum)
- # create the sysfs directory for the WWPN/port
- if not os.path.exists(portdir):
- if os.path.exists(portadd):
- # older zfcp sysfs interface
- try:
- logged_write_line_to_file(portadd, self.wwpn)
- udev.settle()
- except OSError as e:
- raise ValueError(_("Could not add WWPN %(wwpn)s to zFCP "
- "device %(devnum)s (%(e)s).")
- % {'wwpn': self.wwpn,
- 'devnum': self.devnum,
- 'e': e})
- else:
- # newer zfcp sysfs interface with auto port scan
- raise ValueError(_("WWPN %(wwpn)s not found at zFCP device "
- "%(devnum)s.") % {'wwpn': self.wwpn,
- 'devnum': self.devnum})
- else:
- if os.path.exists(portadd):
- # older zfcp sysfs interface
- log.info("WWPN %(wwpn)s at zFCP device %(devnum)s already "
- "there.", {'wwpn': self.wwpn,
- 'devnum': self.devnum})
-
# create the sysfs directory for the LUN/unit
if not os.path.exists(unitdir):
try:
@@ -323,10 +297,7 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
def offline_device(self):
"""Remove the zFCP device from the system."""
- portadd = "%s/%s/port_add" % (zfcpsysfs, self.devnum)
- portremove = "%s/%s/port_remove" % (zfcpsysfs, self.devnum)
unitremove = "%s/%s/%s/unit_remove" % (zfcpsysfs, self.devnum, self.wwpn)
- portdir = "%s/%s/%s" % (zfcpsysfs, self.devnum, self.wwpn)
devdir = "%s/%s" % (zfcpsysfs, self.devnum)
try:
@@ -348,42 +319,6 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
% {'fcplun': self.fcplun, 'wwpn': self.wwpn,
'devnum': self.devnum, 'e': e})
- # remove the WWPN only if there are no other LUNs attached
- if os.path.exists(portadd):
- # only try to remove ports with older zfcp sysfs interface
- for lun in os.listdir(portdir):
- if lun.startswith("0x") and \
- os.path.isdir(os.path.join(portdir, lun)):
- log.info("Not removing WWPN %s at zFCP device %s since port still has other LUNs, e.g. %s.",
- self.wwpn, self.devnum, lun)
- return True
-
- try:
- logged_write_line_to_file(portremove, self.wwpn)
- except OSError as e:
- raise ValueError(_("Could not remove WWPN %(wwpn)s on zFCP "
- "device %(devnum)s (%(e)s).")
- % {'wwpn': self.wwpn,
- 'devnum': self.devnum, 'e': e})
-
- # check if there are other WWPNs existing for the zFCP device number
- if os.path.exists(portadd):
- # older zfcp sysfs interface
- for port in os.listdir(devdir):
- if port.startswith("0x") and \
- os.path.isdir(os.path.join(devdir, port)):
- log.info("Not setting zFCP device %s offline since it still has other ports, e.g. %s.",
- self.devnum, port)
- return True
- else:
- # newer zfcp sysfs interface with auto port scan
- luns = glob.glob("%s/0x????????????????/0x????????????????"
- % (devdir,))
- if len(luns) != 0:
- log.info("Not setting zFCP device %s offline since it still has other LUNs, e.g. %s.",
- self.devnum, luns[0])
- return True
-
return True
--
2.45.2
From cc67470805d871ff6ec09d554fb4b65a375e5b59 Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Tue, 16 Jul 2024 10:21:00 +0200
Subject: [PATCH 4/7] blivet/zfcp: change to consolidated persistent device
config by zdev (#1802482,#1937049)
Implements the zfcp part of referenced bugs.
https://github.com/ibm-s390-linux/s390-tools/tree/master/zdev/
handles everything as of
ibm-s390-linux/s390-tools@06a30ae
("zdev/dracut: add rd.zfcp cmdline option handling").
It is no longer necessary to perform individual pre-req steps, such as
setting an FCP device online, when we want to attach a LUN. Just call
chzdev to configure zfcp LUNs and let it do what is necessary, including
cio_ignore handling and udev settle.
The spec file update reflects the new dependency on `chzdev` from the
s390 architecture specific sub-package s390utils-core. Actually, this
commit here only depends on `chzdev` in older versions already packaged
and shipped, so no version comparison necessary here.
Since chzdev now implicitly sets the FCP device online
and there is no more preceding explicit FCP device online,
move the path over-specification warning after the call to chzdev.
Otherwise, the FCP device could still be offline and its
port_type unknown, so has_auto_lun_scan() would get wrong information
regarding the port_type being NPIV.
Anaconda handles the persistent config of all s390 device types as of
commit ("write persistent config of any (dasd,zfcp,znet) s390 devices to
sysroot"), so drop the special handling in zfcp.write().
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/zfcp.py | 99 +++++++++-------------------------------------
python-blivet.spec | 1 +
2 files changed, 20 insertions(+), 80 deletions(-)
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index 82751382..38ab5668 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -104,8 +104,6 @@ class ZFCPDeviceBase(ABC):
if not self.devnum:
raise ValueError(_("You have not specified a device number or the number is invalid"))
- self._device_online_path = os.path.join(zfcpsysfs, self.devnum, "online")
-
# Force str and unicode types in case any of the properties are unicode
def _to_string(self):
return str(self.devnum)
@@ -113,20 +111,6 @@ class ZFCPDeviceBase(ABC):
def __str__(self):
return self._to_string()
- def _free_device(self):
- """Remove the device from the I/O ignore list to make it visible to the system.
-
- :raises: ValueError if the device cannot be removed from the I/O ignore list
- """
-
- if not os.path.exists(self._device_online_path):
- log.info("Freeing zFCP device %s", self.devnum)
- util.run_program(["zfcp_cio_free", "-d", self.devnum])
-
- if not os.path.exists(self._device_online_path):
- raise ValueError(_("zFCP device %s not found, not even in device ignore list.") %
- (self.devnum,))
-
def _set_zfcp_device_online(self):
"""Set the zFCP device online.
@@ -134,10 +118,8 @@ class ZFCPDeviceBase(ABC):
"""
try:
- with open(self._device_online_path) as f:
- devonline = f.readline().strip()
- if devonline != "1":
- logged_write_line_to_file(self._device_online_path, "1")
+ util.run_program(["chzdev", "--enable", "zfcp-host", self.devnum,
+ "--yes", "--no-root-update", "--force"])
except OSError as e:
raise ValueError(_("Could not set zFCP device %(devnum)s "
"online (%(e)s).")
@@ -150,7 +132,8 @@ class ZFCPDeviceBase(ABC):
"""
try:
- logged_write_line_to_file(self._device_online_path, "0")
+ util.run_program(["chzdev", "--disable", "zfcp-host", self.devnum,
+ "--yes", "--no-root-update", "--force"])
except OSError as e:
raise ValueError(_("Could not set zFCP device %(devnum)s "
"offline (%(e)s).")
@@ -163,6 +146,7 @@ class ZFCPDeviceBase(ABC):
:returns: True or False
"""
+ @abstractmethod
def online_device(self):
"""Initialize the device and make its storage block device(s) ready to use.
@@ -170,10 +154,6 @@ class ZFCPDeviceBase(ABC):
:raises: ValueError if the device cannot be initialized
"""
- self._free_device()
- self._set_zfcp_device_online()
- return True
-
def offline_scsi_device(self):
"""Find SCSI devices associated to the zFCP device and remove them from the system."""
@@ -238,25 +218,15 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
:raises: ValueError if the device cannot be initialized
"""
- super().online_device()
-
portdir = "%s/%s/%s" % (zfcpsysfs, self.devnum, self.wwpn)
- unitadd = "%s/unit_add" % (portdir)
unitdir = "%s/%s" % (portdir, self.fcplun)
- failed = "%s/failed" % (unitdir)
-
- # Activating using devnum, WWPN, and LUN despite available zFCP auto LUN scan should still
- # be possible as this method was used as a workaround until the support for zFCP auto LUN
- # scan devices has been implemented. Just log a warning message and continue.
- if has_auto_lun_scan(self.devnum):
- log.warning("zFCP device %s in NPIV mode brought online. All LUNs will be activated "
- "automatically although WWPN and LUN have been provided.", self.devnum)
# create the sysfs directory for the LUN/unit
if not os.path.exists(unitdir):
try:
- logged_write_line_to_file(unitadd, self.fcplun)
- udev.settle()
+ util.run_program(["chzdev", "--enable", "zfcp-lun",
+ "%s:%s:%s" % (self.devnum, self.wwpn, self.fcplun),
+ "--yes", "--no-root-update", "--force"])
except OSError as e:
raise ValueError(_("Could not add LUN %(fcplun)s to WWPN "
"%(wwpn)s on zFCP device %(devnum)s "
@@ -270,48 +240,23 @@ class ZFCPDeviceFullPath(ZFCPDeviceBase):
'wwpn': self.wwpn,
'devnum': self.devnum})
- # check the state of the LUN
- fail = "0"
- try:
- f = open(failed, "r")
- fail = f.readline().strip()
- f.close()
- except OSError as e:
- raise ValueError(_("Could not read failed attribute of LUN "
- "%(fcplun)s at WWPN %(wwpn)s on zFCP device "
- "%(devnum)s (%(e)s).")
- % {'fcplun': self.fcplun,
- 'wwpn': self.wwpn,
- 'devnum': self.devnum,
- 'e': e})
- if fail != "0":
- self.offline_device()
- raise ValueError(_("Failed LUN %(fcplun)s at WWPN %(wwpn)s on "
- "zFCP device %(devnum)s removed again.")
- % {'fcplun': self.fcplun,
- 'wwpn': self.wwpn,
- 'devnum': self.devnum})
+ # Activating using devnum, WWPN, and LUN despite available zFCP auto LUN scan should still
+ # be possible as this method was used as a workaround until the support for zFCP auto LUN
+ # scan devices has been implemented. Just log a warning message and continue.
+ if has_auto_lun_scan(self.devnum):
+ log.warning("zFCP device %s in NPIV mode brought online. All LUNs will be activated "
+ "automatically although WWPN and LUN have been provided.", self.devnum)
return True
def offline_device(self):
"""Remove the zFCP device from the system."""
- unitremove = "%s/%s/%s/unit_remove" % (zfcpsysfs, self.devnum, self.wwpn)
- devdir = "%s/%s" % (zfcpsysfs, self.devnum)
-
- try:
- self.offline_scsi_device()
- except OSError as e:
- raise ValueError(_("Could not correctly delete SCSI device of "
- "zFCP %(devnum)s %(wwpn)s %(fcplun)s "
- "(%(e)s).")
- % {'devnum': self.devnum, 'wwpn': self.wwpn,
- 'fcplun': self.fcplun, 'e': e})
-
# remove the LUN
try:
- logged_write_line_to_file(unitremove, self.fcplun)
+ util.run_program(["chzdev", "--disable", "zfcp-lun",
+ "%s:%s:%s" % (self.devnum, self.wwpn, self.fcplun),
+ "--yes", "--no-root-update", "--force"])
except OSError as e:
raise ValueError(_("Could not remove LUN %(fcplun)s at WWPN "
"%(wwpn)s on zFCP device %(devnum)s "
@@ -340,7 +285,7 @@ class ZFCPDeviceAutoLunScan(ZFCPDeviceBase):
:raises: ValueError if the device cannot be initialized
"""
- super().online_device()
+ self._set_zfcp_device_online()
if not has_auto_lun_scan(self.devnum):
raise ValueError(_("zFCP device %s cannot use auto LUN scan.") % self)
@@ -480,13 +425,7 @@ class zFCP:
log.warning("%s", str(e))
def write(self, root):
- if len(self.fcpdevs) == 0:
- return
- f = open(root + zfcpconf, "w")
- for d in self.fcpdevs:
- f.write("%s\n" % (d,))
- f.close()
-
+ pass
# Create ZFCP singleton
diff --git a/python-blivet.spec b/python-blivet.spec
index 38a389ae..ac8d2841 100644
--- a/python-blivet.spec
+++ b/python-blivet.spec
@@ -70,6 +70,7 @@ Recommends: libblockdev-swap >= %{libblockdevver}
%ifarch s390 s390x
Recommends: libblockdev-s390 >= %{libblockdevver}
+Requires: s390utils-core
%endif
Requires: python3-bytesize >= %{libbytesizever}
--
2.45.2
From 6c4e57d78562962f014970c32381891c71f05e3b Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Tue, 31 Jan 2023 12:01:31 +0100
Subject: [PATCH 5/7] blivet/zfcp: remove no longer used read_config
functionality (#1802482,#1937049)
Implements the zfcp part of referenced bugs.
Since
https://github.com/rhinstaller/anaconda/commit/87ab1ab2a3aa8b95cd75b2f37e0881e5f57656a5
("Support cio_ignore functionality for zFCP devices (#533492)"),
/etc/zfcp.conf replaced /tmp/fcpconfig.
Since
https://github.com/rhinstaller/anaconda/commit/011ea0a1779459ed20990ddf52166aa75a9c1382
("Remove linuxrc.s390"), /etc/zfcp.conf only exists if the user specified
dracut cmdline parameter rd.zfcp=.
https://github.com/ibm-s390-linux/s390-tools/tree/master/zdev/
handles parsing of rd.zfcp= without /etc/zfcp.conf as of
https://github.com/ibm-s390-linux/s390-tools/commit/06a30ae529a5d6ad2369ed81da056bf3a6147bb6
("zdev/dracut: add rd.zfcp cmdline option handling").
https://src.fedoraproject.org/rpms/s390utils.git
no longer writes /etc/zfcp.conf during deprecated parsing of rd.zfcp=
as of commit
("zfcp: migrate to consolidated persistent device config with zdev")
Hence, nothing populates /etc/zfcp.conf during installer boot anymore.
Anaconda imports configuration for all s390 device types as of
commit ("write persistent config of any (dasd,zfcp,znet) s390 devices to
sysroot"). The only remaining import source is from dracut boot parameters.
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/zfcp.py | 60 ++++++++------------------------------------------
1 file changed, 9 insertions(+), 51 deletions(-)
diff --git a/blivet/zfcp.py b/blivet/zfcp.py
index 38ab5668..a33eb48b 100644
--- a/blivet/zfcp.py
+++ b/blivet/zfcp.py
@@ -45,7 +45,6 @@ def logged_write_line_to_file(fn, value):
zfcpsysfs = "/sys/bus/ccw/drivers/zfcp"
scsidevsysfs = "/sys/bus/scsi/devices"
-zfcpconf = "/etc/zfcp.conf"
def _is_lun_scan_allowed():
@@ -323,18 +322,22 @@ class zFCP:
""" ZFCP utility class.
- This class will automatically online to ZFCP drives configured in
- /tmp/fcpconfig when the startup() method gets called. It can also be
- used to manually configure ZFCP devices through the add_fcp() method.
+ This class is used to manually configure ZFCP devices through the
+ add_fcp() method, which is used by the anaconda GUI or by kickstart.
- As this class needs to make sure that /tmp/fcpconfig configured
+ As this class needs to make sure that configured
drives are only onlined once and as it keeps a global list of all ZFCP
devices it is implemented as a Singleton.
+
+ In particular, this class does not create objects for any other method
+ that enables ZFCP devices such as rd.zfcp= or any device auto
+ configuration. These methods make zfcp-attached SCSI disk block devices
+ available, which ZFCPDiskDevice [devices/disk.py] can directly
+ discover.
"""
def __init__(self):
self.fcpdevs = set()
- self.has_read_config = False
self.down = True
# So that users can write zfcp() to get the singleton instance
@@ -345,46 +348,6 @@ class zFCP:
# pylint: disable=unused-argument
return self
- def read_config(self):
- try:
- f = open(zfcpconf, "r")
- except OSError:
- log.info("no %s; not configuring zfcp", zfcpconf)
- return
-
- lines = [x.strip().lower() for x in f.readlines()]
- f.close()
-
- for line in lines:
- if line.startswith("#") or line == '':
- continue
-
- fields = line.split()
-
- # zFCP auto LUN scan available
- if len(fields) == 1:
- devnum = fields[0]
- wwpn = None
- fcplun = None
- elif len(fields) == 3:
- devnum = fields[0]
- wwpn = fields[1]
- fcplun = fields[2]
- elif len(fields) == 5:
- # support old syntax of:
- # devno scsiid wwpn scsilun fcplun
- devnum = fields[0]
- wwpn = fields[2]
- fcplun = fields[4]
- else:
- log.warning("Invalid line found in %s: %s", zfcpconf, line)
- continue
-
- try:
- self.add_fcp(devnum, wwpn, fcplun)
- except ValueError as e:
- log.warning("%s", str(e))
-
def add_fcp(self, devnum, wwpn=None, fcplun=None):
if wwpn and fcplun:
d = ZFCPDeviceFullPath(devnum, wwpn, fcplun)
@@ -410,11 +373,6 @@ class zFCP:
if not self.down:
return
self.down = False
- if not self.has_read_config:
- self.read_config()
- self.has_read_config = True
- # read_config calls add_fcp which calls online_device already
- return
if len(self.fcpdevs) == 0:
return
--
2.45.2
From e119e1e48a8a8bc83ec42d3c6ab31fac7c4a98eb Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Tue, 28 Feb 2023 17:48:04 +0100
Subject: [PATCH 6/7] respect explicit user choice for full path in zfcp
dracut_setup_args
Complements RHBZ#1937030.
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/devices/disk.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/blivet/devices/disk.py b/blivet/devices/disk.py
index 4ae4a845..edbf41c4 100644
--- a/blivet/devices/disk.py
+++ b/blivet/devices/disk.py
@@ -498,7 +498,12 @@ class ZFCPDiskDevice(DiskDevice):
from ..zfcp import has_auto_lun_scan
# zFCP auto LUN scan needs only the device ID
- if has_auto_lun_scan(self.hba_id):
+ # If the user explicitly over-specified with a full path configuration
+ # respect this choice and emit a full path specification nonetheless.
+ errorlevel = util.run_program(["lszdev", "zfcp-lun", "--configured",
+ "%s:%s:%s" % (self.hba_id, self.wwpn,
+ self.fcp_lun)])
+ if has_auto_lun_scan(self.hba_id) and errorlevel != 0:
dracut_args = set(["rd.zfcp=%s" % self.hba_id])
else:
dracut_args = set(["rd.zfcp=%s,%s,%s" % (self.hba_id, self.wwpn, self.fcp_lun,)])
--
2.45.2
From 4c2d39c4fcea9361b60d99327a9eb8b9d89078fb Mon Sep 17 00:00:00 2001
From: Steffen Maier <maier@linux.ibm.com>
Date: Tue, 16 Jul 2024 10:22:55 +0200
Subject: [PATCH 7/7] DASDDevice: dracut_setup_args() without deprecated
dasd.conf (#1802482,#1937049)
Implements the dasd part of referenced bugs.
Depends on
ibm-s390-linux/s390-tools@689b894
("zdev: add helper to convert from zdev config to dasd_mod.dasd").
The spec file update reflects the new dependency on `zdev-to-dasd_mod.dasd`
in the new v2.31.0 of the s390 architecture specific sub-package
s390utils-core.
Delegate the generation of rd.dasd statements to a helper tool from
s390-tools, which gets its low-level config information from the
consolidated persistent configuration mechanism using chzdev.
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
---
blivet/devices/disk.py | 56 +++-----------------------------
blivet/populator/helpers/disk.py | 3 --
python-blivet.spec | 3 +-
3 files changed, 6 insertions(+), 56 deletions(-)
diff --git a/blivet/devices/disk.py b/blivet/devices/disk.py
index edbf41c4..a849e7ac 100644
--- a/blivet/devices/disk.py
+++ b/blivet/devices/disk.py
@@ -530,67 +530,19 @@ class DASDDevice(DiskDevice):
:type format: :class:`~.formats.DeviceFormat` or a subclass of it
:keyword str wwn: the disk's WWN
:keyword busid: bus ID
- :keyword opts: options
- :type opts: dict with option name keys and option value values
"""
self.busid = kwargs.pop('busid')
- self.opts = kwargs.pop('opts')
DiskDevice.__init__(self, device, **kwargs)
@property
def description(self):
return "DASD device %s" % self.busid
- def get_opts(self):
- return ["%s=%s" % (k, v) for k, v in self.opts.items() if v == '1']
-
def dracut_setup_args(self):
- conf = "/etc/dasd.conf"
- line = None
- if os.path.isfile(conf):
- f = open(conf)
- # grab the first line that starts with our bus_id
- for l in f.readlines():
- if l.startswith(self.busid):
- line = l.rstrip()
- break
-
- f.close()
-
- # See if we got a line. If not, grab our get_opts
- if not line:
- line = self.busid
- for devopt in self.get_opts():
- line += " %s" % devopt
-
- # Create a translation mapping from dasd.conf format to module format
- translate = {'use_diag': 'diag',
- 'readonly': 'ro',
- 'erplog': 'erplog',
- 'failfast': 'failfast'}
-
- # this is a really awkward way of determining if the
- # feature found is actually desired (1, not 0), plus
- # translating that feature into the actual kernel module
- # value
- opts = []
- parts = line.split()
- for chunk in parts[1:]:
- try:
- feat, val = chunk.split('=')
- if int(val):
- opts.append(translate[feat])
- except (ValueError, KeyError):
- # If we don't know what the feature is (feat not in translate
- # or if we get a val that doesn't cleanly convert to an int
- # we can't do anything with it.
- log.warning("failed to parse dasd feature %s", chunk)
-
- if opts:
- return set(["rd.dasd=%s(%s)" % (self.busid,
- ":".join(opts))])
- else:
- return set(["rd.dasd=%s" % self.busid])
+ devspec = util.capture_output(["/lib/s390-tools/zdev-to-dasd_mod.dasd",
+ "persistent", self.busid]).strip()
+ # strip to remove trailing newline, which must not appear in zipl BLS
+ return set(["rd.dasd=%s" % devspec])
NVMeController = namedtuple("NVMeController", ["name", "serial", "nvme_ver", "id", "subsysnqn",
diff --git a/blivet/populator/helpers/disk.py b/blivet/populator/helpers/disk.py
index 3ac3f408..fc47f62a 100644
--- a/blivet/populator/helpers/disk.py
+++ b/blivet/populator/helpers/disk.py
@@ -204,9 +204,6 @@ class DASDDevicePopulator(DiskDevicePopulator):
def _get_kwargs(self):
kwargs = super(DASDDevicePopulator, self)._get_kwargs()
kwargs["busid"] = udev.device_get_dasd_bus_id(self.data)
- kwargs["opts"] = {}
- for attr in ['readonly', 'use_diag', 'erplog', 'failfast']:
- kwargs["opts"][attr] = udev.device_get_dasd_flag(self.data, attr)
log.info("%s is a dasd device", udev.device_get_name(self.data))
return kwargs
diff --git a/python-blivet.spec b/python-blivet.spec
index ac8d2841..81177020 100644
--- a/python-blivet.spec
+++ b/python-blivet.spec
@@ -21,6 +21,7 @@ Source1: http://github.com/storaged-project/blivet/archive/%{realname}-%{realver
%global libblockdevver 3.0
%global libbytesizever 0.3
%global pyudevver 0.18
+%global s390utilscorever 2.31.0
BuildArch: noarch
@@ -70,7 +71,7 @@ Recommends: libblockdev-swap >= %{libblockdevver}
%ifarch s390 s390x
Recommends: libblockdev-s390 >= %{libblockdevver}
-Requires: s390utils-core
+Requires: s390utils-core >= %{s390utilscorever}
%endif
Requires: python3-bytesize >= %{libbytesizever}
--
2.45.2

View File

@ -1,23 +0,0 @@
From a21c4fa61f75f6c900f152651308ac9b457a62da Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 23 May 2024 15:31:47 +0200
Subject: [PATCH] Remove support for the MD linear RAID level
The md-linear kernel module is deprecated and will be removed in
the future.
---
blivet/devicelibs/mdraid.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py
index 3b60c87c4..0ef3d0a4f 100644
--- a/blivet/devicelibs/mdraid.py
+++ b/blivet/devicelibs/mdraid.py
@@ -45,6 +45,6 @@ def is_raid_level(cls, level):
hasattr(level, 'get_size')
-raid_levels = MDRaidLevels(["raid0", "raid1", "raid4", "raid5", "raid6", "raid10", "linear"])
+raid_levels = MDRaidLevels(["raid0", "raid1", "raid4", "raid5", "raid6", "raid10"])
EXTERNAL_DEPENDENCIES = [availability.BLOCKDEV_MDRAID_PLUGIN]

View File

@ -1,27 +0,0 @@
From 7677fc312b821a9c67750220f2494d06f2357780 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 18 Sep 2024 15:30:05 +0200
Subject: [PATCH] Fix checking for NVMe plugin availability
---
blivet/nvme.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/blivet/nvme.py b/blivet/nvme.py
index 4309dea3..72a47070 100644
--- a/blivet/nvme.py
+++ b/blivet/nvme.py
@@ -76,6 +76,10 @@ class NVMe(object):
return False
if not hasattr(blockdev.NVMETech, "FABRICS"):
return False
+ try:
+ blockdev.nvme.is_tech_avail(blockdev.NVMETech.FABRICS, 0) # pylint: disable=no-member
+ except (blockdev.BlockDevNotImplementedError, blockdev.NVMEError):
+ return False
return True
def startup(self):
--
2.46.1

View File

@ -1,30 +0,0 @@
From ad7966a456224f22729c55616f2c8c73321654c7 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 24 Oct 2024 12:18:58 +0200
Subject: [PATCH] Align sizes up for growable LVs
Growable LVs usually start at minimum size so adjusting it down
can change the size below allowed minimum.
Resolves: RHEL-45180
Resolves: RHEL-45181
---
blivet/devices/lvm.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 661881ea..661dc6e0 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -2673,7 +2673,7 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
if not isinstance(newsize, Size):
raise AttributeError("new size must be of type Size")
- newsize = self.vg.align(newsize)
+ newsize = self.vg.align(newsize, roundup=self.growable)
log.debug("trying to set lv %s size to %s", self.name, newsize)
# Don't refuse to set size if we think there's not enough space in the
# VG for an existing LV, since it's existence proves there is enough
--
2.47.0

View File

@ -1,32 +0,0 @@
From c2177aa362d20278a0ebd5c25a776f952d83e5b1 Mon Sep 17 00:00:00 2001
From: Jan Pokorny <japokorn@redhat.com>
Date: Fri, 11 Oct 2024 17:17:41 +0200
Subject: [PATCH] Modified passphrase in stratis test
FIPS requires at least 8 chars long passphrase. Dummy passphrase used
in stratis test was too short causing encryption
tests with FIPS enabled to fail.
Changed passphrase.
fixes RHEL-45173, RHEL-8029
---
tests/storage_tests/devices_test/stratis_test.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/storage_tests/devices_test/stratis_test.py b/tests/storage_tests/devices_test/stratis_test.py
index 5aaa12d4..21c4d0f5 100644
--- a/tests/storage_tests/devices_test/stratis_test.py
+++ b/tests/storage_tests/devices_test/stratis_test.py
@@ -230,7 +230,7 @@ class StratisTestCaseClevis(StratisTestCaseBase):
blivet.partitioning.do_partitioning(self.storage)
pool = self.storage.new_stratis_pool(name="blivetTestPool", parents=[bd],
- encrypted=True, passphrase="abcde",
+ encrypted=True, passphrase="fipsneeds8chars",
clevis=StratisClevisConfig(pin="tang",
tang_url=self._tang_server,
tang_thumbprint=None))
--
2.45.0

View File

@ -0,0 +1,35 @@
From 83ccc9f9f14845fcce7a5ba5fa21fbb97b1dbbb7 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 11 Jul 2018 15:36:24 +0200
Subject: [PATCH] Force command line based libblockdev LVM plugin
---
blivet/__init__.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/blivet/__init__.py b/blivet/__init__.py
index dd8d0f54..62cc539a 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -63,11 +63,16 @@ gi.require_version("BlockDev", "2.0")
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"))
+ _REQUESTED_PLUGIN_NAMES = set(("btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "s390", "nvdimm"))
else:
- _REQUESTED_PLUGIN_NAMES = set(("lvm", "btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm"))
+ _REQUESTED_PLUGIN_NAMES = set(("btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm"))
_requested_plugins = blockdev.plugin_specs_from_names(_REQUESTED_PLUGIN_NAMES)
+# XXX force non-dbus LVM plugin
+lvm_plugin = blockdev.PluginSpec()
+lvm_plugin.name = blockdev.Plugin.LVM
+lvm_plugin.so_name = "libbd_lvm.so.2"
+_requested_plugins.append(lvm_plugin)
try:
# do not check for dependencies during libblockdev initializtion, do runtime
# checks instead
--
2.38.1

View File

@ -0,0 +1,28 @@
From c098d4112635b3ea55d5bd7e1817edbd519735fc Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 16 Jul 2018 14:26:11 +0200
Subject: [PATCH] Remove btrfs from requested libblockdev plugins
---
blivet/__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/__init__.py b/blivet/__init__.py
index 62cc539a..bbc7ea3a 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -63,9 +63,9 @@ gi.require_version("BlockDev", "2.0")
from gi.repository import GLib
from gi.repository import BlockDev as blockdev
if arch.is_s390():
- _REQUESTED_PLUGIN_NAMES = set(("btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "s390", "nvdimm"))
+ _REQUESTED_PLUGIN_NAMES = set(("swap", "crypto", "loop", "mdraid", "mpath", "dm", "s390", "nvdimm"))
else:
- _REQUESTED_PLUGIN_NAMES = set(("btrfs", "swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm"))
+ _REQUESTED_PLUGIN_NAMES = set(("swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm"))
_requested_plugins = blockdev.plugin_specs_from_names(_REQUESTED_PLUGIN_NAMES)
# XXX force non-dbus LVM plugin
--
2.38.1

View File

@ -0,0 +1,330 @@
From f6f90805020d7c6ac46f17a13a00f319fc4351f6 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 26 May 2021 12:15:54 +0200
Subject: [PATCH] Revert "More consistent lvm errors (API break)"
This reverts commit 49ec071c6d0673224a0774d613904387c52c7381.
---
blivet/devices/lvm.py | 72 +++++++++++------------
tests/unit_tests/devices_test/lvm_test.py | 14 ++---
2 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 38e49e18..b8595d63 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -304,7 +304,7 @@ class LVMVolumeGroupDevice(ContainerDevice):
def _add_log_vol(self, lv):
""" Add an LV to this VG. """
if lv in self._lvs:
- raise errors.DeviceError("lv is already part of this vg")
+ raise ValueError("lv is already part of this vg")
# verify we have the space, then add it
# do not verify for growing vg (because of ks)
@@ -337,7 +337,7 @@ class LVMVolumeGroupDevice(ContainerDevice):
def _remove_log_vol(self, lv):
""" Remove an LV from this VG. """
if lv not in self.lvs:
- raise errors.DeviceError("specified lv is not part of this vg")
+ raise ValueError("specified lv is not part of this vg")
self._lvs.remove(lv)
@@ -430,7 +430,7 @@ class LVMVolumeGroupDevice(ContainerDevice):
@thpool_reserve.setter
def thpool_reserve(self, value):
if value is not None and not isinstance(value, ThPoolReserveSpec):
- raise AttributeError("Invalid thpool_reserve given, must be of type ThPoolReserveSpec")
+ raise ValueError("Invalid thpool_reserve given, must be of type ThPoolReserveSpec")
self._thpool_reserve = value
@property
@@ -665,14 +665,14 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
if seg_type not in [None, "linear", "thin", "thin-pool", "cache", "vdo-pool", "vdo", "cache-pool"] + lvm.raid_seg_types:
raise ValueError("Invalid or unsupported segment type: %s" % seg_type)
if seg_type and seg_type in lvm.raid_seg_types and not pvs:
- raise errors.DeviceError("List of PVs has to be given for every non-linear LV")
+ raise ValueError("List of PVs has to be given for every non-linear LV")
elif (not seg_type or seg_type == "linear") and pvs:
if not all(isinstance(pv, LVPVSpec) for pv in pvs):
- raise errors.DeviceError("Invalid specification of PVs for a linear LV: either no or complete "
- "specification (with all space split into PVs has to be given")
+ raise ValueError("Invalid specification of PVs for a linear LV: either no or complete "
+ "specification (with all space split into PVs has to be given")
elif sum(spec.size for spec in pvs) != size:
- raise errors.DeviceError("Invalid specification of PVs for a linear LV: the sum of space "
- "assigned to PVs is not equal to the size of the LV")
+ raise ValueError("Invalid specification of PVs for a linear LV: the sum of space "
+ "assigned to PVs is not equal to the size of the LV")
# When this device's format is set in the superclass constructor it will
# try to access self.snapshots.
@@ -721,13 +721,13 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
self._from_lvs = from_lvs
if self._from_lvs:
if exists:
- raise errors.DeviceError("Only new LVs can be created from other LVs")
+ raise ValueError("Only new LVs can be created from other LVs")
if size or maxsize or percent:
- raise errors.DeviceError("Cannot specify size for a converted LV")
+ raise ValueError("Cannot specify size for a converted LV")
if fmt:
- raise errors.DeviceError("Cannot specify format for a converted LV")
+ raise ValueError("Cannot specify format for a converted LV")
if any(lv.vg != self.vg for lv in self._from_lvs):
- raise errors.DeviceError("Conversion of LVs only possible inside a VG")
+ raise ValueError("Conversion of LVs only possible inside a VG")
self._cache = None
if cache_request and not self.exists:
@@ -746,13 +746,13 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
elif isinstance(pv_spec, StorageDevice):
self._pv_specs.append(LVPVSpec(pv_spec, Size(0)))
else:
- raise AttributeError("Invalid PV spec '%s' for the '%s' LV" % (pv_spec, self.name))
+ raise ValueError("Invalid PV spec '%s' for the '%s' LV" % (pv_spec, self.name))
# Make sure any destination PVs are actually PVs in this VG
if not set(spec.pv for spec in self._pv_specs).issubset(set(self.vg.parents)):
missing = [r.name for r in
set(spec.pv for spec in self._pv_specs).difference(set(self.vg.parents))]
msg = "invalid destination PV(s) %s for LV %s" % (missing, self.name)
- raise errors.DeviceError(msg)
+ raise ValueError(msg)
if self._pv_specs:
self._assign_pv_space()
@@ -1130,7 +1130,7 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
else:
msg = "the specified internal LV '%s' doesn't belong to this LV ('%s')" % (int_lv.lv_name,
self.name)
- raise errors.DeviceError(msg)
+ raise ValueError(msg)
def populate_ksdata(self, data):
super(LVMLogicalVolumeBase, self).populate_ksdata(data)
@@ -1229,7 +1229,7 @@ class LVMInternalLogicalVolumeMixin(object):
def _init_check(self):
# an internal LV should have no parents
if self._parent_lv and self._parents:
- raise errors.DeviceError("an internal LV should have no parents")
+ raise ValueError("an internal LV should have no parents")
@property
def is_internal_lv(self):
@@ -1289,7 +1289,7 @@ class LVMInternalLogicalVolumeMixin(object):
@readonly.setter
def readonly(self, value): # pylint: disable=unused-argument
- raise errors.DeviceError("Cannot make an internal LV read-write")
+ raise ValueError("Cannot make an internal LV read-write")
@property
def type(self):
@@ -1325,7 +1325,7 @@ class LVMInternalLogicalVolumeMixin(object):
def _check_parents(self):
# an internal LV should have no parents
if self._parents:
- raise errors.DeviceError("an internal LV should have no parents")
+ raise ValueError("an internal LV should have no parents")
def _add_to_parents(self):
# nothing to do here, an internal LV has no parents (in the DeviceTree's
@@ -1335,13 +1335,13 @@ class LVMInternalLogicalVolumeMixin(object):
# internal LVs follow different rules limitting size
def _set_size(self, newsize):
if not isinstance(newsize, Size):
- raise AttributeError("new size must of type Size")
+ raise ValueError("new size must of type Size")
if not self.takes_extra_space:
if newsize <= self.parent_lv.size: # pylint: disable=no-member
self._size = newsize # pylint: disable=attribute-defined-outside-init
else:
- raise errors.DeviceError("Internal LV cannot be bigger than its parent LV")
+ raise ValueError("Internal LV cannot be bigger than its parent LV")
else:
# same rules apply as for any other LV
raise NotTypeSpecific()
@@ -1419,18 +1419,18 @@ class LVMSnapshotMixin(object):
return
if self.origin and not isinstance(self.origin, LVMLogicalVolumeDevice):
- raise errors.DeviceError("lvm snapshot origin must be a logical volume")
+ raise ValueError("lvm snapshot origin must be a logical volume")
if self.vorigin and not self.exists:
- raise errors.DeviceError("only existing vorigin snapshots are supported")
+ raise ValueError("only existing vorigin snapshots are supported")
if isinstance(self.origin, LVMLogicalVolumeDevice) and \
isinstance(self.parents[0], LVMVolumeGroupDevice) and \
self.origin.vg != self.parents[0]:
- raise errors.DeviceError("lvm snapshot and origin must be in the same vg")
+ raise ValueError("lvm snapshot and origin must be in the same vg")
if self.is_thin_lv:
if self.origin and self.size and not self.exists:
- raise errors.DeviceError("thin snapshot size is determined automatically")
+ raise ValueError("thin snapshot size is determined automatically")
@property
def is_snapshot_lv(self):
@@ -1606,7 +1606,7 @@ class LVMThinPoolMixin(object):
def _check_from_lvs(self):
if self._from_lvs:
if len(self._from_lvs) != 2:
- raise errors.DeviceError("two LVs required to create a thin pool")
+ raise ValueError("two LVs required to create a thin pool")
def _convert_from_lvs(self):
data_lv, metadata_lv = self._from_lvs
@@ -1652,7 +1652,7 @@ class LVMThinPoolMixin(object):
def _add_log_vol(self, lv):
""" Add an LV to this pool. """
if lv in self._lvs:
- raise errors.DeviceError("lv is already part of this vg")
+ raise ValueError("lv is already part of this vg")
# TODO: add some checking to prevent overcommit for preexisting
self.vg._add_log_vol(lv)
@@ -1663,7 +1663,7 @@ class LVMThinPoolMixin(object):
def _remove_log_vol(self, lv):
""" Remove an LV from this pool. """
if lv not in self._lvs:
- raise errors.DeviceError("specified lv is not part of this vg")
+ raise ValueError("specified lv is not part of this vg")
self._lvs.remove(lv)
self.vg._remove_log_vol(lv)
@@ -1772,14 +1772,14 @@ class LVMThinLogicalVolumeMixin(object):
"""Check that this device has parents as expected"""
if isinstance(self.parents, (list, ParentList)):
if len(self.parents) != 1:
- raise errors.DeviceError("constructor requires a single thin-pool LV")
+ raise ValueError("constructor requires a single thin-pool LV")
container = self.parents[0]
else:
container = self.parents
if not container or not isinstance(container, LVMLogicalVolumeDevice) or not container.is_thin_pool:
- raise errors.DeviceError("constructor requires a thin-pool LV")
+ raise ValueError("constructor requires a thin-pool LV")
@property
def is_thin_lv(self):
@@ -1816,7 +1816,7 @@ class LVMThinLogicalVolumeMixin(object):
def _set_size(self, newsize):
if not isinstance(newsize, Size):
- raise AttributeError("new size must of type Size")
+ raise ValueError("new size must of type Size")
newsize = self.vg.align(newsize)
newsize = self.vg.align(util.numeric_type(newsize))
@@ -2499,7 +2499,7 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
container = self.parents
if not isinstance(container, LVMVolumeGroupDevice):
- raise AttributeError("constructor requires a LVMVolumeGroupDevice")
+ raise ValueError("constructor requires a LVMVolumeGroupDevice")
@type_specific
def _add_to_parents(self):
@@ -2510,12 +2510,12 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
@type_specific
def _check_from_lvs(self):
"""Check the LVs to create this LV from"""
- raise errors.DeviceError("Cannot create a new LV of type '%s' from other LVs" % self.seg_type)
+ raise ValueError("Cannot create a new LV of type '%s' from other LVs" % self.seg_type)
@type_specific
def _convert_from_lvs(self):
"""Convert the LVs to create this LV from into its internal LVs"""
- raise errors.DeviceError("Cannot create a new LV of type '%s' from other LVs" % self.seg_type)
+ raise ValueError("Cannot create a new LV of type '%s' from other LVs" % self.seg_type)
@property
def external_dependencies(self):
@@ -2535,7 +2535,7 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
@type_specific
def _set_size(self, newsize):
if not isinstance(newsize, Size):
- raise AttributeError("new size must be of type Size")
+ raise ValueError("new size must be of type Size")
newsize = self.vg.align(newsize)
log.debug("trying to set lv %s size to %s", self.name, newsize)
@@ -2544,7 +2544,7 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
# space for it. A similar reasoning applies to shrinking the LV.
if not self.exists and newsize > self.size and newsize > self.vg.free_space + self.vg_space_used:
log.error("failed to set size: %s short", newsize - (self.vg.free_space + self.vg_space_used))
- raise errors.DeviceError("not enough free space in volume group")
+ raise ValueError("not enough free space in volume group")
LVMLogicalVolumeBase._set_size(self, newsize)
@@ -2910,7 +2910,7 @@ class LVMCache(Cache):
spec.size = spec.pv.format.free
space_to_assign -= spec.pv.format.free
if space_to_assign > 0:
- raise errors.DeviceError("Not enough free space in the PVs for this cache: %s short" % space_to_assign)
+ raise ValueError("Not enough free space in the PVs for this cache: %s short" % space_to_assign)
@property
def size(self):
diff --git a/tests/unit_tests/devices_test/lvm_test.py b/tests/unit_tests/devices_test/lvm_test.py
index 47613fdc..995c2da4 100644
--- a/tests/unit_tests/devices_test/lvm_test.py
+++ b/tests/unit_tests/devices_test/lvm_test.py
@@ -32,10 +32,10 @@ class LVMDeviceTest(unittest.TestCase):
lv = LVMLogicalVolumeDevice("testlv", parents=[vg],
fmt=blivet.formats.get_format("xfs"))
- with six.assertRaisesRegex(self, errors.DeviceError, "lvm snapshot origin must be a logical volume"):
+ with six.assertRaisesRegex(self, ValueError, "lvm snapshot origin must be a logical volume"):
LVMLogicalVolumeDevice("snap1", parents=[vg], origin=pv)
- with six.assertRaisesRegex(self, errors.DeviceError, "only existing vorigin snapshots are supported"):
+ with six.assertRaisesRegex(self, ValueError, "only existing vorigin snapshots are supported"):
LVMLogicalVolumeDevice("snap1", parents=[vg], vorigin=True)
lv.exists = True
@@ -60,7 +60,7 @@ class LVMDeviceTest(unittest.TestCase):
pool = LVMLogicalVolumeDevice("pool1", parents=[vg], size=Size("500 MiB"), seg_type="thin-pool")
thinlv = LVMLogicalVolumeDevice("thinlv", parents=[pool], size=Size("200 MiB"), seg_type="thin")
- with six.assertRaisesRegex(self, errors.DeviceError, "lvm snapshot origin must be a logical volume"):
+ with six.assertRaisesRegex(self, ValueError, "lvm snapshot origin must be a logical volume"):
LVMLogicalVolumeDevice("snap1", parents=[pool], origin=pv, seg_type="thin")
# now make the constructor succeed so we can test some properties
@@ -310,21 +310,21 @@ class LVMDeviceTest(unittest.TestCase):
vg = LVMVolumeGroupDevice("testvg", parents=[pv, pv2])
# pvs have to be specified for non-linear LVs
- with self.assertRaises(errors.DeviceError):
+ with self.assertRaises(ValueError):
lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("512 MiB"),
fmt=blivet.formats.get_format("xfs"),
exists=False, seg_type="raid1")
- with self.assertRaises(errors.DeviceError):
+ with self.assertRaises(ValueError):
lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("512 MiB"),
fmt=blivet.formats.get_format("xfs"),
exists=False, seg_type="striped")
# no or complete specification has to be given for linear LVs
- with self.assertRaises(errors.DeviceError):
+ with self.assertRaises(ValueError):
lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("512 MiB"),
fmt=blivet.formats.get_format("xfs"),
exists=False, pvs=[pv])
- with self.assertRaises(errors.DeviceError):
+ with self.assertRaises(ValueError):
pv_spec = LVPVSpec(pv, Size("256 MiB"))
pv_spec2 = LVPVSpec(pv2, Size("250 MiB"))
lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("512 MiB"),
--
2.38.1

View File

@ -0,0 +1,899 @@
From d8a8d96450bf0d3458671b9b7d23d972aa540396 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 26 May 2021 12:27:34 +0200
Subject: [PATCH] Revert "Terminology cleanups"
This reverts following commits:
- 3d46339fe9cf12e9082fcbe4dc5acc9f92617e8d
- 63c9c7165e5cdfa4a47dcf0ed9d717b71e7921f2
- 8956b9af8a785ae25e0e7153d2ef0702ce2f567c
---
blivet/devicefactory.py | 24 +++----
blivet/devices/dm.py | 9 ++-
blivet/devices/loop.py | 20 +++---
blivet/devices/luks.py | 26 ++++---
blivet/errors.py | 2 +-
blivet/partitioning.py | 22 +++++-
blivet/populator/helpers/dm.py | 4 +-
blivet/populator/helpers/luks.py | 4 +-
blivet/populator/helpers/lvm.py | 2 +-
blivet/populator/helpers/mdraid.py | 14 ++--
blivet/populator/helpers/multipath.py | 8 +--
blivet/populator/populator.py | 67 ++++++++++---------
blivet/threads.py | 3 +-
blivet/udev.py | 34 +++++-----
tests/unit_tests/devicefactory_test.py | 10 +--
.../devices_test/device_size_test.py | 6 +-
tests/unit_tests/populator_test.py | 34 +++++-----
tests/unit_tests/udev_test.py | 12 ++--
tests/vmtests/vmbackedtestcase.py | 2 +-
19 files changed, 167 insertions(+), 136 deletions(-)
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py
index 6f460f6d..90082c28 100644
--- a/blivet/devicefactory.py
+++ b/blivet/devicefactory.py
@@ -859,12 +859,12 @@ class DeviceFactory(object):
parent_container.parents.remove(orig_device)
if self.encrypted and isinstance(self.device, LUKSDevice) and \
- self.raw_device.format.luks_version != self.luks_version:
- self.raw_device.format.luks_version = self.luks_version
+ self.device.slave.format.luks_version != self.luks_version:
+ self.device.slave.format.luks_version = self.luks_version
if self.encrypted and isinstance(self.device, LUKSDevice) and \
- self.raw_device.format.luks_sector_size != self.luks_sector_size:
- self.raw_device.format.luks_sector_size = self.luks_sector_size
+ self.device.slave.format.luks_sector_size != self.luks_sector_size:
+ self.device.slave.format.luks_sector_size = self.luks_sector_size
def _set_name(self):
if not self.device_name:
@@ -1201,11 +1201,11 @@ class PartitionSetFactory(PartitionFactory):
container.parents.remove(member)
self.storage.destroy_device(member)
members.remove(member)
- self.storage.format_device(member.raw_device,
+ self.storage.format_device(member.slave,
get_format(self.fstype))
- members.append(member.raw_device)
+ members.append(member.slave)
if container:
- container.parents.append(member.raw_device)
+ container.parents.append(member.slave)
continue
@@ -1227,10 +1227,10 @@ class PartitionSetFactory(PartitionFactory):
continue
- if member_encrypted and self.encrypted and self.luks_version != member.raw_device.format.luks_version:
- member.raw_device.format.luks_version = self.luks_version
- if member_encrypted and self.encrypted and self.luks_sector_size != member.raw_device.format.luks_sector_size:
- member.raw_device.format.luks_sector_size = self.luks_sector_size
+ if member_encrypted and self.encrypted and self.luks_version != member.slave.format.luks_version:
+ member.slave.format.luks_version = self.luks_version
+ if member_encrypted and self.encrypted and self.luks_sector_size != member.slave.format.luks_sector_size:
+ member.slave.format.luks_sector_size = self.luks_sector_size
##
# Prepare previously allocated member partitions for reallocation.
@@ -1290,7 +1290,7 @@ class PartitionSetFactory(PartitionFactory):
if isinstance(member, LUKSDevice):
self.storage.destroy_device(member)
- member = member.raw_device
+ member = member.slave
self.storage.destroy_device(member)
diff --git a/blivet/devices/dm.py b/blivet/devices/dm.py
index 2f936170..ae25e8e6 100644
--- a/blivet/devices/dm.py
+++ b/blivet/devices/dm.py
@@ -154,6 +154,11 @@ class DMDevice(StorageDevice):
log_method_call(self, self.name, status=self.status)
super(DMDevice, self)._set_name(value)
+ @property
+ def slave(self):
+ """ This device's backing device. """
+ return self.parents[0]
+
class DMLinearDevice(DMDevice):
_type = "dm-linear"
@@ -189,8 +194,8 @@ class DMLinearDevice(DMDevice):
""" Open, or set up, a device. """
log_method_call(self, self.name, orig=orig, status=self.status,
controllable=self.controllable)
- parent_length = self.parents[0].current_size / LINUX_SECTOR_SIZE
- blockdev.dm.create_linear(self.name, self.parents[0].path, parent_length,
+ slave_length = self.slave.current_size / LINUX_SECTOR_SIZE
+ blockdev.dm.create_linear(self.name, self.slave.path, slave_length,
self.dm_uuid)
def _post_setup(self):
diff --git a/blivet/devices/loop.py b/blivet/devices/loop.py
index 0f4d7775..78f88d7d 100644
--- a/blivet/devices/loop.py
+++ b/blivet/devices/loop.py
@@ -73,7 +73,7 @@ class LoopDevice(StorageDevice):
def update_name(self):
""" Update this device's name. """
- if not self.parents[0].status:
+ if not self.slave.status:
# if the backing device is inactive, so are we
return self.name
@@ -81,7 +81,7 @@ class LoopDevice(StorageDevice):
# if our name is loopN we must already be active
return self.name
- name = blockdev.loop.get_loop_name(self.parents[0].path)
+ name = blockdev.loop.get_loop_name(self.slave.path)
if name.startswith("loop"):
self.name = name
@@ -89,24 +89,24 @@ class LoopDevice(StorageDevice):
@property
def status(self):
- return (self.parents[0].status and
+ return (self.slave.status and
self.name.startswith("loop") and
- blockdev.loop.get_loop_name(self.parents[0].path) == self.name)
+ blockdev.loop.get_loop_name(self.slave.path) == self.name)
@property
def size(self):
- return self.parents[0].size
+ return self.slave.size
def _pre_setup(self, orig=False):
- if not os.path.exists(self.parents[0].path):
- raise errors.DeviceError("specified file (%s) does not exist" % self.parents[0].path)
+ if not os.path.exists(self.slave.path):
+ raise errors.DeviceError("specified file (%s) does not exist" % self.slave.path)
return StorageDevice._pre_setup(self, orig=orig)
def _setup(self, orig=False):
""" Open, or set up, a device. """
log_method_call(self, self.name, orig=orig, status=self.status,
controllable=self.controllable)
- blockdev.loop.setup(self.parents[0].path)
+ blockdev.loop.setup(self.slave.path)
def _post_setup(self):
StorageDevice._post_setup(self)
@@ -123,3 +123,7 @@ class LoopDevice(StorageDevice):
StorageDevice._post_teardown(self, recursive=recursive)
self.name = "tmploop%d" % self.id
self.sysfs_path = ''
+
+ @property
+ def slave(self):
+ return self.parents[0]
diff --git a/blivet/devices/luks.py b/blivet/devices/luks.py
index 2eb1f130..5ab840ea 100644
--- a/blivet/devices/luks.py
+++ b/blivet/devices/luks.py
@@ -66,13 +66,17 @@ class LUKSDevice(DMCryptDevice):
@property
def raw_device(self):
+ return self.slave
+
+ @property
+ def slave(self):
if self._has_integrity:
return self.parents[0].parents[0]
return self.parents[0]
def _get_size(self):
if not self.exists:
- size = self.raw_device.size - crypto.LUKS_METADATA_SIZE
+ size = self.slave.size - crypto.LUKS_METADATA_SIZE
elif self.resizable and self.target_size != Size(0):
size = self.target_size
else:
@@ -80,8 +84,8 @@ class LUKSDevice(DMCryptDevice):
return size
def _set_size(self, newsize):
- if not self.exists and not self.raw_device.exists:
- self.raw_device.size = newsize + crypto.LUKS_METADATA_SIZE
+ if not self.exists and not self.slave.exists:
+ self.slave.size = newsize + crypto.LUKS_METADATA_SIZE
# just run the StorageDevice._set_size to make sure we are in the format limits
super(LUKSDevice, self)._set_size(newsize - crypto.LUKS_METADATA_SIZE)
@@ -108,22 +112,22 @@ class LUKSDevice(DMCryptDevice):
raise ValueError("size is smaller than the minimum for this device")
# don't allow larger luks than size (or target size) of backing device
- if newsize > (self.raw_device.size - crypto.LUKS_METADATA_SIZE):
+ if newsize > (self.slave.size - crypto.LUKS_METADATA_SIZE):
log.error("requested size %s is larger than size of the backing device %s",
- newsize, self.raw_device.size)
+ newsize, self.slave.size)
raise ValueError("size is larger than the size of the backing device")
if self.align_target_size(newsize) != newsize:
raise ValueError("new size would violate alignment requirements")
def _get_target_size(self):
- return self.raw_device.format.target_size
+ return self.slave.format.target_size
@property
def max_size(self):
""" The maximum size this luks device can be. Maximum is based on the
maximum size of the backing device. """
- max_luks = self.raw_device.max_size - crypto.LUKS_METADATA_SIZE
+ max_luks = self.slave.max_size - crypto.LUKS_METADATA_SIZE
max_format = self.format.max_size
return min(max_luks, max_format) if max_format else max_luks
@@ -131,7 +135,7 @@ class LUKSDevice(DMCryptDevice):
def resizable(self):
""" Can this device be resized? """
return (self._resizable and self.exists and self.format.resizable and
- self.raw_device.resizable and not self._has_integrity)
+ self.slave.resizable and not self._has_integrity)
def resize(self):
# size of LUKSDevice depends on size of the LUKS format on backing
@@ -139,7 +143,7 @@ class LUKSDevice(DMCryptDevice):
log_method_call(self, self.name, status=self.status)
def _post_create(self):
- self.name = self.raw_device.format.map_name
+ self.name = self.slave.format.map_name
StorageDevice._post_create(self)
def _post_teardown(self, recursive=False):
@@ -162,10 +166,10 @@ class LUKSDevice(DMCryptDevice):
self.name = new_name
def dracut_setup_args(self):
- return set(["rd.luks.uuid=luks-%s" % self.raw_device.format.uuid])
+ return set(["rd.luks.uuid=luks-%s" % self.slave.format.uuid])
def populate_ksdata(self, data):
- self.raw_device.populate_ksdata(data)
+ self.slave.populate_ksdata(data)
data.encrypted = True
super(LUKSDevice, self).populate_ksdata(data)
diff --git a/blivet/errors.py b/blivet/errors.py
index b886ffec..30c9921a 100644
--- a/blivet/errors.py
+++ b/blivet/errors.py
@@ -201,7 +201,7 @@ class DeviceTreeError(StorageError):
pass
-class NoParentsError(DeviceTreeError):
+class NoSlavesError(DeviceTreeError):
pass
diff --git a/blivet/partitioning.py b/blivet/partitioning.py
index ce77e4eb..2cd6554c 100644
--- a/blivet/partitioning.py
+++ b/blivet/partitioning.py
@@ -32,7 +32,7 @@ import _ped
from .errors import DeviceError, PartitioningError, AlignmentError
from .flags import flags
-from .devices import Device, PartitionDevice, device_path_to_name
+from .devices import Device, PartitionDevice, LUKSDevice, device_path_to_name
from .size import Size
from .i18n import _
from .util import stringize, unicodeize, compare
@@ -1635,7 +1635,15 @@ class TotalSizeSet(object):
:param size: the target combined size
:type size: :class:`~.size.Size`
"""
- self.devices = [d.raw_device for d in devices]
+ self.devices = []
+ for device in devices:
+ if isinstance(device, LUKSDevice):
+ partition = device.slave
+ else:
+ partition = device
+
+ self.devices.append(partition)
+
self.size = size
self.requests = []
@@ -1673,7 +1681,15 @@ class SameSizeSet(object):
:keyword max_size: the maximum size for growable devices
:type max_size: :class:`~.size.Size`
"""
- self.devices = [d.raw_device for d in devices]
+ self.devices = []
+ for device in devices:
+ if isinstance(device, LUKSDevice):
+ partition = device.slave
+ else:
+ partition = device
+
+ self.devices.append(partition)
+
self.size = size / len(devices)
self.grow = grow
self.max_size = max_size
diff --git a/blivet/populator/helpers/dm.py b/blivet/populator/helpers/dm.py
index 4721390e..0ad065e2 100644
--- a/blivet/populator/helpers/dm.py
+++ b/blivet/populator/helpers/dm.py
@@ -47,13 +47,13 @@ class DMDevicePopulator(DevicePopulator):
name = udev.device_get_name(self.data)
log_method_call(self, name=name)
sysfs_path = udev.device_get_sysfs_path(self.data)
- parent_devices = self._devicetree._add_parent_devices(self.data)
+ slave_devices = self._devicetree._add_slave_devices(self.data)
device = self._devicetree.get_device_by_name(name)
if device is None:
device = DMDevice(name, dm_uuid=self.data.get('DM_UUID'),
sysfs_path=sysfs_path, exists=True,
- parents=[parent_devices[0]])
+ parents=[slave_devices[0]])
device.protected = True
device.controllable = False
self._devicetree._add_device(device)
diff --git a/blivet/populator/helpers/luks.py b/blivet/populator/helpers/luks.py
index 3221122a..9b5023f8 100644
--- a/blivet/populator/helpers/luks.py
+++ b/blivet/populator/helpers/luks.py
@@ -43,7 +43,7 @@ class LUKSDevicePopulator(DevicePopulator):
return udev.device_is_dm_luks(data)
def run(self):
- parents = self._devicetree._add_parent_devices(self.data)
+ parents = self._devicetree._add_slave_devices(self.data)
device = LUKSDevice(udev.device_get_name(self.data),
sysfs_path=udev.device_get_sysfs_path(self.data),
parents=parents,
@@ -58,7 +58,7 @@ class IntegrityDevicePopulator(DevicePopulator):
return udev.device_is_dm_integrity(data)
def run(self):
- parents = self._devicetree._add_parent_devices(self.data)
+ parents = self._devicetree._add_slave_devices(self.data)
name = udev.device_get_name(self.data)
try:
diff --git a/blivet/populator/helpers/lvm.py b/blivet/populator/helpers/lvm.py
index 6ef2f417..b549e8d3 100644
--- a/blivet/populator/helpers/lvm.py
+++ b/blivet/populator/helpers/lvm.py
@@ -58,7 +58,7 @@ class LVMDevicePopulator(DevicePopulator):
log.warning("found non-vg device with name %s", vg_name)
device = None
- self._devicetree._add_parent_devices(self.data)
+ self._devicetree._add_slave_devices(self.data)
# LVM provides no means to resolve conflicts caused by duplicated VG
# names, so we're just being optimistic here. Woo!
diff --git a/blivet/populator/helpers/mdraid.py b/blivet/populator/helpers/mdraid.py
index a7602d20..9bec11ef 100644
--- a/blivet/populator/helpers/mdraid.py
+++ b/blivet/populator/helpers/mdraid.py
@@ -31,7 +31,7 @@ from ... import udev
from ...devicelibs import raid
from ...devices import MDRaidArrayDevice, MDContainerDevice
from ...devices import device_path_to_name
-from ...errors import DeviceError, NoParentsError
+from ...errors import DeviceError, NoSlavesError
from ...flags import flags
from ...storage_log import log_method_call
from .devicepopulator import DevicePopulator
@@ -52,12 +52,12 @@ class MDDevicePopulator(DevicePopulator):
log_method_call(self, name=name)
try:
- self._devicetree._add_parent_devices(self.data)
- except NoParentsError:
- log.error("no parents found for mdarray %s, skipping", name)
+ self._devicetree._add_slave_devices(self.data)
+ except NoSlavesError:
+ log.error("no slaves found for mdarray %s, skipping", name)
return None
- # try to get the device again now that we've got all the parents
+ # try to get the device again now that we've got all the slaves
device = self._devicetree.get_device_by_name(name, incomplete=flags.allow_imperfect_devices)
if device is None:
@@ -74,8 +74,8 @@ class MDDevicePopulator(DevicePopulator):
device.name = name
if device is None:
- # if we get here, we found all of the parent devices and
- # something must be wrong -- if all of the parents are in
+ # if we get here, we found all of the slave devices and
+ # something must be wrong -- if all of the slaves are in
# the tree, this device should be as well
if name is None:
name = udev.device_get_name(self.data)
diff --git a/blivet/populator/helpers/multipath.py b/blivet/populator/helpers/multipath.py
index 96c0a9ad..10c745bf 100644
--- a/blivet/populator/helpers/multipath.py
+++ b/blivet/populator/helpers/multipath.py
@@ -40,13 +40,13 @@ class MultipathDevicePopulator(DevicePopulator):
name = udev.device_get_name(self.data)
log_method_call(self, name=name)
- parent_devices = self._devicetree._add_parent_devices(self.data)
+ slave_devices = self._devicetree._add_slave_devices(self.data)
device = None
- if parent_devices:
- device = MultipathDevice(name, parents=parent_devices,
+ if slave_devices:
+ device = MultipathDevice(name, parents=slave_devices,
sysfs_path=udev.device_get_sysfs_path(self.data),
- wwn=parent_devices[0].wwn)
+ wwn=slave_devices[0].wwn)
self._devicetree._add_device(device)
return device
diff --git a/blivet/populator/populator.py b/blivet/populator/populator.py
index 3a419418..068270b2 100644
--- a/blivet/populator/populator.py
+++ b/blivet/populator/populator.py
@@ -31,7 +31,7 @@ gi.require_version("BlockDev", "2.0")
from gi.repository import BlockDev as blockdev
-from ..errors import DeviceError, DeviceTreeError, NoParentsError
+from ..errors import DeviceError, DeviceTreeError, NoSlavesError
from ..devices import DMLinearDevice, DMRaidArrayDevice
from ..devices import FileDevice, LoopDevice
from ..devices import MDRaidArrayDevice
@@ -92,55 +92,56 @@ class PopulatorMixin(object):
self._cleanup = False
- def _add_parent_devices(self, info):
- """ Add all parents of a device, raising DeviceTreeError on failure.
+ def _add_slave_devices(self, info):
+ """ Add all slaves of a device, raising DeviceTreeError on failure.
:param :class:`pyudev.Device` info: the device's udev info
- :raises: :class:`~.errors.DeviceTreeError if no parents are found or
- if we fail to add any parent
- :returns: a list of parent devices
+ :raises: :class:`~.errors.DeviceTreeError if no slaves are found or
+ if we fail to add any slave
+ :returns: a list of slave devices
:rtype: list of :class:`~.StorageDevice`
"""
name = udev.device_get_name(info)
sysfs_path = udev.device_get_sysfs_path(info)
- parent_dir = os.path.normpath("%s/slaves" % sysfs_path)
- parent_names = os.listdir(parent_dir)
- parent_devices = []
- if not parent_names:
- log.error("no parents found for %s", name)
- raise NoParentsError("no parents found for device %s" % name)
-
- for parent_name in parent_names:
- path = os.path.normpath("%s/%s" % (parent_dir, parent_name))
- parent_info = udev.get_device(os.path.realpath(path))
-
- if not parent_info:
- msg = "unable to get udev info for %s" % parent_name
+ slave_dir = os.path.normpath("%s/slaves" % sysfs_path)
+ slave_names = os.listdir(slave_dir)
+ slave_devices = []
+ if not slave_names:
+ log.error("no slaves found for %s", name)
+ raise NoSlavesError("no slaves found for device %s" % name)
+
+ for slave_name in slave_names:
+ path = os.path.normpath("%s/%s" % (slave_dir, slave_name))
+ slave_info = udev.get_device(os.path.realpath(path))
+
+ if not slave_info:
+ msg = "unable to get udev info for %s" % slave_name
raise DeviceTreeError(msg)
# cciss in sysfs is "cciss!cXdYpZ" but we need "cciss/cXdYpZ"
- parent_name = udev.device_get_name(parent_info).replace("!", "/")
-
- parent_dev = self.get_device_by_name(parent_name)
- if not parent_dev and parent_info:
- # we haven't scanned the parent yet, so do it now
- self.handle_device(parent_info)
- parent_dev = self.get_device_by_name(parent_name)
- if parent_dev is None:
+ slave_name = udev.device_get_name(slave_info).replace("!", "/")
+
+ slave_dev = self.get_device_by_name(slave_name)
+ if not slave_dev and slave_info:
+ # we haven't scanned the slave yet, so do it now
+ self.handle_device(slave_info)
+ slave_dev = self.get_device_by_name(slave_name)
+ if slave_dev is None:
if udev.device_is_dm_lvm(info):
- if parent_name not in lvs_info.cache:
+ if slave_name not in lvs_info.cache:
# we do not expect hidden lvs to be in the tree
continue
- # if the current parent is still not in
+ # if the current slave is still not in
# the tree, something has gone wrong
- log.error("failure scanning device %s: could not add parent %s", name, parent_name)
- msg = "failed to add parent %s of device %s" % (parent_name, name)
+ log.error("failure scanning device %s: could not add slave %s", name, slave_name)
+ msg = "failed to add slave %s of device %s" % (slave_name,
+ name)
raise DeviceTreeError(msg)
- parent_devices.append(parent_dev)
+ slave_devices.append(slave_dev)
- return parent_devices
+ return slave_devices
def _add_name(self, name):
if name not in self.names:
diff --git a/blivet/threads.py b/blivet/threads.py
index 5e2dff3f..1a5cc6db 100644
--- a/blivet/threads.py
+++ b/blivet/threads.py
@@ -63,11 +63,12 @@ class SynchronizedMeta(type):
"""
def __new__(cls, name, bases, dct):
new_dct = {}
+ blacklist = dct.get('_unsynchronized_methods', [])
for n in dct:
obj = dct[n]
# Do not decorate class or static methods.
- if n in dct.get('_unsynchronized_methods', []):
+ if n in blacklist:
pass
elif isinstance(obj, FunctionType):
obj = exclusive(obj)
diff --git a/blivet/udev.py b/blivet/udev.py
index efbc53d6..ddc49a37 100644
--- a/blivet/udev.py
+++ b/blivet/udev.py
@@ -39,7 +39,7 @@ from gi.repository import BlockDev as blockdev
global_udev = pyudev.Context()
log = logging.getLogger("blivet")
-ignored_device_names = []
+device_name_blacklist = []
""" device name regexes to ignore; this should be empty by default """
@@ -77,7 +77,7 @@ def get_devices(subsystem="block"):
result = []
for device in global_udev.list_devices(subsystem=subsystem):
- if not __is_ignored_blockdev(device.sys_name):
+ if not __is_blacklisted_blockdev(device.sys_name):
dev = device_to_dict(device)
result.append(dev)
@@ -176,13 +176,13 @@ def resolve_glob(glob):
return ret
-def __is_ignored_blockdev(dev_name):
+def __is_blacklisted_blockdev(dev_name):
"""Is this a blockdev we never want for an install?"""
if dev_name.startswith("ram") or dev_name.startswith("fd"):
return True
- if ignored_device_names:
- if any(re.search(expr, dev_name) for expr in ignored_device_names):
+ if device_name_blacklist:
+ if any(re.search(expr, dev_name) for expr in device_name_blacklist):
return True
dev_path = "/sys/class/block/%s" % dev_name
@@ -375,7 +375,7 @@ def device_is_disk(info):
device_is_dm_crypt(info) or
device_is_dm_stratis(info) or
(device_is_md(info) and
- (not device_get_md_container(info) and not all(device_is_disk(d) for d in device_get_parents(info))))))
+ (not device_get_md_container(info) and not all(device_is_disk(d) for d in device_get_slaves(info))))))
def device_is_partition(info):
@@ -454,18 +454,18 @@ def device_get_devname(info):
return info.get('DEVNAME')
-def device_get_parents(info):
- """ Return a list of udev device objects representing this device's parents. """
- parents_dir = device_get_sysfs_path(info) + "/slaves/"
+def device_get_slaves(info):
+ """ Return a list of udev device objects representing this device's slaves. """
+ slaves_dir = device_get_sysfs_path(info) + "/slaves/"
names = list()
- if os.path.isdir(parents_dir):
- names = os.listdir(parents_dir)
+ if os.path.isdir(slaves_dir):
+ names = os.listdir(slaves_dir)
- parents = list()
+ slaves = list()
for name in names:
- parents.append(get_device(device_node="/dev/" + name))
+ slaves.append(get_device(device_node="/dev/" + name))
- return parents
+ return slaves
def device_get_holders(info):
@@ -742,7 +742,7 @@ def device_get_partition_disk(info):
disk = None
majorminor = info.get("ID_PART_ENTRY_DISK")
sysfs_path = device_get_sysfs_path(info)
- parents_dir = "%s/slaves" % sysfs_path
+ slaves_dir = "%s/slaves" % sysfs_path
if majorminor:
major, minor = majorminor.split(":")
for device in get_devices():
@@ -750,8 +750,8 @@ def device_get_partition_disk(info):
disk = device_get_name(device)
break
elif device_is_dm_partition(info):
- if os.path.isdir(parents_dir):
- parents = os.listdir(parents_dir)
+ if os.path.isdir(slaves_dir):
+ parents = os.listdir(slaves_dir)
if len(parents) == 1:
disk = resolve_devspec(parents[0].replace('!', '/'))
else:
diff --git a/tests/unit_tests/devicefactory_test.py b/tests/unit_tests/devicefactory_test.py
index ff6bcb9e..552aadc1 100644
--- a/tests/unit_tests/devicefactory_test.py
+++ b/tests/unit_tests/devicefactory_test.py
@@ -115,9 +115,9 @@ class DeviceFactoryTestCase(unittest.TestCase):
kwargs.get("encrypted", False) or
kwargs.get("container_encrypted", False))
if kwargs.get("encrypted", False):
- self.assertEqual(device.parents[0].format.luks_version,
+ self.assertEqual(device.slave.format.luks_version,
kwargs.get("luks_version", crypto.DEFAULT_LUKS_VERSION))
- self.assertEqual(device.raw_device.format.luks_sector_size,
+ self.assertEqual(device.slave.format.luks_sector_size,
kwargs.get("luks_sector_size", 0))
self.assertTrue(set(device.disks).issubset(kwargs["disks"]))
@@ -357,7 +357,7 @@ class LVMFactoryTestCase(DeviceFactoryTestCase):
device = args[0]
if kwargs.get("encrypted"):
- container = device.parents[0].container
+ container = device.slave.container
else:
container = device.container
@@ -376,7 +376,7 @@ class LVMFactoryTestCase(DeviceFactoryTestCase):
self.assertIsInstance(pv, member_class)
if pv.encrypted:
- self.assertEqual(pv.parents[0].format.luks_version,
+ self.assertEqual(pv.slave.format.luks_version,
kwargs.get("luks_version", crypto.DEFAULT_LUKS_VERSION))
@patch("blivet.formats.lvmpv.LVMPhysicalVolume.formattable", return_value=True)
@@ -592,7 +592,7 @@ class LVMThinPFactoryTestCase(LVMFactoryTestCase):
device = args[0]
if kwargs.get("encrypted", False):
- thinlv = device.parents[0]
+ thinlv = device.slave
else:
thinlv = device
diff --git a/tests/unit_tests/devices_test/device_size_test.py b/tests/unit_tests/devices_test/device_size_test.py
index d0c0a3f4..a1efa86d 100644
--- a/tests/unit_tests/devices_test/device_size_test.py
+++ b/tests/unit_tests/devices_test/device_size_test.py
@@ -107,8 +107,8 @@ class LUKSDeviceSizeTest(StorageDeviceSizeTest):
def _get_device(self, *args, **kwargs):
exists = kwargs.get("exists", False)
- parent = StorageDevice(*args, size=kwargs["size"] + crypto.LUKS_METADATA_SIZE, exists=exists)
- return LUKSDevice(*args, **kwargs, parents=[parent])
+ slave = StorageDevice(*args, size=kwargs["size"] + crypto.LUKS_METADATA_SIZE, exists=exists)
+ return LUKSDevice(*args, **kwargs, parents=[slave])
def test_size_getter(self):
initial_size = Size("10 GiB")
@@ -116,4 +116,4 @@ class LUKSDeviceSizeTest(StorageDeviceSizeTest):
# for LUKS size depends on the backing device size
self.assertEqual(dev.size, initial_size)
- self.assertEqual(dev.raw_device.size, initial_size + crypto.LUKS_METADATA_SIZE)
+ self.assertEqual(dev.slave.size, initial_size + crypto.LUKS_METADATA_SIZE)
diff --git a/tests/unit_tests/populator_test.py b/tests/unit_tests/populator_test.py
index 369fe878..7ba04bac 100644
--- a/tests/unit_tests/populator_test.py
+++ b/tests/unit_tests/populator_test.py
@@ -86,7 +86,7 @@ class DMDevicePopulatorTestCase(PopulatorHelperTestCase):
@patch.object(DeviceTree, "get_device_by_name")
@patch.object(DMDevice, "status", return_value=True)
@patch.object(DMDevice, "update_sysfs_path")
- @patch.object(DeviceTree, "_add_parent_devices")
+ @patch.object(DeviceTree, "_add_slave_devices")
@patch("blivet.udev.device_get_name")
@patch("blivet.udev.device_get_sysfs_path", return_value=sentinel.sysfs_path)
def test_run(self, *args):
@@ -95,7 +95,7 @@ class DMDevicePopulatorTestCase(PopulatorHelperTestCase):
devicetree = DeviceTree()
- # The general case for dm devices is that adding the parent devices
+ # The general case for dm devices is that adding the slave/parent devices
# will result in the dm device itself being in the tree.
device = Mock()
device.id = 0
@@ -106,7 +106,7 @@ class DMDevicePopulatorTestCase(PopulatorHelperTestCase):
parent = Mock()
parent.id = 0
parent.parents = []
- devicetree._add_parent_devices.return_value = [parent]
+ devicetree._add_slave_devices.return_value = [parent]
devicetree._add_device(parent)
devicetree.get_device_by_name.return_value = None
device_name = "dmdevice"
@@ -235,7 +235,7 @@ class LVMDevicePopulatorTestCase(PopulatorHelperTestCase):
# could be the first helper class checked.
@patch.object(DeviceTree, "get_device_by_name")
- @patch.object(DeviceTree, "_add_parent_devices")
+ @patch.object(DeviceTree, "_add_slave_devices")
@patch("blivet.udev.device_get_name")
@patch("blivet.udev.device_get_lv_vg_name")
def test_run(self, *args):
@@ -247,7 +247,7 @@ class LVMDevicePopulatorTestCase(PopulatorHelperTestCase):
devicetree = DeviceTree()
data = Mock()
- # Add parent devices and then look up the device.
+ # Add slave/parent devices and then look up the device.
device_get_name.return_value = sentinel.lv_name
devicetree.get_device_by_name.return_value = None
@@ -267,7 +267,7 @@ class LVMDevicePopulatorTestCase(PopulatorHelperTestCase):
call(sentinel.vg_name),
call(sentinel.lv_name)])
- # Add parent devices, but the device is still not in the tree
+ # Add slave/parent devices, but the device is still not in the tree
get_device_by_name.side_effect = None
get_device_by_name.return_value = None
self.assertEqual(helper.run(), None)
@@ -639,7 +639,7 @@ class MDDevicePopulatorTestCase(PopulatorHelperTestCase):
# could be the first helper class checked.
@patch.object(DeviceTree, "get_device_by_name")
- @patch.object(DeviceTree, "_add_parent_devices")
+ @patch.object(DeviceTree, "_add_slave_devices")
@patch("blivet.udev.device_get_name")
@patch("blivet.udev.device_get_md_uuid")
@patch("blivet.udev.device_get_md_name")
@@ -650,7 +650,7 @@ class MDDevicePopulatorTestCase(PopulatorHelperTestCase):
devicetree = DeviceTree()
- # base case: _add_parent_devices gets the array into the tree
+ # base case: _add_slave_devices gets the array into the tree
data = Mock()
device = Mock()
device.parents = []
@@ -713,12 +713,12 @@ class MultipathDevicePopulatorTestCase(PopulatorHelperTestCase):
# could be the first helper class checked.
@patch("blivet.udev.device_get_sysfs_path")
- @patch.object(DeviceTree, "_add_parent_devices")
+ @patch.object(DeviceTree, "_add_slave_devices")
@patch("blivet.udev.device_get_name")
def test_run(self, *args):
"""Test multipath device populator."""
device_get_name = args[0]
- add_parent_devices = args[1]
+ add_slave_devices = args[1]
devicetree = DeviceTree()
# set up some fake udev data to verify handling of specific entries
@@ -733,13 +733,13 @@ class MultipathDevicePopulatorTestCase(PopulatorHelperTestCase):
device_name = "mpathtest"
device_get_name.return_value = device_name
- parent_1 = Mock(tags=set(), wwn=wwn[2:], id=0)
- parent_1.parents = []
- parent_2 = Mock(tags=set(), wwn=wwn[2:], id=0)
- parent_2.parents = []
- devicetree._add_device(parent_1)
- devicetree._add_device(parent_2)
- add_parent_devices.return_value = [parent_1, parent_2]
+ slave_1 = Mock(tags=set(), wwn=wwn[2:], id=0)
+ slave_1.parents = []
+ slave_2 = Mock(tags=set(), wwn=wwn[2:], id=0)
+ slave_2.parents = []
+ devicetree._add_device(slave_1)
+ devicetree._add_device(slave_2)
+ add_slave_devices.return_value = [slave_1, slave_2]
helper = self.helper_class(devicetree, data)
diff --git a/tests/unit_tests/udev_test.py b/tests/unit_tests/udev_test.py
index b208efa8..ebcd59e2 100644
--- a/tests/unit_tests/udev_test.py
+++ b/tests/unit_tests/udev_test.py
@@ -49,11 +49,11 @@ class UdevTest(unittest.TestCase):
@mock.patch('blivet.udev.device_is_dm_crypt', return_value=False)
@mock.patch('blivet.udev.device_is_md')
@mock.patch('blivet.udev.device_get_md_container')
- @mock.patch('blivet.udev.device_get_parents')
+ @mock.patch('blivet.udev.device_get_slaves')
def test_udev_device_is_disk_md(self, *args):
import blivet.udev
info = dict(DEVTYPE='disk', SYS_PATH=mock.sentinel.md_path)
- (device_get_parents, device_get_md_container, device_is_md) = args[:3] # pylint: disable=unbalanced-tuple-unpacking
+ (device_get_slaves, device_get_md_container, device_is_md) = args[:3] # pylint: disable=unbalanced-tuple-unpacking
disk_parents = [dict(DEVTYPE="disk", SYS_PATH='/fake/path/2'),
dict(DEVTYPE="disk", SYS_PATH='/fake/path/3')]
@@ -68,20 +68,20 @@ class UdevTest(unittest.TestCase):
# Intel FW RAID (MD RAID w/ container layer)
# device_get_container will return some mock value which will evaluate to True
device_get_md_container.return_value = mock.sentinel.md_container
- device_get_parents.side_effect = lambda info: list()
+ device_get_slaves.side_effect = lambda info: list()
self.assertTrue(blivet.udev.device_is_disk(info))
# Normal MD RAID
- device_get_parents.side_effect = lambda info: partition_parents if info['SYS_PATH'] == mock.sentinel.md_path else list()
+ device_get_slaves.side_effect = lambda info: partition_parents if info['SYS_PATH'] == mock.sentinel.md_path else list()
device_get_md_container.return_value = None
self.assertFalse(blivet.udev.device_is_disk(info))
# Dell FW RAID (MD RAID whose members are all whole disks)
- device_get_parents.side_effect = lambda info: disk_parents if info['SYS_PATH'] == mock.sentinel.md_path else list()
+ device_get_slaves.side_effect = lambda info: disk_parents if info['SYS_PATH'] == mock.sentinel.md_path else list()
self.assertTrue(blivet.udev.device_is_disk(info))
# Normal MD RAID (w/ at least one non-disk member)
- device_get_parents.side_effect = lambda info: mixed_parents if info['SYS_PATH'] == mock.sentinel.md_path else list()
+ device_get_slaves.side_effect = lambda info: mixed_parents if info['SYS_PATH'] == mock.sentinel.md_path else list()
self.assertFalse(blivet.udev.device_is_disk(info))
diff --git a/tests/vmtests/vmbackedtestcase.py b/tests/vmtests/vmbackedtestcase.py
index 797bac85..6255104f 100644
--- a/tests/vmtests/vmbackedtestcase.py
+++ b/tests/vmtests/vmbackedtestcase.py
@@ -50,7 +50,7 @@ class VMBackedTestCase(unittest.TestCase):
defined in set_up_disks.
"""
- udev.ignored_device_names = [r'^zram']
+ udev.device_name_blacklist = [r'^zram']
#
# create disk images
--
2.38.1

View File

@ -0,0 +1,86 @@
From f6490c469904f4808c63a170210e53acc908b018 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 17 Aug 2022 14:24:21 +0200
Subject: [PATCH 1/2] Use MD populator instead of DM to handle DDF RAID format
---
blivet/formats/dmraid.py | 2 +-
blivet/formats/mdraid.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/blivet/formats/dmraid.py b/blivet/formats/dmraid.py
index 2ba9dcfe..ce15905d 100644
--- a/blivet/formats/dmraid.py
+++ b/blivet/formats/dmraid.py
@@ -43,7 +43,7 @@ class DMRaidMember(DeviceFormat):
#
# One problem that presents is the possibility of someone passing
# a dmraid member to the MDRaidArrayDevice constructor.
- _udev_types = ["adaptec_raid_member", "ddf_raid_member",
+ _udev_types = ["adaptec_raid_member",
"hpt37x_raid_member", "hpt45x_raid_member",
"isw_raid_member",
"jmicron_raid_member", "lsi_mega_raid_member",
diff --git a/blivet/formats/mdraid.py b/blivet/formats/mdraid.py
index 41ddef81..4aa3f3b0 100644
--- a/blivet/formats/mdraid.py
+++ b/blivet/formats/mdraid.py
@@ -41,7 +41,7 @@ class MDRaidMember(DeviceFormat):
""" An mdraid member disk. """
_type = "mdmember"
_name = N_("software RAID")
- _udev_types = ["linux_raid_member"]
+ _udev_types = ["linux_raid_member", "ddf_raid_member"]
parted_flag = PARTITION_RAID
_formattable = True # can be formatted
_supported = True # is supported
--
2.38.1
From 5fadd850aae217d7692a6c8a50b2dcd5e61a63cd Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 17 Aug 2022 14:24:58 +0200
Subject: [PATCH 2/2] Do not read DDF RAID UUID from udev
The UUID we get from udev isn't the array UUID, we need to get
that using libblockdev.
---
blivet/populator/helpers/mdraid.py | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/blivet/populator/helpers/mdraid.py b/blivet/populator/helpers/mdraid.py
index 3479e3f7..a7602d20 100644
--- a/blivet/populator/helpers/mdraid.py
+++ b/blivet/populator/helpers/mdraid.py
@@ -98,17 +98,21 @@ class MDFormatPopulator(FormatPopulator):
def _get_kwargs(self):
kwargs = super(MDFormatPopulator, self)._get_kwargs()
- try:
- # ID_FS_UUID contains the array UUID
- kwargs["md_uuid"] = udev.device_get_uuid(self.data)
- except KeyError:
- log.warning("mdraid member %s has no md uuid", udev.device_get_name(self.data))
+ kwargs["biosraid"] = udev.device_is_biosraid_member(self.data)
+ if not kwargs["biosraid"]:
+ try:
+ # ID_FS_UUID contains the array UUID
+ kwargs["md_uuid"] = udev.device_get_uuid(self.data)
+ except KeyError:
+ log.warning("mdraid member %s has no md uuid", udev.device_get_name(self.data))
+ else:
+ # for BIOS RAIDs we can't get the UUID from udev, we'll get it from mdadm in `run` below
+ kwargs["md_uuid"] = None
# reset the uuid to the member-specific value
# this will be None for members of v0 metadata arrays
kwargs["uuid"] = udev.device_get_md_device_uuid(self.data)
- kwargs["biosraid"] = udev.device_is_biosraid_member(self.data)
return kwargs
def run(self):
--
2.38.1

View File

@ -0,0 +1,77 @@
From 62af1d7f96b8ed8eb8f2732787576161ae5da79f Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 13 Oct 2022 10:47:52 +0200
Subject: [PATCH] Revert "Remove the Blivet.roots attribute"
This reverts commit 19a826073345ca6b57a8f9a95ec855892320300e.
---
blivet/blivet.py | 21 +++++++++++++++++++++
blivet/devicefactory.py | 3 +++
2 files changed, 24 insertions(+)
diff --git a/blivet/blivet.py b/blivet/blivet.py
index bf72ee9c..dc066b03 100644
--- a/blivet/blivet.py
+++ b/blivet/blivet.py
@@ -88,6 +88,7 @@ class Blivet(object):
self.devicetree = DeviceTree(ignored_disks=self.ignored_disks,
exclusive_disks=self.exclusive_disks,
disk_images=self.disk_images)
+ self.roots = []
@property
def short_product_name(self):
@@ -1314,5 +1315,25 @@ class Blivet(object):
p = partition.disk.format.parted_disk.getPartitionByPath(partition.path)
partition.parted_partition = p
+ for root in new.roots:
+ root.swaps = [new.devicetree.get_device_by_id(d.id, hidden=True) for d in root.swaps]
+ root.swaps = [s for s in root.swaps if s]
+
+ removed = set()
+ for (mountpoint, old_dev) in root.mounts.items():
+ if old_dev is None:
+ continue
+
+ new_dev = new.devicetree.get_device_by_id(old_dev.id, hidden=True)
+ if new_dev is None:
+ # if the device has been removed don't include this
+ # mountpoint at all
+ removed.add(mountpoint)
+ else:
+ root.mounts[mountpoint] = new_dev
+
+ for mnt in removed:
+ del root.mounts[mnt]
+
log.debug("finished Blivet copy")
return new
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py
index 8105bfc7..6f460f6d 100644
--- a/blivet/devicefactory.py
+++ b/blivet/devicefactory.py
@@ -383,6 +383,7 @@ class DeviceFactory(object):
# used for error recovery
self.__devices = []
self.__actions = []
+ self.__roots = []
def _is_container_encrypted(self):
return all(isinstance(p, LUKSDevice) for p in self.device.container.parents)
@@ -994,10 +995,12 @@ class DeviceFactory(object):
_blivet_copy = self.storage.copy()
self.__devices = _blivet_copy.devicetree._devices
self.__actions = _blivet_copy.devicetree._actions
+ self.__roots = _blivet_copy.roots
def _revert_devicetree(self):
self.storage.devicetree._devices = self.__devices
self.storage.devicetree._actions = self.__actions
+ self.storage.roots = self.__roots
class PartitionFactory(DeviceFactory):
--
2.38.1

View File

@ -0,0 +1,45 @@
From 1561bfe8820118178bbb07021adc1cacd875c4c7 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Tue, 18 Oct 2022 12:28:37 +0200
Subject: [PATCH] Fix potential AttributeError when getting stratis blockdev
info
---
blivet/static_data/stratis_info.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/blivet/static_data/stratis_info.py b/blivet/static_data/stratis_info.py
index bd1c5a18..42f230ee 100644
--- a/blivet/static_data/stratis_info.py
+++ b/blivet/static_data/stratis_info.py
@@ -124,20 +124,22 @@ class StratisInfo(object):
log.error("Failed to get DBus properties of '%s'", blockdev_path)
return None
+ blockdev_uuid = str(uuid.UUID(properties["Uuid"]))
+
pool_path = properties["Pool"]
if pool_path == "/":
pool_name = ""
+ return StratisBlockdevInfo(path=properties["Devnode"], uuid=blockdev_uuid,
+ pool_name="", pool_uuid="", object_path=blockdev_path)
else:
pool_info = self._get_pool_info(properties["Pool"])
if not pool_info:
return None
pool_name = pool_info.name
- blockdev_uuid = str(uuid.UUID(properties["Uuid"]))
-
- return StratisBlockdevInfo(path=properties["Devnode"], uuid=blockdev_uuid,
- pool_name=pool_name, pool_uuid=pool_info.uuid,
- object_path=blockdev_path)
+ return StratisBlockdevInfo(path=properties["Devnode"], uuid=blockdev_uuid,
+ pool_name=pool_name, pool_uuid=pool_info.uuid,
+ object_path=blockdev_path)
def _get_locked_pools_info(self):
locked_pools = []
--
2.38.1

View File

@ -0,0 +1,27 @@
From b747c4ed07937f54a546ffb2f2c8c95e0797dd6c Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 20 Oct 2022 15:19:29 +0200
Subject: [PATCH] tests: Skip XFS resize test on CentOS/RHEL 8
Partitions on loop devices are broken on CentOS/RHEL 8.
---
tests/skip.yml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/tests/skip.yml b/tests/skip.yml
index 568c3fff..66b34493 100644
--- a/tests/skip.yml
+++ b/tests/skip.yml
@@ -29,3 +29,9 @@
- distro: "centos"
version: "9"
reason: "Creating RAID 1 LV on CentOS/RHEL 9 causes a system deadlock"
+
+- test: storage_tests.formats_test.fs_test.XFSTestCase.test_resize
+ skip_on:
+ - distro: ["centos", "enterprise_linux"]
+ version: "8"
+ reason: "Creating partitions on loop devices is broken on CentOS/RHEL 8 latest kernel"
--
2.37.3

View File

@ -0,0 +1,160 @@
From 9618b84f94187efddc7316c2546bed923a91ecf9 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 3 Nov 2022 08:36:27 +0100
Subject: [PATCH 1/2] Revert "Set XFS minimal size to 300 MiB"
This reverts commit 307d49833771d161314bae50c68e70dc35c3bb36.
---
blivet/formats/fs.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
index 8c346aa5..33922f3a 100644
--- a/blivet/formats/fs.py
+++ b/blivet/formats/fs.py
@@ -1091,7 +1091,7 @@ class XFS(FS):
_modules = ["xfs"]
_labelfs = fslabeling.XFSLabeling()
_uuidfs = fsuuid.XFSUUID()
- _min_size = Size("300 MiB")
+ _min_size = Size("16 MiB")
_max_size = Size("16 EiB")
_formattable = True
_linux_native = True
--
2.38.1
From 24d94922d6879baa85aaa101f6b21efa568a9cbc Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 3 Nov 2022 08:36:39 +0100
Subject: [PATCH 2/2] Revert "tests: Create bigger devices for XFS testing"
This reverts commit 467cb8024010b2cabb1e92d9e64f6d3cbe949ad9.
---
tests/storage_tests/formats_test/fs_test.py | 7 +++----
tests/storage_tests/formats_test/fslabeling.py | 4 +---
tests/storage_tests/formats_test/fsuuid.py | 4 +---
tests/storage_tests/formats_test/labeling_test.py | 2 --
tests/storage_tests/formats_test/uuid_test.py | 3 ---
5 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/tests/storage_tests/formats_test/fs_test.py b/tests/storage_tests/formats_test/fs_test.py
index cf8fb441..97f4cbbe 100644
--- a/tests/storage_tests/formats_test/fs_test.py
+++ b/tests/storage_tests/formats_test/fs_test.py
@@ -54,7 +54,6 @@ class ReiserFSTestCase(fstesting.FSAsRoot):
class XFSTestCase(fstesting.FSAsRoot):
_fs_class = fs.XFS
- _DEVICE_SIZE = Size("500 MiB")
def can_resize(self, an_fs):
resize_tasks = (an_fs._resize, an_fs._size_info)
@@ -96,12 +95,12 @@ class XFSTestCase(fstesting.FSAsRoot):
self.assertFalse(an_fs.resizable)
# Not resizable, so can not do resizing actions.
with self.assertRaises(DeviceFormatError):
- an_fs.target_size = Size("300 MiB")
+ an_fs.target_size = Size("64 MiB")
with self.assertRaises(DeviceFormatError):
an_fs.do_resize()
else:
disk = DiskDevice(os.path.basename(self.loop_devices[0]))
- part = self._create_partition(disk, Size("300 MiB"))
+ part = self._create_partition(disk, Size("50 MiB"))
an_fs = self._fs_class()
an_fs.device = part.path
self.assertIsNone(an_fs.create())
@@ -114,7 +113,7 @@ class XFSTestCase(fstesting.FSAsRoot):
part = self._create_partition(disk, size=part.size + Size("40 MiB"))
# Try a reasonable target size
- TARGET_SIZE = Size("325 MiB")
+ TARGET_SIZE = Size("64 MiB")
an_fs.target_size = TARGET_SIZE
self.assertEqual(an_fs.target_size, TARGET_SIZE)
self.assertNotEqual(an_fs._size, TARGET_SIZE)
diff --git a/tests/storage_tests/formats_test/fslabeling.py b/tests/storage_tests/formats_test/fslabeling.py
index ebe0b70a..0e0dc261 100644
--- a/tests/storage_tests/formats_test/fslabeling.py
+++ b/tests/storage_tests/formats_test/fslabeling.py
@@ -21,10 +21,8 @@ class LabelingAsRoot(loopbackedtestcase.LoopBackedTestCase):
_invalid_label = abc.abstractproperty(
doc="A label which is invalid for this filesystem.")
- _DEVICE_SIZE = Size("100 MiB")
-
def __init__(self, methodName='run_test'):
- super(LabelingAsRoot, self).__init__(methodName=methodName, device_spec=[self._DEVICE_SIZE])
+ super(LabelingAsRoot, self).__init__(methodName=methodName, device_spec=[Size("100 MiB")])
def setUp(self):
an_fs = self._fs_class()
diff --git a/tests/storage_tests/formats_test/fsuuid.py b/tests/storage_tests/formats_test/fsuuid.py
index 0b9762fd..16aa19a6 100644
--- a/tests/storage_tests/formats_test/fsuuid.py
+++ b/tests/storage_tests/formats_test/fsuuid.py
@@ -23,11 +23,9 @@ class SetUUID(loopbackedtestcase.LoopBackedTestCase):
_invalid_uuid = abc.abstractproperty(
doc="An invalid UUID for this filesystem.")
- _DEVICE_SIZE = Size("100 MiB")
-
def __init__(self, methodName='run_test'):
super(SetUUID, self).__init__(methodName=methodName,
- device_spec=[self._DEVICE_SIZE])
+ device_spec=[Size("100 MiB")])
def setUp(self):
an_fs = self._fs_class()
diff --git a/tests/storage_tests/formats_test/labeling_test.py b/tests/storage_tests/formats_test/labeling_test.py
index 0702260a..d24e6619 100644
--- a/tests/storage_tests/formats_test/labeling_test.py
+++ b/tests/storage_tests/formats_test/labeling_test.py
@@ -1,7 +1,6 @@
import unittest
from blivet.formats import device_formats
-from blivet.size import Size
import blivet.formats.fs as fs
import blivet.formats.swap as swap
@@ -62,7 +61,6 @@ class InitializationTestCase(unittest.TestCase):
class XFSTestCase(fslabeling.CompleteLabelingAsRoot):
_fs_class = fs.XFS
_invalid_label = "root filesystem"
- _DEVICE_SIZE = Size("500 MiB")
class FATFSTestCase(fslabeling.CompleteLabelingAsRoot):
diff --git a/tests/storage_tests/formats_test/uuid_test.py b/tests/storage_tests/formats_test/uuid_test.py
index af35c0ee..ee8d452e 100644
--- a/tests/storage_tests/formats_test/uuid_test.py
+++ b/tests/storage_tests/formats_test/uuid_test.py
@@ -2,7 +2,6 @@ import unittest
import blivet.formats.fs as fs
import blivet.formats.swap as swap
-from blivet.size import Size
from . import fsuuid
@@ -53,14 +52,12 @@ class XFSTestCase(fsuuid.SetUUIDWithMkFs):
_fs_class = fs.XFS
_invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456"
_valid_uuid = "97e3d40f-dca8-497d-8b86-92f257402465"
- _DEVICE_SIZE = Size("500 MiB")
class XFSAfterTestCase(fsuuid.SetUUIDAfterMkFs):
_fs_class = fs.XFS
_invalid_uuid = "abcdefgh-ijkl-mnop-qrst-uvwxyz123456"
_valid_uuid = "97e3d40f-dca8-497d-8b86-92f257402465"
- _DEVICE_SIZE = Size("500 MiB")
class FATFSTestCase(fsuuid.SetUUIDWithMkFs):
--
2.38.1

View File

@ -0,0 +1,55 @@
From fed62af06eb1584adbacd821dfe79c2df52c6aa4 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 2 Nov 2022 12:14:28 +0100
Subject: [PATCH] Catch BlockDevNotImplementedError for btrfs plugin calls
This is a workaround for RHEL where the btrfs plugin is not
available and where we might still try to call some libblockdev
functions to gather information about preexisting btrfs devices.
---
blivet/devices/btrfs.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/blivet/devices/btrfs.py b/blivet/devices/btrfs.py
index 0e029715..1ae6a04d 100644
--- a/blivet/devices/btrfs.py
+++ b/blivet/devices/btrfs.py
@@ -362,7 +362,7 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice, RaidDevice):
try:
subvols = blockdev.btrfs.list_subvolumes(mountpoint,
snapshots_only=snapshots_only)
- except blockdev.BtrfsError as e:
+ except (blockdev.BtrfsError, blockdev.BlockDevNotImplementedError) as e:
log.debug("failed to list subvolumes: %s", e)
else:
self._get_default_subvolume_id()
@@ -400,7 +400,7 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice, RaidDevice):
with self._do_temp_mount() as mountpoint:
try:
subvolid = blockdev.btrfs.get_default_subvolume_id(mountpoint)
- except blockdev.BtrfsError as e:
+ except (blockdev.BtrfsError, blockdev.BlockDevNotImplementedError) as e:
log.debug("failed to get default subvolume id: %s", e)
self._default_subvolume_id = subvolid
@@ -413,7 +413,7 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice, RaidDevice):
with self._do_temp_mount() as mountpoint:
try:
blockdev.btrfs.set_default_subvolume(mountpoint, vol_id)
- except blockdev.BtrfsError as e:
+ except (blockdev.BtrfsError, blockdev.BlockDevNotImplementedError) as e:
log.error("failed to set new default subvolume id (%s): %s",
vol_id, e)
# The only time we set a new default subvolume is so we can remove
@@ -471,7 +471,7 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice, RaidDevice):
if not self.format.vol_uuid:
try:
bd_info = blockdev.btrfs.filesystem_info(self.parents[0].path)
- except blockdev.BtrfsError as e:
+ except (blockdev.BtrfsError, blockdev.BlockDevNotImplementedError) as e:
log.error("failed to get filesystem info for new btrfs volume %s", e)
else:
self.format.vol_uuid = bd_info.uuid
--
2.38.1

View File

@ -0,0 +1,57 @@
From 2aba050e74dc5df483da022dcf436b101c7a4301 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 11 Jan 2023 14:59:24 +0100
Subject: [PATCH] Default to encryption sector size 512 for LUKS devices
We are currently letting cryptsetup decide the optimal encryption
sector size for LUKS. The problem is that for disks with physical
sector size 4096 cryptsetup will default to 4096 encryption sector
size even if the drive logical sector size is 512 which means
these disks cannot be combined with other 512 logical sector size
disks in LVM. This requires a more sophisticated solution in the
future, but for now just default to 512 if not specified by the
user otherwise.
Resolves: rhbz#2103800
---
blivet/formats/luks.py | 10 +++++++---
tests/unit_tests/formats_tests/luks_test.py | 2 +-
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/blivet/formats/luks.py b/blivet/formats/luks.py
index 8de4911f..2637e0c5 100644
--- a/blivet/formats/luks.py
+++ b/blivet/formats/luks.py
@@ -166,9 +166,13 @@ class LUKS(DeviceFormat):
if self.pbkdf_args.type == "pbkdf2" and self.pbkdf_args.max_memory_kb:
log.warning("Memory limit is not used for pbkdf2 and it will be ignored.")
- self.luks_sector_size = kwargs.get("luks_sector_size") or 0
- if self.luks_sector_size and self.luks_version != "luks2":
- raise ValueError("Sector size argument is valid only for LUKS version 2.")
+ self.luks_sector_size = kwargs.get("luks_sector_size")
+ if self.luks_version == "luks2":
+ if self.luks_sector_size is None:
+ self.luks_sector_size = 512 # XXX we don't want cryptsetup choose automatically here so fallback to 512
+ else:
+ if self.luks_sector_size:
+ raise ValueError("Sector size argument is valid only for LUKS version 2.")
def __repr__(self):
s = DeviceFormat.__repr__(self)
diff --git a/tests/unit_tests/formats_tests/luks_test.py b/tests/unit_tests/formats_tests/luks_test.py
index 5ae6acfe..ec7b7592 100644
--- a/tests/unit_tests/formats_tests/luks_test.py
+++ b/tests/unit_tests/formats_tests/luks_test.py
@@ -53,7 +53,7 @@ class LUKSNodevTestCase(unittest.TestCase):
def test_sector_size(self):
fmt = LUKS()
- self.assertEqual(fmt.luks_sector_size, 0)
+ self.assertEqual(fmt.luks_sector_size, 512)
with self.assertRaises(ValueError):
fmt = LUKS(luks_version="luks1", luks_sector_size=4096)
--
2.39.0

View File

@ -0,0 +1,172 @@
From 11c3e695d9a2130f325bb5459a9881ff70338f71 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 9 Mar 2023 13:18:42 +0100
Subject: [PATCH] Add support for specifying stripe size for RAID LVs
---
blivet/devices/lvm.py | 28 +++++++++++++++++---
tests/storage_tests/devices_test/lvm_test.py | 12 +++++++--
tests/unit_tests/devices_test/lvm_test.py | 27 +++++++++++++++++++
3 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index b8595d63..41358e9b 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -659,7 +659,8 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
def __init__(self, name, parents=None, size=None, uuid=None, seg_type=None,
fmt=None, exists=False, sysfs_path='', grow=None, maxsize=None,
- percent=None, cache_request=None, pvs=None, from_lvs=None):
+ percent=None, cache_request=None, pvs=None, from_lvs=None,
+ stripe_size=0):
if not exists:
if seg_type not in [None, "linear", "thin", "thin-pool", "cache", "vdo-pool", "vdo", "cache-pool"] + lvm.raid_seg_types:
@@ -756,6 +757,15 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
if self._pv_specs:
self._assign_pv_space()
+ self._stripe_size = stripe_size
+ if not self.exists and self._stripe_size:
+ if self.seg_type not in lvm.raid_seg_types:
+ raise errors.DeviceError("Stripe size can be specified only for RAID volumes")
+ if self.seg_type in ("raid1", "RAID1", "1", 1, "mirror"):
+ raise errors.DeviceError("Specifying stripe size is not allowed for RAID1 or mirror")
+ if self.cache:
+ raise errors.DeviceError("Creating cached LVs with custom stripe size is not supported")
+
def _assign_pv_space(self):
if not self.is_raid_lv:
# nothing to do for non-RAID (and thus non-striped) LVs here
@@ -2295,7 +2305,7 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
parent_lv=None, int_type=None, origin=None, vorigin=False,
metadata_size=None, chunk_size=None, profile=None, from_lvs=None,
compression=False, deduplication=False, index_memory=0,
- write_policy=None, cache_mode=None, attach_to=None):
+ write_policy=None, cache_mode=None, attach_to=None, stripe_size=0):
"""
:param name: the device name (generally a device node's basename)
:type name: str
@@ -2375,6 +2385,11 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
be attached to when created
:type attach_to: :class:`LVMLogicalVolumeDevice`
+ For RAID LVs only:
+
+ :keyword stripe_size: size of the RAID stripe
+ :type stripe_size: :class:`~.size.Size`
+
"""
if isinstance(parents, (list, ParentList)):
@@ -2395,7 +2410,8 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
LVMCachePoolMixin.__init__(self, metadata_size, cache_mode, attach_to)
LVMLogicalVolumeBase.__init__(self, name, parents, size, uuid, seg_type,
fmt, exists, sysfs_path, grow, maxsize,
- percent, cache_request, pvs, from_lvs)
+ percent, cache_request, pvs, from_lvs,
+ stripe_size)
LVMVDOPoolMixin.__init__(self, compression, deduplication, index_memory,
write_policy)
LVMVDOLogicalVolumeMixin.__init__(self)
@@ -2651,8 +2667,12 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
pvs = [spec.pv.path for spec in self._pv_specs]
pvs = pvs or None
+ extra = dict()
+ if self._stripe_size:
+ extra["stripesize"] = str(int(self._stripe_size.convert_to("KiB")))
+
blockdev.lvm.lvcreate(self.vg.name, self._name, self.size,
- type=self.seg_type, pv_list=pvs)
+ type=self.seg_type, pv_list=pvs, **extra)
else:
fast_pvs = [pv.path for pv in self.cache.fast_pvs]
diff --git a/tests/storage_tests/devices_test/lvm_test.py b/tests/storage_tests/devices_test/lvm_test.py
index a055fc27..97ef1c4b 100644
--- a/tests/storage_tests/devices_test/lvm_test.py
+++ b/tests/storage_tests/devices_test/lvm_test.py
@@ -1,4 +1,5 @@
import os
+import subprocess
from ..storagetestcase import StorageTestCase
@@ -127,7 +128,7 @@ class LVMTestCase(StorageTestCase):
self.assertTrue(snap.is_snapshot_lv)
self.assertEqual(snap.origin, thinlv)
- def _test_lvm_raid(self, seg_type, raid_level):
+ def _test_lvm_raid(self, seg_type, raid_level, stripe_size=0):
disk1 = self.storage.devicetree.get_device_by_path(self.vdevs[0])
self.assertIsNotNone(disk1)
self.storage.initialize_disk(disk1)
@@ -151,7 +152,7 @@ class LVMTestCase(StorageTestCase):
raidlv = self.storage.new_lv(fmt_type="ext4", size=blivet.size.Size("50 MiB"),
parents=[vg], name="blivetTestRAIDLV",
- seg_type=seg_type, pvs=[pv1, pv2])
+ seg_type=seg_type, pvs=[pv1, pv2], stripe_size=stripe_size)
self.storage.create_device(raidlv)
self.storage.do_it()
@@ -163,9 +164,16 @@ class LVMTestCase(StorageTestCase):
self.assertEqual(raidlv.raid_level, raid_level)
self.assertEqual(raidlv.seg_type, seg_type)
+ if stripe_size:
+ out = subprocess.check_output(["lvs", "-o", "stripe_size", "--noheadings", "--nosuffix", "--units=b", raidlv.vg.name + "/" + raidlv.lvname])
+ self.assertEqual(out.decode().strip(), str(int(stripe_size.convert_to())))
+
def test_lvm_raid_raid0(self):
self._test_lvm_raid("raid0", blivet.devicelibs.raid.RAID0)
+ def test_lvm_raid_raid0_stripe_size(self):
+ self._test_lvm_raid("raid0", blivet.devicelibs.raid.RAID0, stripe_size=blivet.size.Size("1 MiB"))
+
def test_lvm_raid_striped(self):
self._test_lvm_raid("striped", blivet.devicelibs.raid.Striped)
diff --git a/tests/unit_tests/devices_test/lvm_test.py b/tests/unit_tests/devices_test/lvm_test.py
index 995c2da4..d7b55224 100644
--- a/tests/unit_tests/devices_test/lvm_test.py
+++ b/tests/unit_tests/devices_test/lvm_test.py
@@ -363,6 +363,33 @@ class LVMDeviceTest(unittest.TestCase):
self.assertEqual(pv.format.free, Size("264 MiB"))
self.assertEqual(pv2.format.free, Size("256 MiB"))
+ def test_lvm_logical_volume_raid_stripe_size(self):
+ pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
+ size=Size("1025 MiB"))
+ pv2 = StorageDevice("pv2", fmt=blivet.formats.get_format("lvmpv"),
+ size=Size("513 MiB"))
+ vg = LVMVolumeGroupDevice("testvg", parents=[pv, pv2])
+
+ with self.assertRaises(blivet.errors.DeviceError):
+ # non-raid LV
+ lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("1 GiB"),
+ fmt=blivet.formats.get_format("xfs"),
+ exists=False, stripe_size=Size("1 MiB"))
+
+ with self.assertRaises(blivet.errors.DeviceError):
+ # raid1 LV
+ lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("1 GiB"),
+ fmt=blivet.formats.get_format("xfs"),
+ exists=False, seg_type="raid1", pvs=[pv, pv2],
+ stripe_size=Size("1 MiB"))
+
+ lv = LVMLogicalVolumeDevice("testlv", parents=[vg], size=Size("1 GiB"),
+ fmt=blivet.formats.get_format("xfs"),
+ exists=False, seg_type="raid0", pvs=[pv, pv2],
+ stripe_size=Size("1 MiB"))
+
+ self.assertEqual(lv._stripe_size, Size("1 MiB"))
+
def test_target_size(self):
pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
size=Size("1 GiB"))
--
2.40.1

View File

@ -0,0 +1,68 @@
From 1af0d3c37a93e431790e641a329a7f34dabf291a Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 2 Mar 2023 12:34:42 +0100
Subject: [PATCH] Fix setting kickstart data
When changing our code to PEP8 compliant we also changed some
pykickstart properties like onPart by accident. This PR fixes this.
Resolves: rhbz#2175166
---
blivet/devices/btrfs.py | 4 ++--
blivet/devices/lvm.py | 2 +-
blivet/devices/partition.py | 6 +++---
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/blivet/devices/btrfs.py b/blivet/devices/btrfs.py
index 1ae6a04d..3f56624e 100644
--- a/blivet/devices/btrfs.py
+++ b/blivet/devices/btrfs.py
@@ -498,8 +498,8 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice, RaidDevice):
def populate_ksdata(self, data):
super(BTRFSVolumeDevice, self).populate_ksdata(data)
- data.data_level = self.data_level.name if self.data_level else None
- data.metadata_level = self.metadata_level.name if self.metadata_level else None
+ data.dataLevel = self.data_level.name if self.data_level else None
+ data.metaDataLevel = self.metadata_level.name if self.metadata_level else None
data.devices = ["btrfs.%d" % p.id for p in self.parents]
data.preexist = self.exists
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index 41358e9b..c3132457 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -1161,7 +1161,7 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
if self.req_grow:
# base size could be literal or percentage
- data.max_size_mb = self.req_max_size.convert_to(MiB)
+ data.maxSizeMB = self.req_max_size.convert_to(MiB)
elif data.resize:
data.size = self.target_size.convert_to(MiB)
diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py
index 89d907c2..0e9250ce 100644
--- a/blivet/devices/partition.py
+++ b/blivet/devices/partition.py
@@ -982,14 +982,14 @@ class PartitionDevice(StorageDevice):
data.size = self.req_base_size.round_to_nearest(MiB, rounding=ROUND_DOWN).convert_to(spec=MiB)
data.grow = self.req_grow
if self.req_grow:
- data.max_size_mb = self.req_max_size.convert_to(MiB)
+ data.maxSizeMB = self.req_max_size.convert_to(MiB)
# data.disk = self.disk.name # by-id
if self.req_disks and len(self.req_disks) == 1:
data.disk = self.disk.name
- data.prim_only = self.req_primary
+ data.primOnly = self.req_primary
else:
- data.on_part = self.name # by-id
+ data.onPart = self.name # by-id
if data.resize:
# on s390x in particular, fractional sizes are reported, which
--
2.40.1

View File

@ -0,0 +1,133 @@
From c2b06150df0b876c7d442097b6c9ca90c9ca2ecc Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 4 May 2023 11:35:44 +0200
Subject: [PATCH] Do not set memory limit for LUKS2 when running in FIPS mode
With FIPS enabled LUKS uses pbkdf and not argon so the memory
limit is not a valid parameter.
Resolves: rhbz#2183437
---
blivet/devicelibs/crypto.py | 11 +++++++
blivet/formats/luks.py | 12 ++++----
tests/unit_tests/formats_tests/luks_test.py | 30 +++++++++++++++++++
.../unit_tests/formats_tests/methods_test.py | 3 +-
4 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py
index f0caf0f7..68e68db1 100644
--- a/blivet/devicelibs/crypto.py
+++ b/blivet/devicelibs/crypto.py
@@ -21,6 +21,7 @@
#
import hashlib
+import os
import gi
gi.require_version("BlockDev", "2.0")
@@ -100,3 +101,13 @@ def calculate_integrity_metadata_size(device_size, algorithm=DEFAULT_INTEGRITY_A
jsize = (jsize / SECTOR_SIZE + 1) * SECTOR_SIZE # round up to sector
return msize + jsize
+
+
+def is_fips_enabled():
+ if not os.path.exists("/proc/sys/crypto/fips_enabled"):
+ # if the file doesn't exist, we are definitely not in FIPS mode
+ return False
+
+ with open("/proc/sys/crypto/fips_enabled", "r") as f:
+ enabled = f.read()
+ return enabled.strip() == "1"
diff --git a/blivet/formats/luks.py b/blivet/formats/luks.py
index 2637e0c5..adf3c711 100644
--- a/blivet/formats/luks.py
+++ b/blivet/formats/luks.py
@@ -303,11 +303,13 @@ class LUKS(DeviceFormat):
if luks_data.pbkdf_args:
self.pbkdf_args = luks_data.pbkdf_args
else:
- mem_limit = crypto.calculate_luks2_max_memory()
- if mem_limit:
- self.pbkdf_args = LUKS2PBKDFArgs(max_memory_kb=int(mem_limit.convert_to(KiB)))
- luks_data.pbkdf_args = self.pbkdf_args
- log.info("PBKDF arguments for LUKS2 not specified, using defaults with memory limit %s", mem_limit)
+ # argon is not used with FIPS so we don't need to adjust the memory when in FIPS mode
+ if not crypto.is_fips_enabled():
+ mem_limit = crypto.calculate_luks2_max_memory()
+ if mem_limit:
+ self.pbkdf_args = LUKS2PBKDFArgs(max_memory_kb=int(mem_limit.convert_to(KiB)))
+ luks_data.pbkdf_args = self.pbkdf_args
+ log.info("PBKDF arguments for LUKS2 not specified, using defaults with memory limit %s", mem_limit)
if self.pbkdf_args:
pbkdf = blockdev.CryptoLUKSPBKDF(type=self.pbkdf_args.type,
diff --git a/tests/unit_tests/formats_tests/luks_test.py b/tests/unit_tests/formats_tests/luks_test.py
index ec7b7592..1127e968 100644
--- a/tests/unit_tests/formats_tests/luks_test.py
+++ b/tests/unit_tests/formats_tests/luks_test.py
@@ -6,9 +6,14 @@ except ImportError:
import unittest
from blivet.formats.luks import LUKS
+from blivet.size import Size
+from blivet.static_data import luks_data
class LUKSNodevTestCase(unittest.TestCase):
+ def setUp(self):
+ luks_data.pbkdf_args = None
+
def test_create_discard_option(self):
# flags.discard_new=False --> no discard
fmt = LUKS(exists=False)
@@ -51,6 +56,31 @@ class LUKSNodevTestCase(unittest.TestCase):
fmt = LUKS(cipher="aes-cbc-plain64")
self.assertEqual(fmt.key_size, 0)
+ def test_luks2_pbkdf_memory_fips(self):
+ fmt = LUKS()
+ with patch("blivet.formats.luks.blockdev.crypto") as bd:
+ # fips enabled, pbkdf memory should not be set
+ with patch("blivet.formats.luks.crypto") as crypto:
+ attrs = {"is_fips_enabled.return_value": True,
+ "get_optimal_luks_sector_size.return_value": 0,
+ "calculate_luks2_max_memory.return_value": Size("256 MiB")}
+ crypto.configure_mock(**attrs)
+
+ fmt._create()
+ crypto.calculate_luks2_max_memory.assert_not_called()
+ self.assertEqual(bd.luks_format.call_args[1]["extra"].pbkdf.max_memory_kb, 0)
+
+ # fips disabled, pbkdf memory should be set
+ with patch("blivet.formats.luks.crypto") as crypto:
+ attrs = {"is_fips_enabled.return_value": False,
+ "get_optimal_luks_sector_size.return_value": 0,
+ "calculate_luks2_max_memory.return_value": Size("256 MiB")}
+ crypto.configure_mock(**attrs)
+
+ fmt._create()
+ crypto.calculate_luks2_max_memory.assert_called()
+ self.assertEqual(bd.luks_format.call_args[1]["extra"].pbkdf.max_memory_kb, 256 * 1024)
+
def test_sector_size(self):
fmt = LUKS()
self.assertEqual(fmt.luks_sector_size, 512)
diff --git a/tests/unit_tests/formats_tests/methods_test.py b/tests/unit_tests/formats_tests/methods_test.py
index 2743b7db..5d30c260 100644
--- a/tests/unit_tests/formats_tests/methods_test.py
+++ b/tests/unit_tests/formats_tests/methods_test.py
@@ -366,7 +366,8 @@ class LUKSMethodsTestCase(FormatMethodsTestCase):
def _test_create_backend(self):
self.format.exists = False
- self.format.create()
+ with patch("blivet.devicelibs.crypto.is_fips_enabled", return_value=False):
+ self.format.create()
self.assertTrue(self.patches["blockdev"].crypto.luks_format.called) # pylint: disable=no-member
def _test_setup_backend(self):
--
2.40.1

View File

@ -0,0 +1,265 @@
From eb16230427fc1081f8515e6ad69ccf99ca521e5d Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Tue, 4 Apr 2023 13:31:40 +0200
Subject: [PATCH 1/2] Add support for filesystem online resize
Resolves: rhbz#2168680
---
blivet/devices/lvm.py | 13 ++++++++-----
blivet/devices/partition.py | 11 ++++++-----
blivet/flags.py | 3 +++
blivet/formats/fs.py | 32 ++++++++++++++++++++++++++++----
blivet/formats/fslib.py | 7 +++++++
5 files changed, 52 insertions(+), 14 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index c3132457..ca45c4b5 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -42,6 +42,7 @@ from .. import errors
from .. import util
from ..storage_log import log_method_call
from .. import udev
+from ..flags import flags
from ..size import Size, KiB, MiB, ROUND_UP, ROUND_DOWN
from ..static_data.lvm_info import lvs_info
from ..tasks import availability
@@ -2729,12 +2730,14 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
# Setup VG parents (in case they are dmraid partitions for example)
self.vg.setup_parents(orig=True)
- if self.original_format.exists:
- self.original_format.teardown()
- if self.format.exists:
- self.format.teardown()
+ if not flags.allow_online_fs_resize:
+ if self.original_format.exists:
+ self.original_format.teardown()
+ if self.format.exists:
+ self.format.teardown()
+
+ udev.settle()
- udev.settle()
blockdev.lvm.lvresize(self.vg.name, self._name, self.size)
@type_specific
diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py
index 0e9250ce..6ae4b8d3 100644
--- a/blivet/devices/partition.py
+++ b/blivet/devices/partition.py
@@ -745,11 +745,12 @@ class PartitionDevice(StorageDevice):
if not self.exists:
raise errors.DeviceError("device has not been created")
- # don't teardown when resizing luks
- if self.format.type == "luks" and self.children:
- self.children[0].format.teardown()
- else:
- self.teardown()
+ if not flags.allow_online_fs_resize:
+ # don't teardown when resizing luks
+ if self.format.type == "luks" and self.children:
+ self.children[0].format.teardown()
+ else:
+ self.teardown()
if not self.sysfs_path:
return
diff --git a/blivet/flags.py b/blivet/flags.py
index 6364164d..ecfa7ad7 100644
--- a/blivet/flags.py
+++ b/blivet/flags.py
@@ -91,6 +91,9 @@ class Flags(object):
self.debug_threads = False
+ # Allow online filesystem resizes
+ self.allow_online_fs_resize = False
+
def get_boot_cmdline(self):
with open("/proc/cmdline") as f:
buf = f.read().strip()
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
index 33922f3a..3f553eb0 100644
--- a/blivet/formats/fs.py
+++ b/blivet/formats/fs.py
@@ -56,7 +56,7 @@ from ..i18n import N_
from .. import udev
from ..mounts import mounts_cache
-from .fslib import kernel_filesystems
+from .fslib import kernel_filesystems, FSResize
import logging
log = logging.getLogger("blivet")
@@ -88,6 +88,9 @@ class FS(DeviceFormat):
# value is already unpredictable and can change in the future...
_metadata_size_factor = 1.0
+ # support for resize: grow/shrink, online/offline
+ _resize_support = 0
+
config_actions_map = {"label": "write_label"}
def __init__(self, **kwargs):
@@ -436,12 +439,27 @@ class FS(DeviceFormat):
self.write_uuid()
def _pre_resize(self):
- # file systems need a check before being resized
- self.do_check()
+ if self.status:
+ if flags.allow_online_fs_resize:
+ if self.target_size > self.size and not self._resize_support & FSResize.ONLINE_GROW:
+ raise FSError("This filesystem doesn't support online growing")
+ if self.target_size < self.size and not self._resize_support & FSResize.ONLINE_SHRINK:
+ raise FSError("This filesystem doesn't support online shrinking")
+ else:
+ raise FSError("Resizing of mounted filesystems is disabled")
+
+ if self.status:
+ # fsck tools in general don't allow checks on mounted filesystems
+ log.debug("Filesystem on %s is mounted, not checking", self.device)
+ else:
+ # file systems need a check before being resized
+ self.do_check()
+
super(FS, self)._pre_resize()
def _post_resize(self):
- self.do_check()
+ if not self.status:
+ self.do_check()
super(FS, self)._post_resize()
def do_check(self):
@@ -838,6 +856,7 @@ class Ext2FS(FS):
_formattable = True
_supported = True
_resizable = True
+ _resize_support = FSResize.ONLINE_GROW | FSResize.OFFLINE_GROW | FSResize.OFFLINE_SHRINK
_linux_native = True
_max_size = Size("8 TiB")
_dump = True
@@ -1097,6 +1116,7 @@ class XFS(FS):
_linux_native = True
_supported = True
_resizable = True
+ _resize_support = FSResize.ONLINE_GROW | FSResize.OFFLINE_GROW
_packages = ["xfsprogs"]
_fsck_class = fsck.XFSCK
_info_class = fsinfo.XFSInfo
@@ -1247,6 +1267,7 @@ class NTFS(FS):
_labelfs = fslabeling.NTFSLabeling()
_uuidfs = fsuuid.NTFSUUID()
_resizable = True
+ _resize_support = FSResize.OFFLINE_GROW | FSResize.OFFLINE_SHRINK
_formattable = True
_supported = True
_min_size = Size("1 MiB")
@@ -1490,6 +1511,9 @@ class TmpFS(NoDevFS):
# same, nothing actually needs to be set
pass
+ def _pre_resize(self):
+ self.do_check()
+
def do_resize(self):
# Override superclass method to record whether mount options
# should include an explicit size specification.
diff --git a/blivet/formats/fslib.py b/blivet/formats/fslib.py
index ea93b1fd..8722e942 100644
--- a/blivet/formats/fslib.py
+++ b/blivet/formats/fslib.py
@@ -36,3 +36,10 @@ def update_kernel_filesystems():
update_kernel_filesystems()
+
+
+class FSResize():
+ OFFLINE_SHRINK = 1 << 1
+ OFFLINE_GROW = 1 << 2
+ ONLINE_SHRINK = 1 << 3
+ ONLINE_GROW = 1 << 4
--
2.40.1
From 3fce5d0bfd7b09a976ff49feed15077477c6a425 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 6 Apr 2023 14:02:11 +0200
Subject: [PATCH 2/2] Add a test case for filesystem online resize
Related: rhbz#2168680
---
tests/storage_tests/formats_test/fs_test.py | 43 ++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/tests/storage_tests/formats_test/fs_test.py b/tests/storage_tests/formats_test/fs_test.py
index 97f4cbbe..1d42dc21 100644
--- a/tests/storage_tests/formats_test/fs_test.py
+++ b/tests/storage_tests/formats_test/fs_test.py
@@ -6,9 +6,10 @@ import parted
import blivet.formats.fs as fs
from blivet.size import Size, ROUND_DOWN
-from blivet.errors import DeviceFormatError
+from blivet.errors import DeviceFormatError, FSError
from blivet.formats import get_format
from blivet.devices import PartitionDevice, DiskDevice
+from blivet.flags import flags
from .loopbackedtestcase import LoopBackedTestCase
@@ -26,6 +27,46 @@ class Ext3FSTestCase(Ext2FSTestCase):
class Ext4FSTestCase(Ext3FSTestCase):
_fs_class = fs.Ext4FS
+ def test_online_resize(self):
+ an_fs = self._fs_class()
+ if not an_fs.formattable:
+ self.skipTest("can not create filesystem %s" % an_fs.name)
+ an_fs.device = self.loop_devices[0]
+ self.assertIsNone(an_fs.create())
+ an_fs.update_size_info()
+
+ if not self.can_resize(an_fs):
+ self.skipTest("filesystem is not resizable")
+
+ # shrink offline first (ext doesn't support online shrinking)
+ TARGET_SIZE = Size("64 MiB")
+ an_fs.target_size = TARGET_SIZE
+ self.assertEqual(an_fs.target_size, TARGET_SIZE)
+ self.assertNotEqual(an_fs._size, TARGET_SIZE)
+ self.assertIsNone(an_fs.do_resize())
+
+ with tempfile.TemporaryDirectory() as mountpoint:
+ an_fs.mount(mountpoint=mountpoint)
+
+ # grow back when mounted
+ TARGET_SIZE = Size("100 MiB")
+ an_fs.target_size = TARGET_SIZE
+ self.assertEqual(an_fs.target_size, TARGET_SIZE)
+ self.assertNotEqual(an_fs._size, TARGET_SIZE)
+
+ # should fail, online resize disabled by default
+ with self.assertRaisesRegex(FSError, "Resizing of mounted filesystems is disabled"):
+ an_fs.do_resize()
+
+ # enable online resize
+ flags.allow_online_fs_resize = True
+ an_fs.do_resize()
+ flags.allow_online_fs_resize = False
+ self._test_sizes(an_fs)
+ self.assertEqual(an_fs.system_mountpoint, mountpoint)
+
+ an_fs.unmount()
+
class FATFSTestCase(fstesting.FSAsRoot):
_fs_class = fs.FATFS
--
2.40.1

View File

@ -0,0 +1,382 @@
From d06c45db59d0e917dbab4c283f2f04c8f9206a6e Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 6 Mar 2023 10:51:42 +0100
Subject: [PATCH 1/5] Allow changing iSCSI initiator name after setting it
Resolves: rhbz#2083139
---
blivet/iscsi.py | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/blivet/iscsi.py b/blivet/iscsi.py
index 86451db3..0d063f2a 100644
--- a/blivet/iscsi.py
+++ b/blivet/iscsi.py
@@ -212,14 +212,23 @@ class iSCSI(object):
@initiator.setter
@storaged_iscsi_required(critical=True, eval_mode=util.EvalMode.onetime)
def initiator(self, val):
- if self.initiator_set and val != self._initiator:
- raise ValueError(_("Unable to change iSCSI initiator name once set"))
if len(val) == 0:
raise ValueError(_("Must provide an iSCSI initiator name"))
+ active = self._get_active_sessions()
+ if active:
+ raise errors.ISCSIError(_("Cannot change initiator name with an active session"))
+
log.info("Setting up iSCSI initiator name %s", self.initiator)
args = GLib.Variant("(sa{sv})", (val, None))
self._call_initiator_method("SetInitiatorName", args)
+
+ if self.initiator_set and val != self._initiator:
+ log.info("Restarting iscsid after initiator name change")
+ rc = util.run_program(["systemctl", "restart", "iscsid"])
+ if rc != 0:
+ raise errors.ISCSIError(_("Failed to restart iscsid after initiator name change"))
+
self._initiator = val
def active_nodes(self, target=None):
--
2.40.1
From b71991d65c270c023364b03c499b4bf3e245fbd0 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 6 Mar 2023 15:10:28 +0100
Subject: [PATCH 2/5] Add a basic test case for the iscsi module
Related: rhbz#2083139
---
tests/storage_tests/__init__.py | 2 +
tests/storage_tests/iscsi_test.py | 157 +++++++++++++++++++++++++++++
3 files changed, 162 insertions(+)
create mode 100644 tests/storage_tests/iscsi_test.py
diff --git a/tests/storage_tests/__init__.py b/tests/storage_tests/__init__.py
index 3b2a6cc4..e69fcc34 100644
--- a/tests/storage_tests/__init__.py
+++ b/tests/storage_tests/__init__.py
@@ -3,3 +3,5 @@ from .formats_test import *
from .partitioning_test import *
from .unsupported_disklabel_test import *
+
+from .iscsi_test import *
diff --git a/tests/storage_tests/iscsi_test.py b/tests/storage_tests/iscsi_test.py
new file mode 100644
index 00000000..00cc7c36
--- /dev/null
+++ b/tests/storage_tests/iscsi_test.py
@@ -0,0 +1,157 @@
+import glob
+import os
+import re
+import shutil
+import subprocess
+import unittest
+
+from contextlib import contextmanager
+
+from .storagetestcase import create_sparse_tempfile
+
+
+def read_file(filename, mode="r"):
+ with open(filename, mode) as f:
+ content = f.read()
+ return content
+
+
+@contextmanager
+def udev_settle():
+ try:
+ yield
+ finally:
+ os.system("udevadm settle")
+
+
+def _delete_backstore(name):
+ status = subprocess.call(["targetcli", "/backstores/fileio/ delete %s" % name],
+ stdout=subprocess.DEVNULL)
+ if status != 0:
+ raise RuntimeError("Failed to delete the '%s' fileio backstore" % name)
+
+
+def delete_iscsi_target(iqn, backstore=None):
+ status = subprocess.call(["targetcli", "/iscsi delete %s" % iqn],
+ stdout=subprocess.DEVNULL)
+ if status != 0:
+ raise RuntimeError("Failed to delete the '%s' iscsi device" % iqn)
+
+ if backstore is not None:
+ _delete_backstore(backstore)
+
+
+def create_iscsi_target(fpath, initiator_name=None):
+ """
+ Creates a new iSCSI target (using targetcli) on top of the
+ :param:`fpath` backing file.
+
+ :param str fpath: path of the backing file
+ :returns: iSCSI IQN, backstore name
+ :rtype: tuple of str
+
+ """
+
+ # "register" the backing file as a fileio backstore
+ store_name = os.path.basename(fpath)
+ status = subprocess.call(["targetcli", "/backstores/fileio/ create %s %s" % (store_name, fpath)], stdout=subprocess.DEVNULL)
+ if status != 0:
+ raise RuntimeError("Failed to register '%s' as a fileio backstore" % fpath)
+
+ out = subprocess.check_output(["targetcli", "/backstores/fileio/%s info" % store_name])
+ out = out.decode("utf-8")
+ store_wwn = None
+ for line in out.splitlines():
+ if line.startswith("wwn: "):
+ store_wwn = line[5:]
+ if store_wwn is None:
+ raise RuntimeError("Failed to determine '%s' backstore's wwn" % store_name)
+
+ # create a new iscsi device
+ out = subprocess.check_output(["targetcli", "/iscsi create"])
+ out = out.decode("utf-8")
+ match = re.match(r'Created target (.*).', out)
+ if match:
+ iqn = match.groups()[0]
+ else:
+ _delete_backstore(store_name)
+ raise RuntimeError("Failed to create a new iscsi target")
+
+ if initiator_name:
+ status = subprocess.call(["targetcli", "/iscsi/%s/tpg1/acls create %s" % (iqn, initiator_name)], stdout=subprocess.DEVNULL)
+ if status != 0:
+ delete_iscsi_target(iqn, store_name)
+ raise RuntimeError("Failed to set ACLs for '%s'" % iqn)
+
+ with udev_settle():
+ status = subprocess.call(["targetcli", "/iscsi/%s/tpg1/luns create /backstores/fileio/%s" % (iqn, store_name)], stdout=subprocess.DEVNULL)
+ if status != 0:
+ delete_iscsi_target(iqn, store_name)
+ raise RuntimeError("Failed to create a new LUN for '%s' using '%s'" % (iqn, store_name))
+
+ status = subprocess.call(["targetcli", "/iscsi/%s/tpg1 set attribute generate_node_acls=1" % iqn], stdout=subprocess.DEVNULL)
+ if status != 0:
+ raise RuntimeError("Failed to set ACLs for '%s'" % iqn)
+
+ return iqn, store_name
+
+
+@unittest.skipUnless(os.geteuid() == 0, "requires root privileges")
+@unittest.skipUnless(os.environ.get("JENKINS_HOME"), "jenkins only test")
+@unittest.skipUnless(shutil.which("iscsiadm"), "iscsiadm not available")
+class ISCSITestCase(unittest.TestCase):
+
+ _disk_size = 512 * 1024**2
+ initiator = 'iqn.1994-05.com.redhat:iscsi-test'
+
+ def setUp(self):
+ self.addCleanup(self._clean_up)
+
+ self._dev_file = None
+ self.dev = None
+
+ self._dev_file = create_sparse_tempfile("blivet_test", self._disk_size)
+ try:
+ self.dev, self.backstore = create_iscsi_target(self._dev_file, self.initiator)
+ except RuntimeError as e:
+ raise RuntimeError("Failed to setup targetcli device for testing: %s" % e)
+
+ def _force_logout(self):
+ subprocess.call(["iscsiadm", "--mode", "node", "--logout", "--name", self.dev], stdout=subprocess.DEVNULL)
+
+ def _clean_up(self):
+ self._force_logout()
+ delete_iscsi_target(self.dev, self.backstore)
+ os.unlink(self._dev_file)
+
+ def test_discover_login(self):
+ from blivet.iscsi import iscsi, has_iscsi
+
+ if not has_iscsi():
+ self.skipTest("iSCSI not available, skipping")
+
+ iscsi.initiator = self.initiator
+ nodes = iscsi.discover("127.0.0.1")
+ self.assertTrue(nodes)
+
+ if len(nodes) > 1:
+ self.skipTest("Discovered more than one iSCSI target on localhost, skipping")
+
+ self.assertEqual(nodes[0].address, "127.0.0.1")
+ self.assertEqual(nodes[0].port, 3260)
+ self.assertEqual(nodes[0].name, self.dev)
+
+ # change the initiator name
+ iscsi.initiator = self.initiator + "_1"
+ self.assertEqual(iscsi.initiator, self.initiator + "_1")
+
+ # try to login
+ ret, err = iscsi.log_into_node(nodes[0])
+ self.assertTrue(ret, "Login failed: %s" % err)
+
+ # check the session for initiator name
+ sessions = glob.glob("/sys/class/iscsi_session/*/")
+ self.assertTrue(sessions)
+ self.assertEqual(len(sessions), 1)
+ initiator = read_file(sessions[0] + "initiatorname").strip()
+ self.assertEqual(initiator, iscsi.initiator)
--
2.40.1
From 65e8150a7404e37dd2740841a88e7f2565836406 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 6 Mar 2023 15:14:40 +0100
Subject: [PATCH 3/5] tests: Use blivet-specific prefix for targetcli backing
files
The code is originally from libblockdev hence the "bd" prefix, we
should use a different prefix for blivet to be able to identify
which test suite failed to clean the files.
Related: rhbz#2083139
---
tests/storage_tests/storagetestcase.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/storage_tests/storagetestcase.py b/tests/storage_tests/storagetestcase.py
index 35d57ce9..9f859977 100644
--- a/tests/storage_tests/storagetestcase.py
+++ b/tests/storage_tests/storagetestcase.py
@@ -39,7 +39,7 @@ def create_sparse_tempfile(name, size):
:param size: the file size (in bytes)
:returns: the path to the newly created file
"""
- (fd, path) = tempfile.mkstemp(prefix="bd.", suffix="-%s" % name)
+ (fd, path) = tempfile.mkstemp(prefix="blivet.", suffix="-%s" % name)
os.close(fd)
create_sparse_file(path, size)
return path
--
2.40.1
From 41278ef1b3f949303fd30fff2ccdde75f713c9f8 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 19 Jul 2023 13:57:39 +0200
Subject: [PATCH 4/5] iscsi: Save firmware initiator name to
/etc/iscsi/initiatorname.iscsi
Resolves: rhbz#2084043
---
blivet/iscsi.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/blivet/iscsi.py b/blivet/iscsi.py
index 0d063f2a..8080a671 100644
--- a/blivet/iscsi.py
+++ b/blivet/iscsi.py
@@ -160,6 +160,11 @@ class iSCSI(object):
self._initiator = initiatorname
except Exception as e: # pylint: disable=broad-except
log.info("failed to get initiator name from iscsi firmware: %s", str(e))
+ else:
+ # write the firmware initiator to /etc/iscsi/initiatorname.iscsi
+ log.info("Setting up firmware iSCSI initiator name %s", self.initiator)
+ args = GLib.Variant("(sa{sv})", (initiatorname, None))
+ self._call_initiator_method("SetInitiatorName", args)
# So that users can write iscsi() to get the singleton instance
def __call__(self):
--
2.40.1
From fce8b73965d968aab546bc7e0ecb65d1995da46f Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Wed, 19 Jul 2023 10:38:45 +0200
Subject: [PATCH 5/5] tests: Improve iscsi_test.ISCSITestCase
Changed how we create the initiator name ACLs based on RTT test
case for rhbz#2084043 and also improved the test case itself.
Related: rhbz#2083139
---
tests/storage_tests/iscsi_test.py | 36 +++++++++++++++++++++----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/tests/storage_tests/iscsi_test.py b/tests/storage_tests/iscsi_test.py
index 00cc7c36..6cc83a59 100644
--- a/tests/storage_tests/iscsi_test.py
+++ b/tests/storage_tests/iscsi_test.py
@@ -77,21 +77,17 @@ def create_iscsi_target(fpath, initiator_name=None):
_delete_backstore(store_name)
raise RuntimeError("Failed to create a new iscsi target")
- if initiator_name:
- status = subprocess.call(["targetcli", "/iscsi/%s/tpg1/acls create %s" % (iqn, initiator_name)], stdout=subprocess.DEVNULL)
- if status != 0:
- delete_iscsi_target(iqn, store_name)
- raise RuntimeError("Failed to set ACLs for '%s'" % iqn)
-
with udev_settle():
status = subprocess.call(["targetcli", "/iscsi/%s/tpg1/luns create /backstores/fileio/%s" % (iqn, store_name)], stdout=subprocess.DEVNULL)
if status != 0:
delete_iscsi_target(iqn, store_name)
raise RuntimeError("Failed to create a new LUN for '%s' using '%s'" % (iqn, store_name))
- status = subprocess.call(["targetcli", "/iscsi/%s/tpg1 set attribute generate_node_acls=1" % iqn], stdout=subprocess.DEVNULL)
- if status != 0:
- raise RuntimeError("Failed to set ACLs for '%s'" % iqn)
+ if initiator_name:
+ status = subprocess.call(["targetcli", "/iscsi/%s/tpg1/acls create %s" % (iqn, initiator_name)], stdout=subprocess.DEVNULL)
+ if status != 0:
+ delete_iscsi_target(iqn, store_name)
+ raise RuntimeError("Failed to set ACLs for '%s'" % iqn)
return iqn, store_name
@@ -130,6 +126,7 @@ class ISCSITestCase(unittest.TestCase):
if not has_iscsi():
self.skipTest("iSCSI not available, skipping")
+ # initially set the initiator to the correct/allowed one
iscsi.initiator = self.initiator
nodes = iscsi.discover("127.0.0.1")
self.assertTrue(nodes)
@@ -141,11 +138,28 @@ class ISCSITestCase(unittest.TestCase):
self.assertEqual(nodes[0].port, 3260)
self.assertEqual(nodes[0].name, self.dev)
- # change the initiator name
+ # change the initiator name to a wrong one
iscsi.initiator = self.initiator + "_1"
self.assertEqual(iscsi.initiator, self.initiator + "_1")
- # try to login
+ # check the change made it to /etc/iscsi/initiatorname.iscsi
+ initiator_file = read_file("/etc/iscsi/initiatorname.iscsi").strip()
+ self.assertEqual(initiator_file, "InitiatorName=%s" % self.initiator + "_1")
+
+ # try to login (should fail)
+ ret, err = iscsi.log_into_node(nodes[0])
+ self.assertFalse(ret)
+ self.assertIn("authorization failure", err)
+
+ # change the initiator name back to the correct one
+ iscsi.initiator = self.initiator
+ self.assertEqual(iscsi.initiator, self.initiator)
+
+ # check the change made it to /etc/iscsi/initiatorname.iscsi
+ initiator_file = read_file("/etc/iscsi/initiatorname.iscsi").strip()
+ self.assertEqual(initiator_file, "InitiatorName=%s" % self.initiator)
+
+ # try to login (should work now)
ret, err = iscsi.log_into_node(nodes[0])
self.assertTrue(ret, "Login failed: %s" % err)
--
2.40.1

View File

@ -0,0 +1,206 @@
From faef0408d2f7c61aade6d187389c61e64f9f373b Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Thu, 20 Apr 2023 12:35:30 +0200
Subject: [PATCH] Add support for creating shared LVM setups
This feature is requested by GFS2 for the storage role. This adds
support for creating shared VGs and activating LVs in shared mode.
Resolves: RHEL-14021
---
blivet/devices/lvm.py | 44 +++++++++++++++++++----
blivet/tasks/availability.py | 9 +++++
tests/unit_tests/devices_test/lvm_test.py | 25 +++++++++++++
3 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index ca45c4b5..068c5368 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -97,7 +97,8 @@ class LVMVolumeGroupDevice(ContainerDevice):
def __init__(self, name, parents=None, size=None, free=None,
pe_size=None, pe_count=None, pe_free=None, pv_count=None,
- uuid=None, exists=False, sysfs_path='', exported=False):
+ uuid=None, exists=False, sysfs_path='', exported=False,
+ shared=False):
"""
:param name: the device name (generally a device node's basename)
:type name: str
@@ -124,6 +125,11 @@ class LVMVolumeGroupDevice(ContainerDevice):
:type pv_count: int
:keyword uuid: the VG UUID
:type uuid: str
+
+ For non-existing VGs only:
+
+ :keyword shared: whether to create this VG as shared
+ :type shared: bool
"""
# These attributes are used by _add_parent, so they must be initialized
# prior to instantiating the superclass.
@@ -137,6 +143,7 @@ class LVMVolumeGroupDevice(ContainerDevice):
self.pe_count = util.numeric_type(pe_count)
self.pe_free = util.numeric_type(pe_free)
self.exported = exported
+ self._shared = shared
# TODO: validate pe_size if given
if not self.pe_size:
@@ -254,7 +261,19 @@ class LVMVolumeGroupDevice(ContainerDevice):
""" Create the device. """
log_method_call(self, self.name, status=self.status)
pv_list = [pv.path for pv in self.parents]
- blockdev.lvm.vgcreate(self.name, pv_list, self.pe_size)
+ extra = dict()
+ if self._shared:
+ extra["shared"] = ""
+ blockdev.lvm.vgcreate(self.name, pv_list, self.pe_size, **extra)
+
+ if self._shared:
+ if availability.BLOCKDEV_LVM_PLUGIN_SHARED.available:
+ try:
+ blockdev.lvm.vglock_start(self.name)
+ except blockdev.LVMError as err:
+ raise errors.LVMError(err)
+ else:
+ raise errors.LVMError("Shared LVM is not fully supported: %s" % ",".join(availability.BLOCKDEV_LVM_PLUGIN_SHARED.availability_errors))
def _post_create(self):
self._complete = True
@@ -661,7 +680,7 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
def __init__(self, name, parents=None, size=None, uuid=None, seg_type=None,
fmt=None, exists=False, sysfs_path='', grow=None, maxsize=None,
percent=None, cache_request=None, pvs=None, from_lvs=None,
- stripe_size=0):
+ stripe_size=0, shared=False):
if not exists:
if seg_type not in [None, "linear", "thin", "thin-pool", "cache", "vdo-pool", "vdo", "cache-pool"] + lvm.raid_seg_types:
@@ -690,6 +709,7 @@ class LVMLogicalVolumeBase(DMDevice, RaidDevice):
self.seg_type = seg_type or "linear"
self._raid_level = None
self.ignore_skip_activation = 0
+ self._shared = shared
self.req_grow = None
self.req_max_size = Size(0)
@@ -2306,7 +2326,8 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
parent_lv=None, int_type=None, origin=None, vorigin=False,
metadata_size=None, chunk_size=None, profile=None, from_lvs=None,
compression=False, deduplication=False, index_memory=0,
- write_policy=None, cache_mode=None, attach_to=None, stripe_size=0):
+ write_policy=None, cache_mode=None, attach_to=None, stripe_size=0,
+ shared=False):
"""
:param name: the device name (generally a device node's basename)
:type name: str
@@ -2337,6 +2358,8 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
:type cache_request: :class:`~.devices.lvm.LVMCacheRequest`
:keyword pvs: list of PVs to allocate extents from (size could be specified for each PV)
:type pvs: list of :class:`~.devices.StorageDevice` or :class:`LVPVSpec` objects (tuples)
+ :keyword shared: whether to activate the newly create LV in shared mode
+ :type shared: bool
For internal LVs only:
@@ -2412,7 +2435,7 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
LVMLogicalVolumeBase.__init__(self, name, parents, size, uuid, seg_type,
fmt, exists, sysfs_path, grow, maxsize,
percent, cache_request, pvs, from_lvs,
- stripe_size)
+ stripe_size, shared)
LVMVDOPoolMixin.__init__(self, compression, deduplication, index_memory,
write_policy)
LVMVDOLogicalVolumeMixin.__init__(self)
@@ -2634,7 +2657,13 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
log_method_call(self, self.name, orig=orig, status=self.status,
controllable=self.controllable)
ignore_skip_activation = self.is_snapshot_lv or self.ignore_skip_activation > 0
- blockdev.lvm.lvactivate(self.vg.name, self._name, ignore_skip=ignore_skip_activation)
+ if self._shared:
+ if availability.BLOCKDEV_LVM_PLUGIN_SHARED.available:
+ blockdev.lvm.lvactivate(self.vg.name, self._name, ignore_skip=ignore_skip_activation, shared=True)
+ else:
+ raise errors.LVMError("Shared LVM is not fully supported: %s" % ",".join(availability.BLOCKDEV_LVM_PLUGIN_SHARED.availability_errors))
+ else:
+ blockdev.lvm.lvactivate(self.vg.name, self._name, ignore_skip=ignore_skip_activation)
@type_specific
def _pre_create(self):
@@ -2672,6 +2701,9 @@ class LVMLogicalVolumeDevice(LVMLogicalVolumeBase, LVMInternalLogicalVolumeMixin
if self._stripe_size:
extra["stripesize"] = str(int(self._stripe_size.convert_to("KiB")))
+ if self._shared:
+ extra["activate"] = "sy"
+
blockdev.lvm.lvcreate(self.vg.name, self._name, self.size,
type=self.seg_type, pv_list=pvs, **extra)
else:
diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py
index bba1ba84..85945c77 100644
--- a/blivet/tasks/availability.py
+++ b/blivet/tasks/availability.py
@@ -435,6 +435,14 @@ if hasattr(blockdev.LVMTech, "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")
+
# libblockdev mdraid plugin required technologies and modes
BLOCKDEV_MD_ALL_MODES = (blockdev.MDTechMode.CREATE |
blockdev.MDTechMode.DELETE |
@@ -476,6 +484,7 @@ BLOCKDEV_DM_PLUGIN_RAID = blockdev_plugin("libblockdev dm plugin (raid technolog
BLOCKDEV_LOOP_PLUGIN = blockdev_plugin("libblockdev loop plugin", BLOCKDEV_LOOP_TECH)
BLOCKDEV_LVM_PLUGIN = blockdev_plugin("libblockdev lvm plugin", BLOCKDEV_LVM_TECH)
BLOCKDEV_LVM_PLUGIN_VDO = blockdev_plugin("libblockdev lvm plugin (vdo technology)", BLOCKDEV_LVM_TECH_VDO)
+BLOCKDEV_LVM_PLUGIN_SHARED = blockdev_plugin("libblockdev lvm plugin (shared LVM technology)", BLOCKDEV_LVM_TECH_SHARED)
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)
diff --git a/tests/unit_tests/devices_test/lvm_test.py b/tests/unit_tests/devices_test/lvm_test.py
index d7b55224..e645309f 100644
--- a/tests/unit_tests/devices_test/lvm_test.py
+++ b/tests/unit_tests/devices_test/lvm_test.py
@@ -476,6 +476,31 @@ class LVMDeviceTest(unittest.TestCase):
lv.setup()
lvm.lvactivate.assert_called_with(vg.name, lv.lvname, ignore_skip=False)
+ @patch("blivet.tasks.availability.BLOCKDEV_LVM_PLUGIN_SHARED",
+ new=blivet.tasks.availability.ExternalResource(blivet.tasks.availability.AvailableMethod, ""))
+ def test_lv_activate_shared(self):
+ pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
+ size=Size("1 GiB"), exists=True)
+ vg = LVMVolumeGroupDevice("testvg", parents=[pv], exists=True)
+ lv = LVMLogicalVolumeDevice("data_lv", parents=[vg], size=Size("500 MiB"), exists=True, shared=True)
+
+ with patch("blivet.devices.lvm.blockdev.lvm") as lvm:
+ with patch.object(lv, "_pre_setup"):
+ lv.setup()
+ lvm.lvactivate.assert_called_with(vg.name, lv.lvname, ignore_skip=False, shared=True)
+
+ @patch("blivet.tasks.availability.BLOCKDEV_LVM_PLUGIN_SHARED",
+ new=blivet.tasks.availability.ExternalResource(blivet.tasks.availability.AvailableMethod, ""))
+ def test_vg_create_shared(self):
+ pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
+ size=Size("1 GiB"), exists=True)
+ vg = LVMVolumeGroupDevice("testvg", parents=[pv], shared=True)
+
+ with patch("blivet.devices.lvm.blockdev.lvm") as lvm:
+ vg._create()
+ lvm.vgcreate.assert_called_with(vg.name, [pv.path], Size("4 MiB"), shared="")
+ lvm.vglock_start.assert_called_with(vg.name)
+
def test_vg_is_empty(self):
pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
size=Size("1024 MiB"))
--
2.41.0

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-10
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -1,2 +0,0 @@
SHA512 (blivet-3.10.0.tar.gz) = 74172dec98a1b4f71cee6d64d46cdafa5116cfbbaddfdaed3dd118fef019dce54ff9d9206faada5991efac6b61bc558bb3050165f1d68bde1c1ec228c01916c8
SHA512 (blivet-3.10.0-tests.tar.gz) = 53d2f37ff9822141caf669889835069da6e3f728761c0d006afcf80a2628f8816cbf558d30a085082e1bfec2e4b575f9ea78859a17f4e0bf7458e3faba158ef7

View File

@ -1 +0,0 @@
1

View File

@ -1,42 +0,0 @@
#!/usr/bin/python3
import argparse
import sys
import blivet
POOL_NAME = "blivet_test"
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--disks', default='')
args = parser.parse_args()
b = blivet.Blivet()
b.reset()
disks = list()
for disk_id in args.disks.split(','):
disk = b.devicetree.resolve_device(disk_id)
if not disk.is_disk:
sys.stderr.write("specified disk '%s' is not a disk\n" % disk_id)
sys.exit(1)
disks.append(disk)
b.initialize_disk(disk)
if len(disks) > 1:
container_raid_level = "raid1"
total_size = min(d.size for d in disks)
else:
container_raid_level = None
total_size = sum(d.size for d in disks)
lv1 = b.factory_device(size=total_size*0.8, disks=disks,
name="lv1", container_name=POOL_NAME,
fstype='xfs', device_type=blivet.devicefactory.DEVICE_TYPE_LVM)
lv2 = b.factory_device(disks=disks, name="lv2",
container_name=POOL_NAME, container_raid_level='raid1',
fstype='ext4', device_type=blivet.devicefactory.DEVICE_TYPE_LVM)
b.do_it()

View File

@ -1,8 +0,0 @@
---
standard-inventory-qcow2:
qemu:
m: 1G
drive:
- size: 10737418240
- size: 10737418240

View File

@ -1,25 +0,0 @@
---
# - hosts: localhost
- hosts: all
roles:
- role: standard-test-source
tags:
- always
- role: standard-test-basic
tags:
- atomic
- classic
required_packages:
- python3
- python3-dbus
- libblockdev-plugins-all
- python3-yaml
- targetcli
- stratis-cli
- stratisd
tests:
- unit-tests:
dir: .
run: ./unit_testing.sh

View File

@ -1,11 +0,0 @@
#!/bin/bash
# Bail out if anything goes wrong
set -e
# Get path to blivet
blivet_path=$(find /usr/ -path */site-packages | tr '\n' ':')
# Run upstream unit tests
cd ./source/
PYTHONPATH=$blivet_path python3 tests/run_tests.py