#!/usr/bin/perl -w


# check_prelude.pl by Andre Lammel <andre.lammel@swipe.de>
#
# check_prelude.pl - check for prelude events in an MySQL Database
#                    as used my libpreludedb.
#
# The program counts messages with severities medium and high.
# It then produces a WARNING or an CRITICAL based on the limits given
#
# Usage: check_prelude.pl <severity high max events> <severity medium max events>
#        check_prelude.pl --help gives this help
#
# Too many events with severity high   produce a CRITICAL
# Too many events with severity medium produce a WARNING
# All other results produce a OK
#
# License Information:
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
############################################################################


### load essential debugging stuff

#use Carp;
#use strict;
#use diagnostics;

### Load necessary modules

use DBI();

### database access

use constant DBNAME => "prelude";
use constant DBHOST => "127.0.0.1";
use constant DBUSER => "prelude";
use constant DBPASS => "mypassword";

### constants

use constant VERSION => "1.0";
use constant AUTHOR  => "Andre Lammel <andre.lammel\@swipe.de";

### severities and offset

use constant SEV_00 => "high";
use constant SEV_01 => "medium";
use constant OFFSET => -300;	# 5 minutes

### defaults if no args

use constant DEF_MAX_SEV_00 => 3;
use constant DEF_MAX_SEV_01 => 10;

### SQL query

my $QUERY = <<TOKEN;
SELECT COUNT(Prelude_Impact.description) 
         AS alert_count,
       Prelude_Impact.severity
  FROM 
       Prelude_DetectTime,
       Prelude_Impact 
  WHERE 
       Prelude_DetectTime._message_ident=Prelude_Impact._message_ident 
       AND 
       Prelude_DetectTime.time>="%s" 
       AND 
       ( 
         Prelude_Impact.severity="%s" 
	 OR 
	 Prelude_Impact.severity="%s" 
       )
  GROUP BY
       Prelude_Impact.severity;
TOKEN

### help

my $HELP = <<TOKEN;

check_prelude.pl v%s by %s

check_prelude.pl - check for prelude events in an MySQL Database
                   as used my libpreludedb.

The program counts messages with severities medium and high.
It then produces a WARNING or an CRITICAL based on the limits given

Usage: check_prelude.pl <severity high max events> <severity medium max events>                                                                 
       check_prelude.pl --help gives this help

Too many events with severity high   produce a CRITICAL 
Too many events with severity medium produce a WARNING 
All other results produce a OK

TOKEN

### declare methods

sub main ();
sub gettstamp ($);

### define methods

sub main ()
{
  ### make timestamp and declare hash
  ### for accumulated data
  
  my $stt = gettstamp( OFFSET );
  my $sum = {};

  my $MAX_SEV_00;
  my $MAX_SEV_01;

  ### take args from @ARGV

  if ( not defined $ARGV[0] )
  {
    $MAX_SEV_00 = DEF_MAX_SEV_00;
  }
  else
  {
    if( $ARGV[0] =~ /.*--help.*/g )
    {
      ### print help and exit if $ARGV[0] is --help

      printf( $HELP, VERSION, AUTHOR );
      return 0;
    }
    
    $MAX_SEV_00 = $ARGV[0];
  }

  ### set defaults, if no args

  if( not defined $ARGV[1] )
  {
    $MAX_SEV_01 = DEF_MAX_SEV_01;
  }
  else
  {
    $MAX_SEV_01 = $ARGV[1];
  }

  ### build database dsn and query

  my $dsn = sprintf( "DBI:mysql:database=%s;host=%s", DBNAME, DBHOST );
  my $qry = sprintf( $QUERY, $stt, SEV_00, SEV_01 );

  ### connect to database and prepare query

  my $dbh = DBI->connect ( $dsn, DBUSER, DBPASS ) or die $!;
  my $sth = $dbh->prepare( $qry ) or die $!;

  ### execute query

  $sth->execute() or die $!;

  ### walk through results and accumulate data

  RESULT:
  while ( my $ref = $sth->fetchrow_hashref() )
  {
    if ( $ref->{severity} =~ /${\SEV_00}/ )
    {
      $sum->{SEV_00} = $ref->{alert_count};
      next RESULT;
    }
    elsif ( $ref->{severity} =~ /${\SEV_01}/ )
    {
      $sum->{SEV_01} = $ref->{alert_count};
      next RESULT;
    }
  }
  
  ### finish database query

  $sth->finish();

  ### set defaults if query got no data

  if( not defined $sum->{SEV_00} )
  {
    $sum->{SEV_00} = 0;
  }

  if( not defined $sum->{SEV_01} )
  {
    $sum->{SEV_01} = 0;
  }

  ### build sum from all events

  $sum->{SUM} = $sum->{SEV_00} + $sum->{SEV_01};

  ### build nagios messages

  if ( $sum->{SEV_00} >= $MAX_SEV_00 )
  {
    printf( "PRELUDE CRITICAL: %s >= %s ( %s = %s AND %s = %s )\n", SEV_00, $MAX_SEV_00, SEV_00, $sum->{SEV_00}, SEV_01, $sum->{SEV_01} );
  }
  elsif ( $sum->{SEV_01} >= $MAX_SEV_01 )
  {
    printf( "PRELUDE WARNING: %s >= %s ( %s = %s AND %s = %s )\n", SEV_01, $MAX_SEV_01, SEV_00, $sum->{SEV_00}, SEV_01, $sum->{SEV_01} );
  }
  else
  {
    printf( "PRELUDE OK: ( %s = %s AND %s = %s )\n", SEV_00, $sum->{SEV_00}, SEV_01, $sum->{SEV_01} );
  }

  ### and return.

  return 0;
}

sub gettstamp ($)
{
  my $offset = shift;
  my $tstamp = undef;
  
  my $time   = ( time() + $offset );

  # make timestamp for logging from time/localtime

  my ( $sec, $min, $hour, $mday, $mon, $year, undef, undef, undef ) = localtime( $time );
  $year += 1900;
  $mon++;
  
  $tstamp = sprintf( '%04u-%02u-%02u %02u:%02u:%02u', $year, $mon, $mday, $hour, $min, $sec );

  return $tstamp;
}

### call program

main();

### EOF
