Commit Graph

88 Commits

Author SHA1 Message Date
markmorado
1d08c815a7 fix: frontend-backend integration — 14 issues resolved
- nginx: add proxy routes for /settings/, /templates/, /ipam/, /logs/, /admin/, /health
- dashboard: fix data format mismatch (servers[] not nodes[]/vms[])
- dashboard: add WebSocket subscription to dashboard_metrics for real-time updates
- dashboard: connect activity feed to /logs/api/logs endpoint
- dashboard: reduce polling to 15s with WS as primary update source
- graphs: fix rrddata response unwrap (backend returns {data:[],timeframe:''})
- graphs: add i18n translations for chart titles
- console: add xterm.js CSS import for proper terminal rendering
- console: add i18n translations (connecting, reconnect)
- workspace: add switcher dropdown in TopBar
- workspace: add edit dialog in WorkspacesPage
- workspace: create Zustand store with localStorage persistence
- workspace: add X-Active-Workspace header to API client
- sidebar: replace generic icon with actual favicon.svg logo
- instances: translate RowActionMenu and InstanceDetailPage strings
- locales: add graphs, console, workspace, instance tab keys to en/ru
2026-04-07 00:46:04 +02:00
markmorado
4546a798d0 v1.4.0: Networks page — SDN zone/vnet editing, node interfaces CRUD, IPAM auto-create 2026-04-06 21:13:38 +02:00
markmorado
6a0564cea2 v1.3.1: VM list node/server filtering + responsive toolbar redesign
- Add server filter dropdown (populated dynamically from loaded VMs)
- Add node filter dropdown (narrows to nodes of selected server)
- Both filters persisted in URL params and restored on reload
- Toolbar restructured into 2 rows: filters row + actions row
- Responsive breakpoints: ≤900px text labels hidden, ≤768px 2-per-row,
  ≤480px full-width filters, stats hidden on mobile
- Snapshots toolbar migrated to inline flex (no legacy class dependency)
- Update VERSION, CHANGELOG, README, WIKI to v1.3.1
2026-04-05 21:47:16 +02:00
markmorado
abeb8d53a3 chore: release v1.3.0
- VERSION: 1.2.0 → 1.3.0
- CHANGELOG: add v1.3.0 section (VNC & Terminal fixes)
- README: update version badge to 1.3.0
- WIKI: bump version header, expand Console section (VNC/xterm.js),
  update VNC troubleshooting section
2026-03-27 21:36:21 +01:00
markmorado
29f1255705 feat: use xterm.js terminal for LXC containers in VM list context menu
- Context menu now shows Terminal (xterm.js) for lxc type and VNC Console for qemu
- Added openTerminalConsole() / connectTerminalConsole() / closeTerminalModal() functions
- Added terminalModal HTML alongside existing vncModal
- Backend endpoints /api/{server_id}/container/{vmid}/terminal and
  /proxmox/ws/terminal/{server_id}/{node}/{vmid} already existed and are ready
2026-03-27 21:22:27 +01:00
markmorado
32acd74b38 fix: LXC vncproxy - generate-password unsupported, use ticket as VNCAuth password 2026-03-27 21:10:49 +01:00
markmorado
c189dab5e9 fix: VNC auth - add generate-password:1 to vncproxy, fallback to ticket
Root cause of 'Connection closed' / VNCAuth failure:
- vncproxy was called without generate-password=1
- vnc_data.password was None → noVNC sent empty DES-encrypted challenge → Proxmox rejected

Fix:
- Add generate-password=1 to both qemu and lxc vncproxy requests
- If Proxmox returns password field (Proxmox 8.x VNCAuth): use it
- If not (Proxmox 9.x NoAuth): fall back to ticket as password
- Add diagnostic logging (password_len, has_generate_password)
2026-03-27 21:08:40 +01:00
markmorado
cd48c839f8 fix: VNC - pass URL directly to noVNC instead of existing WebSocket
Remove the 'onFirstMessage' hack where backend sent VNC password as
first text WebSocket message and frontend passed the already-open WS
to noVNC's RFBClass. This caused RFB handshake failures because noVNC
couldn't properly manage a WebSocket it didn't create.

