image_pdfimage_print

PRTG – Terminalserver Auslastung (Load Index) überwachen

Die Last eines Terminalservers wird in der Welt von Citrix Virtual Apps and Desktops mittels des Load Indexes angegeben. Dieser Wert geht von 0 (0% – keine Last) bis 10’000 (100% – Volllast). Volllast bedeutet ja noch nicht zwingend, dass ein Server keine Luft mehr hat, dennoch kann sich kein neuer Benutzer mehr anmelden.

Da wir die Berechnungskriterien für den Load Index selbst definieren können (z.B. CPU, RAM, Anzahl Benutzer), können wir uns im Monitoring nicht auf einen uns bekannten Wert wie z.B. die Prozessorlast verlassen.

Ich hatte daher die Idee einen Sensor zu erstellen, welcher für jede Bereitstellungsgruppe die durchschnittliche Last anhand des Load Indexes berechnet uns ausgibt.

Der Sensor selbst wird im PRTG innerhalb des Citrix Controllers erstellt und nicht pro Worker.

Im ersten Schritt werden alle Bereitstellungsgruppen vom Controller ausgelesen und in einem Array gespeichert. Es wird hier bereits geprüft, ob eine Bereitstellungsgruppe ggf. im Wartungsmodus ist.

###
# Prepare an array of all delivery groups from a Citrix controller by an Invoke-Command
# Citrix PS commands are only available on those servers
$Data = $null
$Data=@()

$Data += Invoke-Command -Computername $server -credential $credentials -ScriptBlock {

    # Load Citrix PS Snapin
    add-pssnapin citrix*

    # Get delivery groups with the needed information
    $DeliveryGroups=Get-BrokerDesktopGroup | Select-Object Name, InMaintenanceMode

    # Set the array for later work
    $DG=@()
    ForEach ($group in $DeliveryGroups){
       $DG += [PSCustomObject]@{Name=$group.Name;InMaintenance=$group.InMaintenanceMode} 
    }

    # Return data to PRTG probe
    return $DG
}

Im weiteren Schritt wird jede einzelne Bereitstellungsgruppe (DG) abgearbeitet. Ist eine DG im Wartungsmodus, dann wird ein pseudo Load Index von 99/9% zurück gegeben, damit im Monitoring kein Alarm ausgelöst wird.

Jede weitere DG wird nun erneut beim Controller abgefragt. Nun werden jedoch sämtliche Worker mit ihrem aktuellen Load Index Wert in einen Array gespeichert. Danach wird die Summe aller Lastwerte errechnet und durch die Anzahl Worker geteilt (einfache Mathematik ^^) und zu guter Letzt der Prozentwert auf eine Zahl ohne Komma gerundet, da PRTG keine Kommawerte in einem Prozentfeld ausgeben kann.

Diese Daten werden in einen weiteren Array geschrieben, welcher im Anschluss benutzt wird um die PRTG Ausgabe zu erstellen:

###
# Prepare an array of the load of all delivery groups from a Citrix controller by an Invoke-Command
# Citrix PS commands are only available on those servers
$Load = $null
$Load=@()

ForEach ($RDSHGrp in $Data) {

    $RDSHArg = $null
    $RDSHArg = $RDSHGrp.Name

    # Determine if a delivery group is in maintenance
    # DGs in maintenance goes into warning state, but doesn't affect the whole sensor
    # DGs in maintenance will not be stated based on her usage
    # DGs in maintenance will have fake values of 9% and 99 to avoid an alarm
    If ($RDSHGrp.InMaintenance) {
        $RDSHWorkers=99
        $RDSHTotalLoad=99
        $RDSHAvgLoad=99
        $RDSHAvgPercent=9
    }
    Else {
        $RDSHLoad = $null
        $RDSHLoad = @()


        $RDSHScriptBlock =
            {
                 # Load Citrix PS Snapin
                add-pssnapin citrix*

                # Get delivery groups with the needed information
                $RDSHWorker=Get-BrokerMachine | Where-Object DesktopGroupName -eq $args[0] | Select-Object DNSName, LoadIndex

                # Set the array for later work
                $RDSH=@()
                ForEach ($Worker in $RDSHWorker){
                   $RDSH += [PSCustomObject]@{Name=$Worker.DNSName;Load=$Worker.LoadIndex} 
                }

                # Return data to PRTG probe
                return $RDSH
             }

        # Get the load index of all workers in the delivery group
        $RDSHLoad += Invoke-Command -Computername $server -credential $credentials -ScriptBlock $RDSHScriptBlock -ArgumentList $RDSHArg

        # Count the workers
        $RDSHWorkers = $RDSHLoad.count
        $RDSHTotalLoad = 0
        # Calculate the sum of all load indexes
        $RDSHLoad.Load | ForEach{$RDSHTotalLoad += $_}
        # Calculate the average load index for the delivery group
        $RDSHAvgLoad = "{0:F0}" -f ($RDSHTotalLoad/$RDSHWorkers)
        # Calculate the average percent value of the load index for the delivery group
        $RDSHAvgPercent = "{0:F0}" -f ($RDSHAvgLoad/100)

    }
    $Load += [PSCustomObject]@{Name=$RDSHArg;Worker=$RDSHWorkers;TotalLoad=$RDSHTotalLoad;AvgLoad=$RDSHAvgLoad;AvgPercent=$RDSHAvgPercent}
}

Die PRTG Ausgabe selbst ist durch die vorherigen Berechnungen keine Raketenwissenschaft mehr:

###
# Prepare the data and the PRTG XML output

# Reset some variables and define standard values
$returnState=$null
$returnState=@()
$returnStateOK = 0
$returnStateWarning = 1
$returnStateCritical = 2
$AlertLevel=90
$AlertString = "ALERT - high load index"
$WarningLevel=80
$WarningString = "Warning - load index reaches a high level"

# Start preparing XML output
$retXml = "<prtg>`n"

# Get data for each delivery group from the array created on the Citrix Controller
ForEach ($Dataset in $Load){
    # Prepare variables based on the array data
    $DGName = $Dataset.Name
    $DGTotal = $Dataset.Worker
    $DGLoad = $Dataset.AvgLoad
    # Calculate the percentage of the RDSH delivery groups
    $DGLoadPercent = $Dataset.AvgPercent
    $DGMaintenance = $Dataset.Maintenance

    # Determine return state if delivery group is not in maintenance
    # The values depend on the size of the delivery group
    If ([Int64]$DGLoadPercent -gt $AlertLevel){
        $RetState = $returnStateCritical
        $returnState += [PSCustomObject]@{Name=$DGName;State=[Int64]$RetState} 
    }
    ElseIf ([Int64]$DGLoadPercent -le $WarningLevel) {
        $RetState = $returnStateOK
        $returnState += [PSCustomObject]@{Name=$DGName;State=[Int64]$RetState} 
    }
    Else {
        $RetState = $returnStateWarning
        $returnState += [PSCustomObject]@{Name=$DGName;State=[Int64]$RetState} 
    }


    #$retXml += "  <result>`n"
    #$retXml += "    <channel>$DGName State</channel>`n"
    #$retXml += "    <value>$RetState</value>`n"
    #$retXml += "  </result>`n"
    $retXml += "  <result>`n"
    $retXml += "    <channel>$DGName Load %</channel>`n"
    $retXml += "    <value>$DGLoadPercent</value>`n"
    $retXml += "    <unit>Percent</unit>`n"
    $retXml += "    <limitMode>1</limitMode>`n"
    $retXml += "    <limitMaxError>$AlertLevel</limitMaxError>`n"
    $retXml += "    <limitErrorMsg>$AlertString</limitErrorMsg>`n"
    $retXml += "    <limitMaxWarning>$WarningLevel</limitMaxWarning>`n"
    $retXml += "    <limitWarningMsg>$WarningString</limitWarningMsg>`n"
    $retXml += "  </result>`n"
    $retXml += "  <result>`n"
    $retXml += "    <channel>$DGName Load Index</channel>`n"
    $retXml += "    <value>$DGLoad</value>`n"
    $retXml += "    <unit>Count</unit>`n"
    $retXml += "  </result>`n"
}

# Determine return string depends on the several states
If ($returnState.State -contains 2) {
    $RetString = $AlertString    
}
ElseIf ($returnState.State -contains 1) {
    $RetString = $WarningString    
}
Else {
    $RetString = "OK"    
}

$retXml += "  <text>$RetString</text>`n"
$retXml += "</prtg>`n"

###
# Return info to PRTG
write-host $retXml

Das Ergebnis sieht dann wie folgt aus:

Viel Spass beim Nachbauen. :-)

Neustart nicht registrierter VDAs

Beim Start eines Workers werden bei uns mittels Startup Script noch div. Tasks abgearbeitet. Um eine Anmeldung zu verhindern, stoppt dieses Script als erstes den Citrix Desktop Dienst. Leider haben wir ab und an das Phänomen bei den Terminalservern, dass genau dieser Dienst zum Schluss entweder nicht gestartet wird oder die Registration nicht klappt.

Bisher gingen wir dann den einfach weg eines Neustarts (war sowieso kein Benutzer angemeldet). Dies habe ich nun mit einem einfachen Skript automatisiert:

# Load Citrix Cmdlets
asnp Citrix*

# Check for stopped VDAs not in maintenance mode
$UnregisteredVDAs = get-brokermachine -Filter {(InMaintenanceMode -eq $False) -and (RegistrationState -eq "Unregistered")}
$UnregisteredVDAs | FT DNSName, InMaintenanceMode, RegistrationState -AutoSize

ForEach($VM in $UnregisteredVDAs) {
    New-BrokerHostingPowerAction -Action Restart -MachineName $VM.HostedMachineName
}

Das Skript prüft nach Workern, welche nicht im Wartungsmodus und trotzdem unregistriert sind. Der geplante Task wird dann mit einem Serviceuser ausgeführt, welcher auch die entsprechenden Rechte innerhalb der VAD Umgebung besitzt.

