File send_irc_message of Package nagios-eventhandlers-send_mail
#!/usr/bin/perl
#
# Copyright (C) 2012 SUSE Linux Products GmbH
#
# 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.,
# 51 Franklin Street,
# Fifth Floor,
# Boston, MA 02110-1301,
# USA.
#
use strict;
use warnings;
use Carp;
use Config::IniFiles;
use English qw( -no_match_vars );
use Getopt::Long;
use Pod::Usage;
use URI::Escape;
our $conf={
VERSION => '0.1.3',
PROGNAME => 'send_irc_message',
config => '/etc/nagios/send_irc_message.cfg',
debug => 0,
logfile => '/var/log/nagios/send_irc_message.log',
netcat => '/usr/bin/netcat',
printf => '/usr/bin/printf',
loglevel => 1,
servicealert => 0,
acknowledgement => 0,
version => 0,
};
our @config_options=qw(
irc_bot_host
irc_bot_channel
irc_bot_port
nagios_url
timeout
logfile
loglevel
debug
);
our @needed=qw(
irc_bot_host
irc_bot_channel
irc_bot_port
nagios_url
timeout
logfile
);
my $print_help=0;
#######################################################################
## Function Area
#######################################################################
sub logfile {
my ($action,$config_ref)=@_;
if (!defined($config_ref->{'loglevel'}) || $config_ref->{'loglevel'} eq ""){
$config_ref->{'loglevel'}=0;
}
if (("$action" eq "open" ) || ("$action" eq "new" )) {
open (my $fh, ">>$config_ref->{'logfile'}") or croak "Couldn't open ".$config_ref->{'logfile'}." !\n";
flock($fh,2) or croak "Can't get lock for $config_ref->{'logfile'} !\n";
return $fh;
} else {
close $config_ref->{'logfile_fh'} or croak("Could not close filehandle $config_ref->{'logfile_fh'}\n");
}
}
sub LOG {
my ($message,$level,$config_ref)=@_;
my $time = localtime(time);
my $fh=$config_ref->{'logfile_fh'};
if ($level <= $config_ref->{'loglevel'}){
print $fh "$time [".$config_ref->{'PROGNAME'}."] : $message\n" or croak("Could not write to logfile\n");
}
print STDERR "DEBUG: $message\n" if ($config_ref->{'debug'});
}
sub check_ini_section($$$){
my ($iniref,$name,$needed_ref)=@_;
foreach my $needed (@$needed_ref){
if (!defined($iniref->val("$name","$needed"))){
return "$needed";
}
}
return 0
}
sub cleanup_and_exit($$){
my ($conf,$exitcode)=@_;
logfile('close',$conf);
exit $exitcode;
}
sub sendmsg($$){
my($conf,$ini)=@_;
my $timeout=$ini->val('global','timeout');
my $irchost=$ini->val('global','irc_bot_host');
my $ircchannel="#".$ini->val('global','irc_bot_channel');
my $ircport=$ini->val('global','irc_bot_port');
my $debug=$conf->{'debug'};
my $message='';
my $url=$ini->val('global','nagios_url');
my $host=uri_escape($conf->{'hostname'});
# Create correct URL
if ($conf->{'servicealert'}){
my $service=uri_escape($conf->{'servicename'});
$url.="?type=2&host=".$host."&service=".$service;
}
else {
$url.="?type=1&host=".$host;
}
# Problem acknowledged ?
if ($conf->{'acknowledgement'}){
if ($conf->{'servicealert'}){
$message="$conf->{'notificationtype'} ($conf->{'servicename'} on $conf->{'hostname'}) acknowledged by $conf->{'authorname'}: $conf->{'comment'}";
}
else {
$message="$conf->{'notificationtype'} ($conf->{'hostname'}) acknowledged by $conf->{'authorname'}: $conf->{'comment'}";
}
}
elsif ($conf->{'servicealert'}){
# Service Problem
$message="$conf->{'notificationtype'}: $conf->{'servicename'} on $conf->{'hostname'} - $conf->{'output'} ; See $url";
}
else {
# Host Problem
$message="$conf->{'notificationtype'}: $conf->{'hostname'} - $conf->{'output'} ; See $url";
}
# send out the message
my $status = system("$conf->{'printf'} \"%b\" \"$ircchannel $message\" | $conf->{'netcat'} -w $timeout $irchost $ircport");
# log output, if something goes wrong
if (($status >>=8) != 0){
LOG("Failed to run $conf->{'netcat'}",1,$conf);
}
else {
# just log if the user wants it
LOG("Sent out: $ircchannel $message",4,$conf);
}
}
sub print_version($){
my ($conf)=@_;
print "$conf->{'PROGNAME'} v$conf->{'VERSION'}\n";
print "This script come with ABSOLUTELY NO WARRANTY. You may redistribute\n";
print "copies of the plugins under the terms of the GNU General Public License.\n";
print "For more information about these matters, see the file named COPYING.\n";
}
#######################################################################
## Main Area
#######################################################################
Getopt::Long::Configure('bundling');
GetOptions( "h|help" => \$print_help,
"c|config=s" => \$conf->{'config'},
"d|debug" => \$conf->{'debug'},
"v|version" => \$conf->{'version'},
"n|notificationtype=s" => \$conf->{'notificationtype'}, # $NOTIFICATIONTYPE$
"H|hostname=s" => \$conf->{'hostname'}, # $HOSTNAME$
"S|servicename=s" => \$conf->{'servicename'}, # $SERVICEDESC$
"a|authorname=s" => \$conf->{'authorname'}, # $SERVICEACKAUTHORNAME$, $HOSTACKAUTHORNAME$
"c|comment=s" => \$conf->{'comment'}, # $SERVICEACKCOMMENT$, $HOSTACKCOMMENT$
"s|state=s" => \$conf->{'state'}, # $SERVICESTATE$, $HOSTSTATE$
"o|output=s" => \$conf->{'output'} # $SERVICEOUTPUT$, $HOSTOUTPUT$
) or pod2usage(2);
pod2usage( -exitstatus => 0,
-verbose => 1, # 2 to print full pod
) if $print_help;
if ($conf->{'version'}){
print_version($conf);
exit 0;
}
if ( ! -f "$conf->{'config'}"){
print STDERR "$conf->{'config'} not found or not readable\n";
exit 1;
}
my $ini = new Config::IniFiles( -file => "$conf->{'config'}",
-default => "global",
-allowcontinue => 1);
if( ! $ini ){
croak("Couldn't open $conf->{'config'} : $!\n");
}
$conf->{'logfile'}=$ini->val('global','logfile') if $ini->val('global','logfile');
$conf->{'loglevel'}=$ini->val('global','loglevel') if $ini->val('global','loglevel');
my $logfile_ref=logfile('open',$conf);
$conf->{'logfile_fh'}=$logfile_ref;
foreach my $section ( $ini->Sections() ){
my $res=check_ini_section($ini,$section,\@needed);
if ($res){
LOG("Needed element $res not found in $section from $conf->{'config'} - skipping",2,$conf);
next;
}
}
# first check, if we have the absolute minimum to send out IRC notifications
if (not defined $conf->{'hostname'} or $conf->{'hostname'} eq ''){
LOG("Option -H (--hostname) not defined",1,$conf);
$conf->{'hostname'}='UNDEFINED';
}
if (not defined $conf->{'notificationtype'} or $conf->{'notificationtype'} eq ''){
LOG("Option -n (--notificationtype) not defined",1,$conf);
$conf->{'notificationtype'}='UNDEFINED';
}
if (not defined $ini->val('global','irc_bot_channel') or $ini->val('global','irc_bot_channel') eq ''){
LOG("Config option irc_bot_channel not defined in config - this will not produce any output",1,$conf);
}
if (not defined $conf->{'state'} or $conf->{'state'} eq ''){
LOG("Option -s (--state) not defined",1,$conf);
$conf->{'state'}='UNDEFINED';
}
if (not defined $conf->{'output'} or $conf->{'output'} eq ''){
LOG("Option -o (--output) not defined",1,$conf);
$conf->{'output'}='UNDEFINED';
}
if (defined $conf->{'servicename'} and $conf->{'servicename'} ne ''){
$conf->{'servicealert'}=1;
}
if (defined $conf->{'authorname'} and $conf->{'authorname'} ne ''){
$conf->{'acknowledgement'}=1;
}
if ($conf->{'notificationtype'} eq 'ACKNOWLEDGEMENT'){
$conf->{'acknowledgement'}=1;
}
if ($conf->{'debug'}){
use Data::Dumper;
print STDERR "Config:\n".Data::Dumper->Dump([$conf])."\n";
print STDERR "Ini:\n".Data::Dumper->Dump([$ini])."\n";
}
sendmsg($conf,$ini);
cleanup_and_exit($conf,0);
__END__
=head1 Send Nagios IRC notifications
Commandline tool for sending Nagios notifications via IRC Bot.
=head1 SYNOPSIS
./send_irc_message <OPTIONS>
Example of a service problem/acknowledgement:
./send_irc_message \
--config "/etc/nagios/send_irc_message.cfg" \
--notificationtype "$NOTIFICATIONTYPE$" \
--state "$SERVICESTATE$" \
--hostname "$HOSTNAME$" \
--output "$SERVICEOUTPUT$" \
--servicename "$SERVICEDESC$" \
--authorname "$SERVICEACKAUTHORNAME$" \
--comment "$SERVICEACKCOMMENT$"
Example of a host problem/acknowledgement:
./send_irc_message \
--config "/etc/nagios/send_irc_message.cfg" \
--notificationtype "$NOTIFICATIONTYPE$" \
--state "$HOSTSTATE$" \
--hostname "$HOSTNAME$" \
--output "$HOSTOUTPUT$" \
--authorname "$HOSTACKAUTHORNAME$" \
--comment "$HOSTACKCOMMENT$"
Options:
-c <file> | --config <file>
-H <host> | --hostname <host>
-S <service> | --servicename <host>
-n <notificationtype> | --notificationtype <notificationtype>
-a <authorname> | --authorname <authorname>
-c <comment> | --comment <comment>
-s <state> | --state <state>
-o <output> | --output <output>
-h | --help
-d | --debug
=head1 OPTIONS
=over 8
=item B<--config> F<file>
Use configfile F<file> instead of default F</etc/nagios/send_irc_message.cfg>. This config file is a standard ini-file and
can contain the following values:
[global]
# please fill in at least these settings:
irc_bot_host=localhost
irc_bot_channel=nagios-admin # please do NOT use a '#' here, the script will add this for you
irc_bot_port=5050
nagios_url=https://$nagioshost/nagios/cgi-bin/extinfo.cgi
timeout=1
logfile=/var/log/nagios/send_irc_message.log
# those settings are optional:
loglevel=2
debug=0
=item B<--hostname> F<HOST>
Same as $HOSTNAME$ in Nagios.
(Example: "myhost.example.com")
=item B<--servicename> F<SERVICEDESC>
Same as $SERVICEDESC$ in Nagios.
(Example: "MySQL Service")
=item B<--notificationtype> -F<NOTIFICATIONTYPE>
Same as $NOTIFICATIONTYPE$ in Nagios.
(Example: "PROBLEM")
=item B<--authorname> F<author>
Same as $SERVICEACKAUTHORNAME$ resp. $HOSTACKAUTHORNAME$ in Nagios.
(Example: "Nagios Admin")
=item B<--comment> F<comment>
Same as $SERVICEACKCOMMENT$ resp. $HOSTACKCOMMENT$ in Nagios.
(Example: "too late to fix")
=item B<--state> F<state>
Same as $SERVICESTATE$ resp. $HOSTSTATE$ in Nagios.
(Example: "CRITICAL")
=item B<--output> F<output>
Same as $SERVICEOUTPUT$ resp. $HOSTOUTPUT$ in Nagios.
(Example: "Cant connect to local MySQL server")
=item B<nagios_url> L<https://$nagioshost/nagios/cgi-bin/extinfo.cgi>
URL to extinfo.cgi - the rest will be filled automatically with the given values above.
(Example: "https://nagios.example.com/nagios/cgi-bin/extinfo.cgi")
=back
=head1 DESCRIPTION
Instead of using the standard printf commandline given by Nagios, you can use this script to generate
notification IRC messages via an IRC-Bot together with Nagios.
We recommend the use of Supybot + supybot-notify plugin. The Bot can run on any other host that is
reachable by your Nagios server and has the desired port open for the communication.
This script will take care of unset variables and adds the ability to format the output in your way.
=head1 COPYRIGHT
=over 4
=item Copyright 2012 Lars Vogdt <lrupp@suse.de>.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
=back
=cut