1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00

fix(instances): a VM shut down after its Migrate tab opened moves offline

The Migrate tab shows a running VM's live migration switch, on by
default. A VM shut down after the tab opened, as one is to move it shut
off, was then refused: "A shut-off VM cannot be migrated live". A
shut-off VM now moves offline whatever the request says about live, as
the tab tells for a shut-off VM; the tuning options are for a running VM
only, as before. An offline request for a running or paused VM is still
refused.
This commit is contained in:
catborise 2026-11-01 17:35:32 +03:00
parent dbc7e688ac
commit f63c1ebe32
2 changed files with 6 additions and 5 deletions

View file

@ -116,8 +116,9 @@ class wvmInstances(wvmConnect):
The mode follows the VM's state, read once: a running VM migrates
live or, without live, paused for the transfer (non-live); a paused
VM stays paused; a shut-off VM moves offline. A request that does not
fit the state is refused. unsafe, autoconverge (live only) and
VM stays paused; a shut-off VM moves offline, also when the request
was made while it ran (live). An offline request for a running or
paused VM is refused. unsafe, autoconverge (live only) and
compress apply to a running VM. uri: the native migration URI
(tcp://address) on the destination; None lets libvirt use the
destination's own hostname. pools: {target: pool here} of the disks
@ -126,8 +127,6 @@ class wvmInstances(wvmConnect):
and options used, for the log, and the paths of the copied disks."""
state = conn.get_status()
if state == 5:
if live:
raise util.OperationError("A shut-off VM cannot be migrated live")
mode = ["offline"]
elif state in (1, 3):
if offline:

View file

@ -287,7 +287,7 @@ class MigrationModeTestCase(unittest.TestCase):
return mode, source.instance.calls[0][0] if source.instance.calls else None
def test_refused_requests(self):
for state, request in ((5, {"live": True}), (1, {"offline": True}), (3, {"offline": True}),
for state, request in ((1, {"offline": True}), (3, {"offline": True}),
(1, {"live": True, "offline": True}), (6, {}), (4, {}), (7, {}), (0, {})):
with self.subTest(state=state, request=request):
source = FakeSource(state)
@ -325,6 +325,8 @@ class MigrationModeTestCase(unittest.TestCase):
self.assertEqual(flags & (live | unsafe | converge | compressed), live)
self.assertEqual(self.migrate(5), ("offline", None))
self.assertEqual(self.migrate(5, offline=True), ("offline", None))
# asked while it ran, then shut down: it moves offline, the tuning options unused
self.assertEqual(self.migrate(5, live=True, autoconverge=True, compress=True), ("offline", None))
def with_disks(*disks):