Get cluster html formatted report using PowerShell

Getting cluster information is pretty simple, however its becoming a little more complicated when you want to get this remotely. In one of the previous articles I have written about getting cluster data remotely. Today I would like to share with you one of my newest script for creating cluster report. Final results will be send to email in nice formatted html table:

Get cluster report
cluster
cluster

I found some great function on internet which converts quickly an array into html:

#Function for converting Array into Html
Function Create-HTMLTable{
         
    param([array]$Array)
         
    $arrHTML = $Array | ConvertTo-Html
    $arrHTML[-1] = $arrHTML[-1].ToString().Replace('</body></html>'," ")
         
    Return $arrHTML[5..2000]
}

Basically our script is based on few FailoverClusters module commands – full description can be found on technet site.

Get-ClusterResource | Select-Object ownernode,iscoreresource,name,resourcetype,state,characteristics
Get-ClusterGroup  | Select-Object cluster,Iscoregroup,ownernode,state,name
Get-ClusterNode | Select-Object cluster,name,state,nodeweight

I also added here a cool feature which is doing 5 sending email attempts just in case of some timeout error.

# Use loop to do 5 attempts in case of failure
    $n=1
    do 
    {
        $ErrorMessage = $null
        Write-Host Attempt $n - Sending email
                        
        #Send email
        Send-MailMessage -ErrorAction SilentlyContinue -ErrorVariable SendError -To $emailTo -Subject $subject -BodyAsHtml $output -SmtpServer $smtpServer -port $port -From $emailFrom -Priority $priority
                        
        $ErrorMessage = $SendError.exception.message
        If($ErrorMessage)
        {
            Write-Warning $ErrorMessage
            Start-Sleep -Seconds 5
        }
        
        $n++
    } 
    until ( $SendError.exception.message -eq $null -or $n -eq 6 )

    If($SendError.exception.message -eq $null)
    {
        Write-Host `nEmail has been sent to $emailto -ForegroundColor Yellow
    }
    Else
    {
        Write-Host `nFailed to sent email to $emailto -ForegroundColor Yellow
    }

Final script:


#=======================================================================
#Function for converting Array into Html
Function Create-HTMLTable{
        
    param([array]$Array)
        
    $arrHTML = $Array | ConvertTo-Html
    $arrHTML[-1] = $arrHTML[-1].ToString().Replace('</body></html>'," ")
        
    Return $arrHTML[5..2000]
}

#=======================================================================
#Servers and credentials
$ClusterServers = "Cluster01",
                  "Cluster02", 
                  "Cluster03",
                  "Cluster04"

$Servers = $ClusterServers
$Cred = Get-Credential "domain\$env:username"

#=======================================================================
# Setup email parameters
$SubDate = (Get-Date).ToString('MMMM-dd')
$mailTo = ((Get-ADUser -Identity $ENV:Username -Properties mail).mail ) 
$subject = "[Cluster report]" + $SubDate
$priority = "Normal"
$smtpServer = "smtp.powershellbros.com"
$emailFrom = ”Reports@powershellbros.com”
$emailTo = $mailTo
$port = 25 

$output = $null

