585101
From 43c5a6ef094e5f333a6dd47c467a1516488e2097 Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Mon, 24 May 2021 13:35:39 +0200
585101
Subject: [PATCH 1/7] Remove action device from LVM reject list
585101
585101
Because the device doesn't depend on itself the existing code
585101
won't remove the device we are trying to modify from the list.
585101
585101
Resolves: rhbz#1955942
585101
---
585101
 blivet/actionlist.py | 1 +
585101
 1 file changed, 1 insertion(+)
585101
585101
diff --git a/blivet/actionlist.py b/blivet/actionlist.py
585101
index d03e32b9..2de3fed3 100644
585101
--- a/blivet/actionlist.py
585101
+++ b/blivet/actionlist.py
585101
@@ -260,6 +260,7 @@ class ActionList(object):
585101
             log.debug("action: %s", action)
585101
 
585101
             # Remove lvm filters for devices we are operating on
585101
+            lvm.lvm_cc_removeFilterRejectRegexp(action.device.name)
585101
             for device in (d for d in devices if d.depends_on(action.device)):
585101
                 lvm.lvm_cc_removeFilterRejectRegexp(device.name)
585101
 
585101
-- 
585101
2.31.1
585101
585101
585101
From 2db8aa0aa6ea03c182f7e8e08cd1371ded13b71c Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Mon, 24 May 2021 14:49:12 +0200
585101
Subject: [PATCH 2/7] Convert LVM filter lists to sets
585101
585101
To prevent devices being added multiple times and removed only
585101
once.
585101
585101
Related: rhbz#1955942
585101
---
585101
 blivet/devicelibs/lvm.py | 12 ++++++------
585101
 tests/devicetree_test.py |  6 +++---
585101
 2 files changed, 9 insertions(+), 9 deletions(-)
585101
585101
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
585101
index 121797ce..9e396cca 100644
585101
--- a/blivet/devicelibs/lvm.py
585101
+++ b/blivet/devicelibs/lvm.py
585101
@@ -72,8 +72,8 @@ safe_name_characters = "0-9a-zA-Z._-"
585101
 # Theoretically we can handle all that can be handled with the LVM --config
585101
 # argument.  For every time we call an lvm_cc (lvm compose config) funciton
585101
 # we regenerate the config_args with all global info.
585101
-config_args_data = {"filterRejects": [],    # regular expressions to reject.
585101
-                    "filterAccepts": []}   # regexp to accept
585101
+config_args_data = {"filterRejects": set(),    # regular expressions to reject.
585101
+                    "filterAccepts": set()}    # regexp to accept
585101
 
585101
 
585101
 def _set_global_config():
585101
@@ -125,7 +125,7 @@ def needs_config_refresh(fn):
585101
 def lvm_cc_addFilterRejectRegexp(regexp):
585101
     """ Add a regular expression to the --config string."""
585101
     log.debug("lvm filter: adding %s to the reject list", regexp)
585101
-    config_args_data["filterRejects"].append(regexp)
585101
+    config_args_data["filterRejects"].add(regexp)
585101
 
585101
 
585101
 @needs_config_refresh
585101
@@ -134,15 +134,15 @@ def lvm_cc_removeFilterRejectRegexp(regexp):
585101
     log.debug("lvm filter: removing %s from the reject list", regexp)
585101
     try:
585101
         config_args_data["filterRejects"].remove(regexp)
585101
-    except ValueError:
585101
+    except KeyError:
585101
         log.debug("%s wasn't in the reject list", regexp)
585101
         return
585101
 
585101
 
585101
 @needs_config_refresh
585101
 def lvm_cc_resetFilter():
585101
-    config_args_data["filterRejects"] = []
585101
-    config_args_data["filterAccepts"] = []
585101
+    config_args_data["filterRejects"] = set()
585101
+    config_args_data["filterAccepts"] = set()
585101
 
585101
 
585101
 def determine_parent_lv(internal_lv, lvs, lv_info):
585101
diff --git a/tests/devicetree_test.py b/tests/devicetree_test.py
585101
index d1f4d8f3..ef163c0a 100644
585101
--- a/tests/devicetree_test.py
585101
+++ b/tests/devicetree_test.py
585101
@@ -125,7 +125,7 @@ class DeviceTreeTestCase(unittest.TestCase):
585101
         dt.actions._actions.append(Mock(name="fake action"))
585101
 
585101
         lvm.lvm_cc_addFilterRejectRegexp("xxx")
585101
-        lvm.config_args_data["filterAccepts"].append("yyy")
585101
+        lvm.config_args_data["filterAccepts"].add("yyy")
585101
 
585101
         dt.ignored_disks.append(names[0])
585101
         dt.exclusive_disks.append(names[1])
585101
@@ -144,8 +144,8 @@ class DeviceTreeTestCase(unittest.TestCase):
585101
 
585101
         self.assertEqual(dt._hidden, empty_list)
