PRTG – Verfügbare VDIs überwachen

Im letzten Artikel habe ich beschrieben, wir mittels PRTG der Load Index der Terminalserver überwacht werden kann.

Wenn wir uns die VDIs (single user OS), dann interessiert uns da normalerweise die Auslastung weniger. Dafür wollen wir wissen, wie viele VDIs überhaupt noch zur Verfügung stehen im Kontext von „random non-static“.

Im Vergleich zu den Terminalservern ist hier die Erstellung eines Custom Sensors sogar einfacher, da uns der Citrix Controller mit allen notwendigen Informationen versorgt:

###
# Prepare an array and get the information 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 -Property Name, TotalDesktops, DesktopsAvailable, InMaintenanceMode

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

    # Return data to PRTG probe
    return $DG
}

Diese Informationen können wir in einer weiteren Schlaufe dann auch gleich für die PRTG Ausgabe benutzen. Das komplette Skript steht zum Download bereit, daher beschreibe ich hier nur nochmals ein paar Eckpunkte.

Aus den Daten können die noch verfügbaren VDIs in Prozent umgerechnet und erneut für PRTG auf die nächste Ganzzahl gerundet werden:

    # Prepare variables based on the array data
    $DGName = $Dataset.Name
    $DGTotal = $Dataset.Total
    $DGAvailable = $Dataset.Available
    # Calculate the percentage of the available VDIs
    $DGPercent = "{0:N0}" -f (100/$DGTotal*$DGAvailable)
    $DGMaintenance = $Dataset.Maintenance

Kommt im Namen der Bereitstellungsgruppe „test“ vor, so wollen wir im PRTG nie einen Alarm sondern höchstens eine Warnung auslösen:

    # Determine if a delivery group is a test group
    # Test DGs will never go into alarm state
    # Test DGs in maintenance will have a percentage value of 100 to avoid an alarm
    If ($DGName -like "*test*"){
        $AlertString = $null
        $AlertLimit = $null
        $WarningString = "Warning - Test VDI capacity reachs the end"
        If ([Int64]$DGPercent -ge 20) {
            $RetState = $returnStateOK
            $returnState += [PSCustomObject]@{Name=$DGName;State=[Int64]$RetState} 
        }
        ElseIf ($DGMaintenance){
            $RetState=$returnStateWarning
            $DGPercent=100
        }
        Else {
            $RetState = $returnStateWarning
            $returnState += [PSCustomObject]@{Name=$DGName;State=[Int64]$RetState} 
        }
    }

Ist eine Bereitstellungsgruppe im Wartungsmodus, so geben wir eine Verfügbarkeit von 100% an PRTG aus, um einen Alarm oder eine Warnung komplett zu vermeiden:

    # 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 a percentage value of 100 to avoid an alarm
    ElseIf ($DGMaintenance){
        $RetState=$returnStateWarning
        $DGPercent=100
    }

Die restlichen Bereitstellungsgruppen werden anhand der Prozentwerte eingestuft und entsprechende PRTG Ausgaben aufbereitet.

Die Ausgabe sieht dann folgendermassen aus, wobei die ausgegrauten Channels ehemalige bereits gelöschte Bereitstellungsgruppen sind:

Viel Spass beim Nachbauen :-)




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




PRTG – ADC zentralisiert via ADM überwachen (Zusammenfassung)

In den letzten Tagen habe ich ein paar einzelne Beiträge verfasst, wie man Citrix ADC/NetScaler mittels Citrix ADM im PRTG überwachen kann. In diesem Artikel möchte ich noch einmal kurz darauf eingehen, warum überhaupt und ich möchte euch auch alle Beiträge gesammelt auflisten.

Bevor wir ADM im Einsatz hatten, waren unsere ADCs alle einzeln vom PRTG überwacht. Voraussetzungen dazu waren dann

  • funktionierende Sensoren für die ADCs
  • PRTG Logins auf jeder einzelnen Appliance
  • PRTG Netzwerkzugriff auf jede einzelne Appliance
  • Pflege aller ADC Geräte und inklusiv aller Sensoren im PRTG

Gerade in Umgebungen mit limitiert lizenzierten PRTG Sensoren ist der letzte Punkt auch ein Kostenfaktor. Für mich waren vor allem zwei Punkte entscheidend um das Konstrukt umzubauen:

  • die eingesetzten Sensoren gaben öfter auch einmal „false positive“ Alarme aus
  • im eingesetzten vServer Statussensor konnte nicht ein einzelner vServer bestätigt werden, falls dieser einmal DOWN war – somit konnte ein ‚DOWN‘ vServer einer Testapplikation das komplette Monitoring ausser Kraft setzen

