Public/network-ipam.ps1

function Get-CSGuestNetworkIpv6Prefix {
    <#
    .SYNOPSIS
        Lists guest network IPv6 prefixes.

    .DESCRIPTION
        Returns the IPv6 prefixes that zones allocate guest network /64 subnets
        from (listGuestNetworkIpv6Prefixes).

    .PARAMETER Id
        Filter by prefix ID

    .PARAMETER ZoneId
        Filter by zone ID

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSGuestNetworkIpv6Prefix -ZoneId zone-uuid
        Lists the IPv6 prefixes of a zone, with their used and available subnet counts.
    #>

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

        [string]$ZoneId,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        Id = 'id'; ZoneId = 'zoneid'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
    })
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listGuestNetworkIpv6Prefixes' -Parameters $apiParams) -Command 'listGuestNetworkIpv6Prefixes'
}

function New-CSGuestNetworkIpv6Prefix {
    <#
    .SYNOPSIS
        Adds a guest network IPv6 prefix to a zone.

    .DESCRIPTION
        Adds an IPv6 prefix (/56 or larger) that the zone carves guest network
        /64 subnets from (createGuestNetworkIpv6Prefix). This is an asynchronous
        job; use -Wait to get the new prefix back instead of the job handle.

    .PARAMETER ZoneId
        The zone the prefix belongs to (required)

    .PARAMETER Prefix
        The IPv6 CIDR, /56 or larger, e.g. 2001:db8:100::/56 (required)

    .PARAMETER Wait
        Wait for the async job to finish and return the new prefix

    .EXAMPLE
        New-CSGuestNetworkIpv6Prefix -ZoneId zone-uuid -Prefix '2001:db8:100::/56' -Wait
        Adds a /56 guest prefix (256 guest /64 subnets) to a zone and returns it.
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ZoneId,

        [Parameter(Mandatory = $true)]
        [string]$Prefix,

        [switch]$Wait
    )

    if ($PSCmdlet.ShouldProcess("zone $ZoneId", "Add guest IPv6 prefix $Prefix")) {
        Invoke-CSAsyncApiRequest -Command 'createGuestNetworkIpv6Prefix' -Parameters @{ zoneid = $ZoneId; prefix = $Prefix } -Wait:$Wait
    }
}

function Remove-CSGuestNetworkIpv6Prefix {
    <#
    .SYNOPSIS
        Deletes a guest network IPv6 prefix.

    .DESCRIPTION
        Deletes a guest network IPv6 prefix (deleteGuestNetworkIpv6Prefix). This
        is an asynchronous job; use -Wait to block until it finishes. Accepts
        objects from Get-CSGuestNetworkIpv6Prefix on the pipeline.

    .PARAMETER Id
        The prefix ID (required; binds from a piped prefix's id)

    .PARAMETER Wait
        Wait for the async job to finish and return its result

    .EXAMPLE
        Remove-CSGuestNetworkIpv6Prefix -Id prefix-uuid
        Deletes a prefix after prompting for confirmation.

    .EXAMPLE
        Get-CSGuestNetworkIpv6Prefix -ZoneId zone-uuid | Where-Object prefix -eq '2001:db8:100::/56' | Remove-CSGuestNetworkIpv6Prefix -Confirm:$false
        Deletes a specific prefix from a zone without prompting.
    #>

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

        [switch]$Wait
    )

    process {
        if ($PSCmdlet.ShouldProcess("guest network IPv6 prefix $Id", 'Delete')) {
            Invoke-CSAsyncApiRequest -Command 'deleteGuestNetworkIpv6Prefix' -Parameters @{ id = $Id } -Wait:$Wait
        }
    }
}

function Get-CSIpv4SubnetForGuestNetwork {
    <#
    .SYNOPSIS
        Lists IPv4 subnets for guest networks.

    .DESCRIPTION
        Returns the IPv4 subnets carved out of zone IPv4 subnets for ROUTED guest
        networks and VPCs (listIpv4SubnetsForGuestNetwork).

    .PARAMETER Id
        Filter by subnet ID

    .PARAMETER ZoneId
        Filter by zone ID

    .PARAMETER ParentId
        Filter by the zone IPv4 subnet the subnet was carved from

    .PARAMETER Subnet
        Filter by CIDR, e.g. 10.10.0.0/26

    .PARAMETER NetworkId
        Filter by the network the subnet is associated with

    .PARAMETER VpcId
        Filter by the VPC the subnet is associated with

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSIpv4SubnetForGuestNetwork -ZoneId zone-uuid
        Lists every guest IPv4 subnet in a zone.

    .EXAMPLE
        Get-CSIpv4SubnetForGuestNetwork -NetworkId net-uuid
        Shows the IPv4 subnet a ROUTED network is using.
    #>

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

        [string]$ZoneId,

        [string]$ParentId,

        [string]$Subnet,

        [string]$NetworkId,

        [string]$VpcId,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        Id = 'id'; ZoneId = 'zoneid'; ParentId = 'parentid'; Subnet = 'subnet'; NetworkId = 'networkid'
        VpcId = 'vpcid'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
    })
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listIpv4SubnetsForGuestNetwork' -Parameters $apiParams) -Command 'listIpv4SubnetsForGuestNetwork'
}