585101
 
585101
-        self.assertEqual(lvm.config_args_data["filterAccepts"], empty_list)
585101
-        self.assertEqual(lvm.config_args_data["filterRejects"], empty_list)
585101
+        self.assertEqual(lvm.config_args_data["filterAccepts"], set())
585101
+        self.assertEqual(lvm.config_args_data["filterRejects"], set())
585101
 
585101
         self.assertEqual(dt.exclusive_disks, empty_list)
585101
         self.assertEqual(dt.ignored_disks, empty_list)
585101
-- 
585101
2.31.1
585101
585101
585101
From e2540422945586ca45848a663e391a91b2fdd714 Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Tue, 27 Jul 2021 14:07:05 +0200
585101
Subject: [PATCH 3/7] Switch LVM devices filter from "reject" to "accept" by
585101
 default
585101
585101
We currently use the LVM reject filter to filter out hidden and
585101
ignored devices, this commit changes the behaviour to reject all
585101
devices by default and accept only physical volumes that are not
585101
hidden or ignored. This is preparation for the switch from the
585101
existing lvm.conf based filtering to the new devices file based
585101
filtering introduced in LVM 2.03.12 which allows only listing
585101
"accepted" devices. This allows us to support both the "old" and
585101
"new" style filtering using the same code.
585101
---
585101
 blivet/actionlist.py                  |  5 +--
585101
 blivet/devicelibs/lvm.py              | 62 +++++++++++----------------
585101
 blivet/devices/lvm.py                 |  4 +-
585101
 blivet/devicetree.py                  |  8 ++--
585101
 blivet/formats/lvmpv.py               |  2 +
585101
 blivet/populator/helpers/lvm.py       |  6 +++
585101
 blivet/populator/helpers/partition.py |  8 ----
585101
 blivet/populator/populator.py         |  4 +-
585101
 tests/devicetree_test.py              | 37 ++++++++++++++--
585101
 tests/populator_test.py               |  6 ++-
585101
 10 files changed, 81 insertions(+), 61 deletions(-)
585101
585101
diff --git a/blivet/actionlist.py b/blivet/actionlist.py
585101
index 2de3fed3..f3977401 100644
585101
--- a/blivet/actionlist.py
585101
+++ b/blivet/actionlist.py
585101
@@ -259,10 +259,9 @@ class ActionList(object):
585101
         for action in self._actions:
585101
             log.debug("action: %s", action)
585101
 
585101
-            # Remove lvm filters for devices we are operating on
585101
-            lvm.lvm_cc_removeFilterRejectRegexp(action.device.name)
585101
             for device in (d for d in devices if d.depends_on(action.device)):
585101
-                lvm.lvm_cc_removeFilterRejectRegexp(device.name)
585101
+                if device.format.type == "lvmpv":
585101
+                    lvm.lvm_devices_add(device.path)
585101
 
585101
     def _post_process(self, devices=None):
585101
         """ Clean up relics from action queue execution. """
585101
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
585101
index 9e396cca..96d037b8 100644
585101
--- a/blivet/devicelibs/lvm.py
585101
+++ b/blivet/devicelibs/lvm.py
585101
@@ -67,40 +67,29 @@ LVMETAD_SOCKET_PATH = "/run/lvm/lvmetad.socket"
585101
 
585101
 safe_name_characters = "0-9a-zA-Z._-"
585101
 
585101
-# Start config_args handling code
585101
-#
585101
-# Theoretically we can handle all that can be handled with the LVM --config
585101
-# argument.  For every time we call an lvm_cc (lvm compose config) funciton
585101
-# we regenerate the config_args with all global info.
585101
-config_args_data = {"filterRejects": set(),    # regular expressions to reject.
585101
-                    "filterAccepts": set()}    # regexp to accept
585101
+# list of devices that LVM is allowed to use
585101
+# with LVM >= 2.0.13 we'll use this for the --devices option and when creating
585101
+# the /etc/lvm/devices/system.devices file
585101
+# with older versions of LVM we will use this for the --config based filtering
585101
+_lvm_devices = set()
585101
 
585101
 
585101
 def _set_global_config():
585101
     """lvm command accepts lvm.conf type arguments preceded by --config. """
585101
 
585101
-    filter_string = ""
585101
-    rejects = config_args_data["filterRejects"]
585101
-    for reject in rejects:
585101
-        filter_string += ("\"r|/%s$|\"," % reject)
585101
+    device_string = ""
585101
+
585101
+    # now explicitly "accept" all LVM devices
585101
+    for device in _lvm_devices:
585101
+        device_string += "\"a|%s$|\"," % device
585101
 
585101
-    if filter_string:
585101
-        filter_string = "filter=[%s]" % filter_string.strip(",")
585101
+    # now add all devices to the "reject" filter
585101
+    device_string += "\"r|.*|\""
585101
 
