From d3743e46cd4c9da6884d121247336bd7d397e62c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Feb 2022 18:10:48 +0530 Subject: [PATCH 1/5] Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 is newly to Restore the DB based on SqlHost, SqlObjectName and TargetHost. Restore-CohesityRemoteMSSQLObject.ps1 : DbRestoreOverwritePolicy option is newly added --- .../Cohesity.PowerShell.Core.psd1 | 3 +- .../Cohesity.PowerShell.psd1 | 1 + ...tore-CohesityRemoteMSSQLObject-Wrapper.ps1 | 234 ++++++++++++++++++ .../Restore-CohesityRemoteMSSQLObject.ps1 | 12 +- 4 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 diff --git a/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 b/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 index 7f2ad68b..4158da68 100644 --- a/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 +++ b/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 @@ -132,6 +132,7 @@ FunctionsToExport = @( 'Restore-CohesityBackupToView', 'Restore-CohesityRemoteFile', 'Restore-CohesityRemoteMSSQLObject', + 'Restore-CohesityRemoteMSSQLObject-Wrapper', 'Restore-CohesityVMwareVM', 'Save-CohesityFile', 'Set-CohesityAlertResolutions', @@ -248,7 +249,7 @@ PrivateData = @{ # A URL to an icon representing this module. IconUri = 'https://i.imgur.com/ZbvCiaC.png' - #Prerelease = 'alpha2' + #Prerelease = 'alpha2' # ReleaseNotes of this module ReleaseNotes = 'https://cohesity.github.io/cohesity-powershell-module' diff --git a/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 b/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 index c9ef87e2..6ad4061d 100644 --- a/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 +++ b/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 @@ -132,6 +132,7 @@ FunctionsToExport = @( 'Restore-CohesityBackupToView', 'Restore-CohesityRemoteFile', 'Restore-CohesityRemoteMSSQLObject', + 'Restore-CohesityRemoteMSSQLObject-Wrapper', 'Restore-CohesityVMwareVM', 'Save-CohesityFile', 'Set-CohesityAlertResolutions', diff --git a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 new file mode 100644 index 00000000..033ed0f7 --- /dev/null +++ b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 @@ -0,0 +1,234 @@ + +function Restore-CohesityRemoteMSSQLObject-Wrapper { + + <# + .SYNOPSIS + From remote cluster restores the specified MS SQL object from a previous backup. + .DESCRIPTION + From remote cluster restores the specified MS SQL object from a previous backup. + .NOTES + Published by Cohesity + .LINK + https://cohesity.github.io/cohesity-powershell-module/#/README + .EXAMPLE + Restore-CohesityRemoteMSSQLObject-Wrapper -JobId 5501 -SqlHost 10.14.46.43 -SqlObjectName "MSSQLSERVER/ReportServerTempDB" -TargetHost 10.14.46.56 -CaptureTailLogs:$false -NewDatabaseName ReportServerTempDB_123 -NewInstanceName SQL2016 -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true + Restore MSSQL database from remote cluster for Job Id 5501 , SqlHost 10.14.46.43 and SqlObjectName MSSQLSERVER/ReportServerTempDB at TargetHost 10.14.46.56 with existing DB overwrite policy + $sqlRecords = Find-CohesityObjectsForRestore -Environments KSQL | Where-Object { $_.ObjectName -eq $SqlObjectName} + $record.JobID -eq $JobId + Matching the JobID from sqlRecords based on SQLObjectName + /irisservices/api/v1/searchvms + Finding the equivalent SqlHost from the Rest call to extract SourceId and HostSourceId + Get-CohesityProtectionSource -Environments KSQL + Finding the TargetHostId from the above cmdlet + Get-CohesityProtectionJobRun -JobId $JobId + Identifying the JobRunId and StartTime based on the last known unexpired snapshot + here the curent system time should be less than the recent successful snapshot expiry time + .EXAMPLE + Restore-CohesityRemoteMSSQLObject-Wrapper -JobId 5501 -SqlHost 10.14.46.43 -SqlObjectName "MSSQLSERVER/ReportServerTempDB" -TargetHost 10.14.46.56 -CaptureTailLogs:$false -NewDatabaseName ReportServerTempDB_123 -NewInstanceName SQL2016 -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true + #> + [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $True, ConfirmImpact = "High")] + Param( + + [Parameter(Mandatory = $true)] + # Specifies the SQL Host information + [string]$SqlHost, + + [Parameter(Mandatory = $true)] + # Specifies the SQL Object Name + [string]$SqlObjectName, + + [Parameter(Mandatory = $true)] + [ValidateRange(1, [long]::MaxValue)] + # Specifies the job id that backed up this MS SQL instance and will be used for this restore. + [long]$JobId, + + [Parameter(Mandatory = $true)] + # Specifies the target host to restore + [string]$TargetHost, + + [Parameter(Mandatory = $false)] + # Specifies if the tail logs are to be captured before the restore operation. + # This is only applicable if restoring the SQL database to its hosting Protection Source and the database is not being renamed. + [switch]$CaptureTailLogs, + [Parameter(Mandatory = $false)] + # This field prevents "change data capture" settings from being reomved. + # When a database or log backup is restored on another server and database is recovered. + [switch]$KeepCDC, + + [Parameter(Mandatory = $false)] + # Specifies a new name for the restored database. + [string]$NewDatabaseName, + + [Parameter(Mandatory = $false)] + # Specifies the instance name of the SQL Server that should be restored. + [string]$NewInstanceName, + + [Parameter(Mandatory = $false)] + # Specifies the time in the past to which the SQL database needs to be restored. + # This allows for granular recovery of SQL databases. + # If not specified, the SQL database will be restored from the full/incremental snapshot. + [long]$RestoreTimeSecs = 0, + + [Parameter(Mandatory = $false)] + # Specifies the directory where to put the database data files. + # Missing directory will be automatically created. + # This field must be set if restoring to a different target host. + [string]$TargetDataFilesDirectory, + + [Parameter(Mandatory = $false)] + # Specifies the directory where to put the database log files. + # Missing directory will be automatically created. + # This field must be set if restoring to a different target host. + [string]$TargetLogFilesDirectory, + + [Parameter(Mandatory = $false)] + # This field will overwrite the existing db contents if it sets to true + # By default the db overwrite policy is false + [switch]$DbRestoreOverwritePolicy, + + [Parameter(Mandatory = $false)] + # Specifies the secondary data filename pattern and corresponding directories of the DB. Secondary data + # files are optional and are user defined. The recommended file extension for secondary files is + # ".ndf". If this option is specified and the destination folders do not exist they will be + # automatically created. + # This field can be set only if restoring to a different target host. + [Object[]]$TargetSecondaryDataFilesDirectoryList + ) + Begin { + } + + Process { + + $job = Get-CohesityProtectionJob -Ids $JobId + if (-not $job) { + Write-Output "Cannot proceed, the job id '$JobId' is invalid" + return + } + + $SourceId = 0 + $HostSourceId + $TargetHostId = 0 + $JobRunId + $StartTime + + $sqlRecords = Find-CohesityObjectsForRestore -Environments KSQL | Where-Object { $_.ObjectName -eq $SqlObjectName} + + $searchedVMDetails = $null + $searchIndex = 0 + $continuePagination = $true + $searchTotalCount = 0 + + foreach ($record in $sqlRecords) { + + if ($record.JobID -eq $JobId) { + + while ($continuePagination) { + $searchURL = '/irisservices/api/v1/searchvms?from=' + $searchIndex + '&environment=SQL&entityTypes=kSQL&showAll=false&onlyLatestVersion=true&jobIds=' + $JobId + $searchResult = Invoke-RestApi -Method Get -Uri $searchURL + + if ($Global:CohesityAPIStatus.StatusCode -ne 200) { + Write-Output "Could not search MSSQL objects with the job id $JobId" + return + } + + $indiVm = $searchResult.vms + foreach($vm in $indiVm) { + + # SourceId and HostSource + if ($vm.vmDocument.objectAliases[0] -eq $SqlHost) { + + $SourceId = $record.SnapshottedSource.Id + $HostSourceId = $record.SnapshottedSource.ParentId + break + } + } + + $searchedVMDetails = $searchResult.vms | Where-Object { ($_.vmDocument.objectId.jobId -eq $JobId) -and ($_.vmDocument.objectId.entity.id -eq $SourceId) } + + if ($searchTotalCount -eq 0) { + # find the expected number of search result items + $searchTotalCount = $searchResult.count + } + + if ($searchedVMDetails) { + $errorMsg = "Found database with search index " + $searchIndex + ", and total item count " + $searchTotalCount + CSLog -Message $errorMsg + $continuePagination = $false + } + + # the number of items skimmed + $searchIndex += $searchResult.vms.Count + + if ($searchIndex -ge $searchTotalCount) { + $continuePagination = $false + } + if ($continuePagination -eq $false) { + break + } + } + if ($null -eq $searchedVMDetails) { + Write-Output "Could not find details for MSSQL source id = $SourceId , and Job id = $JobId" + return + } + } + } + + if ($SourceId -eq 0) { + Write-Output "Cannot proceed, Unable to find SourceId" + return + } + + $protectionSources = Get-CohesityProtectionSource -Environments KSQL + foreach ($record in $protectionSources) { + + if($record.protectionSource.Name -eq $TargetHost) { + + $TargetHostId = $record.protectionSource.id + } + } + + if ($TargetHostId -eq 0) { + Write-Output "Unable to find TargetHostId for $TargetHost" + return + } + + # Identifying the JobRunId and StartTime based on the last known unexpired snapshot + # here the curent system time should be less than the recent successful snapshot expiry time + $runs = Get-CohesityProtectionJobRun -JobId $JobId -ExcludeErrorRuns:$true + foreach ($record in $runs) { + + $expiryEpocTime = $record.copyRun[0].expiryTimeUsecs + $currentTime = Get-Date + $currentEpocTime = Get-Date $currentTime -UFormat %s + if ($currentEpocTime -le $expiryEpocTime) { + + $JobRunId = $record[0].backupRun.jobRunId + $StartTime = $record.copyRun[0].runStartTimeUsecs + break + } + } + + $sqlRestoreParams = @{ + JobID = $JobId + SourceID = $SourceId + HostSourceID = $HostSourceId + TargetHostID = $TargetHostId + JobRunId = $JobRunId + StartTime = $StartTime + CaptureTailLogs = $CaptureTailLogs.IsPresent + KeepCDC = $KeepCDC.isPresent + NewDatabaseName = $NewDatabaseName + NewInstanceName = $NewInstanceName + Verbose = $true + Confirm = $false + TargetDataFilesDirectory = $TargetDataFilesDirectory + TargetLogFilesDirectory = $TargetLogFilesDirectory + TargetSecondaryDataFilesDirectoryList = $TargetSecondaryDataFilesDirectoryList + RestoreTimeSecs = $RestoreTimeSecs + DbRestoreOverwritePolicy = $DbRestoreOverwritePolicy + } + Restore-CohesityRemoteMSSQLObject @sqlRestoreParams + } + End { + } +} \ No newline at end of file diff --git a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 index 90a8f379..46fee544 100644 --- a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 +++ b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 @@ -9,11 +9,12 @@ function Restore-CohesityRemoteMSSQLObject { .LINK https://cohesity.github.io/cohesity-powershell-module/#/README .EXAMPLE - Restore-CohesityRemoteMSSQLObject -SourceId 1279 -HostSourceId 1277 -JobId 31520 -TargetHostId 770 -CaptureTailLogs:$false -NewDatabaseName CohesityDB_r1 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" + Restore-CohesityRemoteMSSQLObject -SourceId 1279 -HostSourceId 1277 -JobId 31520 -TargetHostId 770 -CaptureTailLogs:$false -NewDatabaseName CohesityDB_r1 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true Restore MSSQL database from remote cluster with database id 1279 , database instance id 1277 and job id as 31520 $mssqlObjects = Find-CohesityObjectsForRestore -Environments KSQL Get the source id, $mssqlObjects[0].SnapshottedSource.Id Get the source instance id, $mssqlObjects[0].SnapshottedSource.SqlProtectionSource.OwnerId + Use the DbRestoreOverwritePolicy:$true for overriding the existing database .EXAMPLE Restore-CohesityRemoteMSSQLObject -SourceId 3101 -HostSourceId 3099 -JobId 51275 -TargetHostId 3098 -CaptureTailLogs:$false -NewDatabaseName ReportServer_r26 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" -StartTime 1616956306627994 -JobRunId 60832 -RestoreTimeSecs 1616958037 Request for restore MSSQL object with RestoreTimeSecs (point in time) parameter, StartTime and JobRunId. @@ -91,6 +92,10 @@ function Restore-CohesityRemoteMSSQLObject { # This field can be set only if restoring to a different target host. [Object[]]$TargetSecondaryDataFilesDirectoryList, [Parameter(Mandatory = $false)] + # This field will overwrite the existing db contents if it sets to true + # By default the db overwrite policy is false + [switch]$DbRestoreOverwritePolicy, + [Parameter(Mandatory = $false)] [ValidateRange(1, [long]::MaxValue)] # Specifies the target host if the application is to be restored to a different host. # If not specified, then the application is restored to the original host (physical or virtual) that hosted this application. @@ -263,6 +268,11 @@ function Restore-CohesityRemoteMSSQLObject { alternateLocationParams = @{} } + if ($DbRestoreOverwritePolicy -eq $true) { + + $sqlRestoreParams | Add-Member -NotePropertyName dbRestoreOverwritePolicy -NotePropertyValue "kOverwrite" + } + if ($RestoreTimeSecs -gt 0) { $sqlRestoreParams | Add-Member -NotePropertyName restoreTimeSecs -NotePropertyValue $RestoreTimeSecs } From edbc12505fd006841c301b595d5145f6ec80b627 Mon Sep 17 00:00:00 2001 From: KavishreeShanmugam11 Date: Wed, 6 Dec 2023 12:16:33 +0530 Subject: [PATCH 2/5] Added markdown file for MSSQLremote restore wrapper function. --- ...store-cohesityremotemssqlobject-wrapper.md | 289 ++++++++++++++++++ docs/sidebar.md | 1 + 2 files changed, 290 insertions(+) create mode 100644 docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md diff --git a/docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md b/docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md new file mode 100644 index 00000000..4b553056 --- /dev/null +++ b/docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md @@ -0,0 +1,289 @@ +# Restore-CohesityRemoteMSSQLObject-Wrapper + +## SYNOPSIS +From remote cluster restores the specified MS SQL object from a previous backup. + +## SYNTAX + +### Default (Default) +``` +Restore-CohesityRemoteMSSQLObject-Wrapper [-CaptureTailLogs] [-DbRestoreOverwritePolicy] [-JobId ] [-KeepCDC] [-NewDatabaseName ] [-NewInstanceName ] [-SqlHost ] [-RestoreTimeSecs ] [-SqlObjectName ] [-TargetHost ] [-TargetDataFilesDirectory ] [-TargetLogFilesDirectory ] [-TargetSecondaryDataFilesDirectoryList ] +``` + +## DESCRIPTION +From remote cluster restores the specified MS SQL object from a last successful backup. + +## EXAMPLES + +### EXAMPLE 1 +``` +Restore-CohesityRemoteMSSQLObject-Wrapper -JobId 1234 -SqlHost x.x.x.x -SqlObjectName "MSSQLSERVER/database" -TargetHost y.y.y.y -CaptureTailLogs:$false -NewDatabaseName database_new -NewInstanceName SQLInstance_new -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true +``` + +Restore MSSQL database from remote cluster with Job Id 1234, SqlHost x.x.x.x and SqlObjectName MSSQLSERVER/database at TargetHost y.y.y.y from last successfull backup, with existing DB overwrite policy + +For secondary data files, construct the $patternList as follows +$patternList = @() +$pattern1 = @{filePattern = "*.mdf"; targetDirectory = "c:\test"} +$pattern2 = @{filePattern = "*.ldf"; targetDirectory = "c:\test1"} +$patternList += $pattern1 +$patternList += $pattern2 + +## PARAMETERS + +### -SqlHost +Specifies the SQL host from which database need to be restored. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SqlObjectName +Specifies the name of the SQL Object to be restored. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -JobId +Specifies the job id that backed up this MS SQL instance and will be used for this restore. + +```yaml +Type: Int64 +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CaptureTailLogs +Specifies if the tail logs are to be captured before the restore operation. +This is only applicable if restoring the SQL database to its hosting Protection Source and the database is not being renamed. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DbRestoreOverwritePolicy +This field will overwrite the existing db contents if it sets to true +By default the db overwrite policy is false + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -KeepCDC +This field prevents "change data capture" settings from being reomved. +When a database or log backup is restored on another server and database is recovered. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NewDatabaseName +Specifies a new name for the restored database. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NewInstanceName +Specifies the instance name of the SQL Server that should be restored. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RestoreTimeSecs +Specifies the time in the past to which the SQL database needs to be restored. +This allows for granular recovery of SQL databases. +If not specified, the SQL database will be restored from the full/incremental snapshot. + +```yaml +Type: Int64 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TargetDataFilesDirectory +Specifies the directory where to put the database data files. +Missing directory will be automatically created. +This field must be set if restoring to a different target host. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TargetLogFilesDirectory +Specifies the directory where to put the database log files. +Missing directory will be automatically created. +This field must be set if restoring to a different target host. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TargetSecondaryDataFilesDirectoryList +Specifies the secondary data filename pattern and corresponding directories of the DB. +Secondary data +files are optional and are user defined. +The recommended file extension for secondary files is +".ndf". +If this option is specified and the destination folders do not exist they will be +automatically created. +This field can be set only if restoring to a different target host. + +```yaml +Type: Object[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TargetHost +Specifies the target host if the application is to be restored to a different host. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +Published by Cohesity + +## RELATED LINKS + +[https://cohesity.github.io/cohesity-powershell-module/#/README](https://cohesity.github.io/cohesity-powershell-module/#/README) + diff --git a/docs/sidebar.md b/docs/sidebar.md index e64a5fb6..5683fb63 100644 --- a/docs/sidebar.md +++ b/docs/sidebar.md @@ -144,6 +144,7 @@ - [Find-CohesityObjectsForRestore](cmdlets-reference/find-cohesityobjectsforrestore.md) - [Restore-CohesityMSSQLObject](cmdlets-reference/restore-cohesitymssqlobject.md) - [Restore-CohesityRemoteMSSQLObject](cmdlets-reference/restore-cohesityremotemssqlobject.md) +- [Restore-CohesityRemoteMSSQLObject-Wrapper](cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md) - [Restore-CohesityVMwareVM](cmdlets-reference/restore-cohesityvmwarevm.md) - [Restore-CohesityHyperVVM](cmdlets-reference/restore-cohesityhypervvm.md) - [Restore-CohesityAcropolisVM](cmdlets-reference/restore-cohesityacropolisvm.md) From 70f8cdce04e1a05fdefc3cea1afebc0196d5f85c Mon Sep 17 00:00:00 2001 From: KavishreeShanmugam11 Date: Thu, 7 Dec 2023 14:51:35 +0530 Subject: [PATCH 3/5] Included switch parameter to return result as object. --- .../Get-CohesityProtectionJobStatus.ps1 | 23 +++++++++++------ ...egister-CohesityProtectionSourceHyperV.ps1 | 25 +++++++++++++------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/Cohesity.Powershell/Scripts/ProtectionJob/Get-CohesityProtectionJobStatus.ps1 b/src/Cohesity.Powershell/Scripts/ProtectionJob/Get-CohesityProtectionJobStatus.ps1 index a23c0756..8270bf09 100644 --- a/src/Cohesity.Powershell/Scripts/ProtectionJob/Get-CohesityProtectionJobStatus.ps1 +++ b/src/Cohesity.Powershell/Scripts/ProtectionJob/Get-CohesityProtectionJobStatus.ps1 @@ -54,6 +54,10 @@ function Get-CohesityProtectionJobStatus { #> [CmdletBinding()] Param( + [Parameter( + Position = 1, + HelpMessage = "Return Output as Object")] + [Switch]$ReturnObject ) Begin { @@ -146,13 +150,18 @@ function Get-CohesityProtectionJobStatus { } $columnWidth = 20 - $protectionJobStatusList | Sort-Object -Property startTime -Descending | - Format-Table @{ Label = 'ID'; Expression = { $_.jobId }; }, - @{ Label = 'NAME'; Expression = { $_.jobName }; Width = $columnWidth; }, - @{ Label = 'REMOTE COPY'; Expression = { $_.remoteCopy }; Width = $columnWidth }, - @{ Label = 'STARTED AT'; Expression = { $_.GetStartTime() }; Width = $columnWidth }, - @{ Label = 'ESTIMATED TIME'; Expression = { $_.GetEstimatedTime() }; Width = $columnWidth }, - @{ Label = 'COMPLETED(%)'; Expression = { $_.percentCompleted }; Width = $columnWidth } + if ($ReturnObject -eq $true) { + return $protectionJobStatusList + } + else { + $protectionJobStatusList | Sort-Object -Property startTime -Descending | + Format-Table @{ Label = 'ID'; Expression = { $_.jobId }; }, + @{ Label = 'NAME'; Expression = { $_.jobName }; Width = $columnWidth; }, + @{ Label = 'REMOTE COPY'; Expression = { $_.remoteCopy }; Width = $columnWidth }, + @{ Label = 'STARTED AT'; Expression = { $_.GetStartTime() }; Width = $columnWidth }, + @{ Label = 'ESTIMATED TIME'; Expression = { $_.GetEstimatedTime() }; Width = $columnWidth }, + @{ Label = 'COMPLETED(%)'; Expression = { $_.percentCompleted }; Width = $columnWidth } + } } End { diff --git a/src/Cohesity.Powershell/Scripts/ProtectionSource/Register-CohesityProtectionSourceHyperV.ps1 b/src/Cohesity.Powershell/Scripts/ProtectionSource/Register-CohesityProtectionSourceHyperV.ps1 index 6811441a..6064ce8e 100644 --- a/src/Cohesity.Powershell/Scripts/ProtectionSource/Register-CohesityProtectionSourceHyperV.ps1 +++ b/src/Cohesity.Powershell/Scripts/ProtectionSource/Register-CohesityProtectionSourceHyperV.ps1 @@ -1,5 +1,5 @@ function Register-CohesityProtectionSourceHyperV { - <# + <# .SYNOPSIS Registers a new HyperV protection source with the Cohesity Cluster. The HyperV type can be a SCVMM server or HyperV Host. .DESCRIPTION @@ -29,7 +29,10 @@ function Register-CohesityProtectionSourceHyperV { [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] # User credentials for the SCVMM server. - [System.Management.Automation.PSCredential]$Credentials + [System.Management.Automation.PSCredential]$Credentials, + # Set to true, if result need to returned in object format + [Parameter(Position = 1, HelpMessage = "Return Output as Object", Mandatory = $false)] + [Switch]$ReturnObject ) Begin { @@ -37,7 +40,7 @@ function Register-CohesityProtectionSourceHyperV { Process { - $uri = '/irisservices/api/v1/public/protectionSources/register' + $uri = '/irisservices/api/v1/public/protectionSources/register' if ($HyperVType -eq 'KSCVMMServer') { $reqParameters = @{ @@ -58,10 +61,16 @@ function Register-CohesityProtectionSourceHyperV { $columnWidth = 20 $request = $reqParameters | ConvertTo-Json - Invoke-RestApi -Method Post -Uri $uri -Body $request | - Format-Table @{ Label = 'ID'; Expression = { $_.id }; }, - @{ Label = 'Name'; Expression = { $_.name }; Width = $columnWidth; }, - @{ Label = 'Environment'; Expression = { $_.environment }; Width = $columnWidth }, - @{ Label = 'Type'; Expression = { $_.hypervProtectionSource.type }; Width = $columnWidth } + $result = Invoke-RestApi -Method Post -Uri $uri -Body $request + + if ($ReturnObject -eq $true) { + return $result + } + else { + $result | Format-Table @{ Label = 'ID'; Expression = { $_.id }; }, + @{ Label = 'Name'; Expression = { $_.name }; Width = $columnWidth; }, + @{ Label = 'Environment'; Expression = { $_.environment }; Width = $columnWidth }, + @{ Label = 'Type'; Expression = { $_.hypervProtectionSource.type }; Width = $columnWidth } + } } # End of process } # End of function \ No newline at end of file From aff3014101215555bf9c5c27e9ef9c1531a1bf11 Mon Sep 17 00:00:00 2001 From: KavishreeShanmugam11 Date: Thu, 7 Dec 2023 20:21:39 +0530 Subject: [PATCH 4/5] Moved wrapper script from cmdlet to sample script --- ...tore-CohesityRemoteMSSQLObject-Wrapper.ps1 | 148 +++++++++++ .../Cohesity.PowerShell.Core.psd1 | 5 +- .../Cohesity.PowerShell.psd1 | 1 - ...tore-CohesityRemoteMSSQLObject-Wrapper.ps1 | 234 ------------------ .../Restore-CohesityRemoteMSSQLObject.ps1 | 78 +++++- 5 files changed, 215 insertions(+), 251 deletions(-) create mode 100644 samples/RestoreSQLDB/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 delete mode 100644 src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 diff --git a/samples/RestoreSQLDB/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 b/samples/RestoreSQLDB/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 new file mode 100644 index 00000000..9d0769ed --- /dev/null +++ b/samples/RestoreSQLDB/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 @@ -0,0 +1,148 @@ +<# + Use the generic cmdlet to create an MSSQL remote restore task + + Example usage: + Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 -JobId 1234 -SqlHost x.x.x.x -SqlObjectName "MSSQLSERVER/database" -TargetHost y.y.y.y -CaptureTailLogs:$false -NewDatabaseName database_new -NewInstanceName SQL2016 -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true +#> +[CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $True, ConfirmImpact = "High")] +Param( + [Parameter(Mandatory = $false)][switch]$CaptureTailLogs, # Specifies if the tail logs are to be captured before the restore operation. This is only applicable if restoring the SQL database to its hosting Protection Source and the database is not being renamed. + [Parameter(Mandatory = $false)][switch]$DbRestoreOverwritePolicy, # This field will overwrite the existing db contents if it sets to true. By default the db overwrite policy is false. + [Parameter(Mandatory = $true)][ValidateRange(1, [long]::MaxValue)][long]$JobId, # Specifies the job id that backed up this MS SQL instance and will be used for this restore + [Parameter(Mandatory = $false)][switch]$KeepCDC, # This field prevents "change data capture" settings from being reomved. When a database or log backup is restored on another server and database is recovered. + [Parameter(Mandatory = $false)][string]$NewDatabaseName, # Specifies a new name for the restored database. + [Parameter(Mandatory = $false)][string]$NewInstanceName, # Specifies the instance name of the SQL Server that should be restored. + [Parameter(Mandatory = $false)][long]$RestoreTimeSecs = 0, # Specifies the time in the past to which the SQL database needs to be restored. This allows for granular recovery of SQL databases. If not specified, the SQL database will be restored from the full/incremental snapshot. + [Parameter(Mandatory = $true)][string]$SqlHost, # Specifies the SQL Host information + [Parameter(Mandatory = $true)][string]$SqlObjectName, # Specifies the SQL Object Name + [Parameter(Mandatory = $false)][string]$TargetDataFilesDirectory, # Specifies the directory where to put the database data files. Missing directory will be automatically created. This field must be set if restoring to a different target host. + [Parameter(Mandatory = $true)][string]$TargetHost, # Specifies the target host to restore + [Parameter(Mandatory = $false)][string]$TargetLogFilesDirectory, # Specifies the directory where to put the database log files. Missing directory will be automatically created. This field must be set if restoring to a different target host. + [Parameter(Mandatory = $false)][Object[]]$TargetSecondaryDataFilesDirectoryList # Specifies the secondary data filename pattern and corresponding directories of the DB. Secondary data files are optional and are user defined. The recommended file extension for secondary files is ".ndf". If this option is specified and the destination folders do not exist they will be automatically created. This field can be set only if restoring to a different target host. +) + +# Check if specified job exists +$job = Get-CohesityProtectionJob -Ids $JobId +if (-not $job) { + Write-Output "Cannot proceed, the job id '$JobId' is invalid" + return +} + +$HostSourceId +$JobRunId +$SourceId = 0 +$StartTime +$TargetHostId = 0 + +# Get the list of SQL objects that can be restored and fetch the id of the specified SQL host +$sqlRecords = Find-CohesityObjectsForRestore -Environments KSQL -JobIds $JobId | Where-Object { $_.ObjectName -eq $SqlObjectName } + +$searchedVMDetails = $null +$searchIndex = 0 +$continuePagination = $true +$searchTotalCount = 0 + +# Loop through the result to fetch the specified SQL host id and parent id +foreach ($record in $sqlRecords) { + while ($continuePagination) { + $searchURL = '/irisservices/api/v1/searchvms?from=' + $searchIndex + '&environment=SQL&entityTypes=kSQL&showAll=false&onlyLatestVersion=true&jobIds=' + $JobId + $searchVMResult = Invoke-RestApi -Method Get -Uri $searchURL + + if ($Global:CohesityAPIStatus.StatusCode -ne 200) { + Write-Output "Could not search MSSQL objects associated with the job id $JobId" + return + } + + $vmList = $searchVMResult.vms + foreach ($vm in $vmList) { + if ($vm.vmDocument.objectAliases[0] -eq $SqlHost) { + $SourceId = $record.SnapshottedSource.Id + $HostSourceId = $record.SnapshottedSource.ParentId + break + } + } + + $searchedVMDetails = $searchVMResult.vms | Where-Object { ($_.vmDocument.objectId.jobId -eq $JobId) -and ($_.vmDocument.objectId.entity.id -eq $SourceId) } + + if ($searchTotalCount -eq 0) { + # find the expected number of search result items + $searchTotalCount = $searchVMResult.count + } + + if ($searchedVMDetails) { + $infoMsg = "Found database with search index " + $searchIndex + ", and total item count " + $searchTotalCount + CSLog -Message $infoMsg + $continuePagination = $false + } + + # the number of items skimmed + $searchIndex += $searchVMResult.vms.Count + + if ($searchIndex -ge $searchTotalCount) { + $continuePagination = $false + } + if ($continuePagination -eq $false) { + break + } + } + if ($null -eq $searchedVMDetails) { + Write-Output "Could not find details of MSSQL host '$SqlHost'." + return + } +} + +if ($SourceId -eq 0) { + Write-Output "Cannot proceed, Unable to find source id for SQL host '$SqlHost'" + return +} + +# Fin dthe Id of specified target host +$protectionSources = Get-CohesityProtectionSource -Environments KSQL +foreach ($record in $protectionSources) { + if ($record.protectionSource.Name -eq $TargetHost) { + $TargetHostId = $record.protectionSource.id + } +} + +if ($TargetHostId -eq 0) { + Write-Output "Unable to find host if for $TargetHost" + return +} + +# Identifying the JobRunId and StartTime based on the last known unexpired snapshot +# here the curent system time should be less than the recent successful snapshot expiry time +$runs = Get-CohesityProtectionJobRun -JobId $JobId -ExcludeErrorRuns:$true +foreach ($record in $runs) { + + $expiryEpocTime = $record.copyRun[0].expiryTimeUsecs + $currentTime = Get-Date + $currentEpocTime = Get-Date $currentTime -UFormat %s + if ($currentEpocTime -le $expiryEpocTime) { + + $JobRunId = $record[0].backupRun.jobRunId + $StartTime = $record.copyRun[0].runStartTimeUsecs + break + } +} + +$sqlRestoreParams = @{ + JobID = $JobId + SourceID = $SourceId + HostSourceID = $HostSourceId + TargetHostID = $TargetHostId + JobRunId = $JobRunId + StartTime = $StartTime + CaptureTailLogs = $CaptureTailLogs.IsPresent + KeepCDC = $KeepCDC.isPresent + NewDatabaseName = $NewDatabaseName + NewInstanceName = $NewInstanceName + Verbose = $true + Confirm = $false + TargetDataFilesDirectory = $TargetDataFilesDirectory + TargetLogFilesDirectory = $TargetLogFilesDirectory + TargetSecondaryDataFilesDirectoryList = $TargetSecondaryDataFilesDirectoryList + RestoreTimeSecs = $RestoreTimeSecs + DbRestoreOverwritePolicy = $DbRestoreOverwritePolicy +} + +Restore-CohesityRemoteMSSQLObject @sqlRestoreParams \ No newline at end of file diff --git a/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 b/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 index 382c6502..fa237e51 100644 --- a/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 +++ b/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 @@ -76,7 +76,7 @@ FunctionsToExport = @( 'Copy-CohesityView', 'Copy-CohesityVMwareVM', 'Find-CohesityFileSnapshot', - 'Find-CohesityRemoteRestFileSnapshot', + 'Find-CohesityRemoteFileSnapshot', 'Get-CohesityActiveDirectory', 'Get-CohesityCmdletConfig', 'Get-CohesityExternalClient', @@ -132,12 +132,11 @@ FunctionsToExport = @( 'Remove-CohesityVirtualIP', 'Remove-CohesityVlan', 'Restore-CohesityBackupToView', - 'Restore-CohesityFileV2' + 'Restore-CohesityFileV2', 'Restore-CohesityRemoteFile', 'Restore-CohesityRemoteFileV2', 'Restore-CohesityOracleDatabase', 'Restore-CohesityRemoteMSSQLObject', - 'Restore-CohesityRemoteMSSQLObject-Wrapper', 'Restore-CohesityVMwareVM', 'Save-CohesityFile', 'Set-CohesityAlertResolutions', diff --git a/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 b/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 index 35d92f92..1abbca8e 100644 --- a/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 +++ b/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 @@ -136,7 +136,6 @@ FunctionsToExport = @( 'Restore-CohesityRemoteFile', 'Restore-CohesityRemoteFileV2', 'Restore-CohesityRemoteMSSQLObject', - 'Restore-CohesityRemoteMSSQLObject-Wrapper', 'Restore-CohesityOracleDatabase', 'Restore-CohesityVMwareVM', 'Save-CohesityFile', diff --git a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 deleted file mode 100644 index 033ed0f7..00000000 --- a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject-Wrapper.ps1 +++ /dev/null @@ -1,234 +0,0 @@ - -function Restore-CohesityRemoteMSSQLObject-Wrapper { - - <# - .SYNOPSIS - From remote cluster restores the specified MS SQL object from a previous backup. - .DESCRIPTION - From remote cluster restores the specified MS SQL object from a previous backup. - .NOTES - Published by Cohesity - .LINK - https://cohesity.github.io/cohesity-powershell-module/#/README - .EXAMPLE - Restore-CohesityRemoteMSSQLObject-Wrapper -JobId 5501 -SqlHost 10.14.46.43 -SqlObjectName "MSSQLSERVER/ReportServerTempDB" -TargetHost 10.14.46.56 -CaptureTailLogs:$false -NewDatabaseName ReportServerTempDB_123 -NewInstanceName SQL2016 -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true - Restore MSSQL database from remote cluster for Job Id 5501 , SqlHost 10.14.46.43 and SqlObjectName MSSQLSERVER/ReportServerTempDB at TargetHost 10.14.46.56 with existing DB overwrite policy - $sqlRecords = Find-CohesityObjectsForRestore -Environments KSQL | Where-Object { $_.ObjectName -eq $SqlObjectName} - $record.JobID -eq $JobId - Matching the JobID from sqlRecords based on SQLObjectName - /irisservices/api/v1/searchvms - Finding the equivalent SqlHost from the Rest call to extract SourceId and HostSourceId - Get-CohesityProtectionSource -Environments KSQL - Finding the TargetHostId from the above cmdlet - Get-CohesityProtectionJobRun -JobId $JobId - Identifying the JobRunId and StartTime based on the last known unexpired snapshot - here the curent system time should be less than the recent successful snapshot expiry time - .EXAMPLE - Restore-CohesityRemoteMSSQLObject-Wrapper -JobId 5501 -SqlHost 10.14.46.43 -SqlObjectName "MSSQLSERVER/ReportServerTempDB" -TargetHost 10.14.46.56 -CaptureTailLogs:$false -NewDatabaseName ReportServerTempDB_123 -NewInstanceName SQL2016 -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true - #> - [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $True, ConfirmImpact = "High")] - Param( - - [Parameter(Mandatory = $true)] - # Specifies the SQL Host information - [string]$SqlHost, - - [Parameter(Mandatory = $true)] - # Specifies the SQL Object Name - [string]$SqlObjectName, - - [Parameter(Mandatory = $true)] - [ValidateRange(1, [long]::MaxValue)] - # Specifies the job id that backed up this MS SQL instance and will be used for this restore. - [long]$JobId, - - [Parameter(Mandatory = $true)] - # Specifies the target host to restore - [string]$TargetHost, - - [Parameter(Mandatory = $false)] - # Specifies if the tail logs are to be captured before the restore operation. - # This is only applicable if restoring the SQL database to its hosting Protection Source and the database is not being renamed. - [switch]$CaptureTailLogs, - [Parameter(Mandatory = $false)] - # This field prevents "change data capture" settings from being reomved. - # When a database or log backup is restored on another server and database is recovered. - [switch]$KeepCDC, - - [Parameter(Mandatory = $false)] - # Specifies a new name for the restored database. - [string]$NewDatabaseName, - - [Parameter(Mandatory = $false)] - # Specifies the instance name of the SQL Server that should be restored. - [string]$NewInstanceName, - - [Parameter(Mandatory = $false)] - # Specifies the time in the past to which the SQL database needs to be restored. - # This allows for granular recovery of SQL databases. - # If not specified, the SQL database will be restored from the full/incremental snapshot. - [long]$RestoreTimeSecs = 0, - - [Parameter(Mandatory = $false)] - # Specifies the directory where to put the database data files. - # Missing directory will be automatically created. - # This field must be set if restoring to a different target host. - [string]$TargetDataFilesDirectory, - - [Parameter(Mandatory = $false)] - # Specifies the directory where to put the database log files. - # Missing directory will be automatically created. - # This field must be set if restoring to a different target host. - [string]$TargetLogFilesDirectory, - - [Parameter(Mandatory = $false)] - # This field will overwrite the existing db contents if it sets to true - # By default the db overwrite policy is false - [switch]$DbRestoreOverwritePolicy, - - [Parameter(Mandatory = $false)] - # Specifies the secondary data filename pattern and corresponding directories of the DB. Secondary data - # files are optional and are user defined. The recommended file extension for secondary files is - # ".ndf". If this option is specified and the destination folders do not exist they will be - # automatically created. - # This field can be set only if restoring to a different target host. - [Object[]]$TargetSecondaryDataFilesDirectoryList - ) - Begin { - } - - Process { - - $job = Get-CohesityProtectionJob -Ids $JobId - if (-not $job) { - Write-Output "Cannot proceed, the job id '$JobId' is invalid" - return - } - - $SourceId = 0 - $HostSourceId - $TargetHostId = 0 - $JobRunId - $StartTime - - $sqlRecords = Find-CohesityObjectsForRestore -Environments KSQL | Where-Object { $_.ObjectName -eq $SqlObjectName} - - $searchedVMDetails = $null - $searchIndex = 0 - $continuePagination = $true - $searchTotalCount = 0 - - foreach ($record in $sqlRecords) { - - if ($record.JobID -eq $JobId) { - - while ($continuePagination) { - $searchURL = '/irisservices/api/v1/searchvms?from=' + $searchIndex + '&environment=SQL&entityTypes=kSQL&showAll=false&onlyLatestVersion=true&jobIds=' + $JobId - $searchResult = Invoke-RestApi -Method Get -Uri $searchURL - - if ($Global:CohesityAPIStatus.StatusCode -ne 200) { - Write-Output "Could not search MSSQL objects with the job id $JobId" - return - } - - $indiVm = $searchResult.vms - foreach($vm in $indiVm) { - - # SourceId and HostSource - if ($vm.vmDocument.objectAliases[0] -eq $SqlHost) { - - $SourceId = $record.SnapshottedSource.Id - $HostSourceId = $record.SnapshottedSource.ParentId - break - } - } - - $searchedVMDetails = $searchResult.vms | Where-Object { ($_.vmDocument.objectId.jobId -eq $JobId) -and ($_.vmDocument.objectId.entity.id -eq $SourceId) } - - if ($searchTotalCount -eq 0) { - # find the expected number of search result items - $searchTotalCount = $searchResult.count - } - - if ($searchedVMDetails) { - $errorMsg = "Found database with search index " + $searchIndex + ", and total item count " + $searchTotalCount - CSLog -Message $errorMsg - $continuePagination = $false - } - - # the number of items skimmed - $searchIndex += $searchResult.vms.Count - - if ($searchIndex -ge $searchTotalCount) { - $continuePagination = $false - } - if ($continuePagination -eq $false) { - break - } - } - if ($null -eq $searchedVMDetails) { - Write-Output "Could not find details for MSSQL source id = $SourceId , and Job id = $JobId" - return - } - } - } - - if ($SourceId -eq 0) { - Write-Output "Cannot proceed, Unable to find SourceId" - return - } - - $protectionSources = Get-CohesityProtectionSource -Environments KSQL - foreach ($record in $protectionSources) { - - if($record.protectionSource.Name -eq $TargetHost) { - - $TargetHostId = $record.protectionSource.id - } - } - - if ($TargetHostId -eq 0) { - Write-Output "Unable to find TargetHostId for $TargetHost" - return - } - - # Identifying the JobRunId and StartTime based on the last known unexpired snapshot - # here the curent system time should be less than the recent successful snapshot expiry time - $runs = Get-CohesityProtectionJobRun -JobId $JobId -ExcludeErrorRuns:$true - foreach ($record in $runs) { - - $expiryEpocTime = $record.copyRun[0].expiryTimeUsecs - $currentTime = Get-Date - $currentEpocTime = Get-Date $currentTime -UFormat %s - if ($currentEpocTime -le $expiryEpocTime) { - - $JobRunId = $record[0].backupRun.jobRunId - $StartTime = $record.copyRun[0].runStartTimeUsecs - break - } - } - - $sqlRestoreParams = @{ - JobID = $JobId - SourceID = $SourceId - HostSourceID = $HostSourceId - TargetHostID = $TargetHostId - JobRunId = $JobRunId - StartTime = $StartTime - CaptureTailLogs = $CaptureTailLogs.IsPresent - KeepCDC = $KeepCDC.isPresent - NewDatabaseName = $NewDatabaseName - NewInstanceName = $NewInstanceName - Verbose = $true - Confirm = $false - TargetDataFilesDirectory = $TargetDataFilesDirectory - TargetLogFilesDirectory = $TargetLogFilesDirectory - TargetSecondaryDataFilesDirectoryList = $TargetSecondaryDataFilesDirectoryList - RestoreTimeSecs = $RestoreTimeSecs - DbRestoreOverwritePolicy = $DbRestoreOverwritePolicy - } - Restore-CohesityRemoteMSSQLObject @sqlRestoreParams - } - End { - } -} \ No newline at end of file diff --git a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 index 46fee544..28696d17 100644 --- a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 +++ b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 @@ -33,11 +33,11 @@ function Restore-CohesityRemoteMSSQLObject { [Parameter(Mandatory = $false)] # Specifies the name of the restore task. [string]$TaskName = "Restore-MSSQL-Object-" + (Get-Date -Format "dddd-MM-dd-yyyy-HH-mm-ss").ToString(), - [Parameter(Mandatory = $true)] + [Parameter(Mandatory = $false)] [ValidateRange(1, [long]::MaxValue)] # Specifies the source id of the MS SQL database to restore. This can be obtained using Find-CohesityObjectsForRestore -Environments KSQL. [long]$SourceId, - [Parameter(Mandatory = $true)] + [Parameter(Mandatory = $false)] [ValidateRange(1, [long]::MaxValue)] # Specifies the id of MSSQL database instance. [long]$HostSourceId, @@ -99,7 +99,16 @@ function Restore-CohesityRemoteMSSQLObject { [ValidateRange(1, [long]::MaxValue)] # Specifies the target host if the application is to be restored to a different host. # If not specified, then the application is restored to the original host (physical or virtual) that hosted this application. - [long]$TargetHostId + [long]$TargetHostId, + [Parameter(Mandatory = $false)] + # Specifies the SQL Host information + [string]$SqlHost, + [Parameter(Mandatory = $false)] + # Specifies the SQL Object Name + [string]$SqlObjectName, + [Parameter(Mandatory = $false)] + # Specifies the target host to restore + [string]$TargetHost ) Begin { } @@ -113,11 +122,26 @@ function Restore-CohesityRemoteMSSQLObject { } if ($job.IsActive -eq $false) { + if ($TargetHost) { + # Find the Id of specified target host + $protectionSources = Get-CohesityProtectionSource -Environments KSQL + foreach ($record in $protectionSources) { + if ($record.protectionSource.Name -eq $TargetHost) { + $TargetHostId = $record.protectionSource.id + break; + } + } - $protectionSourceObject = Get-CohesityProtectionSource -Id $TargetHostId - if ($protectionSourceObject.id -ne $TargetHostId) { - Write-Output "Cannot proceed, the target host id '$TargetHostId' is invalid" - return + if (!$TargetHostId){ + Write-Output "Unable to find the id of target host '$TargetHost'." + return + } + } elseif ($TargetHostId){ + $protectionSourceObject = Get-CohesityProtectionSource -Id $TargetHostId + if ($protectionSourceObject.id -ne $TargetHostId) { + Write-Output "Cannot proceed, the target host id '$TargetHostId' is invalid" + return + } } $searchedVMDetails = $null @@ -134,6 +158,22 @@ function Restore-CohesityRemoteMSSQLObject { return } + if ($SqlHost) { + $vmList = $searchVMResult.vms + foreach ($vm in $vmList) { + if ($vm.vmDocument.objectAliases[0] -eq $SqlHost) { + $SourceId = $record.SnapshottedSource.Id + $HostSourceId = $record.SnapshottedSource.ParentId + break + } + } + } + + if (!$SourceId) { + Write-Output "Please provide source information." + return + } + $searchedVMDetails = $searchResult.vms | Where-Object { ($_.vmDocument.objectId.jobId -eq $JobId) -and ($_.vmDocument.objectId.entity.id -eq $SourceId) } if ($searchTotalCount -eq 0) { @@ -142,8 +182,8 @@ function Restore-CohesityRemoteMSSQLObject { } if ($searchedVMDetails) { - $errorMsg = "Found database with search index " + $searchIndex + ", and total item count " + $searchTotalCount - CSLog -Message $errorMsg + $infoMsg = "Found database with search index " + $searchIndex + ", and total item count " + $searchTotalCount + CSLog -Message $infoMsg $continuePagination = $false } @@ -164,11 +204,23 @@ function Restore-CohesityRemoteMSSQLObject { } if (-not $JobRunId) { + # Identifying the JobRunId and StartTime based on the last known unexpired snapshot + # here the curent system time should be less than the recent successful snapshot expiry time $runs = Get-CohesityProtectionJobRun -JobId $JobId -ExcludeErrorRuns:$true - $run = $runs[0] - $JobRunId = $run.backupRun.jobRunId - $StartTime = $run.backupRun.stats.startTimeUsecs + foreach ($record in $runs) { + + $expiryEpocTime = $record.copyRun[0].expiryTimeUsecs + $currentTime = Get-Date + $currentEpocTime = Get-Date $currentTime -UFormat %s + if ($currentEpocTime -le $expiryEpocTime) { + + $JobRunId = $record[0].backupRun.jobRunId + $StartTime = $record.copyRun[0].runStartTimeUsecs + break + } + } } + if (-not $NewDatabaseName) { $NewDatabaseName = $searchedVMDetails.vmDocument.objectId.entity.sqlEntity.databaseName } @@ -268,7 +320,7 @@ function Restore-CohesityRemoteMSSQLObject { alternateLocationParams = @{} } - if ($DbRestoreOverwritePolicy -eq $true) { + if ($DbRestoreOverwritePolicy -eq $true) { $sqlRestoreParams | Add-Member -NotePropertyName dbRestoreOverwritePolicy -NotePropertyValue "kOverwrite" } From 98ca504f229556c4b65cd0370caa9ee665b8fded Mon Sep 17 00:00:00 2001 From: KavishreeShanmugam11 Date: Mon, 8 Jan 2024 09:06:54 +0530 Subject: [PATCH 5/5] Updated readme file and version of the module. --- ...store-cohesityremotemssqlobject-wrapper.md | 289 ------------------ .../restore-cohesityremotemssqlobject.md | 67 +++- docs/sidebar.md | 1 - .../Cohesity.PowerShell.Core.psd1 | 2 +- .../Cohesity.PowerShell.psd1 | 2 +- .../Restore-CohesityRemoteMSSQLObject.ps1 | 28 +- 6 files changed, 85 insertions(+), 304 deletions(-) delete mode 100644 docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md diff --git a/docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md b/docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md deleted file mode 100644 index 4b553056..00000000 --- a/docs/cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md +++ /dev/null @@ -1,289 +0,0 @@ -# Restore-CohesityRemoteMSSQLObject-Wrapper - -## SYNOPSIS -From remote cluster restores the specified MS SQL object from a previous backup. - -## SYNTAX - -### Default (Default) -``` -Restore-CohesityRemoteMSSQLObject-Wrapper [-CaptureTailLogs] [-DbRestoreOverwritePolicy] [-JobId ] [-KeepCDC] [-NewDatabaseName ] [-NewInstanceName ] [-SqlHost ] [-RestoreTimeSecs ] [-SqlObjectName ] [-TargetHost ] [-TargetDataFilesDirectory ] [-TargetLogFilesDirectory ] [-TargetSecondaryDataFilesDirectoryList ] -``` - -## DESCRIPTION -From remote cluster restores the specified MS SQL object from a last successful backup. - -## EXAMPLES - -### EXAMPLE 1 -``` -Restore-CohesityRemoteMSSQLObject-Wrapper -JobId 1234 -SqlHost x.x.x.x -SqlObjectName "MSSQLSERVER/database" -TargetHost y.y.y.y -CaptureTailLogs:$false -NewDatabaseName database_new -NewInstanceName SQLInstance_new -TargetDataFilesDirectory "C:\" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true -``` - -Restore MSSQL database from remote cluster with Job Id 1234, SqlHost x.x.x.x and SqlObjectName MSSQLSERVER/database at TargetHost y.y.y.y from last successfull backup, with existing DB overwrite policy - -For secondary data files, construct the $patternList as follows -$patternList = @() -$pattern1 = @{filePattern = "*.mdf"; targetDirectory = "c:\test"} -$pattern2 = @{filePattern = "*.ldf"; targetDirectory = "c:\test1"} -$patternList += $pattern1 -$patternList += $pattern2 - -## PARAMETERS - -### -SqlHost -Specifies the SQL host from which database need to be restored. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: Named -Default value: 0 -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -SqlObjectName -Specifies the name of the SQL Object to be restored. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: Named -Default value: 0 -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -JobId -Specifies the job id that backed up this MS SQL instance and will be used for this restore. - -```yaml -Type: Int64 -Parameter Sets: (All) -Aliases: - -Required: True -Position: Named -Default value: 0 -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -CaptureTailLogs -Specifies if the tail logs are to be captured before the restore operation. -This is only applicable if restoring the SQL database to its hosting Protection Source and the database is not being renamed. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: False -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -DbRestoreOverwritePolicy -This field will overwrite the existing db contents if it sets to true -By default the db overwrite policy is false - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: False -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -KeepCDC -This field prevents "change data capture" settings from being reomved. -When a database or log backup is restored on another server and database is recovered. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: False -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -NewDatabaseName -Specifies a new name for the restored database. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -NewInstanceName -Specifies the instance name of the SQL Server that should be restored. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -RestoreTimeSecs -Specifies the time in the past to which the SQL database needs to be restored. -This allows for granular recovery of SQL databases. -If not specified, the SQL database will be restored from the full/incremental snapshot. - -```yaml -Type: Int64 -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: 0 -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -TargetDataFilesDirectory -Specifies the directory where to put the database data files. -Missing directory will be automatically created. -This field must be set if restoring to a different target host. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -TargetLogFilesDirectory -Specifies the directory where to put the database log files. -Missing directory will be automatically created. -This field must be set if restoring to a different target host. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -TargetSecondaryDataFilesDirectoryList -Specifies the secondary data filename pattern and corresponding directories of the DB. -Secondary data -files are optional and are user defined. -The recommended file extension for secondary files is -".ndf". -If this option is specified and the destination folders do not exist they will be -automatically created. -This field can be set only if restoring to a different target host. - -```yaml -Type: Object[] -Parameter Sets: (All) -Aliases: - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -TargetHost -Specifies the target host if the application is to be restored to a different host. - -```yaml -Type: String -Parameter Sets: (All) -Aliases: - -Required: True -Position: Named -Default value: 0 -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -WhatIf -Shows what would happen if the cmdlet runs. -The cmdlet is not run. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: wi - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -Confirm -Prompts you for confirmation before running the cmdlet. - -```yaml -Type: SwitchParameter -Parameter Sets: (All) -Aliases: cf - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). - -## INPUTS - -## OUTPUTS - -## NOTES -Published by Cohesity - -## RELATED LINKS - -[https://cohesity.github.io/cohesity-powershell-module/#/README](https://cohesity.github.io/cohesity-powershell-module/#/README) - diff --git a/docs/cmdlets-reference/restore-cohesityremotemssqlobject.md b/docs/cmdlets-reference/restore-cohesityremotemssqlobject.md index fa49443f..1ea796ec 100644 --- a/docs/cmdlets-reference/restore-cohesityremotemssqlobject.md +++ b/docs/cmdlets-reference/restore-cohesityremotemssqlobject.md @@ -23,6 +23,15 @@ Restore-CohesityRemoteMSSQLObject [-TaskName ] -SourceId -HostSo [-DbRestoreOverwritePolicy] [-TargetHostId ] [-WhatIf] [-Confirm] [] ``` +### SQL Host +``` +Restore-CohesityRemoteMSSQLObject [-TaskName ] [-SqlHost ] [-SqlObjectName ] [-JobId ] + [-CaptureTailLogs] [-KeepCDC] [-NewDatabaseName ] [-NewInstanceName ] + [-RestoreTimeSecs ] [-TargetDataFilesDirectory ] [-TargetLogFilesDirectory ] + [-TargetSecondaryDataFilesDirectoryList ] [-DbRestoreOverwritePolicy] [-TargetHost ] + [-WhatIf] [-Confirm] [] +``` + ## DESCRIPTION From remote cluster restores the specified MS SQL object from a previous backup. @@ -33,7 +42,7 @@ From remote cluster restores the specified MS SQL object from a previous backup. Restore-CohesityRemoteMSSQLObject -SourceId 1279 -HostSourceId 1277 -JobId 31520 -TargetHostId 770 -CaptureTailLogs:$false -NewDatabaseName CohesityDB_r1 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true ``` -Restore MSSQL database from remote cluster with database id 1279 , database instance id 1277 and job id as 31520 +Restore MSSQL database from remote cluster with database id 1279 , database instance id 1277 and job id as 31520 with the latest recoverable snapshot information. $mssqlObjects = Find-CohesityObjectsForRestore -Environments KSQL Get the source id, $mssqlObjects\[0\].SnapshottedSource.Id Get the source instance id, $mssqlObjects\[0\].SnapshottedSource.SqlProtectionSource.OwnerId @@ -58,6 +67,13 @@ $pattern2 = @{filePattern = "*.ldf"; targetDirectory = "c:\test1"} $patternList += $pattern1 $patternList += $pattern2 +### EXAMPLE 4 +``` +Restore-CohesityRemoteMSSQLObject -SqlHost x.x.x.x -JobId 31520 -SqlObjectName instance/databse_1 -TargetHost y.y.y.y -CaptureTailLogs:$false -NewDatabaseName CohesityDB_r1 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true +``` + +Restore MSSQL database from remote cluster with database name database_1 from the sql host x.x.x.x, and job id as 31520 to the target host y.y.y.y with latest recoverable snapshot information. + ## PARAMETERS ### -TaskName @@ -84,7 +100,7 @@ Type: Int64 Parameter Sets: (All) Aliases: -Required: True +Required: False Position: Named Default value: 0 Accept pipeline input: False @@ -99,7 +115,7 @@ Type: Int64 Parameter Sets: (All) Aliases: -Required: True +Required: False Position: Named Default value: 0 Accept pipeline input: False @@ -217,6 +233,51 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -SqlHost +Specifies the SQL host from which database need to be restored. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SqlObjectName +Specifies the name of the SQL Object to be restored. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TargetHost +Specifies the target host if the application is to be restored to a different host. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -RestoreTimeSecs Specifies the time in the past to which the SQL database needs to be restored. This allows for granular recovery of SQL databases. diff --git a/docs/sidebar.md b/docs/sidebar.md index 0e624ec9..369d96a5 100644 --- a/docs/sidebar.md +++ b/docs/sidebar.md @@ -146,7 +146,6 @@ - [Find-CohesityObjectsForRestore](cmdlets-reference/find-cohesityobjectsforrestore.md) - [Restore-CohesityMSSQLObject](cmdlets-reference/restore-cohesitymssqlobject.md) - [Restore-CohesityRemoteMSSQLObject](cmdlets-reference/restore-cohesityremotemssqlobject.md) -- [Restore-CohesityRemoteMSSQLObject-Wrapper](cmdlets-reference/restore-cohesityremotemssqlobject-wrapper.md) - [Restore-CohesityVMwareVM](cmdlets-reference/restore-cohesityvmwarevm.md) - [Restore-CohesityHyperVVM](cmdlets-reference/restore-cohesityhypervvm.md) - [Restore-CohesityAcropolisVM](cmdlets-reference/restore-cohesityacropolisvm.md) diff --git a/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 b/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 index fa237e51..65c500f8 100644 --- a/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 +++ b/src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1 @@ -8,7 +8,7 @@ RootModule = 'Cohesity.PowerShell.Core.dll' # Version number of this module. -ModuleVersion = '1.9.5' +ModuleVersion = '1.9.6' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 b/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 index 1abbca8e..507d3a1c 100644 --- a/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 +++ b/src/Cohesity.Powershell/Cohesity.PowerShell.psd1 @@ -8,7 +8,7 @@ RootModule = 'Cohesity.PowerShell.dll' # Version number of this module. -ModuleVersion = '1.9.5' +ModuleVersion = '1.9.6' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 index 28696d17..16e18e3f 100644 --- a/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 +++ b/src/Cohesity.Powershell/Scripts/Restore/Restore-CohesityRemoteMSSQLObject.ps1 @@ -16,6 +16,9 @@ function Restore-CohesityRemoteMSSQLObject { Get the source instance id, $mssqlObjects[0].SnapshottedSource.SqlProtectionSource.OwnerId Use the DbRestoreOverwritePolicy:$true for overriding the existing database .EXAMPLE + Restore-CohesityRemoteMSSQLObject -SqlHost x.x.x.x -JobId 31520 -SqlObjectName instance/databse_1 -TargetHost y.y.y.y -CaptureTailLogs:$false -NewDatabaseName CohesityDB_r1 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" -DbRestoreOverwritePolicy:$true + Restore MSSQL database from remote cluster with database name database_1 from the sql host x.x.x.x, and job id as 31520 to the target host y.y.y.y + .EXAMPLE Restore-CohesityRemoteMSSQLObject -SourceId 3101 -HostSourceId 3099 -JobId 51275 -TargetHostId 3098 -CaptureTailLogs:$false -NewDatabaseName ReportServer_r26 -NewInstanceName MSSQLSERVER -TargetDataFilesDirectory "C:\temp" -TargetLogFilesDirectory "C:\temp" -StartTime 1616956306627994 -JobRunId 60832 -RestoreTimeSecs 1616958037 Request for restore MSSQL object with RestoreTimeSecs (point in time) parameter, StartTime and JobRunId. .EXAMPLE @@ -159,12 +162,19 @@ function Restore-CohesityRemoteMSSQLObject { } if ($SqlHost) { + # Get the list of SQL objects that can be restored and fetch the id of the specified SQL host + $sqlRecords = Find-CohesityObjectsForRestore -Environments KSQL -JobIds $JobId | Where-Object { $_.ObjectName -eq $SqlObjectName } + $vmList = $searchVMResult.vms foreach ($vm in $vmList) { if ($vm.vmDocument.objectAliases[0] -eq $SqlHost) { - $SourceId = $record.SnapshottedSource.Id - $HostSourceId = $record.SnapshottedSource.ParentId - break + foreach ($record in $sqlRecords) { + if ($vm.vmDocument.objectId.entity.sqlEntity.ownerId -eq $record.SnapshottedSource.ParentId) { + $SourceId = $record.SnapshottedSource.Id + $HostSourceId = $record.SnapshottedSource.ParentId + break + } + } } } } @@ -278,7 +288,7 @@ function Restore-CohesityRemoteMSSQLObject { $MSSQL_OBJECT_RESTORE_TYPE = 3 $MSSQL_TARGET_PHYSICAL_ENTITY_HOST_TYPE = 1 $MSSQL_TARGET_PHYSICAL_ENTITY_TYPE = 1 - $targetHost = [PSCustomObject]@{ + $targetHostObject = [PSCustomObject]@{ id = $TargetHostId } $targetHostParentSource = $null @@ -288,8 +298,8 @@ function Restore-CohesityRemoteMSSQLObject { type = $MSSQL_TARGET_VMWARE_ENTITY_TYPE name = $protectionSourceObject.vmWareProtectionSource.name } - $targetHost | Add-Member -NotePropertyName parentId -NotePropertyValue $protectionSourceObject.parentId - $targetHost | Add-Member -NotePropertyName vmwareEntity -NotePropertyValue $vmwareEntity + $targetHostObject | Add-Member -NotePropertyName parentId -NotePropertyValue $protectionSourceObject.parentId + $targetHostObject | Add-Member -NotePropertyName vmwareEntity -NotePropertyValue $vmwareEntity $targetHostParentSource = @{ id = $protectionSourceObject.parentId } @@ -304,9 +314,9 @@ function Restore-CohesityRemoteMSSQLObject { hostType = $MSSQL_TARGET_PHYSICAL_ENTITY_HOST_TYPE osName = $protectionSourceObject.physicalProtectionSource.osName } - $targetHost | Add-Member -NotePropertyName physicalEntity -NotePropertyValue $physicalEntity + $targetHostObject | Add-Member -NotePropertyName physicalEntity -NotePropertyValue $physicalEntity } - $targetHost | Add-Member -NotePropertyName type -NotePropertyValue $MSSQL_TARGET_HOST_TYPE + $targetHostObject | Add-Member -NotePropertyName type -NotePropertyValue $MSSQL_TARGET_HOST_TYPE $sqlRestoreParams = [PSCustomObject]@{ captureTailLogs = $CaptureTailLogs.IsPresent @@ -333,7 +343,7 @@ function Restore-CohesityRemoteMSSQLObject { appEntity = $searchedVMDetails.vmDocument.objectId.entity restoreParams = @{ sqlRestoreParams = $sqlRestoreParams - targetHost = $targetHost + targetHost = $targetHostObject targetHostParentSource = $targetHostParentSource } }