Commit Graph

218 Commits

Author SHA1 Message Date
28fa6eb5b4 fix(instances): reset stale server/node filter on workspace switch
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 10s
Persisted instances-server-filter/instances-node-filter kept an old id
after switching workspace, emptying the list and showing the raw id in
the Select. Drop the filter to 'all' when the server/node is no longer
present in the active workspace.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:25:44 +05:00
7117c8adc3 feat(images): collapsible sections with persisted state
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 7s
Make 'Cloud-образы ВМ' and 'LXC-шаблоны' section headers clickable to
collapse/expand. State is saved to localStorage per section so it
survives reloads and navigation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:24:55 +05:00
845c8024c4 feat(auth): forgot/reset password pages and wiring
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 1m16s
Deploy to Production / Trigger production update (push) Successful in 8s
- ForgotPasswordPage and ResetPasswordPage in the split-screen auth layout.
- "Forgot password" link on the login page now routes to /forgot-password.
- Public routes /forgot-password and /reset-password; reset page validates
  the token on mount and gates the form, with show/hide password and
  confirmation matching.
- i18n keys (reset.*) for ru/en.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:24:19 +05:00
8b93161434 feat(auth): self-service password reset (forgot/reset endpoints)
Add an email-based "forgot password" flow:
- PasswordResetToken model (stores only a SHA-256 hash, single-use, TTL)
  and migration 27 for the password_reset_tokens table.
- POST /api/auth/forgot-password — generic response (no account
  enumeration), 60s throttle, emails a one-time reset link via the
  existing EmailChannel as a background task.
- GET /api/auth/reset-password/validate — token validity check for the UI.
- POST /api/auth/reset-password — validates the token, enforces the
  password policy, sets the new password, clears lock state, invalidates
  outstanding tokens and terminates all sessions.
- Configurable link lifetime via PASSWORD_RESET_TOKEN_EXPIRE_MINUTES (30m).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:24:19 +05:00
65e14585c5 chore(frontend): make vite dev runnable outside Docker
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Allow overriding the dep-optimizer cache dir via VITE_CACHE_DIR (the
default node_modules/.vite is root-owned when built in Docker) and honor
a PORT injected by the harness. Both default to prior behavior when the
env vars are unset, so Docker builds are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:05:18 +05:00
89962a7f20 feat(auth): split-screen login with geometric pattern
Redesign the login page into a two-column layout: a decorative
geometric line pattern on the left (hidden on mobile) and the form on
the right with the PVEmanager logo on top and a footer with a language
switcher + copyright. Add a password show/hide toggle and a "forgot
password" link. Login logic (username/password) is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:05:18 +05:00
0510c1739d docs(images): document cloud-image catalog; bump to v1.6.0
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
Add v1.6.0 CHANGELOG entries (EN/RU) for the Images module: cloud-image
catalog, auto-convert to VM template, custom mirrors, arch-aware filtering.
Add feature bullet to README (EN/RU) and a dedicated WIKI section + TOC entry.
Bump VERSION 1.5.2-1 -> 1.6.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 01:38:22 +05:00
f880c9e177 fix(images): idempotent download (skip if file exists) + real failure reason
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 52s
Deploy to Production / Trigger production update (push) Successful in 8s
Retrying a template build failed at download because the qcow2 from a prior
attempt already existed and download-url refuses to overwrite. Now skip the
download when the volume already exists (volume_exists), and surface the PVE
task-log tail on download failure instead of a generic message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 00:38:50 +05:00
cdb49abf0f fix(images): sanitize VM name for import; honest create-error message
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 55s
Deploy to Production / Trigger production update (push) Successful in 9s
create_vm_with_import got the display name ('Ubuntu 22.04 LTS (Jammy) Cloud')
which PVE rejects (Parameter verification failed on 'name'). Sanitize to a
DNS-safe name (e.g. ubuntu-22-04-lts-jammy-cloud). Also stop attributing every
create failure to 'import unsupported' — only say that when the error mentions
import; otherwise surface the real error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 00:31:34 +05:00
1e06be10ad fix(images): normalize import filename extension (.img -> .qcow2)
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 52s
Deploy to Production / Trigger production update (push) Successful in 8s
Proxmox content=import rejects Ubuntu cloud '*.img' with 'invalid filename
or wrong extension' though the format is qcow2. Rename non-import-extension
files to .qcow2 before download-url; import-from auto-detects the format.
Applied to both download and template workers (download filename + import volid).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:52:56 +05:00
03b574777c fix(images): default arch to node platform; fix node selector placeholder
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Successful in 55s
Deploy to Production / Trigger production update (push) Failing after 10s
- arch filter defaults to amd64 and auto-syncs to the selected node's arch
  (useNodeArch), so amd64 nodes no longer show arm64 images by default
- node Select no longer renders raw '__none__'; shows 'Нода' placeholder
  and a disabled hint when no nodes are reachable

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:28:04 +05:00
2dff9f8c5c feat(images): node-arch endpoint for arch-aware filtering
GET /proxmox/api/{server_id}/images/node-arch derives amd64/arm64 from
node status current-kernel.machine; returns null when node unreachable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:28:04 +05:00
d2f57e13db feat(images): Phase 3 UI — custom mirror manager (admin)
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Successful in 51s
Deploy to Production / Trigger production update (push) Failing after 10s
Admin-only MirrorsManager on ImagesPage: list/add/edit/delete custom
mirrors with kind/arch/url/template/checksum fields; mirror CRUD hooks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:17:00 +05:00
ed84e00e7b feat(images): Phase 3 backend — custom mirror CRUD
GET/POST/PUT/DELETE /proxmox/api/images/mirrors (perm template:manage).
Enabled mirrors merge into the catalog feed automatically.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:17:00 +05:00
ec8f4904a1 feat(images): Phase 2 UI — make-template toggle in download dialog
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Successful in 51s
Deploy to Production / Trigger production update (push) Failing after 11s
qcow2: 'make VM template' toggle (default on) with disk-storage picker,
cores/memory/bridge and cloud-init user/password fields; routes to
image_template task kind.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:11:20 +05:00
c7edf72d19 feat(images): Phase 2 — auto-convert qcow2 to VM template
- client.create_vm_with_import: API-only disk import via scsi0 import-from (PVE 8.2+)
- _do_image_template_sync worker: download(import) -> create+import -> cloud-init
  -> convert_to_template -> register OSTemplate (Cloud Images group)
