Citrix Virtual Apps and Desktop HTML Dashboard with PowerShell – Delivery Group capacity

Updated 27-08-2020: percentage rebuild, CSS optimisation and some small changes to code
Updated 29-09-2020: fixed issue with user sessions which are in maintenance

The idea to make this script originates from missing a few features in Citrix Director. A few of the options/views we miss in Citrix Director are:

  1. Sum of two CVAD Sites when using site aggregation.
  2. Warning or critical warning when the amount of free VDI’s is under a certain threshold.
  3. Combined view of two CVAD sites delivery group usage.
  4. Machines in maintenance but Registered can cause an outage because machines are not available.

The script that I created is preconfigured for two CVAD Sites. See below for an example script output:


Features of the script:

  1. Automatically get all Delivery Groups.
  2. Filter out specific Delivery Groups Names and amounts of Total Desktops.
  3. Create a HTML page where a Delivery Group under 10% is colored orange and a Delivery Group under 5% is colored red.
  4. Sum of Delivery Groups in both CVAD Sites
  5. Checking which VDI’s are in maintenance and are Registered. The script will subtract this from the Available amount.

The script has a few paramaters defined which can be changed to own liking:

$ExclusionList = "DU.*|.*_"
$Threshold = 15
$title = "VDI Monitoring - Dashboard - $(get-date)"

What needs to be changed in order to run the PowerShell script:

$DDCXD1 = "CVADDDCsite1"
$DDCXD2 = "CVADDDCsite2"

$html | out-file "\\yourlocation\DeliveryGroupTotals.html"

Complete script:

#############################################################################
#
#  Name      : VDI Monitoring Dashboard
#  Created By: Silas Arentsen
#  Purpose   : Get information for all Delivery Groups and present this in a simple table
#              Warn when delivery group availability minus machines in maintenance mode reaches 10% and critical warning when 5% is reached
##############################################################################
 
Add-PSSnapin citrix*
 
#Declare the DeliveryControllers for each site, if applicable
$DDCXD1 = "CVADDDCsite1"
$DDCXD2 = "CVADDDCsite2"
 
#List of Delivery group names which are not processed in the script
$ExclusionList = "DU.*|.*_"
 
#Minimal amount of total desktops needed before the Delivery Group shows up in the HTML
$Threshold = 15
 
$Xdsite01 = Get-BrokerDesktopGroup -AdminAddress $DDCXD1 | Select Name, DesktopsAvailable, TotalDesktops | Where Name -notmatch $ExclusionList
$Xdsite02 = Get-BrokerDesktopGroup -AdminAddress $DDCXD2 | Select Name, DesktopsAvailable, TotalDesktops | Where Name -notmatch $ExclusionList
 
$Inventory = New-Object System.Collections.ArrayList
 
 
foreach ($DG in $Xdsite01) {
    $ComputerInfo = New-Object System.Object
    if ([int]$DG.TotalDesktops -gt $Threshold) {
        $MM1 = (Get-BrokerMachine -MaxRecordCount 90000 –adminaddress $DDCXD1 -DesktopGroupName $DG.Name -InMaintenanceMode $true | where {$_.RegistrationState -EQ "Registered" -and  $_.SessionCount -notlike "1"} | Select-Object DnsName | Measure-Object).count
        $ComputerInfo | Add-Member -MemberType NoteProperty -Name "Name" -Value $DG.Name.ToString()
        $ComputerInfo | Add-Member -MemberType NoteProperty -Name "DesktopsAvailable" -Value ($DG.DesktopsAvailable - $MM1)
        $ComputerInfo | Add-Member -MemberType NoteProperty -Name "TotalDesktops" -Value $DG.TotalDesktops
        $Inventory.Add($ComputerInfo) | Out-Null
    }
    Else {}
     
}
 
 
foreach ($DG in $Xdsite02) {
    $ComputerInfo2 = New-Object System.Object
    if ([int]$DG.TotalDesktops -gt $Threshold) {
        $MM3 = (Get-BrokerMachine -MaxRecordCount 90000 –adminaddress $DDCXD2 -DesktopGroupName $DG.Name -InMaintenanceMode $true | where {$_.RegistrationState -EQ "Registered" -and  $_.SessionCount -notlike "1"} | Select-Object DnsName | Measure-Object).count
        $ComputerInfo2 | Add-Member -MemberType NoteProperty -Name "Name" -Value $DG.Name.ToString()
        $ComputerInfo2 | Add-Member -MemberType NoteProperty -Name "DesktopsAvailable" -Value ($DG.DesktopsAvailable - $MM3)
        $ComputerInfo2 | Add-Member -MemberType NoteProperty -Name "TotalDesktops" -Value $DG.TotalDesktops
        $Inventory.Add($ComputerInfo2) | Out-Null
    }
    Else {}
     
}
 
