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
33 from shinken
.basemodule
import BaseModule
36 #This text is print at the import
37 print "I am the nocdmod broker for pnp"
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
)
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"
78 if not self
.perfdata_spool_dir
and not self
.perfdata_file
:
79 print "npcdmod: An error occurred while attempting to process module arguments"
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)
85 print "could not open file %s" % self
.perfdata_file
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" % (\
131 self
.host_commands
[b
.data
['host_name']],
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" % (\
143 b
.data
['service_description'],
145 self
.service_commands
[b
.data
['host_name']][b
.data
['service_description']],
147 b
.data
['state_type_id'])
148 self
.logfile
.write(line
)
149 self
.processed_lines
+= 1
152 def process_config_file(self
):
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
)
158 key
, value
= mo
.groups()
159 setattr(self
, key
, value
)
167 target
= '%s/%s.%s' % (self
.perfdata_spool_dir
, self
.perfdata_spool_filename
, int(time
.time()))
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)
175 "could not rotate perfdata_file to %s" % target
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
184 self
.set_exit_handler()
186 last_rotated
= time
.time()
187 while not self
.interrupted
:
188 b
= self
.to_q
.get() # can block here :)
190 if time
.time() - last_rotated
> self
.sleep_time
:
192 last_rotated
= time
.time()