#!/usr/bin/env perl

my $NAME="warnings.pl";

# check commandline arguments
#
my $cmd=shift;
if ($cmd eq "-p") { print_rows(@ARGV); }
elsif ($cmd eq "-c") { check_thresholds(@ARGV); }
else { helptext(); exit; }

sub check_thresholds {
  if ( ($#ARGV != 6) && ($#ARGV != 11) ) {
print "\nUSAGE: $NAME -c <module> <database> <row> <consolidation> <timespan> <lt|eq|gt> <threshold> [-m <> <> <> <>]\n\n";
    exit;
    }
  $module=shift;
  $db=shift;
  $row=shift;
  $consolidation=shift;
  $time=shift;
  $func=shift;
  $threshold=shift;


  open LINES,"rrdtool fetch ./modules/$module/rrd/$db.rrd -s -$time $consolidation|";
  @lines=<LINES>;
  close LINES;

  print @lines;

  $caught=0;
  $num=-1;
  $vmin=999999999999999999;
  $vmax=0;

  if ($func eq "gt") { $function="higher than"; }
  elsif ($func eq "eq") { $function="equal"; }
  elsif ($func eq "lt") { $function="lower than"; }

  foreach (@lines) {
    # first line contains data-row names
    if ($num == -1) {
      chomp;
      @names=split;
      $num++;
      next;
      }
    if ((! /nan/) && ( /:/)) {
      # process lines containing valid values
      chomp;
      $num++;
      @items=split;
      $val=@items[$row];
      $vsum+=$val;
      $vmin=$val if $vmin>$val;
      $vmax=$val if $vmax<$val;
      if (($func eq "gt") && ($val>$threshold)) { $caught++; }
      elsif (($func eq "eq") && ($val==$threshold)) { $caught++; }
      elsif (($func eq "lt") && ($val<$threshold)) { $caught++; }
      }
    }

  # check if there was at least one valid line
  if ($num > 0) { $vavg=$vsum/$num; } else { $vavg=-1; $num=-1; }

  if ($num == $caught) {
    my @message;
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $year+=1900;
    $mon++;
    $dow=("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")[$wday];
    if ($isdst) { $dst="(DST)"; } else { $dst=""; }
    $mday="0".$mday if $mday<10;
    $mon="0".$mon if $mon<10;
    $sec="0".$sec if $sec<10;
    $min="0".$min if $min<10;
    $hour="0".$hour if $hour<10;
  
    my @message=("HotSaNIC THRESHOLD WARNING!","","Date    : $dow, $year-$mon-$mday","Time    : $hour:$min:$sec $dst","Module  : $module","database: $db","data-row: ".@names[$row-1],"","","$consolidation value constantly $function $threshold over the last $time seconds.",(sprintf "minimum: %12.2f",$vmin),(sprintf "average: %12.2f",$vavg),(sprintf "maximum: %12.2f",$vmax),"");

    $cmd=shift;
    if ($cmd eq "-m") {
	    print "sending...\n";
      sendmail(@_,@message);
      }
    else { print join("\n",@message),"\n"; }
    }
  }

sub print_rows {
  if ($#ARGV != 1) {
    print "\nUSAGE: $NAME -p <module> <database>\n\n";
    exit;
    }
  $module=shift;
  $db=shift;
  open LINES,"rrdtool fetch ./modules/$module/rrd/$db.rrd -s -1 MAX|";
  ( $line=<LINES> ) =~ s/^\s*//g;
  close LINES;
  $n=1;
  print "Row numbers for $module - $db.rrd\n";
  foreach (split /\s+/,$line) { print $n++." -> $_\n"; }
  exit;
  }


sub sendmail {
  use Net::SMTP;
             
  my $SMTP_Host  = shift || "";
  my $account    = shift || "dummy";
  my $sender     = shift || "hotsanic-system";
  my $recipient  = shift || "admin";
  my @message = (@_);
  unshift @message,"From: HotSaNIC <$sender>","";
  unshift @message,"Subject: HotSaNIC threshold warning";
  
  # add line-breaks (\r\n)  to text
  @message = map { $_."\r\n" } @message;

  my $smtp = Net::SMTP->new( $SMTP_Host, Helo => $account, Debug => 0 );
  my $OK;
  
  $OK = $smtp->mail($sender);
  if (! $OK) { return "ERROR: sender unknown: \"$sender\""; }
  
  $OK = $smtp->recipient( $recipient );
  if (! $OK) { return "ERROR: recipient invalid: \"$recipient\""; }
  
  # Nachricht senden
  $OK = $smtp->data(\@message);
  if (! $OK) { return "ERROR: message could not be delivered: \"$!\""; }
  
  # Ordungsgemäss beim Server abmelden
  $OK = $smtp->quit();
  if (! $OK) { return "ERROR: could not close connection.\"$!\""; }
  }


sub helptext {
  print "
USAGE:

$NAME -c <module> <database> <row> <consolidation> <timespan> <lt|eq|gt> <threshold>
  check the given database for given events and print results to running shell.

$NAME -p <module> <database>
  print DB-internal names.

$NAME -c ... -m <SMTPhost> <SMTPaccount> <sender> <recipient>
  mails the results in the given way

$NAME -f config_file
  check all targets configured in config_file.  (not implemented yet!)


  <module>            name of the module to query (you have to be in the HotSaNIC main directory)
  
  <database>          name of the database to query

  <data-row-number>   number of the database-row
                      \"?\" to show row names

  [MAX|MIN|AVERAGE]   consolidation function of the data-row you like to query

  <timespan>          timespan backwards from now in seconds

  [lt|eq|gt]          threshold functions
                        lt -> test if values are less than <threshold>
			eq -> test if values are equal <threshold>
			gt -> test if values are greater than <threshold>

  <threshold>         threshold value

  example:

   $NAME -c traffic eth0 1 MAX 120 gt 100000
     generates a warning message if the incoming traffic (row 1) of the traffic on eth0 exceeded 100000 bytes/s over the last 2 minutes

   $NAME -c system cpu 4 MAX 120 lt 0.3
     generates a warning message if the idle-time (row 4) of your CPU was constantly lower than 30% over the last 2 minutes
\n";
  }

