Files
PSProxmoxVE/src/PSProxmoxVE/Cmdlets/Network/NewPveSdnZoneCmdlet.cs
T
Clint Branham 27ecca6251 feat: add two-tier version gating (introduced vs default) for cmdlets
Replace the service-layer RequireSdn hard block with a cmdlet-level
RequireVersion helper in PveCmdletBase that supports two tiers:

- Introduced version: hard fail — the API endpoint doesn't exist
- Default version: warning only — feature exists but may not be
  enabled; users who manually enabled it can proceed

Applied to:
- SDN Zone/VNet/Subnet: introduced 6.2, default 8.0
- SDN IPAM/DNS/Controller: introduced 6.2, default 8.1
- Import-PveVmDisk, Import-PveOva: introduced 8.1

Also fixes integration tests:
- Remove duplicate OVA Import context
- Use systemd calendar format for backup schedule (PVE 9)
- Add SDN IPAM/DNS/Controller read-only integration tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 08:40:23 -05:00

81 lines
3.6 KiB
C#

using System.Collections.Generic;
using System.Management.Automation;
using PSProxmoxVE.Core.Client;
namespace PSProxmoxVE.Cmdlets.Network
{
/// <summary>
/// <para type="synopsis">Creates a new SDN zone in Proxmox VE.</para>
/// <para type="description">
/// Adds a new Software-Defined Networking zone to the Proxmox VE cluster configuration.
/// </para>
/// </summary>
[Cmdlet(VerbsCommon.New, "PveSdnZone", SupportsShouldProcess = true)]
public class NewPveSdnZoneCmdlet : PveCmdletBase
{
/// <summary>The zone identifier (alphanumeric, hyphens allowed).</summary>
[Parameter(Mandatory = true, Position = 0, HelpMessage = "The SDN zone name.")]
public string Zone { get; set; } = string.Empty;
/// <summary>The zone type.</summary>
[Parameter(Mandatory = true, Position = 1, HelpMessage = "The zone type (e.g. vlan, vxlan, evpn, simple).")]
[ValidateSet("vlan", "vxlan", "evpn", "simple", "qinq", IgnoreCase = true)]
public string Type { get; set; } = string.Empty;
/// <summary>VXLAN peer list or multicast address (for vxlan/evpn types).</summary>
[Parameter(Mandatory = false, HelpMessage = "VXLAN peer list or multicast address.")]
public string? Peers { get; set; }
/// <summary>Bridge interface this zone attaches to (for vlan/qinq types).</summary>
[Parameter(Mandatory = false, HelpMessage = "Bridge interface for this zone.")]
public string? Bridge { get; set; }
/// <summary>MTU override for this zone.</summary>
[Parameter(Mandatory = false, HelpMessage = "MTU override for this zone.")]
public int? Mtu { get; set; }
/// <summary>DNS server for automatic DNS registration.</summary>
[Parameter(Mandatory = false, HelpMessage = "DNS server for automatic registration.")]
public string? Dns { get; set; }
/// <summary>Reverse DNS server.</summary>
[Parameter(Mandatory = false, HelpMessage = "Reverse DNS server.")]
public string? ReverseDns { get; set; }
/// <summary>DNS zone name for registration.</summary>
[Parameter(Mandatory = false, HelpMessage = "DNS zone name for registration.")]
public string? DnsZone { get; set; }
/// <summary>IPAM plugin to use for this zone.</summary>
[Parameter(Mandatory = false, HelpMessage = "IPAM plugin to use.")]
public string? Ipam { get; set; }
protected override void ProcessRecord()
{
if (!ShouldProcess(Zone, "Create PVE SDN Zone"))
return;
var session = GetSession();
RequireVersion(session, "SDN", 6, 2, 8, 0);
using var client = new PveHttpClient(session);
WriteVerbose($"Creating SDN zone '{Zone}'...");
var data = new Dictionary<string, string>
{
["zone"] = Zone,
["type"] = Type
};
if (!string.IsNullOrEmpty(Peers)) data["peers"] = Peers!;
if (!string.IsNullOrEmpty(Bridge)) data["bridge"] = Bridge!;
if (Mtu.HasValue) data["mtu"] = Mtu.Value.ToString();
if (!string.IsNullOrEmpty(Dns)) data["dns"] = Dns!;
if (!string.IsNullOrEmpty(ReverseDns)) data["reversedns"] = ReverseDns!;
if (!string.IsNullOrEmpty(DnsZone)) data["dnszone"] = DnsZone!;
if (!string.IsNullOrEmpty(Ipam)) data["ipam"] = Ipam!;
client.PostAsync("cluster/sdn/zones", data).GetAwaiter().GetResult();
}
}
}