mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-09-04 03:05:32 +00:00
db416a3f03
WaitForStatusTransition refused to return while snapshot.Locked, and its comment quoted the exact error it was meant to prevent. Locked reads the guest config's lock: property; the failure is the flock on /var/lock/qemu-server/lock-<vmid>.conf, which PVE exposes nowhere. The flock cannot be observed, so it is retried. GuestLockRetry reissues an operation for a bounded 45s while PVE reports failing to enter lock_config for a guest, which it raises before doing any work. Two seams, because the failure has two surfaces. PveHttpClient.SendAsync retries the request for operations PVE serialises in the API handler; it takes a request factory because an HttpRequestMessage cannot be resent. PveCmdletBase.InvokeGuestTask reissues the call and re-waits its task for operations serialised in the forked worker, where the POST returns 200 and only the task fails. WaitForStatusTransition routes through the latter, hence Func<PveTask>. The predicate is path-specific and anchored at the start of what PVE said: lock_file uses identical wording for storage, LVM and HA locks, and a qmclone that fails after allocating disks must not be reissued into "VM already exists". That requires the raw text, so it reads PveTaskFailedException.ExitStatus and PveApiException.ApiMessage. The Locked check stays — it is correct for the config lock — with a comment that says so. Closes #113
117 lines
9.7 KiB
Markdown
117 lines
9.7 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to this project will be documented in this file.
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
and this project adheres to [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
|
|
|
## [Unreleased]
|
|
|
|
### Fixed
|
|
|
|
- `Restart-PveVm` now uses PVE's native reboot endpoint (`POST {vmid}/status/reboot`) instead of composing a shutdown followed by a start. The two-call form raced Proxmox's own post-stop cleanup: the start won the guest's config lock, `qm cleanup` then held that lock for 30 seconds waiting on the newly started process, and the caller's next operation failed with `can't lock file '/var/lock/qemu-server/lock-<vmid>.conf' - got timeout`. Reproduced in integration runs 183, 185 and 186 as a cascade of 4 failures. `Restart-PveContainer` is unchanged — LXC has no reboot endpoint. See `DECISIONS.md` D016.
|
|
- Guest operations that Proxmox rejects with `can't lock file '/var/lock/qemu-server/lock-<vmid>.conf' - got timeout` are now reissued for up to 45 seconds instead of surfacing as an error. That flock is taken by `qm cleanup` for up to 30 seconds after a guest stops and is not exposed through the API in any form, so it can only be retried past, never waited on. Covers both the synchronous form (`Set-PveVmConfig`, `Resize-PveVmDisk`, and every other call through the HTTP client) and the asynchronous form, where the request succeeds and the PVE task then fails (`Reset-PveVm`, `Copy-PveVm`). Reproduced on a client ~40% slower than CI, which failed three VM tests on a commit CI passed. (#113) See `DECISIONS.md` D020.
|
|
- Lifecycle cmdlets with `-Wait` (`Start`/`Stop`/`Restart`/`Reset`/`Resume` for VMs and containers) also wait for the guest's config lock (the `lock:` property, e.g. `backup` or `migrate`) to clear before returning, and the post-timeout fallback tests the most recent poll rather than whether a match was ever seen. See `DECISIONS.md` D015 — that guard covers the config lock only; the separate flock race is D020.
|
|
- `New-PveCluster -Wait` now blocks until the cluster reports quorum, not merely until the creation task finishes. PVE's create task returns before corosync converges (~6s earlier in testing), so the natural `New-PveCluster -Wait` → `Add-PveClusterMember` sequence failed with `cluster not ready - no quorum?`. Adds `-Timeout` (seconds, default 60, range 1-3600) following the `-Wait` timeout convention used by `Stop-PveContainer` and `Reset-PveVm`. See `DECISIONS.md` D014.
|
|
|
|
## [0.2.0] - 2026-05-22
|
|
|
|
### Added
|
|
|
|
- `New-PveVm` disk controller / IO options: `-DiskBus` (virtio/scsi/sata/ide), `-ScsiHardware` (scsihw), `-DiskIoThread`, `-DiskAio`, `-DiskSsd`, `-DiskDiscard`, `-DiskCache`. Invalid combinations (e.g. `ssd` on virtio, `iothread` on sata/ide or scsi without `virtio-scsi-single`) are rejected up front with a clear error. (#65)
|
|
- `Get-PveVmConfig` now surfaces `scsihw`, `efidisk0`, and `tpmstate0` as typed properties, plus an `AdditionalProperties` dictionary capturing any other config key (e.g. `hostpci0`) as native .NET values instead of silently dropping it. (#65)
|
|
|
|
### Fixed
|
|
|
|
- Form values containing `;` were split into bogus fields by PVE's parser, so a multi-device boot order set via `Set-PveVmConfig -AdditionalConfig @{ boot = 'order=scsi0;ide2' }` failed with `unable to parse drive options`. Semicolons are now percent-encoded. (#64)
|
|
- `Invoke-PveVmGuestExec -Args` were delivered to the guest as JSON on STDIN instead of as argv, so commands ran with no/garbage arguments. Arguments are now sent as the PVE `command` array (repeated keys), reaching the process as real argv. (#68)
|
|
|
|
## [0.1.3] - 2026-05-20
|
|
|
|
### Added
|
|
|
|
- `Connect-PveServer -TimeoutSeconds` to set the session-default `HttpClient` timeout (default 100s; `0` = infinite). (#59)
|
|
- `Send-PveFile -TimeoutSeconds` and `Invoke-PveStorageDownload -TimeoutSeconds` for per-call override with a 30-minute implicit default so large uploads/downloads no longer trip the 100s default. (#59)
|
|
|
|
### Fixed
|
|
|
|
- `New-PveVm -DiskSize` and `New-PveContainer -RootFsSize` now normalize unit suffixes (`32G`, `1T`, `32GB`, etc.) to bare GiB before constructing the disk spec. Previously the suffix was passed verbatim, which LVM/LVM-thin storages rejected with `unable to parse lvm volume name '32G'`. Sub-GB units (`M`, `MB`, `K`, `KB`) are now rejected client-side with a clear error. (#58)
|
|
- `PveHttpClient.SendAsync` surfaces `HttpClient.Timeout` firings as `PveApiException(RequestTimeout)` with the resource path and configured timeout, instead of leaking a raw `TaskCanceledException`. Works across `net48`, `net10.0`, and `netstandard2.0`. (#59)
|
|
- Disk-size validation runs before `ShouldProcess` so typos like `512M` are caught with `-WhatIf`, regardless of whether `-DiskStorage`/`-RootFsStorage` is also supplied. (#58)
|
|
|
|
## [0.1.2] - 2026-03-27
|
|
|
|
### Fixed
|
|
|
|
- `Get-PveApiToken`: `FullTokenId` is now computed from `UserId!TokenId` (was always empty). (#44)
|
|
- `Set-PvePermission`: added `token` ACL type with auto-detection from `!` in `-UgId`, enabling permission assignment for API tokens. (#43)
|
|
- `Connect-PveServer`: always emits the session to the pipeline. Use `-Quiet` to suppress; `-PassThru` is kept hidden for backwards compatibility. (#45)
|
|
|
|
## [0.1.1] - 2026-03-26
|
|
|
|
### Added
|
|
|
|
- Firewall management cmdlets (21): rules, security groups, aliases, IP sets, options at cluster/node/VM/container levels
|
|
- Backup/vzdump cmdlets (5): ad-hoc backup creation and scheduled backup job CRUD
|
|
- SDN IPAM cmdlets (3): `Get`/`New`/`Remove-PveSdnIpam` for IPAM plugin management
|
|
- SDN DNS cmdlets (3): `Get`/`New`/`Remove-PveSdnDns` for DNS plugin management
|
|
- SDN Controller cmdlets (3): `Get`/`New`/`Remove-PveSdnController` for controller management
|
|
- SDN Update cmdlets (7): `Set-PveSdnZone`/`Vnet`/`Subnet`/`Controller`/`Ipam`/`Dns` + `Invoke-PveSdnApply`
|
|
- `Set-PveRole`, `Set-PveStorage`, `Set-PveApiToken` for missing update operations
|
|
- `Get-PveClusterResource`: single-call cluster-wide inventory of all VMs, containers, nodes, storage
|
|
- Task management: `Get-PveTaskList` (list tasks on node), `Stop-PveTask` (cancel running tasks)
|
|
- Pool management cmdlets (4): `Get`/`New`/`Set`/`Remove-PvePool`
|
|
- `Get-PveBackupInfo`: find VMs/containers not covered by backup jobs
|
|
- VM disk operations: `Move-PveVmDisk` (storage migration), `Remove-PveVmDisk` (detach/delete)
|
|
- Guest agent extensions (6): `Get-PveVmGuestOsInfo`, `Get-PveVmGuestFsInfo`, `Read`/`Write-PveVmGuestFile`, `Set-PveVmGuestPassword`, `Invoke-PveVmGuestFsTrim`
|
|
- Container gaps (6): `Suspend`/`Resume-PveContainer`, `Resize-PveContainerDisk`, `New-PveContainerTemplate`, `Move-PveContainerVolume`, `Get-PveContainerInterface`
|
|
- Storage content management (4): `Get-PveStorageStatus`, `Remove`/`Set-PveStorageContent`, `New-PveStorageDisk`
|
|
- Node operations (6): `Get`/`Set-PveNodeConfig`, `Get`/`Set-PveNodeDns`, `Start`/`Stop-PveNodeVms`
|
|
- Access management (9): `Get`/`New`/`Set`/`Remove-PveGroup`, `Get`/`New`/`Set`/`Remove-PveDomain`, `Set-PvePassword`
|
|
- Two-tier version gating: introduced vs default version with clear user messaging
|
|
- 70 xUnit tests validating every `ValidateSet` against the PVE OpenAPI spec, with `pve-api-enums.json` fixture extracted from the full spec
|
|
- Integration tests for firewall rules, aliases, IP sets, backup jobs, and OVA import
|
|
- PSGallery version badge in README
|
|
|
|
### Changed
|
|
|
|
- All cmdlet classes sealed for design clarity and JIT optimization
|
|
- `[OutputType]` attribute added to all 169 cmdlets for IntelliSense and pipeline support
|
|
- Publishable projects retargeted to `netstandard2.0` for PS 5.1 + PS 7.x compatibility
|
|
- `System.Text.Json` attributes removed — module uses `Newtonsoft.Json` exclusively
|
|
- Inline task-polling loops replaced with `TaskService.WaitForTask` (timeout + progress support)
|
|
- Password parameters changed from `string` to `SecureString` with secure memory handling
|
|
- `ValidateRange(100, 999999999)` added to all `VmId` parameters
|
|
- `Uri.EscapeDataString()` applied to all dynamic URL path segments
|
|
- Hardcoded verb strings replaced with verb class constants (`VerbsCommon.Get`, etc.)
|
|
- Auth header magic strings extracted to named constants in `PveHttpClient`
|
|
- Bare `catch` blocks replaced with specific or filtered exception handling
|
|
- MAML help (dll-Help.xml) and 170 markdown cmdlet docs generated
|
|
- PSGallery publish workflow with PS 5.1 smoke testing
|
|
|
|
### Fixed
|
|
|
|
- `ConfirmImpact.High` added to all destructive cmdlets (Stop, Reset, Restart, Suspend, Remove, Restore, New-PveTemplate)
|
|
- Storage `ValidateSet`: removed `glusterfs` (dropped in PVE 9), added `btrfs` and `esxi`
|
|
- Backup compression: `none` → `0` (PVE expects the string `"0"`, not `"none"`)
|
|
- Cluster resource filter: removed `lxc` (PVE uses `vm` for both QEMU and LXC)
|
|
- Hardcoded test password moved from CI workflow to GitHub Actions secret
|
|
- Terraform variable default password removed (requires env var)
|
|
|
|
## [0.1.0-preview] - 2026-03-19
|
|
|
|
### Added
|
|
|
|
- Initial project structure and solution setup
|
|
- Ticket and API token authentication with session management
|
|
- HTTP client with manual multipart ISO upload (bugzilla 7389 workaround)
|
|
- Typed response models for PVE 8.x and 9.x API resources
|
|
- Service layer for all resource domains
|
|
- 66 PowerShell cmdlets for VMs, containers, storage, networking, SDN, users, roles, permissions, API tokens, templates, cloud-init, snapshots, and tasks
|
|
- QEMU guest agent cmdlets (Test-PveVmGuestAgent, Get-PveVmGuestNetwork, Invoke-PveVmGuestExec)
|
|
- xUnit unit tests for core library
|
|
- Pester 5 cmdlet tests across OS/PS version matrix (Windows PS 5.1, PS 7.5 on Windows/Linux/macOS)
|
|
- Integration tests against live PVE 8 and PVE 9 instances via Terraform-provisioned nested VMs
|
|
- GitHub Actions CI/CD workflows (build, unit tests, integration tests)
|
|
- Format definitions for default table output on all PS versions
|