django-login-required-middleware is dropped; Django 5.1+ ships the same
middleware. The login page is already marked login_not_required by
Django; email_otp gets the decorator, which replaces
LOGIN_REQUIRED_IGNORE_VIEW_NAMES. The datasource still requires login.
Existing settings.py files still name the old middleware. A system
check (accounts.E002) stops migrate and the server until MIDDLEWARE
uses Django's middleware, instead of an ImportError at startup; the
README has the steps.
A new matrix test walks every URL anonymously: everything outside a
short allowlist (login pages, the OpenAPI docs) sends the visitor to
the login page, and API views deny with 401/403. It passed with the old
middleware first and passes unchanged now.
Django 4.2 reached end of life on 2026-04-07.
- Django==5.2.17; django-login-required-middleware 0.9.0 keeps working
(the authorization matrix passes).
- USE_L10N removed from the settings template.
- Log out is a POST form in the navbar; Django 5 removed GET logout.
- pip-audit in CI no longer ignores the Django 4.2.30 advisories.
- README: Django 5.2, backup step and upgrade notes for existing
settings and GET logout callers.
python -Wd manage.py test shows no Django deprecation warnings. The live
libvirt suite passes on 5.2 and on 4.2 against a RHEL qemu-kvm host.
- Runs only when TEST_LIBVIRT_HOST is set, so manage.py test on a
developer machine no longer creates VMs on the local libvirtd.
- Every VM and volume is named wvc-test-*, and volumes live in a
temporary wvc-test pool (/var/lib/libvirt/wvc-test) instead of the
default pool next to real images.
- Cleanup removes only prefixed domains and the test pool's volumes;
it also clears leftovers of an interrupted run before starting, and
tolerates domains that turned transient.
- tearDownClass fails if any domain or volume outside the test
namespace appeared, disappeared or was replaced.
- livetest gains create_volume/define_vm helpers and
test_live_dataloss.py, whose setUpClass opens the class transaction
last, so a failed libvirt connection cannot lock the test database
for later test classes.
The first live tests reproduce two known external-snapshot data losses
and are marked expectedFailure: reverting deletes a disk added after
the snapshot, and deleting the older of two snapshots deletes the
newer one's overlay.
- Pick the test VM by name; .first() could select any VM already on
the compute, and tearDownClass deletes the chosen VM's disks.
- Delete the test volume when setUpClass fails after creating it.
- test-vm.xml: no hard-coded emulator, machine alias q35 instead of
pc-q35-5.1, so it defines on RHEL qemu-kvm hosts too.
- Follow current behavior: power actions are POST-only, the create
form needs add_cdrom/add_input and VNC, cloning needs change
permission on the source VM.
- README: the tests read TEST_LIBVIRT_HOST/TYPE/LOGIN/PASSWORD;
WEBVIRTCLOUD_TEST_LIBVIRT_URI never existed.
- 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.
The forced change of the generated admin password was a session flag
set at login when the password still matched data/admin_password. A
new session after the file was gone bypassed it.
- UserAttributes.must_change_password (migration 0007) holds it; the
admin created with a generated password gets it, and a password
change clears it. ForcePasswordChangeMiddleware reads it.
- A system check (accounts.E001) stops the server unless the middleware
follows AuthenticationMiddleware; the README has the settings change.
- If the generated password cannot be stored privately, provisioning
stops without printing it and without creating the admin (one
transaction for the user and its attributes).
- The admin is provisioned on any real migrate run while no user
exists, so running migrate again after a failure creates it; flush
(plan=None) and rollbacks of accounts are skipped.
- The post_migrate receivers check the migration state for the models
they use, so a targeted migrate on a fresh database (e.g. migrate
appsettings) no longer fails with 'no such table'.
While data/admin_password exists and a user's password still matches it,
the login sets a session flag (checked once at login, not per request).
ForcePasswordChangeMiddleware then sends that user to the password-change
page for every view except change password, login and logout. Setting a
new password clears the flag and deletes data/admin_password. No schema
change; if ADMIN_PASSWORD was set, there is no file and nothing is forced.
- The serial console cannot work until socketiod is rewritten (it does
not understand the signed console token), so the README no longer
describes how to enable it; only the hardening line for existing
installs is kept. The reverse-proxy example no longer sets
SOCKETIO_PUBLIC_PORT.
- Move the users, roles and permissions reference to doc/permissions.md
and link it from the README.
- Hash the root password with a random SHA-512 salt instead of the fixed
"$6$kgPoiREy".
- Talk to gstfsd through one helper with a 120 s socket timeout; an
unreachable daemon or a bad reply is an error message, not a 500.
- gstfsd refuses to listen on a non-loopback address unless
GSTFSD_ALLOW_REMOTE=1: it is an unauthenticated root service.
- gstfsd: encode replies (sendall(str) raised TypeError on Python 3, so
the success path never worked) and use octal chmod modes.
- README: what gstfsd does and how to allow it on a remote compute.
- The generated admin password is written to data/admin_password (mode
0600) instead of being printed, so it no longer ends up in the install
log or `docker logs`. If the file cannot be written it is printed as
before, so the admin is never locked out.
- webvirtcloud.sh no longer echoes the generated SECRET_KEY.
- install.sh creates the install log with mode 0600.
- Comment out the nginx /socket.io/ location: a firewall on 6081 does not
protect a console that nginx proxies on 80/443.
- Default SOCKETIO_HOST to 127.0.0.1.
- README: short enable steps and the changes existing installs need.
- test_socketiod_disabled writes its settings module to a temporary
directory instead of the source tree.
is_staff does not reveal console settings or VNC passwords (fixed on
fix/wave0-staff-console-password), but staff owners with is_change may
also change VMs marked as templates. Superuser-only pages answer 403 to
everyone else, and the console page answers 403 both for a missing VM and
for a VM the user may not open.
Describe the access model: superuser, the global permissions
(view_instances as a read-only auditor role, clone_instances,
snapshot_instances, passwordless_console, change_password) and per-VM
ownership flags (is_change, is_delete, is_vnc), with a table of which
VM actions each combination allows.
The table describes the state after all Wave 0 branches are merged:
disk/media views are superuser-only (fix/wave0-disk-tenant-isolation) and
clone requires is_change except for templates (fix/wave0-clone-permission).
socketiod does not validate the console token, keeps a single global PTY
and broadcasts its output to every connected client, so anyone who can
reach port 6081 can read and write a serial console that someone opened.
It is also broken for legitimate users, since console/views.py now writes
signed tokens that socketiod cannot parse.
Until it is rewritten, turn the serial console off by default:
- Add SERIAL_CONSOLE_ENABLED = False to the settings template; installs
whose settings.py lacks it are treated as disabled.
- The console view shows an error instead of the xterm page for pty
consoles while the setting is off.
- socketiod refuses to start unless SERIAL_CONSOLE_ENABLED is True.
- Supervisor: autostart=false for socketiod; drop -d (debug) from the
supervisor and systemd definitions; fix the systemd unit description;
conf/systemd/install.sh no longer suggests enabling socketiod.
- README: stop opening port 6081 and document how to enable the serial
console on a trusted network.
- Rewrite purpose/features intro around libvirt as single source of truth
- Generate SECRET_KEY into data/secret_key instead of editing settings.py
- Consolidate local development setup into one flow using
--system-site-packages, settings-dev and runserver --nostatic
- Document the generated admin password instead of admin/admin
- Use the shared supervisor config on RHEL (adds missing socketiod)
and add supervisor setup on openSUSE
- Document SOCKETIO_PUBLIC_PORT and CSRF_TRUSTED_ORIGINS for proxies
- Point test setup at the dev virtualenv
- Remove obsolete spice-html5 static assets and SPICE console templates
- Restrict default console types to VNC with migration 0012
- Filter out SPICE in VM creation form and backend capabilities
- Return friendly deprecation notice if legacy VM is opened with SPICE
- Clean up docs, architecture references, and libvirt-bootstrap scripts
- Prevent baking SECRET_KEY into Docker image during collectstatic
- Persist runtime SECRET_KEY in data/secret_key volume or read from environment
- Remove sed-based injection of CSRF_TRUSTED_ORIGINS in favor of native os.getenv
- Avoid overwriting system python3 symlink on SUSE; auto-detect python 3.10+ binaries
- Make /etc/hosts entry in installer idempotent
- Add security notice regarding compute node VNC/SPICE port firewall isolation
- Add python3-libvirt to apt and configure --system-site-packages for zero-compilation build
- Introduce 10_webvirtcloud_init.sh to handle container startup, migrations, and SQLite persistence
- Exclude host settings.py in .dockerignore for clean builds from settings.py.template
- Add docker-compose.yml with persistent data and SSH volume mounts
- Document Docker Compose deployment in README.md
- Configure matrix testing across Python 3.10, 3.11, and 3.12 on ubuntu-latest
- Install system libvirt, ldap, and C build dependencies with pip cache
- Run Django database migrations and test suite
- Run vrtManager unit test discovery with test_*.py pattern
- Fix vrtManager unittest discovery command in README.md
- Relax libvirt-python and lxml version pins to allow precompiled distro packages
- Add PEP 508 environment marker to crypt-r (python_version >= 3.13) to avoid unnecessary C compilation on Python 3.12
- Add stdlib crypt fallback when crypt_r is not available in instances/views.py
- Make LDAP imports and configuration optional in settings.py.template
- Add --system-site-packages and missing packages in webvirtcloud.sh for RHEL/CentOS
- Update README with working Rocky Linux / RHEL / Fedora installation and local dev setup
* 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>
* Added ldap support
* Update
* Added logging
* Update
* Working
* Working
* Working
* Working
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Check for ldap3 existence
* Add eol
Co-authored-by: Kendar <unknown@kendar.org>
This commit implements a fully-automated development setup using Gitpod.io, an
online IDE for GitHub and GitLab that enables Dev-Environments-As-Code.
This makes it easy for anyone to get a ready-to-code workspace for any branch,
issue or pull request almost instantly with a single click.