Warum also nicht ADM nutzen wenn schon alle ADCs darüber verwaltet werden? Dies hat für mich folgende positive Effekte:

  • nur ADM benötigt Netzwerkzugriff auf jede einzelne Appliance
  • es wird nur auf dem ADM ein PRTG Login benötigt
  • es müssen nur die Sensoren für den ADM gepflegt (und lizenziert) werden
  • ein einzelner vServer der DOWN ist, kann im ADM bestätigt werden und die PRTG Überwachung läuft wie gewohnt weiter
  • und wer Lust und Laune hat, kann weitere Sensoren skripten falls gewünscht

Um dies nachzubauen, könnte ihr gem. folgenden Artikeln vorgehen:

Zu guter Letzt fragt ihr euch vielleicht, was der Spass kostet? Also Zahlen nenne ich hier nicht, aber Stand heute müsst ihr das PRTG entsprechend eurer Umgebungsanforderung lizenzieren (evtl. reichen ja die 100 Gratissensoren). Die ADCs habt ihr gem. euren Bedürfnissen gekauft oder als Freemium im Einsatz. Und ADM könnt ihr für die genannten Funktionen ebenfalls ohne zusätzliche Lizenz nutzen. Das einzige was es garantiert benötigt, sind die Hardwareressourcen gemäss Spezifikationen und eure Zeit.

Viel Spass und Erfolg beim Nachbauen. :-)




PRTG – Citrix ADM Nutzen um ungespeicherte ADC Konfigurationen zu überwachen

Im einem der letzten Beiträge habe ich ein Powershell Modul vorgestellt, mit welchem man Daten vom Citrix ADM abgreifen kann.

Basierend auf diesem Modul habe ich bei uns einen PRTG Custom Sensor erstellt, welcher ungespeicherte Konfigurationen aus dem ADM ausliest:

Dazu müssen erst einmal die Parameter von PRTG sowie das Modul selbst eingelesen und eine Verbindung zur Appliance hergestellt werden:

# Get parameter from PRTG
param (
[string]$server,
[string]$domain,
[string]$username,
[string]$password
)

# Import ADM PS module
$CustomSensors="C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\"
Import-Module $CustomSensors\PRTGCustomCitrixADM.psm1

# Create the ADM session
$ADMHost = "https://"+$server
$ADMSession = Connect-ADM -ADMHost $ADMHost -CredUser $username -CredPW $password

Damit dies funktioniert, muss der entsprechende Benutzer von PRTG auf dem ADM Leserechte haben. Weiter gehe ich nicht auf jede Zeile ein, dies kann im Script selbst nachgelesen werden. Hier beschreibe ich vor allem die wichtigsten Punkte, wie das auslesen der Konfigurationsdaten aus dem ADM:

# Get the config status from the ADM
$DiffEvents = Invoke-ADMNitro -ADMSession $ADMSession -OperationMethod GET -ResourceType ns_conf
# Create the variable only with the active events content
$DiffEvents2 = $DiffEvents | Select-Object ns_conf

Nun werden die Daten noch auf den String „Diff Exists“ geprüft und für die weitere Auswertung aufbereitet. In diesem Sensor gibt es nur einen guten oder schlechten Rückgabewert, weshalb der Block sehr kurz gehalten ist:

$Events = @()
ForEach ($Event in $DiffEvents2.ns_conf){

    If ($Event.diff_status -eq "Diff Exists"){
        # Filter out 'entityup' messages from critical state
        $RetState = $returnStateCritical
        $Events += [PSCustomObject]@{Severity=$Event.hostname;SourceIP=$Event.ns_ip_address;SourceHost=$Event.hostname;State=[Int64]$RetState}
        $RetCritical = $RetCritical + 1
    }
}

Im restlichen Skript wurden die einzelnen Daten mit einem vorgegebenen Wert gegen geprüft und die entsprechenden PRTG Ausgaben definiert.

Das Script muss nun in den Custom Sensors Ordner von PRTG gelegt werden und der Sensor kann entsprechend eingerichtet werden:

Parameter gem. Script-Beschreibung, Securitykontext vom Gerät
Der Intervall wird ein wenig höher gestellt, damit bei aktiven Änderungen das Monitoring nicht sofort Alarm schlägt.

Das Resultat sieht dann wie folgt aus:

Viel Spass beim Nachbauen :-)




PRTG – Citrix ADM für zentrales ADC Performance Monitoring nutzen

Im einem der letzten Beiträge habe ich ein Powershell Modul vorgestellt, mit welchem man Daten vom Citrix ADM abgreifen kann.

Basierend auf diesem Modul habe ich bei uns einen PRTG Custom Sensor erstellt, welcher die wichtigsten Performance Daten aus dem ADM ausliest:

Dazu müssen erst einmal die Parameter von PRTG sowie das Modul selbst eingelesen und eine Verbindung zur Appliance hergestellt werden:

# Get parameter from PRTG
param (
[string]$server,
[string]$domain,
[string]$username,
[string]$password
)

# Import ADM PS module
$CustomSensors="C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\"
Import-Module $CustomSensors\PRTGCustomCitrixADM.psm1

