]> sourceware.org Git - lvm2.git/commitdiff
dbus: Add function for running lconvert --repair on RAID LVs 19/head 1559329518
authorVojtech Trefny <vtrefny@redhat.com>
Thu, 21 Nov 2024 14:14:10 +0000 (15:14 +0100)
committerZdeněk Kabeláč <zdenek.kabelac@gmail.com>
Mon, 25 Nov 2024 14:22:29 +0000 (14:22 +0000)
daemons/lvmdbusd/cmdhandler.py
daemons/lvmdbusd/lv.py
test/dbus/lvmdbustest.py

index d79db99ae5cf0ef881c561b7d701127cb46c7058..bdc7ba34d94cdb85a6a1ea6535017db866ead8e8 100644 (file)
@@ -552,6 +552,14 @@ def lv_vdo_deduplication(lv_path, enable, dedup_options):
        return call(cmd)
 
 
+def lv_raid_repair(lv_path, new_pvs, repair_options):
+       cmd = ['lvconvert', '-y', '--repair']
+       cmd.append(lv_path)
+       cmd.extend(new_pvs)
+       cmd.extend(options_to_cli_args(repair_options))
+       return call(cmd)
+
+
 def supports_json():
        cmd = ['help']
        rc, out, err = call(cmd)
index 293e2070d938489107cf61d3da7a84b26d544510..0be9123f058b9b2a5f40aefb6013686643de84df 100644 (file)
@@ -795,6 +795,39 @@ class Lv(LvCommon):
                        cache_options), cb, cbe)
                cfg.worker_q.put(r)
 
+       @staticmethod
+       def _repair_raid_lv(lv_uuid, lv_name, new_pvs, repair_options):
+               # Make sure we have a dbus object representing it
+               pv_dests = []
+               dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
+
+               # If we have PVs, verify them
+               if len(new_pvs):
+                       for pv in new_pvs:
+                               pv_dbus_obj = cfg.om.get_object_by_path(pv)
+                               if not pv_dbus_obj:
+                                       raise dbus.exceptions.DBusException(
+                                               LV_INTERFACE,
+                                               'PV Destination (%s) not found' % pv)
+
+                               pv_dests.append(pv_dbus_obj.lvm_id)
+
+               LvCommon.handle_execute(*cmdhandler.lv_raid_repair(
+                       dbo.lvm_id, pv_dests, repair_options))
+               return "/"
+
+       @dbus.service.method(
+               dbus_interface=LV_INTERFACE,
+               in_signature='aoia{sv}',
+               out_signature='o',
+               async_callbacks=('cb', 'cbe'))
+       def RepairRaidLv(self, new_pvs, tmo, repair_options, cb, cbe):
+               r = RequestEntry(
+                       tmo, Lv._repair_raid_lv,
+                       (self.Uuid, self.lvm_id, new_pvs,
+                       repair_options), cb, cbe, return_tuple=False)
+               cfg.worker_q.put(r)
+
 
 # noinspection PyPep8Naming
 @utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')
index db18c930c674650afb98e2631aadb89809f2d7a0..3325b42349ff722c79b13846ad6c87d406afe12c 100755 (executable)
@@ -577,9 +577,13 @@ class TestDbusService(unittest.TestCase):
                        vg.Remove(dbus.Int32(g_tmo), EOD))
                self._check_consistency()
 
-       def _pv_remove(self, pv):
+       def _pv_remove(self, pv, force=False):
+               if force:
+                       options = dbus.Dictionary({'--force': '--force', '--yes': ''}, 'sv')
+               else:
+                       options = EOD
                rc = self.handle_return(
-                       pv.Pv.Remove(dbus.Int32(g_tmo), EOD))
+                       pv.Pv.Remove(dbus.Int32(g_tmo), options))
                return rc
 
        def test_pv_remove_add(self):
@@ -2262,6 +2266,60 @@ class TestDbusService(unittest.TestCase):
 
                self.handle_return(vg.Vg.Remove(dbus.Int32(g_tmo), EOD))
 
+       def test_lv_raid_repair(self):
+               if len(self.objs[PV_INT]) < 3:
+                       self.skipTest("we need at least 3 PVs to run LV repair test")
+
+               lv_name = lv_n()
+               vg = self._vg_create(pv_paths=[self.objs[PV_INT][0].object_path,
+                                              self.objs[PV_INT][1].object_path]).Vg
+               lv = self._test_lv_create(
+                       vg.LvCreateRaid,
+                       (dbus.String(lv_name), dbus.String('raid1'), dbus.UInt64(mib(16)),
+                               dbus.UInt32(0), dbus.UInt32(0), dbus.Int32(g_tmo), EOD),
+                       vg, LV_BASE_INT)
+
+               # deactivate the RAID LV (can't force remove PV with active LVs)
+               self.handle_return(lv.Lv.Deactivate(
+                       dbus.UInt64(0), dbus.Int32(g_tmo), EOD))
+               lv.update()
+               self.assertFalse(lv.LvCommon.Active)
+
+               # remove second PV using --force --force
+               self._pv_remove(self.objs[PV_INT][1], force=True)
+
+               # activate the RAID LV (can't repair inactive LVs)
+               self.handle_return(lv.Lv.Activate(
+                       dbus.UInt64(0), dbus.Int32(g_tmo), EOD))
+               lv.update()
+               self.assertTrue(lv.LvCommon.Active)
+
+               # LV should be "broken" now
+               self.assertEqual(lv.LvCommon.Health[1], "partial")
+
+               # add the third PV to the VG
+               path = self.handle_return(vg.Extend(
+                       dbus.Array([self.objs[PV_INT][2].object_path], signature="o"),
+                       dbus.Int32(g_tmo), EOD))
+               self.assertTrue(path == '/')
+
+               # repair the RAID LV using the third PV
+               rc = self.handle_return(
+                       lv.Lv.RepairRaidLv(
+                               dbus.Array([self.objs[PV_INT][2].object_path], 'o'),
+                               dbus.Int32(g_tmo), EOD))
+
+               self.assertEqual(rc, '/')
+               self._check_consistency()
+
+               lv.update()
+
+               self.assertEqual(lv.LvCommon.Health[1], "unspecified")
+
+               # cleanup: remove the wiped PV from the VG and re-create it to have a clean PV
+               call_lvm(["vgreduce", "--removemissing", vg.Name])
+               self._pv_create(self.objs[PV_INT][1].Pv.Name)
+
        def _test_lv_method_interface(self, lv):
                self._rename_lv_test(lv)
                self._test_activate_deactivate(lv)
This page took 0.042645 seconds and 5 git commands to generate.