1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 03:36:48 +00:00
Commit graph

61 commits

Author SHA1 Message Date
catborise
50dcaba699 refactor(templates): the host pages' scripts load from static files
The host pages lose their last inline scripts: the overview's charts
(host_graphs.js), the New pool, New network and New interface dialogs
(pool_dialog.js, network_dialog.js, interface_dialog.js), a network's
and a network filter's XML editors and dialogs (network_page.js,
nwfilter_page.js, nwfilters_page.js), the secrets page's labels
(secrets_page.js, its texts from the view as usage_texts) and a pool's
page with the ISO upload (storage_page.js). Their URLs and messages are
data attributes of the elements they belong to; the upload reads its
token and address from its form. No template has an inline script or
an inline event handler any more.
2026-11-02 09:45:26 +03:00
catborise
c401479cf9 feat(templates): every confirmation asks in the page's own dialog
Deleting or detaching a disk, deleting a network card, forcing a VM off,
reverting or deleting a snapshot, stopping or deleting a pool, a
network, an interface, a filter or a secret, and the other actions that
ask first opened the browser's yes/no box (confirm()), and the ISO
upload told its mistakes in the browser's alert().

One dialog in the base page now asks for all of them: its title and
confirming button carry the button's own words, its body the button's
question, the confirming button red for a destructive action. Confirmed,
the button is clicked again, so its form sends what it did before. A
button inside another dialog (the flavors) hides that one while asking
and shows it again after; Cancel gives the focus back, and the
confirming button acts once. The ISO upload's mistakes show in its
dialog's error box, announced.
2026-10-31 20:44:39 +03:00
catborise
27b8dd4f1b fix(templates): the dialogs' Cancel is outlined, as the redone ones
The host pages' dialogs (new network, fixed address, DHCP range,
bandwidth limit, new interface, new filter, filter rule, filter clone,
new storage pool, new secret, a secret's value) and the VM page's XML
review closed with a grey filled Cancel beside their action; the
redone dialogs use an outlined Cancel, so the action is the one filled
button.
2026-10-31 18:35:09 +03:00
catborise
a95ec40f69 fix(virtsecrets): a secret in use is not deleted, and a password is stored as typed
- A secret is in use when a VM names it in a disk, a host device or its
  vTPM, or a pool in its source, by UUID or by its usage within the usage
  type, as they run and as saved. The vTPM, host devices and pools' saved
  definitions were not checked before.
- A Ceph key is taken in base64, as `ceph auth get-key` prints it; any other
  value is a password or passphrase stored as typed, spaces included.
- A new secret takes its value at once; a value refused leaves no secret.
- TLS and vTPM secrets can be created; the usage has no length limit.
- Every POST redirects; the list is read once and only with its users; a
  secret, VM or pool gone meanwhile is left out.
- domain_trees() is shared by the in-use checks of secrets, network filters,
  networks and pools; the storage page's Ceph secret picker reads the same
  listing.
2026-10-29 10:10:43 +03:00
catborise
0014b5f240 feat(nwfilters): the network filter pages on Bootstrap's cards, tables and dialogs
As the network and interface pages; plan reviewed with Codex.

- The list is one table with a search: each filter's chain, priority,
  number of rules, the filters it references, and how many VMs and
  filters use it directly; a row's menu clones it (one shared dialog,
  the copy's name filled in) or deletes it, Delete disabled and saying
  so while it is in use. Without the VMs (a host that fails to list
  them) the list is not shown: it would offer to delete filters in use.
- New filter is one dialog with the filter as XML in the Ace editor,
  from a starter filter, with what in, out and priority mean and a link
  to libvirt's format.
- A filter's page: a Filter card (UUID, chain, priority, the VMs that
  use it directly, linked, and the filters that reference it, linked);
  its references with their parameters (one to a filter gone from the
  host marked as missing, not linked), removed per row, added from a
  select of the filters it can reference; its rules with the action as
  a badge, the direction as to or from the VM, the priority (500 where
  none is given), every protocol element with its attributes, a rule
  of no protocol as any traffic of the chain, and when it does not
  track connections; Add rule as an XML dialog; the XML, collapsed,
  saved in place.
- The editors size themselves when shown and keep their label for
  screen readers; tables keep their hidden
  header text inside them, so a phone does not scroll the page
  sideways. add_nwf_rule.html goes (the dialog is on the page).
2026-10-29 10:10:30 +03:00
catborise
bc2b70544a fix(nwfilters): a filter in use is not deleted, and a change replaces no other filter
Plan reviewed with Codex; libvirt's behaviour checked on a host.

- A filter is not deleted while a VM's interface references it, as the
  VM runs or as saved for its next boot (a stopped VM too), or while
  another filter references it: libvirt refuses only one a running VM
  uses, and a VM using a filter that references a deleted one does not
  start. The VMs are read from one listing, one or two XML reads each,
  instead of a connection per VM; the refusal names them.