# Create the ADM session
$ADMHost = "https://"+$server
$ADMSession = Connect-ADM -ADMHost $ADMHost -CredUser $username -CredPW $password

Damit dies funktioniert, muss der entsprechende Benutzer von PRTG auf dem ADM Leserechte haben. Weiter gehe ich nicht auf jede Zeile ein, dies kann im Script selbst nachgelesen werden. Hier beschreibe ich vor allem die wichtigsten Punkte, wie das auslesen der Performance-Daten sowie das Sortieren nach Appliance:

# Get the Instances from the ADM
$ADCInstance = Invoke-ADMNitro -ADMSession $ADMSession -OperationMethod GET -ResourceType ns
# Create the variable only with the NS parameters
$ADCInstance2 = $ADCInstance | Select-Object ns
# For troubleshooting
#$ADCInstance2.ns | FT hostname, ns_mgmt_cpu_usage, ns_cpu_usage, vm_memory_usage, diskperusage, disk0_used, disk1_used, ns_tx, model_id -AutoSize
$ADCInstances = $ADCInstance2.ns
# Sort output based on hostname
$ADCInstances2 = $ADCInstances | Sort-Object hostname

Da das Web GUI von PRTG nicht nach Channel ID sondern nach Alphabet sortiert, habe ich für die Channel-Namen jeweils noch einen eigenen Index erstellt. A0 ist reserviert für den „Overall Health“ Status (weiter unten beschrieben). Anschliessend kriegt jede Appliance einen eigenen Buchstaben und innerhalb einer Appliance wird hochgezählt:

$ChannelLetterIndex = 65    # Start index with 65 for ASCII 'A'
ForEach ($Instance in $ADCInstances2){

    #region returnvariables
    $ChannelLetterIndex = $ChannelLetterIndex + 1      # Increase letter index by one for each appliance instance
    $RetChannelLetter = [char]($ChannelLetterIndex)

Im PRTG werden Prozentwerte nur in ganzen Zahlen angezeigt, daher werden die entsprechenden Werte gerundet:

    $RetMgmtCPU = [math]::Round($Instance.ns_mgmt_cpu_usage)
    $RetCPU = [math]::Round($Instance.ns_cpu_usage)
    $RetRAM = [math]::Round($Instance.vm_memory_usage)

Die prozentuale Bandbreiten-Auslastung wird anhand der Werte sowie der Model ID berechnet. Da diese im Test oft exponentielle Werte lieferte und diese nicht gerundet werden können, musste dies via Umwandlung in einen String gemacht werden:

    #region bwcalculation
    # Calculate the percentage of the bandwidth usage
    # based on the license and the current bandwith
    # A conversation to string is needed because of the
    # exponential results which needed to be trimmed
    $BWPercentCalc = $null
    $BWPercent = $null

    $BWPercentCalc = $Instance.ns_tx*100/$Instance.model_id
    $BWPercentString = [String]$BWPercentCalc
    If ($BWPercentString.Length -ge 5){
        $SubLength = 5
    }
    Else {
        $SubLength = $BWPercentString.Length
    }
    $BWPercentStringShort = $BWPercentString.Substring(0,$SubLength)
    $BWPercentShort = [Decimal]$BWPercentStringShort
    $RetBWPercent = [math]::Round($BWPercentShort)
    #endregion bwcalculation

Im restlichen Skript wurden die einzelnen Daten mit einem vorgegebenen Wert gegen geprüft und die entsprechenden PRTG Ausgaben definiert.

Zu guter Letzt wird aus allen vorher berechneten Werten ein Channel mit einer Gesamtbewertung der Performance erstellt, welche mit dem hardcoded Index A0 auch ganz oben gelistet wird:

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

#region health
# Channel for overall health
$retXml += "  <result>`n"
$retXml += "    <channel>A0 Overall health</channel>`n"
$retXml += "    <value>$RetHealth</value>`n"
$retXml += "    <unit>Count</unit>`n"
$retXml += "    <limitMode>1</limitMode>`n"
$retXml += "    <limitMinError>49</limitMinError>`n"
$retXml += "    <limitErrorMsg>$AlertString</limitErrorMsg>`n"
$retXml += "    <limitMinWarning>99</limitMinWarning>`n"
$retXml += "    <limitWarningMsg>$WarningString</limitWarningMsg>`n"
$retXml += "  </result>`n"
#endregion health

Das Script muss nun in den Custom Sensors Ordner von PRTG gelegt werden und der Sensor kann entsprechend eingerichtet werden:

Parameter gem. Script-Beschreibung, Securitykontext vom Gerät

Das Resultat sieht dann wie folgt aus:

Viel Spass beim Nachbauen :-)




PRTG – ADM Events überwachen

Im einem der letzten Beiträge habe ich ein Powershell Modul vorgestellt, mit welchem man Daten vom Citrix ADM abgreifen kann.