#=======================================================================
#Creating head style and header title
$output = @()
$output += '<html><head></head><body>'
$output += 
@"
<style>
  body {
    font-family: "Arial";
    font-size: 8pt;
    }
  th, td, tr { 
    border: 1px solid #A4A4A4;
    border-collapse: collapse;
    padding: 10px;
    text-align: center;
    }
  th {
    font-size: 9pt;
    text-align: center;
    background-color: #0B2161;
    color: #EFF2FB;
    }
  td {
    color: #000000;
    
    }
  .even { background-color: #E6E6E6; }
  .odd { background-color: #084B8A; }
  h6 { font-size: 8pt; 
       font-color: black;
       font-weight: bold;
       }

 text { font-size: 8pt;
        font-color: black;
        }
 }
</style>
"@
$output += "<h2 style='color: #0B2161'>PowerShellBros cluster</h2>"


#=======================================================================
# Looping servers
ForEach ($Server in $Servers) 
{
    $Server = $Server.Trim()
    $DNSCheck = $null
    $DNSCheck = ([System.Net.Dns]::GetHostByName(("$Server")))

    If($DNSCheck)
    {
        $Server = $DNSCheck.hostname
        
        $ClusRes = $null
        $ClusOwn = $null
        $ClusNod = $null
        $CheckService = $null

        Write-Host "Processing $Server" -ForegroundColor Green
        
        # Check if cluster service exist
        Try
        {
            $CheckService = Invoke-Command -ComputerName $Server -ErrorAction Stop -ScriptBlock{Get-Service -Name ClusSvc } -Credential $Cred
        }
        Catch 
        {
            $_.Exception.Message
            Continue
        }

        If(!$CheckService)
        {
            Continue
        }
        Else
        {
            Try
            {
                #Checking cluster recources:"
                $ClusRes = Invoke-Command -ComputerName $Server -ErrorAction Stop -ScriptBlock{Get-ClusterResource | Select-Object ownernode,iscoreresource,name,resourcetype,state,characteristics | Sort-Object IsCoreResource -Descending } -Credential $Cred | Select-Object * -ExcludeProperty PSComputerName,RunspaceId,PSShowComputerName
                $output += '<p>'
                $output += '<h4>Cluster recources:</h4>'
                $output += '<p>'
                $output += Create-HTMLTable $ClusRes
                $output += '</p>' 

                #Checking cluster owner nodes:"
                $ClusOwn = Invoke-Command -ComputerName $Server -ErrorAction Stop -ScriptBlock{Get-ClusterGroup  | Select-Object cluster,Iscoregroup,ownernode,state,name} -Credential $Cred | Select-Object * -ExcludeProperty PSComputerName,RunspaceId,PSShowComputerName
                $output += '<p>'
                $output += '<h4>Cluster owner nodes:</h4>'
                $output += '<p>'
                $output += Create-HTMLTable $ClusOwn
                $output += '</p>'

                #Checking cluster nodes:"
                $ClusNod = Invoke-Command -ComputerName $Server -ErrorAction Stop -ScriptBlock{Get-ClusterNode | Select-Object cluster,name,state,nodeweight} -Credential $Cred | Select-Object * -ExcludeProperty PSComputerName,RunspaceId,PSShowComputerName
                $output += '<p>'
                $output += '<h4>Cluster nodes:</4>'
                $output += '<p>'
                $output += Create-HTMLTable $ClusNod
                $output += '</p>'

                # End
                $output += '</body></html>' 
                $output =  $output | Out-String
                Break
            }
            Catch
            {
                $_.Exception.Message
                Continue
            }
        }
    }
}

#=======================================================================
#Continue if report was created
If(!($ClusRes -and $ClusOwn -and $ClusNod))
{
    Write-Warning 'Failed to create report'
}
Else
{
    # Use loop to do 5 attempts in case of failure
    $n=1
    do 
    {
        $ErrorMessage = $null
        Write-Host Attempt $n - Sending email
                        
        #Send email
        Send-MailMessage -ErrorAction SilentlyContinue -ErrorVariable SendError -To $emailTo -Subject $subject -BodyAsHtml $output -SmtpServer $smtpServer -port $port -From $emailFrom -Priority $priority
                        
        $ErrorMessage = $SendError.exception.message
        If($ErrorMessage)
        {
            Write-Warning $ErrorMessage
            Start-Sleep -Seconds 5
        }
        
        $n++
    } 
    until ( $SendError.exception.message -eq $null -or $n -eq 6 )

    If($SendError.exception.message -eq $null)
    {
        Write-Host `nEmail has been sent to $emailto -ForegroundColor Yellow
    }
    Else
    {
        Write-Host `nFailed to sent email to $emailto -ForegroundColor Yellow
    }
}
#=======================================================================

pause

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.