Commit Graph

18 Commits

Author SHA1 Message Date
7fcb5eb7c6 fix(reinstall): stop double-converting already-scaled memory/disk_size units
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 1m44s
Deploy to Production / Trigger production update (push) Failing after 10s
SonarCloud / SonarCloud Analysis (push) Failing after 2m45s
VMInstance.memory is stored in MB and disk_size in GB (see _bytes_to_mb/
_bytes_to_gb in monitoring_worker.py), but the reinstall worker divided
them again by 1024*1024 / 1024**3 as if they were raw bytes. Both
computations collapsed to 0, so the post-clone "re-apply config" and
"restore disk size" steps silently no-op'd - reinstalled VMs/containers
ended up with the template's own memory and disk size instead of the
instance's previous values.
2026-08-25 09:32:11 +05:00
42871ee64f fix(reinstall): stop reinstall from wiping template link on delete attempt, support ISO-based QEMU reinstall
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 1m44s
Deploy to Production / Trigger production update (push) Failing after 10s
SonarCloud / SonarCloud Analysis (push) Failing after 3m0s
VM delete pre-save was calling save_vm_instance() without template_id/
template_name, which unconditionally overwrites those fields on the
existing cached row - so any non-force delete attempt (even one that
later failed) permanently detached the VM from its source template and
broke reinstall. Now the previous values are carried through.

Also extend reinstall eligibility and the reinstall worker to cover
QEMU VMs created via "Create VM from ISO" (template_name holds the ISO
volid, same storage:content/file pattern already handled for LXC CT
templates), recreating the VM from the same ISO on reinstall.
2026-08-25 09:17:35 +05:00
8ff757f8c1 fix: re-download cached import images when checksum is provided
Some checks failed
Deploy to Production / Trigger production update (push) Has been cancelled
Backend Tests / pytest (Python 3.12) (push) Has been cancelled
volume_exists() only checked file presence, not content. A stale image
from a previous download (different URL/version) would be silently reused,
causing templates and VMs to be created from unpatched images even when
the mirror's checksum pointed to a newer patched build.

Add delete_volume() to ProxmoxClient storage mixin, and update both
_do_image_download_sync and _do_image_template_sync to delete the cached
volume and re-download whenever a checksum is provided, letting Proxmox
verify the new download server-side.
2026-08-14 16:19:41 +05:00
markmorado
99d8ce750d feat(images): support uploading local ISO/vztmpl files to node storage
Some checks failed
Deploy to Production / Trigger production update (push) Has been cancelled
Backend Tests / pytest (Python 3.12) (push) Has been cancelled
Adds a local file upload path alongside the existing URL download flow:
a new /images/upload endpoint streams the file to a temp path and hands
it to a background worker that proxies it into Proxmox storage via the
upload API (requests-toolbelt handles the large multipart stream). Also
adds /images/resolve-filename to recover the real filename (Content-
Disposition) for URL-based downloads with opaque paths.

Raise nginx client_max_body_size and timeouts on both the frontend proxy
and the standalone nginx configs so multi-GB ISOs don't get cut off.
2026-07-24 06:17:46 +05:00
markmorado
ebc692a324 feat(instances): create blank VMs for ISO installs and download ISOs
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Has been cancelled
Deploy to Production / Trigger production update (push) Has been cancelled
Add a third instance kind to the create wizard: a blank KVM VM with an
empty disk, the installation ISO mounted on ide2 and put first in the
boot order, so the guest boots straight into the installer over noVNC.
Picking a Windows guest presets OVMF, a SATA disk and an e1000 NIC,
which the installer sees without virtio drivers loaded.

Also teach the image downloader content=iso, so ISOs can be fetched
onto a node from the panel: by URL from the images page or from a saved
mirror (mirrors now accept kind=iso), and straight from the ISO step of
the wizard.