Changes:
- Backend: remove send_text(password) before proxy start
- Backend: improve proxy error logging from debug to info level
- Frontend (virtual_machines.html, instance_detail.html): pass WebSocket
  URL string to RFBClass constructor - noVNC creates and manages its own
  WebSocket connection, allowing proper RFB protocol handshake
2026-03-27 20:57:04 +01:00
markmorado
06ea2b5bd4 fix: add keep_last param to backup API and fix notes-template field name 2026-03-22 20:07:50 +01:00
markmorado
4ef79112be fix: wait for Proxmox resize task before VM start (v1.2.0)
- configure_vm: capture resize UPID and call wait_for_task(120s)
  before returning; prevents lock conflict when VM is started right
  after disk resize
- resize_vm_disk / resize_container_disk (x2): same fix applied
- remove unnecessary restart_vm() after manual QEMU disk resize —
  resize is a storage-layer operation and does not require a reboot;
  the auto-restart was causing a second lock conflict

Fixes: can't lock file '/var/lock/qemu-server/lock-xxx.conf' - got timeout
Fixes: command '/usr/bin/qemu-img resize' failed: got timeout
2026-03-16 20:23:06 +01:00
markmorado
bd1777f67b fix: always send first VNC password message (empty for NoAuth in Proxmox 9.x) 2026-03-16 18:42:07 +01:00
markmorado
7940efc958 fix: remove generate-password from vncproxy (not supported in Proxmox 9.x) 2026-03-16 18:31:58 +01:00
markmorado
57575d58ce feat: v1.1.8 — user-server assignment, VM/LXC ownership, smart login redirect, RBAC migrations
- Migration 20: user_servers association table (User ↔ ProxmoxServer)
- API: GET/PUT /api/users/{id}/servers — assign servers to users with workspace-conflict validation
- API: GET /api/users/{id}/server-assignments — enriched server list (assigned + compatible flags)
- Non-admin server filter: intersection of assigned_servers and workspace servers
- Migration 21: dashboard:view = false for user role (new key format)
- Migration 22: proxmox.cluster.manage → cluster:manage for admin role
- API: GET/PUT /api/{server_id}/vm/{vmid}/owner — VM/LXC owner assignment (admin-only)
- Login: smart redirect based on user permissions after authentication
- Login: returnUrl param support for post-login redirect
- Roles API: user_count field per role in GET /api/roles
- node_uptime added to server detail API response
- Remove redundant PermissionChecker from GET /users HTML route
2026-03-16 08:27:36 +01:00
markmorado
c09c0c5b63 refactor(i18n): move translations to JSON locale files
- Extract 1149 translation keys from i18n.py into locales/ru.json and locales/en.json
- Rewrite i18n.py as a lightweight JSON loader (5287 → 128 lines)
- Add I18nService.reload() for runtime hot-reload without restart
- Add I18nService.available_languages() to list loaded language codes
- Public API unchanged: t(), get(), get_all(), add_translation()
- New languages require only a new *.json file in locales/ — no code changes

Bump version: 1.1.6 → 1.1.7
2026-03-16 04:08:28 +01:00
markmorado
4940cbe77f v1.1.6: fix LXC xterm.js terminal (termproxy auth handshake)
- Add mandatory Proxmox termproxy auth: send 'USERNAME:VNCTICKET\n' as
  first WebSocket message, wait for 'OK' before starting PTY proxy
- Fix server.username → server.api_user (token suffix stripped)
- Fix CSRFPreventionToken sent in body → header only
- Fix additional_headers → extra_headers (websockets v12)
- Add URL-encoding for vncticket, PVEAuthCookie WS header, subprotocols=['binary']
- Forward initial terminal data arriving with OK frame
- Bump VERSION 1.1.5 → 1.1.6
2026-03-16 03:07:14 +01:00
markmorado
5a67981f9a feat: v1.1.5 — UPID task tracking, Task Drawer clear button, auto-expire, pve CLI fix 2026-03-15 20:34:17 +01:00
markmorado
284c3dfce0 feat: redesign UI to Hetzner Cloud style with light theme 2026-03-15 03:25:15 +01:00
markmorado
ed7f1f779e feat: real-time WebSocket metrics broadcaster and UI updates
- New metrics_broadcaster service (410 lines) — background broadcaster
  pushing CPU/RAM/disk/network stats to subscribed WebSocket clients