- Create refuses a name or UUID the host has, clone a name in use or
  one outside the panel's names, and editing the XML must keep the
  filter's name and UUID: each would replace another filter or make a
  copy. Entered XML is read for these checks without expanding entities
  or taking a DTD (util.parse_xml, shared with the network editor),
  and a rule is one <rule> element.
- A rule or reference is deleted only while it reads as the page showed
  it, not by index and three attributes: a rule alike in those or a
  filter changed meanwhile loses nothing.
- A reference is added only to another filter of the host not
  referenced yet; the picker offers those.
- References keep their parameters, in order (a name may repeat); a
  rule shows every protocol element it has, a rule without one too.
- One change a POST (two would both start from the page's reading,
  the second undoing the first); every change redirects and reports its
  refusal as a message, a POST for a filter gone meanwhile going to the
  list; the catch-all that showed any error goes, and so does
  wvmInstance.get_filterrefs, which only the old delete check used. The list reads each filter's
  XML once from one listing; a filter's page reads its XML once and
  only the other filters' names; the per-filter XML dialog of the list
  goes (a filter's page shows its XML). The XML editors send their text
  untouched too.
2026-10-29 10:10:17 +03:00
catborise
965cf0080c refactor(templates): the page width, headings and paragraphs as Bootstrap sets them
Three upstream rules in webvirtcloud.css set every page's layout
against Bootstrap 5.3:
- .container { max-width: 900px } held each page to 900px at any
  screen width, below Bootstrap's own widths. Pages now take
  Bootstrap's container widths up to its lg one, 960px, and stop
  there on wider screens: its xl and xxl widths (1140px, 1320px) leave
  the panel's forms and lists too wide;
- .page-header (margins of 5px 5px 20px 20px) put headings 20px right
  of the content under them; its 14 uses are mb-3, flush with the
  content (one carried Bootstrap 4's mr-auto, now me-auto);
- p { margin: 10px } indented every paragraph 10px from the content
  beside it; paragraphs take Bootstrap's own bottom margin.
webvirtcloud.css keeps only what Bootstrap has no utility for: the
page width cap, the XML editor's place and height, the Tom Select
colour fix, the sortable table headers' arrows, the grouped VM list's
collapsed hosts and the charts' height.
2026-10-27 19:13:38 +03:00
catborise
faa6e4bb14 refactor(templates): Bootstrap utilities instead of the upstream rules that redid them
webvirtcloud.css still carried the upstream panel's rules for what
Bootstrap 5.3 has as utilities and components:
- the page's bottom space (body padding) is pb-5 on base.html's body,
  and the console page no longer has to undo it;
- the VM page's action tabs (.action-button, .action-block with a
  fixed 65px width) are text-center with a d-block icon; its tab panes
  (#power ... #undefine, one rule each) mt-3;
- the bordered sub-tab panes (.tab-pane-bordered, a fixed #eee border
  that dark themes could not change) border border-top-0 p-3;
- the search box and header buttons (.search, .btn-header) m-1 and
  mt-1; the SSH key select (.keyselect) a form-select;
- the boot order list (.multipleselect, fixed size, #c0c0c0 border) a
  list-group of form-check-input items; its unused .multipleselect-on
  goes;
- table cells centred by a global rule are align-middle on each table.
Two rules against Bootstrap's behaviour go: menus opened on hover on
wide screens (Bootstrap opens them on a click, and keyboard and touch
users had no hover), and "a { outline: 0 }", which hid the keyboard
focus ring.

The paragraph and page-header margins and the 900px container stay
for a separate change: they set every page's layout.
2026-10-27 19:05:48 +03:00
catborise
86c708ed68 refactor(computes): the host pages share one section nav
Eleven host pages (overview, instances, storages, networks, interfaces,
nwfilters, secrets and their item pages) each carried their own copy of
the links to the host's sections, as a breadcrumb: the sections are
siblings, not a path, and on a phone the separators were left at the
start of wrapped lines. The item pages marked no section at all.

computes/host_nav.html is the one nav, labelled "Host sections": pills
that wrap, the page's section marked active, with aria-current="page"
on the section's own page and "true" on an item of it.
2026-10-27 14:51:18 +03:00
catborise
1262559793 fix(nwfilters): a rule is deleted and added exactly as clicked and entered
- Deleting a rule removes the row clicked, by its position, instead of the
  first rule with the same action, direction and priority; a filter changed
  since the page was read is refused instead of losing another rule.
- An added rule is added as entered, with all its attributes. It was merged
  into a rule with the same action, direction and priority, where libvirt
  keeps only the first protocol, so the new rule was silently dropped.
- A new filter shows in the list after it is created.
2026-10-26 15:36:57 +03:00
catborise
e5c7dc338d fix(templates): the list pages search their rows as text, with one script
The list pages' search (filter-table.js) read what was typed as a
regular expression: a "(" or "[" stopped it with an error. It also
needed jQuery, while the instance list had its own script for the same
search. Both are now static/js/table_filter.js: plain text in any case,
the instance list's state list and host groups where a page has them,
remembered for a day as before. A group's header row is marked as one
(data-group-header) instead of being any row without a state.
2026-10-25 23:08:42 +03:00
catborise
7cf12b997b feat(tables): tables sort with tablesort, the grouped VM list within each host
sortable.js 0.8.0 (abandoned since 2014) sorted only a table's first
body: in the grouped VM list the first host's row moved among its VMs
and the other hosts never sorted, and memory sorted as text ("1024 MB"
before "512 MB"). tablesort 5.7.1 sorts each table body on its own and
keeps a row marked data-sort-method="none" in place, so hosts stay in
name order with their row on top and their VMs sort below it. Memory,
vCPUs and volume sizes sort by their numbers (data-sort). Headers are
reachable by keyboard and carry aria-sort.

base.html loads tablesort for every table marked data-sortable; the
per-page sortable includes and sortable-theme-bootstrap.css go, so these
tables take the theme's table style like the others. The grouped list's
row numbers go (meaningless once sorted). The VM owners and VM logs
tables were marked sortable but never loaded the script; they stay
unsorted.
2026-10-24 19:02:51 +03:00
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
f9c8c36a6b fix(nwfilters): a filter is changed in place, also while a VM uses it
Every change to a filter (a rule or reference removed or added, the XML
edited) undefined it and defined the new XML. libvirt refuses to
undefine a filter a running VM uses, so none of these worked on such a
filter; on an unused one a refused definition was undone by defining
the old XML without its UUID, so the filter came back as another one.
The filter is now defined again with its own UUID, which libvirt does
in place, while VMs use it too; XML it cannot parse or apply to the
running VMs is refused and reported. The XML editor shows the UUID.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 09:55:27 +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
59e120e62d fix(templates): the dialogs only a real host shows have accessible names
An accessibility scan of the pages on a real host (the earlier scans ran
on libvirt's test driver) found unnamed elements the test driver never
renders: the network page's add fixed address buttons and their dialog
fields, the XML box of each nwfilter's details dialog and the convert
checkbox of the volume clone dialog. The buttons get a title, the labels
a for= and the fields an id, the XML box an aria-label.
2026-10-19 21:17:48 +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
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
57cf49262a fix(instances): clones roll back their copies; own error messages stay
Clone:
- only shut-off VMs are cloned, as the UI already required: a running
  guest keeps writing while its disks are copied; the definition comes
  from the persistent XML;
- MAC addresses and disk destinations are checked before anything is
  allocated;
- every volume the clone creates (NVRAM and disks) is tracked; if a
  later copy or the definition fails, only those are deleted, and any
  that cannot be deleted are named in the error. Before, a failed clone
  left its earlier copies behind.

libvirtError(msg) reports the thread's last libvirt error instead of
msg when there is one, so WebVirtCloud's own errors could show an
earlier, unrelated failure. util.OperationError, a libvirtError
subclass that keeps its message, replaces those raises in vrtManager,
instances and nwfilters; 'except libvirtError' still catches it.
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
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
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
cserma
3403d21fea log i18n fixes 2023-05-10 13:57:01 +03:00
catborise
217e106c8b format python code with black 2022-11-02 08:54:35 +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
610efd5520 add host name for logs beside others 2021-05-31 11:39:09 +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
e97d592e51 fix some messages, add translation for some keywords, update tr locale file 2020-06-12 14:46:17 +03:00
catborise
b7fc8a5fea Language change activation. Fix typos and add new translations 2020-06-10 15:16:58 +03:00
catborise
e46bb99b3b fix typos and rearrange imports & add new lines EOF 2020-06-04 15:22:55 +03:00
catborise
bf15de507a add aria-label definition to forms 2020-06-04 12:05:55 +03:00
catborise
8bafaa8720 add scope to th tags for screen readers 2020-06-04 12:04:46 +03:00
catborise
7c93ee1e2f bootstrap 4.5 fixations & Update strings style to f-string 2020-06-04 11:38:41 +03:00
catborise
871083967f bootstrap 4.5 fixations & fix various localizations 2020-06-04 11:35:57 +03:00
catborise
0e5840498e bootstrap 4.5 & Bootswatch Themes 2020-06-04 11:33:25 +03:00
catborise
b48b112a40 Update Ace XML Editor 1.4.10 - Move seperate dir 2020-06-04 08:51:27 +03:00
catborise
22cb8f702a fix code conventions for pylint 2020-06-04 08:48:43 +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