#!/usr/bin/perl
# -*- perl -*-
#
# Copyright 2009 by the Regents of the University of Minnesota
# Written by Munir Nassar <nassarmu@msi.umn.edu>
# Rewrite contribution by TSUCHIYA Masatoshi <tsuchiya@namazu.org>
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# The Minnesota Supercomputing Institute http://www.msi.umn.edu sponsored
#	the development of this software.
#
# Requirements:
#	- lmstat
#
# Note:
#	- You must provide the daemon name as it is listed in the flexlm license
#    if you want it displayed differently use the LMDISPLAYNAME variable
#
# Parameters supported:
#  - config
#  - autoconf
#
# Configuration variables
#  - LMFEATURES:	The individual features of each vendor daemon to graph.
#			If no features are given, all features
#			reported by vendor daemon are treated to graph.
#  - LMDISPLAYNAME:	use the LMDISPLAYNAME instead of the daemon name when
#			generating graph names
#  - LMGRAPHISSUED:	If set generate a graph of the number of licenses issued for
#			each feature.
#  - LMSTAT:		The path to the lmstat binary
#  - LMLICFILE:		The path to the FlexLM License File
#  - LMLOGARITHMIC	If set then graph use a logarithmic scale
#  
# $Log$
# Revision 1.00	20090807	nassarmu
# Initial public release.
# 
# Revision 1.10 20120625 nassarmu@msi.umn.edu
# incorporate the rewrite by TSUCHIYA Masatoshi <tsuchiya@namazu.org>
#
# Magic markers:
#%# family=licensing
#%# capabilities=autoconf

use Class::Struct;
use English qw/ $PROGRAM_NAME /;
use strict;
use warnings;

# What daemon are we going to graph? if none specified exit.
$PROGRAM_NAME =~ /flexlm_(.+)*$/;
our $DAEMON = $1;
exit 2 unless defined $DAEMON;
our $munincommand;

# This section is for some optional values, the defaults may work for you
# if not then i recommend setting these option via plugin-conf.d
# This would also allow you to theoretically support multiple flexlmds
# via different license files.
our $LMSTAT = $ENV{'LMSTAT'} || '/opt/local/flexlm/bin/lmstat';
our $LMLICFILE = $ENV{'LMLICFILE'} || '/opt/local/flexlm/license/license.dat';;

&struct( feature => { name => '$', cleanname => '$', max => '$', used => '$' } );

sub lmstat {
    my @feature;
    open( my $ph, sprintf('%s -c %s -S %s|', $LMSTAT, $LMLICFILE, $DAEMON) ) or exit 2;
    while( <$ph> ){
	if( my( $name ) = m/\AUsers of ([^:]+):/ ){
	    my $x = feature->new( name => $name, max => 0, used => 0 );
	    $name =~ s/^[^A-Za-z_]+/_/;
	    $name =~ s/[^A-Za-z0-9_]/_/g;
	    $x->cleanname( $name );
	    m/Total of (\d+) licenses? issued/ and $x->max( $1 );
	    m/Total of (\d+) licenses? in use/ and $x->used( $1 );
	    push( @feature, $x );
	}
	elsif( m/\A\s+(\d+) RESERVATIONs? for / ){
	    $feature[-1]->used( $feature[-1]->used - $1 );
	}
    }
    if( $ENV{'LMFEATURES'} ){
	my %table;
	for( split( /\s+/, $ENV{'LMFEATURES'} ) ){
	    $table{$_}++;
	}
	grep( $table{$_->name}, @feature );
    } else {
	@feature;
    }
}

if ( $ARGV[0] ) {
	$munincommand = $ARGV[0];
}
else {
	$munincommand = 'none';
}

if( $munincommand eq 'autoconf' ){
    if( &lmstat > 0 ){
	print "yes\n";
    } else {
	print "no\n";
    }
}
elsif( $munincommand eq 'config' ){
    printf "graph_title FlexLM License usage for %s\n", $ENV{'LMDISPLAYNAME'} || $DAEMON;
    if( $ENV{'LMLOGARITHMIC'} ){
	print "graph_args --base 1000 --vertical-label licenses --lower-limit 0.01 --logarithmic\n";
    } else {
	print "graph_args --base 1000 --vertical-label licenses -l 0\n";
    }
    print "graph_category other\n";
    print "graph_period minute\n";
    for my $x ( &lmstat ){
	printf "%s.label %s\n", $x->cleanname, $x->name;
	printf "%s.draw LINE2\n", $x->cleanname;
	printf "%s.info The number of %s licenses checked out\n", $x->cleanname, $x->name;
	if( $ENV{'LMGRAPHISSUED'} ){
	    printf "%smax.label %s max\n", $x->cleanname, $x->name;
	    printf "%smax.draw LINE3\n", $x->cleanname;
	    printf "%smax.info The total number of %s licenses available\n", $x->cleanname, $x->name;
	}
    }
}
else {
    for my $x ( &lmstat ){
	printf "%s.value %d\n", $x->cleanname, $x->used;
	if( $ENV{'LMGRAPHISSUED'} ){
	    printf "%smax.value %d\n", $x->cleanname, $x->max;
	}
    }
}
exit 0;
