Public/network-offering.ps1

function Get-CSNetworkOffering {
    <#
    .SYNOPSIS
        Lists network offerings.

    .DESCRIPTION
        Wraps listNetworkOfferings. With -NetworkId, returns the offerings that
        network can be moved to (see Move-CSNetwork).

    .PARAMETER Id
        Filter by network offering ID

    .PARAMETER Name
        Filter by name

    .PARAMETER DisplayText
        Filter by display text

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER GuestIpType
        Filter by guest IP type: Shared, Isolated, or L2

    .PARAMETER TrafficType
        Filter by traffic type

    .PARAMETER State
        Filter by state: Enabled, Disabled, or Inactive

    .PARAMETER Availability
        Filter by availability: Optional or Required

    .PARAMETER SupportedServices
        Only offerings that support all of these services, e.g. SourceNat, Lb

    .PARAMETER Tags
        Filter by tags

    .PARAMETER RoutingMode
        Filter by routing mode: Static or Dynamic

    .PARAMETER ForVpc
        Only offerings that can ($true) or cannot ($false) be used inside a VPC

    .PARAMETER IsDefault
        Only default ($true) or non-default ($false) offerings

    .PARAMETER IsTagged
        Only offerings that have ($true) or lack ($false) tags

    .PARAMETER SourceNatSupported
        Only offerings that support source NAT

    .PARAMETER SpecifyIpRanges
        Only offerings that let networks specify IP ranges

    .PARAMETER SpecifyVlan
        Only offerings that let networks specify a VLAN

    .PARAMETER NetworkId
        Only offerings this network can be changed to

    .PARAMETER ZoneId
        Only offerings available in this zone

    .PARAMETER DomainId
        Only offerings available in this domain

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSNetworkOffering -State Enabled
        Lists the enabled network offerings.

    .EXAMPLE
        Get-CSNetworkOffering -GuestIpType Isolated -SupportedServices SourceNat, Lb -ForVpc $false
        Lists isolated, non-VPC offerings with source NAT and load balancing.

    .EXAMPLE
        Get-CSNetworkOffering -NetworkId (Get-CSNetwork -Name 'app').id
        Lists the offerings the 'app' network can be moved to.
    #>

    [CmdletBinding()]
    param(
        [string]$Id,

        [Parameter(Position = 0)]
        [string]$Name,

        [string]$DisplayText,

        [string]$Keyword,

        [ValidateSet('Shared', 'Isolated', 'L2')]
        [string]$GuestIpType,

        [string]$TrafficType,

        [ValidateSet('Enabled', 'Disabled', 'Inactive')]
        [string]$State,

        [ValidateSet('Optional', 'Required')]
        [string]$Availability,

        [string[]]$SupportedServices,

        [string]$Tags,

        [ValidateSet('Static', 'Dynamic')]
        [string]$RoutingMode,

        [bool]$ForVpc,

        [bool]$IsDefault,

        [bool]$IsTagged,

        [bool]$SourceNatSupported,

        [bool]$SpecifyIpRanges,

        [bool]$SpecifyVlan,

        [string]$NetworkId,

        [string]$ZoneId,

        [string]$DomainId,

        [int]$Page,

        [int]$PageSize
    )

    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        Id = 'id'; Name = 'name'; DisplayText = 'displaytext'; Keyword = 'keyword'; GuestIpType = 'guestiptype'
        TrafficType = 'traffictype'; State = 'state'; Availability = 'availability'
        SupportedServices = 'supportedservices'; Tags = 'tags'; RoutingMode = 'routingmode'; ForVpc = 'forvpc'
        IsDefault = 'isdefault'; IsTagged = 'istagged'; SourceNatSupported = 'sourcenatsupported'
        SpecifyIpRanges = 'specifyipranges'; SpecifyVlan = 'specifyvlan'; NetworkId = 'networkid'
        ZoneId = 'zoneid'; DomainId = 'domainid'; Page = 'page'; PageSize = 'pagesize'
    })
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listNetworkOfferings' -Parameters $apiParams) -Command 'listNetworkOfferings'
}

