1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
Commit graph

126 commits

Author SHA1 Message Date
catborise
fbd780af02 fix(computes): instance sync asks libvirt outside the DB transaction
refresh_instance_database opened the transaction first and then asked
libvirt for the domain list. A host that goes silent on an established
connection keeps that call waiting until keepalive gives up (30 s). On
SQLite, the default database, the open transaction holds a read lock,
so every other write of the app failed meanwhile with "database is
locked", logins (session writes) included. Reproduced in the test
setup: with a relay to a TCP compute frozen after connecting, three
session writes during the 30 s refresh each failed after 5 s.

- The connection check and listAllDomains run before the transaction,
  still under the compute lock, so create, delete and migration of the
  compute stay excluded as before.
- The transaction only applies the changes. It checks the compute row
  first: a compute deleted while libvirt was asked gets no instances
  (this ended in a foreign key error before).

A failed listing still leaves the database untouched. With the change,
the same reproduction writes the sessions at once and keeps the
instances. Both new tests fail on the previous code.
2026-10-05 10:47:35 +03:00
catborise
7e08224330 perf(instances): instance lists read a VM's info once per row
The VM rows of the instance lists used instance.proxy.instance.info in
every state check, the vCPU column and the action buttons. A template
calls the method on each lookup, so every row made 7 virDomainGetInfo
RPCs (8 on a compute's instances page), and the memory column read the
domain XML once more.

- Instance.info reads virDomainGetInfo once per request; the lists and
  instance_actions.html use it.
- The memory column of both index views comes from the same info
  (current memory) instead of the domain XML. The value is the same:
  checked against currentMemory for every running and shut-off VM of
  the test hosts.

A row now makes one info call and one XML read (the title). The new
test counts the calls in the grouped and non-grouped index and on the
compute instances page; it fails on the previous code with 7 and 8
calls.
2026-10-05 10:17:47 +03:00
catborise
10b46afd36 fix(vrtManager): libvirt connections open within a time limit
libvirt has no timeout for opening a connection. Measured in the test
setup: an unreachable host blocked qemu+tcp for 135 s and qemu+ssh for
133 s; a daemon that accepts and never answers blocks forever. Gunicorn
runs sync workers and the instance list connects to every compute, so
one unreachable compute held a worker for minutes per page load.

- A connection is opened in a helper thread, at most one per
  connection at a time. The request waits LIBVIRT_CONNECT_TIMEOUT
  (default 5 s). An open nobody waits for any more keeps running; until
  it ends, requests get its error at once, and if it succeeds later the
  connection is used. A failed open is not repeated for
  LIBVIRT_RETRY_AFTER (default 30 s). A stuck host holds one thread and
  does not keep other hosts from connecting.
- qemu+ssh runs ssh through vrtManager/libvirt-ssh (the URI's command
  parameter), which adds ConnectTimeout=10 and BatchMode=yes, so an
  abandoned ssh process ends and no prompt can hang. The user's ssh
  configuration (aliases, ProxyJump, keys) still applies.
- The close callback acts only for the connection it was registered
  for: a late callback of a replaced connection dropped its successor.
  The reason is reported as text. A connection that closed before it
  was published is an error.
- Compute.status is a bool (it returned the exception object, so the
  "host is down" check in refresh_instance_database never fired); the
  message is Compute.connection_error.

Unit tests cover the timeout, retry delay, late success, single open,
a stuck host next to a healthy one and the close callback. Live tests
(vrtManager/test_live_connection.py), for TCP and SSH computes of the
test setup: an unreachable address (no ssh left after 10 s), an endpoint
that never answers, a slow open completing later, a host that goes
silent on an established connection (keepalive ends calls within 45 s,
the next request reconnects), an ssh_config alias and a ProxyJump host.
2026-10-05 09:06:52 +03:00
catborise
026391907a chore(computes): remove the unrouted video models view
computes.views.get_compute_video_models had no URL and no caller, and
ComputeManager.get_video_models was used only by it. The video models
of the create page and the VM settings come from wvmConnect directly.
2026-10-04 19:41:56 +03:00
catborise
f94b3cee7a chore: drop references to the local roadmap from code and tests
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.
2026-10-04 11:09:25 +03:00
catborise
39feb373ed fix(vrtManager): host_is_up returns a bool; slow hosts block no others
- host_is_up returned the exception object for a down host, which is
  truthy: check_user_quota then connected to it and failed, so a user
  with a VM on a down host could not open its page, clone or resize,
  and migrate_instance's "target is down" check never fired. It returns
  True or False now, closes its socket, and accepts IPv6 and host:port.
- The connection manager no longer holds its global lock while a new
  connection is opened, so one slow host does not delay new connections
  to the others.

Bounding the connection time itself (including SSH aliases and jump
hosts) is left for a separate change.
2026-10-04 01:08:11 +03:00
catborise
d054b13a87 fix(computes): VM ownership survives a move or a short absence
The sync deleted the Instance of every VM missing from its compute, and
its owners and rights went with it. A VM moved with virsh, or undefined
and defined again, came back with no owner.

Now, when a VM disappears from a compute:
- if the same UUID is recorded on another compute, it moved: its owners
  and template flag go there;
- otherwise they are kept in an InstanceTombstone and restored when the
  UUID appears again within INSTANCE_OWNERSHIP_RETENTION_DAYS (30).
A UUID recorded on two computes at the same time is a copy and gets no
owners. VMs deleted through WebVirtCloud leave no tombstone.
2026-10-04 01:08:11 +03:00
catborise
b04f656d2b ci: replace super-linter with ruff
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.
2026-10-04 01:08:11 +03:00
catborise
51dedb7b8f fix(instances): disk edits keep their XML; changes lock per VM
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.
2026-10-04 01:08:11 +03:00
catborise
3b8869c72f fix(api): typed URLs and accurate response schemas
- Routers use path converters (use_regex_path=False): computes, instances
  and flavors take <int:...> ids, so non-numeric ids get 404 and
  drf-spectacular derives the parameter types itself.
- Each method declares what it really returns: detail serializers,
  a shared StatusSerializer for status-only replies, no request body for
  actions. Instance properties used by the details serializer get return
  type hints.
- The create-instance API drops the firmware field. Its only accepted
  value was "" (BIOS), which produced an empty, invalid enum, and the
  UEFI branch behind it was unreachable. Clients that still send it are
  unaffected; DRF ignores unknown fields.

The schema now passes spectacular --validate --fail-on-warn; a test
keeps it that way.
2026-10-04 01:08:11 +03:00
catborise
fd5aa069be fix: track migrations; installs apply them instead of generating them
The *migrations/* ignore rule is removed. appsettings, computes and
logs pin default_auto_field to AutoField, so makemigrations --check
reports no pending BigAutoField migrations and existing installs need
no schema change.

The Vagrant provisioning no longer runs makemigrations, which created
install-specific migration files that conflict with the committed
history; it only runs migrate.
2026-10-04 01:08:11 +03:00
catborise
e76149c71a fix: serve compute JSON endpoints as application/json, build chipset list safely
compute_graph (text/javascript) and the machine type, disk bus, video
model and domain capability views (text/html) return JSON; send it as
application/json. create_instance_w1.html builds the chipset <option>
elements with .val().text() instead of string concatenation.
2026-10-02 22:34:05 +03:00
catborise
4d34d9d07c fix: add an authorization matrix test and close the endpoints it finds
Add webvirtcloud/test_authorization_matrix.py, which walks every named URL
and checks that a user without any VM/compute relation only reaches an
explicit allowlist, and that the global view_instances permission does not
open consoles. It found:

- /computes/<id>/... views without any check (compute_graph,
  get_compute_*, get_dom_capabilities, storages.get_volumes): the whole
  computes URL namespace is now wrapped with superuser_only, so a view
  added there later cannot be exposed by a missing decorator.
- guess_mac_address (leaks dhcpd.conf host/MAC pairs), random_mac_address
  and guess_clone_name: superuser-only, like the buttons that use them.
- check_instance: cross-tenant VM name lookup with no caller; removed.
- getvvfile and get_vdi_url: reachable with only view_instances, and the
  .vv file contains the VNC password.

Console access now follows one rule, instances.utils.can_open_console:
an active superuser or an active owner of the VM. The global
view_instances permission is read-only. It is used by the console page,
novncd, getvvfile and get_vdi_url (getvvfile and the VDI tab are kept for
virt-viewer users). The console page answers 403 instead of 500 when
access is denied, with the same answer for a missing VM.
2026-10-02 20:33:12 +03:00
catborise
2cdf5dfca1 fix(reconciliation): serialize compute sync and enforce UUID identity 2026-09-28 14:55:49 +03:00
catborise
3f8eeb04bd fix(reconciliation): implement UUID-based domain reconciliation and connection safety 2026-09-27 13:13:43 +03:00
catborise
708b986e8e feat(security): apply Codex review hardening to console tokens and superuser authorization 2026-09-27 11:30:03 +03:00
catborise
1227674d8f feat(security): implement P0 critical security fixes for API, console, and access control
- Computes API: mark password as write_only in ComputeSerializer, restrict ComputeViewSet and architectures to IsAdminUser.
- Instances API: enforce user ownership tenant isolation in InstanceViewSet.list, restrict MigrateViewSet and CreateInstanceViewSet to IsAdminUser, require IsAdminUser for mutating FlavorViewSet.
- Storage, Network, and Interface APIs: restrict StorageViewSet, VolumeViewSet, NetworkViewSet, InterfaceViewSet to IsAdminUser.
- AppSettings & NWFilters: protect appsettings and nwfilter views with @superuser_only (403 Forbidden for non-superusers).
- noVNC Console: sign tokens with TimestampSigner (salt='console.novnc', max_age=600), verify signature and user authorization in novncd with backward-compatible fallback for debug/test mode.
- Accounts: avoid hardcoded default admin password; generate cryptographically secure random password unless ADMIN_PASSWORD is set (preserve 'admin' in test runner).
- gstfsd daemon: bind to 127.0.0.1 by default instead of 0.0.0.0.
- Tests: added comprehensive test coverage for API security, token expiration/rejection, and view permissions (132 tests passing).
2026-09-27 10:50:09 +03:00
catborise
60565b05b3 fix(tests): decouple tests from local libvirt, support configurable test host, and fix URL/logging bugs 2026-09-25 11:51:45 +03:00
catborise
f4651d816d
Merge pull request #650 from catborise/master
fix urls for bus and capabilities
2024-06-24 10:25:48 +03:00
catborise
1edce931ed fix urls for bus and capabilities 2024-06-24 10:22:49 +03:00
catborise
b76b6e382e
Merge pull request #649 from catborise/master
update req
2024-06-24 09:34:25 +03:00
catborise
ee2c55dac7 update chipset url 2024-06-24 08:53:01 +03:00
Wang Hong
e0d83a397b fix icon missing bug 2023-12-13 13:57:38 +08:00
catborise
b47ec2e8f9 bootstrap icon conversion fixes 2023-08-11 09:40:38 +03:00
Emre Serdengeçti
1cbdf76df6
logger updates (#31)
* Log for failed login attempts

* Logger configuration for logging to file

* interface fixes

* login log fix, added logged in too

* bootstrap icons setup

* font-awesome icons replaced with bootstrap icons

* replaced i-tags with django_bootstrap_icons

* removed icons library from project

* bug fix

---------

Co-authored-by: catborise <catborise@gmail.com>
2023-08-09 09:20:18 +03:00
catborise
91ec098aa0 fix cpu_usage waiting for instance creation. 2023-05-18 14:35:19 +03:00
cserma
3cd4212cdd modified 'create new instance' screen with compute details 2023-05-10 13:59:13 +03:00
catborise
e2a15d926c eliminate code repetition with class structure 2022-11-03 10:20:16 +03:00
catborise
a1eab70e2d reorg imports and black format 2022-11-02 16:05:41 +03:00
catborise
217e106c8b format python code with black 2022-11-02 08:54:35 +03:00
catborise
cfce71ec2b
Rest framework (#24)
* 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>
2022-08-22 15:12:33 +03:00
catborise
536caacc80 add title info to vm which list under computes 2021-09-13 10:51:28 +03:00
catborise
073b7b6717
Bootstrap5 (#17)
* Bootstrap5 migration
2021-07-07 14:12:38 +03:00
catborise
ede5710d7c update secret references; move secret to virtsecret because of django compatibility 2021-06-15 14:17:55 +03:00
catborise
5aa22ac042 Django 3.2.4 LTS upgrade 2021-06-15 13:28:47 +03:00
catborise
d7c0f9445d rearrange search functionality 2021-06-15 13:28:47 +03:00
catborise
596d55d481
fix uuid and name changes and update them on db correctly. (#404) 2020-12-31 11:30:33 +03:00
catborise
508e3609be lint with black python. convert f style strings to old one. some small fixes 2020-11-05 12:34:31 +03:00
catborise
5a3e0ad6f2 page header rearragements 2020-10-21 12:09:06 +03:00
Real-Gecko
01043ba8a8 Templates cleanup 2020-10-15 20:18:45 +06:00
Real-Gecko
1b3fd9d05e replaced ugettext_lazy with gettext_lazy 2020-10-14 18:27:57 +06:00
catborise
bb935b3713 fix computes list table layout 2020-07-23 13:57:10 +03:00
catborise
6a8d713ae6 hide compute login password for tcp/tls connections 2020-07-23 13:49:29 +03:00
catborise
74a4a1a3ef vnc console options added 2020-07-17 11:04:21 +03:00
Real-Gecko
47009d47ca Instances overhaul 2020-07-13 15:33:09 +06:00
Real-Gecko
b85e246aed Moved password changing to a separate view 2020-06-16 14:36:53 +06:00
Real-Gecko
d3c59acb3f More tests for computes 2020-06-16 11:04:09 +06:00
Real-Gecko
a4d28f2953 Reworked some computes views and added more tests 2020-06-15 17:52:05 +06:00
Real-Gecko
e4e86ed576 replaced django-fa with django-icons 2020-06-15 14:46:13 +06:00
Real-Gecko
9a75ceb0e5 Replaced __unicode__ with __str__ for models 2020-06-15 12:57:17 +06:00