The host pages lose their last inline scripts: the overview's charts
(host_graphs.js), the New pool, New network and New interface dialogs
(pool_dialog.js, network_dialog.js, interface_dialog.js), a network's
and a network filter's XML editors and dialogs (network_page.js,
nwfilter_page.js, nwfilters_page.js), the secrets page's labels
(secrets_page.js, its texts from the view as usage_texts) and a pool's
page with the ISO upload (storage_page.js). Their URLs and messages are
data attributes of the elements they belong to; the upload reads its
token and address from its form. No template has an inline script or
an inline event handler any more.
The host pages' dialogs (new network, fixed address, DHCP range,
bandwidth limit, new interface, new filter, filter rule, filter clone,
new storage pool, new secret, a secret's value) and the VM page's XML
review closed with a grey filled Cancel beside their action; the
redone dialogs use an outlined Cancel, so the action is the one filled
button.
As the storage pages; reviewed with Codex.
- The list is a card per network: its name with Active or Stopped and
Autostart badges, its type (network_mode: Isolated, NAT, Routed,
Open, Bridge, Macvtap, SR-IOV), its device, and each address with
its DHCP range; a bridge or macvtap network's addresses come from
the outside network.
- A network's page: its heading starts or stops it, the menu sets
autostart and deletes a stopped one. A Network card tells its state,
type, bridge or interface, MAC and what the type does; a card per
address (every <ip>, each with its DHCP range dialog, which libvirt
takes on a stopped network); its fixed addresses of every subnet in
one table, searched, each with Edit and Delete, one dialog adding
and editing them; the VMs whose definition names it, connected or
configured, linked (wvmNetwork.get_vms, one domain listing, a VM
undefined meanwhile left out); its
bandwidth limits where libvirt sets them (not on macvtap or SR-IOV
networks), in KiB/s, from the saved definition with a note that a
running network takes them when restarted; its XML in an accordion.
The page reads the running and the saved definition once each, and
only to render itself: its actions, which all redirect, read nothing
of it first.
- The New network dialog is one form, as the New pool one: the type
as radio cards (the radio_card.html include, now shared by both),
the chosen type's fields only, IPv6 with its box, a bridge or
interface suggested from the host's (get_host_interfaces, not the
bridges libvirt made for its own networks); a refused network or
one libvirt refuses opens the dialog again with what was entered,
the reasons beside the fields and focus on the first.
- What the New pool and New network dialogs share is one script,
static/js/choice_dialog.js: the radio cards show their fieldsets
(data-kinds) and a refused form opens again focused on its first
refused field; each dialog keeps only its own changes.
- The fixed-address dialogs per family go to the page's own dialog.
- The pool list is a card per pool, two to a row, as the host
Overview's Hardware and Software cards: its name with Active or
Stopped and Autostart badges in the header, then its type, its path
(an RBD pool's Ceph pool), its volume count and its space as the
Overview shows it (computes/pool_bar.html, without the name again);
a stopped pool's space is unavailable, not zero.
wvmStorages.get_storages_info gives the path, autostart and percent
used, which computes.views.host_pools computed for itself.
- A pool's page has a Space card (percent, used of size, of what: the
filesystem of its path, its volume group or the Ceph cluster, which
other pools may share; free) and a Pool card (state, autostart,
type, path) instead of a two-column list mixing facts and forms.
Start or Stop is its heading's button; autostart and deleting a
stopped pool are in its menu; the confirmations stay.
- The volume table drops the row number; a volume's capacity and what
it has allocated share a column hidden on a phone; its format is a
badge; its actions are one group, Clone and a menu with Delete,
named for the volume.
- "New pool", "New volume" and "Upload ISO" are labelled buttons
instead of bare green pluses; their dialogs' titles name them.
- The New pool dialog is one form (design reviewed with Codex): the
pool's type as radio cards, as the VM create page chooses its disk
source (their style moves to webvirtcloud.css), one name, and only
the chosen type's fields, the others hidden and disabled.
- A directory's or a share's mount path follows the name
(/var/lib/libvirt/<name>) until it is edited: no default path of
another pool any more.
- ISO images is a directory preset named iso; when the host has an
iso pool, a card links to it instead.
- Ceph offers the host's Ceph secrets by their names, not every
secret by UUID; without one it says so and links the Secrets page.
- LVM asks to agree that the device is erased, the server too.
- AddStgPool checks each type's fields, a name or a path another
pool has, an RBD secret that is not one of the host's Ceph secrets,
and the names "." and "..". A refused pool, or one libvirt refuses,
opens the dialog again with what was entered, the reasons beside
the fields and focus on the first; the audit row for a taken name
stays.
create_storage_ceph and create_storage_netfs wrote the pool, host, user,
secret and format values into the pool XML unescaped and unchecked: the
page's patterns were the only guard, and a direct POST could break or
extend the XML. The values now go through util.xml_escape, as the
network code does. The page's host fields stopped at 20 characters, so
nfs01.storage.example.com could not be typed: they take a host name's
253; the Ceph pool and user fields lose the limit the server never had.
An accessibility scan with every modal opened found 49 fields without a
name: the labels of the instance create forms (custom, template and each
flavor's modal), the interface, network, secret and storage pool modals
did not point at their fields. Each label now has a for= and its field an
id, prefixed per form (and per flavor), so a click on the label focuses
the field too. The "Advanced" collapse buttons and the memory and
processing bars are named.
The VCPU config select had id="vcpu_mode" in each of these forms, nine
times on the create page; the unique-ID test did not see it as the test
driver reports no CPU modes. The id goes (nothing used it), and the test
now renders that branch.
The create pool modals kept their own pattern attributes, older and
stricter than the server's check: a logical source took only lower-case
letters, digits and "/", dir and NFS paths no "." or ":", and the NFS
fields stopped at 40 characters (the form allows 100). The browser
refused /dev/mapper/vg0-data, /dev/disk/by-id/wwn-..., /srv/vm.images or
/export/vm_images.v2 before the server saw them. The path fields keep
"required" and leave the check to the server, which shows its message.
An accessibility scan (axe-core, WCAG 2 A/AA) of every page found 87
elements without a name. Icon-only buttons and links (the navbar's
administration menu on every page, the add/create buttons, the flavor
delete and back buttons) get a title, which is also their tooltip; the
labels of the language, architecture, chipset and filter selects point
at them; the memory bar is named. The shared delete confirmation page
had an empty <title> and heading, as no view passes "title": it says
"Delete <object>". The power-off form's aria-label was misspelled.
Rendered through every URL on libvirt's test driver, the pages had
duplicate IDs and markup browsers repaired silently:
- Each flavor modal's "Advanced" button toggled #flav-add-collapse, the
first modal's section; every modal now has its own. The flavor and
template copies of the custom tab's control IDs, and the template
tab's unused images input, are gone.
- The VM page's action icons and the XML editors were styled by
repeated IDs; they use classes.
- Modal forms opened inside modal-body and closed after modal-footer;
they wrap both. Stray end tags and duplicate attributes are removed,
paragraphs no longer hold modals or rows, table heads have a row, and
the create page closes its row and column.
- html lang is the active language instead of "en".
A test walks every URL as a superuser and fails on a repeated ID. The
console page still has no doctype: its full-height layout relies on
quirks mode and needs its own check.