Cheap VPS & Xen Server

Residential Proxy Network - Hourly & Monthly Packages

Flexnet License Monitoring With rrdtool


Intro

Some of you may know the commercial Flexnet Licencing Application (©Macrovision). It’s a client-server based solution for managing the usage of socalled Flexnet-enabled applications. You can hold licenses of more than one product on one license-server. As you typically have to buy licenses and licenses can be expensive it would be nice to have a monitoring solution, to see the utilization of the precious licenses, wether they are underutilized (so money is wasted) or are always fully utilized (so that you can suspect that sometimes people can not do their work, or only delayed) which is also a waste of resources.

As far as I know there are commercial applications for performing such reports, but again you have to spent money. Why not build a simple system yourself, which shows the actual and past usage in an “MRTG style”?

 

Preliminary Note + Disclaimer

In this tutorial I’m going to use some scripts, namely Shell- and Python scripts. I think the whole application should run on every Linux, I did it on CentOS and Ubuntu. We need a webserversoftware which is able to run CGI scripts, I have used the wellknown Apache and also THTTPD, but I believe every webserversoftware should be able to run this application. It is also a perfect extension for my former Network Monitoring Appliance.

The following tutorial describes the way I realized my solution, it is written in a kind of cooking-recipe style. I can not issue any guarantee that you can realize a similar solution.

 

1. Architecture

The architecture of the solution is quite simple, see the picture below:

licensing

We leave the licensing server untouched, but get the necessary information over the network. Therefore we use the lmutil program which belongs to the Flexnet software and not only exists in a Windoze version, but also in a Linux version. As far as I know older versions of lmutil have also been available for HP/UX, Solaris and AIX, so there are chances that also systems running one of those OS’es could be used to build the monitoring system, but I have not tried.

The output of lmutil is filtered the way, that all relevant info could be put into one or more rrd databases, I have used one database for every license. rrd is also used to produce the graphs, directly in a subdirectory of the webserversoftware, from where it could be shown comfortably in a webbrowser.

 

2. Polling the license server

I have copied a recent version of lmutil into /usr/local/bin, and checked wether it is executable:

# ls -l /usr/local/bin/lmutil

-rwxr-xr-x 1 root root 309168 2008-01-08 00:45 /usr/local/bin/lmutil

We can check wether all shared libraries lmutil is linked against, exist on our system:

# ldd /usr/local/bin/lmutil

        linux-gate.so.1 =>  (0xf7796000)
libpthread.so.0 => /lib32/libpthread.so.0 (0xf7760000)
libdl.so.2 => /lib32/libdl.so.2 (0xf775c000)
libc.so.6 => /lib32/libc.so.6 (0xf7601000)
/lib/ld-linux.so.2 (0xf7797000)

Being a commandline utility lmutil is not linked against a lot of shared libs, so chances are high that they are already installed.

Then I have built a small script for polling all licensing dæmons with licenses for several products running on the licensing server, it looks like:

#!/bin/dash
# Product1
/usr/local/bin/lmutil lmstat -c 27000@licserv -a | /usr/local/sbin/lmrrd.py
# Product2
/usr/local/bin/lmutil lmstat -c 27001@licserv -a | /usr/local/sbin/lmrrd.py

I have used /bin/dash as interpreter for this script, because dash is known to consume less resources than bash, but feel free to use bash if you like. The licensing dæmons for the various products are running on different ports. The output of lmstat is directly piped into a Python script, where all info which is needed is filtered out and put into the appropriate rrd database.

cron is used to establish a 5 minute pollcycle. Therefore an entry in /etc/cron.d/ named rrd is created which looks like:

*/5 8-16 * * 1-5 root LANG=C LC_ALL=C /usr/local/sbin/licenses.sh

We are only interested how the licenses are utilized from monday to friday and from 8am to 5pm.

But before this could be established we first have to create the lmrrd.py script.

 

3. The lmrrd.py script

rrdtool is used as database for this task. rrdtool has different scripting interfaces, namely from shell-, perl-, python- and tcl/tk scripts. I have used python because of it’s clean language design and versatility.

This script is used to filter the output of lmutil and puts the relevant information directly into the assigned rrd database. It looks like:

#!/usr/bin/python
# Script to filter the output of lmstat to use it as input for rrd
import sys, string, rrdtool

# searchterm, position of actual value and position of max value in every line
# db is the name for the rrd dbfile
search = [ { 'term':"Users of CL:", 'val':10, 'max':5, 'db':'CL' },
           { 'term':"Users of xyzabc:", 'val':10, 'max':5, 'db':'xyzabc' },
           { 'term':"Users of qwerty:", 'val':10, 'max':5, 'db':'qwerty' } ]