Basierend auf diesem Modul habe ich bei uns einen PRTG Custom Sensor erstellt, welcher die Events aus dem ADM ausliest:

Dazu müssen erst einmal die Parameter von PRTG sowie das Modul selbst eingelesen und eine Verbindung zur Appliance hergestellt werden:

# Get parameter from PRTG
param (
[string]$server,
[string]$domain,
[string]$username,
[string]$password
)

# Import ADM PS module
$CustomSensors="C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\"
Import-Module $CustomSensors\PRTGCustomCitrixADM.psm1

# Create the ADM session
$ADMHost = "https://"+$server
$ADMSession = Connect-ADM -ADMHost $ADMHost -CredUser $username -CredPW $password

Damit dies funktioniert, muss der entsprechende Benutzer von PRTG auf dem ADM Leserechte haben. Weiter gehe ich nicht auf jede Zeile ein, dies kann im Script selbst nachgelesen werden. Hier beschreibe ich vor allem die wichtigsten Punkte, wie das auslesen der Events:

# Get the events from the ADM
$ActiveEvents = Invoke-ADMNitro -ADMSession $ADMSession -OperationMethod GET -ResourceType active_event
# Create the variable only with the active events content
$ActiveEvents2 = $ActiveEvents | Select-Object active_event

Es sollen im PRTG nicht alle ADM Meldungen gleich einen Alarm auslösen, daher habe ich div. Arrays für Ausschlüsse vorbereitet, welche bei Bedarf genutzt werden können:

# Prepare a device_entity_name exlusion list for PRTG outputs
# Add each device in quota with a comma (except the last line)
$DeviceExcludeList = $null
$DeviceExcludeList = @(
    "entity1",
    "entity.domain.pit"
)

# Prepare a failureobj exlusion list for PRTG outputs
# Add each failure object in quota with a comma (except the last line)
$FailureObjectExcludeList = $null
$FailureObjectExcludeList = @(
    "object1",
    "object2"
)

# Prepare a message exlusion list for PRTG outputs
# Add each message in quota with a comma (except the last line)
$MessageExcludeList = $null
$MessageExcludeList = @(
    "192.168.99.99"
)

Da auch vServer und Services vom ADC welche wieder hochkommen einen „Critical Event“ darstellen, habe ich diese beim Aufbereiten ausgeklammert:

    If ($Event.severity -eq "Critical"){
        # Filter out 'entityup' messages from critical state
        If ($Event.category -ne "entityup"){
            $RetState = $returnStateCritical
            $Events += [PSCustomObject]@{Severity=$Event.severity;SourceIP=$Event.source;SourceHost=$Event.hostname;Category=$Event.category;Entity=$Event.device_entity_name;State=[Int64]$RetState}
            $RetCritical = $RetCritical + 1
        }
    }

Innerhalb der „Major Events“ werden im ersten Schritt die vorher definierten Ausschlüsse gegengeprüft und mittels Variable $DeviceAlarm die weitere Verarbeitung bestätigt oder gestoppt:

        # Filter out known entities, failure objects etc. from major state
        # Set variable $DeviceAlarm, if the device isn't filtered
        
        $DeviceAlarm = $null
        
        ForEach ($ExcludedDevice in $DeviceExcludeList) {
            $Entity = $Event.device_entity_name
            If ($DeviceAlarm -or ($DeviceAlarm -eq $null)) {
                If ($Entity -notlike "*$ExcludedDevice*") {
                    $DeviceAlarm = $true
                }
                Else{
                    $DeviceAlarm = $false
                }
            }
        }
        
        If ($DeviceAlarm){
            ForEach ($ExcludedFO in $FailureObjectExcludeList) {
                $Entity = $Event.failureobj
                If ($DeviceAlarm -or ($DeviceAlarm -eq $null)) {
                    If ($Entity -notlike "*$ExcludedFO*") {
                        $DeviceAlarm = $true
                    }
                    Else{
                        $DeviceAlarm = $false
                    }
                }
            }
        }
        
        If ($DeviceAlarm){
            ForEach ($ExcludedMessage in $MessageExcludeList) {
                $Entity = $Event.message
                If ($DeviceAlarm -or ($DeviceAlarm -eq $null)) {
                    If ($Entity -notlike "*$ExcludedMessage*") {
                        $DeviceAlarm = $true
                    }
                    Else{
                        $DeviceAlarm = $false
                    }
                }
            }
        }

