Commit Graph

13 Commits

Author SHA1 Message Date
67fe01e9b1 fix: show friendly OS name for LXC deployed from CT template
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 1m26s
Deploy to Production / Trigger production update (push) Failing after 12s
SonarCloud / SonarCloud Analysis (push) Failing after 12m14s
Derive a human-readable OS name (e.g. Debian 13, Ubuntu 24.04) from the
vztmpl volid instead of showing the raw template path like
local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst in the instances list.
Applied at the display layer, so existing instances are fixed too.
2026-08-19 15:30:34 +05:00
1152410860 fix(instances): assign the owner on create and inject the owner's SSH keys
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 2m30s
Deploy to Production / Trigger production update (push) Failing after 10s
Newly created VMs/LXCs ended up with owner_id = NULL, and a VM created by an
admin on behalf of a user received the admin's SSH key instead of the user's.

Ownership: save_vm_instance() only set owner_id when inserting a new row. The
row practically always existed by then — sync_vm_cache runs every 10s and
registers VMs it sees on Proxmox with owner_id = NULL while the clone is still
running, whereas the deploy saves the owner minutes later at 95% progress. So
every deploy landed in the update branch and silently dropped the owner. Set
owner_id there too, but only when it is passed explicitly: callers such as
save-before-delete do not know the owner and must not blank it out.

SSH keys: the profile key was taken from whoever pressed "Create" rather than
from the instance owner, and the LXC path injected no profile key at all. Add
build_deploy_ssh_keys(), which merges pasted keys, keys picked from the library
(same authorization rules as before) and the owner's profile key, deduplicated.
Both the template and LXC deploy endpoints now use it, so the key material is
resolved in one place instead of inside the deploy worker.

ISO VMs are left alone on purpose: they are blank VMs without cloud-init, so
there is nowhere to inject keys.

Covered by backend/tests/test_instance_ownership.py, including the sync race.
2026-08-11 17:19:19 +05:00
markmorado
ff1396142b fix(api): scope server listings to workspace, stop serialising Proxmox calls
/api/cluster/topology and /api/resources/all read every ProxmoxServer row
regardless of the caller access or the X-Active-Workspace header, so the
Cluster page listed all servers and dashboard aggregates counted the whole
panel instead of the active workspace. Extract the access + workspace filter
out of /api/servers into get_visible_server_ids() and apply it in all three.

Live metrics were also gathered server by server with the cache lock held
across the network calls, so a single unreachable cluster stalled the request
(21-31s in the logs) and concurrent requests queued behind it. Fetch in
parallel, skip servers already known offline, drop the redundant
is_connected() probe, and hold the lock only around the cache dict.

/api/resources/all now orders by server id: without it Postgres returned heap
order, which shifts whenever update_status rewrites a row, so the server list
reshuffled between requests.
2026-07-24 03:18:14 +05:00
markmorado
42c6acd52e fix(instances): изоляция по владельцу для живых ресурсов Proxmox
Some checks failed
Deploy to Production / Trigger production update (push) Has been cancelled
Backend Tests / pytest (Python 3.12) (push) Has been cancelled
Список инстансов (/api/virtual-machines) уже фильтровался по owner_id, но
эндпоинты живых ресурсов Proxmox — /api/resources/all (дашборд) и
/api/{server_id}/resources (страница ноды/сервера) — отдавали все VM/LXC без
фильтра. Обычный пользователь (proxmox.view) через страницу ноды видел чужие
инстансы.

- _helpers: get_owned_vmids() — VMID, которыми владеет пользователь
- servers: get_server_resources / get_all_resources фильтруют VM/LXC по
  владельцу для не-привилегированных (сверка vmid с кэшем vm_instances);
  админы и роли с vm:manage видят всё
- assign_instances_owner.py: скрипт массового назначения владельца
  существующим инстансам (owner_id синхронизированных из Proxmox = NULL)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 04:56:17 +05:00