Das Skript löst zwar noch nicht die Ursache der fehlerhaften Registrierung, aber es automatisiert den händischen Aufwand.

Viel Spass beim Nachbauen. :-)

XenDesktop 7.12 – und der Local Host Cache ist zurück

Hallo zusammen

Heute (07.12.16) ist die neue Version von XenApp/XenDesktop erschienen. Nebst vielen Neuerungen welche ihr hier nachlesen könnt, kam der Local Host Cache (LHC) zurück.

Mit diesem ist es nun wieder wie vor der Ära von Version 7.x möglich, dass der Betrieb einer XA/XD Umgebung weiterläuft, auch wenn die Verbindung zum SQL Server fehlschlägt. Im Gegensatz zum alten LHC, welcher von jedem XenApp Server lokal verwaltet (Access DB) und direkt angesteuert wurde, läuft der neue LHC in einer kleinen SQL Instanz (Local DB) und bei einem Ausfall des SQL Servers wird eine Instanz bestimmt, auf welche sich alle Controller verbinden. Da die verschiedenen LHC von den jeweiligen CCS parallel zum eigentlichen Betrieb aktuell gehalten werden, soll diese neue Variante auch einiges stabiler sein als der alte LHC.

Die Local DB ist bei einer Neuinstallation von XA/XD 7.12 standardmässig aktiv.

Bei einem Upgrade einer älteren Installation wo das Connection Leasing aktiv war, muss dieses noch deaktiviert und der LHC aktiviert werden:

Mehr und detailliertere Informationen findet ihr in den Docs.

Viel Spass beim Erfahrungen sammeln :-)

Workspace Control – nur getrennte Sitzungen übernehmen

Hallo zusammen

Wer mit Citrix Webinterface gross geworden ist kennt noch die verschiedenen Einstellungen zur Workspace Control.
Als Storefront herausgekommen ist, musste man dieses Feature in der web.config suchen. Mittlerweile ist es im GUI verfügbar aber leider noch nicht so wie wir es uns wünschen würden.

XD-SF-WorkspaceControl

Bei genauerem Hinsehen stellt man fest, dass man nicht zwischen aktiven und getrennten Sitzungen unterscheiden kann.

Wie kann man dies nun lösen?

Read more

XML Services & Citrix Director together behind a NetScaler

Hey NetScaler Fans

I’ve following scenario in my environment:
– two XenDesktop Controller on which is also Director installed
– one Loadbalancing (LB) vServer on a NetScaler, which connects to both server

The goal was:
– use the SSL LB vServer for XML-Requests between Storefront and Controller with the Hostname = xmlxd7.domain.pit
– us the same SSL LB vServer for the access to the Director Site with the Hostname = director.domain.pit
… sounds easy, but
– while accessing the hostname director.domain.pit, the NetScaler should redirect to the URL /Director, but UNDER NO CIRCUMSTANCES if the LB vServer receives a XML Request

Read more

ICA Resolution-Issues with changed DPI settings

Hi Friends of Citrix

I had an interesting supportcase.

The user changed the DPI settings on his client (in this case to 150%)

 

CR-ChangeDPI-2

After the user starts an ICA session, this will be scaled with the DPI settings and cannot be changed:

CR-ChangeDPI-1 CR-ChangeDPI-3

Following settings on the processes wfcrun32.exe and wfica32.exe helps.

CR-ChangeDPI-4

If this workaround helps for ever or only temporary, I don’t know. I received this information graciously from our partner which has called us in this case, but he found the “solution” by himself.

 

Citrix Director without SSL Check

Hi together

Everyone who has worked with Citrix Director is stumbled over this message:

Director-SSLCheckMessage

The shortcut inserted by the installation is linked to a HTTP URL and not HTTPS. This is the reason for this security message. If this is annoying to you, you can disable this within IIS.

Open the Director Site within your IIS Manager and open the Application Settings:

Director-IIS-ApplicationSettings

After you change the parameter UI.EnableSSLCheck to False, the message is vanished.

Director-IIS-ApplicationSettings-UIEnableSslCheckFalse

Director-noSSLCheckMessage

More information: http://support.citrix.com/article/CTX135749
(description below)

—–

since Director 7.x

Director without Applications

Hi together

Director is in my opinion a real useful tool for the helpdesk. On little problem can be the tab “Applications” in the users details. The helpdesk sees the complete title bar of an open application and be honest, some things (filenames, titles of homepages, and so on) are not for the helpdesk’ eyes:

Director-with-Apps-DE

To avoid this you can disable the sending of this data with Registry modifications at the VDA site or you can deactivate this tab within the Director frontend.

To do the second option you’ve to open the Director site within the IIS Manager and open the Application Settings:

Director-IIS-ApplicationSettings

If you change the parameter UI.TaskManager.EnableApplications to False, the applications will be hidden but the tap with the Processes is shown furthermore and the helpdesk employee with the correct rights can kill a faulty process.

Director-IIS-ApplicationSettings-UIEnableAppsFalse

Director-without-Apps

—–

ab Director 7.x