Falls ein „Major Event“ nicht durch einen Ausschluss gefiltert wurde, wird die Eventliste entsprechend aufbereitet. In diesem Schritt werden Meldungen von Services („svc“ im Namen) oder Service Groups („svg“ im Namen) zu einer Warnung herunter gestuft. Dies weil definiert wurde, dass im PRTG erst ein Alarm erscheint, wenn der komplette vServer und nicht ’nur‘ ein Service DOWN ist:

        # If device isn't excluded, add to monitoring array
        # Services (svc) or service groups (svg) returns a warning instead an alarm
        If ($DeviceAlarm){
            If (($Event.device_entity_name -like "*svc*") -or ($Event.device_entity_name -like "*svg*")) {
                $RetState = $returnStateWarning
                $Events += [PSCustomObject]@{Severity=$Event.severity;SourceIP=$Event.source;SourceHost=$Event.hostname;Category=$Event.category;Entity=$Event.device_entity_name;State=[Int64]$RetState}
                $RetWarning = $RetWarning + 1
           }
            Else {
                $RetState = $returnStateCritical
                $Events += [PSCustomObject]@{Severity=$Event.severity;SourceIP=$Event.source;SourceHost=$Event.hostname;Category=$Event.category;Entity=$Event.device_entity_name;State=[Int64]$RetState}
                $RetMajor = $RetMajor + 1
            }
        }

Im restlichen Skript wurden die einzelnen Daten mit einem vorgegebenen Wert gegen geprüft und die entsprechenden PRTG Ausgaben definiert.

Das Script muss nun in den Custom Sensors Ordner von PRTG gelegt werden und der Sensor kann entsprechend eingerichtet werden:

Parameter gem. Script-Beschreibung, Securitykontext vom Gerät

Das Resultat sieht dann wie folgt aus:

Viel Spass beim Nachbauen :-)




PRTG – Zertifikate mittels ADM überwachen

Im einem der letzten Beiträge habe ich ein Powershell Modul vorgestellt, mit welchem man Daten vom Citrix ADM abgreifen kann.

Basierend auf diesem Modul habe ich bei uns einen PRTG Custom Sensor erstellt, welcher die Ablaufdaten aus der SSL Zertifikatsübersicht ausliest:

Dazu müssen erst einmal die Parameter von PRTG sowie das Modul selbst eingelesen und eine Verbindung zur Appliance hergestellt werden:

# Get parameter from PRTG
param (
[string]$server,
[string]$domain,
[string]$username,
[string]$password
)

# Import ADM PS module
$CustomSensors="C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\"
Import-Module $CustomSensors\PRTGCustomCitrixADM.psm1

# Create the ADM session
$ADMHost = "https://"+$server
$ADMSession = Connect-ADM -ADMHost $ADMHost -CredUser $username -CredPW $password

Damit dies funktioniert, muss der entsprechende Benutzer von PRTG auf dem ADM Leserechte haben. Weiter gehe ich nicht auf jede Zeile ein, dies kann im Script selbst nachgelesen werden. Hier beschreibe ich vor allem die wichtigsten Punkte, wie das auslesen der Zertifikate:

# Get the certificates from the ADM
Invoke-ADMNitro -ADMSession $ADMSession -OperationMethod GET -ResourceType ns_ssl_certkey
$ActiveCerts = Invoke-ADMNitro -ADMSession $ADMSession -OperationMethod GET -ResourceType ns_ssl_certkey

Das Ablaufdatum konnte nicht einfach so verwendet werden, daher musste ich mittels einer Funktion dieses erst in einen String umwandeln und dann entsprechend sortiert wieder zurück geben:

# Function ConvertTo-DateTime
# Converts the dates from the certificates to a standardized format
Function ConvertTo-DateTime([string] $datetime) {
    # Removes double spaces
    $datetime2 = $datetime -replace '\s+',' '
    # Create an array and use the space as separator
    $arr = $datetime2 -split ' '
    # Reorder and create a readable date
    $validdate = $arr[3] +"-"+ $arr[0] +"-"+ $arr[1] +" "+ $arr[2]
    # Return the value
    return $validdate
}

Nun konnte ich jedes Zertifikat einzeln in ein Array schreiben mit den entsprechenden Common Names und Ablaufdaten:

# Create array with all the certification information
ForEach ($Cert in $ActiveCerts2.ns_ssl_certkey){
    
    $CertSubject = ($Cert.subject -split "," | ConvertFrom-StringData).CN
    $CertIssuer = ($Cert.issuer -split "," | ConvertFrom-StringData).CN
    $CertValidTo = ConvertTo-DateTime $Cert.valid_to
    # For troubleshooting
    #Write-Host $CertValidTo
    $Certs += [PSCustomObject]@{Host=$Cert.hostname;Subject=$CertSubject;Status=$Cert.status;Expiredate=$CertValidTo;IssuerCA=$CertIssuer}

}

Im restlichen Skript wurden die einzelnen Daten mit einem vorgegebenen Wert gegen geprüft und die entsprechenden PRTG Ausgaben definiert.

Das Script muss nun in den Custom Sensors Ordner von PRTG gelegt werden und der Sensor kann entsprechend eingerichtet werden:

Parameter gem. Script-Beschreibung, Securitykontext vom Gerät
Als primären Channel die bald ablaufenden Zertifikate, Intervall 12h und sofortiger DOWN Status auswählen

Das Resultat sieht dann wie folgt aus:

