lib/Tasks.ps1



# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoTask {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Task Started Before Date (YYYY-MM-DD)')] [string] $StartedBeforeDate,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Task Started After Date')] [string] $StartedAfterDate,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Task Completed Before Date (YYYY-MM-DD)')] [string] $CompletedBeforeDate,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Task Completed After Date')] [string] $CompletedAfterDate,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Task Type')] [ZertoTaskTypes] $TaskType,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Task Status')] [string] $Status,
        [Parameter(Mandatory = $true, ParameterSetName = "ID", HelpMessage = 'Zerto Task Identifier')] [string] $ZertoTaskIdentifier
    )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"



    switch ($PsCmdlet.ParameterSetName) {
        "ID" {
            if ([string]::IsNullOrEmpty($ZertoTaskIdentifier)  ) {
                throw "Missing Zerto Task Identifier"
            }

            #Zerto Returns TASK id's using a ':' as a separator - this needs to be a '.' for the API
            if ($ZertoTaskIdentifier -match ':') {
                $ZertoTaskIdentifier = $ZertoTaskIdentifier -replace ':', '.'
            }

            $FullURL = $baseURL + "tasks/" + $ZertoTaskIdentifier
        }
        Default {
            $FullURL = $baseURL + "tasks"
            if ($StartedBeforeDate -or $StartedAfterDate -or $CompletedBeforeDate -or $CompletedAfterDate -or $TaskType -ne $null -or $Status) {
                $qs = [ordered] @{}
                if ($StartedBeforeDate) { if (Parse-ZertoDate($StartedBeforeDate)) { $qs.Add("startedBeforeDate", $StartedBeforeDate) } else { throw "Invalid StartedBeforeDate: '$StartedBeforeDate'" } }
                if ($StartedAfterDate) { if (Parse-ZertoDate($StartedAfterDate)) { $qs.Add("startedAfterDate", $StartedAfterDate) } else { throw "Invalid StartedAfterDate: '$StartedAfterDate'" } }
                if ($CompletedBeforeDate) { if (Parse-ZertoDate($CompletedBeforeDate)) { $qs.Add("completedBeforeDate", $CompletedBeforeDate) } else { throw "Invalid CompletedBeforeDate: '$CompletedBeforeDate'" } }
                if ($CompletedAfterDate) { if (Parse-ZertoDate($CompletedAfterDate)) { $qs.Add("completedAfterDate", $CompletedAfterDate) } else { throw "Invalid CompletedAfterDate: '$CompletedAfterDate'" } }
                if ($TaskType -ne $null) { $qs.Add("type", $TaskType) }
                if ($Status) { $qs.Add("status", $Status) }

                $FullURL += Get-QueryStringFromHashTable -QueryStringHash $QS
            }
        }
    }
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoTaskType {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default"
    )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"



    $FullURL = $baseURL + "tasks/types"
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoTaskState {
    [CmdletBinding(DefaultParameterSetName = 'default')]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, ParameterSetName = "State", HelpMessage = 'Zerto Task State')] [string] $ZertoTaskState,
        [Parameter(Mandatory = $true, ParameterSetName = "ID", HelpMessage = 'Zerto Task State ID')] [ZertoTaskStates] $ZertoTaskStateID
    )

    #$baseURL = "https://" + $ZertoServer + ":"+$ZertoPort+"/v1/"
    #$TypeJSON = "application/json"


    switch ($PsCmdlet.ParameterSetName) {
        "State" {
            if ([string]::IsNullOrEmpty($ZertoTaskState)  ) {
                throw "Missing Zerto Task State"
            }
            Return [ZertoTaskStates]::$ZertoTaskState.value__
        }
        "ID" {
            Return [ZertoTaskStates]$ZertoTaskStateID
        }
        Default {
            return [System.Enum]::GetNames([ZertoTaskStates])
        }
    }
}

