Parcourir la source

Merge branch 'master' of ssh://code.ffdn.org:55555/asr/nagios-irssi

Gaétan RYCKEBOER il y a 10 ans
Parent
commit
95c86becb1
3 fichiers modifiés avec 292 ajouts et 33 suppressions
  1. 1 0
      README.md
  2. 60 33
      bin/nagios-fifo.pl
  3. 231 0
      bin/tweet.pl

+ 1 - 0
README.md

@@ -32,6 +32,7 @@ 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

+ 60 - 33
bin/nagios-fifo.pl

@@ -72,7 +72,7 @@ my %renot; # { "host" or "host:service" => time_last_notification }
 
 my @cmdqueue = ();
 my %ignore = ();
-my @ACKS;
+my @ACKS; # [ hostname, service, state, plugin_output, last_state_change, ACKnowledged ] );
 my %ACK_Ind;
 
 my %C = (
@@ -165,10 +165,10 @@ sub nagios_inject;
 # F : caracter to display (! : ; C : change ; + : new alert ; - : green flag ; ? : green but not found)
 # I : numeric ID
 # state : state string, from @NagStates or %state_to_color
-sub format_alert_id($$$); # ($Flag,$I,$state)
+sub format_alert_id($$$$); # ($Flag,$I,$state,$acked)
 
 # Add alert to array / index
-sub insert_alert($$$$$); #( $host, $svc, $state, $msg, $d )
+sub insert_alert($$$$$$); #( $host, $svc, $state, $msg, $d )
 
 
 ##########################################################################
@@ -203,7 +203,7 @@ sub parse_nagios_log($);
 
 # Use alert fields to print and insert it
 # timestamp, alert-type, hostname, state, plugin output, service_name
-sub handle_alert($$$$$$$);  # $d,$type,$host,$state,$output,$service
+sub handle_alert($$$$$$$$);  # $d,$type,$host,$state,$output,$service,$acked
 
 
 ##########################################################################
@@ -258,7 +258,7 @@ sub nagios_check($$$) {
     }
     my $message = " CHECK ".$param . join ' ', reverse @issue;
     Irssi::active_server->command('MSG ' . $DEBUG . $message);
-    #    handle_alert($$$$$$) { # $d,$type,$host,$state,$output,$service  }
+    #    handle_alert($$$$$$$) { # $d,$type,$host,$state,$output,$service  }
 }
 
 sub nagios_inject {
@@ -273,22 +273,23 @@ sub nagios_inject {
 #}
 
 # Return alert ID
-sub format_alert_id($$$) {
-	my ($Flag,$I,$state)=@_;
+sub format_alert_id($$$$) {
+	my ($Flag,$I,$state,$acked)=@_;
 	my $M=sprintf('%02d', scalar @ACKS % 100);
 	my $N=sprintf('%02d', $I % 100);
 	if (($I == 0) && (scalar @ACKS == 0)) {
-		return "[".$Flag.$Flag."  ]/$M ";
+		return "[".($acked==0?'!':' ').$Flag."  ]/$M ";
 	} else {
-		return "[".$Flag.$Flag.$state_to_color->{$state}.$N.$C{Z}."]/$M ";
+		return "[".($acked==0?'!':' ').$Flag.$state_to_color->{$state}.$N.$C{Z}."]/$M ";
 	}
 }
 
 # Add alert to array / index
-sub insert_alert($$$$$) {
+sub insert_alert($$$$$$) {
 	#Irssi::print(">> On vire $host/$svc");
-	my $i;
-	( $host, $svc, $state, $msg, $d ) = @_;
+	my $i; 
+	my $acked;
+	( $host, $svc, $state, $msg, $d, $acked ) = @_;
 	# ALERT
 	if ( $state eq 'WARNING' || $state eq 'CRITICAL' || $state eq 'UNKNOWN' || $state eq 'DOWN' ) {
 		while ($i <= $#ACKS) {
@@ -299,18 +300,18 @@ sub insert_alert($$$$$) {
 				if ($ACKS[$i]->[2] ne $state) {
 					# Same alert, but different level
 					$ACKS[$i]->[2]=$state;
-					return format_alert_id('C', $i, $state);
+					return format_alert_id('c', $i+1, $state,0);
 				} else {
 					# Same alert
-					return format_alert_id('!', $i, $state);
+					return format_alert_id('!', $i+1, $state,0);
 					# No need to display...
 				}
 			}
 			$i++;
 		}
 		# New alert, insert.
-		push (@ACKS, [ $host, $svc, $state, $msg, $d ] );
-		return format_alert_id('+',scalar @ACKS,$state);
+		push (@ACKS, [ $host, $svc, $state, $msg, $d, $acked ] );
+		return format_alert_id('+',scalar @ACKS,$state,0);
 	# Clear alert
 	} else {
 #		Irssi::print(">> On vire $host/$svc");
@@ -321,11 +322,11 @@ sub insert_alert($$$$$) {
 				$ACKS[$i] = pop @ACKS;
 				$i=$#ACKS;
 				Irssi::print(">> found $i");
-				return format_alert_id('-',$i+1,$state);
+				return format_alert_id('-',$i+1,$state,1);
 			}
 			$i++;
 		}
-		return format_alert_id('?',0,$state);
+		return format_alert_id('?',0,$state,1);
 	}
 }
 
@@ -412,27 +413,34 @@ sub nagios_query_status($){
 	my ($option)=@_;
 	my @unixcat;
 	my $unixline;
+	my $acked;
 	$nagioscmd = Irssi::settings_get_str("nagios_command");
+	foreach $acked (0,1) {
         foreach $unixline ( `echo "GET services
-Columns: last_state_change host_name display_name state plugin_output
+Columns: last_state_change host_alias display_name state plugin_output
 Filter: state > 0
-Filter: acknowledged = 0
+Filter: acknowledged = $acked 
 And: 2" | unixcat $nagioscmd` ) {
+		chomp $unixline;
 		($d,$host,$service,$state,$output)=split /;/,$unixline;
-		handle_alert($option,$d,'SERVICE',$host,$NagStates[$state+10],$output,$service);
+		handle_alert($option,$d,'SERVICE',$host,$NagStates[$state+10],$output,$service,$acked);
 		Irssi::print("%B>>%n $unixline", MSGLEVEL_CLIENTCRAP);
 	}
+	}
 
 	return;
+	foreach $acked (0,1) {
         foreach $unixline ( `echo "GET hosts
-Columns: last_state_change host_name state plugin_output
+Columns: last_state_change host_alias state plugin_output
 Filter: state > 0
 Filter: acknowledged = 0
 And: 2" | unixcat $nagioscmd` ) {
+		chomp $unixline;
 		($d,$host,$state,$output)=split /;/,$unixline;
-		handle_alert($option,$d,'HOST',$host,$NagStates[$state],$output,"");
+		handle_alert($option,$d,'HOST',$host,$NagStates[$state],$output,"",$acked);
 		Irssi::print("%B>>%n $unixline", MSGLEVEL_CLIENTCRAP);
 	}
+	}
 }
 
 ##########################################################################
@@ -454,14 +462,14 @@ sub parse_nagios_log($){
 	if (@match=$status_line =~ /\[?(\d+)\]? HOST ALERT: ([^@;]+)[@;]([^;@]+)[@;]HARD[@;][^;@]*[@;](.+)/) {
 	# HOST ########################
 		($d,$host,$state,$output)=@match;
-		handle_alert($option,$d,"HOST",$host,$state,$output,$service);
+		handle_alert($option,$d,"HOST",$host,$state,$output,$service,0);
 
 	# SERVICE #####################
 	} elsif (@match=$status_line =~ /\[?(\d+)\]? (\w+) ALERT: ([^;@]+)[@;]([^;@]+)[@;]([^;@]+)[@;]HARD[@;][^;@]*[@;](.+)/) {
 		($d,$type,$host,$service,$state,$output)=@match;
 
 		$service=~s/[^\w\d_-]/_/g;
-		handle_alert($option,$d,$type,$host,$state,$output,$service);
+		handle_alert($option,$d,$type,$host,$state,$output,$service,0);
 
 	# OTHER #######################
 	} elsif (@match=$status_line =~ /\[\d+\] (\w+) ALERT: (.*)/) {
@@ -477,16 +485,17 @@ sub parse_nagios_log($){
 }
 
 # Use alert fields to print and insert it
-sub handle_alert($$$$$$$) { # $d,$type,$host,$state,$output,$service
+sub handle_alert($$$$$$$$) { # $d,$type,$host,$state,$output,$service,acked
 	my $option;
+	my $acked;
 
         # Temporisation
-	($option,$d,$type,$host,$state,$output,$service)=@_;
+	($option,$d,$type,$host,$state,$output,$service,$acked)=@_;
 	next if exists $renot{"$host:$service"} && $renot{"$host:$service"} >= time() - 5;
 	$renot{"$host:$service"} = time();
 
 	# HOST or SERVICE ?
-	$id = insert_alert($host,$service,$state,$output,$d);
+	$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);
 
@@ -547,24 +556,42 @@ sub event_privmsg($$$$) {
 			$server->command ( "msg  ".$nagios_ack_channel.
 				" ".scalar @ACKS." alertes");
 		}
-		elsif ($arg =~ /^list/i) {
+		elsif ($arg =~ /^list ?(.*)/i) {
 			$server->command ( "msg  ".$nagios_ack_channel.
 				" ".scalar @ACKS." alertes");
 			my $i=0;
+
+			# Do you search on pattern (whole database), or a list (reduced database) ?
+			my $grepto;
+			my $motif=$1;
+			$motif="" unless defined($motif) ;
+			my $search_unack=0; 
+			$search_unack="1" if $motif eq "";
+
 			foreach $K (@ACKS) {
+				my $grepto="@$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.
-					" ". format_alert_id(' ',$i++,$K->[2]) ." ".$K->[0]." / $K->[1] / $K->[2] / $K->[3] / ".time2date $K->[4]);
+					" ". 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]"
+				) if ( ($grepto =~ /$motif/i) || ($search_unack && ($K->[5]==0)) );
+				# Display only if : $motif is found, or $motif is empty, and alert is unack
+				$i++;
 			}
 		}
 		elsif ($arg =~ /^help/i) {
 			$server->command ( "msg  ".$nagios_ack_channel.
-				" !nagios list : liste des alertes nagios reçues ici");
+				" !nagios list [pattern] : liste des alertes nagios reçues ici");
 			$server->command ( "msg  ".$nagios_ack_channel.
 				" !nagios help : l'aide");
 			$server->command ( "msg  ".$nagios_ack_channel.
-				" !nagios ack <#ALERTE> <message> : aquitte l'alerte");
+				" !nagios ack <#ALERTE> <message> TODO : aquitte l'alerte");
 			$server->command ( "msg  ".$nagios_ack_channel.
-				" !nagios check <#ALERTE> : recheck une alerte donnée (service/host)");
+				" !nagios check <#ALERTE> TODO : recheck une alerte donnée (service/host)");
 			$server->command ( "msg  ".$nagios_ack_channel.
 				" !nagios refresh [silent] : interroge le nagios pour avoir la liste de toutes les alertes");
 		} elsif ( $arg =~ /^check ?(.*)/i ){

+ 231 - 0
bin/tweet.pl

@@ -0,0 +1,231 @@
+# This script responds with a comment each time someone in the channel says "clockbot"
+#
+# This script requires you to have the text file "clockbot" in your /home/user/.irssi/ directory
+#
+# cat ~/signatures/sig-natures | sed 's/^%$/####/;'| tr '\n' ' ' | sed 's/[[:space:]]\+/ /g;s/[[:space:]]####[[:space:]]/\n/g;' > ../../clockbot
+
+use Irssi;
+
+use vars qw($VERSION %IRSSI);
+use POSIX qw(strftime); 
+
+use LWP::UserAgent;
+
+$VERSION = "1.2.2";
+
+%IRSSI = (
+    author => 'pleia2',
+    contact => 'lyz@princessleia.com ',
+    name => 'TC-14',
+    description => 'Protocol Droid, dedicated to Lautre.roots',
+    license => 'GNU GPL v2 or later',
+    url => 'http://www.lautre.net/',
+);
+open ( CLOCKPO, "<.irssi/quotes" ) or die "can't open clockbot:$!\n";
+chomp( @clockpo = <CLOCKPO> );
+close CLOCKPO;
+
+srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip -f`);
+
+my $changefile="/home/tc-14/var/changelog";
+my $last_tweet="";
+my $debug=0;
+my $bingo=0;
+my $last='';
+my $warn='';
+my @dad=("asr", "asr`", "asr_", "asr\\", "asr`_");
+
+my $timeout=30;
+my $warndate=time()-$timeout;
+
+Irssi::settings_add_str($IRSSI{name},          # default fifo_remote_file
+    'tc_chans', '#flood #starwars');     #
+Irssi::settings_add_str($IRSSI{name},          # default fifo_remote_file
+    'tc_admins', 'asr coin plop');     #
+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 @admin_chan=split m/ /, Irssi::settings_get_str("tc_admins");
+my $change=Irssi::settings_get_str("tc_changefile");
+
+sub in_array {
+	my ($arr,$search_for) = @_;
+	return grep {$search_for eq $_} @$arr;
+}
+
+
+sub gazouille {
+	my ( $user, $pass ) = qw ( lautrenet OoD0aiph );
+	my $message = $_[0];
+	my $url = 'http://identi.ca/api/statuses/update.xml';
+	my $ua = LWP::UserAgent->new ();
+	my $req = HTTP::Request->new ( POST => $url );
+
+	$req->headers->authorization_basic( $user, $pass );
+	$req->content("status=$message");
+	$req->content_type('application/x-www-form-urlencoded');
+	my $res = $ua->request ($req);
+
+	return $res->is_success;
+}
+
+sub event_privmsg {
+
+my ($server, $data, $nick, $mask) =@_;
+my ($target, $text) = $data =~ /^(\S*)\s:(.*)/;
+
+	#print ( "C:$target X:$text A:$admin D:$warndate L:$last W:$warn N:$nick D:$data" );
+
+	sub send_server($$$$) {
+		my ($action,$cible,$pseudo,$msg)=@_;
+		$server->command ( "msg $target SWarn C:$cible X:$action A:$admin D:$warndate L:$last W:$warn N:$pseudo T:$msg" ) unless ($debug == 0);
+		if (in_array(@chan,$target) || in_array(@admin_chan,$pseudo))
+		{
+			return;
+		} else {
+			if (($warndate + $timeout) < time()) {
+				$warn='';
+				$last='';
+			}
+			if (!($warn eq $pseudo)) {
+				if ($last eq $pseudo)  {
+					$server->command ( "msg $cible $pseudo: Chut.");
+					$warn=$nick;
+				} else {
+					$server->command ( "$action $cible $msg" );
+					$last=$nick;
+				}
+			} else {
+				$server->command ( "msg $cible $pseudo bloque pour $timeout" ) unless $debug=0;
+			}
+			$warndate=time();
+		}
+	}
+	
+	my $admin=0;
+
+	if (in_array(@chan,$target) || in_array(@admin_chan,$target))
+	{
+		return;
+	}
+
+	foreach $father (@dad) {
+		if ($father eq $nick) {
+			$admin=1;
+		}
+	}
+
+		if ( $text =~ /^!tweet\s*(.*)/) {
+			if (in_array(@admin_chan, $target)) { return ; }
+			if ($1 eq '') { $server->command("msg $target $nick: Usage: !tweet <<message>>"); } #$server->command ( "msg $target $nick: !tweet <<mesage>>" ); }
+			elsif ($1 eq 'changelog') {
+				open ( CHANGL, "tail -n1 $changefile |" ) or $server->command ( "msg $target $nick: fichier vide" );
+				#chomp( @temp = <CHANGL> );
+				#foreach $line (@temp) {
+				#	$last_tweet=$line;
+				#	if (gazouille ($line)) {
+				#		$clocky = $clockpo[rand @clockpo];
+				#		$server->command("msg $target Gazouilli posté! $clocky") unless ($nick =~ /edgard/i);	
+				#	}
+				#	else
+				#	{
+				#		$server->command ("msg $target $nick: Erreur lors du post du message");
+				#	}
+				#}
+				close ( CHANGL );
+			}
+			elsif ($1 eq 'last') {
+				$server->command("msg $target $nick: Last tweet was:");
+				$server->command("msg $target $nick: $last_tweet");
+			}
+			elsif (length($1)>139) { $server->command("msg $target $nick: Message trop long, plus de 139 caractères." ); }
+			else { 
+				# $server->command("msg $target Message: $nick |$1|");
+				$last_tweet=$1;
+				if (gazouille ($1)) {
+					$clocky = $clockpo[rand @clockpo];
+					$server->command("msg $target Gazouilli posté! $clocky") unless ($nick =~ /edgard/i);	
+				}
+				else
+				{
+					$server->command ("msg $target $nick: Erreur lors du post du message");
+				}
+			}
+		}
+		elsif ( $text =~ /^!changelog( .+)?/ ) {
+			if (in_array(@admin_chan,$target))
+			{ return; }
+			if ($1 eq '') { $server->command ( "msg $target $nick: !changelog (list|add) [<serveur> [<liste d'actions>]]" ); 
+			} elsif ($1 =~ /^ last( .+)?/) {
+				open ( CHANGL, "tail -n1 $changefile |" ) or $server->command ( "msg $target $nick: fichier vide" );
+				chomp( @temp = <CHANGL> );
+				foreach $line (@temp) {
+					$server->command ( "msg $target $nick: $line" );
+				}
+				close ( CHANGL );
+			} elsif ($1 =~ /^ list( .+)?/) {
+				undef @temp;
+				if ($1 eq '') {
+					$server->command ( "msg $target $nick: changelog total (20 lignes) en pv." );
+					open ( CHANGL, "tail $changefile |" ) or $server->command ( "msg $target $nick: fichier vide" );
+				} else {
+					my $pattern = $1;
+					$pattern =~ s/^ //;
+					$pattern =~ s/['"\$]/_/g;
+					$server->command ( "msg $target $nick: changelog pour '$pattern' (20 lignes) en pv" );
+					open ( CHANGL, "/home/tc-14/bin/tailgrep $changefile '$pattern' |" ) or $server->command ( "msg $target $nick: erreur de pattern ou fichier vide" );
+				}
+				chomp( @temp = <CHANGL> );
+				close CHANGL;
+				foreach $line (@temp) {
+					$server->command ( "msg $nick $line" );
+				}
+			} elsif ($1 =~ /^ add ([^ ]+) (.+)/) {
+				my $locdate=strftime "%d/%m/%Y %H:%M", localtime;;
+				open ( CHANGL, ">> $changefile" ) or $server->command ( "msg $target $nick: erreur de fichier... (O)" );
+				printf CHANGL "%s", "$locdate : $1 - $nick - $2\n" or $server->command ( "msg $target $nick: erreur de fichier... (W)" );
+
+				close CHANGL or $server->command ( "msg $target $nick: erreur de fichier... (C)" );
+				$clocky = $clockpo[rand @clockpo];
+				send_server("msg", $target, $nick, $clocky) unless ($nick =~ /edgard/i);
+				
+			} else {
+				$server->command ( "msg $target $nick: !changelog (list|add|last) [<serveur> [<liste d'actions>]]" );
+			}
+		}
+		elsif ( $text =~ /^!lastlog( .+)?/ ) {
+			if (in_array(@admin_chan,$target))
+			{ return; }
+			if ($1 eq '') { $server->command ( "msg $target $nick: !lastlog list [<liste d'actions>]" ); 
+			} elsif ($1 =~ /^ list( .+)?/) {
+				undef @temp;
+				if ($1 eq '') {
+					$server->command ( "msg $target $nick: lastlog total (20 lignes) en pv." );
+					open ( CHANGL, "tail $logfile |" ) or $server->command ( "msg $nick fichier vide" );
+				} else {
+					my $pattern = $1;
+					$pattern =~ s/^ //;
+					$pattern =~ s/['"\$]/_/g;
+					$server->command ( "msg $target $nick: lastlog pour '$pattern' (20 lignes) en pv." );
+					open ( CHANGL, "/homet/tc-14/bin/tailgrep $logfile '$pattern' |" ) or $server->command ( "msg $target $nick: erreur de pattern ou fichier vide" );
+				}
+				chomp( @temp = <CHANGL> );
+				close CHANGL;
+				foreach $line (@temp) {
+					$server->command ( "msg $nick $line" );
+				}
+			} else { $server->command ( "msg $target $nick: !lastlog list [<liste d'actions>]" ); 
+			}
+		}
+	if ($debug == 1) {
+		$server->command ( "msg $target D1 A:$admin L:$last W:$warn N:$nick B:$bingo" );
+		my $locdate=time()-$warndate;
+		$server->command ( "msg $target D2 W:$warndate T1:".time." T2:$locdate" );
+	}
+}
+
+Irssi::signal_add('event privmsg', 'event_privmsg');
+Irssi::signal_add("message public", "event_privmsg");
+
+print $IRSSI{"name"}." loaded $VERSION.";