function New-CSNetworkOffering {
    <#
    .SYNOPSIS
        Creates a network offering.

    .DESCRIPTION
        Wraps createNetworkOffering. An offering defines the network type
        (-GuestIpType), the services networks built from it get
        (-SupportedServices), and which provider delivers each service
        (-ServiceProviders). New offerings are Disabled unless -Enable is given;
        enable one later with Set-CSNetworkOffering -State Enabled.

    .PARAMETER Name
        The name of the offering

    .PARAMETER DisplayText
        Display text. Defaults to the name.

    .PARAMETER GuestIpType
        Shared, Isolated, or L2

    .PARAMETER TrafficType
        Traffic type. Only GUEST is supported, which is the default.

    .PARAMETER SupportedServices
        Services the offering provides, e.g. Dhcp, Dns, SourceNat, StaticNat,
        PortForwarding, Firewall, Lb, UserData, Vpn, NetworkACL. Defaults to the
        services named in -ServiceProviders.

    .PARAMETER ServiceProviders
        Provider per service, as @{ Dhcp = 'VirtualRouter'; Dns = 'VirtualRouter' }.
        Services left out use the physical network's default provider.

    .PARAMETER ServiceCapabilities
        Service capabilities, as an array of hashtables with Service,
        CapabilityType and CapabilityValue keys, e.g.
        @{ Service = 'SourceNat'; CapabilityType = 'SupportedSourceNatTypes'; CapabilityValue = 'peraccount' }

    .PARAMETER Details
        Extra settings, e.g. @{ promiscuousmode = 'true'; publiclbprovider = 'Netscaler' }

    .PARAMETER Availability
        Optional (default) or Required. Required makes this the default offering
        for new networks.

    .PARAMETER ConserveMode
        Whether IP conserve mode is on, letting one public IP carry several services

    .PARAMETER EgressDefaultPolicy
        $true to allow egress traffic by default, $false to deny it

    .PARAMETER NetworkRate
        Data transfer rate in Mbps

    .PARAMETER MaxConnections
        Maximum concurrent load-balancer connections

    .PARAMETER KeepAliveEnabled
        Turn on load-balancer keepalive (haproxy only)

    .PARAMETER ServiceOfferingId
        Service offering for the offering's virtual routers

    .PARAMETER InternetProtocol
        ipv4 (default) or dualstack

    .PARAMETER NetworkMode
        NATTED or ROUTED

    .PARAMETER RoutingMode
        Static or Dynamic (ROUTED networks)

    .PARAMETER Tags
        Tags for the offering

    .PARAMETER ZoneId
        Zones the offering is available in. Omit for all zones.

    .PARAMETER DomainId
        Domains the offering is available to. Omit for a public offering.

    .PARAMETER Enable
        Enable the offering straight away

    .PARAMETER ForVpc
        The offering is for VPC tiers

    .PARAMETER ForNsx
        The offering is for NSX networks

    .PARAMETER NsxSupportLb
        The NSX offering supports the load-balancer service

    .PARAMETER NsxSupportsInternalLb
        The NSX offering supports the internal load-balancer service

    .PARAMETER ForTungsten
        The offering is for Tungsten-Fabric networks

    .PARAMETER IsPersistent
        Networks built from the offering are persistent (implemented at creation)

    .PARAMETER SpecifyVlan
        Networks built from the offering can specify a VLAN

    .PARAMETER SpecifyIpRanges
        Networks built from the offering can specify IP ranges

    .PARAMETER SpecifyAsNumber
        Networks built from the offering can choose a BGP AS number

    .EXAMPLE
        New-CSNetworkOffering -Name 'Isolated with SNAT' -GuestIpType Isolated -ServiceProviders @{ Dhcp = 'VirtualRouter'; Dns = 'VirtualRouter'; SourceNat = 'VirtualRouter'; Firewall = 'VirtualRouter'; PortForwarding = 'VirtualRouter' } -Enable
        Creates and enables a basic isolated offering served by the virtual router.
        The supported services are taken from the provider map.

    .EXAMPLE
        New-CSNetworkOffering -Name 'L2 VLAN' -GuestIpType L2 -SpecifyVlan -Enable
        Creates an L2 offering with no services where each network picks its VLAN.

    .EXAMPLE
        New-CSNetworkOffering -Name 'Isolated per-zone SNAT' -GuestIpType Isolated -ServiceProviders @{ SourceNat = 'VirtualRouter'; Dhcp = 'VirtualRouter'; Dns = 'VirtualRouter' } -ServiceCapabilities @{ Service = 'SourceNat'; CapabilityType = 'SupportedSourceNatTypes'; CapabilityValue = 'perzone' } -ZoneId zone-uuid
        Creates an offering with a per-zone source NAT capability, limited to one zone.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Name,

        [string]$DisplayText,

        [Parameter(Mandatory = $true)]
        [ValidateSet('Shared', 'Isolated', 'L2')]
        [string]$GuestIpType,

        [string]$TrafficType = 'GUEST',

        [string[]]$SupportedServices,

        [System.Collections.IDictionary]$ServiceProviders,

        [hashtable[]]$ServiceCapabilities,

        [hashtable]$Details,

        [ValidateSet('Optional', 'Required')]
        [string]$Availability,

        [bool]$ConserveMode,

        [bool]$EgressDefaultPolicy,

        [int]$NetworkRate,

        [int]$MaxConnections,

        [switch]$KeepAliveEnabled,

        [string]$ServiceOfferingId,

        [ValidateSet('ipv4', 'dualstack')]
        [string]$InternetProtocol,

        [ValidateSet('NATTED', 'ROUTED')]
        [string]$NetworkMode,

        [ValidateSet('Static', 'Dynamic')]
        [string]$RoutingMode,

        [string]$Tags,

        [string[]]$ZoneId,

        [string[]]$DomainId,

        [switch]$Enable,

        [switch]$ForVpc,

        [switch]$ForNsx,

        [switch]$NsxSupportLb,

        [switch]$NsxSupportsInternalLb,

        [switch]$ForTungsten,

        [switch]$IsPersistent,

        [switch]$SpecifyVlan,

        [switch]$SpecifyIpRanges,

        [switch]$SpecifyAsNumber
    )

    $apiParams = @{ name = $Name; guestiptype = $GuestIpType; traffictype = $TrafficType }
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        DisplayText = 'displaytext'; SupportedServices = 'supportedservices'; Availability = 'availability'
        ConserveMode = 'conservemode'; EgressDefaultPolicy = 'egressdefaultpolicy'; NetworkRate = 'networkrate'
        MaxConnections = 'maxconnections'; KeepAliveEnabled = 'keepaliveenabled'; ServiceOfferingId = 'serviceofferingid'
        InternetProtocol = 'internetprotocol'; NetworkMode = 'networkmode'; RoutingMode = 'routingmode'; Tags = 'tags'
        ZoneId = 'zoneid'; DomainId = 'domainid'; Enable = 'enable'; ForVpc = 'forvpc'; ForNsx = 'fornsx'
        NsxSupportLb = 'nsxsupportlb'; NsxSupportsInternalLb = 'nsxsupportsinternallb'; ForTungsten = 'fortungsten'
        IsPersistent = 'ispersistent'; SpecifyVlan = 'specifyvlan'; SpecifyIpRanges = 'specifyipranges'
        SpecifyAsNumber = 'specifyasnumber'
    })
    # CloudStack wants every service listed in supportedservices even when it is
    # already named in the provider map, so fill it in rather than make callers
    # type each service twice.
    if ($ServiceProviders -and -not $PSBoundParameters.ContainsKey('SupportedServices')) {
        $apiParams['supportedservices'] = @($ServiceProviders.Keys) -join ','
    }
    Add-CSMapParameter -ApiParameters $apiParams -Name 'serviceproviderlist' -Map $ServiceProviders -KeyField 'service' -ValueField 'provider'
    Add-CSMapParameter -ApiParameters $apiParams -Name 'details' -Map $Details

    $index = 0
    foreach ($capability in $ServiceCapabilities) {
        foreach ($key in 'Service', 'CapabilityType', 'CapabilityValue') {
            if (-not $capability.ContainsKey($key)) {
                throw "Each -ServiceCapabilities entry needs Service, CapabilityType and CapabilityValue keys; entry $index is missing $key."
            }
            $apiParams["servicecapabilitylist[$index].$($key.ToLowerInvariant())"] = [string]$capability[$key]
        }
        $index++
    }

    if ($PSCmdlet.ShouldProcess("network offering $Name", 'Create')) {
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'createNetworkOffering' -Parameters $apiParams) -Command 'createNetworkOffering'
    }
}

