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

60 commits

Author SHA1 Message Date
catborise
5b8793ad4c feat(logs): changes to networks, storage, interfaces, secrets and filters are logged
The Logs page now records every change an admin makes to a compute's
libvirt objects, with the compute's name in the host column:

- networks: add, start, stop, delete, autostart, DHCP range, fixed
  addresses, QoS and XML edits;
- storage pools: add, start, stop, delete, autostart, from web and
  API; volumes: add and delete (web and API), clone and ISO upload;
- host interfaces: add, start, stop, delete;
- secrets: add, set value (never the value), delete;
- network filters: add, clone, delete, XML edits, rules and
  references.

A refused or failed change is a failed row with its reason (libvirt
text through safe_text). The volume clone and upload jobs write their
row when they end; a refused submission is a failed row at once. A
volume row names the volume libvirt created (a dir pool adds .qcow2 or
.img). Volume create or delete through the API on an inactive pool
(409) is a failed row.

Network filters: the rows read "Network filter f1: add" instead of
"f1 network filter is created", and their host is the compute's name
instead of its hostname. A duplicate name or UUID no longer raises a
bare exception, and a filter XML that cannot be parsed no longer ends
in UnboundLocalError.
2026-10-23 13:30:21 +03:00
catborise
2144b3fe20 fix(templates): each confirmation says what its action does
Twenty-five prompts asked only "Are you sure?", and on the storage page
one handler asked the same before every button, Start and Enable
included. Each destructive button now names its object and says what
happens: a stopped network cuts running VMs off, a deleted pool keeps
its files, a deleted volume loses its data, a reverted snapshot loses
the changes made since. Saves no longer ask, and disabled buttons lose
prompts they could not show. The VM QoS messages said to restart the
network where the VM has to be powered off and on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 21:25:45 +03:00
catborise
676bcfeb09 fix(templates): forms and detail lists fit a phone screen
Column offsets without a breakpoint applied below it, where the column
is already full width, so the change password, compute, user, VM
create and VM settings forms ran past the right edge on a phone. Each
offset now starts at its column's breakpoint. The interface and network
detail lists were rows directly inside rows and sit in a column now;
the compute form loses a Bootstrap 3 thumbnail padding that broke its
gutters, and the add-rule dialog's hint is no longer cut off. The page
test checks both grid rules on every page.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:19:14 +03:00
catborise
e324e79fcb fix(templates): a wide table scrolls in its own box on a narrow screen
Twenty tables had no .table-responsive wrapper, so on a phone the user
list, compute list, VM lists, network and network filter pages scrolled
sideways as a whole. Each table now scrolls inside its box, as the
other ten already did. The page test walks the network page too, and
checks that every table on every page has the wrapper.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 12:57:26 +03:00
catborise
b45f673da7 fix(templates): status colours keep their contrast on every theme
The pool, network and interface cards had a solid green or red header
with light text, and status words (Connected, ON, OFF, the DRBD state)
were in the theme's green or red text colour. axe found them below the
WCAG AA 4.5:1 contrast on the live theme (4.29:1, 3.52:1), on the
default zephyr theme, whose green is light (2.5:1), and on dark themes
(darkly 1.18:1).

The card headers, and the status words as badges, are now the theme's
pale status background with its dark status text (bg-*-subtle with
text-*-emphasis). Bootstrap derives the pair from each theme's palette,
and it does not depend on the page's background: the dark Bootswatch
themes keep light-mode emphasis colours, which on their own would be
dark text on a dark page. The card border keeps the status colour.
2026-10-21 08:10:42 +03:00
catborise
ca74c02c4f fix(templates): the fields of the create modals are named by their labels
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.
2026-10-19 20:01:36 +03:00
catborise
64057f8d05 fix(templates): icon-only buttons, selects and delete pages have accessible names
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.
2026-10-19 16:15:06 +03:00
catborise
3a4488d34f fix(templates): pages parse without markup errors, element IDs are unique
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.
2026-10-19 07:49:25 +03:00
catborise
28a73519d7 fix(interfaces): deleting a bridge keeps the devices it held
With the netcf backend (RHEL/AlmaLinux 8), undefining a bridge also
removes its members' configuration: the device came back without any
after a reboot. Like virsh iface-unbridge, each member is now defined
again on its own after the bridge is undefined, with the bridge's start
mode and, when it is the only member, its addresses. A bond keeps its
mode and devices.

Checked on AlmaLinux 8 (libvirt 8.0, netcf): an ethernet and a bond
member get their ifcfg back, and the bond comes up with the address
after a reboot.
2026-10-18 22:01:18 +03:00
catborise
c55f52f025 test: each app keeps its tests in a tests package
131 test modules sat next to the code they test; instances alone had
51 of them beside views.py and utils.py. They move into a
tests/ package per app, and the JavaScript checks into
webvirtcloud/tests/js. Each non-empty tests.py becomes tests/test_views.py;
the empty generated stubs are removed.