- WebSocket protocol extended: subscribe/unsubscribe channels,
  get_rrd/get_node_rrd requests with request_id
- main.py: metrics broadcaster started in lifespan, WS message dispatcher
- websocket_manager.py: subscription map support
- templates: dashboard, instance_detail, proxmox_server_detail,
  proxmox_vms, workspaces — real-time charts and UI updates
- auth.py, servers.py, settings.py: minor fixes
2026-03-15 02:49:38 +01:00
markmorado
c4778d2972 chore: bump version to 1.1.4 — Workspaces feature 2026-03-15 02:38:15 +01:00
markmorado
bef0bcc542 feat: add Workspace feature — scoped server groups with user access and sidebar selector 2026-03-15 01:00:24 +01:00
markmorado
85cc0ce76d fix: correct PermissionChecker import in dashboard.py 2026-03-10 20:05:11 +01:00
markmorado
3947dae7b9 feat: v1.1.3 — dashboard alerts panel, sparkline charts, log sanitisation, CSS vars 2026-03-10 14:10:00 +01:00
markmorado
a0a502f82a ui: replace native browser dialogs with custom panel modals
- settings.html: confirm() → showConfirm(), prompt() → showPrompt() for update, SMTP test, Telegram test
- backups.html: confirm() → showDeleteConfirm() for backup/storage/job deletion
2026-03-08 20:42:08 +01:00
markmorado
d788ac78c3 feat: v1.1.2 — dashboard redesign, pve CLI tool, sidebar cluster selector 2026-03-08 20:35:43 +01:00
markmorado
b8c6e52c9a fix(update): host-side watchdog replaces in-container rebuild
Root cause: docker compose down killed the nohup script inside the
container before rebuild could complete — only git pull was visible
(updated VERSION file).

Changes:
- update_host.sh: new host-side watchdog (poll .update_trigger every 3s)
  runs: git pull → docker compose down → build --no-cache app → up -d
  PROJECT_DIR and User are dynamic (set at install time, not hardcoded)
- update_service.py: perform_update() now writes .update_trigger instead
  of running git/docker commands inside the container
- deploy.sh: added install_update_watchdog() + --watchdog CLI option;
  generates /etc/systemd/system/pvemanager-update.service dynamically
  with correct User= and WorkingDirectory= for any install path/user
- .gitignore: ignore .update_trigger and generated systemd/ files
- CHANGELOG, VERSION, WIKI: bump to v1.1.1, document new update flow
2026-03-08 19:02:40 +01:00
markmorado
b3db346cfb feat: v1.1.0 — backup module, IPAM node binding, HA, task queue, theme CSS
- Backup module: full CRUD for storages, backup files, scheduled jobs (APScheduler)
- Proxmox client: storage/backup/restore/HA methods
- IPAM: proxmox_node field, server+node binding for networks and allocations
- Task queue service: improvements and new task types
- Monitoring worker: extended metrics and alerts
- HA support: add/remove VMs from Proxmox HA groups
- tasks.html: new task tracking page
- proxmox_vms.html: major UI update (bulk ops, HA, snapshots)
- backups.html: full backup management UI (3 tabs)
- base.html: sidebar backup link, websocket manager
- theme.css: full CSS variables theme, 395 lines added
- migrations: migration #15 (BackupJob), #16 (proxmox_node)
- RBAC: backup resource permissions
- websocket_manager.py: new module for WS connections
2026-03-08 18:29:29 +01:00
markmorado
2c8becc6d4 chore: bump version to 1.1.0
- Backup module with PBS support, APScheduler, storage management
- IPAM: server/node subnet binding, link-allocations modal
- Fix: update system rebuilds Docker image after git pull
- Theme: replace hardcoded colors with CSS variables
- i18n: Uzbek keys for IPAM node selector
2026-03-08 18:27:47 +01:00
markmorado
f1d82ff7ea docs: update WIKI.md to v1.0.5 — IPAM server/node binding, Uzbek locale note 2026-03-08 18:24:56 +01:00
markmorado
91dbf0b81c feat: IPAM improvements - server/node subnet binding, theme color fixes
- IPAM link-allocations: filter networks by proxmox_server_id and proxmox_node
  to prevent cross-server/cross-node IP assignment
