- The root password's SHA-512 crypt hash comes from libpass (the maintained
passlib fork, pure Python) instead of crypt-r, a copy of the stdlib crypt
module gone in Python 3.13: crypt-r ships no wheels and its build needs
crypt.h, which Ubuntu 26.04 no longer brings with python3-dev, so the
installer and the manual installation failed there. The hash is the same
format ($6$, now with libpass's 656000 rounds), checked with glibc's crypt.
- The README's RHEL compute packages left out python3-libguestfs, which
gstfsd imports with the system python: setting the password or key of a
shut-off VM failed there.
- The tests read YAML themselves and had PyYAML only through
drf-spectacular.
The compute bootstrap found openEuler but had no install function for
it, so it stopped. Now it installs qemu, libvirt, python3-libguestfs
and cyrus-sasl (openEuler's names; it has no EPEL), applies the RHEL
family's qemu.conf, SASL and gstfsd steps, and runs the monolithic
libvirtd with its TCP socket: openEuler 24.03 ships modular daemons
only for qemu and the proxy.
Tested in an openEuler 24.03 container with /dev/kvm: the full live
suite over TCP (SASL) ran 2145 tests. What failed is libvirt 9.10's
(reverting a running VM's external snapshot, live clone needs 11.10),
the test host's (no pool named default), and its SeaBIOS, which
prints no banner on the serial port.
gstfsd, the root service on each compute that rewrites a shut-off VM's
/etc/shadow and authorized_keys, did what any client on its port asked.
Now it needs GSTFSD_KEY (64 hexadecimal characters, in the unit's
/etc/default/webvirt-gstfsd) and does not start without it. Each
connection gets a new challenge; the panel signs its request for it
with HMAC-SHA256 and gstfsd checks the signature before any change, so
a request recorded on one connection is refused on another. gstfsd
signs its reply for the same challenge and the panel's nonce, and the
panel accepts only that reply.
Each compute has a gstfsd key, the host's GSTFSD_KEY: the compute forms
and the API take it and never show it, and an empty value on an edit
keeps it. The bootstrap script makes the key file once, readable by
root only; the README shows how to make it and where the panel takes
it. The traffic is still not encrypted: a remote panel's port stays
open to the panel's address only.
"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.
Django clones a SQLite test database by copying its main file, while
migrate's writes were still in the WAL file, so every clone had no
tables. The project test runner writes the WAL back before cloning.
Its pool workers are no longer daemonic, so the operations process
tests can start their own workers. tblib carries the traceback of a
failure out of a worker instead of ending the run.
The suite takes 35 s on 8 CPUs instead of 133 s.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
django-auth-ldap, python-ldap and pyasn1 move to
conf/requirements-ldap.txt. Installs without LDAP no longer need the
openldap and sasl headers that pip builds python-ldap with; the
installer and the README's system packages drop them, and the README's
LDAP section installs them with that file. The settings already work
without the module.
The Docker image and dev/requirements.txt keep LDAP, so CI still builds
and audits python-ldap.
A theme change compiled Bootswatch with libsass (34 MB, upstream
deprecated) into two tracked files, which updates, rollbacks and new
Docker containers then reset. The 27 themes now ship as
static/css/themes/<theme>.min.css, built by "manage.py build_themes";
the Settings page only saves the theme name and every page links that
file (zephyr when no settings are in context, as on the 500 page).
libsass moves to dev/requirements.txt; a test checks that each shipped
file is its theme compiled from dev/scss. The "Theme SASS Path" setting
is removed, and the theme default "flaty", a typo that never applied,
becomes zephyr, the theme those installs showed. The update and
rollback steps restore an older version's rewritten theme files only
where they are modified.
Found by provisioning disposable computes with the bootstrap:
- Ubuntu and Debian: a socket-activated libvirtd ignores libvirtd_opts
"-l", so TCP needs libvirtd-tcp.socket; Ubuntu also kept SASL on
gssapi instead of digest-md5.
- EL10: only virtqemud and virtproxyd were enabled, so storage, network,
interface and other drivers did not answer; and the SELinux policy lets
virtproxyd read but not map the SASL database, so TCP logins failed
(a one-rule module allows it).
- Run from a clone, the bootstrap installs that clone's gstfsd and unit
instead of downloading them.
The RHEL manual install failed at libvirt-devel, which is in CRB; the
installer already enables it. openSUSE's nginx.conf has its own port-80
server for localhost, which the RHEL steps already warn about. The
bootstrap skipped /etc/os-release as a symlink, which on openSUSE Leap
is the only release file, so it found no distribution.
The compute bootstrap installs gstfsd and webvirt-gstfsd.service in one
helper and no longer installs or restarts supervisor; the README's
compute step does the same, a remote panel's bind goes into a drop-in,
and a compute moving from supervisor removes its gstfsd program.
Brite ships with Bootswatch 5.3.8 but was left out when the other themes
were updated. Its sources are copied unchanged from the package, and its
wrapper sets the same breadcrumb, link and navbar spacing as the other
themes. The wrapper also makes the navbar text black: navbar.html uses
navbar-dark on bg-primary, and white on Brite's lime is unreadable.
Brite loads no web font. The Settings page lists it because the theme
list is the wvc-themes directory, and the theme test compiles it with
the rest.
Bootstrap SCSS, the JS bundle and the Bootswatch themes go from 5.3.3 to
5.3.8 (bug fixes only), and wvc-main.min.css is recompiled from zephyr.
Bootswatch now gives table text the body color, and Lux drops card and
modal header borders.
Tests compile every theme with the pinned libsass and check that the
shipped CSS is zephyr from these sources. The update and rollback steps
put back the two files a theme change rewrites, or git refuses to pull
over them.
pycodestyle, pyflakes, pylint, yapf and black were only installed: CI,
pyproject.toml and the docs use ruff, which covers the pyflakes and
pycodestyle checks.
coverage 7.16.2, pyflakes 4.0.3, pylint 4.1.3, black 26.10.1, ruff 0.17.0
(no new findings) and django-debug-toolbar 8.0.0; the template profiler
panel is pinned at 2.1.0. Toolbar 8 renders in a shadow DOM: the
profiler panel still opens and shows its data (checked in a browser).
Its script is requested by a relative URL and gets 404 with 6.3.0 too.
echodebug compared _ECHO_DEBUG and BS_TRUE with -eq, but neither is set
anywhere, so each step printed "[: : integer expression expected". It
now prints debug lines only when _ECHO_DEBUG=1 is set.
The quoting of the tr argument in the /etc/os-release parsing put the
closing parenthesis inside a single-quoted string, so sh and bash
stopped with "unexpected EOF while looking for matching )" before doing
anything: 'curl ... | sudo sh' failed on every distribution. It is now
tr -d "\"'"; bash -n and shellcheck -S error pass.
Also drops the spice_listen edits of qemu.conf; only VNC is used.
- Matrix 3.10-3.13; pip cache keyed on the requirements.
- New steps: makemigrations --check, spectacular --validate
--fail-on-warn, check --deploy --fail-level ERROR, pip-audit of the
installed environment (the Django 4.2.30 advisories are ignored until
the Django 5.2 upgrade), and a Docker image build.
- The separate vrtManager unittest run is dropped; manage.py test
already runs those tests.
- CodeQL also runs on pull requests to master.
- Docker installs into a plain venv instead of using the distro's
python3-lxml and python3-libvirt; lxml>=6.1, since the distro's
lxml 5.2.1 has CVE-2026-41066.
- dev requirements add ruff and pip-audit.
- Upgraded Django to 4.2.30 (latest Django 4.x LTS release)
- Upgraded production dependencies in conf/requirements.txt:
* django_bootstrap5 to 26.2 (latest supporting Django 4.2)
* django-otp to 1.7.3
* django-auth-ldap to 5.3.0
* djangorestframework to 3.17.2 (latest supporting Django 4.2)
* drf-nested-routers to 0.95.3
* drf-spectacular[sidecar] to 0.30.0
* eventlet to 0.41.2
* gunicorn to 26.2.0
* markdown to 3.10 (supporting Python 3.10+)
* paramiko to 5.0.0
* python-engineio to 4.14.0
* python-socketio to 5.17.0
* whitenoise to 6.12.0
* zipp to 4.1.0
- Upgraded development dependencies in dev/requirements.txt:
* coverage to 7.16.1
* django-debug-toolbar to 6.3.0 (latest supporting Django 4.2)
* pycodestyle to 2.15.0
* pyflakes to 4.0.0
* pylint to 4.0.9
* black to 26.5.1
* Add rest framework for API: First Commit
* modify some shell scripts to make variable references safer; modify some python scripts to reduce the code complexity and cyclomatic complexity of functions.
* Add REST API for some webvirtcloud functions. Instance list/delete/create, compute list/delete/create, storages-network list/retrieve. Add swagger and redoc for API interface
* update requirements
Co-authored-by: herengui <herengui@uniontech.com>