function Set-CSNetworkOffering {
    <#
    .SYNOPSIS
        Updates a network offering.

    .DESCRIPTION
        Wraps updateNetworkOffering: rename it, enable or disable it, change where
        it is available, or change its load-balancer limits. The services an
        offering provides cannot be changed after creation. Accepts offering
        objects from Get-CSNetworkOffering on the pipeline.

    .PARAMETER Id
        The ID of the offering (binds from a piped offering's id)

    .PARAMETER Name
        A new name. Never bound from the pipeline.

    .PARAMETER DisplayText
        New display text

    .PARAMETER State
        Enabled or Disabled

    .PARAMETER Availability
        Optional or Required. Only one offering can be Required.

    .PARAMETER Tags
        New tags

    .PARAMETER MaxConnections
        Maximum concurrent load-balancer connections

    .PARAMETER KeepAliveEnabled
        Turn load-balancer keepalive on or off (haproxy only)

    .PARAMETER SortKey
        Sort position in the UI

    .PARAMETER ZoneId
        Zones the offering is available in, or 'all'

    .PARAMETER DomainId
        Domains the offering is available to, or 'public'

    .EXAMPLE
        Set-CSNetworkOffering -Id offering-uuid -State Enabled
        Enables an offering.

    .EXAMPLE
        Get-CSNetworkOffering -Keyword 'legacy' | Set-CSNetworkOffering -State Disabled
        Disables every legacy offering so no new networks use them.

    .EXAMPLE
        Get-CSNetworkOffering -Name 'Isolated with SNAT' | Set-CSNetworkOffering -DomainId domain-a-uuid, domain-b-uuid
        Restricts an offering to two domains.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$Id,

        [string]$Name,

        [string]$DisplayText,

        [ValidateSet('Enabled', 'Disabled')]
        [string]$State,

        [ValidateSet('Optional', 'Required')]
        [string]$Availability,

        [string]$Tags,

        [int]$MaxConnections,

        [bool]$KeepAliveEnabled,

        [int]$SortKey,

        [string[]]$ZoneId,

        [string[]]$DomainId
    )

    process {
        $apiParams = @{ id = $Id }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Name = 'name'; DisplayText = 'displaytext'; State = 'state'; Availability = 'availability'; Tags = 'tags'
            MaxConnections = 'maxconnections'; KeepAliveEnabled = 'keepaliveenabled'; SortKey = 'sortkey'
            ZoneId = 'zoneid'; DomainId = 'domainid'
        })
        if ($apiParams.Count -eq 1) { throw 'Specify at least one property to update.' }
        if ($PSCmdlet.ShouldProcess("network offering $Id", 'Update')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'updateNetworkOffering' -Parameters $apiParams) -Command 'updateNetworkOffering'
        }
    }
}

function Remove-CSNetworkOffering {
    <#
    .SYNOPSIS
        Deletes a network offering.

    .DESCRIPTION
        Wraps deleteNetworkOffering. An offering that networks still use cannot be
        deleted; disable it with Set-CSNetworkOffering -State Disabled instead.
        Accepts offering objects from Get-CSNetworkOffering on the pipeline.

    .PARAMETER Id
        The ID of the offering to delete (binds from a piped offering's id)

    .EXAMPLE
        Remove-CSNetworkOffering -Id offering-uuid
        Deletes an offering after prompting for confirmation.

    .EXAMPLE
        Get-CSNetworkOffering -State Disabled -Keyword 'test-' | Remove-CSNetworkOffering -Confirm:$false
        Deletes every disabled test offering.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$Id
    )

    process {
        if ($PSCmdlet.ShouldProcess("network offering $Id", 'Delete')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'deleteNetworkOffering' -Parameters @{ id = $Id }) -Command 'deleteNetworkOffering'
        }
    }
}