The Logs page now records every change an admin makes to a compute's
libvirt objects, with the compute's name in the host column:
- networks: add, start, stop, delete, autostart, DHCP range, fixed
addresses, QoS and XML edits;
- storage pools: add, start, stop, delete, autostart, from web and
API; volumes: add and delete (web and API), clone and ISO upload;
- host interfaces: add, start, stop, delete;
- secrets: add, set value (never the value), delete;
- network filters: add, clone, delete, XML edits, rules and
references.
A refused or failed change is a failed row with its reason (libvirt
text through safe_text). The volume clone and upload jobs write their
row when they end; a refused submission is a failed row at once. A
volume row names the volume libvirt created (a dir pool adds .qcow2 or
.img). Volume create or delete through the API on an inactive pool
(409) is a failed row.
Network filters: the rows read "Network filter f1: add" instead of
"f1 network filter is created", and their host is the compute's name
instead of its hostname. A duplicate name or UUID no longer raises a
bare exception, and a filter XML that cannot be parsed no longer ends
in UnboundLocalError.
On a running network the change did nothing, yet the page said the
range was changed; a network without a range or an unknown address
family ended in a server error. Each is refused now with the reason:
stop the network first, or the network has no such range.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Stopping a network cut the running VMs on it off, deleting one or a
secret kept the VMs that name it from starting, and stopping a pool
took the disks of running VMs away, all without a word. Each is now
refused with the VMs (and, for a secret, the pools) that need it:
stopping while a running VM uses it, deleting while a VM's definition
names it. A disk given by its file path does not need its pool's
definition. The API's pool stop is refused the same way.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A network's QoS form whose rate was not a whole number (abc, 1.5) made
wvmNetwork.set_qos raise a ValueError that the view did not catch: the
request ended in a server error. The page's pattern stops this in a
browser, but the server must refuse it too. set_qos now says "QoS rates
must be whole numbers", and the view reports that, as it does a libvirt
error, and goes back to the network's page.
The create-network form only checked the characters of its subnets, so
192.0.2.0/33 or 999.0.2.0/24 passed and network_size raised a
ValueError: the user got a server error instead of a message. So did a
subnet too small for the gateway, DHCP range and broadcast address that
network_size derives (0.0.0.0/32, 255.255.255.255/32), and 192.0.2.0/31
or a bare address gave an inverted DHCP range.
Each subnet field now parses its value as a network of its IP version
and refuses it with a field error otherwise. An IPv4 prefix must be /30
or shorter; the IPv6 prefix must be /64, which the view checked after
the form and now the form does.
The MAC field's pattern ([0-9/:]+) had no hex letters, so the browser
refused nearly every MAC address (52:54:00🆎cd:ef) and no IPv4 fixed
address could be added from the page. The host name field of both
dialogs ([a-zA-Z0-9_]+) refused names such as web-01 or db.lan. The MAC
takes hex digits and ":", the name letters, digits, "_", "." and "-";
the server already escapes both into the network XML.