Enh : begin to enhance the use_ssl boolean dispatching. It's global, let use it as it.
[shinken.git] / shinken / satellitelink.py
blobb38d98f9378273ca47ee0747258dfa5711d18f55
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 getattr(self, 'realm', None) is 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", self.__class__.use_ssl)
72 self.con = pyro.getProxy(self.uri)
73 pyro.set_timeout(self.con, self.timeout)
76 def put_conf(self, conf, use_ssl):
78 if self.con == None:
79 self.create_connexion()
80 #print "Connexion is OK, now we put conf", conf
81 #print "Try to put conf:", conf
83 try:
84 pyro.set_timeout(self.con, self.data_timeout)
85 #del conf[0].schedulerlinks
86 import cPickle
87 buf=cPickle.dumps(conf)
88 print "DBG: put conf to", self.con.__dict__
89 self.con.put_conf(conf)
90 pyro.set_timeout(self.con, self.timeout)
91 return True
92 except Pyro.errors.URIError , exp:
93 self.con = None
94 return False
95 except Pyro.errors.ProtocolError , exp:
96 self.con = None
97 return False
98 except TypeError , exp:
99 print ''.join(Pyro.util.getPyroTraceback(exp))
100 except Pyro.errors.CommunicationError , exp:
101 self.con = None
102 return False
105 #Get and clean all of our broks
106 def get_all_broks(self):
107 res = self.broks
108 self.broks = []
109 return res
112 #Set alive, reachable, and reset attemps.
113 #If we change state, raise a status brok update
114 def set_alive(self):
115 was_alive = self.alive
116 self.alive = True
117 self.attempt = 0
118 self.reachable = True
120 #We came from dead to alive
121 #so we must add a brok update
122 if not was_alive:
123 b = self.get_update_status_brok()
124 self.broks.append(b)
127 def set_dead(self):
128 print "Set dead for %s" % self.get_name()
129 was_alive = self.alive
130 self.alive = False
131 self.con = None
133 #We are dead now. Must raise
134 #a brok to say it
135 if was_alive:
136 b = self.get_update_status_brok()
137 self.broks.append(b)
140 #Go in reachable=False and add a failed attempt
141 #if we reach the max, go dead
142 def add_failed_check_attempt(self):
143 print "Add failed attempt to", self.get_name()
144 self.reachable = False
145 self.attempt += 1
146 self.attempt = min(self.attempt, self.max_check_attempts)
147 print "Attemps", self.attempt, self.max_check_attempts
148 #check when we just go HARD (dead)
149 if self.attempt == self.max_check_attempts:
150 self.set_dead()
153 def ping(self, use_ssl):
154 print "Pinging %s" % self.get_name()
155 try:
156 if self.con == None:
157 self.create_connexion()
158 self.con.ping()
159 self.set_alive()
160 except Pyro.errors.ProtocolError , exp:
161 self.add_failed_check_attempt()
162 except Pyro.errors.URIError , exp:
163 print exp
164 self.add_failed_check_attempt()
165 #Only pyro 4 but will be ProtocolError in 3
166 except Pyro.errors.CommunicationError , exp:
167 #print "Is not alive!", self.uri
168 self.add_failed_check_attempt()
169 except Pyro.errors.DaemonError , exp:
170 print exp
171 self.add_failed_check_attempt()
172 except Exception, exp:
173 print exp
174 self.add_failed_check_attempt()
177 def wait_new_conf(self, use_ssl):
178 if self.con == None:
179 self.create_connexion()
180 try:
181 self.con.wait_new_conf()
182 return True
183 except Pyro.errors.URIError , exp:
184 self.con = None
185 return False
186 except Pyro.errors.ProtocolError , exp:
187 self.con = None
188 return False
189 except Exception, exp:
190 self.con = False
191 return False
195 #To know if the satellite have a conf (magic_hash = None)
196 #OR to know if the satellite have THIS conf (magic_hash != None)
197 def have_conf(self, use_ssl, magic_hash=None):
198 if self.con == None:
199 self.create_connexion()
201 try:
202 if magic_hash == None:
203 return self.con.have_conf()
204 else:
205 return self.con.have_conf(magic_hash)
206 except Pyro.errors.URIError , exp:
207 self.con = None
208 return False
209 except Pyro.errors.ProtocolError , exp:
210 self.con = None
211 return False
212 except Exception, exp:
213 self.con = False
214 return False
218 def remove_from_conf(self, sched_id, use_ssl):
219 if self.con == None:
220 self.create_connexion()
221 try:
222 self.con.remove_from_conf(sched_id)
223 return True
224 except Pyro.errors.URIError , exp:
225 self.con = None
226 return False
227 except Pyro.errors.ProtocolError , exp:
228 self.con = None
229 return False
230 except Exception, exp:
231 self.con = False
232 return False
235 def what_i_managed(self, use_ssl):
236 if self.con == None:
237 self.create_connexion()
238 try:
239 tab = self.con.what_i_managed()
240 #I don't know why, but tab can be a bool. Not good here
241 if isinstance(tab, bool):
242 self.con = None
243 return []
244 return tab
245 except Pyro.errors.URIError , exp:
246 self.con = None
247 return []
248 except Pyro.errors.ProtocolError , exp:
249 self.con = None
250 return []
251 except Exception, exp:
252 self.con = False
253 return []
256 def push_broks(self, broks, use_ssl):
257 if self.con == None:
258 self.create_connexion()
259 try:
260 return self.con.push_broks(broks)
261 except Pyro.errors.URIError , exp:
262 self.con = None
263 return False
264 except Pyro.errors.ProtocolError , exp:
265 self.con = None
266 return False
267 except AttributeError , exp:
268 print exp
269 return False
270 except Exception, exp:
271 self.con = False
272 return False
276 def get_external_commands(self, use_ssl):
277 if self.con == None:
278 self.create_connexion()
279 try:
280 tab = self.con.get_external_commands()
281 if isinstance(tab, bool):
282 return []
283 return tab
284 except Pyro.errors.URIError , exp:
285 self.con = None
286 return []
287 except Pyro.errors.ProtocolError , exp:
288 self.con = None
289 return []
290 except AttributeError , exp:
291 print exp
292 return []
293 except Exception, exp:
294 self.con = False
295 return []
299 def prepare_for_conf(self):
300 self.cfg = { 'global' : {}, 'schedulers' : {}, 'arbiters' : {}}
301 #cfg_for_satellite['modules'] = satellite.modules
302 properties = self.__class__.properties
303 for prop in properties:
304 # if 'to_send' in properties[prop] and properties[prop]['to_send']:
305 if properties[prop].to_send:
306 self.cfg['global'][prop] = getattr(self, prop)
308 #Some parameters for satellites are not defined in the satellites conf
309 #but in the global configuration. We can pass them in the global
310 #property
311 def add_global_conf_parameters(self, params):
312 for prop in params:
313 print "Add global parameter", prop, params[prop]
314 self.cfg['global'][prop] = params[prop]
317 def get_my_type(self):
318 return self.__class__.my_type
321 #Here for poller and reactionner. Scheduler have it's own function
322 def give_satellite_cfg(self):
323 return {'port' : self.port, 'address' : self.address, 'name' : self.get_name(), 'instance_id' : self.id, 'active' : True}
327 #Call by picle for dataify the downtime
328 #because we DO NOT WANT REF in this pickleisation!
329 def __getstate__(self):
330 cls = self.__class__
331 # id is not in *_properties
332 res = {'id' : self.id}
333 for prop in cls.properties:
334 if prop != 'realm':
335 if hasattr(self, prop):
336 res[prop] = getattr(self, prop)
337 for prop in cls.running_properties:
338 if prop != 'con':
339 if hasattr(self, prop):
340 res[prop] = getattr(self, prop)
341 return res
344 #Inversed funtion of getstate
345 def __setstate__(self, state):
346 cls = self.__class__
348 self.id = state['id']
349 for prop in cls.properties:
350 if prop in state:
351 setattr(self, prop, state[prop])
352 for prop in cls.running_properties:
353 if prop in state:
354 setattr(self, prop, state[prop])
358 class SatelliteLinks(Items):
359 #name_property = "name"
360 #inner_class = SchedulerLink
362 #We must have a realm property, so we find our realm
363 def linkify(self, realms, modules):
364 self.linkify_s_by_p(realms)
365 self.linkify_s_by_plug(modules)
368 def linkify_s_by_p(self, realms):
369 for s in self:
370 p_name = s.realm.strip()
371 # If no realm name, take the default one
372 if p_name == '':
373 p = realms.get_default()
374 s.realm = p
375 else: # find the realm one
376 p = realms.find_by_name(p_name)
377 s.realm = p
378 # Check if what we get is OK or not
379 if p is not None:
380 print "Me", s.get_name(), "is linked with realm", s.realm.get_name()
381 s.register_to_my_realm()
382 else:
383 err = "The %s %s got a unknown realm '%s'" % (s.__class__.my_type, s.get_name(), p_name)
384 s.configuration_errors.append(err)
385 print err
388 def linkify_s_by_plug(self, modules):
389 for s in self:
390 new_modules = []
391 for plug_name in s.modules:
392 plug = modules.find_by_name(plug_name.strip())
393 if plug != None:
394 new_modules.append(plug)
395 else:
396 print "Error : the module %s is unknow for %s" % (plug_name, s.get_name())
397 s.modules = new_modules