Public/network.ps1

function Get-CSNetwork {
    <#
    .SYNOPSIS
        Lists virtual machines in CloudStack.
    
    .DESCRIPTION
        Retrieves a list of virtual machines with optional filtering by ID, name,
        zone, state, or other parameters.
    
    .PARAMETER Id
        Filter by VM ID
    
    .PARAMETER Name
        Filter by VM name (exact match)
    
    .PARAMETER Keyword
        Filter by keyword (partial match on name)
    
    .PARAMETER ZoneId
        Filter by zone ID
    
    .PARAMETER State
        Filter by VM state (Running, Stopped, etc.)
    
    .PARAMETER Account
        Filter by account name
    
    .PARAMETER DomainId
        Filter by domain ID
    
    .PARAMETER ListAll
        List all VMs (requires appropriate permissions)
    
    .EXAMPLE
        Get-CSNetwork
        Lists all VMs in your account
    
    .EXAMPLE
        Get-CSNetwork -Name "web-server-01"
        Gets a specific VM by name
    
    .EXAMPLE
        Get-CSNetwork -State Running
        Lists all running VMs
    
    .EXAMPLE
        Get-CSNetwork -Keyword "web"
        Lists all VMs with "web" in their name
    #>

    [CmdletBinding(DefaultParameterSetName='Default')]
    param(
        [Parameter(ParameterSetName='ById')]
        [string]$Id,
        
        [Parameter(ParameterSetName='ByName')]
        [string]$Name,
        
        [Parameter(ParameterSetName='Default')]
        [string]$Keyword,
        
        [Parameter(ParameterSetName='Default')]
        [string]$ZoneId,
        
        [Parameter(ParameterSetName='Default')]
        [ValidateSet('Running', 'Stopped', 'Starting', 'Stopping', 'Present', 'Destroyed', 'Expunging', 'Migrating', 'Error', 'Unknown', 'Shutdowned')]
        [string]$State,
        
        [Parameter(ParameterSetName='Default')]
        [string]$Account,
        
        [Parameter(ParameterSetName='Default')]
        [string]$DomainId,
        
        [Parameter(ParameterSetName='Default')]
        [switch]$ListAll
    )
    
    # Build parameters
    $apiParams = @{}
    
    if ($PSBoundParameters.ContainsKey('Id')) {
        $apiParams['id'] = $Id
    }
    
    if ($PSBoundParameters.ContainsKey('Name')) {
        $apiParams['name'] = $Name
    }
    
    if ($PSBoundParameters.ContainsKey('Keyword')) {
        $apiParams['keyword'] = $Keyword
    }
    
    if ($PSBoundParameters.ContainsKey('ZoneId')) {
        $apiParams['zoneid'] = $ZoneId
    }
    
    if ($PSBoundParameters.ContainsKey('State')) {
        $apiParams['state'] = $State
    }
    
    if ($PSBoundParameters.ContainsKey('Account')) {
        $apiParams['account'] = $Account
    }
    
    if ($PSBoundParameters.ContainsKey('DomainId')) {
        $apiParams['domainid'] = $DomainId
    }
    
    if ($ListAll) {
        $apiParams['listall'] = 'true'
    }
    
    # Make the API call
    $response = Invoke-CSApiRequest -Command 'listNetworks' -Parameters $apiParams
    write-verbose $apiParams
    # Return the VM list
    if ($response.listNetworksresponse.Network) {
        return $response.listNetworksresponse.Network
    }
    else {
        Write-Verbose "No virtual machines found matching the criteria."
        return $null
    }
}

