mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-09-03 18:55:33 +00:00
18f5fe6841
* 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>
14 KiB
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-PveNetworkandSet-PveNetworkgained-BridgeVlanAware, so a VLAN-aware Linux bridge can be created and toggled from the module instead of only being read back. The model already surfacedbridge_vlan_awareasBridgeVlanAware, so this closed a write-path gap. OnSet-PveNetworkthe switch is only sent when explicitly bound, so an update that omits it leaves the flag alone. Clearing it goes through the endpoint'sdeletelist rather thanbridge_vlan_aware=0: PVE merges supplied keys onto the stored stanza and accepts the0without 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_vidsis not covered; it is an independent parameter and PVE defaults to 2-4094. (#92)
Changed
Newtonsoft.Jsonis now 13.0.4 in both shipped assemblies, with every package version managed centrally inDirectory.Packages.propsso the two can no longer drift; the SDK is pinned byglobal.json(10.0, latest feature band) and the net48 test build no longer emits theSystem.MemoryMSB3277 conflict. (#156)
Fixed
Copy-PveVmandCopy-PveContainernow allocate a valid guest ID throughcluster/nextidwhen-NewVmIdis omitted, instead of sendingnewid=0, which PVE rejects. Both cmdlets now forward-Storageto the clone request; it was declared and silently dropped, so a full clone always landed on the source storage.New-PveVmandImport-PveOvause the same service call for their ID allocation, so a response withoutdatais a clear error rather than aNullReferenceException. (#135)Import-PveOvano longer throws an unhandledInvalidOperationExceptionwhen 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;-TimeoutSecondswas added (default 30 minutes,0for none), mirroringSend-PveFile. (#139)Wait-PveTaskpolls throughTaskService.WaitForTasklike every other-Waitpath, 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-Timeoutstill waits indefinitely. (#140)Get-PveVmandGet-PveContainerwarn 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-Waitsurface 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-Timeoutwindow. (#142)Remove-PveStorage,Remove-PveSdnVnetandRemove-PveSdnZonenow percent-encode the name before building the API path and reject names outsideA-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-PveVmGuestExecnow recognises a booleanexitedfrom the guest agent, instead of polling until-Timeouton PVE builds that returntruerather than1. (#141)Disconnect-PveServerno longer issues aDELETEto/access/ticket, an endpoint PVE does not have; the call always failed and was hidden. It now discards the local session only and gained-Sessionso 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 withRemove-PveApiToken. (#144)Import-PveOvanow 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 ofscsifor every disk. (#138)Import-PveOvarejects an OVF descriptor whose disk file name contains anything outsideA-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-PvePermissionnow returns the privileges granted on each path in aPrivilegesproperty; 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 -Forcenow sendsskiplock=1(PVE honours it forroot@pamonly) andRemove-PveContainer -Forcesendsforce=1; both switches were accepted and ignored before. (#136)Restart-PveVmnow 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 cleanupthen held that lock for 30 seconds waiting on the newly started process, and the caller's next operation failed withcan'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-PveContaineris unchanged — LXC has no reboot endpoint. SeeDECISIONS.mdD016.- Guest operations that Proxmox rejects with
can't lock file '/var/lock/qemu-server/lock-<vmid>.conf' - got timeoutare now reissued for up to 45 seconds instead of surfacing as an error. That flock is taken byqm cleanupfor 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) SeeDECISIONS.mdD020. - Lifecycle cmdlets with
-Wait(Start/Stop/Restart/Reset/Resumefor VMs and containers) also wait for the guest's config lock (thelock:property, e.g.backupormigrate) to clear before returning, and the post-timeout fallback tests the most recent poll rather than whether a match was ever seen. SeeDECISIONS.mdD015 — that guard covers the config lock only; the separate flock race is D020. New-PveCluster -Waitnow 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 naturalNew-PveCluster -Wait→Add-PveClusterMembersequence failed withcluster not ready - no quorum?. Adds-Timeout(seconds, default 60, range 1-3600) following the-Waittimeout convention used byStop-PveContainerandReset-PveVm. SeeDECISIONS.mdD014.
[0.2.0] - 2026-05-22
Added
New-PveVmdisk controller / IO options:-DiskBus(virtio/scsi/sata/ide),-ScsiHardware(scsihw),-DiskIoThread,-DiskAio,-DiskSsd,-DiskDiscard,-DiskCache. Invalid combinations (e.g.ssdon virtio,iothreadon sata/ide or scsi withoutvirtio-scsi-single) are rejected up front with a clear error. (#65)Get-PveVmConfignow surfacesscsihw,efidisk0, andtpmstate0as typed properties, plus anAdditionalPropertiesdictionary 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 viaSet-PveVmConfig -AdditionalConfig @{ boot = 'order=scsi0;ide2' }failed withunable to parse drive options. Semicolons are now percent-encoded. (#64) Invoke-PveVmGuestExec -Argswere 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 PVEcommandarray (repeated keys), reaching the process as real argv. (#68)
[0.1.3] - 2026-05-20
Added
Connect-PveServer -TimeoutSecondsto set the session-defaultHttpClienttimeout (default 100s;0= infinite). (#59)Send-PveFile -TimeoutSecondsandInvoke-PveStorageDownload -TimeoutSecondsfor per-call override with a 30-minute implicit default so large uploads/downloads no longer trip the 100s default. (#59)
Fixed
New-PveVm -DiskSizeandNew-PveContainer -RootFsSizenow 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 withunable to parse lvm volume name '32G'. Sub-GB units (M,MB,K,KB) are now rejected client-side with a clear error. (#58)PveHttpClient.SendAsyncsurfacesHttpClient.Timeoutfirings asPveApiException(RequestTimeout)with the resource path and configured timeout, instead of leaking a rawTaskCanceledException. Works acrossnet48,net10.0, andnetstandard2.0. (#59)- Disk-size validation runs before
ShouldProcessso typos like512Mare caught with-WhatIf, regardless of whether-DiskStorage/-RootFsStorageis also supplied. (#58)
[0.1.2] - 2026-03-27
Fixed
Get-PveApiToken:FullTokenIdis now computed fromUserId!TokenId(was always empty). (#44)Set-PvePermission: addedtokenACL type with auto-detection from!in-UgId, enabling permission assignment for API tokens. (#43)Connect-PveServer: always emits the session to the pipeline. Use-Quietto suppress;-PassThruis 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-PveSdnIpamfor IPAM plugin management - SDN DNS cmdlets (3):
Get/New/Remove-PveSdnDnsfor DNS plugin management - SDN Controller cmdlets (3):
Get/New/Remove-PveSdnControllerfor controller management - SDN Update cmdlets (7):
Set-PveSdnZone/Vnet/Subnet/Controller/Ipam/Dns+Invoke-PveSdnApply Set-PveRole,Set-PveStorage,Set-PveApiTokenfor missing update operationsGet-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
ValidateSetagainst the PVE OpenAPI spec, withpve-api-enums.jsonfixture 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.0for PS 5.1 + PS 7.x compatibility System.Text.Jsonattributes removed — module usesNewtonsoft.Jsonexclusively- Inline task-polling loops replaced with
TaskService.WaitForTask(timeout + progress support) - Password parameters changed from
stringtoSecureStringwith secure memory handling ValidateRange(100, 999999999)added to allVmIdparametersUri.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
catchblocks 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.Highadded to all destructive cmdlets (Stop, Reset, Restart, Suspend, Remove, Restore, New-PveTemplate)- Storage
ValidateSet: removedglusterfs(dropped in PVE 9), addedbtrfsandesxi - Backup compression:
none→0(PVE expects the string"0", not"none") - Cluster resource filter: removed
lxc(PVE usesvmfor 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