Viel Spass beim Nachbauen :-)




PRTG – Citrix ADM für zentrale ADC Überwachung nutzen

Es ist schon ein paar Tage her, da habe ich über PRTG Custom Sensoren für ADC geschrieben. Diese haben bisher mehr oder weniger gut in unserer Umgebung funktioniert. Für mich zeigten sich dabei jedoch mit der Zeit folgende Nachteile:

  • Jeder ADC, jedes ADC HA Paar muss im PRTG konfiguriert werden
  • Ist ein LB/CS vServer im DOWN Status, bleibt der PRTG Sensor rot, bis der vServer entweder wieder UP oder manuell deaktiviert ist (reaktivieren nicht vergessen)
  • Die Sensoren lieferten teils falsche/unvollständige Daten

Da wir sowieso eine ADM Appliance im Einsatz haben, suchte ich nach Möglichkeiten diese als Datenquelle anzusteuern. Mein erster Ansatz mit SNMP Traps scheiterte an der Tatsache, das PRTG dies nur einmalig als Alarm anzeigt und im nächsten Intervall wieder auf Status grün wechselt, falls nicht ein weiterer Trap gesendet wurde. Diese Option war daher für uns unbrauchbar.

Nach ein paar Recherchen bin ich auf ein Powershell Modul von Kenny Baldwin gestossen, welches mittels Nitro REST eine ADM Appliance mit div. Befehlen ansteuern kann. Das Original kann man auf GitHub herunterladen.

Das Modul hat ursprünglich vorgesehen, dass bei Benutzung die Anmeldedaten manuell eingegeben werden sollen. Für die Nutzung mit PRTG habe ich daher diesen Teil ein wenig angepasst, so dass die Daten aus dem PRTG Sensor übernommen werden können:

    param (
    [Parameter(Mandatory = $true)]
    [string]$ADMHost,
    [Parameter(Mandatory = $true)]
    [string]$CredUser,
    [Parameter(Mandatory = $true)]
    [string]$CredPW,
    [Parameter(Mandatory = $false)]
    [int]$Timeout = 900
    )

Nun kann das Modul zusammen mit den späteren Custom Sensoren im PRTG Custom Sensor Ordner gespeichert und ggf. verteilt werden.




PRTG – Failover Cluster mit Citrix ADC

Bei meinem aktuellen Arbeitgeber steht die Migration in zwei neue Rechenzentren an. Eines der Ziele dieser Migration ist die Erhöhung der Ausfallsicherheit. Dies habe ich zum Anlass genommen mir den PRTG Failover Cluster mit einem vorgeschalteten Citrix ADC einmal anzuschauen.

Die Installation und Konfiguration ist eigentlich recht einfach und das Vorgehen möchte ich in diesem Artikel nochmals erläutern.



PRTG Failover Cluster konfigurieren

Um den Core-Server von PRTG als Failover-Cluster zu konfigurieren gibt es seitens PAESSLER zwei gute Artikel:
Failover Cluster Configuration
Failover Cluster Step by Step

Wenn man sich an diese hält, läuft der Cluster in kürzester Zeit. Was gibt es zu beachten?

  • Der zweite Cluster-Node ist immer Read-Only, d.h. selbst bei einem Ausfall des Master-Servers kann auf dem Failover-Server nur überwacht, jedoch nicht konfiguriert werden.
  • Remote Probes müssen so (um-)konfiguriert werden, dass sie ihre Daten an alle Cluster Nodes senden und nicht nur dem Master.
  • Die Remote Probes werden vom PRTG Cluster selbst konfiguriert. Eine allfällige Registry Anpassung (manuell oder via GPP) wird wieder überschrieben.
  • Remote Probes müssen jeden Cluster Node einzeln erreichen können. Bei einer NAT Konfiguration bedeutet dies ein eigener FQDN und NAT Zugang pro Core Server.
  • Der erste Administrator (prtgadmin) ist autonom pro Node. Um spätere Probleme zu vermeiden sollte das Passwort auf beiden Servern identisch gesetzt und mit der AD Authentifizierung gearbeitet werden.
  • Nur der Master-Server sieht sich selbst noch als „Local Probe“. Auf den Failover-Servern ist nur der „Cluster Probe“ und alle anderen Remote Probe Server ersichtlich.
  • Die Probe Dienste der PRTG Core Server senden ihre Daten nur lokal (127.0.0.1).

In den Cluster Einstellungen sollte man die „Node Namen“ passend setzen und die IP Adressen durch FQDN ersetzen.
Dies macht es einerseits übersichtlicher für alle PRTG Benutzer und andererseits ist man unabhängiger bei einer allfälligen Änderung der IP Adressierung.

Kontrolle in der Registry auf einem Remote Probe Server
Kontrolle im Cluster Status
Cluster-Konfiguration der Remote Probes