- IPAM link-allocations: add manual server+network selection modal before linking
- IPAM add-network forms: add Proxmox server and node selectors with dynamic
  cluster-info loading (ipam_dashboard.html, ipam_networks.html)
- models.py / schemas.py: add proxmox_node field to IPAMNetwork
- migrations: migration #16 adds proxmox_node column to ipam_networks table
- Theme fixes: replace all hardcoded rgba/color:#fff/color:white with CSS vars
  across base.html, virtual_machines.html, instance_detail.html,
  os_templates.html, proxmox_vms.html, ipam_network_detail.html,
  ipam_allocations.html
- i18n: add proxmox_node, node selector, link-allocations modal keys (ru/en)
- Version bump: 1.0.4 -> 1.0.5
2026-03-08 14:17:54 +01:00
markmorado
4bbc02982a fix: update system now rebuilds docker image after git pull
- Add docker-compose package to Dockerfile (was missing, caused silent failure)
- Auto-detect current git branch instead of hardcoding 'main'
- Auto-select compose command (docker compose / docker-compose)
- Write update logs to persistent /app/logs/update.log volume
- Log git pull stdout/stderr for diagnostics
2026-03-08 13:04:02 +01:00
markmorado
835606a0f7 feat: add backup storage module with scheduler, PBS support and icon fixes
- Add BackupJob model and migration 15
- Add RBAC permissions for backup resources
- Add ProxmoxClient storage/backup methods (list, create, restore, delete)
- Add /proxmox/api/backups/* API endpoints
- Add APScheduler-based backup job scheduler service
- Add backups.html template with 3 tabs (backups, storages, jobs)
- Add sidebar navigation link for backups page
- Fix backup page icons (replace SVG with Font Awesome)
- Bump version to 1.0.4
2026-03-08 12:53:26 +01:00
markmorado
8395ccdfde fix: show server IP and admin credentials in deployment output 2026-03-08 12:43:49 +01:00
markmorado
a3abf58453 Update repository URL to git.tzim.uz/markmorado/pvemanager 2026-03-08 12:31:42 +01:00
markmorado
65a71a5742 fix: make backend/.env optional in compose.yml to fix first-run error on clean servers 2026-03-08 12:22:38 +01:00
markmorado
85aa59e7b6 Add favicon, backup scheduler, backup API and templates, RBAC and migration updates 2026-03-08 11:40:41 +01:00
markmorado
7a77ffbd2b fix: use semantic version comparison for update check
String comparison caused local 1.0.3 to show "update available"
when GitHub had 1.0.2, since "1.0.3" != "1.0.2".

Added _is_newer() with proper semver tuple comparison so update_available
is only set when the remote version is strictly greater than local.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:59:39 +01:00
markmorado
7833df3c39 chore: bump version to 1.0.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:56:08 +01:00
markmorado
3d9d1bb2e0 fix: correct repo URL fallback and HTTP error reporting in update service
- Replace hardcoded legacy Gitea URL in settings.py fallback
- Skip legacy Gitea URL even if saved in DB (treat as unset)
- Track last_response in branch loop so errors report the real HTTP
  status code instead of always showing "HTTP unknown"
- Unify 401/403/404 into one "private or not accessible" message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:52:17 +01:00
markmorado
93d60b47e3 fix: correct default repository URL in update service
The fallback repo URL was pointing to the old Gitea instance
(git.tzim.uz/dilshod/pve_manager), causing "Failed to fetch VERSION
file: HTTP unknown" because both main/master branches returned non-200.

Updated to the current GitHub repository.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:47:17 +01:00
markmorado
eea3534e30 chore: bump version to 1.0.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:42:20 +01:00
markmorado
c07d9e8711 fix: deduplicate dashboard node charts by cluster, not just by node name
Previously seenNodes used only the node name as the dedup key, causing
independent servers that happen to share a default node name (e.g. "pve")
to hide each other's charts.

Fix: /api/{server_id}/nodes now also returns cluster_id — the actual
Proxmox cluster name for clustered servers, or "standalone-{server_id}"
for single-node servers. The dashboard deduplicates by
"cluster_id::node_name", so:
- nodes in the same cluster → deduped correctly (shown once)
- nodes on independent servers with the same name → both shown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:37:18 +01:00
markmorado
84015ce0bd fix: make auto-import synchronous, return templates list
The /api/auto-import/{server_id} endpoint ran as a background task
and returned {status: "queued"} with no templates field, while the
frontend's executeAutoImport() immediately called data.templates.forEach()
— causing TypeError: can't access property "forEach", data.templates
is undefined.

Replaced the background task with a synchronous handler that imports
templates in-request and returns {templates: [...], imported_count: N},
matching what the frontend expects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:25:35 +01:00
markmorado
a5059555e9 chore: bump version to 1.0.1, update README
- VERSION: 1.0.0 → 1.0.1 (patch — bug fixes only)
- README: full rewrite with modern formatting, accurate badges,
  real GitHub URLs, complete feature list and tech stack table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:09:59 +01:00
markmorado
8c5a896683 fix: correct relative imports in proxmox subpackage and CSP headers
- Fix all `from ..` → `from ...` in app/api/proxmox/*.py after the
  proxmox.py split (PR #6) placed modules one level deeper, causing
  ModuleNotFoundError on startup
- Broaden Content-Security-Policy to allow CDN sources used in templates:
  cdnjs.cloudflare.com (Font Awesome), cdn.jsdelivr.net (Bootstrap,
  Chart.js, xterm), fonts.googleapis.com/gstatic.com (Google Fonts),
  esm.sh (noVNC) — the overly-strict CSP was blocking all icons and
  charts from loading in the browser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 01:56:08 +01:00
Dilshod Rasulov
a2b53a1b84 Merge pull request #7 from markmorado/claude/code-review-audit-cxCWB
fix: repair two runtime bugs missed in Q2/Q3
2026-03-07 23:40:37 +05:00
Claude
7c42de11a3 fix: repair two runtime bugs missed in Q2/Q3
- proxmox/__init__.py: re-export get_next_vmid, save_vm_instance,
  get_vm_instance so templates.py import doesn't raise ImportError
  (regression introduced in Q3 split)
- ipam.py:791: remove erroneous await on non-async get_orphan_allocations()
  (missed in Q2 async cleanup)

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 18:29:33 +00:00
Dilshod Rasulov
02b607d424 Merge pull request #6 from markmorado/claude/code-review-audit-cxCWB
Claude/code review audit cx cwb
2026-03-07 22:39:45 +05:00
Claude
6fb7406d27 refactor: split proxmox.py (4676 lines) into package with 7 modules
- _helpers.py: shared helpers (check_vm_access, _get_proxmox_client, etc.)
- servers.py: HTML pages, server CRUD, resources, node status (16 routes)
- sdn.py: SDN zones/vnets/subnets (10 routes)
- snapshots.py: VM/container snapshots + archives (10 routes)
- vms.py: VM/LXC control, HA, monitoring, VNC, terminal, bulk ops (42 routes)
- tasks.py: Proxmox task management (6 routes)
- __init__.py: re-exports unified router (84 routes total, no public API change)

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 17:35:17 +00:00
Claude
7bd2dd5b8f refactor: remove spurious async defs in ipam.py, deduplicate ProxmoxClient instantiation
- api/ipam.py: convert 30 async def handlers that had no await to plain def,
  letting FastAPI run them in its thread pool (correct for sync SQLAlchemy I/O);
  cleanup_orphan_allocations kept async (it has await)
- api/proxmox.py: add _get_proxmox_client(server) helper that encapsulates the
  use_password/token branching, replace 58 duplicated 10-line blocks with a
  single call; get_proxmox_resources() call sites left unchanged (different sig)

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 11:57:44 +00:00
Dilshod Rasulov
1aa0819883 Merge pull request #5 from markmorado/claude/code-review-audit-cxCWB
perf: async Proxmox API, optimized IPAM queries, log cleanup scheduli…
2026-03-07 16:49:50 +05:00