*clean: basemodule.Module renamed to basemodule.BaseModule.
[shinken.git] / shinken / modules / npcdmod_broker.py
blobcd2e25c767df198b6ad7cacf4d2cfd399781b1f0
1 #!/usr/bin/python
2 #Copyright (C) 2009 Gabes Jean, naparuba@gmail.com
3 # Gerhard Lausser, Gerhard.Lausser@consol.de
4 # Gregory Starck, g.starck@gmail.com
6 #This file is part of Shinken.
8 #Shinken is free software: you can redistribute it and/or modify
9 #it under the terms of the GNU Affero General Public License as published by
10 #the Free Software Foundation, either version 3 of the License, or
11 #(at your option) any later version.
13 #Shinken is distributed in the hope that it will be useful,
14 #but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 #GNU Affero General Public License for more details.
18 #You should have received a copy of the GNU Affero General Public License
19 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
22 #This Class is a plugin for the Shinken Broker. It's job is to write
23 #host and service perfdata to a file which can be processes by the
24 #npcd daemon (http://pnp4nagios.org). It is a reimplementation of npcdmod.c
27 import shutil
28 import os
29 import time
30 import re
33 from shinken.basemodule import BaseModule
36 #This text is print at the import
37 print "I am the nocdmod broker for pnp"
40 properties = {
41 'type' : 'npcdmod',
42 'external' : True,
43 'phases' : ['running'],
47 #called by the plugin manager to get a broker
48 def get_instance(plugin):
49 print "Get a npcd broker for plugin %s" % plugin.get_name()
50 config_file = getattr(plugin, 'config_file', None)
51 perfdata_spool_dir = getattr(plugin, 'perfdata_spool_dir', None)
52 perfdata_file = getattr(plugin, 'perfdata_file', '/usr/local/shinken/var/perfdata')
53 perfdata_spool_filename = getattr(plugin, 'perfdata_spool_filename', 'perfdata')
54 sleep_time = getattr(plugin, 'sleep_time', 15)
56 instance = Npcd_broker(plugin, config_file, perfdata_file, perfdata_spool_dir, perfdata_spool_filename, sleep_time)
57 return instance
60 #Class for the Npcd Broker
61 #Get broks and put them well-formatted in a spool file
62 class Npcd_broker(BaseModule):
63 def __init__(self, modconf, config_file, perfdata_file, perfdata_spool_dir, perfdata_spool_filename, sleep_time):
64 BaseModule.__init__(self, modconf)
65 self.config_file = config_file
66 self.perfdata_file = perfdata_file
67 self.perfdata_spool_dir = perfdata_spool_dir
68 self.perfdata_spool_filename = perfdata_spool_filename
69 self.sleep_time = sleep_time
70 self.process_performance_data = True # this can be reset and set by program_status_broks
71 self.processed_lines = 0
72 self.host_commands = {}
73 self.service_commands = {}
75 if self.config_file and not self.process_config_file():
76 print "npcdmod: An error occurred process your config file. Check your perfdata_file or perfdata_spool_dir"
77 raise
78 if not self.perfdata_spool_dir and not self.perfdata_file:
79 print "npcdmod: An error occurred while attempting to process module arguments"
80 raise
81 try:
82 # We open the file with line buffering, so we can better watch it with tail -f
83 self.logfile = open(self.perfdata_file, 'a', 1)
84 except:
85 print "could not open file %s" % self.perfdata_file
86 raise
89 #Get a brok, parse it, and put in in database
90 #We call functions like manage_ TYPEOFBROK _brok that return us queries
91 def manage_brok(self, b):
92 if self.process_performance_data or b.type in ('program_status', 'update_program_status'):
93 BaseModule.manage_brok(self, b)
95 # Handle the global process_performance_data setting. If it is not active, this module will not write
96 # any lines to the perfdata_file
97 def manage_program_status_brok(self, b):
98 if self.process_performance_data and not b.data['process_performance_data']:
99 self.process_performance_data = False
100 print "npcdmod: I can not work with disabled performance data in shinken.cfg."
101 print "npcdmod: Please enable it with 'process_performance_data=1' in shinken.cfg"
104 def manage_update_program_status_brok(self, b):
105 if self.process_performance_data and not b.data['process_performance_data']:
106 self.process_performance_data = False
107 print "npcdmod: I stop processing performance data"
108 elif not self.process_performance_data and b.data['process_performance_data']:
109 self.process_performance_data = True
110 print "npcdmod: I start processing performance data"
113 # also manage initial_broks, because of the check_command (which is not part of check_result_broks)
114 # save it in service_commands[host/service]
115 def manage_initial_host_status_brok(self, b):
116 self.host_commands[b.data['host_name']] = b.data['check_command'].call
119 def manage_initial_service_status_brok(self, b):
120 if not b.data['host_name'] in self.service_commands:
121 self.service_commands[b.data['host_name']] = {}
122 self.service_commands[b.data['host_name']][b.data['service_description']] = b.data['check_command'].call
125 # A host check has just arrived. Write the performance data to the file
126 def manage_host_check_result_brok(self, b):
127 line = "DATATYPE::HOSTPERFDATA\tTIMET::%d\tHOSTNAME::%s\tHOSTPERFDATA::%s\tHOSTCHECKCOMMAND::%s\tHOSTSTATE::%d\tHOSTSTATETYPE::%d\n" % (\
128 b.data['last_chk'],
129 b.data['host_name'],
130 b.data['perf_data'],
131 self.host_commands[b.data['host_name']],
132 b.data['state_id'],
133 b.data['state_type_id'])
134 self.logfile.write(line)
135 self.processed_lines += 1
138 # A service check has just arrived. Write the performance data to the file
139 def manage_service_check_result_brok(self, b):
140 line = "DATATYPE::SERVICEPERFDATA\tTIMET::%d\tHOSTNAME::%s\tSERVICEDESC::%s\tSERVICEPERFDATA::%s\tSERVICECHECKCOMMAND::%s\tSERVICESTATE::%d\tSERVICESTATETYPE::%d\n" % (\
141 b.data['last_chk'],
142 b.data['host_name'],
143 b.data['service_description'],
144 b.data['perf_data'],
145 self.service_commands[b.data['host_name']][b.data['service_description']],
146 b.data['state_id'],
147 b.data['state_type_id'])
148 self.logfile.write(line)
149 self.processed_lines += 1
152 def process_config_file(self):
153 try:
154 cfg_file = open(self.config_file)
155 for line in cfg_file:
156 mo = re.match(r'^(perfdata_spool_dir|perfdata_file|perfdata_spool_filename)\s*=\s*(.*?)\s*$', line)
157 if mo:
158 key, value = mo.groups()
159 setattr(self, key, value)
160 cfg_file.close()
161 return True
162 except:
163 return False
166 def rotate(self):
167 target = '%s/%s.%s' % (self.perfdata_spool_dir, self.perfdata_spool_filename, int(time.time()))
168 try:
169 self.logfile.close()
170 if os.path.exists(self.perfdata_file) and os.path.getsize(self.perfdata_file) > 0:
171 print "moving perfdata_file %s (%d lines) to %s" % (self.perfdata_file, self.processed_lines, target)
172 shutil.move(self.perfdata_file, target)
173 self.logfile = open(self.perfdata_file, 'a', 1)
174 except OSError:
175 "could not rotate perfdata_file to %s" % target
176 raise
177 self.processed_lines = 0
180 # Wait for broks and rotate the perfdata_file in intervals of 15 seconds
181 # This version does not use a signal-based timer yet. Rotation is triggered
182 # by a constant flow of status update broks
183 def main(self):
184 self.set_exit_handler()
185 self.rotate()
186 last_rotated = time.time()
187 while not self.interrupted:
188 b = self.to_q.get() # can block here :)
189 self.manage_brok(b)
190 if time.time() - last_rotated > self.sleep_time:
191 self.rotate()
192 last_rotated = time.time()
193 self.logfile.close()