The bundled catalog stays qcow2-only on purpose — install ISOs have no
stable "latest" URLs, so hardcoded links would rot on every point release.
2026-07-24 05:00:51 +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
c12fbf13e5 feat(instances): add VM/LXC migration, autostart/boot order, protection
All checks were successful
Backend Tests / pytest (Python 3.12) (push) Successful in 52s
Deploy to Production / Trigger production update (push) Successful in 7s
- Migrate VMs/LXCs between cluster nodes with live progress tracking
- Configure autostart, boot order, startup/shutdown delays, and delete protection from the instance settings tab
- Group OS templates by detected OS (Ubuntu, AlmaLinux, etc.) instead of a single "Cloud Images" bucket
- Expand native Proxmox backup job management (schedule, compression, retention, guest selection, notifications)
- Add ru/en translations for the above
2026-07-03 02:40:58 +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
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
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
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
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
9da65a46aa fix(lxc): preserve credentials and IP across reinstall
Three related fixes so login/password/SSH key/IP survive a reinstall:

1. backend/app/api/proxmox/lxc.py — on initial LXC deploy save
   cloud_init_user='root' and cloud_init_password=req.password to VMInstance
   (previously both were None, so reinstall could not restore root password).

2. backend/app/api/proxmox/async_ops.py — _do_reinstall_sync passes
   cached.cloud_init_password to create_lxc_container so the new container
   gets the same root password as the original.

3. backend/app/workers/monitoring_worker.py — VM sync worker no longer
   overwrites VMInstance.ip_address with NULL when no IPAM allocation
   exists for that (server_id, vmid). It only updates the field when
   IPAM has a value, otherwise the IP saved at deploy/wizard time is
   preserved.
2026-05-06 20:22:50 +02:00
markmorado
aba2eb3583 feat(lxc): support reinstall for LXC created from CT template file
Previously the reinstall endpoint required cached.template_id (clone-from-VM-
template flow), so LXC instances created via the wizard from an OS template
file (e.g. local:vztmpl/debian-13-...tar.zst) returned 'VM has no associated
template; reinstall is not available'.

Now reinstall works in two modes:
  1) clone-from-template (existing): VM/LXC with cached.template_id pointing
     to OSTemplate.vmid
  2) ostemplate-file (new, LXC only): cached.template_name like
     'storage:vztmpl/...tar.zst'. Reinstall stops, deletes, then re-creates
     the container with the same VMID using create_lxc_container, preserving
     network config, storage, rootfs size, swap, features, ssh_keys, etc.
     pulled from the previous container config + VMInstance cache.
2026-05-06 20:11:05 +02:00
markmorado
adcc86f30a fix: исправления и улучшения от 30.04.2026
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Has been cancelled
- Обновлён backend/Dockerfile и frontend/Dockerfile
- Исправлен async_ops.py (новые асинхронные операции)
- Обновлён config.py
- Исправлены compose.yml и compose.prod.yml
- Обновлён deploy.sh
- Переименованы nginx-конфиги (serverpanel → pvemanager)
- Улучшены InstanceActionDialogs, InstanceDetailPage, InstancesPage
- Обновлён AppLayout.tsx
- Исправлен init.sql
- Обновлён frontend/nginx.conf и package.json
2026-04-30 21:58:44 +02:00
markmorado
79d6864d43 feat(vm-ops): make reinstall/clone/change-password async via DeployTask
Backend:
- Add DeployTask.kind column ('deploy'|'reinstall'|'clone'|'change_password')
  + Migration 23: ALTER TABLE deploy_tasks ADD kind, drop NOT NULL on template_id
- Update DeployTask.to_dict() with kind-aware Russian descriptions
- New backend/app/api/proxmox/async_ops.py with three workers:
    _do_reinstall_sync, _do_clone_sync, _do_change_password_sync
  All run on shared _deploy_executor thread pool from templates.py and
  report progress through _update_deploy_task (DB + WebSocket broadcast)
- Rewrite five vms.py endpoints to return 202 + DeployTaskStartResponse:
    POST /vm/{vmid}/clone, /container/{vmid}/clone,
    POST /vm/{vmid}/reinstall,
    POST /vm/{vmid}/change-password, /container/{vmid}/change-password

Frontend:
- DeployTask: add 'kind' and 'server_id' fields
- useCloneInstance/useReinstallInstance/useChangePassword now return
  AsyncTaskResponse {task_id, status, name}; remove invalidateQueries
- InstanceActionDialogs: each onSuccess pushes task to deploy-tasks-store
  with appropriate kind, shows 'launched in background' toast
- InstancesPage:
  * ghostRows only for kind in {deploy, clone}, deduped by (server_id, vmid)
  * reinstall / change_password tasks shown as inline overlay (badge + ring)
    on the existing VM row's status column
2026-04-30 00:08:41 +02:00