function New-CSNetwork {
    <#
    .SYNOPSIS
        Creates a guest network in CloudStack.

    .DESCRIPTION
        Creates an isolated, shared, or L2 guest network (createNetwork). The
        network type comes from the network offering. Shared networks and VPC
        tiers also need -Gateway and -Netmask; isolated networks normally get
        their addressing from the zone.

    .PARAMETER Name
        The name of the network (required)

    .PARAMETER NetworkOfferingId
        The network offering ID; determines whether the network is isolated, shared or L2 (required)

    .PARAMETER ZoneId
        The zone ID for the network (required)

    .PARAMETER DisplayText
        The display text of the network

    .PARAMETER Account
        Account that will own the network. Must be used with -DomainId.

    .PARAMETER DomainId
        Domain ID of the account owning the network. With -AclType Domain and no
        -Account, the network is created for the whole domain.

    .PARAMETER ProjectId
        An optional project for the network

    .PARAMETER AclType
        Access control type: Account (only the owner can use it) or Domain (all accounts
        in the domain). Shared networks should use Domain, isolated networks Account.

    .PARAMETER SubdomainAccess
        Whether subdomains may use a network dedicated to their parent domain. Use with -AclType Domain.

    .PARAMETER PhysicalNetworkId
        The physical network ID the network belongs to

    .PARAMETER Vlan
        The ID or VID of the network (e.g. 100 or vlan://100)

    .PARAMETER BypassVlanOverlapCheck
        Bypass the VLAN ID/range overlap check (shared and L2 networks)

    .PARAMETER IsolatedPvlan
        The isolated private VLAN for this network

    .PARAMETER IsolatedPvlanType
        The private VLAN type: community, isolated, or promiscuous

    .PARAMETER Gateway
        IPv4 gateway. Required for shared networks and VPC tiers.

    .PARAMETER Netmask
        IPv4 netmask. Required for shared networks and VPC tiers.

    .PARAMETER StartIp
        The beginning IPv4 address of the network IP range

    .PARAMETER EndIp
        The ending IPv4 address of the network IP range (defaults to -StartIp)

    .PARAMETER CidrSize
        The CIDR size of the IPv4 network. Required for regular users creating ROUTED isolated networks.

    .PARAMETER Dns1
        The first IPv4 DNS server for the network

    .PARAMETER Dns2
        The second IPv4 DNS server for the network

    .PARAMETER NetworkDomain
        The DNS domain for the network (e.g. app.internal)

    .PARAMETER Ip6Gateway
        IPv6 gateway. Required for shared IPv6 networks.

    .PARAMETER Ip6Cidr
        The IPv6 CIDR of the network, at least /64

    .PARAMETER StartIpv6
        The beginning IPv6 address of the network range

    .PARAMETER EndIpv6
        The ending IPv6 address of the network range

    .PARAMETER Ip6Dns1
        The first IPv6 DNS server for the network

    .PARAMETER Ip6Dns2
        The second IPv6 DNS server for the network

    .PARAMETER RouterIp
        IPv4 address for the virtual router in a shared network

    .PARAMETER RouterIpv6
        IPv6 address for the virtual router in a shared network

    .PARAMETER SourceNatIpAddress
        Public IPv4 address to use as the router's source NAT address. If it cannot be
        acquired the network is not implemented.

    .PARAMETER VpcId
        The VPC the network (tier) belongs to

    .PARAMETER AclId
        Network ACL ID to associate with a VPC tier

    .PARAMETER AssociatedNetworkId
        The network this network is associated with (shared networks only)

    .PARAMETER PublicMtu
        MTU for the virtual router's public interfaces

    .PARAMETER PrivateMtu
        MTU for the virtual router's private interfaces

    .PARAMETER AsNumber
        The BGP AS number of the network (ROUTED networks with dynamic routing)

    .PARAMETER BgpPeerIds
        IDs of the BGP peers for the network

    .PARAMETER DisplayNetwork
        Whether to display the network to the end user

    .PARAMETER HideIpAddressUsage
        Do not export IP address usage for this network to listUsageRecords

    .PARAMETER ExternalId
        ID of the network in an external system

    .PARAMETER TungstenVirtualRouterUuid
        Tungsten-Fabric virtual router the network belongs to

    .EXAMPLE
        New-CSNetwork -Name 'app-tier' -DisplayText 'Application tier' -NetworkOfferingId off-uuid -ZoneId zone-uuid
        Creates an isolated network owned by the calling account; addressing comes from the zone.

    .EXAMPLE
        New-CSNetwork -Name 'VL_3217' -NetworkOfferingId shared-off-uuid -ZoneId zone-uuid -PhysicalNetworkId pn-uuid -Vlan 3217 -Gateway 10.32.17.1 -Netmask 255.255.255.0 -StartIp 10.32.17.10 -EndIp 10.32.17.250 -AclType Domain -DomainId dom-uuid
        Creates a shared VLAN 3217 network available to every account in the domain.

    .EXAMPLE
        New-CSNetwork -Name 'web' -NetworkOfferingId tier-off-uuid -ZoneId zone-uuid -VpcId vpc-uuid -Gateway 10.1.1.1 -Netmask 255.255.255.0 -AclId acl-uuid
        Creates a VPC tier with an explicit network ACL.

    .EXAMPLE
        New-CSNetwork -Name 'customer-a' -NetworkOfferingId off-uuid -ZoneId zone-uuid -Account 'customer-a' -DomainId dom-uuid -NetworkDomain 'customer-a.internal' -Dns1 1.1.1.1 -Dns2 8.8.8.8
        Creates an isolated network on behalf of another account with custom DNS settings.
    #>

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

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

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

        [string]$DisplayText,

        [string]$Account,

        [string]$DomainId,

        [string]$ProjectId,

        [ValidateSet('Account', 'Domain')]
        [string]$AclType,

        [bool]$SubdomainAccess,

        [string]$PhysicalNetworkId,

        [string]$Vlan,

        [switch]$BypassVlanOverlapCheck,

        [string]$IsolatedPvlan,

        [ValidateSet('community', 'isolated', 'promiscuous')]
        [string]$IsolatedPvlanType,

        [string]$Gateway,

        [string]$Netmask,

        [string]$StartIp,

        [string]$EndIp,

        [ValidateRange(8, 32)]
        [int]$CidrSize,

        [string]$Dns1,

        [string]$Dns2,

        [string]$NetworkDomain,

        [string]$Ip6Gateway,

        [string]$Ip6Cidr,

        [string]$StartIpv6,

        [string]$EndIpv6,

        [string]$Ip6Dns1,

        [string]$Ip6Dns2,

        [string]$RouterIp,

        [string]$RouterIpv6,

        [string]$SourceNatIpAddress,

        [string]$VpcId,

        [string]$AclId,

        [string]$AssociatedNetworkId,

        [ValidateRange(68, 65535)]
        [int]$PublicMtu,

        [ValidateRange(68, 65535)]
        [int]$PrivateMtu,

        [long]$AsNumber,

        [string[]]$BgpPeerIds,

        [bool]$DisplayNetwork,

        [switch]$HideIpAddressUsage,

        [string]$ExternalId,

        [string]$TungstenVirtualRouterUuid
    )

    $apiParams = @{
        name              = $Name
        networkofferingid = $NetworkOfferingId
        zoneid            = $ZoneId
    }
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        DisplayText = 'displaytext'; Account = 'account'; DomainId = 'domainid'; ProjectId = 'projectid'
        AclType = 'acltype'; SubdomainAccess = 'subdomainaccess'; PhysicalNetworkId = 'physicalnetworkid'
        Vlan = 'vlan'; BypassVlanOverlapCheck = 'bypassvlanoverlapcheck'; IsolatedPvlan = 'isolatedpvlan'
        IsolatedPvlanType = 'isolatedpvlantype'; Gateway = 'gateway'; Netmask = 'netmask'; StartIp = 'startip'
        EndIp = 'endip'; CidrSize = 'cidrsize'; Dns1 = 'dns1'; Dns2 = 'dns2'; NetworkDomain = 'networkdomain'
        Ip6Gateway = 'ip6gateway'; Ip6Cidr = 'ip6cidr'; StartIpv6 = 'startipv6'; EndIpv6 = 'endipv6'
        Ip6Dns1 = 'ip6dns1'; Ip6Dns2 = 'ip6dns2'; RouterIp = 'routerip'; RouterIpv6 = 'routeripv6'
        SourceNatIpAddress = 'sourcenatipaddress'; VpcId = 'vpcid'; AclId = 'aclid'
        AssociatedNetworkId = 'associatednetworkid'; PublicMtu = 'publicmtu'; PrivateMtu = 'privatemtu'
        AsNumber = 'asnumber'; BgpPeerIds = 'bgppeerids'; DisplayNetwork = 'displaynetwork'
        HideIpAddressUsage = 'hideipaddressusage'; ExternalId = 'externalid'
        TungstenVirtualRouterUuid = 'tungstenvirtualrouteruuid'
    })

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

