Functions/Send/Send-RSCReport01GlobalClusterHealth.ps1

################################################
# Function - Save-RSCReport01GlobalClusterHealth - Sending RSC Report
################################################
Function Save-RSCReport01GlobalClusterHealth {

<#
.SYNOPSIS
Creates and emails a pre-canned HTML report on all your Rubrik clusters.
 
.DESCRIPTION
Pre-built template of a common request for a global daily cluster health email.
 
.LINK
GraphQL schema reference: https://rubrikinc.github.io/rubrik-api-documentation/schema/reference
 
.PARAMETER Directory
The directory to save the report in.
 
.OUTPUTS
Logs it's actions and the result of sending the email.
 
.EXAMPLE
Send-RSCReport01GlobalClusterHealth -EmailTo "admin@lab.local" -EmailFrom "reporting@lab.local" -SMTPServer "localhost"
Creates a HTML report of all your Rubrik clusters and emails it via local SMTP.
 
.NOTES
Author: Joshua Stenhouse
Date: 05/11/2023
#>

################################################
# Paramater Config
################################################
    Param
    (
        $Directory
    )

# Threholds for coloring storage usage fields (%)
$WarningUsedThreshold = 85
$FailureUsedThreshold = 95
# HTML Color codes used for reports
$HTMLColorSuccess = "#000000"
$HTMLColorWarning = "#ff8c00"
$HTMLColorFailure = "#e60000"
# Report Name
$ReportName = "Rubrik Global Cluster Health"
################################################
# Importing Module & Running Required Functions
################################################
Import-Module RSCReporting
# Checking connectivity, exiting function with error if not connected
Test-RSCConnection
# 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 the machine time
$SystemDateTime = Get-Date
##################################
# Report Description
##################################
$ReportDescription = "This report gives you a list of all Rubrik clusters current status including version, capacity, used storage etc. It is designed to be used as a daily report showing cluster health across a global deployment. If you are looking for cluster storage trending over time use report 22-GlobalClusterStorageUsage."
##################################
# 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
}
##################################
# Setting Time
##################################
$SystemDateTime = Get-Date
###########################
# Getting RSC Data & Template
###########################
$RubrikClusters = Get-RSCClusters
# Importing template
$HTMLCode = Import-RSCReportTemplate $RSCTemplatePath
##################################
# Calculating totals
##################################
$ClusterCount = $RubrikClusters | Measure-Object | Select-Object -ExpandProperty Count
$ClusterCriticalCount = $RubrikClusters | Where-Object {$_.BadNodes -ge "1"} | Measure-Object | Select-Object -ExpandProperty Count
$ClusterHealthyCount = $RubrikClusters | Where-Object {$_.BadNodes -eq "0"} | Measure-Object | Select-Object -ExpandProperty Count
$ClusterNodeCount = $RubrikClusters | Select-Object -ExpandProperty TotalNodes | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClusterBadNodeCount = $RubrikClusters | Select-Object -ExpandProperty BadNodes | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClusterHealthyNodeCount = $RubrikClusters | Select-Object -ExpandProperty HealthyNodes | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClustersPhsical = $RubrikClusters | Where-Object {$_.Type -eq "Physical"} | Measure-Object | Select-Object -ExpandProperty Count
$ClustersVirtual = $RubrikClusters | Where-Object {$_.Type -ne "Physical"} | Measure-Object | Select-Object -ExpandProperty Count
$ClusterTotalCapacityTB = $RubrikClusters | Select-Object -ExpandProperty TotalStorageTB | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClusterTotalUsedTB = $RubrikClusters | Select-Object -ExpandProperty UsedStorageTB | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClusterTotalFreeTB = $RubrikClusters | Select-Object -ExpandProperty FreeStorageTB | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClustersTotalProtectedObjects = $RubrikClusters | Select-Object -ExpandProperty ProtectedObjects | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClustersTotalDoNotProtectObjects = $RubrikClusters | Select-Object -ExpandProperty DoNotProtectObjects | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClustersTotalUnProtectedObjects = $RubrikClusters | Select-Object -ExpandProperty UnProtectedObjects | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ClustersTimeZones = $RubrikClusters | Select-Object -ExpandProperty Timezone -Unique | Measure-Object | Select-Object -ExpandProperty Count
# Counting clusters not connected
$ClustersNotConnectedCount = $RubrikConnections | Where-Object {$_.ConnectionStatus -ne "Connected"} | Measure-Object | Select-Object -ExpandProperty Count
# Combining
$ClusterTotalCriticalCount = $ClusterCriticalCount + $ClustersNotConnectedCount
##################################
# 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("#ClusterCount",$ClusterCount)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterNodeCount",$ClusterNodeCount)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterTotalCapacityTB",$ClusterTotalCapacityTB)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClustersTotalProtectedObjects",$ClustersTotalProtectedObjects)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterCriticalCount",$ClusterTotalCriticalCount)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterBadNodeCount",$ClusterBadNodeCount)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterTotalUsedTB",$ClusterTotalUsedTB)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClustersTimeZones",$ClustersTimeZones)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterHealthyCount",$ClusterHealthyCount)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterHealthyNodeCount",$ClusterHealthyNodeCount)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClusterTotalFreeTB",$ClusterTotalFreeTB)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClustersTotalDoNotProtectObjects",$ClustersTotalDoNotProtectObjects)
$HTMLSummaryTable = $HTMLSummaryTable.Replace("#ClustersTotalUnProtectedObjects",$ClustersTotalUnProtectedObjects)
##################################
# Creating Table 1 HTML structure
##################################
$HTMLTable1Start = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1START"} | Select-Object -ExpandProperty HTMLCode
$HTMLTable1End = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1END"} | Select-Object -ExpandProperty HTMLCode
##################################
# Creating Table 1 HTML Rows
##################################
# Selecting data required for HTML rows
$RubrikClusters = $RubrikClusters | Sort-Object ProtectedObjects -Descending
# Counting records
$RubrikClusterCount = $RubrikClusters | Measure-Object | Select-Object -ExpandProperty Count
$RubrikClusterCounter = 0
# Output to host
"----------------------------"
# Nulling out table, protects against issues with multiple runs in PowerShell ISE
$HTMLReportTable1Middle = $null
# Creating table row for each line
ForEach ($Row in $RubrikClusters) 
{
# Incrementing counter
$RubrikClusterCounter ++
# Output to host
"ProcessingCluster: $RubrikClusterCounter/$RubrikClusterCount"
# Setting values
$HTML1Name = $Row.Cluster
$HTML1Type = $Row.Type
$HTML1ClusterID = $Row.ClusterID
$HTML1Status = $Row.Status
$HTML1ConnectionStatus = $Row.ConnectionStatus
$HTML1Version = $Row.Version
$HTML1VersionStatus = $Row.VersionStatus
$HTML1Nodes = $Row.TotalNodes
$HTML1BadNodes = $Row.BadNodes
$HTML1Disks = $Row.TotalDisks
$HTML1BadDisks = $Row.BadDisks
$HTML1CapacityTB = $Row.TotalStorageTB
$HTML1UsedTB = $Row.UsedStorageTB
$HTML1FreeTB = $Row.FreeStorageTB
$HTML1Used = $Row.Used
$HTML1Free = $Row.Free
$HTML1LocalDedupeRateINT = $Row.LocalDataReduction
$HTML1CloudDedupeRateINT = $Row.ArchiveDataReduction
$HTML1Runwaydays = $Row.RunwayDays
$HTML1Protected = $Row.ProtectedObjects
$HTML1Unprotected = $Row.UnprotectedObjects
$HTML1DoNotProtect = $Row.DoNotProtectObjects
$HTML1SLADomains = $Row.SLADomains
$HTML1TimeZone = $Row.Timezone
$HTML1Location = $Row.Location
$HTML1Encrypted = $Row.Encrypted
# Getting INT
$HTML1UsedINT = $HTML1Used.Replace("%","")
# Getting URL for cluster
$HTML1ClusterURL = Get-RSCObjectURL -ObjectType "Cluster" -ObjectID $HTML1ClusterID
# Setting cluster status color
IF ($HTML1Status -eq "Healthy"){$HTMLStatusColor =  $HTMLColorSuccess}
IF ($HTML1Status -ne "Healthy"){$HTMLStatusColor =  $HTMLColorFailure}
# Overriding status color if not connected recently
IF ($HTML1ConnectionStatus -eq "Connected"){$HTMLStatusColor =  $HTMLColorSuccess}
IF ($HTML1ConnectionStatus -ne "Connected"){$HTMLStatusColor =  $HTMLColorFailure}
# Overriding status color if running low on space
IF ($HTML1UsedINT -lt $FailureUsedThreshold){$HTMLSpaceStatusColor =  $HTMLColorSuccess}
IF ($HTML1UsedINT -ge $WarningUsedThreshold){$HTMLSpaceStatusColor =  $HTMLColorWarning}
IF ($HTML1UsedINT -ge $FailureUsedThreshold){$HTMLSpaceStatusColor =  $HTMLColorFailure}
# Setting color for status
IF ($HTML1VersionStatus -eq "STABLE"){$HTMLVersionStatusColor = $HTMLColorSuccess}
IF ($HTML1VersionStatus -ne "STABLE"){$HTMLVersionStatusColor = $HTMLColorWarning}
# Building HTML table row
$HTMLReportTable1Row = $HTMLCode | Where-Object {$_.SectionName -eq "TABLE1ROW"} | Select-Object -ExpandProperty HTMLCode
# Updating variables in HTML code
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1ClusterURL",$HTML1ClusterURL)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Name",$HTML1Name)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Type",$HTML1Type)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTMLStatusColor",$HTMLStatusColor)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Status",$HTML1Status)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Errors",$HTML1Errors)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Version",$HTML1Version)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTMLVersionStatusColor",$HTMLVersionStatusColor)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Nodes",$HTML1Nodes)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1BadNodes",$HTML1BadNodes)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Disks",$HTML1Disks)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1BadDisks",$HTML1BadDisks)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Details",$HTML1Details)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTMLSpaceStatusColor",$HTMLSpaceStatusColor)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Used",$HTML1Used)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Free",$HTML1Free)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1TBCapacity",$HTML1CapacityTB)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1TBUsed",$HTML1UsedTB)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1TBFree",$HTML1FreeTB)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Runwaydays",$HTML1Runwaydays)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Protected",$HTML1Protected)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Unprotected",$HTML1Unprotected)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1DoNotProtect",$HTML1DoNotProtect)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1TimeZone",$HTML1TimeZone)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Location",$HTML1Location)
$HTMLReportTable1Row = $HTMLReportTable1Row.Replace("#HTML1Encrypted",$HTML1Encrypted)
# Adding row to table
$HTMLReportTable1Middle += $HTMLReportTable1Row
}
##################################
# Putting Table 1 together
##################################
$HTMLTable1 = $HTMLTable1Start + $HTMLReportTable1Middle + $HTMLTable1End
##################################
# Creating Report
##################################
# Building HTML report:
$HTMLReport = [string]$HTMLStart + [string]$HTMLSummaryTable + [string]$HTMLTable1 + [string]$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 = $Directory + $ReportName + "-" + $SystemDateTime.ToString("yyyy-MM-dd") + "@" + $SystemDateTime.ToString("HH-mm-ss") + ".html"
# Exporting the report, if enabled
# Output to host
"----------------------------
CreatedReport: $ObjectReportFile"

$HTMLReport | Out-File -FilePath $ObjectReportFile -Force
##################################
# Creating CSVs
##################################
# Creating the file names
$ObjectCSVFile = $Directory + $ReportName + "-" + $SystemDateTime.ToString("yyyy-MM-dd") + "@" + $SystemDateTime.ToString("HH-mm-ss") + ".csv"
# Exporting to CSV
$RubrikClusters | Export-Csv -Path $ObjectCSVFile -NoTypeInformation -Force
# Returning status
Return $null
}
###############################################
# End of script
###############################################