|
@@ -35,7 +35,7 @@ our ( $FIFO, # fifo absolute filename (expanded from Irssi config)
|
|
|
$FIFO_HANDLE, # fifo filehandle for `open' et al.
|
|
|
$FIFO_TAG ); # fifo signal tag for `input_add'
|
|
|
|
|
|
-$VERSION = "0.3.0";
|
|
|
+$VERSION = "0.4.0";
|
|
|
%IRSSI = (
|
|
|
authors => 'asr',
|
|
|
contact => 'root@lautre.net',
|
|
@@ -46,6 +46,7 @@ $VERSION = "0.3.0";
|
|
|
changed => '20141006',
|
|
|
modules => ''
|
|
|
);
|
|
|
+my $PRINTF = "/usr/bin/printf";
|
|
|
|
|
|
# Put signals to irssi ###################################################
|
|
|
Irssi::settings_add_str($IRSSI{name}, # default fifo_remote_file
|
|
@@ -53,7 +54,8 @@ Irssi::settings_add_str($IRSSI{name}, # default fifo_remote_file
|
|
|
|
|
|
Irssi::settings_add_str("nagios_ack", "nagios_ack_channel", "#main_channel"); # see also etc/config.template
|
|
|
Irssi::settings_add_str("nagios_ack", "nagios_ack_nick", ""); # any user (none by default)
|
|
|
-Irssi::settings_add_str("nagios_ack", "nagios_command", "/var/lib/nagios3/rw/live");
|
|
|
+Irssi::settings_add_str("nagios_ack", "nagios_live", "/var/lib/nagios3/rw/live");
|
|
|
+Irssi::settings_add_str("nagios_ack", "nagios_command", "/var/lib/nagios3/rw/nagios.cmd");
|
|
|
#Irssi::command_bind( 'ack', \&nagios_ack );
|
|
|
#Irssi::command_bind( 'nagstat', \&nagios_status );
|
|
|
Irssi::command_bind( 'nagrefresh', \&nagios_query_status );
|
|
@@ -63,6 +65,7 @@ Irssi::command_bind( 'nagrefresh', \&nagios_query_status );
|
|
|
|
|
|
# To be used to check immediately / hosts-stats
|
|
|
my $nagioscmd = Irssi::settings_get_str("nagios_command");
|
|
|
+my $nagioslive = Irssi::settings_get_str("nagios_live");
|
|
|
my $nagios_ack_channel= Irssi::settings_get_str("nagios_ack_channel");
|
|
|
my $nagios_ack_nick= Irssi::settings_get_str("nagios_ack_nick");
|
|
|
|
|
@@ -117,13 +120,15 @@ my $state_to_color = {
|
|
|
# where is the memory leak.
|
|
|
my ($status_line);
|
|
|
my @match;
|
|
|
-my ($msg,$num);
|
|
|
-my ($message,$i);
|
|
|
+my $msg;
|
|
|
+my $i;
|
|
|
+my $stat;
|
|
|
+my $message;
|
|
|
my ($type,$data);
|
|
|
my ($d,$type,$host,$service,$state,$output);
|
|
|
-my ( $host, $svc, $state, $msg, $id );
|
|
|
+my ( $host, $svc, $state, $id );
|
|
|
|
|
|
-my ($server, $msg, $nick, $addr, $target);
|
|
|
+my ($server, $nick, $addr, $target);
|
|
|
my ( $param, $server, $window );
|
|
|
my (@issue, $issue);
|
|
|
|
|
@@ -133,7 +138,7 @@ my (@issue, $issue);
|
|
|
|
|
|
my $last_alert;
|
|
|
|
|
|
-my $DEBUG=Irssi::settings_get_str("nagios_ack_channel");
|
|
|
+my $DEBUG=Irssi::settings_get_str("nagios_ack_nick");
|
|
|
|
|
|
# Simple subs ############################################################
|
|
|
sub TRUE() { 1 } # some constants [perlsyn(1)
|
|
@@ -141,7 +146,7 @@ sub FALSE() { "" } # "Constant Functions"]
|
|
|
sub DEBUG(@) { print "%B", join(":", @_),"%n" }# DEBUG thingy
|
|
|
|
|
|
sub time2date($) {
|
|
|
- my ($d)=@_;
|
|
|
+ ($d)=@_;
|
|
|
return strftime("%d/%m/%y %H:%M", localtime($d));
|
|
|
}
|
|
|
|
|
@@ -166,6 +171,7 @@ sub nagios_inject;
|
|
|
sub format_alert_id($$$$); # ($Flag,$I,$state,$acked)
|
|
|
|
|
|
# Add alert to array / index
|
|
|
+# returns array (ID,char) : ID of new alert (-1 if not inserted) ; char in !,c,?,+,-.
|
|
|
sub insert_alert($$$$$$); #( $host, $svc, $state, $msg, $d )
|
|
|
|
|
|
|
|
@@ -194,6 +200,10 @@ sub nagios_query_status($);
|
|
|
##########################################################################
|
|
|
# Part D : Alert processing ##############################################
|
|
|
|
|
|
+# display a line resuming the alert
|
|
|
+# ($server,$chan,$alert_id,$prefix) -> alert_id from @ACKS
|
|
|
+sub display_alert($$$$);
|
|
|
+
|
|
|
# Search for services/host informations, and post them to IRC ############
|
|
|
# Delimiter : ; for logs; @ for direct nagios custom notification command
|
|
|
# one parameter : the logline to parse.
|
|
@@ -214,6 +224,9 @@ sub setup(); # [2004-08-13]
|
|
|
# Interact with IRC chan users
|
|
|
sub event_privmsg ($$$$);
|
|
|
|
|
|
+##########################################################################
|
|
|
+# References #############################################################
|
|
|
+##########################################################################
|
|
|
# REFERENCES
|
|
|
# ----------
|
|
|
#
|
|
@@ -239,12 +252,41 @@ sub parse_status() {
|
|
|
|
|
|
sub nagios_ack($$$) {
|
|
|
( $param, $server, $window ) = @_;
|
|
|
+ $msg='';
|
|
|
@issue = parse_status();
|
|
|
if (!@issue) {
|
|
|
#$window->print("Failed to parse last status: $last_alert");
|
|
|
}
|
|
|
- my $message = " ACK ".$param . join ' ', reverse @issue;
|
|
|
- Irssi::active_server->command('MSG ' . $DEBUG . $message);
|
|
|
+ # $host / sticky / notif / persistant / user
|
|
|
+ ($id,$message)=split " ",$param;
|
|
|
+ if (($id =~ /^#(\d+)/) && ($id <= scalar @ACKS)) {
|
|
|
+ $id=$1;
|
|
|
+ $i=time;
|
|
|
+ if ($ACKS[$id]->[5] == 1) {
|
|
|
+ # Already ACKed, print an error.
|
|
|
+ $msg = " ACK : impossible, c'est dejà fait" ;
|
|
|
+ display_alert($server,$nagios_ack_channel,$id,' '
|
|
|
+# format_alert_id(' ', $id, $ACKS[$id]->[2], $ACKS[$id]->[5])
|
|
|
+ );
|
|
|
+ } elsif ($ACKS[$id]->[1] ne "") {
|
|
|
+ $msg = " ACK ".$id." \"ACKNOWLEDGE_SVC_PROBLEM;$ACKS[$id]->[0];$ACKS[$id]->[1];2;0;1;nagiosadmin;$message\" $i > $nagioscmd";
|
|
|
+ Irssi::active_server->command('MSG ' . $DEBUG . " ".
|
|
|
+ `$PRINTF "[\%lu] ACKNOWLEDGE_SVC_PROBLEM;$ACKS[$id]->[0];$ACKS[$id]->[1];2;0;1;nagiosadmin;$message" $i> $nagioscmd`
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ $msg = " ACK ".$id." \"ACKNOWLEDGE_HOST_PROBLEM;$ACKS[$id]->[0];2;0;1;nagiosadmin;$message\" $i > $nagioscmd";
|
|
|
+ Irssi::active_server->command('MSG ' . $DEBUG . " ".
|
|
|
+ `$PRINTF "[\%lu] ACKNOWLEDGE_HOST_PROBLEM;$ACKS[$id]->[0];2;0;1;nagiosadmin;$message" $i > $nagioscmd`
|
|
|
+ );
|
|
|
+ }
|
|
|
+ Irssi::active_server->command('MSG ' . $nagios_ack_channel . $msg);
|
|
|
+ } else {
|
|
|
+ $server->command ( "msg ".$nagios_ack_channel. " Usage : !nagios ACK #<alert_num> <ack message to be sent to nagios>. Please validate first, with a !nagios list #<alert_num>");
|
|
|
+ display_alert($server,$nagios_ack_channel,$id,' '
|
|
|
+# format_alert_id(' ', $id, $ACKS[$id]->[2], $ACKS[$id]->[5])
|
|
|
+ ) if $id =~ /^(\d+)/ ;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
sub nagios_check($$$) {
|
|
@@ -254,7 +296,7 @@ sub nagios_check($$$) {
|
|
|
if (!@issue) {
|
|
|
#$window->print("Failed to parse last status: $last_alert");
|
|
|
}
|
|
|
- my $message = " CHECK ".$param . join ' ', reverse @issue;
|
|
|
+ $message = " CHECK ".$param . join ' ', reverse @issue;
|
|
|
Irssi::active_server->command('MSG ' . $DEBUG . $message);
|
|
|
# handle_alert($$$$$$$) { # $d,$type,$host,$state,$output,$service }
|
|
|
}
|
|
@@ -284,6 +326,7 @@ sub format_alert_id($$$$) {
|
|
|
|
|
|
# Add alert to array / index
|
|
|
sub insert_alert($$$$$$) {
|
|
|
+# returns ID of new alert ; -1 if not inserted.
|
|
|
#Irssi::print(">> On vire $host/$svc");
|
|
|
my $i;
|
|
|
my $acked;
|
|
@@ -298,10 +341,10 @@ sub insert_alert($$$$$$) {
|
|
|
if ($ACKS[$i]->[2] ne $state) {
|
|
|
# Same alert, but different level
|
|
|
$ACKS[$i]->[2]=$state;
|
|
|
- return format_alert_id('c', $i+1, $state,0);
|
|
|
+ return ($i+1,'c');
|
|
|
} else {
|
|
|
# Same alert
|
|
|
- return format_alert_id('!', $i+1, $state,0);
|
|
|
+ return ($i+1, '!');
|
|
|
# No need to display...
|
|
|
}
|
|
|
}
|
|
@@ -309,7 +352,7 @@ sub insert_alert($$$$$$) {
|
|
|
}
|
|
|
# New alert, insert.
|
|
|
push (@ACKS, [ $host, $svc, $state, $msg, $d, $acked ] );
|
|
|
- return format_alert_id('+',scalar @ACKS,$state,0);
|
|
|
+ return (scalar @ACKS,'+');
|
|
|
# Clear alert
|
|
|
} else {
|
|
|
# Irssi::print(">> On vire $host/$svc");
|
|
@@ -320,11 +363,11 @@ sub insert_alert($$$$$$) {
|
|
|
$ACKS[$i] = pop @ACKS;
|
|
|
$i=$#ACKS;
|
|
|
Irssi::print(">> found $i");
|
|
|
- return format_alert_id('-',$i+1,$state,1);
|
|
|
+ return (-1,'-');
|
|
|
}
|
|
|
$i++;
|
|
|
}
|
|
|
- return format_alert_id('?',0,$state,1);
|
|
|
+ return (-1,'?');
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -412,13 +455,13 @@ sub nagios_query_status($){
|
|
|
my @unixcat;
|
|
|
my $unixline;
|
|
|
my $acked;
|
|
|
- $nagioscmd = Irssi::settings_get_str("nagios_command");
|
|
|
+ $nagioslive = Irssi::settings_get_str("nagios_live");
|
|
|
foreach $acked (0,1) {
|
|
|
foreach $unixline ( `echo "GET services
|
|
|
-Columns: last_state_change host_alias display_name state plugin_output
|
|
|
+Columns: last_state_change host_name display_name state plugin_output
|
|
|
Filter: state > 0
|
|
|
Filter: acknowledged = $acked
|
|
|
-And: 2" | unixcat $nagioscmd` ) {
|
|
|
+And: 2" | unixcat $nagioslive` ) {
|
|
|
chomp $unixline;
|
|
|
($d,$host,$service,$state,$output)=split /;/,$unixline;
|
|
|
handle_alert($option,$d,'SERVICE',$host,$NagStates[$state+10],$output,$service,$acked);
|
|
@@ -429,10 +472,10 @@ And: 2" | unixcat $nagioscmd` ) {
|
|
|
return;
|
|
|
foreach $acked (0,1) {
|
|
|
foreach $unixline ( `echo "GET hosts
|
|
|
-Columns: last_state_change host_alias state plugin_output
|
|
|
+Columns: last_state_change host_name state plugin_output
|
|
|
Filter: state > 0
|
|
|
Filter: acknowledged = 0
|
|
|
-And: 2" | unixcat $nagioscmd` ) {
|
|
|
+And: 2" | unixcat $nagioslive` ) {
|
|
|
chomp $unixline;
|
|
|
($d,$host,$state,$output)=split /;/,$unixline;
|
|
|
handle_alert($option,$d,'HOST',$host,$NagStates[$state],$output,"",$acked);
|
|
@@ -444,6 +487,21 @@ And: 2" | unixcat $nagioscmd` ) {
|
|
|
##########################################################################
|
|
|
# Part D : Alert processing ##############################################
|
|
|
|
|
|
+sub display_alert($$$$){
|
|
|
+ my ($server,$chan,$alert_id,$prefix) = @_;
|
|
|
+ #Irssi::print("... $alert_id");
|
|
|
+ return unless defined $ACKS[$alert_id];
|
|
|
+# @ACKS; # [ hostname, service, state, plugin_output, last_state_change, ACKnowledged ] );
|
|
|
+# my ($server,$chan,$date,$prefix,$state,$acked,$hostname,$service,$output) = @_;
|
|
|
+ $prefix=format_alert_id($prefix,$alert_id,$ACKS[$alert_id]->[2],$ACKS[$alert_id]->[5]) ;
|
|
|
+ #format_alert_id(' ', $i, $K->[2], $K->[5]),
|
|
|
+ $server->command ( 'msg ' . $chan .
|
|
|
+ " NAGIOS ". time2date ($ACKS[$alert_id]->[4])." ".
|
|
|
+ $prefix. " ". $state_to_color->{$ACKS[$alert_id]->[2]}.$ACKS[$alert_id]->[0]."/".$ACKS[$alert_id]->[1].$C{Z}.
|
|
|
+ " / $ACKS[$alert_id]->[2]".($ACKS[$alert_id]->[5]?" Acked":"")." : $ACKS[$alert_id]->[3]"
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
# Search for services/host informations, and post them to IRC ############
|
|
|
# Delimiter : ; for logs; @ for direct nagios custom notification command
|
|
|
sub parse_nagios_log($){
|
|
@@ -493,19 +551,14 @@ sub handle_alert($$$$$$$$) { # $d,$type,$host,$state,$output,$service,acked
|
|
|
$renot{"$host:$service"} = time();
|
|
|
|
|
|
# HOST or SERVICE ?
|
|
|
- $id = insert_alert($host,$service,$state,$output,$d,$acked);
|
|
|
- $msg = "$id".$state_to_color->{$state} . "$host:$service".$C{Z}." is $state : $output";
|
|
|
- #Irssi::print( "%B>>%n $IRSSI{name} $msg", MSGLEVEL_CLIENTCRAP);
|
|
|
-
|
|
|
- $last_alert="NAGIOS - $host/$service is $state";
|
|
|
- $d=time2date($d);
|
|
|
- $message = " $d - $last_alert - $msg";
|
|
|
- # Silently ignore previously sent alerts
|
|
|
- return if $id =~ '\[!' ;
|
|
|
+ ($id,$stat) = insert_alert($host,$service,$state,$output,$d,$acked);
|
|
|
+
|
|
|
+ # Silently ignore previously sent/acked alerts
|
|
|
+ Irssi::print(">> $nagios_ack_channel,$d,$id,$state,$acked,$host,$service,$output");
|
|
|
+ return if $id == -1;
|
|
|
$nagios_ack_channel= Irssi::settings_get_str("nagios_ack_channel");
|
|
|
- Irssi::active_server->command('MSG ' . $nagios_ack_channel .
|
|
|
- " ".$message) unless ($option eq "silent");
|
|
|
- # Irssi::print( "%B>>%n $IRSSI{name} $msg", MSGLEVEL_CLIENTCRAP);
|
|
|
+ display_alert(Irssi::active_server,$nagios_ack_channel,$id,$stat),
|
|
|
+ unless ($option eq "silent");
|
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
@@ -538,9 +591,6 @@ sub event_privmsg($$$$) {
|
|
|
Irssi::print(">> $arg - $nagios_ack_channel - $target");
|
|
|
return if $target ne $nagios_ack_channel ;
|
|
|
|
|
|
- # !nagios [*] :
|
|
|
-
|
|
|
- # !nagios list [*] :
|
|
|
if ($arg =~ /^refresh ?(.*)/i) {
|
|
|
$arg=$1;
|
|
|
Irssi::print(">> $arg");
|
|
@@ -562,20 +612,21 @@ sub event_privmsg($$$$) {
|
|
|
# Do you search on pattern (whole database), or a list (reduced database) ?
|
|
|
my $grepto;
|
|
|
my $motif=$1;
|
|
|
+ $motif=s/^ack$/0\$/i;
|
|
|
+ $motif=s/^unack$/1\$/i;
|
|
|
$motif="" unless defined($motif) ;
|
|
|
my $search_unack=0;
|
|
|
$search_unack="1" if $motif eq "";
|
|
|
|
|
|
foreach $K (@ACKS) {
|
|
|
- my $grepto="@$K";
|
|
|
+ my $grepto="#$i @$K";
|
|
|
# just display alert fields, with colors.
|
|
|
# See ACKS fields organization
|
|
|
# Field 5 is "Alert has been previously acknowledged"
|
|
|
- $server->command ( "msg ".$nagios_ack_channel.
|
|
|
- " ". time2date ($K->[4])." ".
|
|
|
- format_alert_id(' ', $i, $K->[2], $K->[5]).
|
|
|
- " ". $state_to_color->{$K->[2]}.$K->[0]."/".$K->[1].$C{Z}.
|
|
|
- " / $K->[2]".($K->[5]?" Acked":"")." : $K->[3]"
|
|
|
+ # display_alert($server,$chan,$date,$prefix,$state,$acked,$hostname,$service,$output)
|
|
|
+ display_alert($server,$nagios_ack_channel,$i,' '
|
|
|
+ #format_alert_id(' ', $i, $K->[2], $K->[5]),
|
|
|
+ #$K->[2],$K->[5],$K->[0],$K->[1],$K->[3]
|
|
|
) if ( ($grepto =~ /$motif/i) || ($search_unack && ($K->[5]==0)) );
|
|
|
# Display only if : $motif is found, or $motif is empty, and alert is unack
|
|
|
$i++;
|
|
@@ -583,7 +634,7 @@ sub event_privmsg($$$$) {
|
|
|
}
|
|
|
elsif ($arg =~ /^help/i) {
|
|
|
$server->command ( "msg ".$nagios_ack_channel.
|
|
|
- " !nagios list [pattern] : liste des alertes nagios reçues ici");
|
|
|
+ " !nagios list [pattern] [ack/unack] : liste des alertes nagios reçues ici");
|
|
|
$server->command ( "msg ".$nagios_ack_channel.
|
|
|
" !nagios help : l'aide");
|
|
|
$server->command ( "msg ".$nagios_ack_channel.
|
|
@@ -596,6 +647,8 @@ sub event_privmsg($$$$) {
|
|
|
nagios_check($1,$server,undef);
|
|
|
} elsif ( $arg =~ /^ack ?(.*)/i ){
|
|
|
nagios_ack($1,$server,undef);
|
|
|
+ $server->command ( "msg ".$nagios_ack_channel.
|
|
|
+ " ".scalar @ACKS." alertes");
|
|
|
} else {
|
|
|
$server->command ( "msg ".$nagios_ack_channel.
|
|
|
" ".scalar @ACKS." alertes");
|
|
@@ -631,15 +684,3 @@ print CLIENTCRAP "%B>>%n $IRSSI{name} $VERSION (by $IRSSI{authors}) loaded";
|
|
|
|
|
|
|
|
|
1;
|
|
|
-
|
|
|
-##########################################################################
|
|
|
-# References #############################################################
|
|
|
-##########################################################################
|
|
|
-# REFERENCES
|
|
|
-# ----------
|
|
|
-#
|
|
|
-# This script is mainly adapted from 3 other scripts related to nagios :
|
|
|
-#
|
|
|
-# https://github.com/zorkian/nagios-irc-bot/blob/master/nagiosirc.pl
|
|
|
-# http://www.update.uu.se/~zrajm/programs/irssi-scripts/fifo_remote.pl-0.5
|
|
|
-# https://github.com/mikegrb/irssi-scripts/blob/master/nagios-ack.pl
|