Hinweise:
– Man kann zwar im GUI dem Master Server einen DNS Alias setzen, die Remote Probes erhalten jedoch immer den originalen Hostname übermittelt.
– Die Änderung wird sofort an die Remote Probes übermittelt.

Bei einer frischen Installation kann nun die Konfiguration direkt in der Cluster Probe gestartet werden. Wurde ein Solo PRTG Core Server in einen Cluster umgewandelt, so müssen die konfigurierten Gruppen, Geräte und Sensoren vomr „Local Probe“ in den „Cluster Probe“ verschoben werden:

Konfiguration Citrix ADC

Nachdem nun der PRTG Failover Cluster soweit konfiguriert ist, bauen wir nun den Zugriff auf diesen. Ohne ADC würde man nun entweder mittels DNS Round-Robin einen FQDN konfigurieren, wobei man hier nicht steuern kann auf welchem Node man landet, oder man arbeitet mit zwei verschiedenen FQDN, was wiederum nicht Anwenderfreundlich ist.

In diesem Abschnitt wird die Konfiguration eines LB vServer mit Failover Funktion erläutert.

Hierzu werden alle (normalerweise zwei) Cluster Nodes im ADC erfasst:

add server prtgserver1 prtgserver1.domain.pit
add server prtgserver2 prtgserver2.domain.pit

Für jeden Server erstellen wir einen Service. Nach best practice sind die PRTG Server SSL verschlüsselt, somit bauen wir passende Services dazu:

add service svc-https-prtgserver1 prtgserver1 SSL 443
add service svc-https-prtgserver2 prtgserver2 SSL 443

Im Gegensatz zu einem normalen Loadbalancing wird im Failover nicht ein einzelner sondern zwei vServer benötigt, um den zweiten als Backup zu konfigurieren. Dem vServer mit einer IP wird der Service des PRTG Master Servers angefügt. Der zweite vServer (ohne Adressierung) steuert den PRTG Failover Server an. Beide LB vServer benötigen auch das dazu passende SSL Zertifikat:

add lb vserver lb-vsrv-prtg.domain.pit SSL 192.168.200.222 443
add lb vserver lb-vsrv-prtg-backup.domain.pit SSL 0.0.0.0 0

bind lb vserver lb-vsrv-prtg.domain.pit svc-https-prtgserver1
bind lb vserver lb-vsrv-prtg-backup.domain.pit svc-https-prtgserver2

bind ssl vserver lb-vsrv-prtg.domain.pit -certkeyName wildcard.domain.pit
bind ssl vserver lb-vsrv-prtg-backup.domain.pit -certkeyName wildcard.domain.pit

set lb vserver lb-vsrv-prtg.domain.pit -backupVServer lb-vsrv-prtg-backup.domain.pit

Dem Service Monitoring habe ich am meisten Zeit gewidmet. Die PRTG Server bieten eine Status-Seite (/api/public/testlogin.htm), welche jedoch bereits bei einem Problem mit dem Mailserver ein „NOTOK“ zurück meldet.
Nur diese Status-Seite alleine konnte ich also nicht nutzen. Daher baute ich ein Monitoring basierend auf dieser plus zusätzlichen zwei Standard-Monitoren (TCP und HTTP). Da sich der TCP-Default Monitor nicht anfügen lässt wenn bereits ein anderer Monitor in Benutzung ist, habe ich einen eigenen erstellt.
Wegen der Benutzung von HTTPS muss dem HTTP Monitor der Response Code 302 hinzugefügt werden.

add lb monitor mon-prtg-TCP TCP
add lb monitor mon-prtg-http HTTP -respCode 200 302 -httpRequest "HEAD /" -secure YES

Das Monitoring der Status-Seite bat mir ein erstes Mal die Nutzung des „Reverse“ Monitorings. Würde man nämlich nur die Antwort „OK“ prüfen, so wäre der Monitor auch bei einem „NOTOK“ zufrieden, da „OK“ ein Bestandteil der Antwort ist. Daher prüfen wir auf ein „NOTOK“ und geben mit dem Monitor grünes Licht, falls diese Antwort nicht vorhanden ist – Reverse eben. ;-)

add lb monitor MON-PRTG-Core-Status HTTP-ECV -send "GET /api/public/testlogin.htm" -recv NOTOK -reverse YES -secure YES

Zu guter Letzt müssen die neu gebauten Monitore in den Services konfiguriert werden. Dazu fügen wir pro Service die drei hinzu und definieren den Monitoring Schwellwert 2. So bleibt der Service verfügbar, solange zwei Monitore grünes Licht geben:

bind service svc-https-prtgserver1 -monitorName mon-prtg-http
bind service svc-https-prtgserver1 -monitorName mon-prtg-TCP
bind service svc-https-prtgserver1 -monitorName mon-prtg-Core-Status
bind service svc-https-prtgserver2 -monitorName mon-prtg-http
bind service svc-https-prtgserver2 -monitorName mon-prtg-TCP
bind service svc-https-prtgserver2 -monitorName mon-prtg-Core-Status

