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 """
25 from multiprocessing
import Queue
29 ## TODO: use a class for defining the module "properties" instead of plain dict ?? Like:
31 class ModuleProperties(object):
32 def __init__(self, type, phases, external=False)
35 self.external = external
37 ## and have the new modules instanciate this like follow :
39 properties = ModuleProperties('the_module_type', the_module_phases, is_mod_ext)
42 """ The `properties´ dict defines what the module can do and if it's an external module or not. """
44 # name of the module type ; to distinguish between them:
47 # is the module "external" (external means here a daemon module) ?
50 # Possible configuration phases where the module is involved :
51 'phases' : [ 'configuration', 'late_configuration', 'running', 'retention' ],
56 ## TODO: why not use simply integers instead of string to represent the different phases ??
58 LATE_CONFIGURATION
= 2
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.
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)
87 def create_queues(self
):
88 self
.create_queues__(self
)
91 def create_queues__(obj
):
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. """
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)
135 def manage_signal(self
, sig
, frame
):
136 self
.interrupted
= True
138 def set_signal_handler(self
, sigs
=None):
140 sigs
= (signal
.SIGINT
, signal
.SIGTERM
)
143 signal
.signal(sig
, self
.manage_signal
)
145 set_exit_handler
= set_signal_handler
150 def do_loop_turn(self
):
151 raise NotImplementedError()
154 self
.set_signal_handler()
155 print("[%s[%d]]: Now running.." % (self
.name
, os
.getpid()))
156 while not self
.interrupted
:
159 print("[%s]: exiting now.." % (self
.name
))