function New-CSIpv4SubnetForGuestNetwork {
    <#
    .SYNOPSIS
        Creates an IPv4 subnet for guest networks from a zone IPv4 subnet.

    .DESCRIPTION
        Carves a guest network IPv4 subnet out of a zone IPv4 subnet
        (createIpv4SubnetForGuestNetwork). Give either an explicit -Subnet CIDR or
        a -CidrSize and let CloudStack pick the next free block. This is an
        asynchronous job; use -Wait to get the new subnet back. Accepts zone
        subnet objects from Get-CSIpv4SubnetForZone on the pipeline.

    .PARAMETER ParentId
        The zone IPv4 subnet to carve from (required; binds from a piped zone subnet's id)

    .PARAMETER Subnet
        The exact CIDR to create, e.g. 10.10.0.64/26. Cannot be used with -CidrSize.

    .PARAMETER CidrSize
        The prefix length to allocate, e.g. 26. Cannot be used with -Subnet.

    .PARAMETER Wait
        Wait for the async job to finish and return the new subnet

    .EXAMPLE
        New-CSIpv4SubnetForGuestNetwork -ParentId zone-subnet-uuid -Subnet '10.10.0.64/26'
        Creates a specific /26 guest subnet.

    .EXAMPLE
        Get-CSIpv4SubnetForZone -ZoneId zone-uuid -Subnet '10.10.0.0/16' | New-CSIpv4SubnetForGuestNetwork -CidrSize 24 -Wait
        Allocates the next free /24 from a zone subnet and returns it.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'BySubnet')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Id')]
        [string]$ParentId,

        [Parameter(Mandatory = $true, ParameterSetName = 'BySubnet')]
        [string]$Subnet,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByCidrSize')]
        [ValidateRange(8, 32)]
        [int]$CidrSize,

        [switch]$Wait
    )

    process {
        $apiParams = @{ parentid = $ParentId }
        if ($PSCmdlet.ParameterSetName -eq 'BySubnet') {
            $apiParams.subnet = $Subnet
            $what = $Subnet
        }
        else {
            $apiParams.cidrsize = $CidrSize
            $what = "a /$CidrSize"
        }
        if ($PSCmdlet.ShouldProcess("zone IPv4 subnet $ParentId", "Create guest subnet $what")) {
            Invoke-CSAsyncApiRequest -Command 'createIpv4SubnetForGuestNetwork' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Remove-CSIpv4SubnetForGuestNetwork {
    <#
    .SYNOPSIS
        Deletes an IPv4 subnet for guest networks.

    .DESCRIPTION
        Deletes a guest network IPv4 subnet (deleteIpv4SubnetForGuestNetwork).
        This is an asynchronous job; use -Wait to block until it finishes. Accepts
        objects from Get-CSIpv4SubnetForGuestNetwork on the pipeline.

    .PARAMETER Id
        The guest subnet ID (required; binds from a piped subnet's id)

    .PARAMETER Wait
        Wait for the async job to finish and return its result

    .EXAMPLE
        Remove-CSIpv4SubnetForGuestNetwork -Id subnet-uuid
        Deletes a guest subnet after prompting for confirmation.

    .EXAMPLE
        Get-CSIpv4SubnetForGuestNetwork -ZoneId zone-uuid | Where-Object { -not $_.networkid -and -not $_.vpcid } | Remove-CSIpv4SubnetForGuestNetwork -Confirm:$false
        Deletes every unused guest subnet in a zone without prompting.
    #>

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

        [switch]$Wait
    )

    process {
        if ($PSCmdlet.ShouldProcess("guest IPv4 subnet $Id", 'Delete')) {
            Invoke-CSAsyncApiRequest -Command 'deleteIpv4SubnetForGuestNetwork' -Parameters @{ id = $Id } -Wait:$Wait
        }
    }
}

function Get-CSStorageNetworkIpRange {
    <#
    .SYNOPSIS
        Lists storage network IP ranges.

    .DESCRIPTION
        Returns the IP ranges that system VMs use on the storage network
        (listStorageNetworkIpRange). Filters are applied in order of precedence:
        -Id, then -PodId, then -ZoneId.

    .PARAMETER Id
        Filter by IP range ID

    .PARAMETER PodId
        Filter by pod ID (ignored when -Id is given)

    .PARAMETER ZoneId
        Filter by zone ID (ignored when -Id or -PodId is given)

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSStorageNetworkIpRange -ZoneId zone-uuid
        Lists every storage network IP range in a zone.

    .EXAMPLE
        Get-CSStorageNetworkIpRange -PodId pod-uuid
        Lists the storage network IP ranges of one pod.
    #>

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

        [string]$PodId,

        [string]$ZoneId,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        Id = 'id'; PodId = 'podid'; ZoneId = 'zoneid'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
    })
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listStorageNetworkIpRange' -Parameters $apiParams) -Command 'listStorageNetworkIpRange'
}

