A XenDesktop environment isn't always critical but when it grows with more desktops, more infrastructure servers and especially when it has many customers depending on its proper functionality to fulfill their tasks the availability of the desktops is crucial. Unless you are working only with Citrix XenDesktop in a daily manner but work with many other different infrastructures simultaneously you would hardly find time to navigate to the console and check how the desktops are performing every day. "Hey Nimantha, I've been trying to log in to this Citrix Desktop for some time but it takes ages and still does not log me in!", then it comes to my mind "damn, what is going on there... I didn't log into it in.. like.. months...!". Then only we get the idea of opening the console and see what is out of the ordinary but now the problem has already occurred. What if I got a report of the health of the XenDesktop environment early in the morning stating that there are a number of them doing not-so-well. Well, then as soon as the guy says, "Hey Nimantha, I've been trying to log in to this Citrix Desktop for..." I would know "Aha, this must be the issue..." or I may already have solved that issue as soon as I saw the report in the morning and the customer never had to experience it.
Long story short, what I did is I created a powershell script that would examine the status of the desktops and the critical infrastructure (the Delivery Controllers, the Provisioning Servers, the XenServers, etc.) at a given schedule and send a report including the statistics in an email to me and my team. For me this report saves a lot of time that I had to spend logging on to the Delivery Controller, then opening the Desktop Studio, then navigating to each desktop group and check the status of the desktops. To be honest although I had the idea of creating this script I had no idea where to start and neither did I know powershell. But, one day, thanks to Miguel Contreras who posted a skeleton script for this purpose in one of his blog posts I was determined to do this somehow and that led me to creating this script and also to mastering powershell along the way.
This script does 6 things.
1. Look for pooled VMs that have not rebooted since the last user logged off and resets them if there are any.
2. Look for VMs that are powered on and unregistered.
3. Look for VMs that are in maintenance mode.
4. Check the availability of the infrastructure servers using ping.
5. Send the summary of 2, 3, and 4 as a report to specified recipients in an email.
6. Log the summarized report to a specified location.
Here is the script:
##----- Start of the script -----
# Load Citrix PowerShell modules
Asnp Citrix.*
#=====================================================================================
$recipients = "someone@somewhere.com","anyother@somewhere.com"
$fromEmail = "XDHealthCheck@somewhere.com"
$SMTPserver = "smtp.somewhere.com"
$currentTime = Get-Date -Format "yyyy-MM-dd | hh:mm:ss tt"
$logTime = Get-Date -Format "yyyy-MM-dd_hh-mm"
$LogFile = "C:\Monitoring\Logs\HealthReport-$logTime.html"
$servers = "DeliveryController1","ProvisioningServer1","XenServer1"
$site = "New York"
$DDC = $Env:COMPUTERNAME
#=====================================================================================
#=====================================================================================
#Reset VMs that failed to reboot after user log off
$badVMs = Get-BrokerDesktop -PowerActionPending $false -PowerState On -SummaryState Available -WillShutdownAfterUse $true -MaxRecordCount 5000
If ($badVMs)
{
foreach($vm in $badVMs)
{
New-BrokerHostingPowerAction -MachineName $vm.HostedMachineName -Action 'Reset'
}
}
$RptHeader = "<!DOCTYPE html>"
$RptHeader+= "<html>"
$RptHeader+= "<head>"
$RptHeader+= "</head>"
$RptHeader+= "<body>"
$RptHeader+= "<h2><font color='purple' face='cambria'>XenDesktop Health Status Report $currentTime </font></h2>"
#Get unregistered VMs
$RptBody += "<b><font color='purple' face='cambria'><u>UNREGISTERED MACHINES</u></font></b><br><br>"
$unregVM = Get-BrokerDesktop -MaxRecordCount 5000 | ? {($_.RegistrationState -eq 'Unregistered') -and ($_.PowerState -eq 'On')}
if (!$unregVM){
$RptBody += "<font color='green' face='cambria'> *** None *** </font>"
}
else{
$RptBody += "<table border=0>"
$RptBody += "<tr>"
$RptBody += "<th><font color='midnightblue' face='cambria'><u>Machine Name</u></font></th><th/>"
$RptBody += "<th><font color='midnightblue' face='cambria'><u>Desktop Group Name</u></font></th><th/>"
$RptBody += "<th><font color='midnightblue' face='cambria'><u>Reason for Last Deregistration</u></font></th>"
$RptBody += "</tr>"
foreach($unregVM in (Get-BrokerDesktop -MaxRecordCount 5000 | ? {($_.RegistrationState -eq 'Unregistered') -and ($_.PowerState -eq 'On')})) {
$RptBody += "<tr><td>" + $unregVM.HostedMachineName + "</td>" + "<td/>" + "<td>" + $unregVM.DesktopGroupName + "</td>" + "<td/>" + "<td>" + $unregVM.LastDeregistrationReason + "</td></tr>"
}
$RptBody += "</table>"
}
$RptBody += "<br><br>"
#Get maintenance mode VMs
$RptBody += "<b><font color='purple' face='cambria'><u>MACHINES IN MAINTENANCE MODE</u></font></b><br><br>"
$maintModeVM = (Get-BrokerDesktop -MaxRecordCount 5000 | ? {$_.InMaintenanceMode -eq 'True'})
if (!$maintModeVM){
$RptBody += "<font color='green' face='cambria'> *** None *** </font>"
}
else{
$RptBody += "<table border=0>"
$RptBody += "<tr>"
$RptBody += "<th><font color='midnightblue' face='cambria'><u>Machine Name</u></font></th><th/>"
$RptBody += "<th><font color='midnightblue' face='cambria'><u>Desktop Group Name</u></font></th><th/>"
$RptBody += "<th><font color='midnightblue' face='cambria'><u>Reason for Last Deregistration</u></font></th>"
$RptBody += "</tr>"
foreach($maintModeVM in (Get-BrokerDesktop -MaxRecordCount 5000 | ? {$_.InMaintenanceMode -eq 'True'})) {
$RptBody += "<tr><td>" + $maintModeVM.HostedMachineName + "</td>" + "<td/>" + "<td>" + $maintModeVM.DesktopGroupName + "</td>" + "<td/>" + "<td>" + $maintModeVM.LastDeregistrationReason + "</td></tr>"
}
$RptBody += "</table>"
}
$RptBody += "<br><br>"
#Check the availability of the Infrastructure
$RptBody += "<b><font color='purple' face='cambria'><u>STATUS OF THE INFRASTRUCTURE</u></font></b><br><br>"
$RptBody += "<table border=0>"
foreach ($server in $servers){
If (Test-Connection -ComputerName $server -Count 2 -Quiet){
$RptBody += "<tr><td>$server</td>" + "<td></td>" + "<td><font color='green' face='cambria'>UP!</font></td></tr>"
}
else{
$RptBody += "<tr><td>$server</td>" + "<td></td>" + "<td><font color='red' face='cambria'>DOWN!</font></td></tr>"
}
}
$RptBody += "</table>"
$RptBody += "<br><br><font color='silver' face='cambria'>Report generated by $DDC</font><br>"
$RptFooter += "</body></html>"
$emailBody = $RptHeader + $RptBody + $RptFooter
#=====================================================================================
#=====================================================================================
$emailBody | out-file $LogFile
send-mailmessage -from $fromEmail -to $recipients -subject "XenDesktop Health Check | $currentTime | $site" -body $emailBody -SmtpServer $SMTPserver -BodyAsHtml -Priority High
·
##----- End of the script -----
The resulting email will look like this:
You'll find a LOT (I mean it! :-D) of HTML formatting in this code. What can I say, I am an engineer who has an artistic mind. :-)
... and who likes to look at a boring black and white report anyway. ;-)
If you feel like doing some tweaking or adding some modifications you'll find Getting Started with PowerShell in XenDesktop 5 useful.
I would like to thank the customers for their feedback on the current system, the good and the bad. If not for them I might not have created this script in the first place.
P.S. If you need to copy the script please use CTRL+C. Right click is disabled. :-)
You can also download the script here.
Inspired by: http://blogs.citrix.com/2012/10/27/xendesktop-monitoring-desktop-availability/