diff --git a/0007-stratis-handle-DbusClientMissingPropertyError-on-D-B.patch b/0007-stratis-handle-DbusClientMissingPropertyError-on-D-B.patch new file mode 100644 index 0000000..70a0899 --- /dev/null +++ b/0007-stratis-handle-DbusClientMissingPropertyError-on-D-B.patch @@ -0,0 +1,184 @@ +From b24b0452cbce7e991b37b83a228bcae7c6f4266e Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 12 Apr 2026 22:11:49 +0100 +Subject: [PATCH 07/10] stratis: handle DbusClientMissingPropertyError on D-Bus + properties + +Resolves: #983 + +Signed-off-by: Bryn M. Reeves +--- + snapm/manager/plugins/stratis.py | 90 +++++++++++++++++++++++++++----- + 1 file changed, 76 insertions(+), 14 deletions(-) + +diff --git a/snapm/manager/plugins/stratis.py b/snapm/manager/plugins/stratis.py +index 1321a897..f408af81 100644 +--- a/snapm/manager/plugins/stratis.py ++++ b/snapm/manager/plugins/stratis.py +@@ -17,6 +17,10 @@ from uuid import UUID + + from dbus.exceptions import DBusException + ++from dbus_client_gen import ( ++ DbusClientMissingPropertyError, ++) ++ + from dbus_python_client_gen import ( + DPClientInvocationError, + DPClientSetPropertyContext, +@@ -242,20 +246,47 @@ class StratisSnapshot(Snapshot): + @property + def status(self): + (_, filesystem) = self._get_dbus_cache() +- if filesystem.MergeScheduled() is True: +- return SnapStatus.REVERTING ++ try: ++ if filesystem.MergeScheduled() is True: ++ return SnapStatus.REVERTING ++ except DbusClientMissingPropertyError: # pragma: no cover ++ # pylint: disable=protected-access ++ self.provider._log_warn( ++ "Could not access filesystem.MergeScheduled() property" ++ ) + return SnapStatus.ACTIVE + + @property + def size(self): + (_, filesystem) = self._get_dbus_cache() +- return int(filesystem.Size()) ++ try: ++ return int(filesystem.Size()) ++ except DbusClientMissingPropertyError: # pragma: no cover ++ # pylint: disable=protected-access ++ self.provider._log_warn("Could not access filesystem.Size() property") ++ return 0 + + @property + def free(self): + (pool, _) = self._get_dbus_cache() +- size = int(pool.TotalPhysicalSize()) +- used = int(pool.TotalPhysicalUsed()[1]) if pool.TotalPhysicalUsed()[0] else 0 ++ try: ++ size = int(pool.TotalPhysicalSize()) ++ except DbusClientMissingPropertyError: # pragma: no cover ++ # pylint: disable=protected-access ++ self.provider._log_warn( ++ "Could not access pool.TotalPhysicalSize() property" ++ ) ++ return 0 ++ try: ++ used = ( ++ int(pool.TotalPhysicalUsed()[1]) if pool.TotalPhysicalUsed()[0] else 0 ++ ) ++ except DbusClientMissingPropertyError: # pragma: no cover ++ # pylint: disable=protected-access ++ self.provider._log_warn( ++ "Could not access pool.TotalPhysicalUsed() property" ++ ) ++ return 0 + return size - used + + # Pylint does not understand the decorator notation. +@@ -301,7 +332,10 @@ def filter_stratis_snapshot(filesystem): + snapshot or ``False`` otherwise. The ``filesystem`` argument must be a + DBus managed object corresponding to a Stratis filesystem. + """ +- return filesystem.Origin()[0] ++ try: ++ return filesystem.Origin()[0] ++ except DbusClientMissingPropertyError: ++ return False + + + def _snapshot_min_size(policy_size): +@@ -417,8 +451,13 @@ def _pool_free_space_bytes(managed_objects, pool_name): + ``pool_name``. + """ + (pool, _) = _get_pool_filesystem(managed_objects, pool_name, None) +- size = int(pool.TotalPhysicalSize()) +- used = int(pool.TotalPhysicalUsed()[1]) if pool.TotalPhysicalUsed()[0] else 0 ++ try: ++ size = int(pool.TotalPhysicalSize()) ++ used = int(pool.TotalPhysicalUsed()[1]) if pool.TotalPhysicalUsed()[0] else 0 ++ except DbusClientMissingPropertyError as err: # pragma: no cover ++ raise SnapmPluginError( ++ f"Could not access Stratis pool capacity properties for {pool_name}" ++ ) from err + return size - used + + +@@ -427,7 +466,12 @@ def _fs_size_bytes(managed_objects, pool_name, fs_name): + Return the size of the specified filesystem in bytes. + """ + (_, filesystem) = _get_pool_filesystem(managed_objects, pool_name, fs_name) +- return int(filesystem.Size()) ++ try: ++ return int(filesystem.Size()) ++ except DbusClientMissingPropertyError as err: # pragma: no cover ++ raise SnapmPluginError( ++ f"Could not access Stratis filesystem size for {pool_name}/{fs_name}" ++ ) from err + + + class Stratis(Plugin): +@@ -505,11 +549,19 @@ class Stratis(Plugin): + if not filter_stratis_snapshot(filesystem): + continue + +- pool_name = path_to_name[filesystem.Pool()] +- filesystem_name = str(filesystem.Name()) ++ try: ++ pool_object_path = filesystem.Pool() ++ origin_info = filesystem.Origin() ++ filesystem_name = str(filesystem.Name()) ++ except DbusClientMissingPropertyError as err: # pragma: no cover ++ self._log_warn( ++ "Skipping filesystem with missing D-Bus property: %s", err ++ ) ++ continue ++ pool_name = path_to_name[pool_object_path] + + origin = _origin_uuid_to_fs_name( +- managed_objects, filesystem.Pool(), str(filesystem.Origin()[1]) ++ managed_objects, pool_object_path, str(origin_info[1]) + ) + + try: +@@ -520,7 +572,6 @@ class Stratis(Plugin): + (snapset, timestamp, mount_point) = fields + full_name = f"{pool_name}/{filesystem_name}" + self._log_debug("Found %s snapshot: %s", self.name, full_name) +- pool_object_path = filesystem.Pool() + cache_pool = MOPool(managed_objects[pool_object_path]) + cache_filesystem = filesystem + snapshots.append( +@@ -989,7 +1040,13 @@ class Stratis(Plugin): + Filesystem.Properties.MergeScheduled.Set(get_object(fs_object_path), True) + except DPClientInvocationError as err: + if isinstance(err.context, DPClientSetPropertyContext): +- origin_uuid = filesystem.Origin()[1] ++ try: ++ origin_uuid = filesystem.Origin()[1] ++ except DbusClientMissingPropertyError: # pragma: no cover ++ self._log_warn("Could not access filesystem.Origin() property") ++ raise SnapmPluginError( ++ f"Unexpected D-Bus error setting property for {pool_name}/{fs_name}" ++ ) from err + if len( + _find_in_progress_merge( + managed_objects, pool_object_path, origin_uuid +@@ -1005,6 +1062,11 @@ class Stratis(Plugin): + raise SnapmPluginError( + f"Unexpected D-Bus error setting property for {pool_name}/{fs_name}" + ) from err ++ except DbusClientMissingPropertyError as err: # pragma: no cover ++ self._log_warn("Could not access filesystem.MergeScheduled property") ++ raise SnapmPluginError( ++ "Unexpected error accessing filesystem.MergeScheduled property" ++ ) from err + + def activate_snapshot(self, name): + """ +-- +2.53.0 + diff --git a/0008-tests-bump-stratisd-test-dependency-to-stratisd-v3.8.patch b/0008-tests-bump-stratisd-test-dependency-to-stratisd-v3.8.patch new file mode 100644 index 0000000..9665c27 --- /dev/null +++ b/0008-tests-bump-stratisd-test-dependency-to-stratisd-v3.8.patch @@ -0,0 +1,34 @@ +From 2eefbb115ac839d0a64ddc1e5c5f40cd7b556164 Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Sun, 12 Apr 2026 22:25:36 +0100 +Subject: [PATCH 08/10] tests: bump stratisd test dependency to stratisd-v3.8.6 + +Resolves: #985 + +Signed-off-by: Bryn M. Reeves +--- + .github/workflows/snapm.yml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/.github/workflows/snapm.yml b/.github/workflows/snapm.yml +index d425a0b8..e3481701 100644 +--- a/.github/workflows/snapm.yml ++++ b/.github/workflows/snapm.yml +@@ -1,4 +1,4 @@ +---- ++-- + name: Snapshot Manager CI + permissions: + contents: read +@@ -113,7 +113,7 @@ jobs: + with: + toolchain: 1.85.0 # CURRENT DEVELOPMENT RUST TOOLCHAIN + - name: Check out stratisd +- run: git clone --depth 1 -b stratisd-v3.8.5 https://github.com/stratis-storage/stratisd ++ run: git clone --depth 1 -b stratisd-v3.8.6 https://github.com/stratis-storage/stratisd + working-directory: /var/tmp + - name: Build stratisd + run: make build-all +-- +2.53.0 + diff --git a/0009-stratis-refactor-filter_stratis_snapshot-to-allow-lo.patch b/0009-stratis-refactor-filter_stratis_snapshot-to-allow-lo.patch new file mode 100644 index 0000000..95e14bc --- /dev/null +++ b/0009-stratis-refactor-filter_stratis_snapshot-to-allow-lo.patch @@ -0,0 +1,96 @@ +From 92497a8874a1a5578564425240371609c940991b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 13 Apr 2026 16:22:16 +0100 +Subject: [PATCH 09/10] stratis: refactor filter_stratis_snapshot() to allow + logging + +Resolves: #987 + +Signed-off-by: Bryn M. Reeves +--- + snapm/manager/plugins/stratis.py | 31 ++++++++++++++++--------------- + tests/test_stratis.py | 8 ++++++-- + 2 files changed, 22 insertions(+), 17 deletions(-) + +diff --git a/snapm/manager/plugins/stratis.py b/snapm/manager/plugins/stratis.py +index f408af81..7000ed1b 100644 +--- a/snapm/manager/plugins/stratis.py ++++ b/snapm/manager/plugins/stratis.py +@@ -324,20 +324,6 @@ class StratisSnapshot(Snapshot): + return (self._pool, self._filesystem) + + +-def filter_stratis_snapshot(filesystem): +- """ +- Filter Stratis snapshots. +- +- Return ``True`` if the filesystem epresented by ``filesystem`` is a stratis +- snapshot or ``False`` otherwise. The ``filesystem`` argument must be a +- DBus managed object corresponding to a Stratis filesystem. +- """ +- try: +- return filesystem.Origin()[0] +- except DbusClientMissingPropertyError: +- return False +- +- + def _snapshot_min_size(policy_size): + """ + Return the minimum snapshot size given the space used by the snapshot +@@ -510,6 +496,21 @@ class Stratis(Plugin): + if self.priority == PLUGIN_NO_PRIORITY: + self.priority = STRATIS_STATIC_PRIORITY + ++ def _filter_stratis_snapshot(self, filesystem): ++ """ ++ Filter Stratis snapshots. ++ ++ Return ``True`` if the filesystem epresented by ``filesystem`` is a stratis ++ snapshot or ``False`` otherwise. The ``filesystem`` argument must be a ++ DBus managed object corresponding to a Stratis filesystem. ++ """ ++ try: ++ return filesystem.Origin()[0] ++ except DbusClientMissingPropertyError: # pragma: no cover ++ self._log_warn("Could not access filesystem.Origin() property") ++ return False ++ return False ++ + # pylint: disable=too-many-locals,too-many-branches + def discover_snapshots(self): + """ +@@ -546,7 +547,7 @@ class Stratis(Plugin): + ] + + for filesystem in filesystems_with_props: +- if not filter_stratis_snapshot(filesystem): ++ if not self._filter_stratis_snapshot(filesystem): + continue + + try: +diff --git a/tests/test_stratis.py b/tests/test_stratis.py +index 89e80f7c..16a6a636 100644 +--- a/tests/test_stratis.py ++++ b/tests/test_stratis.py +@@ -240,12 +240,16 @@ class StratisTests(unittest.TestCase): + proxy = get_object(TOP_OBJECT) + managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) + ++ stratis_plugin = stratis.Stratis(log, ConfigParser()) ++ + (pool, fs) = stratis._get_pool_filesystem(managed_objects, "pool1", "fs1-snapset_test_1721136677_-opt") +- self.assertEqual(True, stratis.filter_stratis_snapshot(fs)) ++ self.assertEqual(True, stratis_plugin._filter_stratis_snapshot(fs)) + + def test_filter_stratis_snapshot_nonsnapshot(self): + proxy = get_object(TOP_OBJECT) + managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) + ++ stratis_plugin = stratis.Stratis(log, ConfigParser()) ++ + (pool, fs) = stratis._get_pool_filesystem(managed_objects, "pool1", "fs1") +- self.assertEqual(False, stratis.filter_stratis_snapshot(fs)) ++ self.assertEqual(False, stratis_plugin._filter_stratis_snapshot(fs)) +-- +2.53.0 + diff --git a/0010-stratis-handle-DbusClientMissingPropertyError-on-.se.patch b/0010-stratis-handle-DbusClientMissingPropertyError-on-.se.patch new file mode 100644 index 0000000..a486b0b --- /dev/null +++ b/0010-stratis-handle-DbusClientMissingPropertyError-on-.se.patch @@ -0,0 +1,52 @@ +From 5347e0e45dce63ccad2b8ca3eddcafff0e9ba49b Mon Sep 17 00:00:00 2001 +From: "Bryn M. Reeves" +Date: Mon, 13 Apr 2026 16:36:08 +0100 +Subject: [PATCH 10/10] stratis: handle DbusClientMissingPropertyError on + .search() invocation + +Resolves: #984 + +Signed-off-by: Bryn M. Reeves +--- + snapm/manager/plugins/stratis.py | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/snapm/manager/plugins/stratis.py b/snapm/manager/plugins/stratis.py +index 7000ed1b..a8be5500 100644 +--- a/snapm/manager/plugins/stratis.py ++++ b/snapm/manager/plugins/stratis.py +@@ -19,6 +19,7 @@ from dbus.exceptions import DBusException + + from dbus_client_gen import ( + DbusClientMissingPropertyError, ++ DbusClientMissingSearchPropertiesError, + ) + + from dbus_python_client_gen import ( +@@ -425,10 +426,19 @@ def _find_in_progress_merge(managed_objects, pool_object_path, origin_uuid): + "MergeScheduled": True, + } + +- return [ +- MOFilesystem(info) +- for objpath, info in filesystems(props=fs_props).search(managed_objects) +- ] ++ try: ++ return [ ++ MOFilesystem(info) ++ for objpath, info in filesystems(props=fs_props).search(managed_objects) ++ ] ++ # Outside a bug in stratisd this is exceedingly unlikely, but handle it ++ # by returning an empty list if we are unable to access the Origin or ++ # MergeScheduled properties for any reason. In the worst case we will end ++ # up returning a SnapmPluginError with a D-Bus error in the case that we ++ # fail to detect an in-progress merge and then on that basis attempt to ++ # start a revert operation on the same device. ++ except DbusClientMissingSearchPropertiesError: # pragma: no cover ++ return [] + + + def _pool_free_space_bytes(managed_objects, pool_name): +-- +2.53.0 + diff --git a/snapm.spec b/snapm.spec index 8aeb3b5..11849b8 100644 --- a/snapm.spec +++ b/snapm.spec @@ -14,6 +14,10 @@ Patch2: 0003-doc-clarify-default-diff-start-path-behaviour-in-sna.patch Patch3: 0004-doc-add-discussion-of-s-start-path-to-user_guide.rst.patch Patch4: 0005-stratis-fix-pool-limit-accounting-in-create-delete-_.patch Patch5: 0006-lvm2-fix-pool-origin-limit-accounting.patch +Patch6: 0007-stratis-handle-DbusClientMissingPropertyError-on-D-B.patch +Patch7: 0008-tests-bump-stratisd-test-dependency-to-stratisd-v3.8.patch +Patch8: 0009-stratis-refactor-filter_stratis_snapshot-to-allow-lo.patch +Patch9: 0010-stratis-handle-DbusClientMissingPropertyError-on-.se.patch BuildArch: noarch