diff --git a/src/PSProxmoxVE.Core/Models/Network/PveSdnSubnet.cs b/src/PSProxmoxVE.Core/Models/Network/PveSdnSubnet.cs index 46c3fdf..ee9c3a3 100644 --- a/src/PSProxmoxVE.Core/Models/Network/PveSdnSubnet.cs +++ b/src/PSProxmoxVE.Core/Models/Network/PveSdnSubnet.cs @@ -46,11 +46,11 @@ public class PveSdnSubnet public string? DnsZonePrefix { get; set; } /// - /// The DHCP range configuration for automatic IP assignment. + /// The DHCP range configurations for automatic IP assignment. /// [JsonPropertyName("dhcp-range")] [JsonProperty("dhcp-range")] - public string? DhcpRange { get; set; } + public string[]? DhcpRanges { get; set; } /// /// The subnet type identifier used internally by PVE. diff --git a/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 b/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 index 5208717..0232542 100644 --- a/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 +++ b/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 @@ -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 } diff --git a/tests/infrastructure/Dockerfile b/tests/infrastructure/Dockerfile index 7b8d801..1c8ab9f 100644 --- a/tests/infrastructure/Dockerfile +++ b/tests/infrastructure/Dockerfile @@ -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 && \ diff --git a/tests/infrastructure/scripts/prepare-test-environment.sh b/tests/infrastructure/scripts/prepare-test-environment.sh index 9eb2cb7..7c8427a 100755 --- a/tests/infrastructure/scripts/prepare-test-environment.sh +++ b/tests/infrastructure/scripts/prepare-test-environment.sh @@ -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'