Add : child_dependencies/ parent_dependencies in livestatus module.
[shinken.git] / shinken / satellitelink.py
blob13c299433cd33d2a1fac0feaef5a1732f96510f6
1 #!/usr/bin/env python
2 #Copyright (C) 2009-2010 :
3 # Gabes Jean, naparuba@gmail.com
4 # Gerhard Lausser, Gerhard.Lausser@consol.de
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 #SatelliteLink is a common Class for link to satellite for
23 #Arbiter with Conf Dispatcher.
26 import shinken.pyro_wrapper as pyro
27 Pyro = pyro.Pyro
30 from shinken.item import Item, Items
32 class SatelliteLink(Item):
33 #id = 0 each Class will have it's own id
34 #properties={'name' : {'required' : True },#, 'pythonize': None},
35 # 'address' : {'required' : True},#, 'pythonize': to_bool},
36 # 'port' : {'required': True, 'pythonize': to_int},
37 # 'spare' : {'required': False, 'default' : '0', 'pythonize': to_bool},
38 # }
40 #running_properties = {
41 # 'con' : {'default' : None}
42 # }
43 #macros = {}
46 #Clean? Really?
47 def clean(self):
48 pass
51 #Check is required prop are set:
52 #contacts OR contactgroups is need
53 def is_correct(self):
54 state = True #guilty or not? :)
55 cls = self.__class__
57 special_properties = ['realm']
58 for prop in cls.properties:
59 if prop not in special_properties:
60 if not hasattr(self, prop) and cls.properties[prop]['required']:
61 print self.get_name(), " : I do not have", prop
62 state = False #Bad boy...
63 #Ok now we manage special cases...
64 if not hasattr(self, 'realm') or hasattr(self, 'realm') and self.realm == None:
65 print self.get_name()," : I do not have a valid realm"
66 state = False
67 return state
70 def create_connexion(self):
71 self.uri = pyro.create_uri(self.address, self.port, "ForArbiter")
72 self.con = pyro.getProxy(self.uri)
73 pyro.set_timeout(self.con, self.timeout)
76 def put_conf(self, conf):
77 if self.con == None:
78 self.create_connexion()
79 #print "Connexion is OK, now we put conf", conf
80 #print "Try to put conf:", conf
81 try:
82 pyro.set_timeout(self.con, self.data_timeout)
83 self.con.put_conf(conf)
84 pyro.set_timeout(self.con, self.timeout)
85 return True
86 except Pyro.errors.URIError , exp:
87 self.con = None
88 return False
89 except Pyro.errors.ProtocolError , exp:
90 self.con = None
91 return False
92 except TypeError , exp:
93 print ''.join(Pyro.util.getPyroTraceback(exp))
94 except Pyro.errors.CommunicationError , exp:
95 self.con = None
96 return False
99 #Get and clean all of our broks
100 def get_all_broks(self):
101 res = self.broks
102 self.broks = []
103 return res
106 #Set alive, reachable, and reset attemps.
107 #If we change state, raise a status brok update
108 def set_alive(self):
109 was_alive = self.alive
110 self.alive = True
111 self.attempt = 0
112 self.reachable = True
114 #We came from dead to alive
115 #so we must add a brok update
116 if not was_alive:
117 b = self.get_update_status_brok()
118 self.broks.append(b)
121 def set_dead(self):
122 print "Set dead for %s" % self.get_name()
123 was_alive = self.alive
124 self.alive = False
125 self.con = None
127 #We are dead now. Must raise
128 #a brok to say it
129 if was_alive:
130 b = self.get_update_status_brok()
131 self.broks.append(b)
134 #Go in reachable=False and add a failed attempt
135 #if we reach the max, go dead
136 def add_failed_check_attempt(self):
137 print "Add failed attempt to", self.get_name()
138 self.reachable = False
139 self.attempt += 1
140 self.attempt = min(self.attempt, self.max_check_attempts)
141 print "Attemps", self.attempt, self.max_check_attempts
142 #check when we just go HARD (dead)
143 if self.attempt == self.max_check_attempts:
144 self.set_dead()
147 def ping(self):
148 print "Pinging %s" % self.get_name()
149 try:
150 if self.con == None:
151 self.create_connexion()
152 self.con.ping()
153 self.set_alive()
154 except Pyro.errors.ProtocolError , exp:
155 self.add_failed_check_attempt()
156 except Pyro.errors.URIError , exp:
157 print exp
158 self.add_failed_check_attempt()
159 #Only pyro 4 but will be ProtocolError in 3
160 except Pyro.errors.CommunicationError , exp:
161 #print "Is not alive!", self.uri
162 self.add_failed_check_attempt()
163 except Pyro.errors.DaemonError , exp:
164 print exp
165 self.add_failed_check_attempt()
168 def wait_new_conf(self):
169 if self.con == None:
170 self.create_connexion()
171 try:
172 self.con.wait_new_conf()
173 return True
174 except Pyro.errors.URIError , exp:
175 self.con = None
176 return False
177 except Pyro.errors.ProtocolError , exp:
178 self.con = None
179 return False
182 #To know if the satellite have a conf (magic_hash = None)
183 #OR to know if the satellite have THIS conf (magic_hash != None)
184 def have_conf(self, magic_hash=None):
185 if self.con == None:
186 self.create_connexion()
188 try:
189 if magic_hash == None:
190 return self.con.have_conf()
191 else:
192 return self.con.have_conf(magic_hash)
193 except Pyro.errors.URIError , exp:
194 self.con = None
195 return False
196 except Pyro.errors.ProtocolError , exp:
197 self.con = None
198 return False
201 def remove_from_conf(self, sched_id):
202 if self.con == None:
203 self.create_connexion()
204 try:
205 self.con.remove_from_conf(sched_id)
206 return True
207 except Pyro.errors.URIError , exp:
208 self.con = None
209 return False
210 except Pyro.errors.ProtocolError , exp:
211 self.con = None
212 return False
215 def what_i_managed(self):
216 if self.con == None:
217 self.create_connexion()
218 try:
219 tab = self.con.what_i_managed()
220 #I don't know why, but tab can be a bool. Not good here
221 if isinstance(tab, bool):
222 self.con = None
223 return []
224 return tab
225 except Pyro.errors.URIError , exp:
226 self.con = None
227 return []
228 except Pyro.errors.ProtocolError , exp:
229 self.con = None
230 return []
233 def push_broks(self, broks):
234 if self.con == None:
235 self.create_connexion()
236 try:
237 return self.con.push_broks(broks)
238 except Pyro.errors.URIError , exp:
239 self.con = None
240 return False
241 except Pyro.errors.ProtocolError , exp:
242 self.con = None
243 return False
244 except AttributeError , exp:
245 print exp
246 return False
249 def get_external_commands(self):
250 if self.con == None:
251 self.create_connexion()
252 try:
253 tab = self.con.get_external_commands()
254 if isinstance(tab, bool):
255 return []
256 return tab
257 except Pyro.errors.URIError , exp:
258 self.con = None
259 return []
260 except Pyro.errors.ProtocolError , exp:
261 self.con = None
262 return []
263 except AttributeError , exp:
264 print exp
265 return []
269 def prepare_for_conf(self):
270 self.cfg = { 'global' : {}, 'schedulers' : {}, 'arbiters' : {}}
271 #cfg_for_satellite['modules'] = satellite.modules
272 properties = self.__class__.properties
273 for prop in properties:
274 # if 'to_send' in properties[prop] and properties[prop]['to_send']:
275 if properties[prop].to_send:
276 self.cfg['global'][prop] = getattr(self, prop)
278 #Some parameters for satellites are not defined in the satellites conf
279 #but in the global configuration. We can pass them in the global
280 #property
281 def add_global_conf_parameters(self, params):
282 for prop in params:
283 print "Add global parameter", prop, params[prop]
284 self.cfg['global'][prop] = params[prop]
287 def get_my_type(self):
288 return self.__class__.my_type
291 #Here for poller and reactionner. Scheduler have it's own function
292 def give_satellite_cfg(self):
293 return {'port' : self.port, 'address' : self.address, 'name' : self.get_name(), 'instance_id' : self.id, 'active' : True}
297 class SatelliteLinks(Items):
298 #name_property = "name"
299 #inner_class = SchedulerLink
301 #We must have a realm property, so we find our realm
302 def linkify(self, realms, modules):
303 self.linkify_s_by_p(realms)
304 self.linkify_s_by_plug(modules)
307 def linkify_s_by_p(self, realms):
308 for s in self:
309 p_name = s.realm.strip()
310 # If no realm name, take the default one
311 if p_name == '':
312 p = realms.get_default()
313 s.realm = p
314 else: # find the realm one
315 p = realms.find_by_name(p_name)
316 s.realm = p
317 # Check if what we get is OK or not
318 if p is not None:
319 print "Me", s.get_name(), "is linked with realm", s.realm.get_name()
320 s.register_to_my_realm()
321 else:
322 err = "The %s %s got a unknown realm '%s'" % (s.__class__.my_type, s.get_name(), p_name)
323 s.configuration_errors.append(err)
324 print err
327 def linkify_s_by_plug(self, modules):
328 for s in self:
329 new_modules = []
330 for plug_name in s.modules:
331 plug = modules.find_by_name(plug_name.strip())
332 if plug != None:
333 new_modules.append(plug)
334 else:
335 print "Error : the module %s is unknow for %s" % (plug_name, s.get_name())
336 s.modules = new_modules