From 75cb9d05b376451448c1c0f5787f437855d15cce Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Fri, 9 Feb 2024 10:17:12 +0100 Subject: [PATCH] Do not add new PVs to the LVM devices file if it doesn't exist and VGs are present Resolves: RHEL-473 --- ...Vs-to-the-LVM-devices-file-if-it-doe.patch | 172 ++++++++++++++++++ python-blivet.spec | 7 +- 2 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 0023-Do-not-add-new-PVs-to-the-LVM-devices-file-if-it-doe.patch diff --git a/0023-Do-not-add-new-PVs-to-the-LVM-devices-file-if-it-doe.patch b/0023-Do-not-add-new-PVs-to-the-LVM-devices-file-if-it-doe.patch new file mode 100644 index 0000000..5be2982 --- /dev/null +++ b/0023-Do-not-add-new-PVs-to-the-LVM-devices-file-if-it-doe.patch @@ -0,0 +1,172 @@ +From 517f17481685afbabea6750b57d71a736f9a157e Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 25 May 2023 17:02:39 +0200 +Subject: [PATCH] Do not add new PVs to the LVM devices file if it doesn't + exist and VGs are present + +If there is a preexisting VG on the system when we create a new PV +and the LVM devices file doesn't exist we will create it and add +only the new PV to it which means the preexisting VG will now be +ignored by LVM tools. This change skips adding newly created PVs +to the devices file in the same way 'pvcreate' and 'vgcreate' do. +--- + blivet/devicelibs/lvm.py | 3 + + blivet/formats/lvmpv.py | 17 ++++- + tests/unit_tests/formats_tests/__init__.py | 1 + + tests/unit_tests/formats_tests/lvmpv_test.py | 73 ++++++++++++++++++++ + 4 files changed, 91 insertions(+), 3 deletions(-) + create mode 100644 tests/unit_tests/formats_tests/lvmpv_test.py + +diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py +index 16a8e8f8..dc7d0cbe 100644 +--- a/blivet/devicelibs/lvm.py ++++ b/blivet/devicelibs/lvm.py +@@ -84,6 +84,9 @@ if hasattr(blockdev.LVMTech, "DEVICES"): + else: + HAVE_LVMDEVICES = False + ++ ++LVM_DEVICES_FILE = "/etc/lvm/devices/system.devices" ++ + # list of devices that LVM is allowed to use + # with LVM >= 2.0.13 we'll use this for the --devices option and when creating + # the /etc/lvm/devices/system.devices file +diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py +index cb01b2f3..65acedbe 100644 +--- a/blivet/formats/lvmpv.py ++++ b/blivet/formats/lvmpv.py +@@ -36,7 +36,7 @@ from ..size import Size + from ..errors import PhysicalVolumeError + from . import DeviceFormat, register_device_format + from .. import udev +-from ..static_data.lvm_info import pvs_info ++from ..static_data.lvm_info import pvs_info, vgs_info + + import logging + log = logging.getLogger("blivet") +@@ -121,10 +121,21 @@ class LVMPhysicalVolume(DeviceFormat): + def supported(self): + return super(LVMPhysicalVolume, self).supported and self._plugin.available + +- def lvmdevices_add(self): ++ def lvmdevices_add(self, force=True): ++ """ Add this PV to the LVM system devices file ++ :keyword force: whether to add the PV even if the system devices file doesn't exist and ++ VGs are present in the system ++ :type force: bool ++ """ ++ + if not lvm.HAVE_LVMDEVICES: + raise PhysicalVolumeError("LVM devices file feature is not supported") + ++ if not os.path.exists(lvm.LVM_DEVICES_FILE) and vgs_info.cache and not force: ++ log.debug("Not adding %s to devices file: %s doesn't exist and there are VGs present in the system", ++ self.device, lvm.LVM_DEVICES_FILE) ++ return ++ + try: + blockdev.lvm.devices_add(self.device) + except blockdev.LVMError as e: +@@ -151,7 +162,7 @@ class LVMPhysicalVolume(DeviceFormat): + # with lvmdbusd we need to call the pvcreate without --devices otherwise lvmdbusd + # wouldn't be able to find the newly created pv and the call would fail + blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes]) +- self.lvmdevices_add() ++ self.lvmdevices_add(force=False) + else: + blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes]) + +diff --git a/tests/unit_tests/formats_tests/__init__.py b/tests/unit_tests/formats_tests/__init__.py +index d678900b..95c7a25b 100644 +--- a/tests/unit_tests/formats_tests/__init__.py ++++ b/tests/unit_tests/formats_tests/__init__.py +@@ -2,6 +2,7 @@ from .device_test import * + from .disklabel_test import * + from .init_test import * + from .luks_test import * ++from .lvmpv_test import * + from .methods_test import * + from .misc_test import * + from .selinux_test import * +diff --git a/tests/unit_tests/formats_tests/lvmpv_test.py b/tests/unit_tests/formats_tests/lvmpv_test.py +new file mode 100644 +index 00000000..6490c7d4 +--- /dev/null ++++ b/tests/unit_tests/formats_tests/lvmpv_test.py +@@ -0,0 +1,73 @@ ++try: ++ from unittest.mock import patch ++except ImportError: ++ from mock import patch ++ ++from contextlib import contextmanager ++ ++import unittest ++ ++from blivet.formats.lvmpv import LVMPhysicalVolume ++ ++ ++class LVMPVNodevTestCase(unittest.TestCase): ++ ++ @contextmanager ++ def patches(self): ++ patchers = dict() ++ mocks = dict() ++ ++ patchers["blockdev"] = patch("blivet.formats.lvmpv.blockdev") ++ patchers["lvm"] = patch("blivet.formats.lvmpv.lvm") ++ patchers["vgs_info"] = patch("blivet.formats.lvmpv.vgs_info") ++ patchers["os"] = patch("blivet.formats.lvmpv.os") ++ ++ for name, patcher in patchers.items(): ++ mocks[name] = patcher.start() ++ ++ yield mocks ++ ++ for patcher in patchers.values(): ++ patcher.stop() ++ ++ def test_lvm_devices(self): ++ fmt = LVMPhysicalVolume(device="/dev/test") ++ ++ with self.patches() as mock: ++ # LVM devices file not enabled/supported -> devices_add should not be called ++ mock["lvm"].HAVE_LVMDEVICES = False ++ ++ fmt._create() ++ ++ mock["blockdev"].lvm.devices_add.assert_not_called() ++ ++ with self.patches() as mock: ++ # LVM devices file enabled and devices file exists -> devices_add should be called ++ mock["lvm"].HAVE_LVMDEVICES = True ++ mock["os"].path.exists.return_value = True ++ ++ fmt._create() ++ ++ mock["blockdev"].lvm.devices_add.assert_called_with("/dev/test") ++ ++ with self.patches() as mock: ++ # LVM devices file enabled and devices file doesn't exist ++ # and no existing VGs present -> devices_add should be called ++ mock["lvm"].HAVE_LVMDEVICES = True ++ mock["os"].path.exists.return_value = False ++ mock["vgs_info"].cache = {} ++ ++ fmt._create() ++ ++ mock["blockdev"].lvm.devices_add.assert_called_with("/dev/test") ++ ++ with self.patches() as mock: ++ # LVM devices file enabled and devices file doesn't exist ++ # and existing VGs present -> devices_add should not be called ++ mock["lvm"].HAVE_LVMDEVICES = True ++ mock["os"].path.exists.return_value = False ++ mock["vgs_info"].cache = {"fake_vg_uuid": "fake_vg_data"} ++ ++ fmt._create() ++ ++ mock["blockdev"].lvm.devices_add.assert_not_called() +-- +2.43.0 + diff --git a/python-blivet.spec b/python-blivet.spec index 80d2878..487907f 100644 --- a/python-blivet.spec +++ b/python-blivet.spec @@ -23,7 +23,7 @@ Version: 3.6.0 #%%global prerelease .b2 # prerelease, if defined, should be something like .a1, .b1, .b2.dev1, or .c2 -Release: 13%{?prerelease}%{?dist} +Release: 14%{?prerelease}%{?dist} Epoch: 1 License: LGPLv2+ %global realname blivet @@ -52,6 +52,7 @@ Patch18: 0019-nvme-hostnqn_from_active_fabrics_connection.patch Patch19: 0020-nvme-add_unit_tests.patch Patch20: 0021-Add-support-for-creating-shared-LVM-setups.patch Patch21: 0022-add-udev-builtin-path_id-property-to-zfcp-attached-S.patch +Patch22: 0023-Do-not-add-new-PVs-to-the-LVM-devices-file-if-it-doe.patch # Versions of required components (done so we make sure the buildrequires # match the requires versions of things). @@ -215,6 +216,10 @@ configuration. %endif %changelog +* Fri Feb 09 2024 Vojtech Trefny - 3.6.0-14 +- Do not add new PVs to the LVM devices file if it doesn't exist and VGs are present + Resolves: RHEL-473 + * Thu Jan 18 2024 Vojtech Trefny - 3.6.0-13 - add udev-builtin-path_id property to zfcp-attached SCSI disks Resolves: RHEL-22007