Vojtech Trefny 75cb9d
From 517f17481685afbabea6750b57d71a736f9a157e Mon Sep 17 00:00:00 2001
Vojtech Trefny 75cb9d
From: Vojtech Trefny <vtrefny@redhat.com>
Vojtech Trefny 75cb9d
Date: Thu, 25 May 2023 17:02:39 +0200
Vojtech Trefny 75cb9d
Subject: [PATCH] Do not add new PVs to the LVM devices file if it doesn't
Vojtech Trefny 75cb9d
 exist and VGs are present
Vojtech Trefny 75cb9d
Vojtech Trefny 75cb9d
If there is a preexisting VG on the system when we create a new PV
Vojtech Trefny 75cb9d
and the LVM devices file doesn't exist we will create it and add
Vojtech Trefny 75cb9d
only the new PV to it which means the preexisting VG will now be
Vojtech Trefny 75cb9d
ignored by LVM tools. This change skips adding newly created PVs
Vojtech Trefny 75cb9d
to the devices file in the same way 'pvcreate' and 'vgcreate' do.
Vojtech Trefny 75cb9d
---
Vojtech Trefny 75cb9d
 blivet/devicelibs/lvm.py                     |  3 +
Vojtech Trefny 75cb9d
 blivet/formats/lvmpv.py                      | 17 ++++-
Vojtech Trefny 75cb9d
 tests/unit_tests/formats_tests/__init__.py   |  1 +
Vojtech Trefny 75cb9d
 tests/unit_tests/formats_tests/lvmpv_test.py | 73 ++++++++++++++++++++
Vojtech Trefny 75cb9d
 4 files changed, 91 insertions(+), 3 deletions(-)
Vojtech Trefny 75cb9d
 create mode 100644 tests/unit_tests/formats_tests/lvmpv_test.py
Vojtech Trefny 75cb9d
Vojtech Trefny 75cb9d
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
Vojtech Trefny 75cb9d
index 16a8e8f8..dc7d0cbe 100644
Vojtech Trefny 75cb9d
--- a/blivet/devicelibs/lvm.py
Vojtech Trefny 75cb9d
+++ b/blivet/devicelibs/lvm.py
Vojtech Trefny 75cb9d
@@ -84,6 +84,9 @@ if hasattr(blockdev.LVMTech, "DEVICES"):
Vojtech Trefny 75cb9d
 else:
Vojtech Trefny 75cb9d
     HAVE_LVMDEVICES = False
Vojtech Trefny 75cb9d
 
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+LVM_DEVICES_FILE = "/etc/lvm/devices/system.devices"
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
 # list of devices that LVM is allowed to use
Vojtech Trefny 75cb9d
 # with LVM >= 2.0.13 we'll use this for the --devices option and when creating
Vojtech Trefny 75cb9d
 # the /etc/lvm/devices/system.devices file
Vojtech Trefny 75cb9d
diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py
Vojtech Trefny 75cb9d
index cb01b2f3..65acedbe 100644
Vojtech Trefny 75cb9d
--- a/blivet/formats/lvmpv.py
Vojtech Trefny 75cb9d
+++ b/blivet/formats/lvmpv.py
Vojtech Trefny 75cb9d
@@ -36,7 +36,7 @@ from ..size import Size
Vojtech Trefny 75cb9d
 from ..errors import PhysicalVolumeError
Vojtech Trefny 75cb9d
 from . import DeviceFormat, register_device_format
Vojtech Trefny 75cb9d
 from .. import udev
Vojtech Trefny 75cb9d
-from ..static_data.lvm_info import pvs_info
Vojtech Trefny 75cb9d
+from ..static_data.lvm_info import pvs_info, vgs_info
Vojtech Trefny 75cb9d
 
Vojtech Trefny 75cb9d
 import logging
Vojtech Trefny 75cb9d
 log = logging.getLogger("blivet")