function Set-CSNetwork {
    <#
    .SYNOPSIS
        Updates a guest network.

    .DESCRIPTION
        Changes the name, DNS, MTU, offering, guest CIDR, or other settings of an
        existing network (updateNetwork). This is an asynchronous job; use -Wait to
        get the updated network back instead of the job handle. Accepts network
        objects from Get-CSNetwork on the pipeline.

    .PARAMETER Id
        The ID of the network to update (required; binds from a piped network's id)

    .PARAMETER Name
        The new name for the network

    .PARAMETER DisplayText
        The new display text for the network

    .PARAMETER NetworkOfferingId
        Move the network to a different network offering

    .PARAMETER GuestVmCidr
        CIDR for guest VMs; CloudStack allocates guest IPs only from this CIDR

    .PARAMETER ChangeCidr
        Force the update even if the CIDR type is different

    .PARAMETER NetworkDomain
        The DNS domain for the network

    .PARAMETER Dns1
        The first IPv4 DNS server for the network

    .PARAMETER Dns2
        The second IPv4 DNS server for the network

    .PARAMETER Ip6Dns1
        The first IPv6 DNS server for the network

    .PARAMETER Ip6Dns2
        The second IPv6 DNS server for the network

    .PARAMETER PublicMtu
        MTU for the virtual router's public interfaces

    .PARAMETER PrivateMtu
        MTU for the virtual router's private interfaces

    .PARAMETER SourceNatIpAddress
        New source NAT address; must already be acquired for this network

    .PARAMETER DisplayNetwork
        Whether to display the network to the end user

    .PARAMETER HideIpAddressUsage
        Whether to stop exporting IP address usage for this network

    .PARAMETER CustomId
        A custom ID for the resource (root admins only)

    .PARAMETER Forced
        Force the update even if backend commands fail

    .PARAMETER UpdateInSequence
        Update redundant routers one after the other (virtual router provider only)

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

    .EXAMPLE
        Set-CSNetwork -Id net-uuid -Name 'app-tier-v2' -DisplayText 'Application tier (v2)'
        Renames a network.

    .EXAMPLE
        Get-CSNetwork -Name 'app-tier' | Set-CSNetwork -Dns1 10.0.0.53 -Dns2 10.0.1.53 -Wait
        Sets custom DNS servers on a network found by name and waits for the result.

    .EXAMPLE
        Set-CSNetwork -Id net-uuid -NetworkOfferingId redundant-off-uuid -UpdateInSequence -Wait
        Moves a network to a redundant-router offering, updating the routers one at a time.
    #>

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

        [string]$Name,

        [string]$DisplayText,

        [string]$NetworkOfferingId,

        [string]$GuestVmCidr,

        [switch]$ChangeCidr,

        [string]$NetworkDomain,

        [string]$Dns1,

        [string]$Dns2,

        [string]$Ip6Dns1,

        [string]$Ip6Dns2,

        [ValidateRange(68, 65535)]
        [int]$PublicMtu,

        [ValidateRange(68, 65535)]
        [int]$PrivateMtu,

        [string]$SourceNatIpAddress,

        [bool]$DisplayNetwork,

        [bool]$HideIpAddressUsage,

        [string]$CustomId,

        [switch]$Forced,

        [switch]$UpdateInSequence,

        [switch]$Wait
    )

    process {
        $apiParams = @{ id = $Id }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Name = 'name'; DisplayText = 'displaytext'; NetworkOfferingId = 'networkofferingid'
            GuestVmCidr = 'guestvmcidr'; ChangeCidr = 'changecidr'; NetworkDomain = 'networkdomain'
            Dns1 = 'dns1'; Dns2 = 'dns2'; Ip6Dns1 = 'ip6dns1'; Ip6Dns2 = 'ip6dns2'
            PublicMtu = 'publicmtu'; PrivateMtu = 'privatemtu'; SourceNatIpAddress = 'sourcenatipaddress'
            DisplayNetwork = 'displaynetwork'; HideIpAddressUsage = 'hideipaddressusage'; CustomId = 'customid'
            Forced = 'forced'; UpdateInSequence = 'updateinsequence'
        })
        if ($PSCmdlet.ShouldProcess("network $Id", 'Update')) {
            Invoke-CSAsyncApiRequest -Command 'updateNetwork' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Remove-CSNetwork {
    <#
    .SYNOPSIS
        Deletes a guest network.

    .DESCRIPTION
        Deletes a network (deleteNetwork). The network must have no VMs attached
        unless -Forced is used. This is an asynchronous job; use -Wait to block
        until it finishes. Accepts network objects from Get-CSNetwork on the pipeline.

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

    .PARAMETER Forced
        Mark the network as destroyed even if the backend shutdown/cleanup fails

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

    .EXAMPLE
        Remove-CSNetwork -Id net-uuid
        Deletes a network after prompting for confirmation.

    .EXAMPLE
        Get-CSNetwork -Keyword 'temp-' | Remove-CSNetwork -Confirm:$false -Wait
        Deletes every network whose name contains 'temp-' without prompting, one at a time.

    .EXAMPLE
        Remove-CSNetwork -Id net-uuid -Forced -WhatIf
        Shows what a forced delete would do without doing it.
    #>

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

        [switch]$Forced,

        [switch]$Wait
    )

    process {
        $apiParams = @{ id = $Id }
        if ($Forced) { $apiParams.forced = 'true' }
        if ($PSCmdlet.ShouldProcess("network $Id", 'Delete')) {
            Invoke-CSAsyncApiRequest -Command 'deleteNetwork' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Restart-CSNetwork {
    <#
    .SYNOPSIS
        Restarts a guest network.

    .DESCRIPTION
        Restarts a network (restartNetwork), re-applying its rules on the virtual
        router(s). With -Cleanup the routers are destroyed and recreated. This is
        an asynchronous job; use -Wait to block until it finishes. Accepts network
        objects from Get-CSNetwork on the pipeline.

    .PARAMETER Id
        The ID of the network to restart (required; binds from a piped network's id)

    .PARAMETER Cleanup
        Destroy and recreate the network elements (virtual routers)

    .PARAMETER LivePatch
        Live patch the router software before restarting. Only applies without -Cleanup.

    .PARAMETER MakeRedundant
        Turn the network into a redundant-router network

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

    .EXAMPLE
        Restart-CSNetwork -Id net-uuid
        Restarts a network in place.

    .EXAMPLE
        Get-CSNetwork -Name 'app-tier' | Restart-CSNetwork -Cleanup -Wait
        Recreates the network's virtual router and waits for it to finish.

    .EXAMPLE
        Restart-CSNetwork -Id net-uuid -MakeRedundant -Cleanup
        Converts a network to redundant virtual routers.
    #>

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

        [switch]$Cleanup,

        [switch]$LivePatch,

        [switch]$MakeRedundant,

        [switch]$Wait
    )

    process {
        $apiParams = @{ id = $Id }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Cleanup = 'cleanup'; LivePatch = 'livepatch'; MakeRedundant = 'makeredundant'
        })
        if ($PSCmdlet.ShouldProcess("network $Id", 'Restart')) {
            Invoke-CSAsyncApiRequest -Command 'restartNetwork' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Move-CSNetwork {
    <#
    .SYNOPSIS
        Migrates a network to a different network offering.

    .DESCRIPTION
        Migrates a network to another network offering (migrateNetwork), for
        example to move to a different provider. This is an asynchronous job; use
        -Wait to block until it finishes. Accepts network objects from
        Get-CSNetwork on the pipeline.

    .PARAMETER NetworkId
        The ID of the network to migrate (required; binds from a piped network's id)

    .PARAMETER NetworkOfferingId
        The network offering to migrate to (required)

    .PARAMETER Resume
        Resume a previous migration that failed

    .PARAMETER Wait
        Wait for the async job to finish and return the migrated network

    .EXAMPLE
        Move-CSNetwork -NetworkId net-uuid -NetworkOfferingId new-off-uuid -Wait
        Migrates a network to a new offering and waits for completion.

    .EXAMPLE
        Get-CSNetwork -Name 'legacy-net' | Move-CSNetwork -NetworkOfferingId new-off-uuid -Resume
        Resumes a previously failed migration of a network found by name.
    #>

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

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

        [switch]$Resume,

        [switch]$Wait
    )

    process {
        $apiParams = @{ networkid = $NetworkId; networkofferingid = $NetworkOfferingId }
        if ($Resume) { $apiParams.resume = 'true' }
        if ($PSCmdlet.ShouldProcess("network $NetworkId", "Migrate to offering $NetworkOfferingId")) {
            Invoke-CSAsyncApiRequest -Command 'migrateNetwork' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Set-CSNetworkBgpPeer {
    <#
    .SYNOPSIS
        Changes the BGP peers linked to a network.

    .DESCRIPTION
        Replaces the set of BGP peers for a ROUTED network (changeBgpPeersForNetwork).
        Calling it without -BgpPeerIds unlinks all BGP peers. This is an
        asynchronous job; use -Wait to block until it finishes. Accepts network
        objects from Get-CSNetwork on the pipeline.

    .PARAMETER NetworkId
        The ID of the network (required; binds from a piped network's id)

    .PARAMETER BgpPeerIds
        IDs of the BGP peers to link. Omit to unlink all BGP peers.

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

    .EXAMPLE
        Set-CSNetworkBgpPeer -NetworkId net-uuid -BgpPeerIds peer-1-uuid, peer-2-uuid
        Links two BGP peers to a network, replacing any existing peers.

    .EXAMPLE
        Get-CSNetwork -Name 'routed-net' | Set-CSNetworkBgpPeer -Wait
        Unlinks all BGP peers from a network.
    #>

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

        [string[]]$BgpPeerIds,

        [switch]$Wait
    )

    process {
        $apiParams = @{ networkid = $NetworkId }
        if ($BgpPeerIds) { $apiParams.bgppeerids = $BgpPeerIds -join ',' }
        $action = if ($BgpPeerIds) { "Set BGP peers to $($BgpPeerIds -join ', ')" } else { 'Unlink all BGP peers' }
        if ($PSCmdlet.ShouldProcess("network $NetworkId", $action)) {
            Invoke-CSAsyncApiRequest -Command 'changeBgpPeersForNetwork' -Parameters $apiParams -Wait:$Wait
        }
    }
}

function Get-CSNetworkPermission {
    <#
    .SYNOPSIS
        Lists the accounts and projects allowed to use a network.

    .DESCRIPTION
        Returns the network permissions of an isolated or L2 network
        (listNetworkPermissions). Accepts network objects from Get-CSNetwork on
        the pipeline.

    .PARAMETER NetworkId
        The ID of the network (required; binds from a piped network's id)

    .EXAMPLE
        Get-CSNetworkPermission -NetworkId net-uuid
        Lists the accounts/projects that have been granted access to a network.

    .EXAMPLE
        Get-CSNetwork -Name 'shared-app' | Get-CSNetworkPermission
        Lists the permissions of a network found by name.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Id')]
        [string]$NetworkId
    )

    process {
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listNetworkPermissions' -Parameters @{ networkid = $NetworkId }) -Command 'listNetworkPermissions'
    }
}

function Grant-CSNetworkPermission {
    <#
    .SYNOPSIS
        Allows other accounts or projects to use a network.

    .DESCRIPTION
        Adds accounts and/or projects to a network's permissions
        (createNetworkPermissions). At least one of -Account, -AccountId or
        -ProjectId is required; all must be in the network owner's domain.
        Accepts network objects from Get-CSNetwork on the pipeline.

    .PARAMETER NetworkId
        The ID of the network (required; binds from a piped network's id)

    .PARAMETER Account
        Account names within the owner's domain to grant access to

    .PARAMETER AccountId
        Account IDs within the owner's domain to grant access to

    .PARAMETER ProjectId
        Project IDs within the owner's domain to grant access to

    .EXAMPLE
        Grant-CSNetworkPermission -NetworkId net-uuid -Account 'qa', 'staging'
        Lets the qa and staging accounts deploy VMs on the network.

    .EXAMPLE
        Get-CSNetwork -Name 'shared-app' | Grant-CSNetworkPermission -ProjectId proj-uuid
        Grants a project access to a network found by name.
    #>

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

        [string[]]$Account,

        [string[]]$AccountId,

        [string[]]$ProjectId
    )

    process {
        if (-not ($Account -or $AccountId -or $ProjectId)) {
            throw 'Specify at least one of -Account, -AccountId, or -ProjectId.'
        }
        $apiParams = @{ networkid = $NetworkId }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Account = 'accounts'; AccountId = 'accountids'; ProjectId = 'projectids'
        })
        if ($PSCmdlet.ShouldProcess("network $NetworkId", 'Grant permissions')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'createNetworkPermissions' -Parameters $apiParams) -Command 'createNetworkPermissions'
        }
    }
}

function Revoke-CSNetworkPermission {
    <#
    .SYNOPSIS
        Removes accounts or projects from a network's permissions.

    .DESCRIPTION
        Removes accounts and/or projects from a network's permissions
        (removeNetworkPermissions). At least one of -Account, -AccountId or
        -ProjectId is required. Accepts network objects from Get-CSNetwork on the
        pipeline.

    .PARAMETER NetworkId
        The ID of the network (required; binds from a piped network's id)

    .PARAMETER Account
        Account names to remove

    .PARAMETER AccountId
        Account IDs to remove

    .PARAMETER ProjectId
        Project IDs to remove

    .EXAMPLE
        Revoke-CSNetworkPermission -NetworkId net-uuid -Account 'staging'
        Stops the staging account from using the network.

    .EXAMPLE
        Get-CSNetwork -Name 'shared-app' | Revoke-CSNetworkPermission -AccountId acct-uuid -Confirm:$false
        Revokes an account's access without prompting.
    #>

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

        [string[]]$Account,

        [string[]]$AccountId,

        [string[]]$ProjectId
    )

    process {
        if (-not ($Account -or $AccountId -or $ProjectId)) {
            throw 'Specify at least one of -Account, -AccountId, or -ProjectId.'
        }
        $apiParams = @{ networkid = $NetworkId }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Account = 'accounts'; AccountId = 'accountids'; ProjectId = 'projectids'
        })
        if ($PSCmdlet.ShouldProcess("network $NetworkId", 'Revoke permissions')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'removeNetworkPermissions' -Parameters $apiParams) -Command 'removeNetworkPermissions'
        }
    }
}

function Reset-CSNetworkPermission {
    <#
    .SYNOPSIS
        Removes all extra permissions from a network.

    .DESCRIPTION
        Resets a network's permissions so only the owner can use it
        (resetNetworkPermissions). Accepts network objects from Get-CSNetwork on
        the pipeline.

    .PARAMETER NetworkId
        The ID of the network (required; binds from a piped network's id)

    .EXAMPLE
        Reset-CSNetworkPermission -NetworkId net-uuid
        Revokes every granted account/project after prompting for confirmation.

    .EXAMPLE
        Get-CSNetwork -Name 'shared-app' | Reset-CSNetworkPermission -Confirm:$false
        Resets a network's permissions without prompting.
    #>

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

    process {
        if ($PSCmdlet.ShouldProcess("network $NetworkId", 'Reset all permissions')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'resetNetworkPermissions' -Parameters @{ networkid = $NetworkId }) -Command 'resetNetworkPermissions'
        }
    }
}