moveto read the VM state for each flag and dropped options that did
not fit it, so a request could run as something else than asked; the
log then named the mode from the form ("live" or "offline"), not the
one used. The API did not log at all and answered "instance migrate is
started" after the migration had finished.
- moveto reads the state once. A running VM migrates live, or without
live paused for the transfer (non-live); a paused VM stays paused; a
shut-off VM moves offline. Live for a shut-off VM, offline for a
running or paused one, and any other state are refused before
anything changes. unsafe, auto converge (live only) and compressed
apply to a running VM.
- migrate_instance logs the outcome for the VM page and the API: the
mode and options used, or the error. The API answers
"instance is migrated (<mode>)" and accepts requests that leave out
an optional option.
- Post copy is gone from the form, the view and the API: only the
flag was set, and without migrateStartPostCopy, which the app never
called, the migration never switched to post copy.
Comments, docstrings and live test names cited item IDs of a roadmap
that is not part of the repository. They now say what is meant, or
nothing where the sentence stands without them. Test assertions and
behavior are unchanged.
Super-linter ran from the unpinned :latest image and, because of
branches-ignore: [master], never on pull requests to master. Ruff now
checks syntax errors and pyflakes rules (E9, F) on every push and PR.
Fixes the existing findings: unused imports and variables, an unused
duplicate import in instances/tests.py, and the star import in
accounts/views.py. settings-dev.py keeps its star import of the base
settings.
Disk edits:
- edit_disk built a new <disk> from the form and replaced the old one,
losing what the form does not show (e.g. encryption and virtio
driver options); a bus change detached and re-attached the disk.
The disk of the persistent definition is now edited in place and the
domain defined once; a bus change picks a free device name and drops
the old address and virtio-only options. Pending persistent changes of
a running VM are kept.
- Clone omits empty disk devices, refuses a disk without a supported
source and destination, and checks the name before allocating storage.
Locks:
- Every VM change held its compute's exclusive lock, so one slow
operation blocked all VMs on that compute. A VM change now holds its
own VM lock plus a shared compute lock; reconciliation, migration and
cloning hold the compute exclusively (two clones of different VMs
must not pass the name check together).
- Quota-checked changes of one user (CPU, memory and disk resize,
clone) run one at a time under a per-user lock, also across computes,
so concurrent requests cannot all pass the check against the old
allocation. It is the outermost lock; superusers, who have no quota,
skip it.
- A busy lock answers 409 to the API and a message in the web UI. API
power and destroy actions return the view's error instead of success.
Disk and media mutation views (add_new_vol, add_existing_vol, edit_volume,
delete_vol, detach_vol, add_cdrom, detach_cdrom, mount_iso, unmount_iso)
were reachable by any owner with is_change, although the UI only shows the
Disk tab to superusers. An ordinary user could delete any volume on the
compute or attach arbitrary host files to their VM.
- Require superuser for all disk/media views, matching the UI.
- delete_vol resolves the volume from the VM's own disk XML by dev and
ignores the posted storage/name.
- Validate bus/cache/io/discard/detect_zeroes against the hypervisor's
lists, and format/serial/volume name against strict patterns.
- add_existing_vol only accepts volumes that exist in the selected pool.
- edit_volume only accepts a dev attached to the VM.
- vrtManager: escape all values interpolated into disk XML and pass dev
as an XPath variable in detach_disk/edit_disk.