fix(test): fix suspend, SDN, container, and OVA integration test failures

- Suspend/Resume: move to Linux VM lifecycle context (empty VMs may
  not reliably transition to paused state)
- SDN subnet model: dhcp-range is an array, not string
- SDN subnet delete: use PVE-format ID (vnet-ip-prefix) not CIDR
- Container config: trim trailing newline from PVE description
- OVA: use qemu-img to create valid sparse VMDK (add qemu-utils to
  test container Dockerfile)
- Enable 'images' content type on local storage for OVA import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Clint Branham
2026-03-20 14:49:06 -05:00
parent 531deafdb7
commit c5396707eb
4 changed files with 33 additions and 31 deletions
@@ -46,11 +46,11 @@ public class PveSdnSubnet
public string? DnsZonePrefix { get; set; }
/// <summary>
/// The DHCP range configuration for automatic IP assignment.
/// The DHCP range configurations for automatic IP assignment.
/// </summary>
[JsonPropertyName("dhcp-range")]
[JsonProperty("dhcp-range")]
public string? DhcpRange { get; set; }
public string[]? DhcpRanges { get; set; }
/// <summary>
/// The subnet type identifier used internally by PVE.
@@ -458,31 +458,8 @@ Describe 'Integration Tests' -Tag 'Integration' {
# -----------------------------------------------------------------------
Context 'VM — Suspend / Resume / Resize' {
It 'Should suspend and resume a VM' {
if (Skip-IfNoTestVm) { return }
# Start the VM
Start-PveVm -Node $script:Node -VmId $script:TestVmId -Wait | Out-Null
# Suspend — sends QMP stop to QEMU
{ Suspend-PveVm -Node $script:Node -VmId $script:TestVmId -Wait -ErrorAction Stop } |
Should -Not -Throw
Start-Sleep -Seconds 3
$vm = Get-PveVm -Node $script:Node | Where-Object { $_.VmId -eq $script:TestVmId }
$vm.Status | Should -Be 'paused'
# Resume — sends QMP cont to QEMU
{ Resume-PveVm -Node $script:Node -VmId $script:TestVmId -Wait -ErrorAction Stop } |
Should -Not -Throw
Start-Sleep -Seconds 2
$vm = Get-PveVm -Node $script:Node | Where-Object { $_.VmId -eq $script:TestVmId }
$vm.Status | Should -Be 'running'
# Clean up — stop
Stop-PveVm -Node $script:Node -VmId $script:TestVmId -Wait -Confirm:$false | Out-Null
}
# Suspend/Resume is tested on the Linux VM (Guest Agent VM — Lifecycle)
# because an empty VM with no OS may not reliably transition to 'paused'.
It 'Should resize a VM disk (Resize-PveVmDisk)' {
if (Skip-IfNoTestVm) { return }
@@ -796,7 +773,8 @@ Describe 'Integration Tests' -Tag 'Integration' {
if (Skip-IfNoTarget) { return }
if ($script:SkipSdn) { Set-ItResult -Skipped -Because $script:SkipSdn; return }
{ Remove-PveSdnSubnet -Vnet 'pestervn' -Subnet '10.99.0.0/24' `
# PVE stores subnet IDs in the format: {vnet}-{ip}-{prefix}
{ Remove-PveSdnSubnet -Vnet 'pestervn' -Subnet 'pestervn-10.99.0.0-24' `
-Confirm:$false -ErrorAction Stop } | Should -Not -Throw
}
@@ -913,7 +891,7 @@ Describe 'Integration Tests' -Tag 'Integration' {
-ErrorAction Stop } | Should -Not -Throw
$config = Get-PveContainerConfig -Node $script:Node -VmId $script:TestContainerId
$config.Description | Should -Be 'Updated by Pester integration test'
$config.Description.Trim() | Should -Be 'Updated by Pester integration test'
}
It 'Should start a container (Start-PveContainer)' {
@@ -1168,6 +1146,28 @@ Describe 'Integration Tests' -Tag 'Integration' {
$vm.Status | Should -Be 'running'
}
It 'Should suspend and resume a running VM (Suspend-PveVm / Resume-PveVm)' {
if (Skip-IfNoLinuxVm) { return }
# Suspend — sends QMP stop
{ Suspend-PveVm -Node $script:Node -VmId $script:LinuxVmId -Wait -ErrorAction Stop } |
Should -Not -Throw
Start-Sleep -Seconds 3
$vm = Get-PveVm -Node $script:Node |
Where-Object { $_.VmId -eq $script:LinuxVmId }
$vm.Status | Should -Be 'paused'
# Resume — sends QMP cont
{ Resume-PveVm -Node $script:Node -VmId $script:LinuxVmId -Wait -ErrorAction Stop } |
Should -Not -Throw
Start-Sleep -Seconds 5
$vm = Get-PveVm -Node $script:Node |
Where-Object { $_.VmId -eq $script:LinuxVmId }
$vm.Status | Should -Be 'running'
}
It 'Should gracefully restart a VM via ACPI (Restart-PveVm)' {
if (Skip-IfNoLinuxVm) { return }
+2
View File
@@ -44,6 +44,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
powershell \
terraform \
proxmox-auto-install-assistant \
qemu-utils \
&& rm -rf /var/lib/apt/lists/*
# ── Install Pester ────────────────────────────────────────────────────
@@ -58,6 +59,7 @@ RUN echo "=== Tool verification ===" && \
proxmox-auto-install-assistant --version && \
sshpass -V | head -1 && \
xorriso --version 2>&1 | head -1 && \
qemu-img --version | head -1 && \
curl --version | head -1 && \
jq --version && \
python3 --version && \
@@ -63,8 +63,8 @@ if [ ! -f "${OVA_PATH}" ]; then
echo "Creating minimal test OVA..."
OVA_TMPDIR=$(mktemp -d)
# Create a 1MB raw disk image and convert to vmdk-stream (flat)
dd if=/dev/zero of="${OVA_TMPDIR}/test-disk.vmdk" bs=1M count=1 2>/dev/null
# Create a minimal valid sparse VMDK using qemu-img
qemu-img create -f vmdk -o subformat=streamOptimized "${OVA_TMPDIR}/test-disk.vmdk" 64M 2>/dev/null
# Create OVF descriptor
cat > "${OVA_TMPDIR}/test-appliance.ovf" <<'OVF'