Skip to content

VirtDeck v3.0.3

Choose a tag to compare

@github-actions github-actions released this 13 Oct 07:22
· 28 commits to main since this release

VirtDeck v3.0.3

Fixed

  • Late answers: a refresh answer is judged by the attempt it was made in, not by its arrival time. RefreshCoordinator now 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 now ok (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) or error (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.utils instead of virtdeck.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).