*TAG : 0.5 release
[shinken.git] / bin / shinken-arbiter
blobb19014289438aa5d04862122744c73951b8487b7
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 #This is the class of the Arbiter. It's role is to read configuration,
23 #cuts it, and send it to other elements like schedulers, reactionner
24 #or pollers. It is responsible for hight avaibility part. If a scheduler
25 #is dead,
26 #it send it's conf to another if available.
27 #It also read order form users (nagios.cmd) and send orders to schedulers.
30 import os
31 import time
32 import sys
33 import select
34 import getopt
35 import random
36 from Queue import Empty
39 # We try to raise up recusion limit on
40 # but we don't have resource module on windows
41 if os.name != 'nt':
42 import resource
43 # All the pickle will ask for a lot of recursion, so we must make
44 # sure to set it at a high value. The maximum recursion depth depends
45 # on the Python version and the process limit "stack size".
46 # The factors used were aquired by testing a broad range of installations
47 stacksize_soft, stacksize_hard = resource.getrlimit(3)
48 if sys.version_info < (2,6):
49 sys.setrecursionlimit(int(stacksize_soft * 0.65 + 1100))
50 elif sys.version_info < (3,):
51 sys.setrecursionlimit(int(stacksize_soft * 1.9 + 3200))
52 else:
53 sys.setrecursionlimit(int(stacksize_soft * 2.4 + 3200))
56 ## Make sure people are using Python 2.5 or higher
57 if sys.version_info < (2,4):
58 print "Shinken requires as a minimum Python 2.4.x, sorry"
59 sys.exit(1)
60 elif sys.version_info >= (3,):
61 print "Shinken is not yet compatible with Python3k, sorry"
62 sys.exit(1)
65 #In fact it's useful for installed daemon
66 sys.path.insert(0, '.')
69 #Try to load shinken lib.
70 #Maybe it's not in our python path, so we detect it
71 #it so (it's a untar install) we add .. in the path
72 try :
73 from shinken.util import to_bool
74 if hasattr(sys.modules['__main__'], '__file__'):
75 my_path = os.path.abspath(sys.modules['__main__'].__file__)
76 elts = os.path.dirname(my_path).split(os.sep)[:-1]
77 elts.append('shinken')
78 sys.path.append(os.sep.join(elts))
79 except ImportError:
80 if hasattr(sys.modules['__main__'], '__file__'):
81 #Now add in the python path the shinken lib
82 #if we launch it in a direct way and
83 #the shinken is not a python lib
84 my_path = os.path.abspath(sys.modules['__main__'].__file__)
85 elts = os.path.dirname(my_path).split(os.sep)[:-1]
86 sys.path.append(os.sep.join(elts))
87 elts.append('shinken')
88 sys.path.append(os.sep.join(elts))
92 try:
93 import shinken.pyro_wrapper
94 except ImportError:
95 print "Shinken require the Python Pyro module. Please install it."
96 sys.exit(1)
98 Pyro = shinken.pyro_wrapper.Pyro
101 from shinken.util import to_bool
102 #from scheduler import Scheduler
103 from shinken.config import Config
104 from shinken.external_command import ExternalCommandManager
105 from shinken.dispatcher import Dispatcher
106 from shinken.daemon import Daemon
107 from shinken.log import logger
108 from shinken.modulesmanager import ModulesManager
109 from shinken.brok import Brok
110 from shinken.external_command import ExternalCommand
113 VERSION = "0.5"
117 #Interface for the other Arbiter
118 #It connect, and we manage who is the Master, slave etc.
119 #Here is a also a fnction to have a new conf from the master
120 class IArbiters(Pyro.core.ObjBase):
121 #we keep arbiter link
122 def __init__(self, arbiter):
123 Pyro.core.ObjBase.__init__(self)
124 self.arbiter = arbiter
125 self.running_id = random.random()
128 #Broker need to void it's broks?
129 def get_running_id(self):
130 return self.running_id
133 def have_conf(self, magic_hash):
134 #I've got a conf and the good one
135 if self.arbiter.have_conf and self.arbiter.conf.magic_hash == magic_hash:
136 return True
137 else: #No conf or a bad one
138 return False
141 #The master Arbiter is sending us a new conf. Ok, we take it
142 def put_conf(self, conf):
143 self.arbiter.conf = conf
144 print "Get conf:", self.arbiter.conf
145 self.arbiter.have_conf = True
146 print "Just after reception"
147 self.arbiter.must_run = False
150 #Ping? Pong!
151 def ping(self):
152 return None
155 #the master arbiter ask me to do not run!
156 def do_not_run(self):
157 #If i'm the master, just FUCK YOU!
158 if self.arbiter.is_master:
159 print "Some fucking idiot ask me to do not run. I'm a proud master, so I'm still running"
160 #Else I'm just a spare, so I listen to my master
161 else:
162 print "Someone ask me to do not run"
163 self.arbiter.last_master_speack = time.time()
164 self.arbiter.must_run = False
167 #Main Arbiter Class
168 class Arbiter(Daemon):
171 properties = {
172 #'workdir' : {'default' : '/usr/local/shinken/var', 'pythonize' : None},
173 #'pidfile' : {'default' : '/usr/local/shinken/var/arbiterd.pid', 'pythonize' : None},
174 #'port' : {'default' : '7768', 'pythonize' : to_int},
175 #'host' : {'default' : '0.0.0.0', 'pythonize' : None},
176 #'user' : {'default' : 'shinken', 'pythonize' : None},
177 #'group' : {'default' : 'shinken', 'pythonize' : None},
178 #'idontcareaboutsecurity' : {'default' : '0', 'pythonize' : to_bool}
182 def __init__(self, config_files, is_daemon, do_replace, verify_only, debug, debug_file):
183 self.config_file = config_files[0]
184 self.config_files = config_files
185 self.is_daemon = is_daemon
186 self.verify_only = verify_only
187 self.do_replace = do_replace
188 self.debug = debug
189 self.debug_file = debug_file
191 #From daemon to manage signal. Call self.manage_signal if
192 #exists, a dummy function otherwise
193 self.set_exit_handler()
194 self.broks = {}
195 self.is_master = False
196 self.me = None
198 self.nb_broks_send = 0
200 #Now tab for external_commands
201 self.external_commands = []
203 self.t_each_loop = time.time() # to track system time change
206 #Use for adding things like broks
207 def add(self, b):
208 if isinstance(b, Brok):
209 self.broks[b.id] = b
210 elif isinstance(b, ExternalCommand):
211 self.external_commands.append(b)
212 else:
213 logger.log('Warning : cannot manage object type %s (%s)' % (type(b), b))
216 #We must push our broks to the broker
217 #because it's stupid to make a crossing connexion
218 #so we find the broker responbile for our broks,
219 #and we send him it
220 #TODO : better find the broker, here it can be dead?
221 #or not the good one?
222 def push_broks_to_broker(self):
223 for brk in self.conf.brokers:
224 #Send only if alive of course
225 if brk.manage_arbiters and brk.alive:
226 is_send = brk.push_broks(self.broks)
227 if is_send:
228 #They are gone, we keep none!
229 self.broks = {}
232 #We must take external_commands from all brokers
233 def get_external_commands_from_brokers(self):
234 for brk in self.conf.brokers:
235 #Get only if alive of course
236 if brk.alive:
237 new_cmds = brk.get_external_commands()
238 for new_cmd in new_cmds:
239 self.external_commands.append(new_cmd)
242 #Our links to satellites can raise broks. We must send them
243 def get_broks_from_satellitelinks(self):
244 tabs = [self.conf.brokers, self.conf.schedulerlinks, \
245 self.conf.pollers, self.conf.reactionners]
246 for tab in tabs:
247 for s in tab:
248 new_broks = s.get_all_broks()
249 for b in new_broks:
250 self.add(b)
253 #Our links to satellites can raise broks. We must send them
254 def get_initial_broks_from_satellitelinks(self):
255 tabs = [self.conf.brokers, self.conf.schedulerlinks, \
256 self.conf.pollers, self.conf.reactionners]
257 for tab in tabs:
258 for s in tab:
259 b = s.get_initial_status_brok()
260 self.add(b)
263 #Load the external commander
264 def load_external_command(self, e):
265 self.external_command = e
266 self.fifo = e.open()
269 #Check if our system time change. If so, change our
270 def check_for_system_time_change(self):
271 now = time.time()
272 difference = now - self.t_each_loop
273 #If we have more than 15 min time change, we need to compensate
276 if abs(difference) > 900:
277 self.compensate_system_time_change(difference)
279 #Now set the new value for the tick loop
280 self.t_each_loop = now
282 #return the diff if it need, of just 0
283 if abs(difference) > 900:
284 return difference
285 else:
286 return 0
289 #If we've got a system time change, we need to compensate it
290 #from now, we do not do anything in fact.
291 def compensate_system_time_change(self, difference):
292 logger.log('Warning: A system time change of %s has been detected. Compensating...' % difference)
293 #We only need to change some value
297 def main(self):
298 #Log will be broks
299 self.log = logger
300 self.log.load_obj(self)
302 self.print_header()
303 for line in self.get_header():
304 self.log.log(line)#, format = 'TOTO %s\n')
306 #Use to know if we must still be alive or not
307 self.must_run = True
309 print "Loading configuration"
310 self.conf = Config()
311 #The config Class must have the USERN macro
312 #There are 256 of them, so we create online
313 Config.fill_usern_macros()
315 #REF: doc/shinken-conf-dispatching.png (1)
316 buf = self.conf.read_config(self.config_files)
318 raw_objects = self.conf.read_config_buf(buf)
320 #### Loading Arbiter module part ####
322 #first we need to get arbtiers and modules first
323 #so we can ask them some objects too
324 self.conf.create_objects_for_type(raw_objects, 'arbiter')
325 self.conf.create_objects_for_type(raw_objects, 'module')
328 self.conf.early_arbiter_linking()
330 #Search wich Arbiterlink I am
331 for arb in self.conf.arbiterlinks:
332 if arb.is_me():
333 arb.need_conf = False
334 self.me = arb
335 print "I am the arbiter :", arb.get_name()
336 print "Am I the master?", not self.me.spare
337 else: #not me
338 arb.need_conf = True
340 #If None, there will be huge problems. The conf will be invalid
341 #And we will bail out after print all errors
342 if self.me != None:
343 print "My own modules :"
344 for m in self.me.modules:
345 print m
347 #BEWARE: this way of finding path is good if we still
348 #DO NOT HAVE CHANGE PWD!!!
349 #Now get the module path. It's in fact the directory modules
350 #inside the shinken directory. So let's find it.
351 print "modulemanager file", shinken.modulesmanager.__file__
352 modulespath = os.path.abspath(shinken.modulesmanager.__file__)
353 print "modulemanager absolute file", modulespath
354 #We got one of the files of
355 elts = os.path.dirname(modulespath).split(os.sep)[:-1]
356 elts.append('shinken')
357 elts.append('modules')
358 self.modulespath = os.sep.join(elts)
359 logger.log("Using modules path : %s" % os.sep.join(elts))
362 self.modules_manager = ModulesManager('arbiter', self.modulespath, self.me.modules)
363 self.modules_manager.load()
364 self.mod_instances = self.modules_manager.get_instances()
366 # Now we ask for configuration modules if they
367 # got items for us
368 for inst in self.mod_instances:
369 if 'configuration' in inst.properties['phases']:
370 try :
371 r = inst.get_objects()
372 types_creations = self.conf.types_creations
373 for k in types_creations:
374 (cls, clss, prop) = types_creations[k]
375 if prop in r:
376 for x in r[prop]:
377 # test if raw_objects[k] is already set - if not, add empty array
378 if not k in raw_objects:
379 raw_objects[k] = []
380 # now append the object
381 raw_objects[k].append(x)
382 print "Added %i objects to %s from module %s" % (len(r[prop]), k, inst.get_name())
383 except Exception, exp:
384 print "The instance %s raise an exception %s. I bypass it" % (inst.get_name(), str(exp))
386 ### Resume standard operations ###
387 self.conf.create_objects(raw_objects)
389 #Maybe conf is already invalid
390 if not self.conf.conf_is_correct:
391 print "***> One or more problems was encountered while processing the config files..."
392 sys.exit(1)
395 #************** Change Nagios2 names to Nagios3 ones ******
396 self.conf.old_properties_names_to_new()
398 #print "****************** Create Template links **********"
399 self.conf.linkify_templates()
401 #print "****************** Inheritance *******************"
402 self.conf.apply_inheritance()
404 #print "****************** Explode ***********************"
405 self.conf.explode()
407 #print "***************** Create Name reversed list ******"
408 self.conf.create_reversed_list()
410 #print "***************** Cleaning Twins *****************"
411 self.conf.remove_twins()
413 #print "****************** Implicit inheritance *******************"
414 self.conf.apply_implicit_inheritance()
416 #print "****************** Fill default ******************"
417 self.conf.fill_default()
419 #print "****************** Clean templates ******************"
420 self.conf.clean_useless()
422 #print "****************** Pythonize ******************"
423 self.conf.pythonize()
425 #print "****************** Linkify ******************"
426 self.conf.linkify()
428 #print "*************** applying dependancies ************"
429 self.conf.apply_dependancies()
431 #Hacking some global parameter inherited from Nagios to create
432 #on the fly some Broker modules like for status.dat parameters
433 #or nagios.log one if there are no already available
434 self.conf.hack_old_nagios_parameters()
436 #Raise warning about curently unmanaged parameters
437 self.conf.warn_about_unmanaged_parameters()
439 #print "************** Exlode global conf ****************"
440 self.conf.explode_global_conf()
442 #set ourown timezone and propagate it to other satellites
443 self.conf.propagate_timezone_option()
445 # Look for business rules, and create teh dep trees
446 self.conf.create_business_rules()
447 # And link them
448 self.conf.create_business_rules_dependencies()
451 #************* Print warning about useless parameters in Shinken **************"
452 self.conf.notice_about_useless_parameters()
454 #print "****************** Correct ?******************"
455 self.conf.is_correct()
457 #If the conf is not correct, we must get out now
458 if not self.conf.conf_is_correct:
459 print "Configuration is incorrect, sorry, I bail out"
460 sys.exit(1)
463 #self.conf.dump()
465 #from guppy import hpy
466 #hp=hpy()
467 #print hp.heap()
468 #print hp.heapu()
470 if self.me == None:
471 print "Error : I cannot find my own Arbiter object, I bail out"
472 print "To solve it : please change the host_name parameter in the object Arbiter"
473 print "in the file shinken-specific.cfg. Thanks."
474 sys.exit(1)
477 #If I am a spare, I must wait a (true) conf from Arbiter Master
478 self.wait_conf = self.me.spare
480 #print "Dump realms"
481 #for r in self.conf.realms:
482 # print r.get_name(), r.__dict__
483 print "\n"
486 #REF: doc/shinken-conf-dispatching.png (2)
487 logger.log("Cutting the hosts and services into parts")
488 self.confs = self.conf.cut_into_parts()
490 #The conf can be incorrect here if the cut into parts see errors like
491 #a realm with hosts and not schedulers for it
492 if not self.conf.conf_is_correct:
493 print "Configuration is incorrect, sorry, I bail out"
494 sys.exit(1)
496 logger.log('Things look okay - No serious problems were detected during the pre-flight check')
498 #Exit if we are just here for config checking
499 if self.verify_only:
500 sys.exit(0)
502 #self.conf.debug()
504 #Some properties need to be "flatten" (put in strings)
505 #before being send, like realms for hosts for example
506 #BEWARE: after the cutting part, because we stringify some properties
507 self.conf.prepare_for_sending()
510 #Ok, here we must check if we go on or not.
511 #TODO : check OK or not
512 self.pidfile = self.conf.lock_file
513 self.idontcareaboutsecurity = self.conf.idontcareaboutsecurity
514 self.user = self.conf.shinken_user
515 self.group = self.conf.shinken_group
516 self.workdir = os.path.expanduser('~'+self.user)
518 #If we go, we must go in daemon or not
519 #Check if another Scheduler is not running (with the same conf)
520 self.check_parallel_run(do_replace)
523 # And set SSL things too
524 if self.conf.use_ssl:
525 Pyro.config.PYROSSL_CERTDIR = os.path.abspath(self.conf.certs_dir)
526 logger.log("Using ssl certificate directory : %s" % Pyro.config.PYROSSL_CERTDIR)
527 Pyro.config.PYROSSL_CA_CERT = os.path.abspath(self.conf.ca_cert)
528 logger.log("Using ssl ca cert file : %s" % Pyro.config.PYROSSL_CA_CERT)
529 Pyro.config.PYROSSL_CERT = os.path.abspath(self.conf.server_cert)
530 logger.log("Using ssl server cert file : %s" % Pyro.config.PYROSSL_CERT)
531 if self.conf.hard_ssl_name_check:
532 Pyro.config.PYROSSL_POSTCONNCHECK=1
533 else:
534 Pyro.config.PYROSSL_POSTCONNCHECK=0
536 #If the admin don't care about security, I allow root running
537 insane = not self.idontcareaboutsecurity
539 #Try to change the user (not nt for the moment)
540 #TODO: change user on nt
541 if os.name != 'nt':
542 self.change_user(insane)
543 else:
544 logger.log("Warning : you can't change user on this system")
546 #Now the daemon part if need
547 if is_daemon:
548 self.create_daemon(do_debug=debug, debug_file=debug_file)
550 logger.log("Opening of the network port")
551 #Now open the daemon port for Broks and other Arbiter sends
552 Pyro.config.PYRO_STORAGE = self.workdir
553 Pyro.config.PYRO_COMPRESSION = 1
554 Pyro.config.PYRO_MULTITHREADED = 0
555 logger.log("Using working directory : %s" % os.path.abspath(self.workdir))
557 self.poller_daemon = shinken.pyro_wrapper.init_daemon(self.me.address, self.me.port, self.conf.use_ssl)
559 logger.log("Listening on %s:%d" % (self.me.address, self.me.port))
561 self.iarbiters = IArbiters(self)
563 self.uri_arb = shinken.pyro_wrapper.register(self.poller_daemon, self.iarbiters, "ForArbiter")
565 logger.log("Configuration Loaded")
567 #Main loop
568 while True:
569 #If I am a spare, I wait for the master arbiter to send me
570 #true conf. When
571 if self.me.spare:
572 self.wait_initial_conf()
573 else:#I'm the master, I've got a conf
574 self.is_master = True
575 self.have_conf = True
577 #Ok, now It've got a True conf, Now I wait to get too much
578 #time without
579 if self.me.spare:
580 print "I must wait now"
581 self.wait_for_master_death()
583 if self.must_run:
584 #Main loop
585 self.run()
588 #Get 'objects' from external modules
589 #It can be used for get external commands for example
590 def get_objects_from_from_queues(self):
591 for f in self.modules_manager.get_external_from_queues():
592 print "Groking from module instance %s" % f
593 full_queue = True
594 while full_queue:
595 try:
596 o = f.get(block=False)
597 print "Got object :", o
598 self.add(o)
599 except Empty :
600 full_queue = False
604 #We wait (block) for arbiter to send us conf
605 def wait_initial_conf(self):
606 self.have_conf = False
607 print "Waiting for configuration from master"
608 timeout = 1.0
609 while not self.have_conf :
610 socks = shinken.pyro_wrapper.get_sockets(self.poller_daemon)
612 avant = time.time()
613 # 'foreign' event loop
614 ins, outs, exs = select.select(socks, [], [], timeout)
616 #Manage a possible time change (our avant will be change with the diff)
617 diff = self.check_for_system_time_change()
618 avant += diff
620 if ins != []:
621 for s in socks:
622 if s in ins:
623 shinken.pyro_wrapper.handleRequests(self.poller_daemon, s)
624 apres = time.time()
625 diff = apres-avant
626 timeout = timeout - diff
627 break # no need to continue with the for loop
628 else: #Timeout
629 sys.stdout.write(".")
630 sys.stdout.flush()
631 timeout = 1.0
633 if timeout < 0:
634 timeout = 1.0
637 #We wait (block) for arbiter to send us something
638 def wait_for_master_death(self):
639 print "Waiting for master death"
640 timeout = 1.0
641 is_master_dead = False
642 self.last_master_speack = time.time()
643 while not is_master_dead:
644 socks = shinken.pyro_wrapper.get_sockets(self.poller_daemon)
645 avant = time.time()
646 # 'foreign' event loop
647 ins, outs, exs = select.select(socks, [], [], timeout)
649 #Manage a possible time change (our avant will be change with the diff)
650 diff = self.check_for_system_time_change()
651 avant += diff
653 if ins != []:
654 for s in socks:
655 if s in ins:
656 shinken.pyro_wrapper.handleRequests(self.poller_daemon, s)
657 self.last_master_speack = time.time()
658 apres = time.time()
659 diff = apres-avant
660 timeout = timeout - diff
661 else: #Timeout
662 sys.stdout.write(".")
663 sys.stdout.flush()
664 timeout = 1.0
666 if timeout < 0:
667 timeout = 1.0
669 #Now check if master is dead or not
670 now = time.time()
671 if now - self.last_master_speack > 5:
672 print "Master is dead!!!"
673 self.must_run = True
674 is_master_dead = True
677 #Manage signal function
678 #Frame is just garbage
679 def manage_signal(self, sig, frame):
680 print "\nExiting with signal", sig
681 print "Stopping all network connexions"
682 self.poller_daemon.shutdown(True)
683 print "Unlinking pid file"
684 try:
685 os.unlink(self.pidfile)
686 except OSError, exp:
687 print "Error un deleting pid file:", exp
688 sys.exit(0)
691 #Main function
692 def run(self):
693 #Before running, I must be sure who am I
694 #The arbiters change, so we must refound the new self.me
695 for arb in self.conf.arbiterlinks:
696 if arb.is_me():
697 self.me = arb
699 logger.log("Begin to dispatch configurations to satellites")
700 self.dispatcher = Dispatcher(self.conf, self.me)
701 self.dispatcher.check_alive()
702 self.dispatcher.check_dispatch()
703 #REF: doc/shinken-conf-dispatching.png (3)
704 self.dispatcher.dispatch()
706 #Now we can get all initial broks for our satellites
707 self.get_initial_broks_from_satellitelinks()
709 #Now create the external commander
710 if os.name != 'nt':
711 e = ExternalCommandManager(self.conf, 'dispatcher')
713 #Scheduler need to know about external command to activate it
714 #if necessary
715 self.load_external_command(e)
716 else:
717 self.fifo = None
719 print "Run baby, run..."
720 timeout = 1.0
721 while self.must_run :
722 socks = []
723 daemon_sockets = shinken.pyro_wrapper.get_sockets(self.poller_daemon)
724 socks.extend(daemon_sockets)
725 avant = time.time()
726 if self.fifo != None:
727 socks.append(self.fifo)
728 # 'foreign' event loop
729 ins, outs, exs = select.select(socks, [], [], timeout)
731 #Manage a possible time change (our avant will be change with the diff)
732 diff = self.check_for_system_time_change()
733 avant += diff
735 if ins != []:
736 for s in socks:
737 if s in ins:
738 if s in daemon_sockets:
739 shinken.pyro_wrapper.handleRequests(self.poller_daemon, s)
740 apres = time.time()
741 diff = apres-avant
742 timeout = timeout - diff
743 break # no need to continue with the for loop
744 #If FIFO, read external command
745 if s == self.fifo:
746 ext_cmds = self.external_command.get()
747 for ext_cmd in ext_cmds:
748 self.external_commands.append(ext_cmd)
749 self.fifo = self.external_command.open()
751 else: #Timeout
752 self.dispatcher.check_alive()
753 self.dispatcher.check_dispatch()
754 #REF: doc/shinken-conf-dispatching.png (3)
755 self.dispatcher.dispatch()
756 self.dispatcher.check_bad_dispatch()
758 #Now get things from our module instances
759 self.get_objects_from_from_queues()
761 #Maybe our satellites links raise new broks. Must reap them
762 self.get_broks_from_satellitelinks()
764 #One broker is responsible for our broks,
765 #we must give him our broks
766 self.push_broks_to_broker()
767 self.get_external_commands_from_brokers()
768 #send_conf_to_schedulers()
769 timeout = 1.0
771 print "Nb Broks send:", self.nb_broks_send
772 #logger.log("Nb Broks send: %d" % self.nb_broks_send)
773 self.nb_broks_send = 0
776 #Now send all external commands to schedulers
777 for ext_cmd in self.external_commands:
778 self.external_command.resolve_command(ext_cmd)
779 #It's send, do not keep them
780 #TODO: check if really send. Queue by scheduler?
781 self.external_commands = []
783 if timeout < 0:
784 timeout = 1.0
788 ################### Process launch part
789 def usage(name):
790 print "Shinken Arbiter Daemon, version %s, from :" % VERSION
791 print " Gabes Jean, naparuba@gmail.com"
792 print " Gerhard Lausser, Gerhard.Lausser@consol.de"
793 print "Usage: %s [options] -c configfile [-c additionnal_config_file]" % name
794 print "Options:"
795 print " -c, --config"
796 print "\tConfig file (your nagios.cfg). Multiple -c can be used, it will be like if all files was just one"
797 print " -d, --daemon"
798 print "\tRun in daemon mode"
799 print " -r, --replace"
800 print "\tReplace previous running scheduler"
801 print " -h, --help"
802 print "\tPrint detailed help screen"
803 print " --debug"
804 print "\tDebug File. Default : no use (why debug a bug free program? :) )"
809 #Here we go!
810 if __name__ == "__main__":
811 #Manage the options
812 try:
813 opts, args = getopt.getopt(sys.argv[1:], "hvrdc::w", ["help", "verify-config", "replace", "daemon", "config=", "debug=", "easter"])
814 except getopt.GetoptError, err:
815 # print help information and exit:
816 print str(err) # will print something like "option -a not recognized"
817 usage(sys.argv[0])
818 sys.exit(2)
819 #Default params
820 config_files = []
821 verify_only = False
822 is_daemon = False
823 do_replace = False
824 debug = False
825 debug_file = None
826 for o, a in opts:
827 if o in ("-h", "--help"):
828 usage(sys.argv[0])
829 sys.exit()
830 elif o in ("-v", "--verify-config"):
831 verify_only = True
832 elif o in ("-r", "--replace"):
833 do_replace = True
834 elif o in ("-c", "--config"):
835 config_files.append(a)
836 elif o in ("-d", "--daemon"):
837 is_daemon = True
838 elif o in ("--debug"):
839 debug = True
840 debug_file = a
841 else:
842 print "Sorry, the option", o, a, "is unknown"
843 usage(sys.argv[0])
844 sys.exit()
846 if len(config_files) == 0:
847 print "Error : config file is need"
848 usage(sys.argv[0])
849 sys.exit()
851 p = Arbiter(config_files, is_daemon, do_replace, verify_only, debug, debug_file)
852 #Ok, now we load the config
854 #p = Shinken(conf)
855 #import cProfile
856 p.main()
857 #command = """p.main()"""
858 #cProfile.runctx( command, globals(), locals(), filename="/tmp/Arbiter.profile" )