Files
PSProxmoxVE/tests/PSProxmoxVE.Tests/Integration/03a_SharedStorage.Tests.ps1
T
goodolclint-claude[bot] f48f0ea9ae ci: storage and answer services move to a VM inside the CI sandbox (1/2)
The nested PVE guests live on an isolated VLAN with no route to the
runner network (ADR 0032, homelab repo), and the runner-hosted Docker
services died with each ephemeral ARC pod anyway. A small cloud-image VM
in the ci pool now serves NFS, iSCSI, and the auto-install answer files
from inside the sandbox. Includes fixes from Codex and in-house review:
bpg provider >= 0.79.0, serial console for the resized cloud image,
key-based SSH (cloud images refuse password auth), CIDR validation,
storage VM in the headroom check, docker socket mounts removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 19:52:36 +00:00

149 lines
5.6 KiB
PowerShell

#Requires -Module Pester
<#
.SYNOPSIS
Pester 5 integration tests for shared storage backends (NFS, iSCSI).
These tests require the multi-node integration test infrastructure with
the shared storage VM (iSCSI target + NFS server on the CI VLAN). They are
SKIPPED when the storage env vars are not set.
Required environment variables (in addition to base integration vars):
PVETEST_STORAGE_VM_IP - IP of the storage host running iSCSI/NFS
PVETEST_ISCSI_IQN - iSCSI target IQN
PVETEST_NFS_EXPORT - NFS export path (e.g. 10.0.0.1:/srv/nfs/shared)
WARNING: These tests CREATE and DESTROY storage definitions on the target
PVE node. Never run against a production cluster.
#>
BeforeAll {
. $PSScriptRoot/_IntegrationHelper.ps1
Connect-TestPve
# --- Shared storage vars ---
$script:StorageVmIp = $env:PVETEST_STORAGE_VM_IP
$script:IscsiIqn = $env:PVETEST_ISCSI_IQN
$script:NfsExport = $env:PVETEST_NFS_EXPORT
# Track created storages for cleanup
$script:CreatedStorages = [System.Collections.Generic.List[string]]::new()
function script:Skip-IfNoSharedStorage {
if (Skip-IfNoTarget) { return $true }
if (-not $script:StorageVmIp -or -not $script:IscsiIqn -or -not $script:NfsExport) {
Set-ItResult -Skipped -Because 'Shared storage env vars not set (PVETEST_STORAGE_VM_IP, PVETEST_ISCSI_IQN, PVETEST_NFS_EXPORT)'
return $true
}
return $false
}
}
AfterAll {
# Best-effort cleanup of any storages we created
foreach ($name in $script:CreatedStorages) {
try { Remove-PveStorage -Storage $name -Confirm:$false -ErrorAction Stop }
catch { Write-Warning "Cleanup: failed to remove storage '$name': $_" }
}
Disconnect-TestPve
}
Describe 'Shared Storage — Integration' -Tag 'Integration' {
# -------------------------------------------------------------------
Context 'NFS Storage' {
It 'Should create NFS storage' {
if (Skip-IfNoSharedStorage) { return }
# Parse server and export from the full NFS export path (e.g. "10.0.0.1:/srv/nfs/shared")
$nfsParts = $script:NfsExport -split ':', 2
if (-not $nfsParts -or
$nfsParts.Count -ne 2 -or
[string]::IsNullOrWhiteSpace($nfsParts[0]) -or
[string]::IsNullOrWhiteSpace($nfsParts[1])) {
Set-ItResult -Skipped -Because "PVETEST_NFS_EXPORT must be in 'server:/export/path' format (current value: '$($script:NfsExport)')"
return
}
$nfsServer = $nfsParts[0]
$nfsExportPath = $nfsParts[1]
# Note: NFS is implicitly shared in PVE — do not pass -Shared
$result = New-PveStorage -Storage 'pester-nfs' -Type 'nfs' `
-Server $nfsServer `
-Export $nfsExportPath `
-Content 'images,iso,backup' `
-ErrorAction Stop
$result | Should -Not -BeNullOrEmpty
$result.Storage | Should -Be 'pester-nfs'
$script:CreatedStorages.Add('pester-nfs')
}
It 'Should list and find the NFS storage' {
if (Skip-IfNoSharedStorage) { return }
$storages = Get-PveStorage -Node $script:Node
$nfs = $storages | Where-Object { $_.Storage -eq 'pester-nfs' }
$nfs | Should -Not -BeNullOrEmpty
$nfs.Type | Should -Be 'nfs'
}
It 'Should get NFS storage status' {
if (Skip-IfNoSharedStorage) { return }
$status = Get-PveStorageStatus -Node $script:Node -Storage 'pester-nfs' -ErrorAction Stop
$status | Should -Not -BeNullOrEmpty
$status.Active | Should -Be 1
}
It 'Should remove NFS storage' {
if (Skip-IfNoSharedStorage) { return }
{ Remove-PveStorage -Storage 'pester-nfs' -Confirm:$false -ErrorAction Stop } |
Should -Not -Throw
$script:CreatedStorages.Remove('pester-nfs')
}
}
# -------------------------------------------------------------------
Context 'iSCSI Storage' {
It 'Should create iSCSI storage with -Target parameter' {
if (Skip-IfNoSharedStorage) { return }
# iSCSI uses -Portal (not -Server) for the target address.
# iSCSI is implicitly shared in PVE — do not pass -Shared.
$result = New-PveStorage -Storage 'pester-iscsi' -Type 'iscsi' `
-Portal $script:StorageVmIp `
-Target $script:IscsiIqn `
-ErrorAction Stop
$result | Should -Not -BeNullOrEmpty
$result.Storage | Should -Be 'pester-iscsi'
$script:CreatedStorages.Add('pester-iscsi')
}
It 'Should list and find the iSCSI storage' {
if (Skip-IfNoSharedStorage) { return }
$storages = Get-PveStorage -Node $script:Node
$iscsi = $storages | Where-Object { $_.Storage -eq 'pester-iscsi' }
$iscsi | Should -Not -BeNullOrEmpty
$iscsi.Type | Should -Be 'iscsi'
}
It 'Should get iSCSI storage status' {
if (Skip-IfNoSharedStorage) { return }
$status = Get-PveStorageStatus -Node $script:Node -Storage 'pester-iscsi' -ErrorAction Stop
$status | Should -Not -BeNullOrEmpty
}
It 'Should remove iSCSI storage' {
if (Skip-IfNoSharedStorage) { return }
{ Remove-PveStorage -Storage 'pester-iscsi' -Confirm:$false -ErrorAction Stop } |
Should -Not -Throw
$script:CreatedStorages.Remove('pester-iscsi')
}
}
}