diff --git a/backup.ps1 b/backup.ps1 index 233b21d..d639a93 100644 --- a/backup.ps1 +++ b/backup.ps1 @@ -3,7 +3,6 @@ # # TODO: Update cleanup time based on backup type - $sqlInstance = "sqlfcsql\TESTINST" #$directory = "H:\Backup" $directory = "C:\Rubrik\mount" diff --git a/setActiveNode.ps1 b/setActiveNode.ps1 new file mode 100644 index 0000000..99e5b0b --- /dev/null +++ b/setActiveNode.ps1 @@ -0,0 +1,121 @@ +########################################################################## +# +# Update an SLA MV to point to the local host +# Created by Rubrik PS for ZF, September 2025 +# +# Must be run with a Global service account. +# +# Requires RubrikSecurityCloud module to be installed and working with +# a Global Service Account with the following rights (TBC) +# +# Create the service account file with: +# Set-RscServiceAccountFile sa.json -OutputFilePath Global.xml +# +# Example invocation +# .\claimInstance.ps1 -sqlInstance "sqlfcsql\TESTINST" -mvName "JP-ZF-SQL" +# +# v0.1 Initial Release +# +########################################################################## + +param ( + [Parameter(Mandatory=$False, + HelpMessage="Instance to claim")] + [string]$sqlInstance, + + [Parameter(Mandatory=$False, + HelpMessage="Do not change the MV")] + [switch]$dryrun +) + +# SA File must be an absolute path +$GlobalSAFile = "C:\Rubrik\scripts\sa.xml" +$logFile = "C:\Rubrik\scripts\claimInstance.log" +$mvName = "JP-ZF-SQL" +$sqlInstance = "sqlfcsql\TESTINST" +$checkCluster = $true + +########################### +# Script begins +########################### + +$ErrorActionPreference = 'Stop' + +function Write-Log($message) { + $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + $logEntry = "$timestamp $message" + Add-Content -Path $logFile -Value $logEntry + Write-Host $logEntry +} + +Import-Module RubrikSecurityCloud + +if ($checkCluster) { + # Check if SQL instance is running locally + $localNode = $env:COMPUTERNAME + $instanceName = $sqlInstance.Split('\')[1] + $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 $GlobalSAFile + 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 + } +} else { + Write-Log "INFO: Cluster check is disabled. Proceeding without verification." +} + +Disconnect-Rsc \ No newline at end of file