Public/configuration.ps1

# Global/scoped settings, capabilities, hypervisor capabilities, API rate limits,
# and LDAP server configuration.

function Get-CSConfiguration {
    <#
    .SYNOPSIS
        Lists configuration settings.

    .DESCRIPTION
        Wraps listConfigurations. With no scope, lists global settings; narrow to an
        account, domain, zone, cluster, or storage pool to see settings overridden at
        that level. Filter by -Name for one setting or -Category/-Group to browse.

    .PARAMETER Name
        Filter by the exact setting name

    .PARAMETER Category
        Filter by category

    .PARAMETER Group
        Filter by configuration group

    .PARAMETER Subgroup
        Filter by configuration subgroup

    .PARAMETER ZoneId
        Show the setting as scoped to this zone

    .PARAMETER ClusterId
        Show the setting as scoped to this cluster

    .PARAMETER StorageId
        Show the setting as scoped to this storage pool

    .PARAMETER AccountId
        Show the setting as scoped to this account

    .PARAMETER DomainId
        Show the setting as scoped to this domain

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSConfiguration -Name 'expunge.delay'
        Gets one global setting.

    .EXAMPLE
        Get-CSConfiguration -Keyword vm.password | Select-Object name, value
        Searches settings by keyword.
    #>

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

        [string]$Category,

        [string]$Group,

        [string]$Subgroup,

        [string]$ZoneId,

        [string]$ClusterId,

        [string]$StorageId,

        [string]$AccountId,

        [string]$DomainId,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        Name = 'name'; Category = 'category'; Group = 'group'; Subgroup = 'subgroup'; ZoneId = 'zoneid'; ClusterId = 'clusterid'
        StorageId = 'storageid'; AccountId = 'accountid'; DomainId = 'domainid'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
    })
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listConfigurations' -Parameters $apiParams) -Command 'listConfigurations'
}

function Set-CSConfiguration {
    <#
    .SYNOPSIS
        Updates a configuration setting.

    .DESCRIPTION
        Wraps updateConfiguration. Sets a global setting, or an account/domain/zone/
        cluster/storage-scoped override when a scope is given. Some global settings
        only take effect after a management server restart. Accepts configuration
        objects (which carry a name) on the pipeline.

    .PARAMETER Name
        The setting name. Binds from a piped setting's name.

    .PARAMETER Value
        The new value

    .PARAMETER ZoneId
        Set the override for this zone

    .PARAMETER ClusterId
        Set the override for this cluster

    .PARAMETER StorageId
        Set the override for this storage pool

    .PARAMETER AccountId
        Set the override for this account

    .PARAMETER DomainId
        Set the override for this domain

    .EXAMPLE
        Set-CSConfiguration -Name 'expunge.delay' -Value 120
        Changes a global setting.

    .EXAMPLE
        Set-CSConfiguration -Name 'use.local.storage' -Value true -ZoneId $zoneId
        Overrides a setting at zone scope.
    #>

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

        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]
        [string]$Value,

        [string]$ZoneId,

        [string]$ClusterId,

        [string]$StorageId,

        [string]$AccountId,

        [string]$DomainId
    )

    process {
        $apiParams = @{ name = $Name; value = $Value }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            ZoneId = 'zoneid'; ClusterId = 'clusterid'; StorageId = 'storageid'; AccountId = 'accountid'; DomainId = 'domainid'
        })
        if ($PSCmdlet.ShouldProcess("setting $Name", "Set to '$Value'")) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'updateConfiguration' -Parameters $apiParams) -Command 'updateConfiguration'
        }
    }
}

function Reset-CSConfiguration {
    <#
    .SYNOPSIS
        Resets a configuration setting to its default.

    .DESCRIPTION
        Wraps resetConfiguration. A global setting is returned to its default value;
        an account/domain/zone/cluster/storage override is removed so the setting
        falls back to the broader scope. Accepts configuration objects on the
        pipeline.

    .PARAMETER Name
        The setting to reset. Binds from a piped setting's name.

    .PARAMETER ZoneId
        Reset the override at this zone

    .PARAMETER ClusterId
        Reset the override at this cluster

    .PARAMETER StorageId
        Reset the override at this storage pool

    .PARAMETER AccountId
        Reset the override at this account

    .PARAMETER DomainId
        Reset the override at this domain

    .EXAMPLE
        Reset-CSConfiguration -Name 'expunge.delay'
        Returns a global setting to its default.

    .EXAMPLE
        Reset-CSConfiguration -Name 'use.local.storage' -ZoneId $zoneId
        Removes a zone-scoped override.
    #>

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

        [string]$ZoneId,

        [string]$ClusterId,

        [string]$StorageId,

        [string]$AccountId,

        [string]$DomainId
    )

    process {
        $apiParams = @{ name = $Name }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            ZoneId = 'zoneid'; ClusterId = 'clusterid'; StorageId = 'storageid'; AccountId = 'accountid'; DomainId = 'domainid'
        })
        if ($PSCmdlet.ShouldProcess("setting $Name", 'Reset to default')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'resetConfiguration' -Parameters $apiParams) -Command 'resetConfiguration'
        }
    }
}