Vojtech Trefny 75cb9d
@@ -121,10 +121,21 @@ class LVMPhysicalVolume(DeviceFormat):
Vojtech Trefny 75cb9d
     def supported(self):
Vojtech Trefny 75cb9d
         return super(LVMPhysicalVolume, self).supported and self._plugin.available
Vojtech Trefny 75cb9d
 
Vojtech Trefny 75cb9d
-    def lvmdevices_add(self):
Vojtech Trefny 75cb9d
+    def lvmdevices_add(self, force=True):
Vojtech Trefny 75cb9d
+        """ Add this PV to the LVM system devices file
Vojtech Trefny 75cb9d
+            :keyword force: whether to add the PV even if the system devices file doesn't exist and
Vojtech Trefny 75cb9d
+                            VGs are present in the system
Vojtech Trefny 75cb9d
+            :type force: bool
Vojtech Trefny 75cb9d
+        """
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
         if not lvm.HAVE_LVMDEVICES:
Vojtech Trefny 75cb9d
             raise PhysicalVolumeError("LVM devices file feature is not supported")
Vojtech Trefny 75cb9d
 
Vojtech Trefny 75cb9d
+        if not os.path.exists(lvm.LVM_DEVICES_FILE) and vgs_info.cache and not force:
Vojtech Trefny 75cb9d
+            log.debug("Not adding %s to devices file: %s doesn't exist and there are VGs present in the system",
Vojtech Trefny 75cb9d
+                      self.device, lvm.LVM_DEVICES_FILE)
Vojtech Trefny 75cb9d
+            return
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
         try:
Vojtech Trefny 75cb9d
             blockdev.lvm.devices_add(self.device)
Vojtech Trefny 75cb9d
         except blockdev.LVMError as e:
Vojtech Trefny 75cb9d
@@ -151,7 +162,7 @@ class LVMPhysicalVolume(DeviceFormat):
Vojtech Trefny 75cb9d
                 # with lvmdbusd we need to call the pvcreate without --devices otherwise lvmdbusd
Vojtech Trefny 75cb9d
                 # wouldn't be able to find the newly created pv and the call would fail
Vojtech Trefny 75cb9d
                 blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes])
Vojtech Trefny 75cb9d
-                self.lvmdevices_add()
Vojtech Trefny 75cb9d
+                self.lvmdevices_add(force=False)
Vojtech Trefny 75cb9d
         else:
Vojtech Trefny 75cb9d
             blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes])
Vojtech Trefny 75cb9d
 
Vojtech Trefny 75cb9d
diff --git a/tests/unit_tests/formats_tests/__init__.py b/tests/unit_tests/formats_tests/__init__.py
Vojtech Trefny 75cb9d
index d678900b..95c7a25b 100644
Vojtech Trefny 75cb9d
--- a/tests/unit_tests/formats_tests/__init__.py
Vojtech Trefny 75cb9d
+++ b/tests/unit_tests/formats_tests/__init__.py
Vojtech Trefny 75cb9d
@@ -2,6 +2,7 @@ from .device_test import *
Vojtech Trefny 75cb9d
 from .disklabel_test import *
Vojtech Trefny 75cb9d
 from .init_test import *
Vojtech Trefny 75cb9d
 from .luks_test import *
Vojtech Trefny 75cb9d
+from .lvmpv_test import *
Vojtech Trefny 75cb9d
 from .methods_test import *
Vojtech Trefny 75cb9d
 from .misc_test import *
Vojtech Trefny 75cb9d
 from .selinux_test import *
