Public/resource-limit.ps1

# Resource limits: the per-account/domain/project caps CloudStack enforces on
# each resource type (VMs, volumes, CPU, memory, and so on).

function Get-CSResourceLimit {
    <#
    .SYNOPSIS
        Lists the configured resource limits.

    .DESCRIPTION
        Wraps listResourceLimits. A limit of -1 (the 'max' field) means unlimited.
        Limits apply to a specific account, domain, or project; with no owner
        filter the caller's own limits are returned. Accepts account, domain, and
        project objects on the pipeline, so 'Get-CSAccount engineering |
        Get-CSResourceLimit' lists that account's limits.

    .PARAMETER ResourceType
        Only the limit for this resource type. One of VirtualMachine, PublicIp,
        Volume, Snapshot, Template, Project, Network, Vpc, Cpu, Memory,
        PrimaryStorage, or SecondaryStorage.

    .PARAMETER Account
        Filter by account name. Must be used with -DomainId.

    .PARAMETER DomainId
        Filter by domain ID

    .PARAMETER ProjectId
        Filter by project ID

    .PARAMETER Id
        Filter by the resource limit's own ID

    .PARAMETER Tag
        Only tagged limits for this resource tag (for tag-based resource limits)

    .PARAMETER IsRecursive
        With -DomainId, also include limits in subdomains

    .PARAMETER ListAll
        List every limit the caller is allowed to see

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSResourceLimit
        Lists the caller's own resource limits.

    .EXAMPLE
        Get-CSResourceLimit -Account 'engineering' -DomainId domain-uuid
        Lists one account's limits.

    .EXAMPLE
        Get-CSResourceLimit -Account 'engineering' -DomainId domain-uuid -ResourceType Cpu
        Gets just the CPU-core cap for an account.

    .EXAMPLE
        Get-CSAccount -Name 'engineering' -DomainId domain-uuid | Get-CSResourceLimit
        Pipes an account object in to list its limits.
    #>

    [CmdletBinding()]
    param(
        [ValidateSet('VirtualMachine', 'PublicIp', 'Volume', 'Snapshot', 'Template', 'Project',
            'Network', 'Vpc', 'Cpu', 'Memory', 'PrimaryStorage', 'SecondaryStorage')]
        [string]$ResourceType,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [Alias('Name')]
        [string]$Account,

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

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$ProjectId,

        [string]$Id,

        [string]$Tag,

        [switch]$IsRecursive,

        [switch]$ListAll,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    process {
        $apiParams = @{}
        if ($PSBoundParameters.ContainsKey('ResourceType')) {
            $apiParams['resourcetype'] = ConvertTo-CSResourceTypeId -ResourceType $ResourceType
        }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Account = 'account'; DomainId = 'domainid'; ProjectId = 'projectid'; Id = 'id'; Tag = 'tag'
            IsRecursive = 'isrecursive'; ListAll = 'listall'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
        })
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listResourceLimits' -Parameters $apiParams) -Command 'listResourceLimits'
    }
}

function Set-CSResourceLimit {
    <#
    .SYNOPSIS
        Sets a resource limit for an account, domain, or project.

    .DESCRIPTION
        Wraps updateResourceLimit. -Max is the new cap; -1 means unlimited and 0
        means none allowed. With no owner given the limit is set at the domain of
        the caller. Accepts account, domain, and project objects on the pipeline.

    .PARAMETER ResourceType
        The resource type to cap. One of VirtualMachine, PublicIp, Volume,
        Snapshot, Template, Project, Network, Vpc, Cpu, Memory, PrimaryStorage,
        or SecondaryStorage.

    .PARAMETER Max
        The new limit. -1 for unlimited, 0 for none, or a positive count. Omit to
        reset the owner back to inheriting its parent domain's limit.

    .PARAMETER Account
        Set the limit on this account. Must be used with -DomainId.

    .PARAMETER DomainId
        Set the limit on this domain (or scope the -Account)

    .PARAMETER ProjectId
        Set the limit on this project. Takes precedence over -Account.

    .PARAMETER Tag
        Apply the limit to a tagged resource limit for this resource tag

    .EXAMPLE
        Set-CSResourceLimit -ResourceType VirtualMachine -Max 50 -Account 'engineering' -DomainId domain-uuid
        Caps one account at 50 instances.

    .EXAMPLE
        Set-CSResourceLimit -ResourceType Cpu -Max -1 -DomainId domain-uuid
        Gives a domain unlimited CPU cores.

    .EXAMPLE
        Set-CSResourceLimit -ResourceType Volume -Max 100 -ProjectId project-uuid
        Caps a project at 100 volumes.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateSet('VirtualMachine', 'PublicIp', 'Volume', 'Snapshot', 'Template', 'Project',
            'Network', 'Vpc', 'Cpu', 'Memory', 'PrimaryStorage', 'SecondaryStorage')]
        [string]$ResourceType,

        [int]$Max,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [Alias('Name')]
        [string]$Account,

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

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$ProjectId,

        [string]$Tag
    )

    process {
        $apiParams = @{ resourcetype = ConvertTo-CSResourceTypeId -ResourceType $ResourceType }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Max = 'max'; Account = 'account'; DomainId = 'domainid'; ProjectId = 'projectid'; Tag = 'tag'
        })

        $owner = if ($ProjectId) { "project $ProjectId" } elseif ($Account) { "account $Account" } elseif ($DomainId) { "domain $DomainId" } else { 'the current domain' }
        $limit = if ($PSBoundParameters.ContainsKey('Max')) { if ($Max -eq -1) { 'unlimited' } else { $Max } } else { 'inherited' }
        if ($PSCmdlet.ShouldProcess($owner, "Set $ResourceType limit to $limit")) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'updateResourceLimit' -Parameters $apiParams) -Command 'updateResourceLimit'
        }
    }
}