function New-CSStorageNetworkIpRange {
    <#
    .SYNOPSIS
        Creates a storage network IP range in a pod.

    .DESCRIPTION
        Adds an IP range that system VMs use to reach secondary storage over a
        dedicated storage network (createStorageNetworkIpRange). This is an
        asynchronous job; use -Wait to get the new range back.

    .PARAMETER PodId
        The pod the range belongs to (required)

    .PARAMETER StartIp
        The first IP address of the range (required)

    .PARAMETER EndIp
        The last IP address of the range

    .PARAMETER Gateway
        The storage network gateway (required)

    .PARAMETER Netmask
        The storage network netmask (required)

    .PARAMETER Vlan
        The VLAN the range sits on. Mainly needed for VMware; other hypervisors
        take the bridge from the Storage traffic type.

    .PARAMETER Wait
        Wait for the async job to finish and return the new range

    .EXAMPLE
        New-CSStorageNetworkIpRange -PodId pod-uuid -StartIp 172.16.50.10 -EndIp 172.16.50.50 -Gateway 172.16.50.1 -Netmask 255.255.255.0 -Wait
        Adds a storage network range to a pod and returns it.

    .EXAMPLE
        New-CSStorageNetworkIpRange -PodId pod-uuid -StartIp 172.16.60.10 -EndIp 172.16.60.50 -Gateway 172.16.60.1 -Netmask 255.255.255.0 -Vlan 60
        Adds a range on VLAN 60 (VMware).
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param(
        [Parameter(Mandatory = $true)]
        [string]$PodId,

        [Parameter(Mandatory = $true)]
        [string]$StartIp,

        [string]$EndIp,

        [Parameter(Mandatory = $true)]
        [string]$Gateway,

        [Parameter(Mandatory = $true)]
        [string]$Netmask,

        [string]$Vlan,

        [switch]$Wait
    )

    $apiParams = @{ podid = $PodId; startip = $StartIp; gateway = $Gateway; netmask = $Netmask }
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        EndIp = 'endip'; Vlan = 'vlan'
    })
    $range = if ($EndIp) { "$StartIp-$EndIp" } else { $StartIp }
    if ($PSCmdlet.ShouldProcess("pod $PodId", "Create storage network IP range $range")) {
        Invoke-CSAsyncApiRequest -Command 'createStorageNetworkIpRange' -Parameters $apiParams -Wait:$Wait
    }
}