Imports of the app's own modules become absolute, paths built from
__file__ go one level up, the live helper is instances.tests.livetest,
and coverage omits */tests/*. The suite discovers the same 960 tests as
before.
2026-10-12 15:17:30 +03:00
catborise
0bb4337043 fix(interfaces): no create, start, stop or delete where libvirt cannot change interfaces
libvirt's udev interface backend (RHEL 9 and later, Debian 12) only reads
interfaces, so the create form and the start, stop and delete buttons
only failed there. The pages ask the host with an invalid definition,
which defines nothing: a backend without define refuses it as not
supported. There they show the interface state and a note instead, and
posts change nothing; the host's devices, needed only by the create
form, are not read. Any other answer keeps the pages as they were.
2026-10-10 21:38:22 +03:00
catborise
342f6a7135 fix(interfaces): a bridge over a bond or vlan keeps the device's settings
A new bridge always declared its member as type='ethernet'. On a host
with the netcf backend that rewrote the member's configuration: a bond
lost its BONDING_OPTS and a vlan its VLAN=yes. The member is now taken
from the host's own definition of the device (a bond keeps its mode and
devices, a vlan its tag), without the start mode, MTU and addresses that
only a top-level interface has; a device the host does not define stays
ethernet.
2026-10-08 23:23:22 +03:00
catborise
55eb63a09f fix(interfaces): an ethernet interface needs no bridge member, and unreadable host devices are reported
The form required a bridge member for an ethernet interface, which does
not use one. When the host's network devices could not be read, the error
was swallowed and every creation failed with "the device is not on this
host"; the page now shows the real error and does not try.
2026-10-08 08:50:21 +03:00
catborise
443b31d86b fix(interfaces): a host interface can be created with DHCP or no IPv4, and every value is validated
The IPv4 address and gateway were required even for DHCP or no IPv4, so
such an interface could not be created; malformed addresses passed and a
missing prefix crashed the XML builder. They are validated like the IPv6
fields now (netmask notation accepted, IPv6 scope ids rejected), and a
static address without a gateway gets no empty route. Interface names
follow the Linux rule (up to 15 letters, digits, . _ -). A bridge member,
or the device an ethernet interface configures, must be a device of the
host (the page no longer falls back to made-up names), a bridge cannot
contain itself, and needs STP and a non-negative delay.
2026-10-07 20:42:02 +03:00
catborise
525018dd99 fix(interfaces): validate IPv6 address and gateway of host interfaces
The form checked both with re.match("^[0-9a-f./:]+|^$"), which tests
only how a value starts: "2001:db8::10/64'/><evil/>" passed and went
into the interface XML, which is built with f-strings, while upper-case
hex was refused. An address without a prefix passed too and then failed
with a ValueError when the XML was built.

The address is parsed with ipaddress.IPv6Interface and stored as
address/prefix (/128 when none is given), the gateway with
IPv6Address. A static configuration needs an address, and the XML gets
a route only when a gateway is given instead of gateway=''. The HTML
patterns accept upper-case hex.

Eight of the ten form and XML checks fail on the previous code.
2026-10-04 17:29:59 +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
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
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
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
a1eab70e2d reorg imports and black format 2022-11-02 16:05:41 +03:00
catborise
af38e90f41 fix dhcp type interface error 2022-11-02 11:32:44 +03:00
catborise
217e106c8b format python code with black 2022-11-02 08:54:35 +03:00
catborise
234638a85c add missing migrations for new models 2022-08-24 09:34:16 +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
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
2f1b11b3ca reorganize host interfaces. remove it from instance methods 2021-02-12 16:05:16 +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
7bb6bd310b update locale files and TR translations. 2020-06-10 11:15:14 +03:00
catborise
6a0d04d300 replace deprecated ifequal/ifnotequal with if 2020-06-04 15:40:57 +03:00
catborise
bf15de507a add aria-label definition to forms 2020-06-04 12:05:55 +03:00
catborise
0e5840498e bootstrap 4.5 & Bootswatch Themes 2020-06-04 11:33:25 +03:00
Real-Gecko
10b6f88dbb Added coverage.py support 2020-05-29 19:37:49 +06:00
Real-Gecko
27f62dff6c Added admin application
- Manage users
- Manage groups
- Manage logs
2020-05-27 18:24:06 +06:00
Real-Gecko
38befa4362 Added django-login-required-middleware
Thus eliminating need for login_requred decorator on every view
2020-05-27 12:43:29 +06:00
catborise
a6f7618854 convert django.core.urlresolver to django.urls. fix i18n. fix identation 2020-01-24 10:09:46 +03:00
catborise
592112590c add ability to show interface's ip address with qemu agent. Add checking agent if installed or not 2019-12-23 15:48:11 +03:00
catborise
0738ec7ec4 adds bridge slave list to details of interface 2019-11-04 12:03:13 +03:00
catborise
f3f4f0afe8 Fix typos. Code Inspection for pep8 conventions 2019-10-30 11:05:50 +03:00
catborise
828a271789 pep8 style code corrections 2019-09-10 09:48:31 +03:00
catborise
b18290794e Translate, indentation and typo fixes 2019-07-31 11:03:48 +03:00
catborise
25e6381fc9 add Compute instances tab. Minimal invasion. minimal change. keep structure 2018-09-28 13:33:21 +03:00
catborise
35bc8c67e4 Add NWFilters 2018-09-21 19:11:17 +03:00
catborise
aba92e30b5 x character converted to &times; 2018-08-01 17:18:51 +03:00
Jan Krcmar
dac974ddab request.user.is_authenticated() substitued for @login_required decorator
settings.LOGIN_URL = /accounts/login
2015-12-22 15:09:02 +01:00