function Get-CSConfigurationGroup {
    <#
    .SYNOPSIS
        Lists configuration groups.

    .DESCRIPTION
        Wraps listConfigurationGroups, the groupings the UI uses to organize
        settings.

    .PARAMETER Name
        Filter by group name

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSConfigurationGroup
        Lists the configuration groups and their subgroups.
    #>

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

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

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

function Get-CSCapability {
    <#
    .SYNOPSIS
        Gets the cloud's capabilities and feature flags.

    .DESCRIPTION
        Wraps listCapabilities, returning a single object of feature toggles and
        limits such as whether security groups are enabled, the API version, and
        dynamic-scaling support.

    .EXAMPLE
        Get-CSCapability
        Returns the capability flags of the CloudStack deployment.
    #>

    [CmdletBinding()]
    param()

    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listCapabilities' -Parameters @{}) -Command 'listCapabilities'
}

function Get-CSDeploymentPlanner {
    <#
    .SYNOPSIS
        Lists the available deployment planners.

    .DESCRIPTION
        Wraps listDeploymentPlanners, the planners that decide where new instances
        are placed (for example FirstFitPlanner).

    .EXAMPLE
        Get-CSDeploymentPlanner
        Lists the deployment planners the deployment supports.
    #>

    [CmdletBinding()]
    param()

    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listDeploymentPlanners' -Parameters @{}) -Command 'listDeploymentPlanners'
}

function Get-CSHypervisor {
    <#
    .SYNOPSIS
        Lists the supported hypervisors.

    .DESCRIPTION
        Wraps listHypervisors, the hypervisor types available (optionally in a
        specific zone).

    .PARAMETER ZoneId
        Only hypervisors available in this zone

    .EXAMPLE
        Get-CSHypervisor
        Lists every supported hypervisor.

    .EXAMPLE
        Get-CSHypervisor -ZoneId $zoneId
        Lists the hypervisors available in one zone.
    #>

    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$ZoneId
    )

    process {
        $apiParams = @{}
        if ($PSBoundParameters.ContainsKey('ZoneId')) { $apiParams['zoneid'] = $ZoneId }
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listHypervisors' -Parameters $apiParams) -Command 'listHypervisors'
    }
}

function Get-CSHypervisorCapability {
    <#
    .SYNOPSIS
        Lists hypervisor capabilities.

    .DESCRIPTION
        Wraps listHypervisorCapabilities, the per-hypervisor limits such as the
        maximum guests per host and whether VM snapshots are supported.

    .PARAMETER Id
        Filter by capability record ID

    .PARAMETER Hypervisor
        Filter by hypervisor type

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSHypervisorCapability -Hypervisor KVM
        Gets the KVM capability limits.
    #>

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

        [string]$Hypervisor,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

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

function Set-CSHypervisorCapability {
    <#
    .SYNOPSIS
        Updates a hypervisor's capability limits.

    .DESCRIPTION
        Wraps updateHypervisorCapabilities. Only the attributes you supply are
        changed. Accepts hypervisor capability objects on the pipeline.

    .PARAMETER Id
        The capability record to update. Binds from a piped record's id.

    .PARAMETER MaxGuestsLimit
        Maximum number of guests per host

    .PARAMETER MaxDataVolumesLimit
        Maximum data volumes attachable to a VM

    .PARAMETER MaxHostsPerCluster
        Maximum hosts allowed in a cluster

    .PARAMETER SecurityGroupEnabled
        Whether security groups are supported

    .PARAMETER StorageMotionEnabled
        Whether storage live migration is supported

    .PARAMETER VmSnapshotEnabled
        Whether VM snapshots are supported

    .EXAMPLE
        Set-CSHypervisorCapability -Id $capId -MaxGuestsLimit 120
        Raises the max guests per host for a hypervisor.

    .EXAMPLE
        Get-CSHypervisorCapability -Hypervisor KVM | Set-CSHypervisorCapability -VmSnapshotEnabled $true
        Enables VM snapshots for KVM.
    #>

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

        [long]$MaxGuestsLimit,

        [int]$MaxDataVolumesLimit,

        [int]$MaxHostsPerCluster,

        [Nullable[bool]]$SecurityGroupEnabled,

        [Nullable[bool]]$StorageMotionEnabled,

        [Nullable[bool]]$VmSnapshotEnabled
    )

    process {
        $apiParams = @{ id = $Id }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            MaxGuestsLimit = 'maxguestslimit'; MaxDataVolumesLimit = 'maxdatavolumeslimit'; MaxHostsPerCluster = 'maxhostspercluster'
        })
        foreach ($p in @('SecurityGroupEnabled', 'StorageMotionEnabled', 'VmSnapshotEnabled')) {
            if ($PSBoundParameters.ContainsKey($p)) {
                $apiParams[$p.ToLowerInvariant()] = ([bool](Get-Variable -Name $p -ValueOnly)).ToString().ToLowerInvariant()
            }
        }
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'updateHypervisorCapabilities' -Parameters $apiParams) -Command 'updateHypervisorCapabilities'
    }
}

