################################################################################################
## XenAppServerHealthCheck
## Jason Poyner, jason.poyner@deptive.co.nz, techblog.deptive.co.nz
## 28 May 2012
## v1.0
##
## The script checks the health of a XenApp 6.x farm and e-mails two reports. The full farm
## health report is attached to the e-mail and any errors encountered are in an html report
## embedded in the email body.
## This script checks the following:
## - Ping response
## - Logon enabled
## - Assigned Load Evaluator
## - ICA port response (at this stage only ICA, not CGP is tested)
## - WMI response (to check for WMI corruption)
## - Server uptime (to ensure scheduled reboots are occurring)
## - Server folder path and worker group memberships are report for informational purposes
##
## You are free to use this script in your environment but please e-mail me any improvements.
################################################################################################
Add-PSSnapin Citrix.XenApp.Commands
# Change the below variables to suit your environment
#==============================================================================================
# Default load evaluator assigned to servers. If the load evaluator assigned to a server does
# not match this load evaluator the server is flagged in the script report.
$defaultLE = "Acme Default"
# We always schedule reboots on XenApp farms, usually on a weekly basis. Set the maxUpTimeDays
# variable to the maximum number of days a XenApp server should be up for.
$maxUpTimeDays = 7
$emailFrom = "XenAppFarmReport@acme.com"
$emailTo = "XenAppAdmins@acme.com"
$smtpServer = "acmesmtp"
#==============================================================================================
$successCodes = @("success","ok","enabled")
$currentDir = Split-Path $MyInvocation.MyCommand.Path
$logfile = Join-Path $currentDir ("XenAppServerHealthCheck.log")
$resultsHTM = Join-Path $currentDir ("XenAppServerHealthCheckResults.htm")
$errorsHTM = Join-Path $currentDir ("XenAppServerHealthCheckErrors.htm")
rm $logfile -force
#==============================================================================================
function LogMe() {
Param(
[parameter(Mandatory = $true, ValueFromPipeline = $true)] $logEntry,
[switch]$display,
[switch]$error,
[switch]$warning,
[switch]$progress
)
if ($error) {
$logEntry = "[ERROR] $logEntry" ; Write-Host "$logEntry" -Foregroundcolor Red}
elseif ($warning) {
Write-Warning "$logEntry" ; $logEntry = "[WARNING] $logEntry"}
elseif ($progress) {
Write-Host "$logEntry" -Foregroundcolor Green}
elseif ($display) {
Write-Host "$logEntry" }
#$logEntry = ((Get-Date -uformat "%D %T") + " - " + $logEntry)
$logEntry | Out-File $logFile -Append
}
#==============================================================================================
function Ping([string]$hostname, [int]$timeout = 200) {
$ping = new-object System.Net.NetworkInformation.Ping #creates a ping object
try {
$result = $ping.send($hostname, $timeout).Status.ToString()
} catch {
$result = "failure"
}
return $result
}
#==============================================================================================
Function writeHtmlHeader
{
param($title, $fileName)
$date = ( Get-Date ).ToString('dddd dd/MM/yyyy')
$head = @"
$title
"@
$head | Out-File $fileName
}
# ==============================================================================================
Function writeTableHeader
{
param($fileName)
$tableHeader = @"
ComputerName |
FolderPath |
WorkerGroups |
Ping |
Logons |
LoadEvaluator |
ICAPort |
WMI |
WeeklyReboot |
"@
$tableHeader | Out-File $fileName -append
}
# ==============================================================================================
Function writeData
{
param([string[]]$infoColumns, [string[]]$rowData, $fileName)
# Populate info cells
$tableEntry = ""
$infoColumns | % {
$tableEntry += "$_ | "
}
# Populate data cells and colour them red or green based on success/failure
$rowData | % {
# Check for possible success messages
if ($_ -eq "success" -or $_ -eq "enabled" -or $_ -eq "ok")
{
$tableEntry += "$_ | "
}
else
{
$tableEntry += "$_ | "
}
}
$tableEntry += "
"
$tableEntry | Out-File $fileName -append
}
# ==============================================================================================
Function writeHtmlFooter
{
param($fileName)
@"
"@ | Out-File $FileName -append
}
# ==============================================================================================
# == MAIN SCRIPT ==
# ==============================================================================================
"Checking server health..." | LogMe -display
$allResults = @()
Get-XAServer | % {
$Results = "" | Select-Object ComputerName, FolderPath, WorkerGroups, Ping, Logons, LoadEvaluator, ICAPort, WMI, WeeklyReboot
$server = $_.ServerName
$server | LogMe -display -progress
$Results.ComputerName = $server
$Results.FolderPath = $_.FolderPath
$Results.WorkerGroups = Get-XAWorkerGroup -ServerName $server | % {$_.WorkerGroupName}
$result = Ping $server 100
$Results.Ping = $result
# Check server logons
if($_.LogOnsEnabled -eq $false){
"Logons are disabled on this server" | LogMe -display -warning
$Results.Logons = "Disabled"
} else {
$Results.Logons = "Enabled"
}
# Check Load Evaluator
if ((Get-XALoadEvaluator -ServerName $_.ServerName).LoadEvaluatorName -ne $defaultLE) {
"Non-default Load Evaluator assigned" | LogMe -display -warning
$Results.LoadEvaluator = Get-XALoadEvaluator -ServerName $_.ServerName
} else {
$Results.LoadEvaluator = "Success"
}
if($result -eq "Success"){
# Test ICA connectivity
$Results.ICAPort = "Error"
try {
$socket = new-object System.Net.Sockets.TcpClient($ip, $_.IcaPortNumber) #creates a socket connection to see if the port is open
} catch {
$socket = $null
}
if($socket -ne $null) {
"Socket Connection Successful" | LogMe
$stream = $socket.GetStream() #gets the output of the response
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding
Start-Sleep -Milliseconds 500 #records data for half a second
while($stream.DataAvailable)
{
$read = $stream.Read($buffer, 0, 1024)
$response=$encoding.GetString($buffer, 0, $read)
if($response -like '*ICA*'){
"ICA protocol responded" | LogMe
$Results.ICAPort = "Success"
} else {
"ICA did not respond" | LogMe -display -error
}
}
} else {
"Socket connection failed" | LogMe -display -error
}
# Test WMI
$Results.WMI = "Error"
try {
$wmi=Get-WmiObject -class Win32_OperatingSystem -computer $_.ServerName
} catch {
$wmi = $null
}
# Check for server uptime
if ($wmi -ne $null) {
$Results.WMI = "Success"
$LBTime=$wmi.ConvertToDateTime($wmi.Lastbootuptime)
[TimeSpan]$uptime=New-TimeSpan $LBTime $(get-date)
if ($uptime.days -gt $maxUpTimeDays){
"Server reboot warning, last reboot: {0:D}" -f $LBTime | LogMe -display -error
$Results.WeeklyReboot = "Error"
} else {
$Results.WeeklyReboot = "Success"
}
} else {
"WMI connection failed - check WMI for corruption" | LogMe -display -error
}
}
else {
("Cannot ping " + $server) | LogMe -display -error
}
$allResults += $Results
}
# Write all results to an html file
Write-Host ("Saving results to html report: " + $resultsHTM)
#$allResults | sort-object -property ComputerName | export-csv $resultsCSV -noTypeInformation
writeHtmlHeader "XenApp Farm Report" $resultsHTM
writeTableHeader $resultsHTM
$allResults | sort-object -property ComputerName | % {
writeData $_.ComputerName, $_.FolderPath, $_.WorkerGroups $_.Ping, $_.Logons, $_.LoadEvaluator, $_.ICAPort, $_.WMI, $_.WeeklyReboot $resultsHTM
}
writeHtmlFooter $resultsHTM
# Write only the errors to an html file
$allErrors = $allResults | where-object { $_.Ping -ne "success" -or $_.Logons -ne "enabled" -or $_.LoadEvaluator -ne "success" -or $_.ICAPort -ne "success" -or $_.WMI -ne "success" -or $_.WeeklyReboot -ne "success" }
Write-Host ("Saving errors to html report: " + $errorsHTM)
#$allErrors | sort-object -property ComputerName | export-csv $errorsCSV -noTypeInformation
writeHtmlHeader "XenApp Farm Report Errors" $errorsHTM
writeTableHeader $errorsHTM
$allErrors | sort-object -property ComputerName | % {
writeData $_.ComputerName, $_.FolderPath, $_.WorkerGroups $_.Ping, $_.Logons, $_.LoadEvaluator, $_.ICAPort, $_.WMI, $_.WeeklyReboot $errorsHTM
}
writeHtmlFooter $errorsHTM
$mailMessageParameters = @{
From = $emailFrom
To = $emailTo
Subject = ("XenApp Farm Report - " + (Get-Date).ToString('dddd dd/MM/yyyy'))
SmtpServer = $smtpServer
Body = (gc $errorsHTM) | Out-String
Attachment = $resultsHTM
}
Send-MailMessage @mailMessageParameters -BodyAsHtml