#Count totals of both sites if a Delivery group is present in both
$Inventory = $Inventory | Group-Object -Property Name | Select-Object -Property @{Name='ProcentAvailable'; Expression='Procent'}, @{Name='Name'; Expression='Name'}, @{Name='DesktopsAvailable'; Expression={($_.Group| Measure-Object -Sum -Property DesktopsAvailable).Sum}}, @{Name='TotalDesktops'; Expression={($_.Group| Measure-Object -Sum -Property TotalDesktops).Sum}}
 
 
$Header = "
table
{
Margin: 0px 0px 0px 4px;
Border: 1px solid rgb(190, 190, 190);
Font-Family: Tahoma;
Font-Size: 24pt;
Background-Color: rgb(252, 252, 252);
}
 
th
{
Text-Align: Left;
Color: rgb(150, 150, 220);
Padding: 1px 4px 1px 4px;
}
 
td
{
Vertical-Align: Top;
Padding: 1px 4px 1px 4px;
}
 
tr.under-5 td 
{
background-color: red;
color: white;
}
tr.under-10 td 
{
background-color: orange;
color: white;
}
h3
{
margin-top: -25;
margin-bottom: 0;
}
tr:nth-child(even) {
    background-color: #efefef;
}
"
 
 
$Inventory  = $Inventory | Sort-Object TotalDesktops -Descending
 


$title = "VDI Monitoring - Dashboard - $(get-date)"
$refresh = '<meta http-equiv="refresh" content="60; URL=http://YourLocation/DeliveryGroupTotals.html">'

$html = "<html>
    <head>
        <title>$title</title>
        $refresh
        <style>`n`
            $Header`n`
        </style>
    </head>
    <body>"

$html += "`n`t`t<H3><br><i>Run on: $(get-date)</i></H3>"
$html += "`n`t`t<table>`
        `n`t`t`t<tr>`
            `n`t`t`t`t<th>ProcentAvailable</th>`
            `n`t`t`t`t<th>Name</th>`
            `n`t`t`t`t<th>DesktopsAvailable</th>`
            `n`t`t`t`t<th>TotalDesktops</th>`
        `n`t`t`t</tr>"
foreach ($item in $Inventory) {
    

    foreach($percentage in $item.Name) {
        $name = $item.Name
        $ProcentAvailable = [math]::round(($item.DesktopsAvailable / $item.TotalDesktops) * 100)
        $DesktopsAvailable = $item.DesktopsAvailable
        $TotalDesktops = $item.TotalDesktops

        if($ProcentAvailable -le 5) {
            $rowclass = "under-5"
            
        }
        elseif($ProcentAvailable -le 10) {
            $rowclass = "under-10"
        } 
        else {
            $rowclass = ""
        }

        $html += "`n`t`t`t<tr class=`"$rowclass`">`
            `n`t`t`t`t<td>$ProcentAvailable</td>`
            `n`t`t`t`t<td>$name</td>`
            `n`t`t`t`t<td>$DesktopsAvailable</td>`
            `n`t`t`t`t<td>$TotalDesktops</td>`
        `n`t`t`t</tr>"
    }
    
}
$html += "`n`t`t</table>"
$html += "`n`t</body>`n</html>"
 
$html | out-file "\\YourLocation\DeliveryGroupTotals.html"
1 reply
  1. Tom Kasmir
    Tom Kasmir says:

    Fantastic script. I discovered the Get-BrokerDesktopGroup command just yesterday and could not get it to do what I wanted. Could not pipe to it, could not get it work with a ForEach. I have a journeyman’s skillset at best with POSH, so this is a great teaching tool and a super useful script example for some VDI dashboards I’m creating. The beauty here is how you combined Get-BrokerDesktopGroup with Get-BrokerMachine.

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

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