Public/Network/New-VergeNetwork.ps1
|
function New-VergeNetwork { <# .SYNOPSIS Creates a new virtual network in VergeOS. .DESCRIPTION New-VergeNetwork creates a new virtual network with the specified configuration. The network is created in a stopped state by default. Use -PowerOn to start the network immediately after creation. .PARAMETER Name The name of the new network. Must be unique and 1-128 characters. .PARAMETER Type The network type. Valid values: Internal, External, DMZ. Default is Internal. .PARAMETER NetworkAddress The network address in CIDR notation (e.g., "10.0.0.0/24"). .PARAMETER IPAddress The IP address for the network router within the network. .PARAMETER Gateway The default gateway IP address (sent as DHCP option to clients). .PARAMETER Description An optional description for the network. .PARAMETER DHCPEnabled Enable DHCP server on this network. .PARAMETER DHCPStart The starting IP address for DHCP range. .PARAMETER DHCPStop The ending IP address for DHCP range. .PARAMETER DHCPDynamic Enable dynamic DHCP (create host entries for DHCP leases). .PARAMETER DNS DNS server mode. Valid values: Disabled, Simple, Bind, Network. Default is Simple. .PARAMETER DNSServers List of DNS server IP addresses to provide via DHCP. .PARAMETER Domain The domain name for this network. .PARAMETER MTU The MTU size (1000-65536). Leave unset for default. .PARAMETER InterfaceNetwork The name or key of another network to use as the interface (uplink) network. Required for External and DMZ type networks. .PARAMETER Layer2Type The Layer 2 encapsulation type. Valid values: vLan, vxLan, None. Default is vxLan. .PARAMETER Layer2ID The VLAN or VXLAN ID. If not specified, one will be auto-assigned. .PARAMETER OnPowerLoss Behavior when power is restored. Valid values: PowerOn, LastState, LeaveOff. Default is LastState. .PARAMETER Cluster The cluster to run the network on. .PARAMETER PowerOn Start the network immediately after creation. .PARAMETER PassThru Return the created network object. .PARAMETER Server The VergeOS connection to use. Defaults to the current default connection. .EXAMPLE New-VergeNetwork -Name "Dev-Network" -NetworkAddress "10.10.10.0/24" Creates a basic internal network with the specified address range. .EXAMPLE New-VergeNetwork -Name "Dev-Network" -NetworkAddress "10.10.10.0/24" -DHCPEnabled -DHCPStart "10.10.10.100" -DHCPStop "10.10.10.200" Creates an internal network with DHCP enabled. .EXAMPLE New-VergeNetwork -Name "Web-DMZ" -Type DMZ -NetworkAddress "172.16.0.0/24" -IPAddress "172.16.0.1" -InterfaceNetwork "External" -PowerOn -PassThru Creates a DMZ network connected to the External network and starts it. .OUTPUTS None by default. Verge.Network when -PassThru is specified. .NOTES After creating a network, use New-VergeNetworkRule to add firewall rules and Invoke-VergeNetworkApply to apply them. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, Position = 0)] [ValidateNotNullOrEmpty()] [ValidateLength(1, 128)] [string]$Name, [Parameter()] [ValidateSet('Internal', 'External', 'DMZ')] [string]$Type = 'Internal', [Parameter()] [ValidatePattern('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/(3[0-2]|[1-2][0-9]|[0-9])$')] [string]$NetworkAddress, [Parameter()] [ValidatePattern('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')] [string]$IPAddress, [Parameter()] [ValidatePattern('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')] [string]$Gateway, [Parameter()] [ValidateLength(0, 2048)] [string]$Description, [Parameter()] [switch]$DHCPEnabled, [Parameter()] [ValidatePattern('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')] [string]$DHCPStart, [Parameter()] [ValidatePattern('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')] [string]$DHCPStop, [Parameter()] [switch]$DHCPDynamic, [Parameter()] [ValidateSet('Disabled', 'Simple', 'Bind', 'Network')] [string]$DNS = 'Simple', [Parameter()] [string[]]$DNSServers, [Parameter()] [string]$Domain, [Parameter()] [ValidateRange(1000, 65536)] [int]$MTU, [Parameter()] [string]$InterfaceNetwork, [Parameter()] [ValidateSet('vLan', 'vxLan', 'None')] [string]$Layer2Type = 'vxLan', [Parameter()] [int]$Layer2ID, [Parameter()] [ValidateSet('PowerOn', 'LastState', 'LeaveOff')] [string]$OnPowerLoss = 'LastState', [Parameter()] [string]$Cluster, [Parameter()] [switch]$PowerOn, [Parameter()] [switch]$PassThru, [Parameter()] [object]$Server ) begin { # Resolve connection if (-not $Server) { $Server = $script:DefaultConnection } if (-not $Server) { throw [System.InvalidOperationException]::new( 'Not connected to VergeOS. Use Connect-VergeOS to establish a connection.' ) } # Map friendly names to API values $typeMap = @{ 'Internal' = 'internal' 'External' = 'external' 'DMZ' = 'dmz' } $dnsMap = @{ 'Disabled' = 'disabled' 'Simple' = 'simple' 'Bind' = 'bind' 'Network' = 'network' } $layer2Map = @{ 'vLan' = 'vlan' 'vxLan' = 'vxlan' 'None' = 'none' } $powerLossMap = @{ 'PowerOn' = 'power_on' 'LastState' = 'last_state' 'LeaveOff' = 'leave_off' } } process { # Build request body $body = @{ name = $Name type = $typeMap[$Type] layer2_type = $layer2Map[$Layer2Type] dns = $dnsMap[$DNS] on_power_loss = $powerLossMap[$OnPowerLoss] } # Add optional parameters if ($Description) { $body['description'] = $Description } if ($NetworkAddress) { $body['network'] = $NetworkAddress } if ($IPAddress) { $body['ipaddress'] = $IPAddress } if ($Gateway) { $body['gateway'] = $Gateway } if ($DHCPEnabled) { $body['dhcp_enabled'] = $true } if ($DHCPStart) { $body['dhcp_start'] = $DHCPStart } if ($DHCPStop) { $body['dhcp_stop'] = $DHCPStop } if ($DHCPDynamic) { $body['dhcp_dynamic'] = $true } if ($DNSServers -and $DNSServers.Count -gt 0) { $body['dnslist'] = $DNSServers -join ',' } if ($Domain) { $body['domain'] = $Domain } if ($MTU) { $body['mtu'] = $MTU } if ($Layer2ID) { $body['layer2_id'] = $Layer2ID } # Resolve interface network if specified if ($InterfaceNetwork) { if ($InterfaceNetwork -match '^\d+$') { $body['interface_vnet'] = [int]$InterfaceNetwork } else { try { $netResponse = Invoke-VergeAPI -Method GET -Endpoint 'vnets' -Query @{ filter = "name eq '$InterfaceNetwork'" fields = '$key,name' } -Connection $Server if ($netResponse -and $netResponse.'$key') { $body['interface_vnet'] = $netResponse.'$key' } elseif ($netResponse -is [array] -and $netResponse.Count -gt 0) { $body['interface_vnet'] = $netResponse[0].'$key' } else { throw "Interface network '$InterfaceNetwork' not found" } } catch { throw "Failed to resolve interface network '$InterfaceNetwork': $($_.Exception.Message)" } } } # Resolve cluster if specified if ($Cluster) { if ($Cluster -match '^\d+$') { $body['cluster'] = [int]$Cluster } else { try { $clusterResponse = Invoke-VergeAPI -Method GET -Endpoint 'clusters' -Query @{ filter = "name eq '$Cluster'" fields = '$key,name' } -Connection $Server if ($clusterResponse -and $clusterResponse.'$key') { $body['cluster'] = $clusterResponse.'$key' } elseif ($clusterResponse -is [array] -and $clusterResponse.Count -gt 0) { $body['cluster'] = $clusterResponse[0].'$key' } else { throw "Cluster '$Cluster' not found" } } catch { throw "Failed to resolve cluster '$Cluster': $($_.Exception.Message)" } } } # Confirm action $actionDescription = "Create $Type network '$Name'" if ($NetworkAddress) { $actionDescription += " ($NetworkAddress)" } if ($PSCmdlet.ShouldProcess($Name, 'Create Network')) { try { Write-Verbose "Creating network '$Name'" $response = Invoke-VergeAPI -Method POST -Endpoint 'vnets' -Body $body -Connection $Server # Get the created network key $networkKey = $response.'$key' if (-not $networkKey -and $response.key) { $networkKey = $response.key } Write-Verbose "Network '$Name' created with Key: $networkKey" # Power on if requested if ($PowerOn -and $networkKey) { Write-Verbose "Powering on network '$Name'" $powerBody = @{ vnet = $networkKey action = 'poweron' params = @{ apply = $true } } Invoke-VergeAPI -Method POST -Endpoint 'vnet_actions' -Body $powerBody -Connection $Server | Out-Null } if ($PassThru -and $networkKey) { # Return the created network Start-Sleep -Milliseconds 500 Get-VergeNetwork -Key $networkKey -Server $Server } } catch { $errorMessage = $_.Exception.Message if ($errorMessage -match 'already in use') { throw "A network with the name '$Name' already exists." } throw "Failed to create network '$Name': $errorMessage" } } } } |