################################################################################################ ## 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
$title - $date
"@ $head | Out-File $fileName } # ============================================================================================== Function writeTableHeader { param($fileName) $tableHeader = @" "@ $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
ComputerName FolderPath WorkerGroups Ping Logons LoadEvaluator ICAPort WMI WeeklyReboot
$_$_$_