Files
PSProxmoxVE/CHANGELOG.md
T
goodolclint-claude[bot] 18f5fe6841 docs: changelog entries for the wave 2 fixes (#183)
* docs: changelog entries for the wave 2 fixes

Lifts the Changelog section of #178, #179, #180, #181 and #182 into
[Unreleased].

* docs: do not call the Import-PveOva fallback documented; it was not

---------

Co-authored-by: goodolclint-claude[bot] <323206664+goodolclint-claude[bot]@users.noreply.github.com>
2026-09-02 16:35:38 -05:00

14 KiB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Conventional Commits.

[Unreleased]

Added

  • New-PveNetwork and Set-PveNetwork gained -BridgeVlanAware, so a VLAN-aware Linux bridge can be created and toggled from the module instead of only being read back. The model already surfaced bridge_vlan_aware as BridgeVlanAware, so this closed a write-path gap. On Set-PveNetwork the switch is only sent when explicitly bound, so an update that omits it leaves the flag alone. Clearing it goes through the endpoint's delete list rather than bridge_vlan_aware=0: PVE merges supplied keys onto the stored stanza and accepts the 0 without acting on it, so the obvious form is a silent no-op — confirmed against a live PVE 9 cluster, where the bridge stayed VLAN-aware. bridge_vids is not covered; it is an independent parameter and PVE defaults to 2-4094. (#92)

Changed

  • Newtonsoft.Json is now 13.0.4 in both shipped assemblies, with every package version managed centrally in Directory.Packages.props so the two can no longer drift; the SDK is pinned by global.json (10.0, latest feature band) and the net48 test build no longer emits the System.Memory MSB3277 conflict. (#156)

Fixed

  • Copy-PveVm and Copy-PveContainer now allocate a valid guest ID through cluster/nextid when -NewVmId is omitted, instead of sending newid=0, which PVE rejects. Both cmdlets now forward -Storage to the clone request; it was declared and silently dropped, so a full clone always landed on the source storage. New-PveVm and Import-PveOva use the same service call for their ID allocation, so a response without data is a clear error rather than a NullReferenceException. (#135)
  • Import-PveOva no longer throws an unhandled InvalidOperationException when the created VM is not yet listed on the node (the disk import still running without -Wait); it returns the basic VM record instead, as the cmdlet always intended. Its upload no longer runs under the session's 100-second timeout, so an OVA that takes longer to transfer completes; -TimeoutSeconds was added (default 30 minutes, 0 for none), mirroring Send-PveFile. (#139)
  • Wait-PveTask polls through TaskService.WaitForTask like every other -Wait path, so it clamps the poll interval to one second, checks the task before sleeping, and no longer overflows on intervals over 24 days. An omitted -Timeout still waits indefinitely. (#140)
  • Get-PveVm and Get-PveContainer warn for each node skipped because it was unreachable or returned a server error, instead of silently returning a partial or empty list, and a permission error on any node now surfaces instead of reading as "no guests". Lifecycle cmdlets with -Wait surface an expired session, a permission error or a missing guest during the status poll immediately, instead of failing with a generic timeout after the full -Timeout window. (#142)
  • Remove-PveStorage, Remove-PveSdnVnet and Remove-PveSdnZone now percent-encode the name before building the API path and reject names outside A-Z a-z 0-9 . _ -, so a name containing ../ can no longer be turned into a request against a different endpoint. The three cmdlets now call the existing service methods instead of building their own request. (#145)
  • Invoke-PveVmGuestExec now recognises a boolean exited from the guest agent, instead of polling until -Timeout on PVE builds that return true rather than 1. (#141)
  • Disconnect-PveServer no longer issues a DELETE to /access/ticket, an endpoint PVE does not have; the call always failed and was hidden. It now discards the local session only and gained -Session so an explicitly created session can be disconnected. The warning for a session that is not the module-level one names the credential's real lifecycle: tickets expire on their own, API tokens do not and can be revoked with Remove-PveApiToken. (#144)
  • Import-PveOva now places disks on the bus the OVF descriptor names. The controller mapping had SCSI and SATA swapped for VMware-produced OVAs, and the computed bus was then ignored in favour of scsi for every disk. (#138)
  • Import-PveOva rejects an OVF descriptor whose disk file name contains anything outside A-Z a-z 0-9 . _ -, and refuses descriptors with a DTD. A crafted archive could otherwise inject extra keys into the disk config line or exhaust memory through entity expansion. (#148)
  • Get-PvePermission now returns the privileges granted on each path in a Privileges property; previously the map PVE returned was dropped and every result carried only the path. The key's presence is the grant; the value is whether it propagates to sub-paths. (#137)
  • Remove-PveVm -Force now sends skiplock=1 (PVE honours it for root@pam only) and Remove-PveContainer -Force sends force=1; both switches were accepted and ignored before. (#136)
  • 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 -WaitAdd-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: none0 (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