Commit Graph

235 Commits

Author SHA1 Message Date
bbec17abd1 feat(metrics): add collector + retention loops and wiring 2026-06-21 21:35:02 +05:00
df2c59eb3f chore: pre-existing WIP (overview/realtime/format/types/use-instances)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:35:02 +05:00
6769e5b218 feat(metrics): add /metrics read endpoints for vm and container 2026-06-21 21:35:02 +05:00
e380ec1ab2 feat(metrics): add query_instance_metrics read aggregation 2026-06-21 21:35:02 +05:00
8f9f78ef91 feat(metrics): add blockstats + netstat client wrappers 2026-06-21 21:35:02 +05:00
3d55b1ab8d feat(metrics): add timeframe/bucket math and series aggregation 2026-06-21 21:35:02 +05:00
3a2c87bd0a feat(metrics): add rate + blockstats/netstat/fsinfo parsing helpers
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:35:02 +05:00
3b3841fc0e fix(metrics): portable BigInteger PKs + split test asserts 2026-06-21 21:35:02 +05:00
572bb44ffa feat(metrics): add instance_metric and instance_nic_metric models
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 21:35:02 +05:00
a4b99c2383 fix(instances): type multiSelectFilter as FilterFn<any> for column reuse
Some checks failed
Deploy to Production / Trigger production update (push) Failing after 10s
Allows the shared column filter to be attached to typed VMInstance columns
without a FilterFn<unknown> assignability error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:28:01 +05:00
5c6bb013c9 feat(instances): surface PVE lock state in the instances list
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 50s
Deploy to Production / Trigger production update (push) Successful in 8s
Backend returns the live `lock` field (clone/create/migrate/...) and the
list shows an amber badge next to the status, so an instance that is
still being cloned no longer looks like a ready stopped VM.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 00:38:41 +05:00
6b3700f496 feat(clone): richer clone dialog with node, storage and owner pickers
Expose target node, target storage, owner (admin-only) and description
in the clone dialog, wired to the existing backend params. Reset the
form on open and fix the cramped label/field spacing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 00:38:41 +05:00
1cc4d86b18 feat(clone): real disk-copy progress, owner assignment and DB registration
- _do_clone_sync now tails the PVE clone task log and maps the disk
  transfer percentage to deploy progress 50→95% instead of a static 70%.
- Add owner_id to CloneRequest; admins may assign the clone to another
  user (mirrors LXC deploy). Register the cloned instance via
  save_vm_instance so it has an owner and is visible to limited users.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 00:38:26 +05:00
8ebef3d10e feat(instances): add column filters and VM config formatter
Add ColumnFilter component (Popover-based faceted filter) and a
formatVmConfig helper rendering "N vCPU / X GB RAM / Y GB".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 00:38:14 +05:00
0d4406024f i18n(instances): translate settings tab labels and tidy field spacing
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Move hardcoded English labels (compute resources, disk resize, raw
config, etc.) to i18n keys and replace ad-hoc mt-1 with consistent
space-y-1.5 between labels and inputs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:40:12 +05:00
a1aaa97b24 feat(backups): add search field to backup files and amber VM-picker checkboxes
Filter backup files by VMID, volume, notes or node in real time, with a
distinct empty state for no-match. Tint the job dialog VM-picker
checkboxes with the brand amber accent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:40:12 +05:00
315aaed58b fix(instances): widen VM management dropdown so menu items fit on one line
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:40:12 +05:00
aa0ea459cd fix(snapshots): send required node param and add storage-support hint
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 49s
Deploy to Production / Trigger production update (push) Successful in 9s
useCreateSnapshot omitted the required ?node= query param, so creation
failed with a 422. Pass node through, and add a UI hint plus a clear
error message when the VM storage does not support snapshots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:35:42 +05:00
3cac5f6c2a fix(api-client): format FastAPI error detail instead of [object Object]
new Error(error.detail) produced "[object Object]" when detail was an
array (422 validation errors) or object. Add formatApiError() to extract
a readable message and widen ApiError.detail to match real responses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:35:34 +05:00
7d003f7fa1 fix(snapshots): wait for Proxmox task to report real outcome
create_vm_snapshot/create_container_snapshot returned success as soon as
the POST returned a UPID, so a snapshot that failed asynchronously (e.g.
storage without snapshot support) still reported "created". Now wait on
the task and surface the actual exitstatus.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 23:35:26 +05:00
a675976303 docs: fix UI port from 8000 to 3001 in all docs
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Frontend (React/nginx) is served on port 3001, not 8000.
Port 8000 is the backend FastAPI — API endpoint and /docs
references at 8000 are kept as-is since they are correct.