set service svc-https-prtgserver1 -monThreshold 2
set service svc-https-prtgserver2 -monThreshold 2

Mit dieser Konfiguration kann nun ein Benutzer über eine FQDN (z.B. prtgcluster.domain.pit) auf die PRTG Oberfläche zugreifen. Der LB vServer vom ADC schaltet erst auf den Failover Server um, sobald der Master Server nicht mehr verfügbar ist (z.B. Neustart). Ist der Master Server wieder online, schaltet der ADC wieder auf diesen zurück.

Viel Spass beim Nachbauen. :-)




PRTG – Citrix ADC überwachen

Citrix bietet zur Überwachung und Konfiguration von Citrix ADC (ehem. NetScaler) das Citrix Application Delivery Management (ehem. NetScaler MAS). Wie kann man nun aber die ADC Appliances im PRTG überwachen? Diese Frage haben sich schon einige gestellt und nebst kostenpflichtigen Plugins von www.prtgplugins.com gibt es weitere Open Source Optionen.

Eine mögliche Lösung habe ich bei Jason McKenry gefunden. Er hat basierend auf dem NetScaler PowerShell Modul passende Skripte erstellt, mit welchen aktuell folgendes überwacht werden kann:

  • Appliance Performance (CPU, PE CPU, Disk, RAM und Durchsatz)
  • Status aller vServer (LB, AAA, VPN und CS)
  • Status aller LB vServer
  • Ablaufdaten aller Zertifikate
  • ungespeicherte Konfigurationen

Sein Blog-Artikel erklärt die komplette Konfiguration in Englisch. Ich möchte in diesem Artikel einerseits die Vorgehensweise auf Deutsch erläutern und andererseits noch ein paar Ergänzungen anbringen.



Als Basis dient nun jedoch der Blog-Artikel von Jason:

Quelle: https://itrandomness.com/2018/01/monitoring-netscaler-with-prtg/

Als erstes lädt man die passenden Skripte herunter. Dieser sind entweder auf GitHub (manchmal aktualisiert) oder am Ende des Artikels zu finden.

Nun muss das NetScaler Module installiert werden. Hierbei gibt es folgendes zu beachten:

  • Ein aktuelles Windows Management Framework sollte installiert sein (muss manuell gemacht werden, nicht über die Microsoft Updates).
  • PRTG arbeitet mit der 32-bit Version von PowerShell. Somit müssen alle Befehle in der (x86) Version ausgeführt werden.
  • Das NetScaler Module muss auf allen Probe Server installiert werden, welche den Custom Sensor ausführen sollen.

Wenn alles rund läuft reichen folgende Befehle:

Set-ExecutionPolicy Unrestricted
Install-Module -Name NetScaler -scope AllUsers

Ich hatte auf meinem System das Problem, dass kein passender Provider gefunden wurde. Bei der Fehleranalyse stellte ich fest, dass im System kein Paket-Provider registriert war. Mit folgenden Befehlen kann dies korrigiert werden:

Install-PackageProvider Nuget –Force
Install-Module –Name PowerShellGet –Force

Damit wir die Appliances abfragen können, benötigen wir einen lokalen Benutzer auf jeder Appliance. Dieser benötigt nur Read-Only Rechte:

add system user svcprtg PASSWORD -externalAuth DISABLED
bind system user svcprtg read-only 100

Nun müssen die Sensor Dateien in die entsprechenden Ordner kopiert werden.

Die .ps1 Dateien kommen in den Ordner „Custom SensorsEXEXML“ (Standard: %programfiles(x86)%PRTG Network MonitorCustom SensorsEXEXML).

Die .ovl Dateien kommen in den Ordner „lookupscustom“ (Standard: %programfiles(x86)%PRTG Network Monitorlookupscustom).

Anschliessend müssen die Dateien (lookups) im PRTG neu geladen werden. Der Menüpunkt ist unter PRTG > Setup > Administrative Tools zu finden:

Bevor die Sensoren eingerichtet werden können, muss der neu erstellte Benutzer konfiguriert werden. Entweder gilt dieser nur für die ADC Appliances oder es ist eine Überlegung wert, den Benutzer für alle Linux/UNIX Server zu verwenden:

Linux Benutzer im PRTG konfigurieren

Nun können die fünf Sensoren (einer pro PowerShell Skript) eingerichtet werden. Diese werden als EXE/Script Advanced hinzugefügt. Der Name kann frei vergeben werden. Folgende Parameter müssen mitgegeben werden:

%host %linuxuser %linuxpassword

Hier ein paar Beispiele:

Performance Übersicht
Gültigkeit der SSL Zertifikate
Status LB vServer

Falls seitens ADC vServer hinzugefügt oder entfernt werden, so muss der Sensor neu eingerichtet werden. Die Channels können dies nicht automatisch abgleichen.

Viel Spass beim Nachbauen. :-)