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

feat(instances): a VM's options in one list, each saved when it can be

Settings > Options was four forms under bold sentences, most of them
disabled while the VM ran. The owner chose this layout from three
rendered options: one list, each row a setting with its description on
the left and its control on the right: VM details (title, description),
Template, primary video model, QEMU guest agent. vCPU hot plug moved to
Resize > CPU, next to the vCPU counts.

Codex reviewed the four forms; these are fixed:

- Title, description and the video model are saved while the VM runs:
  they are in the persistent definition, used at the next start.
- The template flag has its own form and view, set_template, for
  superusers and staff, and only for a shut-off VM: a running VM made a
  template left the quota while it kept running. Turning a template
  back into a VM checks the quota there, and each change is audited.
  The title form no longer touches the flag.
- A new video model stays the primary one; the old model's memory and
  head settings, which are its own, go with it.
- The agent and vCPU hot plug forms show the persistent definition; they
  showed the running VM's, so a pending change looked undone.
- Enabling the guest agent adds its channel only where it is missing:
  saving Enabled again failed, and a channel pending the next start kept
  a running VM from getting one.
- The agent line tells a VM that is not running, one without a channel,
  and a connected or not connected agent apart.
This commit is contained in:
catborise 2026-10-30 16:03:43 +03:00
parent 46188d3230
commit a993c12db0
13 changed files with 272 additions and 172 deletions

View file

@ -94,7 +94,8 @@ class DeviceEditsByStateTestCase(unittest.TestCase):
vm.instance = MagicMock()
vm.instance.isActive.return_value = active
vm.get_status = MagicMock(return_value=state)
vm._XMLDesc = MagicMock(return_value=AGENT_DOMAIN)
# an agent channel is added where there is none, removed where there is one
vm._XMLDesc = MagicMock(return_value=DOMAIN if name == "add_guest_agent" else AGENT_DOMAIN)
edit(vm)
result[name] = [names[c.args[1]] for c in getattr(vm.instance, method).call_args_list]
return result
@ -119,11 +120,25 @@ class DeviceEditsByStateTestCase(unittest.TestCase):
vm = wvmInstance.__new__(wvmInstance)
vm.instance = MagicMock()
vm.instance.isActive.return_value = True
vm._XMLDesc = MagicMock(return_value=DOMAIN)
vm.instance.attachDeviceFlags.side_effect = libvirtError("target sda already exists")
with self.assertRaises(libvirtError):
self.EDITS[name][1](vm)
vm.instance.attachDeviceFlags.assert_called_once()
def test_an_agent_channel_is_added_only_where_it_is_missing(self):
from libvirt import VIR_DOMAIN_AFFECT_CONFIG, VIR_DOMAIN_AFFECT_LIVE
for live, persistent, affected in ((AGENT_DOMAIN, AGENT_DOMAIN, []),
(DOMAIN, AGENT_DOMAIN, [VIR_DOMAIN_AFFECT_LIVE]),
(AGENT_DOMAIN, DOMAIN, [VIR_DOMAIN_AFFECT_CONFIG])):
with self.subTest(affected=affected):
vm = wvmInstance.__new__(wvmInstance)
vm.instance = MagicMock(**{"isActive.return_value": True})
vm._XMLDesc = lambda flags, live=live, persistent=persistent: persistent if flags == PERSISTENT_XML else live
vm.add_guest_agent()
self.assertEqual([c.args[1] for c in vm.instance.attachDeviceFlags.call_args_list], affected)
if __name__ == "__main__":
unittest.main()