function Get-CSApiLimit {
    <#
    .SYNOPSIS
        Gets the caller's API rate-limit usage.

    .DESCRIPTION
        Wraps getApiLimit, returning how many API calls the caller has made and how
        many remain in the current interval.

    .EXAMPLE
        Get-CSApiLimit
        Shows the caller's API count and allowance.
    #>

    [CmdletBinding()]
    param()

    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'getApiLimit' -Parameters @{}) -Command 'getApiLimit'
}

function Reset-CSApiLimit {
    <#
    .SYNOPSIS
        Resets the API rate-limit counter.

    .DESCRIPTION
        Wraps resetApiLimit. With no account, resets the caller's counter; an admin
        can reset a specific -Account.

    .PARAMETER Account
        Reset the counter for this account ID

    .EXAMPLE
        Reset-CSApiLimit
        Resets the caller's API counter.

    .EXAMPLE
        Reset-CSApiLimit -Account $accountId
        Resets one account's API counter.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
    param(
        [string]$Account
    )

    $apiParams = @{}
    if ($PSBoundParameters.ContainsKey('Account')) { $apiParams['account'] = $Account }
    $target = if ($Account) { "account $Account" } else { 'the caller' }
    if ($PSCmdlet.ShouldProcess($target, 'Reset API limit counter')) {
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'resetApiLimit' -Parameters $apiParams) -Command 'resetApiLimit'
    }
}

function Get-CSLdapConfiguration {
    <#
    .SYNOPSIS
        Lists the configured LDAP servers.

    .DESCRIPTION
        Wraps listLdapConfigurations, the LDAP servers CloudStack authenticates
        against, optionally scoped to a domain.

    .PARAMETER Hostname
        Filter by LDAP server hostname

    .PARAMETER Port
        Filter by LDAP server port

    .PARAMETER DomainId
        Filter by the domain the configuration is scoped to

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSLdapConfiguration
        Lists every configured LDAP server.
    #>

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

        [int]$Port,

        [string]$DomainId,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        Hostname = 'hostname'; Port = 'port'; DomainId = 'domainid'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
    })
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listLdapConfigurations' -Parameters $apiParams) -Command 'listLdapConfigurations'
}

function Add-CSLdapConfiguration {
    <#
    .SYNOPSIS
        Adds an LDAP server configuration.

    .DESCRIPTION
        Wraps addLdapConfiguration, registering an LDAP server for authentication,
        optionally scoped to a single domain.

    .PARAMETER Hostname
        The LDAP server hostname

    .PARAMETER Port
        The LDAP server port

    .PARAMETER DomainId
        Scope the configuration to this domain (omit for global)

    .EXAMPLE
        Add-CSLdapConfiguration -Hostname 'ldap.example.com' -Port 636
        Adds a global LDAP server.

    .EXAMPLE
        Add-CSLdapConfiguration -Hostname 'ldap.eng.example.com' -Port 389 -DomainId $domainId
        Adds an LDAP server scoped to one domain.
    #>

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

        [Parameter(Mandatory = $true)]
        [int]$Port,

        [string]$DomainId
    )

    $apiParams = @{ hostname = $Hostname; port = $Port }
    if ($PSBoundParameters.ContainsKey('DomainId')) { $apiParams['domainid'] = $DomainId }
    if ($PSCmdlet.ShouldProcess("LDAP server ${Hostname}:$Port", 'Add')) {
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'addLdapConfiguration' -Parameters $apiParams) -Command 'addLdapConfiguration'
    }
}

function Remove-CSLdapConfiguration {
    <#
    .SYNOPSIS
        Removes an LDAP server configuration.

    .DESCRIPTION
        Wraps deleteLdapConfiguration. Accepts LDAP configuration objects (which
        carry a hostname and port) on the pipeline.

    .PARAMETER Hostname
        The LDAP server hostname to remove. Binds from a piped configuration's hostname.

    .PARAMETER Port
        The LDAP server port. Binds from a piped configuration's port.

    .PARAMETER DomainId
        The domain the configuration is scoped to

    .EXAMPLE
        Remove-CSLdapConfiguration -Hostname 'ldap.example.com' -Port 636
        Removes an LDAP server.

    .EXAMPLE
        Get-CSLdapConfiguration | Where-Object hostname -eq 'old-ldap.example.com' | Remove-CSLdapConfiguration
        Removes an LDAP server located by hostname.
    #>

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

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [int]$Port,

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

    process {
        $apiParams = @{ hostname = $Hostname }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            Port = 'port'; DomainId = 'domainid'
        })
        if ($PSCmdlet.ShouldProcess("LDAP server $Hostname", 'Remove')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'deleteLdapConfiguration' -Parameters $apiParams) -Command 'deleteLdapConfiguration'
        }
    }
}