mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 04:36:48 +00:00
fix(instances): disk edits keep their XML; changes lock per VM
Disk edits: - edit_disk built a new <disk> from the form and replaced the old one, losing what the form does not show (e.g. encryption and virtio driver options); a bus change detached and re-attached the disk. The disk of the persistent definition is now edited in place and the domain defined once; a bus change picks a free device name and drops the old address and virtio-only options. Pending persistent changes of a running VM are kept. - Clone omits empty disk devices, refuses a disk without a supported source and destination, and checks the name before allocating storage. Locks: - Every VM change held its compute's exclusive lock, so one slow operation blocked all VMs on that compute. A VM change now holds its own VM lock plus a shared compute lock; reconciliation, migration and cloning hold the compute exclusively (two clones of different VMs must not pass the name check together). - Quota-checked changes of one user (CPU, memory and disk resize, clone) run one at a time under a per-user lock, also across computes, so concurrent requests cannot all pass the check against the old allocation. It is the outermost lock; superusers, who have no quota, skip it. - A busy lock answers 409 to the API and a message in the web UI. API power and destroy actions return the view's error instead of success.
This commit is contained in:
parent
158d4db6c4
commit
51dedb7b8f
12 changed files with 510 additions and 269 deletions
|
|
@ -175,3 +175,15 @@ class APISecurityTestCase(TestCase):
|
|||
self.client.force_login(self.staff_user)
|
||||
res = self.client.get(f"/api/v1/computes/{self.compute.id}/storages/")
|
||||
self.assertEqual(res.status_code, 403)
|
||||
|
||||
def test_busy_instance_api_does_not_report_success(self):
|
||||
self.client.force_login(self.regular_user)
|
||||
with patch("instances.views.libvirt_instance_lock", side_effect=TimeoutError("busy")), patch(
|
||||
"instances.models.wvmInstance"
|
||||
) as proxy:
|
||||
response = self.client.post(
|
||||
f"/api/v1/computes/{self.compute.pk}/instances/{self.instance1.pk}/poweron/", {}
|
||||
)
|
||||
self.assertEqual(response.status_code, 409)
|
||||
self.assertIn("busy", response.json()["detail"])
|
||||
proxy.assert_not_called()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue