[Script] Checking the Percentage of Desktops Available in Each XenDesktop Site


When you manage multiple sites you may find that Citrix Director lacks an “at-a-glance” view of the status of multiple sites. This becomes extra apparent in a large pod-based design where multiple sites may exist within the same datacenter or in an active-active datacenter setup. With VDI, it is important to check the total number of VM’s that are available for brokering. If the number is too low, you could be faced with a boot storm (assuming you have powered off virtual machines) if a large number of users log in. Or worse, you may not have available capacity. It is important to catch such incidents before they happen. Therefore, I present to you a script to output a simple HTML formatted table that can be incorporated into existing monitoring dashboards or sites (such as SharePoint).

clip_image001

Figure 1 Sample table output from script

   


    [CmdletBinding()]
    Param (
        [Parameter(Mandatory,Position=0,ValueFromPipeline)]
        [string[]]$SitesToMonitor,
        [Parameter(Mandatory,Position=1)]
        [string]$OutputPath,
        [Parameter(Position=2)]
        [int]$WarningThreshold=15,
        [Parameter(Position=3)]
        [switch]$Interactive
        )

Asnp Citrix*
Function Set-AlternatingRows {
  and replace 
  it with .  With the combination of CSS it
  can set alternating colors on table rows.
  
  CSS requirements:
  .odd { background-color:#ffffff; }
  .even { background-color:#dddddd; }
  
  Classnames can be anything and are configurable when executing the
  function.  Colors can, of course, be set to your preference.
  
  This function does not add CSS to your report, so you must provide
  the style sheet, typically part of the ConvertTo-HTML cmdlet using
  the -Head parameter.
 .PARAMETER Line
  String containing the HTML line, typically piped in through the
  pipeline.
 .PARAMETER CSSEvenClass
  Define which CSS class is your "even" row and color.
 .PARAMETER CSSOddClass
  Define which CSS class is your "odd" row and color.
 .EXAMPLE $Report | ConvertTo-HTML -Head $Header | Set-AlternateRows -CSSEvenClass even -CSSOddClass odd | Out-File HTMLReport.html
 
  $Header can be defined with a here-string as:
  $Header = @"
  
  "@
  
  This will produce a table with alternating white and grey rows.  Custom CSS
  is defined in the $Header string and included with the table thanks to the -Head
  parameter in ConvertTo-HTML.
 .NOTES
  Author:         Martin Pugh
  Twitter:        @thesurlyadm1n
  Spiceworks:     Martin9700
  Blog:           www.thesurlyadmin.com
  
  Changelog:
   1.1         Modified replace to include the  tag, as it was changing the class
                        for the TH row as well.
   1.0         Initial function release
 .LINK
  http://community.spiceworks.com/scripts/show/1745-set-alternatingrows-function-modify-your-html-table-to-have-alternating-row-colors
    .LINK
        http://thesurlyadmin.com/2013/01/21/how-to-create-html-reports/
 #>
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory,ValueFromPipeline)]
        [string]$Line,
       
        [Parameter(Mandatory)]
        [string]$CSSEvenClass,
       
        [Parameter(Mandatory)]
        [string]$CSSOddClass
    )
 Begin {
  $ClassName = $CSSEvenClass
 }
 Process {
  If ($Line.Contains("
"))
  { $Line = $Line.Replace("","")
   If ($ClassName -eq $CSSEvenClass)
   { $ClassName = $CSSOddClass
   }
   Else
   { $ClassName = $CSSEvenClass
   }
  }
  Return $Line
 }
}
Function Set-CellColor{
     
        
        ::= the same as $Property.  This must match exactly
        ::= "-eq" | "-le" | "-ge" | "-ne" | "-lt" | "-gt"| "-approx" | "-like" | "-notlike" 
             ::= "-and" | "-or"
             ::= "-not"
        
        The script first attempts to convert the cell to a number, and if it fails it will
        cast it as a string.  So 40 will be a number and you can use -lt, -gt, etc.  But 40%
        would be cast as a string so you could only use -eq, -ne, -like, etc.  
    .PARAMETER Row
        Instructs the script to change the entire row to the specified color instead of the individual cell.
    .INPUTS
        HTML with table
    .OUTPUTS
        HTML
    .EXAMPLE
        get-process | convertto-html | set-cellcolor -Propety cpu -Color red -Filter "cpu -gt 1000" | out-file c:\test\get-process.html

        Assuming Set-CellColor has been dot sourced, run Get-Process and convert to HTML.  
        Then change the CPU cell to red only if the CPU field is greater than 1000.
        
    .EXAMPLE
        get-process | convertto-html | set-cellcolor cpu red -filter "cpu -gt 1000 -and cpu -lt 2000" | out-file c:\test\get-process.html
        
        Same as Example 1, but now we will only turn a cell red if CPU is greater than 100 
        but less than 2000.
        
    .EXAMPLE
        $HTML = $Data | sort server | ConvertTo-html -head $header | Set-CellColor cookedvalue red -Filter "cookedvalue -gt 1"
        PS C:\> $HTML = $HTML | Set-CellColor Server green -Filter "server -eq 'dc2'"
        PS C:\> $HTML | Set-CellColor Path Yellow -Filter "Path -like ""*memory*""" | Out-File c:\Test\colortest.html
        
        Takes a collection of objects in $Data, sorts on the property Server and converts to HTML.  From there 
        we set the "CookedValue" property to red if it's greater then 1.  We then send the HTML through Set-CellColor
        again, this time setting the Server cell to green if it's "dc2".  One more time through Set-CellColor
        turns the Path cell to Yellow if it contains the word "memory" in it.
        
    .EXAMPLE
        $HTML = $Data | sort server | ConvertTo-html -head $header | Set-CellColor cookedvalue red -Filter "cookedvalue -gt 1" -Row
        
        Now, if the cookedvalue property is greater than 1 the function will highlight the entire row red.
        
    .NOTES
        Author:             Martin Pugh
        Twitter:            @thesurlyadm1n
        Spiceworks:         Martin9700
        Blog:               www.thesurlyadmin.com
          
        Changelog:
            1.5 Added ability to set row color with -Row switch instead of the individual cell
            1.03 Added error message in case the $Property field cannot be found in the table header
            1.02            Added some additional text to help.  Added some error trapping around $Filter
                            creation.
            1.01 Added verbose output
            1.0 Initial Release
    .LINK
        http://community.spiceworks.com/scripts/show/2450-change-cell-color-in-html-table-with-powershell-set-cellcolor
    #>

    [CmdletBinding()]
    Param (
        [Parameter(Mandatory,Position=0)]
        [string]$Property,
        [Parameter(Mandatory,Position=1)]
        [string]$Color,
        [Parameter(Mandatory,ValueFromPipeline)]
        [Object[]]$InputObject,
        [Parameter(Mandatory)]
        [string]$Filter,
        [switch]$Row
    )
    
    Begin {
        Write-Verbose "$(Get-Date): Function Set-CellColor begins"
        If ($Filter)
        {   If ($Filter.ToUpper().IndexOf($Property.ToUpper()) -ge 0)
            {   $Filter = $Filter.ToUpper().Replace($Property.ToUpper(),"`$Value")
                Try {
                    [scriptblock]$Filter = [scriptblock]::Create($Filter)
                }
                Catch {
                    Write-Warning "$(Get-Date): ""$Filter"" caused an error, stopping script!"
                    Write-Warning $Error[0]
                    Exit
                }
            }
            Else
            {   Write-Warning "Could not locate $Property in the Filter, which is required.  Filter: $Filter"
                Exit
            }
        }
    }
    
    Process {
        ForEach ($Line in $InputObject)
        {   If ($Line.IndexOf("(.*?)' -AllMatches
                $Index = 0
                ForEach ($Match in $Search.Matches)
                {   If ($Match.Groups[1].Value -eq $Property)
                    {   Break
                    }
                    $Index ++
                }
                If ($Index -eq $Search.Matches.Count)
                {   Write-Warning "$(Get-Date): Unable to locate property: $Property in table header"
                    Exit
                }
                Write-Verbose "$(Get-Date): $Property column found at index: $Index"
            }
            If ($Line -match "
(.*?)' -AllMatches
                $Value = $Search.Matches[$Index].Groups[1].Value -as [double]
                If (-not $Value)
                {   $Value = $Search.Matches[$Index].Groups[1].Value
                }
                If (Invoke-Command $Filter)
                {   If ($Row)
                    {   Write-Verbose "$(Get-Date): Criteria met!  Changing row to $Color..."
                        If ($Line -match "
")
                        {   $Line = $Line -replace "
","
")
                        }
                    }
                    Else
                    {   Write-Verbose "$(Get-Date): Criteria met!  Changing cell to $Color..."
                        $Line = $Line.Replace($Search.Matches[$Index].Value,"$Value")
                    }
                }
            }
            Write-Output $Line
        }
    }
    
    End {
        Write-Verbose "$(Get-Date): Function Set-CellColor completed"
    }
}
function AddDesktopsAvailablePercent {
[CmdletBinding()]
    Param(
        [Parameter(Mandatory,ValueFromPipeline)]
        $Input
        )
        try {  $val=$($Input.DesktopsAvailable/$Input.totalDesktops) }
        catch { $val=0 }
   
        $per=[Math]::Truncate($val*100)

    $Input | Add-Member -NotePropertyName "DesktopsAvailablePercent" -NotePropertyValue $per

}




$Header = @"

"@

$dgs=@()
foreach ($siteAddress in $SitesToMonitor)
{
 $dgs+=Get-BrokerDesktopGroup -AdminAddress $siteAddress
}


foreach($group in $dgs)
{
 $group | AddDesktopsAvailablePercent
}

$output= $dgs | select name,desktopsavailable, TotalDesktops,InMaintenanceMode,DesktopsAvailablePercent | ConvertTo-HTML -head $header -body "

Desktops Available - Warning at $($WarningThreshold)

" | ` set-cellcolor InMaintenanceMode yellow -filter "InMaintenanceMode -eq 'True'"  ` | set-cellcolor DesktopsAvailablePercent red -filter "DesktopsAvailablePercent -lt $($WarningThreshold)" ` | Set-AlternatingRows -CSSEvenClass even -CSSOddClass odd $output | out-file $OutputPath if($Interactive) { invoke-expression $OutputPath }  

Copy the script above into a text editor and save it as a .ps1 file. From there you can execute it via the command line or run it as a schedule task. For example:

.\CheckDesktopsAvailable.ps1 -SitesToMonitor “site1.contoso.local”,”site2.contoso.local” -OutputPath “C:\temp\report.html” -Interactive

If you are running the script as a scheduled task, omit the -Interactive switch to receive the file only. You can then integrate the output via another method into your monitoring platform of choice.

Leave a comment

Your email address will not be published.