Jump to content
Welcome to our new Citrix community!
  • Monitoring License Expiration in LogicMonitor


    cugcblogs

    prestongalwasrnd.png by Preston Galwas, CTA

    When you’re responsible for the care and feeding of your Citrix environment, it is important to keep tabs on your licensing status. In particular, if you have a license type that expires, it is important to monitor that data point to ensure you don’t ever have a “Bad Day™.”

    The Citrix licensing documentation explains the different sections of the license files.

    galwas041619-01.png.d2c7bc8ac35625bb5c08e158e21dd2b0.png

    Specifically, we’re interested in section 3, “INCREMENT,” with the “CSS_expiry_date” and “exp_date”.  The license counts themselves are actually available from the Citrix WMI provider, if you’re interested in monitoring those.

    To monitor these dates in LogicMonitor, we’re going to set up a “PropertySource” to automatically discover servers running the “Citrix Licensing” service, then create a “DataSource,” which will query all licenses in the default path, and alarm on any SA or Expiry dates that are less than 30 days.

    To get started, let’s create a “PropertySource” to assign a category “CitrixLicense” to the device.

    Settings->PropertySources->Add | PropertySource

    Add some descriptive information and “Group” the property source for ease of finding it later.

    galwas041619-02.png.7ecc1b2b2ed3ace6edee8c5e270d7130.png

    For the PropertySource Script, paste the following GroovyScript in. Note, you can use PowerShell Scripts to do similar.

     

    import com.santaba.agent.groovyapi.win32.WMI;

    def host = hostProps.get("system.hostname");

    try

    {

        // get a list of running services

        def service_list = WMI.queryAll(host, "select * from win32_service");

        def is_citrixLicenseServer = false;

        // enumerate each service as a map

        service_list.each

        { service_map ->

            // enumerate each of the fields in this service map

            service_map.each

            { key, value ->

                // is this a CitrixLicense service?

                if ((key == "NAME") && value.contains("Citrix Licensing"))

                {

                    // yes, flag it

                    is_citrixLicenseServer = true;

                }

            }

        }

        // did we locate a CitrixLicense service?

        if (is_citrixLicenseServer)

        {

            // yes, add the CitrixLicense to system.categories

            println "system.categories=CitrixLicense";

        }

        return 0

    }

    catch (Exception e)

    {

        println e

        return 1

    }

    Add the proper "Applies to" such as Windows(). You can click “test script” to see which devices will be matched. Click “Save” to save the PropertySource.

    You can see that if the service is found, we perform add “system.categories=CitrixLicense”.  We will use this category in the data source to specify which systems the discovery will apply to.

     

    Alternatively, you can use this Powershell script to apply categories for a variety of common Citrix roles.

     

    $hostname = "##Hostname##"

    add-type @"

        using System.Net;

        using System.Security.Cryptography.X509Certificates;

        public class TrustAllCertsPolicy : ICertificatePolicy {

            public bool CheckValidationResult(

                ServicePoint srvPoint, X509Certificate certificate,

                WebRequest request, int certificateProblem) {

                return true;

            }

        }

    "@

    [system.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

    $categories=@()

    $services=get-service -computername $hostname

    foreach($service in $services)

    {

           switch($service.DisplayName)

        {

            "Citrix Licensing" { $categories+="CitrixLicensing" }

            "Citrix Broker Service" { $categories+="CitrixDeliveryController" }

            "Citrix PVS Stream Service" { $categories+="CitrixPVS" }

            "Norskale Infrastructure Service" { $categories+="CitrixWEM" }

            "Citrix Remote Broker Provider" { $categories+="CitrixCloudConnector" }

        }

    }

    $directorResult=Invoke-WebRequest -Uri "https://$hostname/Director"  -UseBasicParsing -Method HEAD

    if($directorResult.StatusCode -eq 200)

    {

        $categories+="CitrixDirector"

    }

    $storefrontResult=Invoke-WebRequest -Uri "http://$hostname`:8000/StorefrontMonitor/GetSFServicesStatus"  -UseBasicParsing

    if($storefrontResult.StatusCode -eq 200)

    {

        $categories+="CitrixStorefront"

    }

    write-host "system.categories=$($categories -join ",")"

    exit 0

     

    Next, we will create a DataSource.  Settings -> DataSources -> Add DataSource

    galwas041619-03.png.8397408d6075155eab4a5506a6935413.png

    Fill in the descriptive information.

    galwas041619-04.png.4c1960da982752f6e5bb48fd4bf46737.png

    Relevant settings:

    Collect every: 1 day

    Collector: Batch Script

    Multi-Instance

    Enable Active Discovery

    Automatically Delete Instance | Delete Immediately

    Discovery Schedule: day

    Discovery method: Script, Embedded Powershell Script

     

    $hostname = '##SYSTEM.HOSTNAME##'

    $licenses=@()

    $regexPattern="INCREMENT.*(\d{4}.\d{4}) (\d{1}?-((jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)-2\d{3})|permanent)"

    $path="\\$hostname\C$\Program Files (x86)\Citrix\Licensing\MyFiles"

    function Convert-SADateToDateTime{

        [Parameter(Mandatory=$true)]

        param ($inputString)

        $year=$inputString.Substring(0,4)

        $mon=$inputString.Substring(5,2)

        $day=$inputString.Substring(7,2)

        $builtString="$year/$mon/$day"

        $DateTime = Get-Date($builtString)

        return $DateTime

    }

    function Convert-LicenseExpiryDate{

        [Parameter(Mandatory=$true)]

        param($inputString)

        if($inputString -eq "permanent")

        {

            $dateString="Jan-1-2099"

        }

        else

        {

            $dateString=$inputString

        }

        return (get-date $dateString)

    }

    $files= get-childitem -path $path -Filter *.lic | where-object {$_.name -ne "citrix_startup.lic"}

    if ($files)

        {

        foreach ($file in $files)

        {

            $currentFileContent=$null

            $currentFileContent=get-content $file.pspath

            $v=[Regex]::Matches($currentFileContent,$regexPattern)

            $SAExpirationDate=Convert-SADateToDateTime $($v[0].groups[1].Value)

        $LicenseExpiryDate=Convert-LicenseExpiryDate $($v[0].groups[2].Value)

        $licenses+=

            [pscustomobject][ordered]@{

            FileName = $file.Name

            SAExpiration = $SAExpirationDate

            LicenseExpiryDate= $LicenseExpiryDate

            DaysUntilSAExpiration = (($SAExpirationDate) - (get-date)).days

            DaysUntilLicenseExpiration = (($LicenseExpiryDate) - (get-date)).days

        }

        }

        for($i=0; $i -lt $licenses.Length; $i++)

        {

        write-host  "CitrixLicense_$($Licenses[$i].FileName)##$($Licenses[$i].FileName)"

        }

        exit 0

    }

    else

    {

        exit 80009999

    }

    For the Active Discovery script, we’re supplying a LogicMonitor variable, ##System.Hostname##, for use in connecting from our Collector machine to the Citrix licensing service. Note, in order to do this, the collector service account will need to have UNC access to the remote machine(s).

    Assuming you have devices in the “Applies to” category, you should be able to test script (for active discovery) to see which licenses are detected. In my case, the following items were found:

    galwas041619-05.png.c07a1980c432ecb0eabed4a25393bd72.png

    The WildValue and WildAlias are specified in the discovery script from this line:

        write-host  "CitrixLicense_$($Licenses[$i].FileName)##$($Licenses[$i].FileName)"

     

    LogicMonitor parses stdOutput to construct these, per their documentation on Scripted Active Discovery.

    At this point, we’re now ready to gather the collector attributes. Paste in this script:

    $hostname =     '##HOSTNAME##'

    $licenses=@()

    $regexPattern="INCREMENT.*(\d{4}.\d{4}) (\d{1}?-((jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)-2\d{3})|permanent)"

    $path="\\$hostname\C$\Program Files (x86)\Citrix\Licensing\MyFiles"

    function Convert-SADateToDateTime{

        [Parameter(Mandatory=$true)]

        param ($inputString)

        $year=$inputString.Substring(0,4)

        $mon=$inputString.Substring(5,2)

        $day=$inputString.Substring(7,2)

        $builtString="$year/$mon/$day"

        $DateTime = Get-Date($builtString)

        return $DateTime

    }

    function Convert-LicenseExpiryDate{

        [Parameter(Mandatory=$true)]

        param($inputString)

        if($inputString -eq "permanent")

        {

            $dateString="Jan-1-2099"

        }

        else

        {

            $dateString=$inputString

        }

        return (get-date $dateString)

    }

    $files= get-childitem -path $path | where-object { $_.name -ne "CITRIX.opt" -and $_.name -ne "citrix_startup.lic" }

    foreach ($file in $files)

    {

        $currentFileContent=$null

        $currentFileContent=get-content $file.pspath

        $v=[Regex]::Matches($currentFileContent,$regexPattern)

        $SAExpirationDate=Convert-SADateToDateTime $($v[0].groups[1].Value)

        $LicenseExpiryDate=Convert-LicenseExpiryDate $($v[0].groups[2].Value)

        $licenses+=

            [pscustomobject][ordered]@{

            FileName = $file.Name

            SAExpiration = $SAExpirationDate

            LicenseExpiryDate= $LicenseExpiryDate

            DaysUntilSAExpiration = (($SAExpirationDate) - (get-date)).days

            DaysUntilLicenseExpiration = (($LicenseExpiryDate) - (get-date)).days

        }   

    }

    foreach($license in $licenses)

    {

     "CitrixLicense_$($license.Filename)`.DaysUntilSAExpiration=$($license.DaysUntilSAExpiration)"

     "CitrixLicense_$($license.Filename)`.DaysUntilLicenseExpiration=$($license.DaysUntilLicenseExpiration)"

    }

    exit 0

     

    This script will retrieve all licenses on the specified host, then for each license discovered, it uses a regex pattern to extract the dates. If the word “permanent” is found, we convert that to January 1, 2099. Since the SA expiry date isn’t a format that “get-date” understands, we convert it to a format that will work for the cmdlet.

    Finally, for each discovered license, we output text to stdOutput in the key=value format that LogicMonitor will parse. 

    CitrixLicense_FID_19445f95_d1a0_4594_81df_e871e87a4678.lic.DaysUntilSAExpiration=356

    CitrixLicense_FID_19445f95_d1a0_4594_81df_e871e87a4678.lic.DaysUntilLicenseExpiration=386

    CitrixLicense_FID__23f6bf6d_161c87582c5__26bf.lic.DaysUntilSAExpiration=-42

    CitrixLicense_FID__23f6bf6d_161c87582c5__26bf.lic.DaysUntilLicenseExpiration=-12 

    Finally, we create the actual datapoints from the output of the collection.  Click “Add DataPoint” and create 2 gauge datapoints.

    galwas041619-07.png.2e1da8257420f2c63ce62c35582b025a.pnggalwas041619-08.png.0203f1a100f426dd7fe9671f616cc4b6.png

    Set the alert threshold

    galwas041619-09.png.28bf67adf71f352f9d2b8a6659a96ef3.png

    Then click save.

    Once you’ve saved your datapoint, any matching devices will run active discovery and you should now see your licenses associated with that device!  Based on your notification/escalation settings within LogicMonitor, you now have actionable monitoring of a vital piece of Citrix infrastructure.

    galwas041619-10.png.c23d3ac2be044a139e84ed8a5a800a3b.png

    User Feedback

    Recommended Comments

    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

×
×
  • Create New...