Functions/Send-RSCReport02MultiDayStrikes.ps1
################################################ # Function - Send-RSCReport02MultiDayStrikes - Sending RSC Report ################################################ Function Send-RSCReport02MultiDayStrikes { <# .SYNOPSIS Creates and emails a pre-canned HTML report for multi-day strikes and backups (days missing a backup/snapshot) across all protected objects, also known as a christmas tree report. .DESCRIPTION By default reports back 7 days, but configurable via DaysToReport for any timeframe required. Warning: the longer the time frame the longer it will take to run! .LINK GraphQL schema reference: https://rubrikinc.github.io/rubrik-api-documentation/schema/reference .PARAMETER DaysToReport The number of days to report on. Typical use cases are 3, 7, 14, or 30 day strike reports. .PARAMETER EmailSubject Set the name of the email subject, by default uses "Rubrik Multi-Day Strikes" .PARAMETER ObjectType Use Get-RSCObjectTypes for a list of valid params, can be left null to report on all objects (default), don't specify more than 1 but useful for a "MSSQL Strike Report" etc. .PARAMETER SwitchOrder If switch is not used, days are shown left to right with left being the most recent. If you prefer right to left, with right most being most recent use this switch. .PARAMETER ExcludeSystemDBs If reporting on all objects, or just MSSQL, you might not want to include system DBs (master, model etc) in this report. Use this switch to remove them automatically. .PARAMETER BackupWindowEndHour The end hour of your backup window for consideration of a succesful backup. Default is 10am unless you specicy otherwise. I.E 11am = 11 .PARAMETER BackupWindowEndminutes The end minutes of your backup window for consideration of a succesful backup. I.E 11:30am = 30 + configuring the above. .PARAMETER EmailTo The email address to send the report to. .PARAMETER EmailFrom The email address the report will be sent from. .PARAMETER SMTPServer Your local SMTP server which will accept a relay request from the server you are running this script on (does not send via RSC itself) .PARAMETER SortByColumnName The name of a single column heading in the array to sort by. I.E Username .PARAMETER ExportReportHTML Creates a HTML file of the report in the $ScriptDirectory specified when connecting to RSC. .PARAMETER SSLRequired Switch if you require SSL to send the email via SMTP locally. .PARAMETER SampleFirst100Objects If you have a large environment use this to test sampling with a subset. .OUTPUTS Logs it's actions and the result of sending the email. .EXAMPLE Send-RSCReport02MultiDayStrikes -DaysToReport 3 -EmailSubject "Rubrik 3-Strike Report" -EmailTo "admin@lab.local" -EmailFrom "reporting@lab.local" -SMTPServer "localhost" -ExcludeSystemDBs Creates a HTML report of all protected object backups within the last 3 days, excluding MSSQL system DBs. .EXAMPLE Send-RSCReport02MultiDayStrikes -DaysToReport 7 -ObjectType "VmwareVirtualMachine" -EmailSubject "Rubrik MSSQL 3-Strike Report" -EmailTo "admin@lab.local" -EmailFrom "reporting@lab.local" -SMTPServer "localhost" Creates a HTML report of all protected VmwareVirtualMachine backups within the last 7 days. .EXAMPLE Send-RSCReport02MultiDayStrikes -DaysToReport 7 -ObjectType "Mssql" -EmailSubject "Rubrik MSSQL 3-Strike Report" -EmailTo "admin@lab.local" -EmailFrom "reporting@lab.local" -SMTPServer "localhost" -ExcludeSystemDBs Creates a HTML report of all protected MSSQL full backups within the last 7 days, excluding MSSQL system DBs. .EXAMPLE Send-RSCReport02MultiDayStrikes -DaysToReport 3 -ObjectType "OracleDatabase" -EmailSubject "Rubrik 3-Strike Report" -EmailTo "admin@lab.local" -EmailFrom "reporting@lab.local" -SMTPServer "localhost" Creates a HTML report of all protected Oracle full backups within the last 3 days. .EXAMPLE Send-RSCReport02MultiDayStrikes -DaysToReport 5 -ObjectType "Db2Database" -EmailSubject "Rubrik 3-Strike Report" -EmailTo "admin@lab.local" -EmailFrom "reporting@lab.local" -SMTPServer "localhost" Creates a HTML report of all protected DB2 full backups within the last 5 days. .NOTES Author: Joshua Stenhouse Date: 05/11/2023 #> ################################################ # Paramater Config ################################################ Param ( $DaysToReport,$EmailTo,$EmailFrom,$EmailSubject,$SMTPServer,$ObjectType,$BackupWindowStartHour,$BackupWindowStartMinutes,$ExcludeObjectType,$SLADomain, [Parameter(ParameterSetName="User")][switch]$SwitchOrder, [Parameter(ParameterSetName="User")][switch]$UseSymbols, [Parameter(ParameterSetName="User")][switch]$SSLRequired, [Parameter(ParameterSetName="User")][switch]$ExcludeSystemDBs, [Parameter(ParameterSetName="User")][switch]$OnlyShowObjectsWithStrikes, [Parameter(ParameterSetName="User")][switch]$OnlyShowObjectsWithAllStrikes, [Parameter(ParameterSetName="User")][switch]$SampleFirst100Objects, [Parameter(ParameterSetName="User")][switch]$ExportReportHTML ) # Email subject IF($EmailSubject -eq $null){$EmailSubject = "Rubrik Multi-Day Strikes"} # Report Name $ReportName = "02-MultiDayStrikes" # Setting days to report to be 7 if null IF($DaysToReport -eq $null){$DaysToReport = 7} # Setting backup window start hour to be 8pm if null IF($BackupWindowStartHour -eq $null){$BackupWindowStartHour = 20} # Setting backup window start minutes to b 0 if null IF($BackupWindowStartMinutes -eq $null){$BackupWindowStartMinutes = 0} # Setting switch order IF($SwitchOrder){$SwitchOrder = $TRUE}ELSE{$SwitchOrder = $FALSE} # If multiple emails passed converting to an array IF($EmailTo -match """"){$EmailTo = Invoke-Expression $EmailTo} ################################################ # Importing Module & Running Required Functions ################################################ Import-Module RSCReporting # Getting RSC files $RSCFiles = Get-RSCModuleFiles # Getting templates $RSCTemplates = Get-RSCReportTemplates # Getting file path of required template $RSCTemplatePath = $RSCTemplates | Where-Object {$_.Report -match $ReportName} | Select-Object -ExpandProperty FilePath # Getting logo file included with module $LogoFile = $RSCFiles | Where-Object {$_.File -match "logo"} | Select-Object -ExpandProperty FilePath -First 1 # Getting the machine time $SystemDateTime = Get-Date ################################## # Setting file names required ################################## IF ($IsLinux -eq $TRUE) { $CSVExportDir = $RSCScriptDirectory + "CSVExports/" + $ReportName + "/" $ReportExportDir = $RSCScriptDirectory + "ReportExports/" + $ReportName + "/" } ELSE { $CSVExportDir = $RSCScriptDirectory + "CSVExports\" + $ReportName + "\" $ReportExportDir = $RSCScriptDirectory + "ReportExports\" + $ReportName + "\" } ################################## # Creating export directories if not exists ################################## $ReportExportDirTest = Test-Path $ReportExportDir IF ($ReportExportDirTest -eq $False) { New-Item -Path $ReportExportDir -ItemType "directory" | Out-Null } $CSVExportDirTest = Test-Path $CSVExportDir IF ($CSVExportDirTest -eq $False) { New-Item -Path $CSVExportDir -ItemType "directory" | Out-Null } ########################### # Getting RSC Data & Template ########################### IF($SampleFirst100Objects) { # Switch set for sample, only getting first 100 objects $ObjectCompliance = Get-RSCAllObjectCompliance -DaysToReport $DaysToReport -BackupWindowStartHour $BackupWindowStartHour -BackupWindowStartminutes $BackupWindowStartMinutes -SampleFirst100Objects -ObjectType $ObjectType -ExcludeObjectType $ExcludeObjectType -SLADomain $SLADomain } ELSE { # Deciding if excluding system DBs or not IF($ExcludeSystemDBs) { # Switch set to exclude system DBs, removes them on function $ObjectCompliance = Get-RSCAllObjectCompliance -DaysToReport $DaysToReport -BackupWindowStartHour $BackupWindowStartHour -BackupWindowStartminutes $BackupWindowStartMinutes -ExcludeSystemDBs -ObjectType $ObjectType -ExcludeObjectType $ExcludeObjectType -SLADomain $SLADomain } ELSE { # No switches set, getting all objects $ObjectCompliance = Get-RSCAllObjectCompliance -DaysToReport $DaysToReport -BackupWindowStartHour $BackupWindowStartHour -BackupWindowStartminutes $BackupWindowStartMinutes -ObjectType $ObjectType -ExcludeObjectType $ExcludeObjectType -SLADomain $SLADomain } } # Importing template $HTMLCode = Import-RSCReportTemplate $RSCTemplatePath #################################################################### # Calculating totals #################################################################### "---------------------------- Calculating Totals & Creating HTML Report" # Totals $ObjectCount = $ObjectCompliance | Select-Object ObjectID -Unique | Measure-Object | Select-Object -ExpandProperty Count $ObjectClusterCount = $ObjectCompliance | Select-Object ClusterID -Unique | Measure-Object | Select-Object -ExpandProperty Count $ObjectSLADomainCount = $ObjectCompliance | Select-Object SLADomainID -Unique | Measure-Object | Select-Object -ExpandProperty Count # Totals $TotalBackups = $ObjectCompliance | Select-Object -ExpandProperty Backups | Measure-Object -Sum | Select-Object -ExpandProperty Sum $TotalStrikes = $ObjectCompliance | Select-Object -ExpandProperty Strikes | Measure-Object -Sum | Select-Object -ExpandProperty Sum # Objects $ObjectsWithStrikes = $ObjectCompliance | Where-Object {$_.Strikes -gt 0} $ObjectsWithoutStrikes = $ObjectCompliance | Where-Object {$_.Strikes -eq 0} $ObjectsWithStrikesCount = $ObjectsWithStrikes | Measure-Object | Select-Object -ExpandProperty Count $ObjectsWithoutStrikesCount = $ObjectsWithoutStrikes | Measure-Object | Select-Object -ExpandProperty Count # Getting total backups that should exist for success rate calc $TotalBackupsThatShouldExist = $ObjectCount * $DaysToReport # Calculating percent, but only if there are strikes IF ($TotalStrikes -eq 0){$ObjectSuccessRate = "100%"}ELSE{$ObjectSuccessRate = ($TotalBackups / $TotalBackupsThatShouldExist).ToString("P")} # Getting integer $ObjectSuccessRateINT = $ObjectSuccessRate.Replace("%"," ").TrimEnd() # Last 24 hour totals $LastDayBackups = $ObjectCompliance | Select-Object -ExpandProperty Last24HoursBackups | Measure-Object -Sum | Select-Object -ExpandProperty Sum $LastDayStrikes = $ObjectCompliance | Select-Object -ExpandProperty Last24HoursStrikes | Measure-Object -Sum | Select-Object -ExpandProperty Sum # Calculating percent, but only if there are strikes IF ($LastDayStrikes -eq 0){$LastDaySuccessRate = "100%"}ELSE{$LastDaySuccessRate = ($LastDayBackups / $ObjectCount).ToString("P")} # Getting integer $LastDaySuccessRateINT = $LastDaySuccessRate.Replace("%"," ").TrimEnd() ################################## # SMTP Body - HTML Email style settings ################################## $HTMLStart = $HTMLCode | Where-Object {$_.SectionName -eq "Header"} | Select-Object -ExpandProperty HTMLCode $HTMLEnd = $HTMLCode | Where-Object {$_.SectionName -eq "End"} | Select-Object -ExpandProperty HTMLCode # Updating title in HTML start $HTMLStart = $HTMLStart.Replace("#HTMLReportTitle",$EmailSubject) ################################## # Creating HTML Summary table ################################## $HTMLSummaryTable = $HTMLCode | Where-Object {$_.SectionName -eq "SUMMARYTABLE"} | Select-Object -ExpandProperty HTMLCode # Updating variables in HTML code $HTMLSummaryTable = $HTMLSummaryTable.Replace("#SystemDateTime",$SystemDateTime) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#DaysToReport",$DaysToReport) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#ObjectCount",$ObjectCount) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#ObjectsWithStrikes",$ObjectsWithStrikesCount) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#ObjectsWithoutStrikes",$ObjectsWithoutStrikesCount) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#ObjectSuccessRate",$ObjectSuccessRate) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#TotalBackups",$TotalBackups) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#TotalStrikes",$TotalStrikes) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#LastDayBackups",$LastDayBackups) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#LastDayStrikes",$LastDayStrikes) $HTMLSummaryTable = $HTMLSummaryTable.Replace("#LastDaySuccessRate",$LastDaySuccessRate) ################################## # Creating Table 1 HTML structure ################################## # Creating column for every day $HTMLTable1Colunms = @() # Switching order if enabled, pulling date ranges from global variable on RSCAllObjectCompliance IF ($SwitchOrder -eq $TRUE) { [array]::Reverse($RSCDateRanges) } # For Each ForEach ($Date in $RSCDateRanges) { # Setting day $HTMLDay = $Date.DayHTML $HTMLDate = $Date.DateHTML # Creating column $HTMLTable1Column = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1COLUMNSTART"} | Select-Object -ExpandProperty HTMLCode $HTMLTable1Column = $HTMLTable1Column.Replace("#HTMLDay",$HTMLDay) $HTMLTable1Column = $HTMLTable1Column.Replace("#HTMLDate",$HTMLDate) # Adding column $HTMLTable1Colunms += $HTMLTable1Column } # Adding end to columns $HTMLTable1ColumnEnd = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1COLUMNEND"} | Select-Object -ExpandProperty HTMLCode $HTMLTable1Colunms += $HTMLTable1ColumnEnd # Creating end of table $HTMLTable1End = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1END"} | Select-Object -ExpandProperty HTMLCode #################################################################### # Getting Unique Object Types With Strikes & Creating Table Array #################################################################### $ObjectTypes = $ObjectCompliance | Sort-Object Type | Select-Object -ExpandProperty Type -Unique $HTMLTables = @() ################################## # For Each Object Type Creating Table ################################## ForEach ($ObjectType in $ObjectTypes) { # Setting object type $HTML1ObjectType = $ObjectType # Getting table 1 code $HTMLTable1Start = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1START"} | Select-Object -ExpandProperty HTMLCode # Output to host "---------------------------- CreatingHTMLTable: $HTML1ObjectType" # Getting objects $Table1Data = $ObjectCompliance | Where-Object {$_.Type -eq $HTML1ObjectType} | Sort-Object Object # Counting $HTML1ObjectCount = $Table1Data | Measure-Object | Select-Object -ExpandProperty Count $HTML1ObjectStrikeCount = $Table1Data | Where-Object {$_.Strikes -gt 0} | Measure-Object | Select-Object -ExpandProperty Count # Updating table title $HTMLTable1Start = $HTMLTable1Start.Replace("#HTMLTableTitle","$HTML1ObjectType").Replace("#HTMLTableObjectStrikeCount","$HTML1ObjectStrikeCount").Replace("#HTMLTableObjectCount","$HTML1ObjectCount") # Removing non-strike objects for list if switch used IF($OnlyShowObjectsWithStrikes){$Table1Data = $Table1Data | Where-Object {$_.Strikes -gt 0}} # Showing only all-strike objects for list if switch used IF($OnlyShowObjectsWithAllStrikes){$Table1Data = $Table1Data | Where-Object {$_.Strikes -ge $DaysToReport}} ################################## # Creating Table 1 HTML Rows ################################## # Nulling out table, protects against issues with multiple runs in PowerShell ISE $HTMLReportTable1Rows = $null # Creating table row for each line ForEach ($Row in $Table1Data) { # Setting values $HTML1Object = $Row.Object $HTML1ObjectID = $Row.ObjectID $HTML1Type = $Row.Type $HTML1Location = $Row.Location $HTML1LocationID = $Row.LocationID $HTML1Cluster = $Row.RubrikCluster $HTML1ClusterID = $Row.RubrikClusterID $HTML1SLADomain = $Row.SLADomain $HTML1SLADomainID = $Row.SLADomainID $HTML1TotalBackups = $Row.Backups $HTML1TotalStrikes = $Row.Strikes $HTML1LastBackup = $Row.LastBackup $HTML1HoursSince = $Row.HoursSince # Getting Object URLs $HTML1ClusterURL = Get-RSCObjectURL -ObjectType "Cluster" -ObjectID $HTML1ClusterID $HTML1SLAURL = Get-RSCObjectURL -ObjectType "SLADomain" -ObjectID $HTML1SLADomainID $HTML1ObjectURL = Get-RSCObjectURL -ObjectType $HTML1Type -ObjectID $HTML1ObjectID # Deciding status color IF ($HTML1TotalStrikes -gt 0){$HTMLStatusColor = "red"}ELSE{$HTMLStatusColor = "black"} # Building HTML table row $HTMLReportTable1Row = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1ROW"} | Select-Object -ExpandProperty HTMLCode $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1ObjectURL",$HTML1ObjectURL) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTMLStatusColor",$HTMLStatusColor) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Object",$HTML1Object) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Location",$HTML1Location) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1ClusterURL",$HTML1ClusterURL) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Cluster",$HTML1Cluster) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1SLAURL",$HTML1SLAURL) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1SLADomain",$HTML1SLADomain) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1LastBackup",$HTML1LastBackup) $HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1HoursSince",$HTML1HoursSince) # Getting columns for object $HTMLObjectHistory = $RSCObjectCompliance | Where-Object {$_.ObjectID -eq $HTML1ObjectID} # Switching order if enabled IF ($SwitchOrder -eq $TRUE) { [array]::Reverse($HTMLObjectHistory) } # Creating column for every day # For Each ForEach ($HTMLDate in $HTMLObjectHistory) { # Setting variables $HTML1BackupNotFound = $HTMLDate.BackupNotFound $HTML1BackupFound = $HTMLDate.BackupFound $HTML1Day = $HTMLDate.DayHTML $HTML1Date = $HTMLDate.DateHTML $HTML1DayDate = $HTML1Day + " " + $HTML1Date # Setting result - new way IF ($HTML1BackupFound -eq 1){$HTML1BackupStatus = "green"}ELSE{$HTML1BackupStatus = "red"} # Changing result if set to use symbols IF ($UseSymbols) { # Setting appropirate symbol IF ($HTML1BackupFound -eq 1){$HTML1Symbol = "✔"}ELSE{$HTML1Symbol = "❌"} # Setting cell background to nothing as using symbols $HTML1BackupStatus = $null } ELSE { # Not using symbols, so setting to null $HTML1Symbol = $null } # Creating column $HTMLTable1Column = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1COLUMN"} | Select-Object -ExpandProperty HTMLCode $HTMLTable1Column = $HTMLTable1Column.Replace("#HTML1BackupStatus",$HTML1BackupStatus) $HTMLTable1Column = $HTMLTable1Column.Replace("#HTML1Date",$HTML1DayDate) $HTMLTable1Column = $HTMLTable1Column.Replace("#HTML1Symbol",$HTML1Symbol) # Adding column $HTMLReportTable1Row += $HTMLTable1Column } # Adding end to columns $HTMLTable1ColumnEnd = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1COLUMNEND"} | Select-Object -ExpandProperty HTMLCode $HTMLReportTable1Row += $HTMLTable1ColumnEnd # Adding row to table $HTMLReportTable1Rows += $HTMLReportTable1Row } ################################## # Putting Table 1 together ################################## $HTMLTable1 = $HTMLTable1Start + $HTMLTable1Colunms + $HTMLReportTable1Rows + $HTMLTable1End # Adding to tables array $HTMLTables += $HTMLTable1 ################################## # End of for each object type below ################################## } # End of for each object type above ################################## # Creating Report ################################## # Building HTML report: $HTMLReport = $HTMLStart + $HTMLSummaryTable + $HTMLTables + $HTMLEnd # Replacing any 100.00% strings with 100% for easier reading $HTMLReport = $HTMLReport.Replace("100.00%","100%").TrimEnd() ################################## # Exporting Report ################################## # Creating the file names $ObjectReportFile = $ReportExportDir + $ReportName + "-" + $SystemDateTime.ToString("yyyy-MM-dd") + "@" + $SystemDateTime.ToString("HH-mm-ss") + ".html" # Exporting the report, if enabled IF($ExportReportHTML) { $HTMLReport | Out-File -FilePath $ObjectReportFile -Force # Output to host "---------------------------- CreatedReport: $ObjectReportFile" } ################################## # Creating CSVs ################################## # Creating the file names $ObjectCSVFile = $CSVExportDir + "Rubrik-AllObjects-" + $SystemDateTime.ToString("yyyy-MM-dd") + "@" + $SystemDateTime.ToString("HH-mm-ss") + ".csv" $ObjectStrikesCSVFile = $CSVExportDir + "Rubrik-Strikes-" + $SystemDateTime.ToString("yyyy-MM-dd") + "@" + $SystemDateTime.ToString("HH-mm-ss") + ".csv" # Exporting to CSV $ObjectCompliance | Sort-Object Strikes,Object | Export-Csv -Path $ObjectCSVFile -NoTypeInformation -Force $ObjectCompliance | Where-Object {$_.Strikes -gt 0} | Sort-Object Strikes,Object | Export-Csv -Path $ObjectStrikesCSVFile -NoTypeInformation -Force # Creating email attachement $Attachments = "$ObjectCSVFile" ################################## # Sending email using function ################################## # Output to host "---------------------------- SendingEmailTo: $EmailTo" # Sending Try { Send-RSCEmail -SMTPServer $SMTPServer -EmailTo $EmailTo -EmailFrom $EmailFrom -EmailBody $HTMLReport -EmailSubject $EmailSubject -Attachments $Attachments $EmailSent = $TRUE } Catch { $EmailSent = $FALSE $Error[0] | Format-List -Force } # Returning status Return $EmailStatus } ############################################### # End of script ############################################### |