- The VM list's power forms (style="display:inline") are d-inline.
- The fields scripts show and hide are d-none, and the scripts add and
remove that class instead of calling jQuery's show() and hide(),
which could not undo it: the custom memory boxes of the Resize tab,
the ISO upload's error message and the clone dialog's metadata row.
- The please-wait dialog's full bar is w-100.
- The create-VM pages' own 56rem width (.create-vm) goes: pages stop
at 960px now, about the same.
- static/css/font-awesome.min.css goes: no page loaded it, no element
used its classes and its fonts were never in the repository.
The console pages carried style blocks for what Bootstrap 5.3 has:
- the page's column (flex, no padding, a #494949 background) is
d-flex flex-column p-0 bg-dark; its height stays 100dvh inline, as
vh-100 would run under a phone browser's bar;
- the VNC screen and the serial terminal fill the rest with
flex-grow-1, the screen overflow-hidden, the terminal bg-black; their
min-height: 0 stays inline (Bootstrap has no class for it);
- the rule centring the VNC canvas goes: noVNC centres its own canvas
and draws its own background.
The unused main_container id goes with its style block.
static/css/signin.css (308 lines) gave the sign-in and two-factor
sign-in pages their own components: a card, input groups, a submit
button, a footer and a status dot, with gradients, a blurred card,
entry and pulse animations, and rules that undid base.html's layout
(its container, its padding) from a "signin-page" class the pages'
scripts put on the body.
The pages are Bootstrap now: a card in the grid's centre column, the
logo a rounded-3 bg-primary block, the fields Bootstrap input-groups
with the password toggle an outline button, the submit a w-100
btn-primary, the footer a border-top line with a rounded-circle dot.
They follow the selected Bootswatch theme like every other page.
signin.css, its body class and its decoration go; so does the footer's
"v2.0.0", a version the panel never had.
The sign-out page (logout.html) was never shown: LOGOUT_REDIRECT_URL
sends a signed-out user to the sign-in page. It goes, with the view's
template name.
Three upstream rules in webvirtcloud.css set every page's layout
against Bootstrap 5.3:
- .container { max-width: 900px } held each page to 900px at any
screen width, below Bootstrap's own widths. Pages now take
Bootstrap's container widths up to its lg one, 960px, and stop
there on wider screens: its xl and xxl widths (1140px, 1320px) leave
the panel's forms and lists too wide;
- .page-header (margins of 5px 5px 20px 20px) put headings 20px right
of the content under them; its 14 uses are mb-3, flush with the
content (one carried Bootstrap 4's mr-auto, now me-auto);
- p { margin: 10px } indented every paragraph 10px from the content
beside it; paragraphs take Bootstrap's own bottom margin.
webvirtcloud.css keeps only what Bootstrap has no utility for: the
page width cap, the XML editor's place and height, the Tom Select
colour fix, the sortable table headers' arrows, the grouped VM list's
collapsed hosts and the charts' height.
webvirtcloud.css still carried the upstream panel's rules for what
Bootstrap 5.3 has as utilities and components:
- the page's bottom space (body padding) is pb-5 on base.html's body,
and the console page no longer has to undo it;
- the VM page's action tabs (.action-button, .action-block with a
fixed 65px width) are text-center with a d-block icon; its tab panes
(#power ... #undefine, one rule each) mt-3;
- the bordered sub-tab panes (.tab-pane-bordered, a fixed #eee border
that dark themes could not change) border border-top-0 p-3;
- the search box and header buttons (.search, .btn-header) m-1 and
mt-1; the SSH key select (.keyselect) a form-select;
- the boot order list (.multipleselect, fixed size, #c0c0c0 border) a
list-group of form-check-input items; its unused .multipleselect-on
goes;
- table cells centred by a global rule are align-middle on each table.
Two rules against Bootstrap's behaviour go: menus opened on hover on
wide screens (Bootstrap opens them on a click, and keyboard and touch
users had no hover), and "a { outline: 0 }", which hid the keyboard
focus ring.
The paragraph and page-header margins and the 900px container stay
for a separate change: they set every page's layout.
The fork's own rules in webvirtcloud.css redid what Bootstrap 5.3 has:
- the capacity bars (.cap-*) are Bootstrap progress bars: the memory a
.progress-stacked of running VMs' memory and shut-off VMs' (at half
opacity), each segment a progressbar with its amount as its value
text; the pool bars a thin .progress. The line where the host's
memory ends goes: the share above the bar says it, red when over;
- the status dot (.compute-dot) is a rounded-circle, the big figures
(.compute-ratio) fs-4, the Computes table's cell padding py-3;
- the steps of creating a VM (.create-steps) are a breadcrumb with "›"
as its divider;
- the XML and Advanced disclosures (.disclosure with a turning chevron)
are Bootstrap accordions;
- the chosen volumes and networks (.row-list) are list-unstyled, their
names text-break;
- a chart's container is position-relative by utility; its height stays.
Dead rules go too: .netIN, .netOUT, .diskRD, .diskWR, .input-xs and
.bottom-bar-margin had no users.
The Instances page (grouped and not) and a host's Instances page read
the VMs without an order, so they showed in whatever order the database
returned them: insertion order on SQLite, any order on PostgreSQL,
where it changed between page loads and made a state test fail at
random in CI. They are now ordered by name.
The memory given read "24.0 GB given of 32.0 GB": long, and the share
of the host's memory, what one looks for, had to be worked out. It is
now told as the vCPUs are: the share large ("75 %", amber over 90 %,
red over 100 %), then "24.0 GB / 32.0 GB", the bar and "12.0 GB
running". The Computes list's memory column shares it.
Every card of the overview has a Bootstrap card-header with an icon:
VMs, vCPUs, Memory, Storage, CPU in use and Memory in use (with the
current reading at its right), Hardware, Software and connection. The
last two were label and value lists under indented headings; they are
list-group-flush rows now, the label at the left, the value at the
right: counts in semibold, the hypervisor's and libvirt's versions as
badges, the guest architectures as light badges, the emulator and the
connection as code. The section headings, indented by the panel's
page-header margin unlike the cards, are gone: each card names itself.
The status line and notes are not paragraphs, which the panel indents.
#241 made the host sections pills: on a desktop they took two lines,
unlike the breadcrumb the pages had. computes/host_nav.html is the
breadcrumb again, one line at 1200 px and wider, still shared by the
eleven host pages: the section's own page is its bold item with
aria-current="page", an item page (a pool, a network) links its
section in bold with aria-current="true".
The capacity lines were kept on one line, made for the Computes
table: in the overview's narrower cards a long memory line ran out of
its card. They now wrap.
A host the panel could not reach made its overview the 500 page,
without the host's sections, and the Computes list gave such a host an
Overview button that led nowhere. The page now keeps the host's name,
sections, "Edit connection" and "Remove from panel" (the existing
confirmation), and says "Not connected" with the reason and a "Try
again". Details that cannot be read are said in an alert; the VMs,
capacity and load still show, as they are read on their own.
A reachable host's page leads with what it runs and what it gave:
- its VMs by state (running, shut off, paused, other), linked to
Instances;
- the vCPUs, memory and storage pools given, as on the Computes list,
which now shares those parts (computes/capacity_*.html) and their
preparation (views.shown_capacity) with it;
- CPU and memory in use, side by side, with the current reading in
words, a note on what the charts hold and when they were last
updated, or since when not; memory in GB like the rest of the page;
- Hardware and Software and connection: logical CPUs and clock from
virNodeGetInfo, but physical cores, sockets and NUMA nodes counted
from the CPUs of the capabilities' NUMA cells, as virNodeGetInfo
makes a topology up for hosts it cannot describe (asymmetric NUMA);
the hypervisor's own name and version, libvirt, emulator, the guest
architectures as text instead of menus of dead links. A host without
sysinfo shows no processor instead of failing.
Empty notes no longer show "None"; labels stack over their values on a
phone instead of running into them.
Pools that cannot be read no longer drop a host's vCPUs and memory from
its capacity: the storage part says so. get_capacity also counts the
VMs by state.
Eleven host pages (overview, instances, storages, networks, interfaces,
nwfilters, secrets and their item pages) each carried their own copy of
the links to the host's sections, as a breadcrumb: the sections are
siblings, not a path, and on a phone the separators were left at the
start of wrapped lines. The item pages marked no section at all.
computes/host_nav.html is the one nav, labelled "Host sections": pills
that wrap, the page's section marked active, with aria-current="page"
on the section's own page and "true" on an item of it.
42a1783 refuses a vCPU change on a running VM, also on a direct
request: the VM would get them only at its next start, past the quota
counted now. The live data-loss test still posted vCPUs to a running VM
and expected the change to be pending, so it failed on every connection
type. It now expects the refusal, with its message, and the definition's
vCPUs unchanged; the pending options part is as before.
A key held from the menu (Hold Ctrl, Alt or Windows) is the same key as
the keyboard's left Ctrl, Alt or Windows key. Pressing and releasing
that key on the screen let the VM's key go, while the menu still showed
it held. And when the key went down outside the screen (in the
Clipboard dialog) and came up on it, noVNC sent no release, as it had
not seen the key go down.
The release of that key where noVNC takes keys (the screen, the touch
keyboard) now lets a held key go itself, and clears the menu's mark. A
release elsewhere reaches no VM and changes nothing.
"Type it" sent each character's keysym and let QEMU pick the key from
its own US map, with Shift added for the US shifted characters. A VM
on another layout got other characters: on Turkish Q, '"' typed 'İ',
'@' typed "'", and ğ, ü, ş, ı, ö, ç typed nothing.
The Clipboard dialog now asks for the VM's keyboard layout and
remembers it per browser. Each character is typed as the key that makes
it on that layout (its scancode), with Shift, AltGr or both (AltGr
first: pressed after Shift, the right Alt is Alt on the Linux console),
so the VM's own layout makes the character. The layout is fixed when
typing starts. Text with a character no key types on the layout is not
typed at all, and the dialog lists those characters: a password or a
command with a character left out would be a wrong one.
A layout is one file in console/layouts/: its name and, for each key,
the characters it types plainly, with Shift, with AltGr and with
Shift+AltGr. The view offers every file, US first. dev/console_layout.py
writes a file from the system's XKB data as libxkbcommon computes it
(through ctypes, no new dependency), mapping keys to DOM codes with
noVNC's table from QEMU's keycodemapdb; it lists the dead keys it leaves
out, and drops the keys the keyboard model lacks (the key left of Z on
US pc104 keyboards). English (US) and Turkish Q come with it; the
README says how to add one.
The serial page had a white strip of inline styles with an untranslated
status and a browser-default button above the terminal, sent input while
disconnected, sized the terminal only on window load and resize, and left
the keyboard elsewhere after the key menu. When a superuser opened a
console open in another window, its user saw "[An administrator opened
this console]" and a plain "disconnected".
- console-xterm.html shares the VNC page's bar: status badge (Connecting,
Connected, Disconnected, the server's refusal), Disconnect, then
Reconnect (a new page for a new token). The script is
static/js/console_serial.js; the token reaches it as json_script data.
- The terminal takes the keyboard on connect and after the key menu; input
is sent only while connected; it fits its box on connect and whenever
the box changes size (ResizeObserver).
- A console that writes nothing yet gets a dim local hint: press Enter.
- socketiod sends the displaced client "taken_over" with the superuser's
username; the page shows "Taken over by <name>" in the bar and the
terminal. The superuser is not asked first (owner's decision).
- Fullscreen uses the shared console_keys.js handler (keyboard lock).
The VM page offered a lite and a full VNC console. Lite lacked a clipboard,
display settings and a way to reconnect; full put noVNC's own side bar under
the panel's bar, with a Fullscreen item that called a function noVNC does
not have, status messages hidden behind the bar, saved noVNC settings that
overrode the Access tab's, connection settings that cannot apply, and a
Connect button that reused the page's two-minute token and failed.
console-vnc.html and static/js/console_vnc.js replace both, on noVNC's RFB
with Bootstrap controls, and keep what the full view did:
- Status in the bar (Connecting, Connected, Disconnected, Connection lost,
Could not connect, Authentication failed with the server's reason on
hover); Disconnect, then Reconnect, which loads the page again for a new
token.
- The VNC password in a dialog (with a username when the server asks for
one), not a browser prompt; without passwordless console it is not in
the page.
- Send key(s) gains Hold Ctrl / Alt / Windows (noVNC's extra keys).
- Clipboard: what the VM copies, sending text to the VM's clipboard, and
typing it key by key (new: works in firmware, installers and login
prompts; Shift for the characters a US keyboard shifts, 25 ms a key as
firmware drops faster keys, verified in a UEFI shell).
- View: scaling (none, fit, resize the VM's screen), clip, drag a clipped
screen, view only, dot cursor, quality, compression; it starts as
Settings > Console says (a touch screen starts fitted).
- A Keyboard item on touch devices (noVNC's on-screen keyboard input,
key events and Android's text-only input), Fullscreen with keyboard
lock, the bell.
Dropped with the full view: noVNC's websocket host/port/path, repeater ID
and log level (the panel fixes them), automatic reconnect (the token is
single use in time), XVP power buttons (QEMU has no XVP) and shared-mode off.
The bar is compact (about 45 px in the 850x600 window). The Access tab has
one Console button instead of the Lite/Full split and four switches, and
it and the VM list open one window per VM (opening it again reloads it).
A stopped VM, an unreachable or unsupported console and a disabled serial
console rendered the lite VNC page under the error: it connected to novncd
anyway, showed "Something went wrong" and offered keys, Scale and Send
CtrlAltDel for a console that was not there. A refused console was a bare
text 403 inside the popup.
- console-error.html: the console shell with the VM's name and the reason,
no menu and no script; a refused or unknown VM gets it with 403 and
without the VM's name, as before for everyone (no superuser exception).
- The view signs the console token only for a page that connects.
- console-menu.html: the Send key(s) menu and Fullscreen, included by the
console pages; the serial page lists only the keys it sends (the VNC
groups did nothing there).
- Every console window is titled "<VM> - Console".
- The lite page no longer takes a VNC password from its link.
- The shell lost its 850px x 600px corner radius (a grey arc on the
serial and error pages) and spans the window (container-fluid).
The page's "listens only on its host" check read the VM's next-start
definition, while novncd connects to the running VM's listener: after a
listen address change on a running VM, the page refused a console novncd
could reach, or let through one it could not. The page now reads the
running VM's listener, as novncd does, with the same loopback test, which
moves to vrtManager.util.
ssh's error output went to a pipe that nobody read while the console ran:
once it filled, ssh stopped and the console froze. It now goes to a
temporary file, read when the tunnel closes. Closing waits five seconds
for ssh to end and then kills it, instead of waiting for ever. The Tunnel
holds the ssh process and its error file together.
- The worker told why a console did not open or closed only in the user's
terminal (as users see errors: a host that cannot be reached is not
named). It now also logs the full reason to socketiod's own stderr, the
journal or docker logs, which socketiod hands it as a descriptor.
- A refused token says the link has expired or the user may no longer
open the console: a valid link for a user who lost access was told only
that it had expired.
- A send that takes nothing (0 bytes) waits like a busy stream instead of
spinning.
- socketiod wrote input to the worker's terminal while holding the
session's lock, and the write could wait for the worker; the output
forwarder needs that lock. A large paste into a guest that echoes it
could stop both for good. The terminal is now non-blocking: input is
written as far as the worker takes it, and the wait for room is outside
the lock.
- The terminal is raw from the start. Until the worker made it raw, it
kept at most one 4 KiB line of a paste, and the worker's own setraw
dropped what was typed meanwhile; the worker no longer sets it.
- A superuser's takeover ends the old worker, and waits for it, before
starting the new one: libvirt gives a VM's console to one at a time.
- A resize while the worker ends no longer raises.
webvirt-novncd and webvirt-socketiod get read-only system directories, no
access to /home and /root, no new privileges, no kernel tunables, modules
or cgroups, and only Unix, IPv4 and IPv6 sockets; socketiod also a private
/tmp. novncd keeps the shared /tmp, where a VM's VNC Unix socket may be.
They keep what they need: a pty and its console worker, TCP and Unix
sockets, ssh with its configuration, writes under /srv/webvirtcloud and
the service user's ~/.ssh. The units installed by the update steps bring
this.
A VM defined with QEMU's own VNC websocket (graphics websocket='...',
which the panel never sets) made the console page connect to that port on
the panel's host name: the port is on the compute, so the console did not
open unless the panel ran on that compute, and then it bypassed novncd and
the panel's console token. Such a VM has its ordinary VNC port too, and
novncd now reaches it there like any other VM.
- novncd and socketiod log to stderr: the journal on hosts, docker logs in
the container (runit no longer sends them to unrotated files under
/var/log). Django's settings gave them the panel's own log file, which
every process rotated on its own, and made novncd's -v and -d have no
effect; both work again.
- A refused console says why in the log: novncd's denials are warnings
(they were shown only with -v), socketiod logs each refusal and who
opened which VM's serial console.
- The README's serial console notes say what #228 changed (access
re-checked, superuser takeover, reasons) and where the logs are.
- The VM's console settings have no "Clear keymap" box: it wrote an empty
keymap attribute into the VM, and choosing Auto already removes the
keymap; that change is logged as "remove console keymap".
- The "Clip viewport" switch was labelled "View Clipboard".
- The full console page no longer fills the password field with "None"
for a VM without a console password.
The lite and the full console page each carried the same 150 lines that
send key combinations (Ctrl+Alt+Del, Ctrl+Alt+F1..F12, Alt+Tab, ...). They
now import static/js/console_keys.js, which binds the menu to the page's
RFB connection.
The console page is /console/<compute>/<uuid>/ with the view and display
options in the query. It was /console/?token=<compute>-<uuid>, a "token"
that was only the VM's address, parsed alongside a signed token that no
link ever sent. The list's console button takes the VM's UUID from the
database instead of asking libvirt for each row, and no longer defines a
global function per row.
- The fallbacks for websockify releases without ProxyRequestHandler and
for noVNC's old wsproxy are gone (websockify 0.13 is pinned), with the
Nova names, the per-connection mode switch and the traffic legend.
- The certificate option is gone: nginx ends TLS and novncd speaks plain
websockets on the loopback.
- The mixin is ConsoleClient and the handler ConsoleProxyHandler; the
CLI test that tested a copy of the parser instead of novncd's is
removed (novncd's own parser is tested).
- A console listening on a given address is reached on that address;
the compute's host name is used only for a wildcard listener (0.0.0.0,
::, none). It was always the host name, which may resolve to another
interface.
- ::1 and localhost count as loopback like 127.0.0.0/8: such a console
on a TCP or TLS host is refused instead of being tried on the host's
name.
- The console page says why such a console cannot open and what to change
(listen on all interfaces, or add the host over SSH) instead of a
generic connection error.
The console pages connect to /novncd/ on the address, scheme and port the
page itself was loaded from; nginx proxies it to novncd, which listens on
the loopback only. There is nothing to configure: the console works on
HTTPS (wss), behind another proxy and on any published port.
Before, the page connected to WS_PUBLIC_HOST/PORT/PATH, port 6080 by
default: straight to novncd, past nginx and without TLS, so an HTTPS panel
and a Docker container published on another port had no console until the
public port was set by hand, and novncd listened on every interface.
Gone: WS_PUBLIC_PORT, WS_PUBLIC_HOST, WS_PUBLIC_PATH and WS_CERT, the
installer's two public console questions and its 6080 firewall rule, the
Docker image's WS_PUBLIC_PORT and its init script lines, the manual
install's firewall rule for 6080 and nginx's unused /websockify location.
WS_HOST defaults to 127.0.0.1. A VM with a QEMU websocket port is still
reached on that port of the panel's host name (left for a separate
decision).
- The console worker learns whose session it is and checks every ten
seconds that the user may still open the console: an owner removed or a
user deactivated meanwhile loses it, with a line in the terminal. Access
was checked only when the session started, which could last for days.
- One console per VM: a console left open in a forgotten tab locked
everyone out, superusers included. A superuser's connection now takes
the console over, and the other window is told so.
- A paste reaches the VM whole: the non-blocking console stream takes it
in parts, or none while the VM is busy, and the rest was dropped. The
worker sends the rest until the VM has it, for at most five seconds.
- A libvirt error while the console is open (the host gone, the VM
undefined or migrated) ends the session with one line in the terminal
instead of a Python traceback; libvirt no longer prints its errors on
the terminal. Errors are shown as users see them elsewhere: a host that
cannot be reached is not named.
- The terminal says when the VM is not running and its console will open
when it starts. The terminal is raw before the console opens, and the
stream is dropped once when both threads see the VM stop.
- socketiod's handlers run on their own threads. A connection is now
admitted under a lock, so two at once can no longer both open a VM's
console or pass the session cap. A session's terminal is used and closed
only under its own lock while it is open: a closed descriptor's number,
taken again by a new session, never receives another session's input
or gives it the other's output.
- A refused connection says why: serial console off, the link expired,
the VM's console open in another window, too many consoles. The page
shows it instead of "refused".
- The page no longer retries on its own with a token that has expired
after two minutes; Reconnect loads a new page. Input the browser cannot
encode no longer raises in the daemon.
- The tunnel is `ssh -W` to the console's address or Unix socket: the
compute needs no nc and runs no shell. The old tunnel, copied from
virt-manager, built a shell script with the console's address and socket
path in it and eval'd it on the compute, and always passed "-p 22",
overriding a Port in the SSH configuration.
- On an SSH compute the console always goes through the tunnel, also when
it listens on a network address: it was sent there unencrypted.
- ssh never prompts (BatchMode) and gives up connecting after 10 seconds;
when it fails, what it said is logged. The tunnel ends with the session.
pty.fork returns an inheritable master descriptor, so each new console
worker, and the ssh it may start, held the terminals of every other open
session until it ended. A worker now closes every descriptor above its own
terminal before it starts.
- novncd takes the console token only from its websocket URL. The page
also put the token in a cookie, one for the whole browser, and novncd
preferred the cookie: with two consoles open, a tab that (re)connected
after another console was opened got that other VM.
- novncd opens the VM by its UUID, the VM the access check was made for,
not by its name, which another VM on the host may carry now.
- A VM delete reads delete_disk and delete_nvram as booleans from a JSON
or form body. The view read them as HTML checkboxes from the form body
only: JSON {"delete_disk": true} kept the disks while reporting success,
and a form "delete_disk=false" deleted them. Refused options stop
nothing; the API schema names both options.
- Power on and power cycle of a template answer 409 instead of reporting a
start that did not happen.
- The VM details leave out the host's ISO images for non-superusers, as
the VM page does; reading them also refreshed every pool of the host.
- Flavors take values of at least 1, as the web form does, and show their
id for later changes; a migration needs neither live nor offline; a VM
create on an unknown compute answers 404 instead of 500.
- An API volume takes the name and size the web form takes. Its name went
into the volume XML unchecked, so a name could add elements such as a
backing store pointing at another VM's disk; the name is also escaped
there now. A size of 0 and metadata preallocation on a non-qcow2 volume
are refused or dropped, as on the web form.
- An API compute update with an empty or null password keeps the stored
one, as the web form does; it emptied it and cut the host off.
- The architectures endpoint answers 404 for an unknown compute instead of
500; an unrouted copy of it is removed.
Django replaces a SQLite test database and its parallel clones by the main
file only. A run that is killed, or whose worker pool crashes on a failure
it cannot send back, leaves the clones' WAL files behind; the next run's
fresh copies then replay that run's writes, and hundreds of tests fail with
"Cannot operate on a closed database" or foreign key errors until a clean
run checkpoints the stale WAL away. The test runner now removes the test
database's and its clones' WAL files before it creates and clones them
(not with --keepdb, whose databases they belong to).
- On a narrow screen the grouped list hid the User, VCPU and Memory
headings but not the VMs' cells, so values sat under the wrong headings;
the cells now hide with their headings. Memory says MiB.
- A user with the view_instances permission sees each VM's host in the
list, as the host alerts already name them; the host page link stays a
superuser's.
- A flavor's memory and disk are labelled MiB and GiB, and each value is at
least 1, so "4" is no longer saved as a 4 MiB preset by mistake.
- A booting VM is named by its address's reverse DNS entry. Without one,
the address itself was taken as the name, so its first number ("10",
"192") named the VM: a user who made a VM with that name had their keys
given to every such VM. Such an address now gets no keys; its metadata
hostname is still the address.
- Keys are written as quoted YAML strings, so a comment with an apostrophe
or ": " no longer breaks the key or the file.
- The lite VNC page took the proxy's host, port and path from its link. A
link naming another host made the page send that host a fresh signed
console token, which opened the VM's console for two minutes. The page
now uses only what the server gives it, like the full page.
- On a local-socket host, a VM whose console listens on 127.0.0.1 is
reached directly instead of being refused for want of an SSH tunnel.
- A shut-off VM's console says that the VM is not running instead of
failing with no reason.
- An SSH public key whose comment holds spaces (ssh-keygen -C "John Doe
laptop") is accepted; only the type and the key are checked.
- The created API token is shown by a GET after a redirect, so reloading
the page no longer creates a second token the user never sees.
- The OTP login page shows field errors instead of an empty error box.
- A user without a local password (an LDAP user) is not offered a password
change that could never succeed.
- The create form refuses a name the host already defines. Defining it
again replaced that interface's configuration, for example the host's
own uplink when a bridge was named after it.
- An interface that does not start is undefined again, so the name is
free for another try; the name check above makes this safe.
- A network created with fixed addresses gets one per address of its DHCP
range for any subnet; the old prefix cut assumed a gateway ending in .1
and built addresses such as 10.0.0.1.130. Fixed addresses need a /24 or
smaller subnet.
- A new network that does not start (its subnet is in use) is undefined
again, so the name is free for another try.
- Fixed addresses are changed and deleted on a stopped network too: the
running network is changed only while it runs. A host with only a name
is deleted as defined, not with an empty MAC, shows no "None", and has no
edit button it could not use.
- The create dialog disables the fields it hides, so an IPv6 subnet typed
and then unchecked is not created, and switching from MACVTAP back to
BRIDGE restores the bridge label and the Open vSwitch option.
- Isolated networks show QoS; QoS save buttons no longer raise a script
error; saving an unchanged fixed address says so; two messages lose a
stray backslash and spaces.
- Deleting a rule removes the row clicked, by its position, instead of the
first rule with the same action, direction and priority; a filter changed
since the page was read is refused instead of losing another rule.
- An added rule is added as entered, with all its attributes. It was merged
into a rule with the same action, direction and priority, where libvirt
keeps only the first protocol, so the new rule was silently dropped.
- A new filter shows in the list after it is created.
- libvirt refuses to refresh a pool while a volume is cloned in it. The pool
page, the volume list of the VM and create pages, upload planning and the
API no longer fail on that refusal; they use the list libvirt has.
- A new pool that does not start (unreachable NFS server, a device LVM
cannot use) is undefined again, so the name is free for another try.
- A pool reporting no size, such as an iSCSI pool without LUNs, shows its
page instead of a division error.
- Each clone dialog shows its own format and metadata rows, so a format
is never shown without Convert ticked and silently ignored.
- The new-volume size is labelled in GiB and is at least 1; an inactive
pool shows no "None" volume count.
- The host graphs and the machine/bus lists connect inside their libvirt
error handling, so a down host gives empty answers instead of a 500 page
the polling script drops.
- The Secrets page lists vTPM secrets instead of failing on them, and a
secret without usage data shows an empty cell instead of "None".
- A TCP/TLS host takes a SASL password longer than 14 characters and a
login up to the Linux limit of 32.
- The compute edit page says "Edit Compute"; a host without VMs no longer
closes an extra page element; the memory graph is labelled MiB.
A boot device moved up or down was rebuilt without its click handler, so
unticking it afterwards left it in the boot order that was applied; the
moved label now keeps its checkbox. An empty root password did nothing
and said nothing; it is refused with a message. Changing a NIC of a
shut-off VM gave no confirmation; it now says the device changed.
The resource pattern was not anchored and took any letters after the VM's
name, so VM "web" also counted "webserver" and "myweb"; a VM with no
resource of its own got "Secondary/OK", stored on every page view. A
VM's resources are now its name or name_SUFFIX at the start of a line,
and a VM without one is "None DRBD".