585101
-    # XXX consider making /tmp/blivet.lvm.XXXXX, writing an lvm.conf there, and
585101
-    #     setting LVM_SYSTEM_DIR
585101
-    devices_string = 'preferred_names=["^/dev/mapper/", "^/dev/md/", "^/dev/sd"]'
585101
-    if filter_string:
585101
-        devices_string += " %s" % filter_string
585101
+    filter_string = "filter=[%s]" % device_string
585101
 
585101
-    # for now ignore the LVM devices file and rely on our filters
585101
-    if availability.LVMDEVICES.available:
585101
-        devices_string += " use_devicesfile=0"
585101
+    config_string = " devices { %s } " % filter_string
585101
 
585101
-    # devices_string can have (inside the brackets) "dir", "scan",
585101
-    # "preferred_names", "filter", "cache_dir", "write_cache_state",
585101
-    # "types", "sysfs_scan", "md_component_detection".  see man lvm.conf.
585101
-    config_string = " devices { %s } " % (devices_string)  # strings can be added
585101
     if not flags.lvm_metadata_backup:
585101
         config_string += "backup {backup=0 archive=0} "
585101
     if flags.debug:
585101
@@ -122,27 +111,26 @@ def needs_config_refresh(fn):
585101
 
585101
 
585101
 @needs_config_refresh
585101
-def lvm_cc_addFilterRejectRegexp(regexp):
585101
-    """ Add a regular expression to the --config string."""
585101
-    log.debug("lvm filter: adding %s to the reject list", regexp)
585101
-    config_args_data["filterRejects"].add(regexp)
585101
+def lvm_devices_add(path):
585101
+    """ Add a device (PV) to the list of devices LVM is allowed to use """
585101
+    log.debug("lvm filter: device %s added to the list of allowed devices")
585101
+    _lvm_devices.add(path)
585101
 
585101
 
585101
 @needs_config_refresh
585101
-def lvm_cc_removeFilterRejectRegexp(regexp):
585101
-    """ Remove a regular expression from the --config string."""
585101
-    log.debug("lvm filter: removing %s from the reject list", regexp)
585101
+def lvm_devices_remove(path):
585101
+    """ Remove a device (PV) to the list of devices LVM is allowed to use """
585101
+    log.debug("lvm filter: device %s removed from the list of allowed devices")
585101
     try:
585101
-        config_args_data["filterRejects"].remove(regexp)
585101
+        _lvm_devices.remove(path)
585101
     except KeyError:
585101
-        log.debug("%s wasn't in the reject list", regexp)
585101
+        log.debug("%s wasn't in the devices list", path)
585101
         return
585101
 
585101
 
585101
 @needs_config_refresh
585101
-def lvm_cc_resetFilter():
585101
-    config_args_data["filterRejects"] = set()
585101
-    config_args_data["filterAccepts"] = set()
585101
+def lvm_devices_reset():
585101
+    _lvm_devices.clear()
585101
 
585101
 
585101
 def determine_parent_lv(internal_lv, lvs, lv_info):
585101
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
585101
index c61eeb4b..9c230f1b 100644
585101
--- a/blivet/devices/lvm.py
585101
+++ b/blivet/devices/lvm.py
585101
@@ -273,8 +273,8 @@ class LVMVolumeGroupDevice(ContainerDevice):
585101
         log_method_call(self, self.name, status=self.status)
585101
         if not self.complete:
585101
             for pv in self.pvs:
585101
-                # Remove the PVs from the ignore filter so we can wipe them.
585101
-                lvm.lvm_cc_removeFilterRejectRegexp(pv.name)
585101
+                # add PVS to the list of LVM devices so we can wipe them.
585101
+                lvm.lvm_devices_add(pv.path)
585101
 
585101
             # Don't run vgremove or vgreduce since there may be another VG with
585101
             # the same name that we want to keep/use.
585101
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
585101
index f4ae1968..c6c1b440 100644
585101
--- a/blivet/devicetree.py
585101
+++ b/blivet/devicetree.py
585101
@@ -96,7 +96,7 @@ class DeviceTreeBase(object):
585101
 
585101
         self._hidden = []
585101
 
585101
-        lvm.lvm_cc_resetFilter()
585101
+        lvm.lvm_devices_reset()
585101
 
585101
         self.exclusive_disks = exclusive_disks or []
585101
         self.ignored_disks = ignored_disks or []
585101
@@ -879,7 +879,8 @@ class DeviceTreeBase(object):
585101
         self._remove_device(device, force=True, modparent=False)
585101
 
585101
         self._hidden.append(device)
585101
-        lvm.lvm_cc_addFilterRejectRegexp(device.name)
585101
+        if device.format.type == "lvmpv":
585101
+            lvm.lvm_devices_remove(device.path)
585101
 
585101
     def unhide(self, device):
