Parcourir la source

Add ack (to nagios) ability -- ASR

Gaétan RYCKEBOER il y a 10 ans
Parent
commit
5d955d8e94
6 fichiers modifiés avec 126 ajouts et 64 suppressions
  1. 22 0
      CHANGELOG
  2. 1 1
      INSTALL
  3. 2 4
      README.md
  4. 96 55
      bin/nagios-fifo.pl
  5. 3 3
      bin/tweet.pl
  6. 2 1
      etc/config.template

+ 22 - 0
CHANGELOG

@@ -0,0 +1,22 @@
+v0.1.0 - 29-09-2014
+asr - initial design : simple log parser from nagios log
+      built from 2 nagios bots, and a fifo irssi command bot.
+
+v0.2.0 - 04-10-2014
+asr - Add function to load alerts from nagios mk_livestatus
+
+v0.2.1 - 05-10-2014
+asr - Documentation, cosmetic, and git import
+
+v0.2.2 - 06-10-2014
+asr - Code rewriting, functiOn name cleansing
+
+v0.3.0 - 08-10-2014
+asr - Add ability to check patterns accros acked or unacked alerts
+
+v0.4.0 - 09-10-2014
+asr - Add ACK command to acknowledge alerts. _Will_break_configuration_file_
+      (mixed names between nagios_live, added, and nagios_command, previously refering
+      to livestatus fifo today renames nagios_live)
+asr - Change HOST ALIAS to HOST NAME for nagios services. _will_break_previous_nagios_configuration_file_
+

+ 1 - 1
INSTALL

@@ -14,7 +14,7 @@ define command{
 
 define command{
         command_name    notify-service-by-irssi
-        command_line    /usr/local/bin/nagios-irssi.pl $CONTACTPAGER$ "[$LASTSERVICESTATECHANGE$] SERVICE ALERT: $HOSTALIAS$@$SERVICEDESC$@$SERVICESTATE$@HARD@1@$SERVICEOUTPUT$"
+        command_line    /usr/local/bin/nagios-irssi.pl $CONTACTPAGER$ "[$LASTSERVICESTATECHANGE$] SERVICE ALERT: $HOSTNAME$@$SERVICEDESC$@$SERVICESTATE$@HARD@1@$SERVICEOUTPUT$"
 }
 
 Add to /etc/nagios3/<placeholder>.cfg

+ 2 - 4
README.md

@@ -32,11 +32,9 @@ Using the bots
 
 Commands allowed by *nagios-fifo.pl* / Nagios module :
 The nagios bot is designed to work with nagios notifications, via commands.cfg configuration file.
-- `!nagios list [PATTERN]` : list of received alerts
-- `!nagios list` : list of received alerts
 - `!nagios help` : l'aide
-- `!nagios ack <#ALERT> <message>` : ACK the alert
-- `!nagios check <#ALERT>` : recheck any alert (service/host)
+- `!nagios ack #<ALERT> <message>` : ACK the alert
+- `!nagios check <#ALERT>`(todo) : recheck any alert (service/host)
 - `!nagios refresh [silent]` : request nagios livestatus and import all unack alerts
 
 Commands allowed by *tc-14.pl* / Dumb module :

+ 96 - 55
bin/nagios-fifo.pl

@@ -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

+ 3 - 3
bin/tweet.pl

@@ -11,12 +11,12 @@ use POSIX qw(strftime);
 
 use LWP::UserAgent;
 
-$VERSION = "1.2.2";
+$VERSION = "1.3.0";
 
 %IRSSI = (
     author => 'pleia2',
     contact => 'lyz@princessleia.com ',
-    name => 'TC-14',
+    name => 'TC-14 Tweet',
     description => 'Protocol Droid, dedicated to Lautre.roots',
     license => 'GNU GPL v2 or later',
     url => 'http://www.lautre.net/',
@@ -45,7 +45,7 @@ Irssi::settings_add_str($IRSSI{name},          # default fifo_remote_file
 Irssi::settings_add_str($IRSSI{name},          # default fifo_remote_file
     'tc_changefile', '/home/tc-14/var/last.log');     #
 
-my @chan=split m/ /, Irssi::settings_get_str("tc_chan");
+my @chan=split m/ /, Irssi::settings_get_str("tc_chans");
 my @admin_chan=split m/ /, Irssi::settings_get_str("tc_admins");
 my $change=Irssi::settings_get_str("tc_changefile");
 

+ 2 - 1
etc/config.template

@@ -283,7 +283,8 @@ settings = {
     autorejoin_channels = "#main_channel";
     nagios_ack_channel = "#main_channel"
     nagios_ack_nick = ""
-    nagios_command = "/var/lib/nagios3/rw/live"
+    nagios_command = "/var/lib/nagios3/rw/nagios.cmd"
+    nagios_live = "/var/lib/nagios3/rw/live"
     fifo_remote_file = "/home/tc-14/var/nagios-fifo"
 }
   };