- HasDiskOptions(): include -ScsiHardware so the "disk options ignored"
warning fires when -ScsiHardware is passed without -DiskStorage/-DiskSize.
- PveVmConfig.AdditionalProperties: lazy-init a backing field so the native
dictionary is built once rather than reallocated on every property access
(matters when iterating many configs in a pipeline). Safe because the model
is effectively immutable after deserialization.
- New-PveVm.Tests.ps1: add a case asserting -DiskIoThread on scsi with a
wrong -ScsiHardware (virtio-scsi-pci) is rejected, covering the validator's
"!= virtio-scsi-single" branch (not just the null case).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New-PveVm (F089):
- Add -DiskBus (virtio/scsi/sata/ide, default virtio), -ScsiHardware (scsihw),
-DiskIoThread, -DiskAio, -DiskSsd, -DiskDiscard, -DiskCache so a tuned disk
(e.g. virtio-scsi-single + scsi0,iothread=1,aio=native,ssd=1,discard=on) can
be created in one call instead of diskless + a hand-built Set-PveVmConfig string.
- Disk spec built via BuildDiskSpec; ValidateDiskOptions runs before ShouldProcess
and rejects ssd on virtio and iothread on sata/ide or scsi-without-virtio-scsi-single
with clear errors, instead of letting PVE fail at VM start.
Get-PveVmConfig (F090):
- PveVmConfig was a fixed allow-list, silently dropping keys like scsihw, efidisk0,
tpmstate0, hostpci0. Add typed scsihw/efidisk0/tpmstate0 plus a [JsonExtensionData]
catch-all exposed as AdditionalProperties (native types via JsonHelper.ToNative,
per D013 — no JToken leakage). Makes the disk tuning above verifiable by reading
the config back.
Closes#65.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- SizeParser: wrap TB-suffix overflow in try/catch so callers get
ArgumentException with the parameter name rather than OverflowException.
- New-PveVm/New-PveContainer: validate -DiskSize/-RootFsSize before
ShouldProcess so typos like "512M" are rejected even with -WhatIf and
even when the matching -DiskStorage/-RootFsStorage is omitted.
- Add Pester tests for the new DiskSize and RootFsSize validation paths,
including a new New-PveContainer.Tests.ps1.
- Add SizeParserTests coverage for the TB overflow path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- xUnit test project now targets net10.0 instead of net9.0 (EOL Nov 2026)
- Updated GuestAgentExtCmdlets tests for SecureString Password parameter
- Added Timeout parameter tests to GuestAgentCmdlets
- Added ConfirmImpact.High assertions for Suspend/Restart-PveVm
- Added -Confirm:$false to Suspend-PveVm integration test call
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parses OVF metadata client-side from the OVA TAR archive to extract
VM name, CPU, memory, disks, and network adapters. Then uploads the
OVA with content=import, creates the VM, and imports each disk.
- OvfMetadata parser with multi-target TAR support (System.Formats.Tar
on net9.0, manual 512-byte header parsing on netstandard2.0/net48)
- VmService.UploadOva() for content=import uploads
- Import-PveOva cmdlet with -Name/-Memory/-Cores overrides and -Wait
- Pester unit tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Imports disk images (qcow2, raw, vmdk) and OVA archives into VMs
via the PVE API using POST config with import-from syntax.
- VmService.ImportDisk() method using POST /nodes/{node}/qemu/{vmid}/config
- Import-PveVmDisk cmdlet with -Source, -Disk, -TargetStorage, -Format, -Wait
- Pester unit tests
- prepare-test-vm.sh updated to use Import-PveVmDisk instead of SSH qm importdisk
- Set-PveNetwork: add required Type parameter (fixes PVE API 400 error)
- Integration test fix: pass -Type bridge to Set-PveNetwork
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ConfirmImpact.High causes interactive confirmation prompts in
non-interactive CI, blocking before ProcessRecord runs. Add
-Confirm:$false to all Stop-PveVm, Reset-PveVm, Remove-*,
Restore-*, and New-PveTemplate calls in both unit and integration tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PS 5.1 prompts interactively for mandatory parameters instead of
throwing, causing CI to hang indefinitely. Replace invocation-based
tests with attribute-based IsMandatory checks where duplicates exist,
or convert to attribute checks where they don't.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Coverage for 16 cmdlets that had no unit tests:
- Nodes: Get-PveNode, Get-PveNodeStatus
- VM config: Get-PveVmConfig, Set-PveVmConfig, Resize-PveVmDisk
- VM ops: Copy-PveVm, Move-PveVm
- Container config: Copy-PveContainer, Get-PveContainerConfig,
Set-PveContainerConfig
- Storage: Invoke-PveStorageDownload
- Roles: New-PveRole, Remove-PveRole
- Tasks: Get-PveTask, Wait-PveTask
Each test covers: command existence, parameter metadata, pipeline
support, ShouldProcess/WhatIf, and no-session error handling.
Total Pester unit tests: 705 (was 431)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create shared _TestHelper.ps1 for reliable module loading in both
local dev and CI (fixes System.Runtime 9.0.0.0 FileNotFoundException
on PS 7.x by trying Import-Module by name first, then local paths)
- Use (Get-Module).ModuleBase for manifest path resolution
- Remove PSProxmoxVE.MockServer project and MockIntegration tests
- Remove MockIntegration from ExcludeTag filters
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
18 Pester 5 test files covering parameter validation, pipeline support,
-WhatIf behavior, ShouldProcess/ConfirmImpact attributes, and session
requirement enforcement for all cmdlet groups. Fully mocked — no network
calls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>