Rubrik – PowerShell/API SLA Backup & Restores
Having been lucky enough to procure a Rubrik Cloud Data Management appliance at my work recently; we have had the pleasure of experiencing a fantastic technical solution which has assisted us in improving our backup/recover and business continuity planning. The solution, for us, is still in its infancy but we hope to scale and grow as the business realises the full potential of the service. Until then, we have had fun in preparing it for our own production use as it is such a joy to work with!
One thing we questioned was how we get a list of our SLA Domains (as we’ve made a fair few) and their contents. This could be useful in the scenario of someone accidentally deleting policies or machines out of policies. Another potential use case could be if we needed to ‘rebuild’ our Brik SLA configuration in the event of a major failure – highly unlikely but better to be prepared and have committed some brain cycles to it, right?
With that in mind, my esteemed colleague @LordMiddlewick has written some PowerShell scripts with the help of @joshuastenhouse previous blog posts about using Rubrik RestAPIs .
Backup Script
This script can be scheduled to run at your own convenience. Ensure that you fill in the variables in the top section for your own environment. It is possible to encrypt the password within the file itself, this can be achieved using a methodology described here. We have only encrypted it for transmission to the Rubrik service in the case below for simplicity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
################################################ # Configure the variables below for the Rubrik Cluster ################################################ $RubrikCluster = "MYRUBRIK.DOMAIN.COM" # username and password to authenicate $username = "MYUSER@DOMAIN.COM" $password = "PASSWORD_TO_MYUSER" ## This can also be encrypted within the script. $secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $username, $secureStringPwd $RubrikUser = $Credentials.UserName $Credentials.Password | ConvertFrom-SecureString $RubrikPassword = $Credentials.GetNetworkCredential().password $Rubrik_PS_Module = "F:\Rubrik\Rubrik-PowerShell\Rubrik\Rubrik.psm1" ######################################################################################################################## # Nothing to configure below this line - Starting the main function of the script ######################################################################################################################## # Adding certificate exception to prevent API errors ################################################ add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy ################################################ # Building Rubrik API string & invoking REST API ################################################ $baseURL = "https://" + $RubrikCluster + "/api/v1/" $xRubrikSessionURL = $baseURL + "session" $authInfo = ("{0}:{1}" -f $RubrikUser,$RubrikPassword) $authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo) $authInfo = [System.Convert]::ToBase64String($authInfo) $headers = @{Authorization=("Basic {0}" -f $authInfo)} $TypeJSON = "application/json" # Authentication with API Try { $xRubrikSessionResponse = Invoke-WebRequest -Uri $xRubrikSessionURL -Headers $headers -Method POST -Body $sessionBody -ContentType $TypeJSON } Catch { Write-Host $_.Exception.ToString() $error[0] | Format-List -Force } # Extracting the token from the JSON response $xRubrikSession = (ConvertFrom-Json -InputObject $xRubrikSessionResponse.Content) $RubrikSessionHeader = @{'Authorization' = "Bearer $($xRubrikSession.token)"} ############################################### # Creating list of new SLAs ############################################### $SLAURL = $baseURL+"sla_domain" $SLAListJSON = Invoke-RestMethod -Uri $SLAURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON $SLAList = $SLAListJSON.data foreach ($x in $SLAList) { $filename = $x.name $x | convertto-json -depth 5 > f:\Rubrik\backup\$filename.txt } ####################################### # Getting list of VMs in Rubrik ####################################### #Import-Module -Name Rubrik -ErrorAction Stop Import-Module $Rubrik_PS_Module Connect-Rubrik -Server $RubrikCluster -Credential $Credentials $VMList = Get-RubrikVM $VMList | where {$_.effectiveSlaDomainName -ne "UNPROTECTED"} | select name, effectivesladomainname | Sort-Object effectivesladomainname | Export-Csv -NoTypeInformation F:\Rubrik\Backup\VM-SLA.csv ############################################### # End of script ############################################### |
The key take aways from this script in whatever fashion you run it are:
* You receive a bunch of .txt files, for each SLA you have defined, in JSON format. Useful for restoring SLA’s. Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
{ "id": "1XXXXXXXX-cXXX-40XX-XXXX-XXXXXXXXXXX", "primaryClusterId": "XXXXXX-0XXXX-4XXX-XXXX-8XXXXXXXXXX", "name": "Sandbox - Testing", "frequencies": [ { "timeUnit": "Daily", "frequency": 1, "retention": 3 } ], "allowedBackupWindows": [ ], "firstFullAllowedBackupWindows": [ ], "localRetentionLimit": 345600, "archivalSpecs": [ { "locationId": "XXXXXXXX-cXXX-40XX-XXXX-XXXXXXXXXXX", "archivalThreshold": 1 } ], "replicationSpecs": [ ], "numDbs": 0, "numFilesets": 0, "numHypervVms": 0, "numNutanixVms": 0, "numManagedVolumes": 0, "numLinuxHosts": 0, "numShares": 0, "numWindowsHosts": 0, "numVms": 1, "isDefault": false, "uiColor": "#f5bd22" } |
* Another take home is the file “VM-SLA.csv” which contains a list of all your VMs that are backed up and to what policy they belong. This is really useful restoring VM’s into SLA’s or bulk importing VM’s into SLA’s.
Restore SLA Domain Policies
To reverse the backup process and restore an SLA or all of your SLA’s into the Rubrik, use the following script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
################################################ # Configure the variables below for the Rubrik Cluster ################################################ $RubrikCluster = "MYRUBRIK.DOMAIN.COM" # Prompting for username and password to authenicate $Credentials = Get-Credential -Credential $null $RubrikUser = $Credentials.UserName $Credentials.Password | ConvertFrom-SecureString $RubrikPassword = $Credentials.GetNetworkCredential().password ######################################################################################################################## # Nothing to configure below this line - Starting the main function of the script ######################################################################################################################## # Adding certificate exception to prevent API errors ################################################ add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy ################################################ # Building Rubrik API string & invoking REST API ################################################ $baseURL = "https://" + $RubrikCluster + "/api/v1/" $xRubrikSessionURL = $baseURL + "session" $authInfo = ("{0}:{1}" -f $RubrikUser,$RubrikPassword) $authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo) $authInfo = [System.Convert]::ToBase64String($authInfo) $headers = @{Authorization=("Basic {0}" -f $authInfo)} $TypeJSON = "application/json" # Authentication with API Try { $xRubrikSessionResponse = Invoke-WebRequest -Uri $xRubrikSessionURL -Headers $headers -Method POST -Body $sessionBody -ContentType $TypeJSON } Catch { Write-Host $_.Exception.ToString() $error[0] | Format-List -Force } # Extracting the token from the JSON response $xRubrikSession = (ConvertFrom-Json -InputObject $xRubrikSessionResponse.Content) $RubrikSessionHeader = @{'Authorization' = "Bearer $($xRubrikSession.token)"} ############################################### # Restoring saved list of SLAs ############################################### $SLAURL = $baseURL+"sla_domain" $path = "F:\Scripts\Rubrik\Backup" $files = Get-ChildItem $path\*.txt | select -ExpandProperty Name $totalsla=$files.count $i = 1 foreach ($file in $files) { $statusstring = "$i of $totalsla" write-Progress -Activity "Importing SLAs" -Status $statusstring -PercentComplete ($i/$totalsla*100) $restsla = Get-Content -raw $path\$file Invoke-RestMethod -Uri $SLAURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON -Method Post -body $restsla $i++ } ############################################### # End of script ############################################### |
This script will take any .txt (SLA Backup files) in the designated $path and try and create it back on your Rubrik.
Restore/Import VMs to SLAs
The final part of this excercise is to be able to restore a list of VMs that have been pulled out, against the SLA domain policies that you have. The following script does this by using the above “VM-SLA.csv” to import a list of objects in and assign them as per the csv.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
############################################### # Configure the variables below for the Rubrik Cluster ################################################ $RubrikCluster = "MYRUBRIK.DOMAIN.COM" # username and password to authenicate $username = "MYUSER@DOMAIN.COM" $password = "MYPASSWORDHERE" $secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $username, $secureStringPwd ####################################### # Restore list of VMs in Rubrik ####################################### Import-Module -Name Rubrik -ErrorAction Stop Connect-Rubrik -Server $RubrikCluster -Credential $Credentials $VMList = Import-Csv “F:\Rubrik\Backup\VM-SLA.csv” $totalvms=$VMList.count $i = 1 foreach ($VM in $VMList) { $statusstring = "$i of $totalvms" write-Progress -Activity "Importing VMs" -Status $statusstring -PercentComplete ($i/$totalvms*100) Get-RubrikVM $VM.name | Protect-RubrikVM -SLA $VM.effectiveSlaDomainName -Confirm:$false $i++ } ############################################### # End of script ############################################### |
The format for the VM-SLA.csv file is as follows:
1 2 3 4 5 6 |
"name","effectiveSlaDomainName" "server1","Bronze" "server2","Platinum" "server3","Platinum" "server4","Platinum" "server5","Gold" |
In theory, if you have lots of machines you want to bulk assign to any given policies, you can create your own CSV and run it to import your VM estate to your predefined policies using this script. We used this several times when assigning 100+ objects to a given policy and it worked a treat!
Disclaimer:Please try to fully read and understand the above scripts before implementing them. You should test them fully first in a development environment before implementing in any production sense. I/we do not take any responsibility for rouge administrators stupidity.
I’m sure as Rubrik continue to steam ahead with excellent releases, infact they might evne build in some of this functioanlity making these scripts redundant. In the meantime hopefully someone finds these scripts useful, I know we have. Once again big shout out to @LordMiddlewick for writing this and giving me permission to post it and also to @joshuastenhouse for his blog https://virtuallysober.com .