Vojtech Trefny 75cb9d
diff --git a/tests/unit_tests/formats_tests/lvmpv_test.py b/tests/unit_tests/formats_tests/lvmpv_test.py
Vojtech Trefny 75cb9d
new file mode 100644
Vojtech Trefny 75cb9d
index 00000000..6490c7d4
Vojtech Trefny 75cb9d
--- /dev/null
Vojtech Trefny 75cb9d
+++ b/tests/unit_tests/formats_tests/lvmpv_test.py
Vojtech Trefny 75cb9d
@@ -0,0 +1,73 @@
Vojtech Trefny 75cb9d
+try:
Vojtech Trefny 75cb9d
+    from unittest.mock import patch
Vojtech Trefny 75cb9d
+except ImportError:
Vojtech Trefny 75cb9d
+    from mock import patch
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+from contextlib import contextmanager
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+import unittest
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+from blivet.formats.lvmpv import LVMPhysicalVolume
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+class LVMPVNodevTestCase(unittest.TestCase):
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+    @contextmanager
Vojtech Trefny 75cb9d
+    def patches(self):
Vojtech Trefny 75cb9d
+        patchers = dict()
Vojtech Trefny 75cb9d
+        mocks = dict()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        patchers["blockdev"] = patch("blivet.formats.lvmpv.blockdev")
Vojtech Trefny 75cb9d
+        patchers["lvm"] = patch("blivet.formats.lvmpv.lvm")
Vojtech Trefny 75cb9d
+        patchers["vgs_info"] = patch("blivet.formats.lvmpv.vgs_info")
Vojtech Trefny 75cb9d
+        patchers["os"] = patch("blivet.formats.lvmpv.os")
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        for name, patcher in patchers.items():
Vojtech Trefny 75cb9d
+            mocks[name] = patcher.start()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        yield mocks
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        for patcher in patchers.values():
Vojtech Trefny 75cb9d
+            patcher.stop()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+    def test_lvm_devices(self):
Vojtech Trefny 75cb9d
+        fmt = LVMPhysicalVolume(device="/dev/test")
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        with self.patches() as mock:
Vojtech Trefny 75cb9d
+            # LVM devices file not enabled/supported -> devices_add should not be called
Vojtech Trefny 75cb9d
+            mock["lvm"].HAVE_LVMDEVICES = False
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            fmt._create()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            mock["blockdev"].lvm.devices_add.assert_not_called()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        with self.patches() as mock:
Vojtech Trefny 75cb9d
+            # LVM devices file enabled and devices file exists -> devices_add should be called
Vojtech Trefny 75cb9d
+            mock["lvm"].HAVE_LVMDEVICES = True
Vojtech Trefny 75cb9d
+            mock["os"].path.exists.return_value = True
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            fmt._create()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            mock["blockdev"].lvm.devices_add.assert_called_with("/dev/test")
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        with self.patches() as mock:
Vojtech Trefny 75cb9d
+            # LVM devices file enabled and devices file doesn't exist
Vojtech Trefny 75cb9d
+            # and no existing VGs present -> devices_add should be called
Vojtech Trefny 75cb9d
+            mock["lvm"].HAVE_LVMDEVICES = True
Vojtech Trefny 75cb9d
+            mock["os"].path.exists.return_value = False
Vojtech Trefny 75cb9d
+            mock["vgs_info"].cache = {}
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            fmt._create()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            mock["blockdev"].lvm.devices_add.assert_called_with("/dev/test")
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+        with self.patches() as mock:
Vojtech Trefny 75cb9d
+            # LVM devices file enabled and devices file doesn't exist
Vojtech Trefny 75cb9d
+            # and existing VGs present -> devices_add should not be called
Vojtech Trefny 75cb9d
+            mock["lvm"].HAVE_LVMDEVICES = True
Vojtech Trefny 75cb9d
+            mock["os"].path.exists.return_value = False
Vojtech Trefny 75cb9d
+            mock["vgs_info"].cache = {"fake_vg_uuid": "fake_vg_data"}
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            fmt._create()
Vojtech Trefny 75cb9d
+
Vojtech Trefny 75cb9d
+            mock["blockdev"].lvm.devices_add.assert_not_called()
Vojtech Trefny 75cb9d
-- 
Vojtech Trefny 75cb9d
2.43.0
Vojtech Trefny 75cb9d