aboutsummaryrefslogtreecommitdiff
path: root/hooks/nagios2psyc
blob: d67eb94d7583ba6b355ba71ebe4dafd25e641b5e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/perl
#
# nagios2psyc: psyc notification script for nagios
# written by Gabor Adam Toth <psyc://tgbit.net/~tg>
# based on git2psyc and rss4nagios.
#
# This script uses nagios environment variables,
# enable it by setting enable_environment_macros=1 in nagios.cfg
# (or set manually at the command_line with NAGIOS_FOO="$FOO$")
# for some reason i had to set an additional dummy env var to enable it:
#
# define command {
#	command_name    notify-by-psyc
#	command_line    NAGIOS_ENV=1 /usr/local/bin/nagios2psyc
# }
#
# CONFIGURATION
# - set address<x> directives in contact definitions
# - add notify-by-psyc command and set service/host_notification_commands
# - create a psyc.cfg in /etc/nagios (copy the part between =pod & =cut below)

=pod

# Options for nagios2psyc

# Use address<x> directives in contact definitions, write ADDRESS<x-1> here
# this will use address1:
$contact_directive = 'ADDRESS0';

$nagios_url = "https://nagios.example.org/cgi-bin/extinfo.cgi";

=cut

#use warnings;
use strict;
use URI::Escape;
use Socket;

{ package Settings; do "/etc/nagios/psyc.cfg" }

my $dir = uc $Settings::contact_directive;
my $target = $ENV{"NAGIOS_CONTACT$dir"};
#exit if contact has no psyc address defined
exit unless $target;

#use Data::Dumper;
#open LOG, '>>/tmp/nagios-psyc.log';
#print "target: $target\n\n";
#print LOG Dumper(\%ENV);
#close LOG;

my ($method,$data,$ack,%packet);
$ack = "ACKNOWLEDGEMENT" if $ENV{NAGIOS_NOTIFICATIONTYPE} eq "ACKNOWLEDGEMENT";

# variable names aren't all psyc conformant.. FIXME someday
if ($ENV{NAGIOS_SERVICESTATE}) {
	%packet = (
		_state		=> $ack || $ENV{NAGIOS_SERVICESTATE},
		_host		=> $ENV{NAGIOS_HOSTNAME},
		_desc		=> $ENV{NAGIOS_SERVICEDESC},
		_output 	=> $ENV{NAGIOS_SERVICEOUTPUT},
		_ackauthor	=> $ENV{NAGIOS_SERVICEACKAUTHOR},
		_ackcomment	=> $ENV{NAGIOS_SERVICEACKCOMMENT},
		_url		=> "${Settings::nagios_url}?type=2&host=$ENV{NAGIOS_HOSTNAME}&service=".uri_escape($ENV{NAGIOS_SERVICEDESC}),
	);
	$method = "_notice_service_" . lc $packet{_state};
	$data = "SERVICE [_state]: [_host] [_desc] - [_output] - [_url]";

} elsif ($ENV{NAGIOS_HOSTSTATE}) {
	%packet = (
		_state		=> $ack || $ENV{NAGIOS_HOSTSTATE},
		_host		=> $ENV{NAGIOS_HOSTNAME},
		_output 	=> $ENV{NAGIOS_HOSTOUTPUT},
		_ackauthor	=> $ENV{NAGIOS_HOSTACKAUTHOR},
		_ackcomment	=> $ENV{NAGIOS_HOSTACKCOMMENT},
		_url		=> "${Settings::nagios_url}?type=1&host=$ENV{NAGIOS_HOSTNAME}",
	);
	$method = '_notice_host_' . lc $packet{dt};
	$data = "HOST [_state]: [_host] - [_output] - [_url]";
} else {
	die "no host/service data";
}

# PSYC socket stuff:
my ($delim, $delimre);
if ($psycver >= 1.0) {
  $delim = '|';
  $delimre = qr/\|/;
} else {
  $delim = '.';
  $delimre = qr/\./;
}

my ($host, $port);
if ($target =~ m#^psyc://([\w.-]+)(?::(\d+))?#i) {
    $host = $1;
    $port = $2 || 4404;
} else {
    die "target invalid: $target";
}

my $iaddr = inet_aton($host) || die "no host: $host";
my $paddr = sockaddr_in($port, $iaddr);

# there is no real reason why we aren't using UDP here...
socket(S, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || die "socket: $!";

connect(S, $paddr) || die "connect: $!";
select S; $|=1; select STDOUT;

print S <<X;
$delim
X

if (defined($_ = <S>) && !/^$delim/) {
    die "Error while establishing circuit: invalid greeting";
}

while (defined($_ = <S>) && !/^$delim/) {
#	print if s/^=//;
}
#print "\n";
    
# THE MESSAGE:
print S ":_target\t$target\n\n";
print S ":$_\t$packet{$_}\n" for (keys %packet);
print S <<X;
$method
$data
$delim

_request_circuit_shutdown
$delim
X
# the _request_circuit_shutdown shouldn't be necessary for a simple
# one-way message submission, but psyced needs to become easier about that

# at this point we should wait for the other side to close the socket.. argl
close (S) || die "close: $!";

exit;