585101
         """ Restore a device's visibility.
585101
@@ -905,7 +906,8 @@ class DeviceTreeBase(object):
585101
                 self._hidden.remove(hidden)
585101
                 self._devices.append(hidden)
585101
                 hidden.add_hook(new=False)
585101
-                lvm.lvm_cc_removeFilterRejectRegexp(hidden.name)
585101
+                if hidden.format.type == "lvmpv":
585101
+                    lvm.lvm_devices_add(hidden.path)
585101
 
585101
     def expand_taglist(self, taglist):
585101
         """ Expands tags in input list into devices.
585101
diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py
585101
index ea84e9e4..3b00951f 100644
585101
--- a/blivet/formats/lvmpv.py
585101
+++ b/blivet/formats/lvmpv.py
585101
@@ -124,6 +124,7 @@ class LVMPhysicalVolume(DeviceFormat):
585101
     def _create(self, **kwargs):
585101
         log_method_call(self, device=self.device,
585101
                         type=self.type, status=self.status)
585101
+        lvm.lvm_devices_add(self.device)
585101
 
585101
         lvm._set_global_config()
585101
 
585101
@@ -138,6 +139,7 @@ class LVMPhysicalVolume(DeviceFormat):
585101
         except blockdev.LVMError:
585101
             DeviceFormat._destroy(self, **kwargs)
585101
         finally:
585101
+            lvm.lvm_devices_remove(self.device)
585101
             udev.settle()
585101
 
585101
     @property
585101
diff --git a/blivet/populator/helpers/lvm.py b/blivet/populator/helpers/lvm.py
585101
index c7adfa4e..9e7e4630 100644
585101
--- a/blivet/populator/helpers/lvm.py
585101
+++ b/blivet/populator/helpers/lvm.py
585101
@@ -87,6 +87,12 @@ class LVMFormatPopulator(FormatPopulator):
585101
     def _get_kwargs(self):
585101
         kwargs = super(LVMFormatPopulator, self)._get_kwargs()
585101
 
585101
+        # new PV, add it to the LVM devices list and re-run pvs/lvs/vgs
585101
+        lvm.lvm_devices_add(self.device.path)
585101
+        pvs_info.drop_cache()
585101
+        vgs_info.drop_cache()
585101
+        lvs_info.drop_cache()
585101
+
585101
         pv_info = pvs_info.cache.get(self.device.path, None)
585101
 
585101
         name = udev.device_get_name(self.data)
585101
diff --git a/blivet/populator/helpers/partition.py b/blivet/populator/helpers/partition.py
585101
index f00323d1..8659bd48 100644
585101
--- a/blivet/populator/helpers/partition.py
585101
+++ b/blivet/populator/helpers/partition.py
585101
@@ -24,7 +24,6 @@ import copy
585101
 import six
585101
 
585101
 from ... import udev
585101
-from ...devicelibs import lvm
585101
 from ...devices import PartitionDevice
585101
 from ...errors import DeviceError
585101
 from ...formats import get_format
585101
@@ -66,7 +65,6 @@ class PartitionDevicePopulator(DevicePopulator):
585101
         if disk is None:
585101
             # if the disk is still not in the tree something has gone wrong
585101
             log.error("failure finding disk for %s", name)
585101
-            lvm.lvm_cc_addFilterRejectRegexp(name)
585101
             return
585101
 
585101
         if not disk.partitioned or not disk.format.supported:
585101
@@ -78,12 +76,6 @@ class PartitionDevicePopulator(DevicePopulator):
585101
             # and instantiate a PartitionDevice so our view of the layout is
585101
             # complete.
585101
             if not disk.partitionable or disk.format.type == "iso9660" or disk.format.hidden:
585101
-                # there's no need to filter partitions on members of multipaths or
585101
-                # fwraid members from lvm since multipath and dmraid are already
585101
-                # active and lvm should therefore know to ignore them
585101
-                if not disk.format.hidden:
585101
-                    lvm.lvm_cc_addFilterRejectRegexp(name)
585101
-
585101
                 log.debug("ignoring partition %s on %s", name, disk.format.type)
585101
                 return
585101
 
585101
diff --git a/blivet/populator/populator.py b/blivet/populator/populator.py
585101
index 75bb1741..958593ec 100644
585101
--- a/blivet/populator/populator.py
585101
+++ b/blivet/populator/populator.py
585101
@@ -317,10 +317,10 @@ class PopulatorMixin(object):
585101
                 continue
585101
 
585101
             # Make sure lvm doesn't get confused by PVs that belong to
585101
-            # incomplete VGs. We will remove the PVs from the reject list when/if
585101
+            # incomplete VGs. We will add the PVs to the accept list when/if
585101
             # the time comes to remove the incomplete VG and its PVs.
585101
             for pv in vg.pvs:
585101
-                lvm.lvm_cc_addFilterRejectRegexp(pv.name)
585101
+                lvm.lvm_devices_remove(pv.path)
585101
 
585101
     def set_disk_images(self, images):