Function Wait-ZertoTask {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto Task Identifier')] [string] $ZertoTaskIdentifier,
        [Parameter(HelpMessage = 'Write Console Output')] [Switch] $Output,
        [Parameter(HelpMessage = 'Activity ID for Progress output')] [Int] $ActivityId,
        [Parameter(HelpMessage = 'Parent Activity ID for Progress output')] [Int] $ParentId = 0,
        [Parameter(HelpMessage = 'Polling interval for Retrieving Task Status')] [Int] $PollIntervalSeconds = 2

    )

    if ([string]::IsNullOrEmpty($ZertoTaskIdentifier)  ) {
        throw "Missing Zerto Task Identifier"
    }

    #Zerto Returns TASK id's using a ':' as a separator - this needs to be a '.' for the API
    if ($ZertoTaskIdentifier -match ':') {
        $ZertoTaskIdentifier = $ZertoTaskIdentifier -replace ':', '.'
    }

    try {

        ## Get Task Type, States and the Task
        $TaskStates = Get-ZertoTaskState
        $ZertoTask = Get-ZertoTask -ZertoTaskIdentifier $ZertoTaskIdentifier -ZertoSession $ZertoSession

        if ($ZertoTask.RelatedEntities.Vpgs) {
            $ZertoVpg = Get-ZertoVPG -ZertoSession $ZertoSession -ZertoVpgIdentifier $ZertoTask.RelatedEntities.Vpgs.identifier
        }

        if ($Output) {
            Write-Host "Monitoring Zerto [" -NoNewline
            Write-Host $($ZertoTask.Type) -NoNewline -ForegroundColor Cyan
            Write-Host "] Task ID: " -NoNewline
            Write-Host $ZertoTaskIdentifier -ForegroundColor Yellow -NoNewline

            if ($ZertoVpg) {
                Write-Host " for VPG: " -NoNewline
                Write-Host $($ZertoVpg.VpgName) -NoNewline -ForegroundColor Cyan
            }
            Write-Host ''
        }

        $TaskComplete = $False
        $PercentageComplete = 1
        $LoggedMessages = @()
        while (-Not $TaskComplete) {

            ## Sleep to allow the job to progress
            Start-Sleep -Seconds $PollIntervalSeconds
            $ZertoTask = Get-ZertoTask -ZertoTaskIdentifier $ZertoTaskIdentifier -ZertoSession $ZertoSession

            ## If the Task has a VPG related to it
            if($ZertoVpg){
                $ZertoVpg = Get-ZertoVPG -ZertoSession $ZertoSession -ZertoVpgIdentifier $ZertoVpg.VpgIdentifier
            }

            ## Log the Status of the Job
            if ($Output) {
                if ($LoggedMessages -notcontains $TaskStates[$ZertoTask.Status.State]) {
                    $LoggedMessages += $TaskStates[$ZertoTask.Status.State]
                    Write-Host $ZertoTask.Type -NoNewline -ForegroundColor Cyan
                    Write-Host ", Status: " -NoNewline
                    Write-Host $TaskStates[$ZertoTask.Status.State] -ForegroundColor Yellow
                }
            }

            ## Report the Percentage Complete
            if ($PercentageComplete -lt $ZertoTask.Status.Progress) {
                $PercentageComplete = $ZertoTask.Status.Progress

                if ($ActivityId) {
                    Write-Progress -Id $ActivityId -ParentId $ParentId -PercentComplete $PercentageComplete -Activity "Task: [$($ZertoTask.Type)], Device: [$($Params.DeviceName)]"
                }
            }

            ## Update the Task Completion to exit the loop
            if ($TaskStates[$ZertoTask.Status.State] -eq 'Completed') {
                $TaskComplete = $true
                Write-Host "Zerto [" -NoNewline
                Write-Host $($ZertoTask.Type) -NoNewline -ForegroundColor Cyan
                Write-Host "] Task has " -NoNewline
                Write-Host 'Completed' -ForegroundColor Green
            }
        }
    }
    catch {
        throw $_
    }
}