rrddir='/var/rrd/'
# read all lines from stdin 
for line in sys.stdin.readlines():
  # search in every line for the searchterm out of the above array
  for x in search:
    if x[ 'term' ] in line:
      cols = line.split()
      if not cols[ x[ 'max' ] ].isdigit() or not cols[ x[ 'val' ] ].isdigit():
        print "0\n0\n0\n", x[ 'term' ]
      
      # put the values in the assigned rrd dbfile
      rrdtool.update( rrddir + x[ 'db' ] + '.rrd', \
        '--template=value:total', \
        'N:' + cols[ x [ 'val' ] ] + ':' + cols[ x[ 'max' ] ] )

The search terms in the array could be extracted of the output of “lmutil”, also the positions of the actual and the maximum possible values of the number of licenses.

You need the python bindings of rrdtool, which can either be found in the package repository of your OS, or on the website of the maintainer of rrdtool.

As implemented this script is run with root permission. The originating rrd files should be world readable, because the following scripts which generate the graphs run only under permission of the owner of the http-server processes, usually www-data or similar.

4. Creating the graphs

The graphs could easily be created with the help of the rrdcgi program, which is in the rrdtool package. Creation is then only done on demand to save CPU cycles, you have to create some CGI scripts with special RRD:: tags, which are interpreted by rrdcgi.

My CGI script looks like:

#!/usr/bin/rrdcgi

<HTML>
<HEAD><TITLE>Prod1 License Usage</TITLE></HEAD>
<BODY>
<H1>Prod1 License Usage at <RRD::TIME::NOW '%a, %d %b %Y %H:%M'></H1>
<P></P>

<P>
<RRD::GRAPH /var/www/rrd/CL.png
        --imginfo '<IMG SRC=/rrd/%s>'
        -s -24hours -w 600 -h 200 -W gbi@localhost@localdomain
        -v "Licenses used" --lazy
        --title "Users of CL"
        -l 0 -Y
        DEF:value=/var/rrd/CL.rrd:value:MAX
        DEF:total=/var/rrd/CL.rrd:total:MAX
        AREA:value#660000
        LINE3:total#FF00FF>

</P>
</BODY>
</HTML>

For details see the manpages of rrdcgi and rrdgraph.

This is an example of a wellknown MRTG-style graph:

CL

Not much going on here.

The script above was my first, simple approach. The idea was to implement a set of scripts for every product and for different periods, one for daily, one for weekly one for monthly and one for yearly overviews. But this leads to a flood of scripts being nearly identical. After another look into the documentation of rrdcgi another possibility was found, leading to a solution with one script per product and radiobuttons for interactive selection of the timeperiod of interest. The script looks like:

#!/usr/bin/rrdcgi

<HTML>
<HEAD><TITLE>Prod1 License Usage</TITLE></HEAD>
<H1>Prod1 License Usage at <RRD::TIME::NOW '%a, %d %b %Y %H:%M'></H1>

<H2>Time period</H2>
<FORM><INPUT NAME=period TYPE=RADIO Value=24hours> Daily,
        <INPUT NAME=period TYPE=RADIO VALUE=7days> Weekly,
        <INPUT NAME=period TYPE=RADIO VALUE=1month> Monthly,
        <INPUT NAME=period TYPE=RADIO VALUE=1year> Yearly.
        <INPUT TYPE=SUBMIT></FORM>

<BODY>
<P></P>

<P>
<RRD::GRAPH /var/www/rrd/CL-<RRD::CV period>.png
        --imginfo '<IMG SRC=/rrd/%s>'
        -s -<RRD::CV period> -w 600 -h 200 
        -W gbi@localhost.localdomain
        -v "Licenses used" --lazy
        --title "Users of CL"
        -l 0 -Y
        DEF:value=/var/rrd/CL.rrd:value:MAX
        DEF:total=/var/rrd/CL.rrd:total:MAX
        AREA:value#660000
        LINE3:total#FF00FF>
</P>

</BODY>
</HTML>

The radiobuttons above the graphs for selecting the timeperiod look like:

rbtn

Not much going on here.

The script above was my first, simple approach. The idea was to implement a set of scripts for every product and for different periods, one for daily, one for weekly one for monthly and one for yearly overviews. But this leads to a flood of scripts being nearly identical. After another look into the documentation of rrdcgi another possibility was found, leading to a solution with one script per product and radiobuttons for interactive selection of the timeperiod of interest. The script looks like:

#!/usr/bin/rrdcgi

<HTML>
<HEAD><TITLE>Prod1 License Usage</TITLE></HEAD>
<H1>Prod1 License Usage at <RRD::TIME::NOW '%a, %d %b %Y %H:%M'></H1>

<H2>Time period</H2>
<FORM><INPUT NAME=period TYPE=RADIO Value=24hours> Daily,
        <INPUT NAME=period TYPE=RADIO VALUE=7days> Weekly,
        <INPUT NAME=period TYPE=RADIO VALUE=1month> Monthly,
        <INPUT NAME=period TYPE=RADIO VALUE=1year> Yearly.
        <INPUT TYPE=SUBMIT></FORM>

<BODY>
<P></P>

