2 # Copyright (c) 2010, Thomas Guyot-Sionnest
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are met:
8 # * Redistributions of source code must retain the above copyright notice,
9 # this list of conditions, and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above copyright notice,
11 # this list of conditions, and the following disclaimer in the
12 # documentation and/or other materials provided with the distribution.
13 # * Neither the name of the author of this software nor the name of
14 # contributors to this software may be used to endorse or promote products
15 # derived from this software without specific prior written consent.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
33 import supybot
.utils
as utils
34 import supybot
.world
as world
35 from supybot
.commands
import *
36 import supybot
.ircmsgs
as ircmsgs
37 import supybot
.plugins
as plugins
38 import supybot
.ircutils
as ircutils
39 import supybot
.callbacks
as callbacks
42 class NagiosLogger(callbacks
.Plugin
):
43 """This plugin receives alert notifications from Nagios and show them in
44 channel. The only configuration needed is running the client on a Nagios
45 server. See the client script for more details."""
50 # Notification type map
54 'ACKNOWLEDGEMENT': 'blue',
55 'FLAPPINGSTART': 'orange',
56 'FLAPPINGSTOP': 'green',
57 'FLAPPINGDISABLED': 'orange',
58 'DOWNTIMESTART': 'dark grey',
59 'DOWNTIMEEND': 'dark grey',
60 'DOWNTIMECANCELLED': 'orange',
67 'UNREACHABLE': 'orange',
74 def __init__(self
, irc
):
75 self
.__parent
= super(NagiosLogger
, self
)
76 self
.__parent
.__init
__(irc
)
78 self
.tp
= threading
.Thread(target
=self
.listener
)
79 self
.tp
.setDaemon(True)
82 def _get_irc(self
, network
):
83 for irc
in world
.ircs
:
84 if irc
.network
== network
:
87 def _get_person_or_channel(self
, irc
, personorchannel
):
88 if personorchannel
.startswith('#'):
89 for channel
in irc
.state
.channels
:
90 if channel
== personorchannel
:
93 return personorchannel
95 def _get_irc_and_target(self
, network
, personorchannel
):
96 target_irc
= self
._get
_irc
(network
)
97 if target_irc
is None:
98 raise Exception('Not on Network: %s' % network
)
99 target
= self
._get
_person
_or
_channel
(target_irc
, personorchannel
)
101 raise Exception('Not on Channel: %s' % personorchannel
)
102 return target_irc
, target
105 ctx
= zmq
.Context(1, 1)
106 socket
= zmq
.Socket(ctx
, zmq
.REP
)
107 #socket.bind(self.registryValue('ZmqURL')) # TODO: Doesn't work, help!
108 socket
.bind('tcp://0.0.0.0:12543')
116 # server(str)[Tab]notifi_type(str)[Tab]stateid(int)[Tab]host(str)
117 # [Tab]service(str)[Tab]message(str)
119 msgarray
= msg
.split('\t', 5)
122 stateid
= int(msgarray
[2])
123 hostname
= msgarray
[3]
124 service
= msgarray
[4]
125 message
= msgarray
[5]
127 self
.log
.error('NagiosLogger: Received message is invalid')
129 self
.log
.error('NagiosLogger: Received message is invalid '
132 self
.logEvent(server
, notype
, stateid
,
133 hostname
, service
, message
)
136 def logEvent(self
, server
, notype
, stateid
, hostname
, service
, message
):
137 # Get the IRC object and target
138 # TODO: Queue up messages if not on channel yet?
140 # TODO: add channel parameter
141 (irc
, tgt
) = self
._get
_irc
_and
_target
('NETWORK', '#CHANNEL')
143 # Likely cause is not being on channel yet
144 self
.log
.error('NagiosLogger: Getting context failed: %s' % (str(e
),))
147 # TODO: Wrap around color map, allowing unknown types
149 if service
is not '':
150 statemap
= {0: 'OK', 1: 'WARNING', 2: 'CRITICAL', 3: 'UNKNOWN'}
151 msg
= format('%s %s %s %s %s %s',
152 ircutils
.mircColor(server
, fg
='light grey'),
153 ircutils
.mircColor(ircutils
.bold(notype
+ ':'),
154 fg
=NagiosLogger
.notype_cmap
[notype
]),
155 ircutils
.mircColor(hostname
, fg
='dark grey'),
156 ircutils
.mircColor(ircutils
.underline(service
),
158 ircutils
.mircColor(ircutils
.bold(statemap
[stateid
] + ':'),
159 fg
=NagiosLogger
.state_cmap
[statemap
[stateid
]]),
160 ircutils
.mircColor(ircutils
.underline(message
), fg
='teal')
163 statemap
= {0: 'UP', 1: 'DOWN', 2: 'UNREACHABLE'}
164 msg
= format('%s %s %s %s %s',
165 ircutils
.mircColor(server
, fg
='light grey'),
166 ircutils
.mircColor(ircutils
.bold(notype
+ ':'),
167 fg
=NagiosLogger
.notype_cmap
[notype
]),
168 ircutils
.mircColor(hostname
, fg
='dark grey'),
169 ircutils
.mircColor(ircutils
.bold(statemap
[stateid
] + ':'),
170 fg
=NagiosLogger
.state_cmap
[statemap
[stateid
]]),
171 ircutils
.mircColor(ircutils
.underline(message
), fg
='teal')
174 self
.log
.error('NagiosLogger: Message contain invalid fields')
177 # TODO: Split lines and send multiple messages if necessary
179 tgt_msg
= ircmsgs
.privmsg(tgt
, msg
)
180 irc
.queueMsg(tgt_msg
)
181 except AssertionError:
182 self
.log
.error('NagiosLogger: Sending message failed, this may '
183 'be caused by invalid characters in it')
189 # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: