#!/usr/bin/perl -w

=pod

=head1 NAME

check_tina_alarm.pl - nagios plugin for TiNa

=head1 SYNOPSIS

Check alerts from Time Navigator and return a netsaint/nagios compatible result

=head1 OPTIONS

check_tina_alarm.pl <outputfile> [options]

=item B<-verbose>

more times for more debugging info

=item B<-warning>

warning limit: number of severity 2 errors that generate a WARNING error

=item B<-critical>

critical limit: number of severity 2 errors that generate a CRITICAL error

=item B<-catalog>

tina catalog: name of the catalog to connect to

=item B<-identity>

tina identity: user and password to use to connect to tina, syntax user:pass

=head1 DESCRIPTION

This is a nagios plugin to retrieve active alerts from a local instance of Atempo Time Navigator.
It uses the tina_shell scripting utility. Note that severity 3 errors always return CRITICAL.

=head1 FILES

F</dev/null> input file

=head1 RESTRICTIONS

Severity 1 errors are reported but not considered for level alert

=head1 CAVEATS

tina acknowledgements are ignored

=head1 AUTHOR

Some code from (c) William Preston, noris network AG, 2005 (william.preston@noris.net)
Other from Phelma

=head1 LICENSE

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.

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 (see the file COPYING included with this
distribution); if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

=head1 HISTORY

=cut


use strict;
use Getopt::Long;
use Pod::Usage;
use POSIX;

# Binaire tina qui lance les autres progs tina avec les bonnes librairies
my $runtina = "/tina/tina/Bin/runtina";

# Option de la ligne de commande
my $help = 0;
my $warn_limit = 1;
my $crit_limit = 1;
my $identity = '';
my $catalog = '';

# Decompte des alarmes tina
my $crit_count = 0;
my $major_count = 0;
my $minor_count = 0;
my $test_count = 0;
my $other_count = 0;

my @tina_errors;
my $tmpfile;

# Nagios exit values
# 0 = OK, 1 = WARNING, 2 = CRITICAL, 3 = UNKNOWN
my $returnvalue = 3;
my $returnstatus = "UNKNOWN";
my $returntext = "";
my $returnperf = "";

# debug - 0 = none, >0 = more
my $debug = 0;

# check the command line options
GetOptions('h|help|?' => \$help,
           'v|verbose|debug+' => \$debug,
	   'w|warning=s' => \$warn_limit,
	   'c|critical=s' => \$crit_limit,
	   'i|identity=s' => \$identity,
           'l|catalog=s' => \$catalog);
	   
if ($#ARGV!=-1) {$help=1;} # wrong number of command line options
pod2usage(1) if $help;

if (! $ENV{TINA_SERVICE_NAME}) { $ENV{TINA_SERVICE_NAME} = "tina" };
if (! $ENV{TINA_HOME}) { $ENV{TINA_HOME} = "/usr/tina" };
$ENV{LD_LIBRARY_PATH}=$ENV{LD_LIBRARY_PATH}?"$ENV{LD_LIBRARY_PATH}:$ENV{TINA_HOME}/Lib":"$ENV{TINA_HOME}/Lib";

do {$tmpfile = tmpnam();} until sysopen(FH, $tmpfile, O_RDWR|O_CREAT|O_EXCL, 0666);


# Script tina
print FH <<EOL;
# Simulation d'alarme pour tester par la suite la bonne exectution du script
echo 0 , test alarme ;;;
# Recuperation et parcours de la liste des alarmes
list Alarm in HDL_LIST_ALARM
foreach HDL_ALARM in HDL_LIST_ALARM
  # Les attributs, de l'alarme, que nous souhaitons lire :
  assign AlarmMessage      &STR_MSG
  assign AlarmSeverity     &INT_SEVERITY
  assign AlarmDate         &INT_DATE
  assign AlarmDateLast     &INT_LAST
  assign AlarmAcknowledged &INT_ACKNOWLEDGE
  assign AlarmCount        &INT_COUNT
  assign AlarmObjectClass  &INT_CLASS
  assign AlarmObjectHandle &HDL_OBJ
  get HDL_ALARM

  # On ne veut signaler que les alarmes non-acquittees
  if INT_ACKNOWLEDGE == 0
    date INT_DATE STR_DATE
    # Si l'objet de l'alarme est un hote, on affiche son hostname en plus du reste
    if INT_CLASS == 1
      assign HostName &STR_HOST
      get HDL_OBJ
      echo INT_SEVERITY , STR_HOST : STR_MSG - INT_COUNT fois ;;;
    else
      echo INT_SEVERITY , STR_MSG - INT_COUNT fois ;;;
    endif
  endif
endfor
EOL

close FH;
my $opt_catalog = "";
if (! $catalog eq "") { $opt_catalog = " -catalog $catalog"; }
my $opt_identity = "";
if (! $identity eq "") { $opt_identity = " -identity $identity"; }
open (FH2, "$runtina tina_shell $opt_catalog $opt_identity -file $tmpfile |") or die "tina shell not found";

# Parcours du retour de la commande tina_shell et insertion des alarmes dans un tableau
my $nb_lines = 0;
while (<FH2>) {
  my $alarm;
  $nb_lines++;

  if (! /([0-9]) , (.*) ;;;/ms) {
    # concatenate multi-line errors
    chomp;
    $_ = $_.<FH2>;
    redo;
  }
  if ($debug>1) { print "$1,\"$2\"\n"; }
  $alarm->{level}=$1;
  $alarm->{text}=$2;
  push @tina_errors,($alarm);
}
close FH2;
unlink $tmpfile;

if ($debug>1) { print "$nb_lines alarme (dont celle de test)\n"; }


# Analyse des alarmes
my $crit_text = "";
my $major_text = "";
my $minor_text = "";
# sort errors by severity
my @newarray = sort {$a->{level} <=> $b->{level}} (@tina_errors);
while (my $alarm = pop (@newarray)) {

  if ($alarm->{level}==0 && $alarm->{text} eq "test alarme") {
    $test_count++;

  } elsif ($alarm->{level}>2) {
    $crit_count++;
    $crit_text .= $alarm->{text}.", ";

  } elsif ($alarm->{level}==2) {
    $major_count++;
    $major_text .= $alarm->{text}.", ";

  } elsif ($alarm->{level}==1) {
    $minor_count++;
    $minor_text .= $alarm->{text}.", ";
  }
}

# Alarmes Non Identifiees
$other_count = $nb_lines - $test_count - $crit_count - $major_count - $minor_count;

# Construction du message pour Nagios
if ($nb_lines==0) { $returntext .= "La commande tina_shell n'a rien ecrit sur la sortie standard ; "; }
if ($nb_lines>0 && $test_count==0) { $returntext .= "L'alarme de test est introuvable ; "; }
if ($nb_lines==1 && $test_count==1) { $returntext = "Aucune alarme"; }
if ($other_count>0) { $returntext .= "$crit_count alarme(s) inconnue(s) ; "; }
if ($crit_count>10) { $returntext .= "$crit_count alarme(s) critique(s) => $crit_text ; "; }
if ($major_count>0) { $returntext .= "$major_count alarme(s) majeur(s) (seuils C:$crit_limit/W:$warn_limit) => $major_text ; "; }
if ($minor_count>0) { $returntext .= "$minor_count alarme(s) mineure(s)"; }

# Niveau d'alerte suivant les alarmes en presence
$returnvalue = 3; $returnstatus = "TINA-ALARM UNKNOWN";
if ($crit_count>10 || $major_count >= $crit_limit) {
  $returnvalue = 2; $returnstatus = "TINA-ALARM CRITICAL";

} elsif ($major_count >= $warn_limit || $other_count>0) {
  $returnvalue = 1; $returnstatus = "TINA-ALARM WARNING";
 
} elsif ($test_count==1) {
  $returnvalue = 0; $returnstatus = "TINA-ALARM OK";
}

# Le message 'performance data' de Nagios (utilise par les modules de graphe), seulement si le check s'est bien passe
if ($returnvalue!=3) {
  $returnperf = "| nb_alarmes_critiques=$crit_count, nb_alarmes_majeurs=$major_count, nb_alarmes_mineures=$minor_count, nb_alarmes_inconnues=$other_count";
}

print "$returnstatus - $returntext $returnperf\n";
exit $returnvalue;

