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'