2 #Copyright (C) 2009-2010 :
3 # Gabes Jean, naparuba@gmail.com
4 # Gerhard Lausser, Gerhard.Lausser@consol.de
5 # Gregory Starck, g.starck@gmail.com
6 # Hartmut Goebel, h.goebel@goebel-consult.de
8 #This file is part of Shinken.
10 #Shinken is free software: you can redistribute it and/or modify
11 #it under the terms of the GNU Affero General Public License as published by
12 #the Free Software Foundation, either version 3 of the License, or
13 #(at your option) any later version.
15 #Shinken is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 #GNU Affero General Public License for more details.
20 #You should have received a copy of the GNU Affero General Public License
21 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
24 #SatelliteLink is a common Class for link to satellite for
25 #Arbiter with Conf Dispatcher.
29 import shinken
.pyro_wrapper
as pyro
32 from shinken
.objects
import Item
, Items
34 class SatelliteLink(Item
):
35 #id = 0 each Class will have it's own id
36 #properties={'name' : {'required' : True },#, 'pythonize': None},
37 # 'address' : {'required' : True},#, 'pythonize': to_bool},
38 # 'port' : {'required': True, 'pythonize': to_int},
39 # 'spare' : {'required': False, 'default' : '0', 'pythonize': to_bool},
42 #running_properties = {
43 # 'con' : {'default' : None}
53 #Check is required prop are set:
54 #contacts OR contactgroups is need
56 state
= True #guilty or not? :)
59 special_properties
= ['realm']
60 for prop
, entry
in cls
.properties
.items():
61 if prop
not in special_properties
:
62 if not hasattr(self
, prop
) and entry
['required']:
63 print self
.get_name(), " : I do not have", prop
64 state
= False #Bad boy...
65 # Ok now we manage special cases...
66 if getattr(self
, 'realm', None) is None:
67 print self
.get_name()," : I do not have a valid realm"
72 def create_connexion(self
):
73 self
.uri
= pyro
.create_uri(self
.address
, self
.port
, "ForArbiter", self
.__class
__.use_ssl
)
74 self
.con
= pyro
.getProxy(self
.uri
)
75 pyro
.set_timeout(self
.con
, self
.timeout
)
78 def put_conf(self
, conf
):
81 self
.create_connexion()
82 #print "Connexion is OK, now we put conf", conf
83 #print "Try to put conf:", conf
86 pyro
.set_timeout(self
.con
, self
.data_timeout
)
87 #del conf[0].schedulerlinks
88 buf
=cPickle
.dumps(conf
)
89 print "DBG: put conf to", self
.con
.__dict
__
90 self
.con
.put_conf(conf
)
91 pyro
.set_timeout(self
.con
, self
.timeout
)
93 except Pyro
.errors
.URIError
, exp
:
96 except Pyro
.errors
.ProtocolError
, exp
:
99 except TypeError , exp
:
100 print ''.join(Pyro
.util
.getPyroTraceback(exp
))
101 except Pyro
.errors
.CommunicationError
, exp
:
106 #Get and clean all of our broks
107 def get_all_broks(self
):
113 #Set alive, reachable, and reset attemps.
114 #If we change state, raise a status brok update
116 was_alive
= self
.alive
119 self
.reachable
= True
121 #We came from dead to alive
122 #so we must add a brok update
124 b
= self
.get_update_status_brok()
129 print "Set dead for %s" % self
.get_name()
130 was_alive
= self
.alive
134 #We are dead now. Must raise
137 b
= self
.get_update_status_brok()
141 #Go in reachable=False and add a failed attempt
142 #if we reach the max, go dead
143 def add_failed_check_attempt(self
):
144 print "Add failed attempt to", self
.get_name()
145 self
.reachable
= False
147 self
.attempt
= min(self
.attempt
, self
.max_check_attempts
)
148 print "Attemps", self
.attempt
, self
.max_check_attempts
149 #check when we just go HARD (dead)
150 if self
.attempt
== self
.max_check_attempts
:
155 print "Pinging %s" % self
.get_name()
158 self
.create_connexion()
161 except Pyro
.errors
.ProtocolError
, exp
:
162 self
.add_failed_check_attempt()
163 except Pyro
.errors
.URIError
, exp
:
165 self
.add_failed_check_attempt()
166 #Only pyro 4 but will be ProtocolError in 3
167 except Pyro
.errors
.CommunicationError
, exp
:
168 #print "Is not alive!", self.uri
169 self
.add_failed_check_attempt()
170 except Pyro
.errors
.DaemonError
, exp
:
172 self
.add_failed_check_attempt()
173 except Exception, exp
:
175 self
.add_failed_check_attempt()
178 def wait_new_conf(self
):
180 self
.create_connexion()
182 self
.con
.wait_new_conf()
184 except Pyro
.errors
.URIError
, exp
:
187 except Pyro
.errors
.ProtocolError
, exp
:
190 except Exception, exp
:
196 #To know if the satellite have a conf (magic_hash = None)
197 #OR to know if the satellite have THIS conf (magic_hash != None)
198 def have_conf(self
, magic_hash
=None):
200 self
.create_connexion()
203 if magic_hash
is None:
204 return self
.con
.have_conf()
206 return self
.con
.have_conf(magic_hash
)
207 except Pyro
.errors
.URIError
, exp
:
210 except Pyro
.errors
.ProtocolError
, exp
:
213 except Exception, exp
:
219 def remove_from_conf(self
, sched_id
):
221 self
.create_connexion()
223 self
.con
.remove_from_conf(sched_id
)
225 except Pyro
.errors
.URIError
, exp
:
228 except Pyro
.errors
.ProtocolError
, exp
:
231 except Exception, exp
:
236 def what_i_managed(self
):
238 self
.create_connexion()
240 tab
= self
.con
.what_i_managed()
241 #I don't know why, but tab can be a bool. Not good here
242 if isinstance(tab
, bool):
246 except Pyro
.errors
.URIError
, exp
:
249 except Pyro
.errors
.ProtocolError
, exp
:
252 except Exception, exp
:
257 def push_broks(self
, broks
):
259 self
.create_connexion()
261 return self
.con
.push_broks(broks
)
262 except Pyro
.errors
.URIError
, exp
:
265 except Pyro
.errors
.ProtocolError
, exp
:
268 except AttributeError , exp
:
271 except Exception, exp
:
277 def get_external_commands(self
):
279 self
.create_connexion()
281 tab
= self
.con
.get_external_commands()
282 if isinstance(tab
, bool):
285 except Pyro
.errors
.URIError
, exp
:
288 except Pyro
.errors
.ProtocolError
, exp
:
291 except AttributeError , exp
:
294 except Exception, exp
:
300 def prepare_for_conf(self
):
301 self
.cfg
= { 'global' : {}, 'schedulers' : {}, 'arbiters' : {}}
302 #cfg_for_satellite['modules'] = satellite.modules
303 properties
= self
.__class
__.properties
304 for prop
, entry
in properties
.items():
305 # if 'to_send' in entry and entry['to_send']:
307 self
.cfg
['global'][prop
] = getattr(self
, prop
)
309 #Some parameters for satellites are not defined in the satellites conf
310 #but in the global configuration. We can pass them in the global
312 def add_global_conf_parameters(self
, params
):
314 print "Add global parameter", prop
, params
[prop
]
315 self
.cfg
['global'][prop
] = params
[prop
]
318 def get_my_type(self
):
319 return self
.__class
__.my_type
322 #Here for poller and reactionner. Scheduler have it's own function
323 def give_satellite_cfg(self
):
324 return {'port' : self
.port
, 'address' : self
.address
, 'name' : self
.get_name(), 'instance_id' : self
.id, 'active' : True, 'passive' : self
.passive
, 'poller_tags' : getattr(self
, 'poller_tags', [])}
328 #Call by picle for dataify the downtime
329 #because we DO NOT WANT REF in this pickleisation!
330 def __getstate__(self
):
332 # id is not in *_properties
333 res
= {'id' : self
.id}
334 for prop
in cls
.properties
:
336 if hasattr(self
, prop
):
337 res
[prop
] = getattr(self
, prop
)
338 for prop
in cls
.running_properties
:
340 if hasattr(self
, prop
):
341 res
[prop
] = getattr(self
, prop
)
345 #Inversed funtion of getstate
346 def __setstate__(self
, state
):
349 self
.id = state
['id']
350 for prop
in cls
.properties
:
352 setattr(self
, prop
, state
[prop
])
353 for prop
in cls
.running_properties
:
355 setattr(self
, prop
, state
[prop
])
356 # con needs to be explicitely set:
361 class SatelliteLinks(Items
):
362 #name_property = "name"
363 #inner_class = SchedulerLink
365 #We must have a realm property, so we find our realm
366 def linkify(self
, realms
, modules
):
367 self
.linkify_s_by_p(realms
)
368 self
.linkify_s_by_plug(modules
)
371 def linkify_s_by_p(self
, realms
):
373 p_name
= s
.realm
.strip()
374 # If no realm name, take the default one
376 p
= realms
.get_default()
378 else: # find the realm one
379 p
= realms
.find_by_name(p_name
)
381 # Check if what we get is OK or not
383 print "Me", s
.get_name(), "is linked with realm", s
.realm
.get_name()
384 s
.register_to_my_realm()
386 err
= "The %s %s got a unknown realm '%s'" % (s
.__class
__.my_type
, s
.get_name(), p_name
)
387 s
.configuration_errors
.append(err
)
391 def linkify_s_by_plug(self
, modules
):
394 for plug_name
in s
.modules
:
395 plug
= modules
.find_by_name(plug_name
.strip())
397 new_modules
.append(plug
)
399 print "Error : the module %s is unknow for %s" % (plug_name
, s
.get_name())
400 s
.modules
= new_modules