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

perf(instances): a clone request reads its source VM once

The clone form's checks read the source's NICs from the live and the
persistent definition, and each NIC read the running VM's addresses
again since b2b2386d: a guest agent that is connected but hung held the
request for its timeout once a NIC and definition. The checks now run
in one cached_reads block, as the VM page does.
This commit is contained in:
catborise 2026-11-05 08:50:15 +03:00
parent 3c51602652
commit ae03679b0e
2 changed files with 22 additions and 1 deletions

View file

@ -519,7 +519,9 @@ class CloneInstance(Kind):
def plan(self, user, params):
instance = _clonable(user, params["instance"])
data, quota = clone_data(user, instance, params["fields"])
# the source once a request: a running VM's NICs read its guest agent, which may take its whole timeout
with instance.proxy.cached_reads():
data, quota = clone_data(user, instance, params["fields"])
keys = vm_claims(instance.compute, data["name"])
# the VM's definition is read again when the clone is defined
keys[claims.instance_key(instance.uuid)] = Claim.EXCLUSIVE

View file

@ -1,5 +1,6 @@
"""VM clone runs as a job: the page queues it, the worker clones and records it."""
import contextlib
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
from uuid import uuid4
@ -124,6 +125,24 @@ class CloneJobTestCase(TransactionTestCase):
"submission_key": "key-clone003", "clone-vcpu": "\u00b2"})
self.assertEqual([str(m) for m in get_messages(response.wsgi_request)], ["Enter a whole number of vCPUs for the clone"])
def test_the_form_reads_the_vm_in_one_cached_reads_block(self):
inside, reads = [], []
@contextlib.contextmanager
def cached_reads():
inside.append(True)
yield self.proxy
inside.pop()
self.proxy.cached_reads = cached_reads
disks = self.proxy.get_disk_devices.return_value
self.proxy.get_disk_devices.side_effect = lambda *args, **kwargs: reads.append(bool(inside)) or disks
self.client.post(reverse("instances:clone", args=[self.source.pk]),
{"name": "copy", "disk-vda": "copy.qcow2", "clone-net-mac-0": "52:54:00:00:00:01",
"submission_key": "key-clone004"})
self.assertTrue(Operation.objects.exists())
self.assertEqual(reads, [True])
def test_a_clone_that_cannot_start_is_made_with_a_warning(self):
self.proxy.start.side_effect = libvirt.libvirtError("no memory")
op, result = self.clone_with(**{"clone-start": "true"})