Public/management.ps1

# Assorted management/discovery commands: rolling maintenance across hosts, the
# cloud identifier, and API discovery.

function Start-CSRollingMaintenance {
    <#
    .SYNOPSIS
        Starts a rolling maintenance run across hosts.

    .DESCRIPTION
        Wraps startRollingMaintenance. CloudStack takes each host in the chosen scope
        into maintenance one at a time - migrating VMs off, running an optional
        payload script, then bringing it back - so the cloud stays available
        throughout. Give at least one of -HostIds, -ClusterIds, -PodIds, or -ZoneIds.
        This is an asynchronous job; use -Wait to block until the whole run finishes.

    .PARAMETER HostIds
        Roll through these specific hosts

    .PARAMETER ClusterIds
        Roll through every host in these clusters

    .PARAMETER PodIds
        Roll through every host in these pods

    .PARAMETER ZoneIds
        Roll through every host in these zones

    .PARAMETER Payload
        A script to run on each host while it is in maintenance

    .PARAMETER Timeout
        Per-host timeout in seconds

    .PARAMETER Forced
        Continue the run even if a host fails

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

    .EXAMPLE
        Start-CSRollingMaintenance -ClusterIds $clusterId -Wait
        Rolls maintenance through every host in a cluster and waits for it.

    .EXAMPLE
        Start-CSRollingMaintenance -HostIds $hostA, $hostB -Payload (Get-Content ./patch.sh -Raw) -Forced
        Patches two hosts with a payload script, continuing past failures.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
    param(
        [string[]]$HostIds,

        [string[]]$ClusterIds,

        [string[]]$PodIds,

        [string[]]$ZoneIds,

        [string]$Payload,

        [int]$Timeout,

        [switch]$Forced,

        [switch]$Wait
    )

    if (-not ($PSBoundParameters.ContainsKey('HostIds') -or $PSBoundParameters.ContainsKey('ClusterIds') -or
            $PSBoundParameters.ContainsKey('PodIds') -or $PSBoundParameters.ContainsKey('ZoneIds'))) {
        throw 'Specify a scope with -HostIds, -ClusterIds, -PodIds, or -ZoneIds.'
    }
    $apiParams = @{}
    Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
        HostIds = 'hostids'; ClusterIds = 'clusterids'; PodIds = 'podids'; ZoneIds = 'zoneids'; Payload = 'payload'; Timeout = 'timeout'; Forced = 'forced'
    })
    $scope = if ($HostIds) { "hosts $($HostIds -join ',')" } elseif ($ClusterIds) { "clusters $($ClusterIds -join ',')" } elseif ($PodIds) { "pods $($PodIds -join ',')" } else { "zones $($ZoneIds -join ',')" }
    if ($PSCmdlet.ShouldProcess($scope, 'Start rolling maintenance')) {
        Invoke-CSAsyncApiRequest -Command 'startRollingMaintenance' -Parameters $apiParams -Wait:$Wait
    }
}

function Get-CSCloudIdentifier {
    <#
    .SYNOPSIS
        Gets a signed cloud identifier for a user.

    .DESCRIPTION
        Wraps getCloudIdentifier, returning a unique identifier for this cloud
        together with a signature, as used by external tools to tie a user to a
        specific CloudStack deployment. Accepts user objects on the pipeline.

    .PARAMETER UserId
        The user to get the identifier for. Binds from a piped user's id.

    .EXAMPLE
        Get-CSCloudIdentifier -UserId $userId
        Returns the cloud identifier and signature for a user.

    .EXAMPLE
        Get-CSUser -Username 'operator' | Get-CSCloudIdentifier
        Gets the identifier for a user piped in by object.
    #>

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

    process {
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'getCloudIdentifier' -Parameters @{ userid = $UserId }) -Command 'getCloudIdentifier'
    }
}

function Get-CSApi {
    <#
    .SYNOPSIS
        Lists the APIs available on the server.

    .DESCRIPTION
        Wraps listApis (the API Discovery plugin), returning the API commands the
        caller can run, each with its description, parameters, and response fields.
        Filter to one command with -Name.

    .PARAMETER Name
        Only the API with this exact command name

    .EXAMPLE
        Get-CSApi | Select-Object name, description
        Lists every API the caller can run.

    .EXAMPLE
        Get-CSApi -Name deployVirtualMachine | Select-Object -ExpandProperty params
        Shows the parameters of one API command.
    #>

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

    $apiParams = @{}
    if ($PSBoundParameters.ContainsKey('Name')) { $apiParams['name'] = $Name }
    ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listApis' -Parameters $apiParams) -Command 'listApis'
}