585101
         """ Set the disk images and reflect them in exclusive_disks.
585101
diff --git a/tests/devicetree_test.py b/tests/devicetree_test.py
585101
index ef163c0a..3be4d572 100644
585101
--- a/tests/devicetree_test.py
585101
+++ b/tests/devicetree_test.py
585101
@@ -124,8 +124,7 @@ class DeviceTreeTestCase(unittest.TestCase):
585101
 
585101
         dt.actions._actions.append(Mock(name="fake action"))
585101
 
585101
-        lvm.lvm_cc_addFilterRejectRegexp("xxx")
585101
-        lvm.config_args_data["filterAccepts"].add("yyy")
585101
+        lvm.lvm_devices_add("xxx")
585101
 
585101
         dt.ignored_disks.append(names[0])
585101
         dt.exclusive_disks.append(names[1])
585101
@@ -144,8 +143,7 @@ class DeviceTreeTestCase(unittest.TestCase):
585101
 
585101
         self.assertEqual(dt._hidden, empty_list)
585101
 
585101
-        self.assertEqual(lvm.config_args_data["filterAccepts"], set())
585101
-        self.assertEqual(lvm.config_args_data["filterRejects"], set())
585101
+        self.assertEqual(lvm._lvm_devices, set())
585101
 
585101
         self.assertEqual(dt.exclusive_disks, empty_list)
585101
         self.assertEqual(dt.ignored_disks, empty_list)
585101
@@ -438,6 +436,37 @@ class DeviceTreeTestCase(unittest.TestCase):
585101
         self.assertEqual(tree.get_related_disks(sda), set([sda, sdb]))
585101
         self.assertEqual(tree.get_related_disks(sdb), set([sda, sdb]))
585101
 
585101
+    def test_lvm_filter_hide_unhide(self):
585101
+        tree = DeviceTree()
585101
+
585101
+        sda = DiskDevice("sda", size=Size("30 GiB"))
585101
+        sdb = DiskDevice("sdb", size=Size("30 GiB"))
585101
+
585101
+        tree._add_device(sda)
585101
+        tree._add_device(sdb)
585101
+
585101
+        self.assertTrue(sda in tree.devices)
585101
+        self.assertTrue(sdb in tree.devices)
585101
+
585101
+        sda.format = get_format("lvmpv", device=sda.path)
585101
+        sdb.format = get_format("lvmpv", device=sdb.path)
585101
+
585101
+        # LVMPhysicalVolume._create would do this
585101
+        lvm.lvm_devices_add(sda.path)
585101
+        lvm.lvm_devices_add(sdb.path)
585101
+
585101
+        self.assertSetEqual(lvm._lvm_devices, {sda.path, sdb.path})
585101
+
585101
+        tree.hide(sda)
585101
+        self.assertSetEqual(lvm._lvm_devices, {sdb.path})
585101
+        tree.hide(sdb)
585101
+        self.assertSetEqual(lvm._lvm_devices, set())
585101
+
585101
+        tree.unhide(sda)
585101
+        self.assertSetEqual(lvm._lvm_devices, {sda.path})
585101
+        tree.unhide(sdb)
585101
+        self.assertSetEqual(lvm._lvm_devices, {sda.path, sdb.path})
585101
+
585101
 
585101
 class DeviceTreeIgnoredExclusiveMultipathTestCase(unittest.TestCase):
585101
 
585101
diff --git a/tests/populator_test.py b/tests/populator_test.py
585101
index 2a8532f0..dd36c16a 100644
585101
--- a/tests/populator_test.py
585101
+++ b/tests/populator_test.py
585101
@@ -13,6 +13,7 @@ from gi.repository import BlockDev as blockdev
585101
 from blivet.devices import DiskDevice, DMDevice, FileDevice, LoopDevice
585101
 from blivet.devices import MDRaidArrayDevice, MultipathDevice, OpticalDevice
585101
 from blivet.devices import PartitionDevice, StorageDevice, NVDIMMNamespaceDevice
585101
+from blivet.devicelibs import lvm
585101
 from blivet.devicetree import DeviceTree
585101
 from blivet.formats import get_device_format_class, get_format, DeviceFormat
585101
 from blivet.formats.disklabel import DiskLabel
585101
@@ -393,8 +394,7 @@ class PartitionDevicePopulatorTestCase(PopulatorHelperTestCase):
585101
     @patch.object(DiskLabel, "parted_disk")
585101
     @patch.object(DiskLabel, "parted_device")
585101
     @patch.object(PartitionDevice, "probe")
585101
-    # TODO: fix the naming of the lvm filter functions
585101
-    @patch("blivet.devicelibs.lvm.lvm_cc_addFilterRejectRegexp")
585101
+    @patch("blivet.devicelibs.lvm.lvm_devices_add")
585101
     @patch("blivet.udev.device_get_major", return_value=88)
585101
     @patch("blivet.udev.device_get_minor", return_value=19)
585101
     @patch.object(DeviceTree, "get_device_by_name")
585101
@@ -973,6 +973,8 @@ class LVMFormatPopulatorTestCase(FormatPopulatorTestCase):
585101
                     self.assertTrue(vg_device is not None)
585101
                     devicetree._remove_device(vg_device)
585101
 
585101
+                    self.assertIn(device.path, lvm._lvm_devices)
585101
+
585101
         get_device_by_uuid.reset_mock()
585101
 
585101
         # pv belongs to a valid vg not in the tree with two lvs
585101
-- 
585101
2.31.1
585101
585101
585101
From 15a63b01bd2b6e7fe197fade849f28b83407c166 Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Fri, 30 Jul 2021 14:01:04 +0200
585101
Subject: [PATCH 4/7] Use LVM devices for filtering LVM devices with LVM >=
585101
 2.02.13
585101
585101
---
585101
 blivet/devicelibs/lvm.py | 38 +++++++++++++++++++++++++++++---------
585101
 tests/populator_test.py  |  9 ++++-----
585101
 2 files changed, 33 insertions(+), 14 deletions(-)
585101
585101
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
585101
index 96d037b8..3ab1540b 100644
585101
--- a/blivet/devicelibs/lvm.py
585101
+++ b/blivet/devicelibs/lvm.py
585101
@@ -67,6 +67,16 @@ LVMETAD_SOCKET_PATH = "/run/lvm/lvmetad.socket"
585101
 
585101
 safe_name_characters = "0-9a-zA-Z._-"
585101
 
585101
+if hasattr(blockdev.LVMTech, "DEVICES"):
585101
+    try:
585101
+        blockdev.lvm.is_tech_avail(blockdev.LVMTech.DEVICES, 0)  # pylint: disable=no-member
585101
+    except blockdev.LVMError:
585101
+        HAVE_LVMDEVICES = False
585101
+    else:
585101
+        HAVE_LVMDEVICES = True
585101
+else:
585101
+    HAVE_LVMDEVICES = False
585101
+
585101
 # list of devices that LVM is allowed to use
585101
 # with LVM >= 2.0.13 we'll use this for the --devices option and when creating
585101
 # the /etc/lvm/devices/system.devices file
585101
@@ -79,25 +89,34 @@ def _set_global_config():
585101
 
585101
     device_string = ""
585101
 
585101
-    # now explicitly "accept" all LVM devices
585101
-    for device in _lvm_devices:
585101
-        device_string += "\"a|%s$|\"," % device
585101
+    if not HAVE_LVMDEVICES:
585101
+        # now explicitly "accept" all LVM devices
585101
+        for device in _lvm_devices:
585101
+            device_string += "\"a|%s$|\"," % device
585101
 
585101
-    # now add all devices to the "reject" filter
585101
-    device_string += "\"r|.*|\""
585101
+        # now add all devices to the "reject" filter
585101
+        device_string += "\"r|.*|\""
585101
 
585101
-    filter_string = "filter=[%s]" % device_string
585101
+        filter_string = "filter=[%s]" % device_string
585101
 
585101
-    config_string = " devices { %s } " % filter_string
585101
+        config_string = " devices { %s } " % filter_string
585101
+    else:
585101
+        config_string = " "
585101
 
585101
     if not flags.lvm_metadata_backup:
585101
         config_string += "backup {backup=0 archive=0} "
585101
-    if flags.debug:
585101
-        config_string += "log {level=7 file=/tmp/lvm.log syslog=0}"
585101
+    config_string += "log {level=7 file=/tmp/lvm.log syslog=0}"
585101
 
585101
     blockdev.lvm.set_global_config(config_string)
585101
 
585101
 
585101
+def _set_lvm_devices():
585101
+    if not HAVE_LVMDEVICES:
585101
+        return
585101
+
585101
+    blockdev.lvm.set_devices_filter(list(_lvm_devices))
585101
+
585101
+
585101
 def needs_config_refresh(fn):
585101
     if not availability.BLOCKDEV_LVM_PLUGIN.available:
585101
         return lambda *args, **kwargs: None
585101
@@ -105,6 +124,7 @@ def needs_config_refresh(fn):
585101
     def fn_with_refresh(*args, **kwargs):
585101
         ret = fn(*args, **kwargs)
585101
         _set_global_config()
585101
+        _set_lvm_devices()
585101
         return ret
585101
 
585101
     return fn_with_refresh
585101
diff --git a/tests/populator_test.py b/tests/populator_test.py
585101
index dd36c16a..a9584319 100644
585101
--- a/tests/populator_test.py
585101
+++ b/tests/populator_test.py
585101
@@ -897,6 +897,7 @@ class LVMFormatPopulatorTestCase(FormatPopulatorTestCase):
585101
         device = Mock()
585101
         device.parents = []
585101
         device.size = Size("10g")
585101
+        device.path = "/dev/sda1"
585101
         devicetree._add_device(device)
585101
 
585101
         # pylint: disable=attribute-defined-outside-init
585101
@@ -924,15 +925,13 @@ class LVMFormatPopulatorTestCase(FormatPopulatorTestCase):
585101
         pv_info.pe_start = 0
585101
         pv_info.pv_free = 0
585101
 
585101
-        device.path = sentinel.pv_path
585101
-
585101
         vg_device = Mock()
585101
         vg_device.parents = []
585101
         vg_device.lvs = []
585101
         get_device_by_uuid.return_value = vg_device
585101
 
585101
         with patch("blivet.static_data.lvm_info.PVsInfo.cache", new_callable=PropertyMock) as mock_pvs_cache:
585101
-            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
585101
+            mock_pvs_cache.return_value = {device.path: pv_info}
585101
             with patch("blivet.udev.device_get_format", return_value=self.udev_type):
585101
                 helper = self.helper_class(devicetree, data, device)
585101
                 self.assertFalse(device in vg_device.parents)
585101
@@ -957,7 +956,7 @@ class LVMFormatPopulatorTestCase(FormatPopulatorTestCase):
585101
         pv_info.vg_pv_count = 1
585101
 
585101
         with patch("blivet.static_data.lvm_info.PVsInfo.cache", new_callable=PropertyMock) as mock_pvs_cache:
585101
-            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
585101
+            mock_pvs_cache.return_value = {device.path: pv_info}
585101
             with patch("blivet.static_data.lvm_info.VGsInfo.cache", new_callable=PropertyMock) as mock_vgs_cache:
585101
                 mock_vgs_cache.return_value = {pv_info.vg_uuid: Mock()}
585101
                 with patch("blivet.udev.device_get_format", return_value=self.udev_type):
585101
@@ -1007,7 +1006,7 @@ class LVMFormatPopulatorTestCase(FormatPopulatorTestCase):
585101
         get_device_by_uuid.side_effect = gdbu
585101
 
585101
         with patch("blivet.static_data.lvm_info.PVsInfo.cache", new_callable=PropertyMock) as mock_pvs_cache:
585101
-            mock_pvs_cache.return_value = {sentinel.pv_path: pv_info}
585101
+            mock_pvs_cache.return_value = {device.path: pv_info}
585101
             with patch("blivet.static_data.lvm_info.VGsInfo.cache", new_callable=PropertyMock) as mock_vgs_cache:
585101
                 mock_vgs_cache.return_value = {pv_info.vg_uuid: Mock()}
585101
                 with patch("blivet.static_data.lvm_info.LVsInfo.cache", new_callable=PropertyMock) as mock_lvs_cache:
585101
-- 
585101
2.31.1
585101
585101
585101
From d4e1395de3691f30196b6b0e3b2c82e83b27afaf Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Fri, 30 Jul 2021 14:01:43 +0200
585101
Subject: [PATCH 5/7] Make sure PVs are added/deleted to/from the LVM device
585101
 file
585101
585101
We are using the --devices option when running LVM commands which
585101
mean the newly created PV won't be added to the device list by
585101
pvcreate so we need to do that manually.
585101
---
585101
 blivet/formats/lvmpv.py | 5 +++++
585101
 1 file changed, 5 insertions(+)
585101
585101
diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py
585101
index 3b00951f..71ec699f 100644
585101
--- a/blivet/formats/lvmpv.py
585101
+++ b/blivet/formats/lvmpv.py
585101
@@ -131,6 +131,9 @@ class LVMPhysicalVolume(DeviceFormat):
585101
         ea_yes = blockdev.ExtraArg.new("-y", "")
585101
         blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes])
585101
 
585101
+        if lvm.HAVE_LVMDEVICES:
585101
+            blockdev.lvm.devices_add(self.device)
585101
+
585101
     def _destroy(self, **kwargs):
585101
         log_method_call(self, device=self.device,
585101
                         type=self.type, status=self.status)
585101
@@ -141,6 +144,8 @@ class LVMPhysicalVolume(DeviceFormat):
585101
         finally:
585101
             lvm.lvm_devices_remove(self.device)
585101
             udev.settle()
585101
+            if lvm.HAVE_LVMDEVICES:
585101
+                blockdev.lvm.devices_delete(self.device)
585101
 
585101
     @property
585101
     def destroyable(self):
585101
-- 
585101
2.31.1
585101
585101
585101
From c221d313bde21fb2cba701b93fe0c57336cba8ec Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Thu, 14 Oct 2021 15:32:24 +0200
585101
Subject: [PATCH 6/7] Ignore errors for LVM devices file actions
585101
585101
The LVM devices file feature might be disabled either locally or
585101
globally by LVM config.
585101
---
585101
 blivet/formats/lvmpv.py | 10 ++++++++--
585101
 1 file changed, 8 insertions(+), 2 deletions(-)
585101
585101
diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py
585101
index 71ec699f..b27213cc 100644
585101
--- a/blivet/formats/lvmpv.py
585101
+++ b/blivet/formats/lvmpv.py
585101
@@ -132,7 +132,10 @@ class LVMPhysicalVolume(DeviceFormat):
585101
         blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes])
585101
 
585101
         if lvm.HAVE_LVMDEVICES:
585101
-            blockdev.lvm.devices_add(self.device)
585101
+            try:
585101
+                blockdev.lvm.devices_add(self.device)
585101
+            except blockdev.LVMError as e:
585101
+                log.debug("Failed to add newly created PV %s to the LVM devices file: %s", self.device, str(e))
585101
 
585101
     def _destroy(self, **kwargs):
585101
         log_method_call(self, device=self.device,
585101
@@ -145,7 +148,10 @@ class LVMPhysicalVolume(DeviceFormat):
585101
             lvm.lvm_devices_remove(self.device)
585101
             udev.settle()
585101
             if lvm.HAVE_LVMDEVICES:
585101
-                blockdev.lvm.devices_delete(self.device)
585101
+                try:
585101
+                    blockdev.lvm.devices_delete(self.device)
585101
+                except blockdev.LVMError as e:
585101
+                    log.debug("Failed to remove PV %s from the LVM devices file: %s", self.device, str(e))
585101
 
585101
     @property
585101
     def destroyable(self):
585101
-- 
585101
2.31.1
585101
585101
585101
From 6b96d4ead6890fffd95840b8935f71ecd9e310ef Mon Sep 17 00:00:00 2001
585101
From: Vojtech Trefny <vtrefny@redhat.com>
585101
Date: Tue, 19 Oct 2021 14:27:05 +0200
585101
Subject: [PATCH 7/7] Add public functions to add/remove PV to/from the LVM
585101
 system.devices
585101
585101
Anaconda needs to be able to add preexisting PVs to the file
585101
during installation.
585101
---
585101
 blivet/formats/lvmpv.py | 28 ++++++++++++++++++++--------
585101
 1 file changed, 20 insertions(+), 8 deletions(-)
585101
585101
diff --git a/blivet/formats/lvmpv.py b/blivet/formats/lvmpv.py
585101
index b27213cc..3fef667e 100644
585101
--- a/blivet/formats/lvmpv.py
585101
+++ b/blivet/formats/lvmpv.py
585101
@@ -121,6 +121,24 @@ class LVMPhysicalVolume(DeviceFormat):
585101
     def supported(self):
585101
         return super(LVMPhysicalVolume, self).supported and self._plugin.available
585101
 
585101
+    def lvmdevices_add(self):
585101
+        if not lvm.HAVE_LVMDEVICES:
585101
+            raise PhysicalVolumeError("LVM devices file feature is not supported")
585101
+
585101
+        try:
585101
+            blockdev.lvm.devices_add(self.device)
585101
+        except blockdev.LVMError as e:
585101
+            log.debug("Failed to add PV %s to the LVM devices file: %s", self.device, str(e))
585101
+
585101
+    def lvmdevices_remove(self):
585101
+        if not lvm.HAVE_LVMDEVICES:
585101
+            raise PhysicalVolumeError("LVM devices file feature is not supported")
585101
+
585101
+        try:
585101
+            blockdev.lvm.devices_delete(self.device)
585101
+        except blockdev.LVMError as e:
585101
+            log.debug("Failed to remove PV %s from the LVM devices file: %s", self.device, str(e))
585101
+
585101
     def _create(self, **kwargs):
585101
         log_method_call(self, device=self.device,
585101
                         type=self.type, status=self.status)
585101
@@ -132,10 +150,7 @@ class LVMPhysicalVolume(DeviceFormat):
585101
         blockdev.lvm.pvcreate(self.device, data_alignment=self.data_alignment, extra=[ea_yes])
585101
 
585101
         if lvm.HAVE_LVMDEVICES:
585101
-            try:
585101
-                blockdev.lvm.devices_add(self.device)
585101
-            except blockdev.LVMError as e:
585101
-                log.debug("Failed to add newly created PV %s to the LVM devices file: %s", self.device, str(e))
585101
+            self.lvmdevices_add()
585101
 
585101
     def _destroy(self, **kwargs):
585101
         log_method_call(self, device=self.device,
585101
@@ -148,10 +163,7 @@ class LVMPhysicalVolume(DeviceFormat):
585101
             lvm.lvm_devices_remove(self.device)
585101
             udev.settle()
585101
             if lvm.HAVE_LVMDEVICES:
585101
-                try:
585101
-                    blockdev.lvm.devices_delete(self.device)
585101
-                except blockdev.LVMError as e:
585101
-                    log.debug("Failed to remove PV %s from the LVM devices file: %s", self.device, str(e))
585101
+                self.lvmdevices_remove()
585101
 
585101
     @property
585101
     def destroyable(self):
585101
-- 
585101
2.31.1
585101