- images download endpoint: to_template branch + cloud-init/disk_storage params
- clear fallback error when storage lacks import support (file kept)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:11:20 +05:00
32e06fe922 feat(images): frontend Images page, catalog hooks, download dialog
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Successful in 55s
Deploy to Production / Trigger production update (push) Failing after 11s
Phase 1 UI for VM image mirror feature:
- use-image-catalog hook (catalog, lxc repo templates, target storages, download)
- ImagesPage: server/node context, arch/search filters, cloud + LXC sections
- DownloadImageDialog: storage picker, background download via DeployTask
- CatalogImage/ImageMirror types, image_download/image_template task kinds
- sidebar nav 'Images' + /images route

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:57:16 +05:00
7aed5dd97e feat(images): backend catalog + mirror model + download API/worker
Phase 1 of VM image mirror feature:
- StorageMixin.download_url (PVE download-url/aria2) + get_download_target_storages
- builtin curated cloud-image catalog (Ubuntu/Debian/Rocky/Alma, amd64+arm64)
- ImageMirror model for admin custom mirrors
- /proxmox/api/images: catalog, lxc-templates proxy, storages, download
- _do_image_download_sync worker with log-tailing progress (DeployTask)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 22:51:21 +05:00
4d8cdc0143 Merge branch 'main' of https://github.com/markmorado/pvemanager
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 8s
2026-06-22 03:10:27 +05:00
6e67ad7e77 fix(disk-resize): keep growpart script ASCII-only
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Successful in 51s
Deploy to Production / Trigger production update (push) Has been cancelled
Proxmox's guest-agent exec (PVE/QemuServer/Agent.pm) dies with
"Wide character in subroutine entry" when input-data contains non-ASCII
bytes. The growpart script had Cyrillic comments, so the whole auto-grow
call returned 500 and the FS was never resized. Replace those comments
with ASCII so the script reaches the guest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 03:09:43 +05:00
Dilshod Rasulov
359b85310f Create SECURITY.md 2026-06-22 02:58:35 +05:00
f67ee24155 Merge branch 'feature/metrics-history'
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 50s
Deploy to Production / Trigger production update (push) Successful in 7s
2026-06-22 02:47:45 +05:00
9e9cac15e1 fix(disk-resize): pass node, real disk picker, shrink guard, grow output
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 49s
Deploy to Production / Trigger production update (push) Successful in 8s
Settings tab disk-resize UX:
- useResizeDisk/useUpdateConfig now send the required node query param,
  fixing the 422 "Field required" error.
- disk device is chosen from the VM's actual disks (defaults to the boot
  disk) instead of a hardcoded scsi0.
- show the current disk size, prefill it, and block shrinking before
  hitting Proxmox (which rejects it).
- render the growpart output and a grown/not-grown status after resize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 02:43:12 +05:00
38d485be4b fix(disk-resize): honest task status, auto-grow FS, CRLF-safe guest exec
Backend fixes for VM/LXC disk resize:
- resize_vm_disk/resize_container_disk now honor wait_for_task and raise
  the real Proxmox exitstatus (e.g. "disk 'scsi0' does not exist") instead
  of always returning success.
- add grow_vm_filesystem: after a VM resize, rescan the disk (retry loop,
  needed for SATA/SCSI), growpart the partition and resize the FS
  (ext*/xfs/btrfs) via the guest agent; surface its output to the API.
- execute_script normalizes CRLF/CR to LF so pasted scripts and growpart
  don't break on trailing \r ("partition-number must be a number").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 02:43:03 +05:00
1a17ceed82 fix(sync): store VM memory/disk in MB/GB, not raw Proxmox bytes
The monitoring worker wrote Proxmox maxmem/maxdisk (bytes) straight into
the memory/disk_size columns, which the rest of the app stores as MB/GB.
Every sync cycle clobbered correct values with bytes, so the saved-config
card showed huge byte numbers under MB/GB labels. Convert via new
_bytes_to_mb/_bytes_to_gb helpers; existing rows self-heal on next sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 02:42:49 +05:00
ddd37060fe fix(metrics): move disk-fill chart to the very end after IOPS
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 01:23:32 +05:00
7a5485c63c fix(metrics): reorder graph cards, per-chart hover cursor, readable dark tooltip
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 01:21:04 +05:00
0f7c5a44df fix(metrics): move disk-fill chart up next to CPU and memory
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:57:52 +05:00
e90ad2e0d2 fix(metrics): keep previous series on NIC/range switch to avoid full-grid reload
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:57:52 +05:00
af10009375 chore: ignore local superpowers specs/plans and SDD scratch
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:35:15 +05:00
074983a1f6 fix(metrics): correct cpu/disk% chart scaling, evict stale collector state, lighten nic query, drop polling & dead RRD code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 21:35:02 +05:00
4f224d90cf feat(metrics): graphs tab reads stored history with date range, NIC selector, IOPS & disk% 2026-06-21 21:35:02 +05:00
0aed32f998 feat(metrics): add useVMMetrics hook 2026-06-21 21:35:02 +05:00
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