Scripts/Restore/Restore-CohesityRemoteOracleDatabase.ps1

function Restore-CohesityRemoteOracleDatabase {
    <#
        .SYNOPSIS
        Restores the specified oracle database from a remote backup.
        .DESCRIPTION
        Restores the specified oracle database from a remote backup.
        .NOTES
        Published by Cohesity.
        .LINK
        https://cohesity.github.io/cohesity-powershell-module/#/README
        .EXAMPLE
        Restore-CohesityRemoteOracleDatabase -DatabaseName db_1 -SourceId 3 -OracleHome /u01/app/oracle/product/19c/db_1 -OracleBase /u01/app/oracle/product/ -DatabaseFileDestination /u01/app/oracle/product/19c/db_1 -TargetSourceId 1 -JobId 12 -NewDatabaseName new_db1 -RedoLogMemberPath '/' -NoFilenameCheck -EnableArchiveLogMode -NumRedoLogGroup 3
        Restores the specified oracle database from the remote cluster using latest snapshot, protected by job with id 12, from the source with id 3 to the target oracle source with id 1. With specified restore settings.
        To get the source details to be restored,
        $oracleObj = Find-CohesityObjectsForRestore -Environments KOracle
        $DatabaseName = $oracleObj[0].SnapshottedSource.name
        $SourceId = $oracleObj[0].SnapshottedSource.ParentId
        To get the target source detail, where database need to be restored,
        $sourceObj = Get-CohesityProtectionSource -Environments kOracle
        $TargetSourceId = $sourceObj[0].protectionSource.id
        .EXAMPLE
        Restore-CohesityRemoteOracleDatabase -DatabaseName db_1 -SourceName x.x.x.x -OracleHome /u01/app/oracle/product/19c/db_1 -OracleBase /u01/app/oracle/product/ -DatabaseFileDestination /u01/app/oracle/product/19c/db_1 -TargetSource y.y.y.y -JobId 12 -NewDatabaseName new_db1 -SnapshotId abcd
        Restores the specified oracle database from the remote cluster using specified snapshot, protected by job with id 12, from the source with id 3 to the target oracle source y.y.y.y. With specified restore settings.
        To get the snapshot id for restore,
        $snapshotObj = Find-CohesityObjectSnapshot -Object <databaseId>
        $SnapshotId = $snapshotObj[0].id
    #>


    [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $True, ConfirmImpact = "High")]
    Param(
        # Specifies BCT file path.
        [Parameter(Mandatory = $false)]
        [string]$BCTFilePath,
        # Location to put the database files(datafiles, logfiles etc.).
        [Parameter(Mandatory = $true)]
        [string]$DatabaseFileDestination,
        # Specifies archive log mode for oracle restore.
        [Parameter(Mandatory = $false)]
        [switch]$EnableArchiveLogMode,
        # Specifies name of the database to recover.
        [Parameter(Mandatory = $true)]
        [string]$DatabaseName,
        # Specifies the job id that backed up this Oracle database.
        [Parameter(Mandatory = $true)]
        [ValidateRange(1, [long]::MaxValue)]
        [long]$JobId,
        # Specifies a new name for the restored database.
        [Parameter(Mandatory = $true)]
        [string]$NewDatabaseName,
        # Specifies whether to validate filenames or not in Oracle alternate restore workflow.
        [Parameter(Mandatory = $false)]
        [switch]$NoFilenameCheck,
        # Number of redo log groups.
        [Parameter(Mandatory = $false)]
        [ValidateRange(2, [long]::MaxValue)]
        [long]$NumRedoLogGroup,
        # Specifies no. of tempfiles to be used for the recovered database.
        [Parameter(Mandatory = $false)]
        [ValidateRange(1, [long]::MaxValue)]
        [long]$NumTempFiles,
        # Specifies the Oracle base directory path.
        [Parameter(Mandatory = $true)]
        [string]$OracleBase,
        # Specifies the Oracle home directory path.
        [Parameter(Mandatory = $true)]
        [string]$OracleHome,
        # List of members of this redo log group.
        [Parameter(Mandatory = $false)]
        [string[]]$RedoLogMemberPath,
        # Log member name prefix.
        [Parameter(Mandatory = $false)]
        [string]$RedoLogMemberPrefix,
        # Size of the member in MB.
        [Parameter(Mandatory = $false)]
        [ValidateRange(1, [long]::MaxValue)]
        [long]$RedoLogSizeInMb,
        # Specifies the snapshot id for this Oracle database. If not specified the latest snapshot will be used to restore.
        [Parameter(Mandatory = $false)]
        [string]$SnapshotId,
        # Specifies id of an oracle source from where database need to be restored.
        [Parameter(Mandatory = $true)]
        [long]$SourceId,
        # Specifies the name of an alternate Oracle source where database to be restored.
        [Parameter(Mandatory = $false)]
        [string]$TargetSource,
        # Specifies the id of an alternate Oracle source where database to be restored.
        [Parameter(Mandatory = $false)]
        [long]$TargetSourceId,
        # Specifies the name of the restore task.
        [Parameter(Mandatory = $false)]
        [string]$TaskName = "Recover_Oracle_" + (Get-Date -Format "MMM_dd_yyyy_h_mm_tt").ToString()
    )
    Begin {
    }

    Process {
        # Construct v2 protection group id from provided v1 protection group id
        $clusterURL = '/v2/clusters'
        $clusterResult = Invoke-RestApi -Method Get -Uri $clusterURL
        $clusterId = $clusterResult.id
        $clusterIncarnationId = $clusterResult.incarnationId
        $protectionGroupId = "${clusterId}:${clusterIncarnationId}:${jobId}"

        # Check whether specified job is valid or not
        $protectionGroupUrl = "/v2/data-protect/protection-groups?ids=${protectionGroupId}"
        $protectionGroupObj = Invoke-RestApi -Method Get -Uri $protectionGroupUrl
        if (-not $protectionGroupObj.protectionGroups) {
            $errorMsg = "Cannot proceed, the protection job with id '$JobId' is not found."
            Write-Output $errorMsg
            CSLog -Message $errorMsg -Severity 2
            return
        }
        $protectionGroup = $protectionGroupObj.protectionGroups[0]

        # Validate provided oracle database exists
        $searchUrl = "/v2/data-protect/search/protected-objects?environments=kOracle&snapshotActions=RecoverApps&searchString=${DatabaseName}&protectionGroupIds=${protectionGroupId}"
        $searchResult = Invoke-RestApi -Method Get -Uri $searchUrl

        $searchObj = $searchResult.objects | Where-Object { $_.name -eq $DatabaseName -and $_.sourceId -eq $SourceId }

        if (!$searchObj) {
            $errorMsg = "Oracle Database '${DatabaseName}' under source with an id $SourceId is not found in the specified protection group."
            Write-Output $errorMsg
            CSLog -Message $errorMsg
            return
        }

        # Validate provided target oracle source exists.
        if ($TargetSource) {
            # Find the Id of specified target source
            $protectionSources = Get-CohesityProtectionSource -Environments KOracle
            foreach ($record in $protectionSources) {
                if ($record.protectionSource.Name -eq $TargetSource) {
                    $TargetSourceId = $record.protectionSource.id
                    break;
                }
            }
        } elseif ($TargetSourceId){
            $protectionSourceObject = Get-CohesityProtectionSource -Id $TargetSourceId
            if ($protectionSourceObject.id -ne $TargetSourceId) {
                Write-Output "Cannot proceed, the target oracle source id '$TargetSourceId' is invalid"
                return
            }
        }

        if (!$TargetSourceId){
            Write-Output "Please provide the valid target oracle source."
            return
        }

        <#
            Check if snapshot detail is provided.
            If not, collect the latest recoverable job run information.
        #>

        if (-not $SnapshotId) {
            Write-Host "Fetching latest snapshot for restore."
            $snapshotInfo = $searchObj.latestSnapshotsInfo
            if ($snapshotInfo -and $snapshotInfo.Length -ne 0) {
                $snapshotObj = $snapshotInfo[0].localSnapshotInfo

                if ($snapshotObj) {
                    $SnapshotId = $snapshotObj.snapshotId
                }
                else {
                    $errorMsg = "Could not fetch remote snapshot information for the database '$DatabaseName'"
                    Write-Output $errorMsg
                    CSLog -Message $errorMsg -Severity 2
                    return
                }
            }
            else {
                $errorMsg = "Could not fetch remote snapshot information for the database '$DatabaseName'"
                Write-Output $errorMsg
                CSLog -Message $errorMsg -Severity 2
                return
            }
        }
            
        # Construct payload for restore
        $payload = @{
            name                = $TaskName
            snapshotEnvironment = $protectionGroup.environment
        }

        $payload['oracleParams'] = @{}
        $payload['oracleParams']['objects'] = @(
            @{
                snapshotId = $SnapshotId
            }
        )
        $payload['oracleParams']['recoveryAction'] = 'RecoverApps'
        $payload['oracleParams']['recoverAppParams'] = @{
            targetEnvironment  = 'kOracle';
            oracleTargetParams = @{
                recoverToNewSource              = $true;
                newSourceConfig                 = @{
                    host                        = @{
                        id                      = $TargetSourceId
                    };
                    recoveryTarget              = 'RecoverDatabase';
                    recoverDatabaseParams       = @{
                        bctFilePath             = if ($BCTFilePath) { $BCTFilePath } else { $null };
                        databaseName            = $NewDatabaseName;
                        dbFilesDestination      = if ($DatabaseFileDestination) { $DatabaseFileDestination } else { $OracleHome }
                        enableArchiveLogMode    = $EnableArchiveLogMode.IsPresent;
                        nofilenameCheck         = $NoFilenameCheck.IsPresent;
                        numTempfiles            = if ($NumTempFiles) { $NumTempFiles } else { $null };
                        oracleBaseFolder        = $OracleBase;
                        oracleHomeFolder        = $OracleHome;
                        redoLogConfig           = @{
                            groupMembers        = @($RedoLogMemberPath)
                            memberPrefix        = if ($RedoLogMemberPrefix) { $RedoLogMemberPrefix } else { $null };
                            numGroups           = $NumRedoLogGroup
                            sizeMBytes          = if ($RedoLogSizeInMb) { $RedoLogSizeInMb } else { 20 }
                        }
                    }
                }                            
            };
        }

        $restoreURL = '/v2/data-protect/recoveries'
        $payloadJson = $payload | ConvertTo-Json -Depth 100

        $resp = Invoke-RestApi -Method 'Post' -Uri $restoreURL -Body $payloadJson
        if ($Global:CohesityAPIStatus.StatusCode -eq 201) {
            $resp
        }
        else {
            $errorMsg = $Global:CohesityAPIStatus.ErrorMessage + ", File operation : Failed to recover."
            Write-Output $errorMsg
            CSLog -Message $errorMsg
        }
    }
    End {
    }
}