*Some changes to the jenkins files for a code qualiy test
[shinken.git] / shinken / basemodule.py
blobd07ccd8f2fc8fe9f3668e52417a11d5f38487efc
1 # -*- coding: utf-8 -*-
2 #Copyright (C) 2009 Gabes Jean, naparuba@gmail.com
4 #This file is part of Shinken.
6 #Shinken is free software: you can redistribute it and/or modify
7 #it under the terms of the GNU Affero General Public License as published by
8 #the Free Software Foundation, either version 3 of the License, or
9 #(at your option) any later version.
11 #Shinken is distributed in the hope that it will be useful,
12 #but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 #GNU Affero General Public License for more details.
16 #You should have received a copy of the GNU Affero General Public License
17 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
20 """ This python module contains the class BaseModule that shinken modules will subclass """
23 import os
24 import signal
25 from multiprocessing import Queue
29 ## TODO: use a class for defining the module "properties" instead of plain dict ?? Like:
30 """
31 class ModuleProperties(object):
32 def __init__(self, type, phases, external=False)
33 self.type = type
34 self.phases = phases
35 self.external = external
36 """
37 ## and have the new modules instanciate this like follow :
38 """
39 properties = ModuleProperties('the_module_type', the_module_phases, is_mod_ext)
40 """
41 ##
42 """ The `properties´ dict defines what the module can do and if it's an external module or not. """
43 properties = {
44 # name of the module type ; to distinguish between them:
45 'type': None,
47 # is the module "external" (external means here a daemon module) ?
48 'external': True,
50 # Possible configuration phases where the module is involved :
51 'phases' : [ 'configuration', 'late_configuration', 'running', 'retention' ],
55 class ModulePhases:
56 ## TODO: why not use simply integers instead of string to represent the different phases ??
57 CONFIGURATION = 1
58 LATE_CONFIGURATION = 2
59 RUNNING = 4
60 RETENTION = 8
64 class BaseModule(object):
65 """ This is the base class for the shinken modules.
66 Modules can be used by the different shinken daemons/services for different tasks.
67 Example of task that a shinken module can do:
68 - load additional configuration objects.
69 - recurrently save hosts/services status/perfdata informations in different format.
70 - ...
71 """
73 def __init__(self, mod_conf):
74 """ `name´ is the name given to this module instance. There can be many instance of the same type.
75 `props´ is the properties dict of this module. dict that defines at what phases the module is involved. """
76 self.myconf = mod_conf
77 self.name = mod_conf.get_name()
78 self.props = mod_conf.properties.copy()
79 self.properties = self.props
80 self.interrupted = False
81 self.is_external = self.props.get('external', False)
82 self.phases = self.props.get('phases', []) # though a module defined with no phase is quite useless ..
83 self.phases.append(None)
84 self.to_q = None
85 self.from_q = None
87 def create_queues(self):
88 self.create_queues__(self)
90 @staticmethod
91 def create_queues__(obj):
92 obj.from_q = Queue()
93 obj.to_q = Queue()
95 def init(self):
96 """ Handle this module "post" init ; just before it'll be started.
97 Like just open necessaries file(s), database(s), or whatever the module will need. """
98 pass
100 def get_name(self):
101 return self.name
103 def has(self, prop):
104 """ The classic has : do we have a prop or not? """
105 return hasattr(self, prop)
107 def get_objects(self):
108 """ Called during arbiter configuration phase. Return a dict to the objects that the module provides.
109 Possible objects are Host, Service, Timeperiod, etc ..
110 Examples of valid return:
111 h1 = { 'host_name': "server1", register=0 }
112 return { 'hosts': [ h1 ] } """
113 raise NotImplementedError()
116 def update_retention_objects(self, sched, log_mgr):
117 """ Update the retention objects of this module.
118 Called recurrently by scheduler. Also during stop of scheduler. """
119 raise NotImplementedError()
122 def hook_late_configuration(self, conf):
123 """ Hook for the module "late configuration" : Called by arbiter after the configuration has been fully loaded & built """
124 raise NotImplementedError()
127 def manage_brok(self, brok):
128 """ Request the module to manage the given brok.
129 There a lot of different possible broks to manage. """
130 manage = getattr(self, 'manage_' + brok.type + '_brok', None)
131 if manage:
132 return manage(brok)
135 def manage_signal(self, sig, frame):
136 self.interrupted = True
138 def set_signal_handler(self, sigs=None):
139 if sigs is None:
140 sigs = (signal.SIGINT, signal.SIGTERM)
142 for sig in sigs:
143 signal.signal(sig, self.manage_signal)
145 set_exit_handler = set_signal_handler
147 def do_stop(self):
148 pass
150 def do_loop_turn(self):
151 raise NotImplementedError()
153 def main(self):
154 self.set_signal_handler()
155 print("[%s[%d]]: Now running.." % (self.name, os.getpid()))
156 while not self.interrupted:
157 self.do_loop_turn()
158 self.do_stop()
159 print("[%s]: exiting now.." % (self.name))