Repository navigation
Releases: mcluremail/virtdeck
Release list
VirtDeck v3.0.5
What changed
Fixed:
- Backup job editing no longer destroys the guest selection: the editor now models the three PVE selection kinds (all / pool / VMID list), an unchanged save sends nothing, and a pool or all-guests job can no longer silently degrade into an explicit VMID list (PVE deletes
pool/all/excludethe momentvmidarrives in a PUT) - The backup retention policy is preserved verbatim:
prune-backupskeeps everykeep-*element in both string and object form, an unparsable policy blocks the save instead of being replaced by an inventedkeep-last=3, and omitted server defaults (remove,compress) are never written back unless actually changed - Fleet Health stops asserting what it could not verify: a failed task-history collection shows a yellow "Backup state unverified" row naming the failed source instead of the false red "Never backed up"; a caveat explains missing job-run attribution on PVE below 7.2; one corrupt task row can no longer crash the whole cluster report
- Refresh safety: a timed-out or failed pools/HA fetch is "not fetched", not a confirmed absence — a host whose worker fails keeps its last known-good data through refresh cycles (audit 6.1.1)
- The backup jobs table shows the selection kind (All guests / pool / VMID list / node) instead of a VMIDs column that was empty for pool and all-guests jobs
Internal: the fake_pve stand implements backup-job CRUD with real PVE update_job semantics (58 new tests, 1358 → 1416); i18n version 39 (21 new keys in all 5 locales); pyside6 debs declare the full Qt runtime closure in Depends.
Full details: CHANGELOG.md.
Install
Website: https://virtdeck.mclure.ru · Repository: https://repo.mclure.ru
Download: .deb (Debian/Ubuntu), .rpm (Fedora), .zip/.exe (Windows); .tar.gz / .whl — from source.
Debian 12 / 13, Ubuntu 24.04 / 26.04 — from the package repository (PySide6 comes from there too, no pip needed):
curl -fsSL https://repo.mclure.ru/KEY.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/virtdeck.gpg
echo "deb [signed-by=/etc/apt/keyrings/virtdeck.gpg] https://repo.mclure.ru/apt bookworm main" | sudo tee /etc/apt/sources.list.d/virtdeck.list
sudo apt update && sudo apt install virtdeck
(Ubuntu 24.04 — replace bookworm with noble; Ubuntu 26.04 — resolute; Debian 13 — trixie)
Fedora 43 / 44:
sudo tee /etc/yum.repos.d/virtdeck.repo <<'EOF'
[virtdeck]
name=VirtDeck
baseurl=https://repo.mclure.ru/rpm/fedora/$releasever
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.mclure.ru/KEY.gpg
EOF
sudo dnf install virtdeck
Verify the repository key fingerprint after downloading it
(the key and the packages share one domain; the fingerprint is also
published on the website and at repo.mclure.ru):
117D EABD 3EA4 8810 B219 BA6B 401F 700F B97D E8B8
For the VM console install virt-viewer (sudo apt install virt-viewer / sudo dnf install virt-viewer).
VirtDeck v3.0.4
VirtDeck v3.0.4
What changed
v3.0.4 — connection identity and safe cache restore (external audit stage 5.1)
Bug fixes
- Connection identity: every connection now carries a stable
conn_id, independent of its display name. Connection names must be unique up to normalization (NFC + outer-space strip + case-insensitive comparison). Legacy databases that already contain colliding names (Web/web, trailing spaces, different Unicode compositions of the same text) load untouched — the entries are not merged, renamed or removed; they stay visible with a distinct warning and are excluded from hard/soft refresh, cache restore, token operations, the PBS panel and fleet collection until the user resolves the conflict in the new repair dialog (pick the connection to keep — the loser is removed through the regular delete flow with its own confirmation and token revoke). Creating new conflicts is rejected at the add dialog, at the add flow and centrally at config save - Startup cache restore is identity-keyed: cached rows are matched by the producing connection's
conn_id, never by the display name. A connection deleted and re-created under the same name restores nothing, rows written by previous versions (no conn_id) and rows of unknown connections are never attached — the data is re-fetched from the server instead of showing resources of a foreign infrastructure. Resource-cache writes are skipped entirely while a conn_id migration has not been persisted (e.g. a read-only config directory), and rows without an identity are never stored - Worker results are identity-gated: a refresh result of an unknown, deleted or re-created connection (or of an ambiguous one) is dropped before it can touch the repositories, the update epochs, the UI or the cache; the owner's name is taken from the current configuration, not from the stale result. The existing generation/epoch checks are preserved — a late answer of a deleted connection cannot resurrect its data
- Config import: entries are matched by
(type, host, user)instead of(host, user)— a PBS entry at the same address as a PVE entry no longer silently replaces it. A matched connection keeps its local name and identity; only credential/option fields are imported, and the token is written to the keyring only when it actually changed. Identifiers from the bundle are never accepted as local identity: new entries get fresh local ids, and a full-restore import (merge=False) assigns fresh ids to every entry — a restored backup can never attach the local cache of another installation. Conflicting names, invalid entries and ambiguous matches are skipped with explicit reasons collected into the import summary instead of aborting the whole import or silently overwriting; re-importing the same bundle is idempotent and no longer leaves orphaned keyring entries - Token refresh (reconnect) no longer rebuilds the connection from the dialog's short field list —
skip,group, port/proxy/cluster settings and the conn_id survive a token rotation (previouslyskipandgroupwere silently dropped)
Internal
- The conn_id migration runs at config load and persists in a single SQLite transaction touching only the changed rows; on failure the app keeps working with in-memory ids while resource-cache writes stay blocked until a successful config save anchors them. Tokens and other secrets are never touched by the migration
- Name normalization, ambiguity detection and uniqueness checks are centralized in the config layer (
normalize_name,name_key,mark_ambiguous,save_config); the shrink-only guarantee for legacy conflict groups is enforced insidesave_configitself, against the stored database — no caller can widen the tolerance (a group may stay verbatim, shrink or disappear, never grow, and no new group may appear) - 50 new regression tests (config-level and UI-level) covering the audit 5.1/5.1.1 matrices and the 5.1.3 review: id migration and the pending state (including failed saves keeping the flag), ambiguity handling and the shrink-only save rule, import rules, the three data-ingestion gates, the legacy name-fallback boundaries and cache-write blocking
- Release engineering: the CI matrix covers Python 3.10–3.14 and PySide6 is capped to
>=6.5,<6.12per the project policy (the floating CI resolution pulled the buggy 6.12.0 and was red); a newscripts/check_release.pyruns as a CI job and verifies install-command versions, CI-matrix-vs-declared-support, i18n key parity and fingerprint formatting; the README install command, the PEP 668 note (venv-first), the fingerprint spacing (+ machine verification snippet) and the Language switching section were corrected to match the actual implementation - python3-pyside6 debs (revision -3) declare
Provides: libpyside6-py3, libshiboken6-py3andConflicts:against the distro split-PySide6 packages: Ubuntu 26.04's python3-pyqtgraph hard-depends onlibpyside6-py3, which previously madeapt install virtdeckunsolvable there (file clash with our wheel). The virtual provides satisfy pyqtgraph, the conflicts remove the distro pieces gracefully instead of a dpkg error
Install
Website: https://virtdeck.mclure.ru · Repository: https://repo.mclure.ru
Download: .deb (Debian/Ubuntu), .rpm (Fedora), .zip/.exe (Windows); .tar.gz / .whl — from source.
Debian 12 / 13, Ubuntu 24.04 / 26.04 — from the package repository (PySide6 comes from there too, no pip needed):
curl -fsSL https://repo.mclure.ru/KEY.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/virtdeck.gpg
echo "deb [signed-by=/etc/apt/keyrings/virtdeck.gpg] https://repo.mclure.ru/apt bookworm main" | sudo tee /etc/apt/sources.list.d/virtdeck.list
sudo apt update && sudo apt install virtdeck
(Ubuntu 24.04 — replace bookworm with noble; Ubuntu 26.04 — resolute; Debian 13 — trixie)
Fedora 43 / 44:
sudo tee /etc/yum.repos.d/virtdeck.repo <<'EOF'
[virtdeck]
name=VirtDeck
baseurl=https://repo.mclure.ru/rpm/fedora/$releasever
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.mclure.ru/KEY.gpg
EOF
sudo dnf install virtdeck
Verify the repository key fingerprint after downloading it
(the key and the packages share one domain; the fingerprint is also
published on the website and at repo.mclure.ru):
117D EABD 3EA4 8810 B219 BA6B 401F 700F B97D E8B8
For the VM console install virt-viewer (sudo apt install virt-viewer / sudo dnf install virt-viewer).
VirtDeck v3.0.3
VirtDeck v3.0.3
Fixed
- Late answers: a refresh answer is judged by the attempt it was made in, not by its arrival time.
RefreshCoordinatornow stamps every attempt with a monotonic epoch (incremented when an attempt starts or is discarded) and records the epoch of the last snapshot APPLIED per host; an answer older than that is dropped silently — it does not overwrite the fresher snapshot, re-trigger notifications, re-run the first selection or rewrite the cache. Previously a hard cycle closed by the watchdog could still accept a late answer with stale content and wipe fresher data applied by a later soft cycle. A lone late answer for a host with no fresher data is still accepted, so the only available result is never lost - Pools: pool identity is now
(host_name, poolid)— a poolid is unique within a PVE cluster/standalone instance but not across independent infrastructures, so identical ids of two hosts silently replaced each other before. A hard cycle no longer clears the shared pool repository: pools of hosts whose workers fail or are rejected keep their last known-good data, only hosts that left the configuration are dropped; a confirmed empty list clears the host's pools, a failed pool fetch signals "not fetched" (pools: null) instead of pretending "no pools". The create-VM dialog receives the pools of the host the VM is created on, and global search distinguishes same-id pools by host - Cluster config: two active representatives of the SAME configured cluster duplicated every node and VM in the repositories, counters and the tree. The first representative per cluster name is kept, the duplicates are dropped with an explicit notification instead of silently doubling resources. Clusters with different names but coinciding node names are treated as independent infrastructures and never merged — identity is the configured cluster name only, node names are not compared across clusters
- Refresh snapshots: the absence of an answer is no longer the absence of resources. FetchWorker classified failures of mandatory API requests (cluster resources; node status; guest/storage listings) as
status="ok"with empty lists, so the UI erased a host's real resources from the tree and the persistent cache whenever the host was unreachable. Results are nowok(every mandatory source completed successfully — an empty list is a confirmed absence, not a failure),partial(the host identity is confirmed, some mandatory resource lists are not — the consumer keeps the previous snapshot) orerror(nothing confirmed). A thread that outlives its join deadline counts as data that never arrived; optional sources (pools, HA, versions, storage details, ISO images) never affect the status - Soft refresh merges per-host snapshots instead of swapping the whole world: a host that answered replaces its own snapshot entirely (resources really removed on the server disappear), a host whose worker failed keeps its last known-good data with its nodes flagged ERROR, hosts that did not take part stay untouched. Previously one dead host wiped its VMs/storages, and a fully failed cycle wiped every host and rewrote the persistent cache with that emptiness
- Hard refresh no longer clears the repositories at cycle start: each worker replaces only its own host's confirmed snapshot, so a host whose worker was rejected by a full pool (or failed) keeps its data. When nothing can be started the UI leaves the loading state immediately instead of waiting forever, and a watchdog (180 s ceiling) force-finalizes a hard cycle whose workers stopped reporting — late reports still apply per-host, stale generations never overwrite newer state
- Repository indexes: moving a VM to another node no longer leaves a ghost in the old node's bucket —
filter_by_host()/count_by_host()no longer report the pre-migration placement - Startup cache: hosts removed from the configuration or excluded by skip are no longer resurrected from the cache; cluster representatives are matched by config name, so PVE node names inside a cluster snapshot are never filtered out. The first hard cycle no longer clears the freshly loaded cache — cached hosts keep serving until their own fresh confirmed answer replaces them
- The error branch of a failed refresh worker crashed on a broken internal import (
virtdeck.utilsinstead ofvirtdeck.ui.utils), skipping the notification, the tree update and the cache save for that cycle - ISO/HA lists of a successful response replace the previous data even when the new list is empty (a confirmed absence), while a failed optional fetch no longer pretends "no ISOs" — the previous list survives
Internal
- Package platforms refreshed to current distro releases: rpm builds target Fedora 43 / 44 (one build per Fedora release — the auto-generated
python3.Xdist(proxmoxer)dependencies must resolve against that release's Python); the apt side adds Ubuntu 26.04 "resolute" (Python 3.14) alongside Debian 12/13 and Ubuntu 24.04. The EOL fedora/41 catalog stays frozen on the repository server (append-only — existing dnf users keep working) but is no longer built for or documented - The python3-pyside6 deb for resolute is built from the official PySide6 6.11.2 wheel (abi3 cp310+, officially supports Python 3.14); 6.8.3 remains for bookworm/noble/trixie. 6.12.x stays avoided (known refcount bug)
- Release artifacts are now GPG-signed (.asc, same key as the package repository): signatures are produced on repo.mclure.ru — the private key never leaves the server — and uploaded next to the release files; the v3.0.2 artifacts were signed retroactively
- The signing key's fingerprint (117D EABD 3EA4 8810 B219 BA6B 401F 700F B97D E8B8) is published in three independent places — README, website, and the repo.mclure.ru root page — with explicit "verify the fingerprint after download" instructions; the release CI smoke test checks the fingerprint before trusting the repository
- repo.mclure.ru now serves an index page at its root (install commands for all supported distros, the key fingerprint, links) instead of a bare autoindex
- Release procedure: the release body must lead with "Fixed: …" from the CHANGELOG (v3.0.2's boilerplate body was fixed retroactively); a website-update step (version strings + install blocks synced with README, i18n parity checks) and a semi-annual platform/EOL review were added to docs/RELEASE_PROCESS.md
- README: an honest comparison with Proxmox Datacenter Manager added (nothing to deploy server-side — a window on your desktop); the "From source" instructions now actually install the package (
pip install virtdeck-<ver>-py3-none-any.whl …), not just its dependencies
Install
Website: https://virtdeck.mclure.ru · Repository: https://repo.mclure.ru
Download: .deb (Debian/Ubuntu), .rpm (Fedora), .zip/.exe (Windows); .tar.gz / .whl — from source.
Debian 12 / 13, Ubuntu 24.04 / 26.04 — from the package repository (PySide6 comes from there too, no pip needed):
curl -fsSL https://repo.mclure.ru/KEY.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/virtdeck.gpg
echo "deb [signed-by=/etc/apt/keyrings/virtdeck.gpg] https://repo.mclure.ru/apt bookworm main" | sudo tee /etc/apt/sources.list.d/virtdeck.list
sudo apt update && sudo apt install virtdeck
(Ubuntu 24.04 — replace bookworm with noble; Ubuntu 26.04 — resolute; Debian 13 — trixie)
Fedora 43 / 44:
sudo tee /etc/yum.repos.d/virtdeck.repo <<'EOF'
[virtdeck]
name=VirtDeck
baseurl=https://repo.mclure.ru/rpm/fedora/$releasever
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.mclure.ru/KEY.gpg
EOF
sudo dnf install virtdeck
Verify the repository key fingerprint after downloading it (the key and the
packages share one domain; the fingerprint is also published on the website
and at repo.mclure.ru):
117D EABD 3EA4 8810 B219 BA6B 401F 700F B97D E8B8
For the VM console install virt-viewer (sudo apt install virt-viewer / sudo dnf install virt-viewer).
VirtDeck v3.0.2
VirtDeck v3.0.2
Fixed
- Storage: deleting and moving storage content (ISO/backup volumes) works against real PVE again — the volume ID (
local:iso/name.iso) was passed into the API path unencoded; proxmoxer splits such strings on "/" and PVE answered 404 for every standard volid - Backup jobs (scheduled vzdump): the silent fallback to the legacy API path is gone — a timed-out create could silently duplicate the job, a validation error was swallowed, a delete re-ran and reported a misleading 404 while the job was actually gone; the path is now chosen before the request and real errors propagate
- Task polling: one transient network failure during a long operation no longer reports the operation as failed while the PVE task keeps running — up to 3 consecutive transport failures are tolerated and the outcome is reported as "unknown" instead of a fake failure
- Upload: failed uploads raise a classified error with the HTTP status (401/403/413/5xx, pveproxy 595–599 hint) instead of a bare exception; a 200 with a broken body raises a clean error
- Error texts: messages reaching the UI are sanitized consistently — bare hostnames are masked alongside URLs, while timestamps, volids and the task's own error text survive
- Internal: CI runs the full pytest suite (3 Python versions, offscreen Qt); a UI suite degradation (30+ min → ~1.5 min) fixed
Note: these release artifacts got their
.ascGPG signatures retroactively (2026-10) — the signature was produced with the same key that signs the package repository. Verify the key fingerprint after downloading it (published in the README, on the website and at repo.mclure.ru):117D EABD 3EA4 8810 B219 BA6B 401F 700F B97D E8B8
Сайт: https://virtdeck.mclure.ru
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows; .tar.gz / .whl — установка из исходников.
Debian 12 / 13 и Ubuntu 24.04 — из пакета-репозитория (PySide6 приедет оттуда же, pip не нужен):
curl -fsSL https://repo.mclure.ru/KEY.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/virtdeck.gpg
echo "deb [signed-by=/etc/apt/keyrings/virtdeck.gpg] https://repo.mclure.ru/apt bookworm main" | sudo tee /etc/apt/sources.list.d/virtdeck.list
sudo apt update && sudo apt install virtdeck
(Ubuntu 24.04 — замените bookworm на noble, Debian 13 — на trixie)
Fedora 41:
sudo tee /etc/yum.repos.d/virtdeck.repo <<'EOF'
[virtdeck]
name=VirtDeck
baseurl=https://repo.mclure.ru/rpm/fedora/41
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.mclure.ru/KEY.gpg
EOF
sudo dnf install virtdeck
Для консоли VM установите virt-viewer (sudo apt install virt-viewer / sudo dnf install virt-viewer).
VirtDeck v3.0.1
VirtDeck v3.0.1
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows; .tar.gz / .whl — установка из исходников.
Debian 12 / 13 и Ubuntu 24.04 — из пакета-репозитория (PySide6 приедет оттуда же, pip не нужен):
curl -fsSL https://repo.mclure.ru/KEY.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/virtdeck.gpg
echo "deb [signed-by=/etc/apt/keyrings/virtdeck.gpg] https://repo.mclure.ru/apt bookworm main" | sudo tee /etc/apt/sources.list.d/virtdeck.list
sudo apt update && sudo apt install virtdeck
(Ubuntu 24.04 — замените bookworm на noble, Debian 13 — на trixie)
Fedora 41:
sudo tee /etc/yum.repos.d/virtdeck.repo <<'EOF'
[virtdeck]
name=VirtDeck
baseurl=https://repo.mclure.ru/rpm/fedora/41
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.mclure.ru/KEY.gpg
EOF
sudo dnf install virtdeck
Для консоли VM установите virt-viewer (sudo apt install virt-viewer / sudo dnf install virt-viewer).
VirtDeck v3.0.0
VirtDeck v3.0.0
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows, .tar.gz / .whl для pip.
Установка .deb:
sudo dpkg -i virtdeck_*.deb
pip install proxmoxer
sudo apt install virt-viewer
Установка .rpm:
sudo dnf install virtdeck-*.rpm
pip install proxmoxer
sudo dnf install virt-viewer
Установка Windows:
Распакуйте .zip в любую папку, запустите virtdeck.exe.
Для консоли VM установите virt-viewer:
https://virt-manager.org/download/
Установка через pip:
pip install virtdeck
PVE Center v2.13.0
PVE Center v2.13.0
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows, .tar.gz / .whl для pip.
Установка .deb:
sudo dpkg -i pve-center_*.deb
pip install proxmoxer
sudo apt install virt-viewer
Установка .rpm:
sudo dnf install pve-center-*.rpm
pip install proxmoxer
sudo dnf install virt-viewer
Установка Windows:
Распакуйте .zip в любую папку, запустите pvecenter.exe.
Для консоли VM установите virt-viewer:
https://virt-manager.org/download/
Установка через pip:
pip install pvecenter
PVE Center v2.12.0
PVE Center v2.12.0
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows, .tar.gz / .whl для pip.
Установка .deb:
sudo dpkg -i pve-center_*.deb
pip install proxmoxer
sudo apt install virt-viewer
Установка .rpm:
sudo dnf install pve-center-*.rpm
pip install proxmoxer
sudo dnf install virt-viewer
Установка Windows:
Распакуйте .zip в любую папку, запустите pvecenter.exe.
Для консоли VM установите virt-viewer:
https://virt-manager.org/download/
Установка через pip:
pip install pvecenter
PVE Center v2.11.3
PVE Center v2.11.3
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows, .tar.gz / .whl для pip.
Установка .deb:
sudo dpkg -i pve-center_*.deb
pip install proxmoxer
sudo apt install virt-viewer
Установка .rpm:
sudo dnf install pve-center-*.rpm
pip install proxmoxer
sudo dnf install virt-viewer
Установка Windows:
Распакуйте .zip в любую папку, запустите pvecenter.exe.
Для консоли VM установите virt-viewer:
https://virt-manager.org/download/
Установка через pip:
pip install pvecenter
PVE Center v2.11.2
PVE Center v2.11.2
Скачать: .deb для Debian/Ubuntu, .rpm для Fedora/RHEL, .zip для Windows, .tar.gz / .whl для pip.
Установка .deb:
sudo dpkg -i pve-center_*.deb
pip install proxmoxer
sudo apt install virt-viewer
Установка .rpm:
sudo dnf install pve-center-*.rpm
pip install proxmoxer
sudo dnf install virt-viewer
Установка Windows:
Распакуйте .zip в любую папку, запустите pvecenter.exe.
Для консоли VM установите virt-viewer:
https://virt-manager.org/download/
Установка через pip:
pip install pvecenter