markmorado
6a79dd2048 fix(appstore): DNS, per-server golden template, bind-mount perms, delete race
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 1m1s
Deploy to Production / Trigger production update (push) Successful in 8s
App Store install/update pipeline reliability fixes:
- explicit nameserver (APPSTORE_NAMESERVER) on App Store LXCs and the golden
  template build CT, instead of inheriting a node resolver that may be
  unreachable from the container network (e.g. Tailscale-only DNS)
- golden template storage/resolution moved from one global setting to
  per-server_id (migration 37: app_operations.server_id) — building it on one
  Proxmox server no longer overwrites the template configured for another
- golden template automated build fixed: vzdump export step no longer fails
  on "unable to parse directory volume name 'vztmpl/probe'"
- bind-mount host directories are pre-created with permissive ownership
  before `docker compose up`, fixing Permission denied for non-root
  containers (e.g. MariaDB) writing to Docker-auto-created root-owned dirs
- delete/teardown now waits for Proxmox to actually confirm the destroy task
  finished (was silently proceeding after a short timeout, letting a new
  install reuse the VMID while the node was still wiping the old disk)
- pct create retries a few times on transient "got lock" config errors
- failed pipeline steps now report the tail of command output (4000 chars)
  instead of the head, so the real error isn't buried under pull/progress noise
- install error box in the UI wraps long text and scrolls instead of
  stretching the dialog

Also carries forward in-progress script catalog / instances / RBAC changes
that were already uncommitted in the working tree before this session.

Bump to v1.9.1, update WIKI.md/docs/CHANGELOG accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 04:49:40 +05:00
markmorado
db2f408d57 fix(core): пункты 5-10 аудита — UPID-синк, порт, бэкап all, IPAM, креды
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 56s
Deploy to Production / Trigger production update (push) Successful in 8s
5. UPID-синк: транзитная ошибка опроса статуса больше не помечает живую
   задачу failed — get_task_status(raise_on_error=True) + счётчик из 3
   последовательных неудач; в exit_status пишется реальная причина.
6. Дашборд и бэкапы для серверов на порту != 8006: metrics_broadcaster и
   backup_scheduler строят клиент через ProxmoxClient.from_server (учёт
   порта и token/password) вместо ручной сборки по ip_address.
7. Бэкап "все VM": create_backup при vmid in (None, 0, "all") передаёт
   vzdump параметр all=1 — раньше уходил vmid=0 и PVE отвергал задание.
8. IPAM: get_next_available_ip собирает занятые IP глобально (как проверяет
   allocate_ip), а не только по pool_id — авто-выдача больше не предлагает
   занятый адрес и не срывает создание инстанса.
9. IPAM: fallback в release_ip_by_vmid ищет только записи без
   proxmox_server_id — удаление VM не освобождает IP одноимённого vmid
   на другом сервере.
10. _get_proxmox_client: сервер без валидных кредов теперь возвращает
    понятную 503-ошибку вместо молчаливо пустых списков; перечисление
    серверов в метриках защищено per-server try/except.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 01:06:28 +05:00
35dcbfd18f feat(quotas): per-user resource limits for VM/LXC deployment
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 54s
Deploy to Production / Trigger production update (push) Successful in 8s
Add per-user quotas (max instances, vCPU, RAM, disk) enforced at deploy
time and surfaced to users self-service.

Backend:
- UserQuota model (one-to-one, NULL = unlimited) + migration #28
- quota_service: usage from vm_instances cache, check_quota raises 429
- enforce in VM (templates.py) and LXC (lxc.py) deploy paths
- RBAC quota:view / quota:manage, granted to admin
- admin API GET/PUT /admin/api/users/{id}/quota
- self-service GET /settings/api/quota
- tighten VM list isolation via can_view_all_instances

Frontend:
- admin quota dialog in UsersPage with usage bars
- quota card on Settings page (own limits)
- remaining-quota hint in CreateInstanceWizard config step
- useUserQuota/useSetUserQuota, useMyQuota hooks; RU/EN locales

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:15:02 +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
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
bfd92102cf Refactor backend: Split models and proxmox_client into modules, add alembic
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 2m27s
2026-06-13 03:53:27 +05:00
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
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
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