checkpoint
This commit is contained in:
186
backupmult.ps1
186
backupmult.ps1
@@ -2,71 +2,28 @@ param(
|
|||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$SqlInstance,
|
[string]$SqlInstance,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$Directories,
|
[string]$MvName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[int]$Jobs = 2,
|
[int]$Jobs = 2
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
|
||||||
[switch]$Force
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
# backupmult.ps1 - Parallel database backup script using Ola Hallengren's DatabasesInParallel feature
|
# backupmult.ps1 - Parallel database backup script using Ola H
|
||||||
#
|
#
|
||||||
# Uses Ola H's built-in parallel processing by starting multiple concurrent backup jobs
|
# Uses Ola H's built-in parallel processing by starting multiple concurrent backup jobs
|
||||||
# Each job will automatically share the database load using DatabasesInParallel=Y
|
# Each job will automatically share the database load using DatabasesInParallel=Y
|
||||||
#
|
|
||||||
|
|
||||||
# Import SQL Server PowerShell module
|
# TODO: Log file management (don't just overwrite existing logs)
|
||||||
try {
|
# TODO: Dynmically figure out MV channels and paths using Rubrik API
|
||||||
if (Get-Module -ListAvailable -Name SqlServer) {
|
# TODO: See if there is way to query QueueDatabase during backup to monitor progress
|
||||||
Import-Module SqlServer -ErrorAction Stop
|
|
||||||
Write-Host "INFO: SqlServer PowerShell module loaded successfully."
|
|
||||||
}
|
|
||||||
elseif (Get-Module -ListAvailable -Name SQLPS) {
|
|
||||||
Import-Module SQLPS -ErrorAction Stop
|
|
||||||
Write-Host "INFO: SQLPS PowerShell module loaded successfully."
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "No SQL Server PowerShell module found"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not (Get-Command Invoke-Sqlcmd -ErrorAction SilentlyContinue)) {
|
|
||||||
throw "Invoke-Sqlcmd command not available"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "ERROR: Failed to import SQL Server PowerShell module. Please install it using: Install-Module -Name SqlServer -AllowClobber"
|
|
||||||
Write-Host "ERROR: $($_.Exception.Message)"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
$instanceName = $SqlInstance.Split('\')[1]
|
|
||||||
|
|
||||||
# Use provided directories or default to comma-separated multi-directory setup
|
|
||||||
if ($Directories) {
|
|
||||||
$directoryParam = $Directories
|
|
||||||
Write-Host "INFO: Using provided directories: $directoryParam"
|
|
||||||
} else {
|
|
||||||
$directoryParam = "C:\Rubrik\$instanceName\Dir1, C:\Rubrik\$instanceName\Dir2, C:\Rubrik\$instanceName\Dir3, C:\Rubrik\$instanceName\Dir4"
|
|
||||||
Write-Host "INFO: Using default multi-directory setup: $directoryParam"
|
|
||||||
}
|
|
||||||
|
|
||||||
$fullBackupDay = 'Thursday'
|
$fullBackupDay = 'Thursday'
|
||||||
$fullBackupOverdueDays = 7
|
$fullBackupOverdueDays = 7
|
||||||
|
$instanceName = $SqlInstance.Split('\')[1]
|
||||||
$logFile = "C:\Rubrik\backup-multi-$instanceName.log"
|
$logFile = "C:\Rubrik\backup-multi-$instanceName.log"
|
||||||
|
$SAFile = "C:\Rubrik\scripts\rbksql.xml"
|
||||||
# Validate job count
|
|
||||||
if ($Jobs -lt 1 -or $Jobs -gt 8) {
|
|
||||||
Write-Host "ERROR: Jobs parameter must be between 1 and 8. Provided: $Jobs"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "INFO: Starting $Jobs parallel backup jobs"
|
|
||||||
|
|
||||||
$today = (Get-Date).Date
|
|
||||||
|
|
||||||
function Write-Log($message, $jobId = "") {
|
function Write-Log($message, $jobId = "") {
|
||||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||||
@@ -94,6 +51,131 @@ function Write-Log($message, $jobId = "") {
|
|||||||
Write-Host $logEntry
|
Write-Host $logEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Import SQL Server PowerShell module
|
||||||
|
try {
|
||||||
|
if (Get-Module -ListAvailable -Name SqlServer) {
|
||||||
|
Import-Module SqlServer -ErrorAction Stop
|
||||||
|
Write-Log "INFO: SqlServer PowerShell module loaded successfully."
|
||||||
|
}
|
||||||
|
elseif (Get-Module -ListAvailable -Name SQLPS) {
|
||||||
|
Import-Module SQLPS -ErrorAction Stop
|
||||||
|
Write-Log "INFO: SQLPS PowerShell module loaded successfully."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "No SQL Server PowerShell module found"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Get-Command Invoke-Sqlcmd -ErrorAction SilentlyContinue)) {
|
||||||
|
throw "Invoke-Sqlcmd command not available"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "ERROR: Failed to import SQL Server PowerShell module. Please install it using: Install-Module -Name SqlServer -AllowClobber"
|
||||||
|
Write-Host "ERROR: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Import Rubrik Security Cloud module
|
||||||
|
try {
|
||||||
|
Import-Module RubrikSecurityCloud -ErrorAction Stop
|
||||||
|
Write-Log "INFO: RubrikSecurityCloud module loaded successfully."
|
||||||
|
} catch {
|
||||||
|
Write-Log "ERROR: Failed to import RubrikSecurityCloud module. $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$localNode = $env:COMPUTERNAME
|
||||||
|
$clusterInstance = Get-ClusterResource | Where-Object { $_.ResourceType -eq "SQL Server" -and $_.Name -eq "SQL Server ($instanceName)" }
|
||||||
|
|
||||||
|
if ($clusterInstance) {
|
||||||
|
$ownerNode = $clusterInstance.OwnerNode
|
||||||
|
if ($ownerNode -ne $localNode) {
|
||||||
|
Write-Log "SQL instance '$SqlInstance' is not running on local node '$localNode'. Updating the MV."
|
||||||
|
|
||||||
|
Connect-Rsc -ServiceAccountFile $SAFile
|
||||||
|
Write-Log "Connected to Rubrik Security Cloud."
|
||||||
|
|
||||||
|
$newHost = Get-RscHost -Name $ownerNode -OsType WINDOWS
|
||||||
|
|
||||||
|
$query = New-RscQuery -GqlQuery slaManagedVolumes -AddField Nodes.HostDetail, Nodes.SmbShare, Nodes.ClientConfig, Nodes.ClientConfig.BackupScript, Nodes.ClientConfig.PreBackupScript
|
||||||
|
$query.var.filter = @(Get-RscType -Name Filter)
|
||||||
|
$query.var.filter[0].field = "NAME_EXACT_MATCH"
|
||||||
|
$query.var.filter[0].Texts = $mvName
|
||||||
|
$mvDetail = $query.Invoke().nodes[0]
|
||||||
|
|
||||||
|
Write-Log "Found Managed Volume: $($mvDetail.Name) (ID: $($mvDetail.Id), Status: $($mvDetail.hostDetail.Status), HostDetail Name: $($mvDetail.hostDetail.Name))"
|
||||||
|
|
||||||
|
$query = New-RscMutation -GqlMutation updateManagedVolume
|
||||||
|
$query.Var.input = Get-RscType -Name UpdateManagedVolumeInput
|
||||||
|
$query.Var.input.update = Get-RscType -Name ManagedVolumeUpdateInput
|
||||||
|
$query.Var.input.update.config = Get-RscType -Name ManagedVolumePatchConfigInput
|
||||||
|
$query.Var.input.update.slaClientConfig = Get-RscType -Name ManagedVolumePatchSlaClientConfigInput
|
||||||
|
|
||||||
|
$query.Var.input.Id = $mvDetail.Id
|
||||||
|
$query.Var.input.update.Name = $mvName
|
||||||
|
$query.Var.input.update.config.SmbDomainName = $mvDetail.SmbShare.DomainName
|
||||||
|
$query.Var.input.update.config.SmbValidIps = $newHost.Name
|
||||||
|
$query.Var.input.update.config.SmbValidUsers = $mvDetail.SmbShare.ValidUsers + $mvDetail.SmbShare.ActiveDirectoryGroups
|
||||||
|
$query.Var.input.update.slaClientConfig.clientHostId = $newHost.Id
|
||||||
|
$query.Var.input.update.slaClientConfig.channelHostMountPaths = $mvDetail.ClientConfig.ChannelHostMountPaths
|
||||||
|
$query.Var.input.update.slaClientConfig.backupScriptCommand = $mvDetail.ClientConfig.BackupScript.ScriptCommand
|
||||||
|
$query.Var.input.update.slaClientConfig.preBackupScriptCommand = $mvDetail.ClientConfig.PreBackupScript.ScriptCommand
|
||||||
|
$query.Var.input.update.slaClientConfig.preBackupScriptTimeout = $mvDetail.ClientConfig.PreBackupScript.Timeout
|
||||||
|
$query.Var.input.update.slaClientConfig.shouldDisablePostBackupScriptOnBackupFailure = $true
|
||||||
|
$query.Var.input.update.slaClientConfig.shouldDisablePostBackupScriptOnBackupSuccess = $true
|
||||||
|
$query.Var.input.update.slaClientConfig.shouldDisablePreBackupScript = $false
|
||||||
|
$query.Var.input.update.slaClientConfig.shouldCancelBackupOnPreBackupScriptFailure = $mvDetail.ClientConfig.ShouldCancelBackupOnPreBackupScriptFailure
|
||||||
|
|
||||||
|
$query.gqlRequest().Variables
|
||||||
|
|
||||||
|
if (-not $dryrun) {
|
||||||
|
$result = $query.Invoke()
|
||||||
|
} else {
|
||||||
|
Write-Log "Dry run mode: Managed Volume update not invoked."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now must exit 1 to stop the backup continuing on the wrong node
|
||||||
|
Disconnect-Rsc
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Write-Log "SQL instance '$SqlInstance' is running on local node '$localNode'. No action needed."
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Log "ERROR: SQL instance '$SqlInstance' not found in cluster resources."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Connect to Rubrik and retrieve managed volume paths
|
||||||
|
try {
|
||||||
|
Connect-Rsc -ServiceAccountFile $SAFile
|
||||||
|
Write-Log "INFO: Connected to Rubrik Security Cloud."
|
||||||
|
|
||||||
|
$query = New-RscQuery -GqlQuery slaManagedVolumes -AddField Nodes.HostDetail, Nodes.SmbShare, Nodes.ClientConfig, Nodes.ClientConfig.BackupScript, Nodes.ClientConfig.PreBackupScript
|
||||||
|
$query.var.filter = @(Get-RscType -Name Filter)
|
||||||
|
$query.var.filter[0].field = "NAME_EXACT_MATCH"
|
||||||
|
$query.var.filter[0].Texts = $MvName
|
||||||
|
$mvDetail = $query.Invoke().nodes[0]
|
||||||
|
|
||||||
|
$paths = $mvDetail.ClientConfig.ChannelHostMountPaths
|
||||||
|
Write-Log "INFO: Retrieved paths: $($paths -join ', ')"
|
||||||
|
} catch {
|
||||||
|
Write-Log "ERROR: Failed to retrieve paths from Rubrik. $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$directoryParam = $paths -join ', '
|
||||||
|
|
||||||
|
# Validate job count
|
||||||
|
if ($Jobs -lt 1 -or $Jobs -gt 8) {
|
||||||
|
Write-Host "ERROR: Jobs parameter must be between 1 and 8. Provided: $Jobs"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "INFO: Starting $Jobs parallel backup jobs"
|
||||||
|
|
||||||
|
$today = (Get-Date).Date
|
||||||
|
|
||||||
function Get-BackupType($directoryParam) {
|
function Get-BackupType($directoryParam) {
|
||||||
# Use first directory to check flags (assuming shared flag logic across all directories)
|
# Use first directory to check flags (assuming shared flag logic across all directories)
|
||||||
$firstDir = ($directoryParam -split ',')[0].Trim()
|
$firstDir = ($directoryParam -split ',')[0].Trim()
|
||||||
|
|||||||
Reference in New Issue
Block a user