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).
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.