Fixed in: README.md, README.ru.md, WIKI.md (quick-start URL
and standalone deployment port description).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:27:13 +05:00
7f439aa08e fix(updates): build before down so a failed rebuild keeps the stack up
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 46s
Deploy to Production / Trigger production update (push) Successful in 8s
The host watchdog ran `down` before `build --no-cache`, so a failed
build left the whole stack offline ("code updated, containers don't come
up"). Reorder to build first (app + frontend) while the old stack runs;
only tear down once images are ready. Use `up -d --wait` so success means
containers actually became healthy (DB migrations run on app startup),
and log `compose ps` + a hint on failure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:23:23 +05:00
11d2c06fb1 fix(updates): parse version build suffix like 1.5.2-1
_parse_version split on "." only, so "2-1" hit int() and the whole
version collapsed to (0,) — update checks ignored build bumps and could
even offer a "downgrade". Extract every numeric run via regex instead:
"1.5.2-1" -> (1, 5, 2, 1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:23:23 +05:00
efcefb5ae3 docs: sync README and WIKI to v1.5.2-1
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 9s
- README.ru.md: bump badge from 1.5.0 to 1.5.2-1; add real-time
  disk/IOPS/network metrics, per-user language and ConfirmDialog entries
- README.md: add same new feature bullets to Monitoring and Other sections
- WIKI: fix language-switch path (Panel → Profile since v1.5.2);
  update log-retention note (log_retention_days now in UI, not DB-only);
  update footer date and version (May 7 / 1.5.0 → June 20 / 1.5.2-1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:13:32 +05:00
48215cbc0b chore(release): bump to v1.5.2-1
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Update VERSION, README badge, CHANGELOG (en/ru) and WIKI for v1.5.2-1.
Patch release: styled ConfirmDialog replaces all native browser confirm() popups.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 17:50:46 +05:00
14cac12191 feat(ui): replace all native confirm() dialogs with styled ConfirmDialog
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Add ConfirmDialogProvider + useConfirm hook (Promise-based API) so every
window.confirm() in the app is replaced with a consistent themed modal.

Replaced in 11 files (16 call-sites):
- Settings: update panel action
- Templates: delete template
- Storages: delete storage
- SSH Keys: delete key
- Nodes: delete server
- NodeNetworks: delete interface, apply pending, revert pending
- HAResources: remove HA resource
- SDNManager: apply SDN, delete zone/vnet, delete subnet
- IPAM: release allocation, delete pool, cleanup orphans

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 09:09:26 +05:00
9b4fbf13ba chore(release): bump to v1.5.2
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Update VERSION, README badge, CHANGELOG (en/ru) and WIKI for v1.5.2.
Covers: real-time disk/IOPS/network metrics, per-user language preference,
settings UX fixes (SMTP fields, Telegram Chat ID, Webhook URL removal).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 08:57:36 +05:00
00cbe9716b fix(settings): remove unimplemented Webhook URL field from notifications
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
The webhook_url field was stored in DB but never used to send
notifications — removing it from UI avoids misleading users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 08:53:40 +05:00
cc2bb349e5 fix(settings): notifications/profile form UX fixes
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 48s
Deploy to Production / Trigger production update (push) Successful in 8s
- Profile tab: add language selector (per-user), add toast on save/error
  for profile info and password change (clears fields only on success)
- Notifications: remove Chat ID field from admin Telegram section —
  it was never saved to DB and only served as a test-only input;
  testing is now done via "Мои уведомления" → Send test
- Add missing onSuccess/onError toasts to SMTP and Telegram save buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 08:47:37 +05:00
9ced08b88c feat(settings): per-user language preference and panel improvements
Store UI language per user (users.language column, migration 26).
Language selector moves from Panel tab to Profile tab — each account
picks its own language, saved to DB and applied via i18n.changeLanguage()
on save so the interface switches immediately.

Panel tab: panel_name read-only (falls back to env PANEL_NAME),
log_retention_days field exposed in UI, language selector removed.
Panel API accepts panel_name in PUT so it can be overridden in DB
without touching the env var.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 08:47:18 +05:00
4451b3e45a fix(settings): align SMTP/security settings fields with API
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 46s
Deploy to Production / Trigger production update (push) Successful in 8s
Rename SMTP request/response fields (host/port/username/password/from_email/tls)
and point security settings hooks at /admin/api/security/settings with a typed
SecuritySettings shape. Add minutes / security_saved i18n keys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 08:26:39 +05:00
a507e3c4bc feat(metrics): real-time VM disk fill, IOPS and network I/O
Add live per-disk usage, disk read/write and network in/out rates to the
instance Overview tab, the instances list and the dashboard top-loaded list.

Backend:
- get_vm_fsinfo() pulls per-filesystem usage via QEMU guest agent
- metrics_broadcaster computes I/O rates (bytes/sec) from cumulative counters
- instances-list loop now refreshes each running VM via status/current
  (1s-granular) instead of cluster/resources (10s pvestatd), with bounded
  concurrency, and paces both realtime loops to a 1s cadence

Frontend:
- OverviewTab: per-disk cards, Network I/O and I/O-rate cards via WS
- InstancesPage: Net and Disk I/O columns; Disk% shown for LXC only
- DashboardPage: top-loaded list overlaid with realtime metrics

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 08:26:29 +05:00
6fc617d3e5 fix(deploy scpirt): replace message text deploy procces address to 3001
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
2026-06-20 04:23:30 +05:00
965fb858da fix(ipam): require resource name before allocating IP and fill missing fields on VM link
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 46s
Deploy to Production / Trigger production update (push) Successful in 8s
- Validate resource name in auto-allocate form before sending request
- Fill resource_name, proxmox_node, resource_type, mac_address when syncing
  a VM that already has matching vmid/server_id but missing metadata

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 03:23:57 +05:00
7546883393 feat(dashboard): show top 10 loaded running instances by CPU
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 02:59:43 +05:00
4feb802c4f fix(ipam): filter unlinked allocations to VMs with IPs inside active IPAM networks
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 46s
Deploy to Production / Trigger production update (push) Successful in 8s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 02:53:50 +05:00
64924e50ed fix(instances): persist server filter selection across navigation and page reload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 02:53:45 +05:00
5b781f9e16 fix(ipam): show VM id/name/IP in IP map tooltip
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
The IP map tooltip read e.ip, but the backend ip-map endpoint returns
the address as ip_address, so the IP rendered as 'undefined'. Align the
IPAMIPMapEntry type with the backend response and build the tooltip from
proxmox_vmid, resource_name/hostname and ip_address.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:27:04 +05:00
14a6f5ace7 feat(ipam): expose network/pool/allocation management in UI
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 7s
Wire up backend IPAM endpoints that had no frontend:
- edit/delete network (with force) on network detail page
- full pool CRUD (create/edit/delete) on network detail page
- manual allocation create + edit on allocations page
- IP address map visualization per network

Add missing hooks (useCreatePool/useUpdatePool/useDeletePool,
useUpdateAllocation), force support in useDeleteNetwork, typed
ip-map entries, writable allocation fields, and RU/EN locale keys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:12:40 +05:00
e1951bafe1 fix(deploy): correct postgres volume name and generate FERNET_KEY
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
- check_stale_db_volume looked for <project>_postgres_data but the
  compose volume is <project>_db_data, so stale-volume detection and
  --reset-data silently did nothing; use the real name.
- Generate a Fernet key (url-safe base64 of 32 bytes) for backend/.env
  in all env-creation paths so sensitive fields are encrypted at rest
  instead of stored as plaintext.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:09:10 +05:00
58e73d4af4 fix(tests): repair Proxmox client mock after from_server refactor
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 46s
Deploy to Production / Trigger production update (push) Successful in 8s
The mock_proxmox fixture patched ProxmoxClient with return_value= (constructor
style), but since commit d66928e clients are built via the
ProxmoxClient.from_server classmethod. from_server() therefore returned an
unconfigured child mock, so endpoints serialized a MagicMock and responded 500
— failing 5 tests in test_api_vms.py on every CI run (Backend Tests workflow).

Wire .from_server.return_value (and .return_value) on all patched ProxmoxClient
references to the configured instance so every construction path resolves to
the same mock. Full suite now green (60 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:08:28 +05:00
d0badd0a2e refactor(rbac): drop runtime legacy-format resolution from engine
Roles are stored in the new resource:action format and any legacy keys are
converted once at startup by the RBAC v2 DB migration (migrate_rbac_v2), so
the permission engine no longer needs to resolve legacy codes on every check.

- get_user_permissions: store role permission codes as-is (no dual add).
- has_permission: match new-format codes only; drop resolve_permission and the
  dotted-code fallbacks.
- Remove now-unused resolve_permission import in middleware.
- LEGACY_PERMISSION_MAP / convert_* are retained as one-shot DB-migration
  utilities (upgrade path), not a runtime bridge.
- Tests: adapt fixtures to new-format role permissions; assert legacy keys are
  no longer honored at request time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:08:19 +05:00
de967c35e0 refactor(rbac): migrate API permission checks to resource:action format
Replace all legacy dotted permission codes (vms.view, proxmox.manage, ...)
in PermissionChecker/has_permission across app/api with the new
resource:action format (vm:view, server:manage, ...), per LEGACY_PERMISSION_MAP.
All 33 codes used by the API are now registered in the permission registry.

Also switch the /api/auth/me admin branch to get_all_permissions_v2 so the
endpoint emits permissions in the new format only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:07:48 +05:00
57513c4dc9 fix(rbac): register user:manage and vm:manage, close legacy map gaps
These permissions were referenced by the API (users.manage, proxmox.vm.manage)
but never registered in the permission registry, so they only worked through
the is_admin bypass — non-admin users granted them silently received 403.

- Register user:manage and vm:manage in the registry.
- Add missing legacy mappings: users.manage->user:manage,
  settings.manage->setting:manage.
- Grant both new permissions to the admin role (defaults + init.sql seed);
  ensure_default_roles_new_format propagates them to existing deployments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 02:07:36 +05:00
d66928ee78 refactor(proxmox): unify ProxmoxClient construction via from_server
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 48s
Deploy to Production / Trigger production update (push) Successful in 8s
Collapse four duplicated host+auth client-building blocks into a single
ProxmoxClient.from_server() classmethod (the canonical source of truth):

- _helpers._get_proxmox_client now delegates to from_server (107 callers
  untouched)
- ipam._build_proxmox_client removed; its one call site uses from_server
- task_queue_service keeps its per-server cache pool, builds via from_server
- monitoring_worker keeps its ValueError-on-missing-auth contract, builds
  via from_server

Behaviour preserved (token-first, then password; non-default port appended).
Verified: containers rebuild healthy, smoke test of both auth paths passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 22:30:57 +05:00
34fe9b4924 chore: ignore graphify-out/ and local preview config
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 15s
Also drop the stray markdown code fences that wrapped the file and were
being treated as literal ignore patterns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 22:21:07 +05:00
f18ba4d597 revert(nodes): remove server auto-setup feature
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 1m35s
Deploy to Production / Trigger production update (push) Successful in 8s
Drop the /api/servers/auto-setup endpoint, the AutoSetupDialog UI and the
useAutoSetupServer hook. Rename the auto_setup locale strings to
auto_create_token. Also normalize the storages response to an array.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 22:18:38 +05:00
493814f44f fix(dashboard): populate recent-activity feed from audit logs
Align the frontend with the /logs API contract: the endpoint returns
{ logs: [...] } with a created_at field, not { items: [...] } / timestamp.
Add a Vite dev-proxy rule for /logs so the request reaches the backend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 22:18:30 +05:00
ed4ff6576a feat(instances): show saved VM configuration on the Settings tab
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 10s
Read-only card on the instance Settings tab surfacing the panel-stored config
(cores/memory/disk/network/cloud-init) via the saved-config endpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:30:44 +05:00
bb5d30ab68 feat(nodes): add server auto-setup and cluster-info badge
Add an 'Auto-setup' dialog that onboards a Proxmox server by password and
lets the backend auto-create the API token (adds all nodes for a cluster).
Show a cluster/standalone badge with node count on the node detail page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:30:44 +05:00