<P>
<RRD::GRAPH /var/www/rrd/CL-<RRD::CV period>.png
        --imginfo '<IMG SRC=/rrd/%s>'
        -s -<RRD::CV period> -w 600 -h 200 
        -W gbi@localhost.localdomain
        -v "Licenses used" --lazy
        --title "Users of CL"
        -l 0 -Y
        DEF:value=/var/rrd/CL.rrd:value:MAX
        DEF:total=/var/rrd/CL.rrd:total:MAX
        AREA:value#660000
        LINE3:total#FF00FF>
</P>

</BODY>
</HTML>

The radiobuttons above the graphs for selecting the timeperiod look like:

rbtn

5. Creation of the rrd databases

There is one topic I have not mentioned so far, how the rrd databases are created. I have used, you sense it, another script. It looks like:

#!/usr/bin/python
# Script to create all rrd dbs for all instances of licenses 
# in a mrtg compatible fashion


import sys, string, rrdtool

search = [ { 'term':"Users of CL:", 'val':10, 'max':5, 'db':'CL' },
           { 'term':"Users of xyzabc:", 'val':10, 'max':5, 'db':'xyzabc' },
           { 'term':"Users of qwerty:", 'val':10, 'max':5, 'db':'qwerty' } ]


for x in search:

      rrdtool.create( '/var/rrd/' + x[ 'db' ] + '.rrd', '-s 300', \
	'DS:value:GAUGE:600:U:U', 'DS:total:GAUGE:600:U:U', \
        'RRA:MAX:0.5:1:600', 'RRA:MAX:0.5:6:700', 'RRA:MAX:0.5:24:775', \
	'RRA:MAX:0.5:288:797' )

Of course you have to adjust this to your needs.

 

6. Another CGI script

To further ease the handling of the Flexnet system and the users who need to lease a license to do their work, another CGI script was created. It is used to show who has leased how much licenses, it is only the output of “lmutil lmstat -a”, but without logging in into a system where lmutil is installed. But be aware, this may collide with privacy protection in your enterprise, because personal informations are free accessible. So you may have to protect running this script with some authentication mechanism, but this topic is not covered in this tutorial.

The script is again a dash script as the one in chapter 2, you can query more than one product on more than one server, if implemented accordingly. It is also a so called here-script, which is a special, rarely used kind of shellscript. Again feel free to adjust to your needs:

#!/bin/dash

case $1 in
        prod1)          PORT=27000; PROD="Prod1";;
        prod2)          PORT=27002; PROD="Prod2";;
        prod3)          PORT=27042; PROD="Prod3";;
        *|prod4)        PORT=27001; PROD="Prod4";;
esac

echo Content-type: text/html
echo ""

/bin/cat << EOM
<HTML>
<HEAD><TITLE>Licensestate $PROD</TITLE>
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="cache-control" CONTENT="no-cache">
</HEAD>
<BODY bgcolor="#cccccc" text="#000000">
<HR SIZE=5>
<H1>Licensestate $PROD</H1>
<TD WIDTH=30%>
</P>
</TD>
<HR SIZE=5>
<P>
<PRE>
EOM

/usr/local/bin/lmutil lmstat -c $PORT@LICENSESERVER -a

/bin/cat << EOM
</PRE>
</SMALL>
<P>
<HR SIZE=3>
<P STYLE="margin-bottom: 0in"><A HREF="mailto:gbi@localhost.localdomain"><SPAN STYLE="text-decoration: none"><FONT SIZE=4 STYLE="font-size: 16pt"><FONT FACE="URW Chancery L">GBi</FONT></FONT></SPAN></A></P>
<P STYLE="margin-bottom: 0in; font-weight: medium; text-decoration: none">
<FONT FACE="Nimbus Roman No9 L, serif"><FONT SIZE=4>14.6.2010</FONT></FONT>

</BODY>
</HTML>
EOM

Simply copy this script into the cgi-bin directory of your webserver (/usr/lib/cgi-bin in my case), make it world read- and executable, do not forget to load the CGI module of your webserver (if it has one, or it is not loaded already), and you are ready to take off. The output looks like:

lic_state

This script is called in your webbrowser with a URL like:

http://server/cgi-bin/licstate.cgi?prod2

So you can select one of several products simply by supplying a “command line parameter” to the CGI script.

By supplying a script like this one to the users of products where available licenses tend to be nearly maxed out all the time, it is easy that the users handle their issues regarding license usage among themselves, and there is no need for the administrator to be involved at all ;-).

 

7. URLs

  • MRTG: http://oss.oetiker.ch/mrtg/
  • RRDTOOL: http://oss.oetiker.ch/rrdtool/
  • Apache: http://httpd.apache.org/
  • THTTPD: http://www.acme.com/software/thttpd/
  • DASH: http://gondor.apana.org.au/~herbert/dash/
  • Python: http://www.python.org/
  • My Network Monitoring Appliance: http://www.Kreationnext.com/network-monitoring-appliance

 

 

Comments

comments