diff --git a/blivet/devicelibs/stratis.py b/blivet/devicelibs/stratis.py index e813924e9..1f7432344 100644 --- a/blivet/devicelibs/stratis.py +++ b/blivet/devicelibs/stratis.py @@ -255,3 +255,28 @@ def create_filesystem(name, pool_uuid, fs_size=None): # repopulate the stratis info cache so the new filesystem will be added stratis_info.drop_cache() + + +def add_device(pool_uuid, device): + if not availability.STRATIS_DBUS.available: + raise StratisError("Stratis DBus service not available") + + # repopulate the stratis info cache just to be sure all values are still valid + stratis_info.drop_cache() + + pool_info = stratis_info.pools[pool_uuid] + + try: + ((succ, _paths), rc, err) = safe_dbus.call_sync(STRATIS_SERVICE, + pool_info.object_path, + STRATIS_POOL_INTF, + "AddDataDevs", + GLib.Variant("(as)", ([device],))) + except safe_dbus.DBusCallError as e: + raise StratisError("Failed to create stratis filesystem on '%s': %s" % (pool_info.name, str(e))) + else: + if not succ: + raise StratisError("Failed to create stratis filesystem on '%s': %s (%d)" % (pool_info.name, err, rc)) + + # repopulate the stratis info cache so the new filesystem will be added + stratis_info.drop_cache() diff --git a/blivet/devices/stratis.py b/blivet/devices/stratis.py index f58f8bd50..20e57db75 100644 --- a/blivet/devices/stratis.py +++ b/blivet/devices/stratis.py @@ -26,6 +26,7 @@ from collections import defaultdict +from .container import ContainerDevice from .storage import StorageDevice from ..static_data import stratis_info from ..storage_log import log_method_call @@ -35,7 +36,7 @@ from .. import devicelibs -class StratisPoolDevice(StorageDevice): +class StratisPoolDevice(ContainerDevice): """ A stratis pool device """ _type = "stratis pool" @@ -184,6 +185,15 @@ def _add_parent(self, parent): raise InconsistentParentSectorSize(msg) + parent.format.pool_name = self.name + parent.format.pool_uuid = self.uuid + + def _add(self, member): + devicelibs.stratis.add_device(self.uuid, member.path) + + def _remove(self, member): + raise DeviceError("Removing members from a Stratis pool is not supported") + def _destroy(self): """ Destroy the device. """ log_method_call(self, self.name, status=self.status) diff --git a/tests/storage_tests/devices_test/stratis_test.py b/tests/storage_tests/devices_test/stratis_test.py index 3aba7685f..cfb645ef5 100644 --- a/tests/storage_tests/devices_test/stratis_test.py +++ b/tests/storage_tests/devices_test/stratis_test.py @@ -162,3 +162,46 @@ def test_stratis_overprovision(self): self.assertIsNotNone(fs) self.assertIsInstance(fs, blivet.devices.StratisFilesystemDevice) self.assertAlmostEqual(fs.size, blivet.size.Size("2 GiB"), delta=blivet.size.Size("10 MiB")) + + def test_stratis_add_device(self): + disk1 = self.storage.devicetree.get_device_by_path(self.vdevs[0]) + self.assertIsNotNone(disk1) + self.storage.initialize_disk(disk1) + + bd1 = self.storage.new_partition(size=blivet.size.Size("1 GiB"), fmt_type="stratis", + parents=[disk1]) + self.storage.create_device(bd1) + + blivet.partitioning.do_partitioning(self.storage) + + pool = self.storage.new_stratis_pool(name="blivetTestPool", parents=[bd1]) + self.storage.create_device(pool) + + self.storage.do_it() + self.storage.reset() + + disk2 = self.storage.devicetree.get_device_by_path(self.vdevs[1]) + self.assertIsNotNone(disk2) + self.storage.initialize_disk(disk2) + + bd2 = self.storage.new_partition(size=blivet.size.Size("1 GiB"), fmt_type="stratis", + parents=[disk2]) + self.storage.create_device(bd2) + + blivet.partitioning.do_partitioning(self.storage) + + pool = self.storage.devicetree.get_device_by_name("blivetTestPool") + + ac = blivet.deviceaction.ActionAddMember(pool, bd2) + self.storage.devicetree.actions.add(ac) + self.storage.do_it() + self.storage.reset() + + pool = self.storage.devicetree.get_device_by_name("blivetTestPool") + self.assertIsNotNone(pool) + self.assertEqual(len(pool.parents), 2) + self.assertCountEqual([p.path for p in pool.parents], [self.vdevs[0] + "1", self.vdevs[1] + "1"]) + + bd2 = self.storage.devicetree.get_device_by_path(self.vdevs[1] + "1") + self.assertEqual(bd2.format.pool_name, pool.name) + self.assertEqual(bd2.format.pool_uuid, pool.uuid)