function Set-CSStorageNetworkIpRange {
    <#
    .SYNOPSIS
        Updates a storage network IP range.

    .DESCRIPTION
        Changes the addresses, netmask, or VLAN of a storage network IP range
        (updateStorageNetworkIpRange). This is an asynchronous job; use -Wait to
        get the updated range back. Accepts objects from
        Get-CSStorageNetworkIpRange on the pipeline.

    .PARAMETER Id
        The IP range ID (required; binds from a piped range's id)

    .PARAMETER StartIp
        The new first IP address

    .PARAMETER EndIp
        The new last IP address

    .PARAMETER Netmask
        The new netmask

    .PARAMETER Vlan
        The new VLAN

    .PARAMETER Wait
        Wait for the async job to finish and return the updated range

    .EXAMPLE
        Set-CSStorageNetworkIpRange -Id range-uuid -EndIp 172.16.50.100
        Extends a storage network range.

    .EXAMPLE
        Get-CSStorageNetworkIpRange -PodId pod-uuid | Set-CSStorageNetworkIpRange -Vlan 61 -Wait
        Moves every storage range in a pod to VLAN 61.
    #>

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

        [string]$StartIp,

        [string]$EndIp,

        [string]$Netmask,

        [string]$Vlan,

        [switch]$Wait
    )

    process {
        $apiParams = @{ id = $Id }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            StartIp = 'startip'; EndIp = 'endip'; Netmask = 'netmask'; Vlan = 'vlan'
        })
        if ($PSCmdlet.ShouldProcess("storage network IP range $Id", 'Update')) {
            Invoke-CSAsyncApiRequest -Command 'updateStorageNetworkIpRange' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Remove-CSStorageNetworkIpRange {
    <#
    .SYNOPSIS
        Deletes a storage network IP range.

    .DESCRIPTION
        Deletes a storage network IP range (deleteStorageNetworkIpRange). This is
        an asynchronous job; use -Wait to block until it finishes. Accepts objects
        from Get-CSStorageNetworkIpRange on the pipeline.

    .PARAMETER Id
        The IP range ID (required; binds from a piped range's id)

    .PARAMETER Wait
        Wait for the async job to finish and return its result

    .EXAMPLE
        Remove-CSStorageNetworkIpRange -Id range-uuid
        Deletes a range after prompting for confirmation.

    .EXAMPLE
        Get-CSStorageNetworkIpRange -PodId pod-uuid | Remove-CSStorageNetworkIpRange -Confirm:$false -Wait
        Deletes every storage range in a pod without prompting.
    #>

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

        [switch]$Wait
    )

    process {
        if ($PSCmdlet.ShouldProcess("storage network IP range $Id", 'Delete')) {
            Invoke-CSAsyncApiRequest -Command 'deleteStorageNetworkIpRange' -Parameters @{ id = $Id } -Wait:$Wait
        }
    }
}

function Set-CSPublicIpRangeDedicated {
    <#
    .SYNOPSIS
        Dedicates a public IP range to a domain, account, or project.

    .DESCRIPTION
        Reserves a public VLAN IP range for one domain/account/project
        (dedicatePublicIpRange). Release it again with
        Clear-CSPublicIpRangeDedicated. Accepts objects with an id property (e.g.
        from listVlanIpRanges) on the pipeline.

    .PARAMETER Id
        The ID of the public VLAN IP range (required; binds from a piped range's id)

    .PARAMETER DomainId
        The domain that will own the range (required)

    .PARAMETER Account
        The account that will own the range

    .PARAMETER ProjectId
        The project that will own the range

    .EXAMPLE
        Set-CSPublicIpRangeDedicated -Id vlanrange-uuid -DomainId dom-uuid -Account 'customer-a'
        Dedicates a public IP range to one account.

    .EXAMPLE
        Set-CSPublicIpRangeDedicated -Id vlanrange-uuid -DomainId dom-uuid -ProjectId proj-uuid
        Dedicates a public IP range to a project.
    #>

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

        [Parameter(Mandatory = $true)]
        [string]$DomainId,

        [string]$Account,

        [string]$ProjectId
    )

    process {
        $apiParams = @{ id = $Id; domainid = $DomainId }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Account = 'account'; ProjectId = 'projectid'
        })
        if ($PSCmdlet.ShouldProcess("public IP range $Id", 'Dedicate')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'dedicatePublicIpRange' -Parameters $apiParams) -Command 'dedicatePublicIpRange'
        }
    }
}

function Clear-CSPublicIpRangeDedicated {
    <#
    .SYNOPSIS
        Releases a dedicated public IP range back to the system pool.

    .DESCRIPTION
        Releases a public IP range previously dedicated with
        Set-CSPublicIpRangeDedicated so any account can use it again
        (releasePublicIpRange). Accepts objects with an id property on the pipeline.

    .PARAMETER Id
        The ID of the public IP range (required; binds from a piped range's id)

    .EXAMPLE
        Clear-CSPublicIpRangeDedicated -Id vlanrange-uuid
        Returns a dedicated range to the system pool.

    .EXAMPLE
        Clear-CSPublicIpRangeDedicated -Id vlanrange-uuid -WhatIf
        Shows which range would be released without releasing it.
    #>

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

    process {
        if ($PSCmdlet.ShouldProcess("public IP range $Id", 'Release to system pool')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'releasePublicIpRange' -Parameters @{ id = $Id }) -Command 'releasePublicIpRange'
        }
    }
}