From 20cfc25367edfa23958c16db73ab802e4bd23644 Mon Sep 17 00:00:00 2001 From: catborise Date: Fri, 30 Oct 2026 10:06:03 +0300 Subject: [PATCH] feat(instances): a VM's boot settings as switches and its boot order as one list The Boot pane shows Autostart and the boot menu as switches that save on change, and the boot order as one list of the VM's disks, CD-ROM drives and NICs: the devices in the order first, checked and numbered, the others below. Up and Down move the checked devices; Apply order saves. - The boot menu can be changed while the VM runs: it is in the persistent definition, so it applies at the next start, as the boot order does. - The boot order editor no longer needs the boot menu enabled. - A VM that boots by device type () names those types; checking devices replaces that order. - An order is refused while a device the list does not show (a host device, a floppy) has a boot place, so Apply does not drop it; the message points to the XML editor. - An empty order is refused with a message instead of being ignored. - get_bootorder gives a NIC's full MAC as its target. - The unused jQuery multiselect plugin is removed. --- instances/models.py | 18 +++ instances/templates/instance.html | 78 ++++-------- .../templates/instances/settings_tab.html | 115 +++++++----------- instances/tests/test_live_dataloss.py | 2 +- instances/tests/test_pending_edits.py | 21 +++- instances/views.py | 38 +++--- static/css/webvirtcloud.css | 22 ++++ vrtManager/instance.py | 25 ++-- vrtManager/tests/test_device_edits.py | 10 ++ vrtManager/tests/test_instance_getters.py | 2 +- 10 files changed, 168 insertions(+), 163 deletions(-) diff --git a/instances/models.py b/instances/models.py index 27dcc3d3..a9aede16 100644 --- a/instances/models.py +++ b/instances/models.py @@ -201,6 +201,24 @@ class Instance(models.Model): def config_boot_order(self) -> dict: return self.proxy.get_bootorder(config=True) + @cached_property + def config_boot_devices(self) -> list[dict]: + """The disks, CD-ROM drives and NICs the boot order editor lists, those + in the boot order first in their position; value is as posted, as in + "disk:vda".""" + order = [f"{d['dev']}:{d['target']}" for position, d in sorted(self.config_boot_order.items())] + devices = ( + [{"value": f"disk:{d['dev']}", "name": d["dev"], "kind": _("Disk"), "source": d["image"]} + for d in self.config_disks] + + [{"value": f"cdrom:{d['dev']}", "name": d["dev"], "kind": _("CD-ROM"), "source": d["image"]} + for d in self.config_media] + + [{"value": f"network:{n['mac']}", "name": n["mac"], "kind": _("NIC"), "source": n["nic"]} + for n in self.config_networks] + ) + for device in devices: + device["checked"] = device["value"] in order + return sorted(devices, key=lambda d: order.index(d["value"]) if d["checked"] else len(order)) + @cached_property def config_video_model(self) -> str | None: """Video model and console settings of the persistent definition, diff --git a/instances/templates/instance.html b/instances/templates/instance.html index f44ddd83..9a37acb6 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -226,63 +226,39 @@ });