diff --git a/src/PSProxmoxVE/Cmdlets/Storage/NewPveStorageCmdlet.cs b/src/PSProxmoxVE/Cmdlets/Storage/NewPveStorageCmdlet.cs index 95a67a2..f8d643a 100644 --- a/src/PSProxmoxVE/Cmdlets/Storage/NewPveStorageCmdlet.cs +++ b/src/PSProxmoxVE/Cmdlets/Storage/NewPveStorageCmdlet.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Management.Automation; using Newtonsoft.Json.Linq; @@ -114,14 +115,32 @@ namespace PSProxmoxVE.Cmdlets.Storage AddIfNotEmpty(data, "content", Content); AddIfNotEmpty(data, "path", Path); - AddIfNotEmpty(data, "server", Server); AddIfNotEmpty(data, "export", Export); AddIfNotEmpty(data, "vgname", VgName); AddIfNotEmpty(data, "thinpool", ThinPool); - AddIfNotEmpty(data, "pool", Pool ?? CephPool); + AddIfNotEmpty(data, "pool", !string.IsNullOrEmpty(Pool) ? Pool : CephPool); AddIfNotEmpty(data, "monhost", MonHost); AddIfNotEmpty(data, "target", Target); - AddIfNotEmpty(data, "portal", Portal); + + // For iSCSI types, 'server' is not a valid API field; derive portal from Server if Portal omitted. + bool isIscsiType = string.Equals(Type, "iscsi", StringComparison.OrdinalIgnoreCase) + || string.Equals(Type, "iscsidirect", StringComparison.OrdinalIgnoreCase); + if (isIscsiType) + { + string? portalValue; + if (!string.IsNullOrEmpty(Portal)) + portalValue = Portal; + else if (!string.IsNullOrEmpty(Server)) + portalValue = $"{Server}:3260"; + else + portalValue = null; + AddIfNotEmpty(data, "portal", portalValue); + } + else + { + AddIfNotEmpty(data, "server", Server); + AddIfNotEmpty(data, "portal", Portal); + } AddIfNotEmpty(data, "nodes", Nodes); if (Shared.IsPresent) data["shared"] = "1"; if (Disable.IsPresent) data["disable"] = "1"; diff --git a/tests/PSProxmoxVE.Tests/Integration/SharedStorage.Tests.ps1 b/tests/PSProxmoxVE.Tests/Integration/SharedStorage.Tests.ps1 index 1e02b57..62e07fc 100644 --- a/tests/PSProxmoxVE.Tests/Integration/SharedStorage.Tests.ps1 +++ b/tests/PSProxmoxVE.Tests/Integration/SharedStorage.Tests.ps1 @@ -95,6 +95,13 @@ Describe 'Shared Storage — Integration' -Tag 'Integration' { # 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] diff --git a/tests/infrastructure/docker-compose.storage.yml b/tests/infrastructure/docker-compose.storage.yml index 6d04dee..40eb511 100644 --- a/tests/infrastructure/docker-compose.storage.yml +++ b/tests/infrastructure/docker-compose.storage.yml @@ -53,6 +53,9 @@ services: privileged: true volumes: - nfs-data:/srv/nfs/shared + # NOTE: /lib/modules is required by the NFS kernel module loader. + # This mount is Linux-host-specific and will fail on macOS/Windows Docker Desktop. + # Integration tests using this compose file must run on a Linux host (e.g. GitHub-hosted runners or the dev container). - /lib/modules:/lib/modules:ro environment: NFS_EXPORT_0: /srv/nfs/shared *(rw,sync,no_subtree_check,no_root_squash)