diff --git a/vrtManager/instance.py b/vrtManager/instance.py index f5e11259..39803ae5 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -117,6 +117,10 @@ class wvmInstances(wvmConnect): mode.append(label) dom = conn.instance + # libvirt keeps snapshot metadata on the source host: shared disks do + # not carry it to the destination. + if dom.snapshotNum(0): + raise util.OperationError("A VM with snapshots cannot be migrated") if state == 5: self.refuse_local_state(dom.XMLDesc(0)) definitions = {dom.XMLDesc(0)} @@ -283,8 +287,6 @@ class wvmInstances(wvmConnect): first (RHEL-145770) and tracks the fix as RHEL-156800; RHEL/Rocky 9.8 with libvirt 11.10.0-12.el9_8 is affected. When supported hosts all have the fix, offline migration can go back to dom.migrate.""" - if dom.snapshotNum(0): - raise util.OperationError("A VM with snapshots cannot be migrated") if dom.hasManagedSaveImage(0): raise util.OperationError("A VM with a saved state cannot be migrated") for lookup, key in ((self.wvm.lookupByUUIDString, dom.UUIDString()), (self.wvm.lookupByName, dom.name())): diff --git a/vrtManager/tests/test_migration.py b/vrtManager/tests/test_migration.py index 729b11ee..8e46fcb2 100644 --- a/vrtManager/tests/test_migration.py +++ b/vrtManager/tests/test_migration.py @@ -237,7 +237,6 @@ class ShutOffMigrationTestCase(unittest.TestCase): def test_refused_before_anything_changes(self): cases = { - "snapshots": (FakeHost(), {"snapshots": 2}), "saved state": (FakeHost(), {"saved": True}), "same uuid on the destination": (FakeHost(existing={"u-1"}), {}), "same name on the destination": (FakeHost(existing={"vm"}), {}), @@ -300,6 +299,18 @@ class MigrationModeTestCase(unittest.TestCase): destination().moveto(source, "vm", unsafe=False, **{"live": False, "offline": False, **request}) self.assertEqual(source.instance.calls, []) + def test_a_vm_with_snapshots_is_refused_in_every_state(self): + """libvirt keeps snapshot metadata on the source host; a migration + does not carry it, even with shared disks.""" + for state, request in ((1, {"live": True}), (1, {}), (3, {}), (5, {})): + with self.subTest(state=state, request=request): + host = FakeHost() + source = FakeSource(state, snapshots=1) + with self.assertRaisesRegex(util.OperationError, "A VM with snapshots cannot be migrated"): + destination(host).moveto(source, "vm", unsafe=False, **{"live": False, "offline": False, **request}) + self.assertEqual(source.instance.calls, []) + self.assertEqual(host.defined, []) + def test_modes(self): live, unsafe = libvirt.VIR_MIGRATE_LIVE, libvirt.VIR_MIGRATE_UNSAFE converge, compressed = libvirt.VIR_MIGRATE_AUTO_CONVERGE, libvirt.VIR_MIGRATE_COMPRESSED