Skip to content

Commit

Permalink
Added commandlet for oracle remote restore.
Browse files Browse the repository at this point in the history
  • Loading branch information
KavishreeShanmugam11 committed Mar 19, 2024
1 parent 5b45fa5 commit 4f5dabd
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 6 deletions.
5 changes: 3 additions & 2 deletions src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1
Expand Up @@ -8,7 +8,7 @@
RootModule = 'Cohesity.PowerShell.Core.dll'

# Version number of this module.
ModuleVersion = '1.9.6'
ModuleVersion = '1.9.8'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -133,10 +133,11 @@ FunctionsToExport = @(
'Remove-CohesityVlan',
'Restore-CohesityBackupToView',
'Restore-CohesityFileV2',
'Restore-CohesityOracleDatabase',
'Restore-CohesityRemoteFile',
'Restore-CohesityRemoteFileV2',
'Restore-CohesityOracleDatabase',
'Restore-CohesityRemoteMSSQLObject',
'Restore-CohesityRemoteOracleDatabase',
'Restore-CohesityVMwareVM',
'Save-CohesityFile',
'Set-CohesityAlertResolutions',
Expand Down
9 changes: 5 additions & 4 deletions src/Cohesity.Powershell/Cohesity.PowerShell.psd1
Expand Up @@ -8,7 +8,7 @@
RootModule = 'Cohesity.PowerShell.dll'

# Version number of this module.
ModuleVersion = '1.9.6'
ModuleVersion = '1.9.8'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -132,11 +132,12 @@ FunctionsToExport = @(
'Remove-CohesityVirtualIP',
'Remove-CohesityVlan',
'Restore-CohesityBackupToView',
'Restore-CohesityFileV2',
'Restore-CohesityFileV2',
'Restore-CohesityOracleDatabase',
'Restore-CohesityRemoteFile',
'Restore-CohesityRemoteFileV2',
'Restore-CohesityRemoteMSSQLObject',
'Restore-CohesityOracleDatabase',
'Restore-CohesityRemoteOracleDatabase',
'Restore-CohesityVMwareVM',
'Save-CohesityFile',
'Set-CohesityAlertResolutions',
Expand All @@ -154,7 +155,7 @@ FunctionsToExport = @(
'Update-CohesityProtectionJobRun',
'Update-CohesityUserGroup',
'Update-CohesityVlan'
)
)

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @('Add-CohesityViewShare',
Expand Down
@@ -0,0 +1,272 @@
function Restore-CohesityRemoteOracleDatabase {
<#
.SYNOPSIS
Restores the specified files or folders from a remote backup.
.DESCRIPTION
Restores the specified files or folders from a remote backup. This commandlet supports only source with environment type VMware/Physical/Isilon.
.NOTES
Published by Cohesity.
.LINK
https://cohesity.github.io/cohesity-powershell-module/#/README
.EXAMPLE
Restore-CohesityRemoteOracleDatabase -TaskName "restore-file-vm" -FileName /C/data/file.txt -JobId 1234 -SourceId 843 -TargetSourceId 856 -RestoreMethod AutoDeploy -TargetVMCredential (Get-Credential)
Restores the specified file/folder to the target VM with specified source id from the latest external target backup.
.EXAMPLE
Restore-CohesityRemoteOracleDatabase -FileName "/C/myFolder" -NewBaseDirectory "C:\temp\restore" -JobId 61592 -SourceId 3517
Restores the specified file/folder in the same server from the latest external target backup.
.EXAMPLE
Restore-CohesityRemoteOracleDatabase -FileName "/C/myFolder" -NewBaseDirectory "C:\temp\restore" -JobId 61592 -SourceId 3517 -SnapshotId "exchjik"
Restores the specified file/folder in the same server from the specified external target backup.
#>

[CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $True, ConfirmImpact = "High")]
Param(
[Parameter(Mandatory = $false)]
# Specifies the name of the restore task.
[string]$TaskName = "Restore-Oracle-Object-" + (Get-Date -Format "dddd-MM-dd-yyyy-HH-mm-ss").ToString(),
[Parameter(Mandatory = $true)]
# Specifies ID of the database to recover.
[string]$DatabaseId,
[Parameter(Mandatory = $true)]
# Specifies the Oracle home directory path.
[string]$OracleHome,
[Parameter(Mandatory = $true)]
# Specifies the Oracle base directory path.
[string]$OracleBase,
[Parameter(Mandatory = $false)]
# Location to put the database files(datafiles, logfiles etc.).
[string]$DatabaseFileDestination,
[Parameter(Mandatory = $true)]
# Specifies the id of an alternate Oracle source where database to be restored.
[long]$TargetSourceId,
[Parameter(Mandatory = $true)]
[ValidateRange(1, [long]::MaxValue)]
# Specifies the job id that backed up this Oracle database.
[long]$JobId,
[Parameter(Mandatory = $false)]
[ValidateRange(1, [long]::MaxValue)]
# Specifies the snapshot id for this Oracle database. If not specified the latest snapshot will be used to restore.
[long]$SnapshotId,
[Parameter(Mandatory = $false)]
# Specifies a new name for the restored database.
[string]$NewDatabaseName,
[Parameter(Mandatory = $false)]
[ValidateRange(2, [long]::MaxValue)]
# Number of redo log groups.
[long]$NumRedoLogGroup,
[Parameter(Mandatory = $false)]
# List of members of this redo log group.
[string[]]$RedoLogMemberPath,
[Parameter(Mandatory = $false)]
# Log member name prefix.
[string]$RedoLogMemberPrefix,
[Parameter(Mandatory = $false)]
[ValidateRange(1, [long]::MaxValue)]
# Size of the member in MB.
[long]$RedoLogSizeInMb,
[Parameter(Mandatory = $false)]
[ValidateRange(1, [long]::MaxValue)]
# Specifies no. of tempfiles to be used for the recovered database.
[long]$NumTempFiles
)
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]

Write-Host $protectionGroupId

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

$searchObj = $searchResult.objects | Where-Object { $_.id -eq $DatabaseId }
Write-Host $searchObj
if (!$searchObj) {
$errorMsg = "Oracle Database with id $DatabaseId not found in specified protection group."
Write-Output $errorMsg
CSLog -Message $errorMsg
return
}

<#
Check if snapshot detail is provided.
If not, collect the latest recoverable job run information.
#>
if ($SnapshotId -eq $null) {
$databaseName = $searchObj.name
$snapshotInfo = $searchObj.latestSnapshotsInfo
if ($snapshotInfo -and $snapshotInfo.Length -ne 0) {
$snapshotObj = $snapshotInfo[0].localSnapshotInfo

if ($snapshotInfo) {
$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
}

# Source with environment type Oracle
switch ($protectionGroup.environment) {
'oracleParams' {
$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 = $BCTFilePath;
databaseName = $NewDatabaseName;
dbFilesDestination = $DatabaseFileDestination;
enableArchiveLogMode = $true;
numTempfiles = $NumTempFiles;
oracleBaseFolder = $OracleBase;
oracleHomeFolder = $OracleHome;
redoLogConf = @{
groupMemberVec = @($RedoLogMemberPath)
memberPrefix = $RedoLogMemberPrefix
numGroups = $NumRedoLogGroup
sizeMb = if ($RedoLogSizeInMb) { $RedoLogSizeInMb } else { 20 }
}
}
}
};
}
}
'kPhysical' {
$payload['physicalParams'] = @{}
$payload['physicalParams']['objects'] = @(
@{
snapshotId = $SnapshotId
}
)
$payload['physicalParams']['recoveryAction'] = 'RecoverFiles'
$payload['physicalParams']['recoverFileAndFolderParams'] = @{
filesAndFolders = @(
@{
absolutePath = $absolutePath;
isDirectory = $isDirectory
}
);
targetEnvironment = 'kPhysical';
physicalTargetParams = @{
recoverTarget = @{
id = $(if ($TargetSourceId) { $TargetSourceId } else { $SourceId });
};
restoreToOriginalPaths = $recoverToOriginalPath;
overwriteExisting = $OverwriteExisting.IsPresent;
preserveAttributes = $PreserveAttributes.IsPresent;
continueOnError = $ContinueOnError.IsPresent;
saveSuccessFiles = $SaveSuccessFiles.IsPresent;
alternateRestoreDirectory = $(if (!$recoverToOriginalPath) { $NewBaseDirectory } else { $null });
};
}
}
'kIsilon' {
$payload['isilonParams'] = @{}
$payload['isilonParams']['objects'] = @(
@{
snapshotId = $SnapshotId
}
)
$payload['isilonParams']['recoveryAction'] = 'RecoverFiles'
$payload['isilonParams']['recoverFileAndFolderParams'] = @{
filesAndFolders = @(
@{
absolutePath = $absolutePath;
isDirectory = $isDirectory
}
);
targetEnvironment = 'kIsilon';
isilonTargetParams = @{
recoverToNewSource = $restoreToNewSource
};
}

if ($restoreToNewSource) {
$payload.isilonParams.recoverFileAndFolderParams.isilonTargetParams['newSourceConfig'] = @{
overwriteExistingFile = $OverwriteExisting.IsPresent;
preserveFileAttributes = $PreserveAttributes.IsPresent;
continueOnError = $ContinueOnError.IsPresent;
encryptionEnabled = $EncryptionEnabled.IsPresent;
volume = @{
id = $TargetSourceId
}
alternatePath = $NewBaseDirectory
}
}
else {
$payload.isilonParams.recoverFileAndFolderParams.isilonTargetParams['originalSourceConfig'] = @{
alternatePath = $(if (!$recoverToOriginalPath) { $NewBaseDirectory } else { $null });
overwriteExistingFile = $OverwriteExisting.IsPresent;
preserveFileAttributes = $PreserveAttributes.IsPresent;
continueOnError = $ContinueOnError.IsPresent;
encryptionEnabled = $encryptionEnabled.IsPresent;
recoverToOriginalPath = $recoverToOriginalPath;
}
}
}
}

$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 {
}
}

0 comments on commit 4f5dabd

Please sign in to comment.