Revision 04ccf5e9
b/daemons/ganeti-masterd | ||
---|---|---|
43 | 43 |
|
44 | 44 |
from ganeti import config |
45 | 45 |
from ganeti import constants |
46 |
from ganeti import daemon |
|
46 | 47 |
from ganeti import mcpu |
47 | 48 |
from ganeti import opcodes |
48 | 49 |
from ganeti import jqueue |
... | ... | |
383 | 384 |
self.glm.remove(locking.LEVEL_NODE, name) |
384 | 385 |
|
385 | 386 |
|
386 |
def ParseOptions(): |
|
387 |
"""Parse the command line options. |
|
388 |
|
|
389 |
@return: (options, args) as from OptionParser.parse_args() |
|
390 |
|
|
391 |
""" |
|
392 |
parser = OptionParser(description="Ganeti master daemon", |
|
393 |
usage="%prog [-f] [-d]", |
|
394 |
version="%%prog (ganeti) %s" % |
|
395 |
constants.RELEASE_VERSION) |
|
396 |
|
|
397 |
parser.add_option("-f", "--foreground", dest="fork", |
|
398 |
help="Don't detach from the current terminal", |
|
399 |
default=True, action="store_false") |
|
400 |
parser.add_option("-d", "--debug", dest="debug", |
|
401 |
help="Enable some debug messages", |
|
402 |
default=False, action="store_true") |
|
403 |
parser.add_option("--no-voting", dest="no_voting", |
|
404 |
help="Do not check that the nodes agree on this node" |
|
405 |
" being the master and start the daemon unconditionally", |
|
406 |
default=False, action="store_true") |
|
407 |
parser.add_option("--yes-do-it", dest="yes_do_it", |
|
408 |
help="Override interactive check for --no-voting", |
|
409 |
default=False, action="store_true") |
|
410 |
|
|
411 |
options, args = parser.parse_args() |
|
412 |
return options, args |
|
413 |
|
|
414 |
|
|
415 | 387 |
def CheckAgreement(): |
416 | 388 |
"""Check the agreement on who is the master. |
417 | 389 |
|
... | ... | |
468 | 440 |
|
469 | 441 |
return result |
470 | 442 |
|
443 |
def CheckMASTERD(options, args): |
|
444 |
"""Initial checks whether to run or exit with a failure |
|
471 | 445 |
|
472 |
def main(): |
|
473 |
"""Main function""" |
|
474 |
|
|
475 |
options, args = ParseOptions() |
|
476 |
utils.no_fork = True |
|
477 |
daemon_name = constants.MASTERD |
|
478 |
|
|
479 |
if options.fork: |
|
480 |
utils.CloseFDs() |
|
481 |
|
|
446 |
""" |
|
482 | 447 |
rpc.Init() |
483 | 448 |
try: |
484 | 449 |
ssconf.CheckMaster(options.debug) |
... | ... | |
496 | 461 |
elif not options.no_voting: |
497 | 462 |
if not CheckAgreement(): |
498 | 463 |
return |
499 |
|
|
500 |
dirs = [(constants.RUN_GANETI_DIR, constants.RUN_DIRS_MODE), |
|
501 |
(constants.SOCKET_DIR, constants.SOCKET_DIR_MODE), |
|
502 |
] |
|
503 |
utils.EnsureDirs(dirs) |
|
504 |
|
|
505 |
# This is safe to do as the pid file guarantees against |
|
506 |
# concurrent execution. |
|
507 |
utils.RemoveFile(constants.MASTER_SOCKET) |
|
508 |
|
|
509 |
master = IOServer(constants.MASTER_SOCKET, ClientRqHandler) |
|
510 | 464 |
finally: |
511 | 465 |
rpc.Shutdown() |
512 | 466 |
|
513 |
# become a daemon |
|
514 |
if options.fork: |
|
515 |
utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name]) |
|
516 | 467 |
|
517 |
utils.WritePidFile(daemon_name) |
|
518 |
try: |
|
519 |
utils.SetupLogging(constants.DAEMONS_LOGFILES[daemon_name], |
|
520 |
debug=options.debug, |
|
521 |
stderr_logging=not options.fork, multithreaded=True) |
|
468 |
def ExecMASTERD(options, args): |
|
469 |
"""Main MASTERD function, executed with the pidfile held. |
|
522 | 470 |
|
523 |
logging.info("Ganeti master daemon startup") |
|
471 |
""" |
|
472 |
# This is safe to do as the pid file guarantees against |
|
473 |
# concurrent execution. |
|
474 |
utils.RemoveFile(constants.MASTER_SOCKET) |
|
524 | 475 |
|
476 |
master = IOServer(constants.MASTER_SOCKET, ClientRqHandler) |
|
477 |
try: |
|
525 | 478 |
rpc.Init() |
526 | 479 |
try: |
527 | 480 |
# activate ip |
... | ... | |
539 | 492 |
finally: |
540 | 493 |
rpc.Shutdown() |
541 | 494 |
finally: |
542 |
utils.RemovePidFile(daemon_name) |
|
543 | 495 |
utils.RemoveFile(constants.MASTER_SOCKET) |
544 | 496 |
|
545 | 497 |
|
498 |
def main(): |
|
499 |
"""Main function""" |
|
500 |
parser = OptionParser(description="Ganeti master daemon", |
|
501 |
usage="%prog [-f] [-d]", |
|
502 |
version="%%prog (ganeti) %s" % |
|
503 |
constants.RELEASE_VERSION) |
|
504 |
parser.add_option("--no-voting", dest="no_voting", |
|
505 |
help="Do not check that the nodes agree on this node" |
|
506 |
" being the master and start the daemon unconditionally", |
|
507 |
default=False, action="store_true") |
|
508 |
parser.add_option("--yes-do-it", dest="yes_do_it", |
|
509 |
help="Override interactive check for --no-voting", |
|
510 |
default=False, action="store_true") |
|
511 |
dirs = [(constants.RUN_GANETI_DIR, constants.RUN_DIRS_MODE), |
|
512 |
(constants.SOCKET_DIR, constants.SOCKET_DIR_MODE), |
|
513 |
] |
|
514 |
daemon.GenericMain(constants.MASTERD, parser, dirs, |
|
515 |
CheckMASTERD, ExecMASTERD) |
|
516 |
|
|
546 | 517 |
if __name__ == "__main__": |
547 | 518 |
main() |
b/daemons/ganeti-noded | ||
---|---|---|
732 | 732 |
return backend.ValidateHVParams(hvname, hvparams) |
733 | 733 |
|
734 | 734 |
|
735 |
def ParseOptions(): |
|
736 |
"""Parse the command line options. |
|
737 |
|
|
738 |
@return: (options, args) as from OptionParser.parse_args() |
|
735 |
def CheckNODED(options, args): |
|
736 |
"""Initial checks whether to run exit with a failure |
|
739 | 737 |
|
740 | 738 |
""" |
741 |
parser = OptionParser(description="Ganeti node daemon", |
|
742 |
usage="%prog [-f] [-d] [-b ADDRESS]", |
|
743 |
version="%%prog (ganeti) %s" % |
|
744 |
constants.RELEASE_VERSION) |
|
745 |
|
|
746 |
parser.add_option("-f", "--foreground", dest="fork", |
|
747 |
help="Don't detach from the current terminal", |
|
748 |
default=True, action="store_false") |
|
749 |
parser.add_option("-d", "--debug", dest="debug", |
|
750 |
help="Enable some debug messages", |
|
751 |
default=False, action="store_true") |
|
752 |
parser.add_option("-b", "--bind", dest="bind_address", |
|
753 |
help="Bind address", |
|
754 |
default="", metavar="ADDRESS") |
|
755 |
|
|
756 |
options, args = parser.parse_args() |
|
757 |
return options, args |
|
739 |
for fname in (constants.SSL_CERT_FILE,): |
|
740 |
if not os.path.isfile(fname): |
|
741 |
print "config %s not there, will not run." % fname |
|
742 |
sys.exit(constants.EXIT_NOTCLUSTER) |
|
758 | 743 |
|
759 | 744 |
|
760 |
def main():
|
|
761 |
"""Main function for the node daemon.
|
|
745 |
def ExecNODED(options, args):
|
|
746 |
"""Main NODED function, executed with the pidfile held.
|
|
762 | 747 |
|
763 | 748 |
""" |
764 | 749 |
global queue_lock |
765 |
daemon_name = constants.NODED |
|
766 | 750 |
|
767 |
options, args = ParseOptions() |
|
751 |
# Read SSL certificate |
|
752 |
ssl_params = http.HttpSslParams(ssl_key_path=constants.SSL_CERT_FILE, |
|
753 |
ssl_cert_path=constants.SSL_CERT_FILE) |
|
768 | 754 |
|
769 |
if options.fork:
|
|
770 |
utils.CloseFDs()
|
|
755 |
# Prepare job queue
|
|
756 |
queue_lock = jstore.InitAndVerifyQueue(must_lock=False)
|
|
771 | 757 |
|
772 |
for fname in (constants.SSL_CERT_FILE,): |
|
773 |
if not os.path.isfile(fname): |
|
774 |
print "config %s not there, will not run." % fname |
|
775 |
sys.exit(constants.EXIT_NOTCLUSTER) |
|
758 |
mainloop = daemon.Mainloop() |
|
759 |
server = NodeHttpServer(mainloop, options.bind_address, options.port, |
|
760 |
ssl_params=ssl_params, ssl_verify_peer=True) |
|
761 |
server.Start() |
|
762 |
try: |
|
763 |
mainloop.Run() |
|
764 |
finally: |
|
765 |
server.Stop() |
|
776 | 766 |
|
777 |
port = utils.GetDaemonPort(constants.NODED) |
|
778 | 767 |
|
768 |
def main(): |
|
769 |
"""Main function for the node daemon. |
|
770 |
|
|
771 |
""" |
|
772 |
parser = OptionParser(description="Ganeti node daemon", |
|
773 |
usage="%prog [-f] [-d] [-p port] [-b ADDRESS]", |
|
774 |
version="%%prog (ganeti) %s" % |
|
775 |
constants.RELEASE_VERSION) |
|
779 | 776 |
dirs = [(val, constants.RUN_DIRS_MODE) for val in constants.SUB_RUN_DIRS] |
780 | 777 |
dirs.append((constants.LOG_OS_DIR, 0750)) |
781 | 778 |
dirs.append((constants.LOCK_DIR, 1777)) |
782 |
utils.EnsureDirs(dirs) |
|
783 |
|
|
784 |
# become a daemon |
|
785 |
if options.fork: |
|
786 |
utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name]) |
|
787 |
|
|
788 |
utils.WritePidFile(daemon_name) |
|
789 |
try: |
|
790 |
utils.SetupLogging(logfile=constants.DAEMONS_LOGFILES[daemon_name], |
|
791 |
debug=options.debug, |
|
792 |
stderr_logging=not options.fork) |
|
793 |
logging.info("ganeti node daemon startup") |
|
794 |
|
|
795 |
# Read SSL certificate |
|
796 |
ssl_params = http.HttpSslParams(ssl_key_path=constants.SSL_CERT_FILE, |
|
797 |
ssl_cert_path=constants.SSL_CERT_FILE) |
|
798 |
|
|
799 |
# Prepare job queue |
|
800 |
queue_lock = jstore.InitAndVerifyQueue(must_lock=False) |
|
801 |
|
|
802 |
mainloop = daemon.Mainloop() |
|
803 |
server = NodeHttpServer(mainloop, options.bind_address, port, |
|
804 |
ssl_params=ssl_params, ssl_verify_peer=True) |
|
805 |
server.Start() |
|
806 |
try: |
|
807 |
mainloop.Run() |
|
808 |
finally: |
|
809 |
server.Stop() |
|
810 |
finally: |
|
811 |
utils.RemovePidFile(daemon_name) |
|
779 |
daemon.GenericMain(constants.NODED, parser, dirs, CheckNODED, ExecNODED) |
|
812 | 780 |
|
813 | 781 |
|
814 | 782 |
if __name__ == '__main__': |
b/daemons/ganeti-rapi | ||
---|---|---|
177 | 177 |
return result |
178 | 178 |
|
179 | 179 |
|
180 |
def ParseOptions(): |
|
181 |
"""Parse the command line options. |
|
182 |
|
|
183 |
@return: (options, args) as from OptionParser.parse_args() |
|
180 |
def CheckRAPI(options, args): |
|
181 |
"""Initial checks whether to run or exit with a failure |
|
184 | 182 |
|
185 | 183 |
""" |
186 |
parser = optparse.OptionParser(description="Ganeti Remote API", |
|
187 |
usage="%prog [-d]", |
|
188 |
version="%%prog (ganeti) %s" % |
|
189 |
constants.RAPI_VERSION) |
|
190 |
parser.add_option("-d", "--debug", dest="debug", |
|
191 |
help="Enable some debug messages", |
|
192 |
default=False, action="store_true") |
|
193 |
parser.add_option("--no-ssl", dest="ssl", |
|
194 |
help="Do not secure HTTP protocol with SSL", |
|
195 |
default=True, action="store_false") |
|
196 |
parser.add_option("-K", "--ssl-key", dest="ssl_key", |
|
197 |
help="SSL key", |
|
198 |
default=constants.RAPI_CERT_FILE, type="string") |
|
199 |
parser.add_option("-C", "--ssl-cert", dest="ssl_cert", |
|
200 |
help="SSL certificate", |
|
201 |
default=constants.RAPI_CERT_FILE, type="string") |
|
202 |
parser.add_option("-f", "--foreground", dest="fork", |
|
203 |
help="Don't detach from the current terminal", |
|
204 |
default=True, action="store_false") |
|
205 |
parser.add_option("-b", "--bind", dest="bind_address", |
|
206 |
help="Bind address", |
|
207 |
default="", metavar="ADDRESS") |
|
208 |
|
|
209 |
options, args = parser.parse_args() |
|
210 |
|
|
211 | 184 |
if len(args) != 0: |
212 |
print >> sys.stderr, "Usage: %s [-d]" % sys.argv[0] |
|
185 |
print >> sys.stderr, "Usage: %s [-f] [-d] [-p port] [-b ADDRESS]" % \ |
|
186 |
sys.argv[0] |
|
213 | 187 |
sys.exit(constants.EXIT_FAILURE) |
214 | 188 |
|
215 |
if options.ssl and not (options.ssl_cert and options.ssl_key): |
|
216 |
print >> sys.stderr, ("For secure mode please provide " |
|
217 |
"--ssl-key and --ssl-cert arguments") |
|
218 |
sys.exit(constants.EXIT_FAILURE) |
|
189 |
if options.ssl: |
|
190 |
if not (options.ssl_cert and options.ssl_key): |
|
191 |
print >> sys.stderr, ("For secure mode please provide " |
|
192 |
"--ssl-key and --ssl-cert arguments") |
|
193 |
sys.exit(constants.EXIT_FAILURE) |
|
194 |
for fname in (options.ssl_cert, options.ssl_key): |
|
195 |
if not os.path.isfile(fname): |
|
196 |
print >> sys.stderr, "config %s not there, will not run." % fname |
|
197 |
sys.exit(constants.EXIT_FAILURE) |
|
219 | 198 |
|
220 |
return options, args
|
|
199 |
ssconf.CheckMaster(options.debug)
|
|
221 | 200 |
|
222 | 201 |
|
223 |
def main():
|
|
224 |
"""Main function.
|
|
202 |
def ExecRAPI(options, args):
|
|
203 |
"""Main RAPI function, executed with the pidfile held.
|
|
225 | 204 |
|
226 | 205 |
""" |
227 |
options, args = ParseOptions() |
|
228 |
daemon_name = constants.RAPI |
|
229 |
|
|
230 |
if options.fork: |
|
231 |
utils.CloseFDs() |
|
232 |
|
|
206 |
# Read SSL certificate |
|
233 | 207 |
if options.ssl: |
234 |
# Read SSL certificate |
|
235 |
try: |
|
236 |
ssl_params = http.HttpSslParams(ssl_key_path=options.ssl_key, |
|
237 |
ssl_cert_path=options.ssl_cert) |
|
238 |
except Exception, err: |
|
239 |
sys.stderr.write("Can't load the SSL certificate/key: %s\n" % (err,)) |
|
240 |
sys.exit(constants.EXIT_FAILURE) |
|
208 |
ssl_params = http.HttpSslParams(ssl_key_path=options.ssl_key, |
|
209 |
ssl_cert_path=options.ssl_cert) |
|
241 | 210 |
else: |
242 | 211 |
ssl_params = None |
243 | 212 |
|
244 |
ssconf.CheckMaster(options.debug) |
|
245 |
port = utils.GetDaemonPort(constants.RAPI) |
|
213 |
mainloop = daemon.Mainloop() |
|
214 |
server = RemoteApiHttpServer(mainloop, options.bind_address, options.port, |
|
215 |
ssl_params=ssl_params, ssl_verify_peer=False, |
|
216 |
request_executor_class=JsonErrorRequestExecutor) |
|
217 |
server.Start() |
|
218 |
try: |
|
219 |
mainloop.Run() |
|
220 |
finally: |
|
221 |
server.Stop() |
|
246 | 222 |
|
247 |
if options.fork: |
|
248 |
utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name]) |
|
249 | 223 |
|
250 |
utils.SetupLogging(constants.DAEMONS_LOGFILES[daemon_name], debug=options.debug,
|
|
251 |
stderr_logging=not options.fork)
|
|
224 |
def main():
|
|
225 |
"""Main function.
|
|
252 | 226 |
|
253 |
utils.WritePidFile(daemon_name) |
|
254 |
try: |
|
255 |
mainloop = daemon.Mainloop() |
|
256 |
server = RemoteApiHttpServer(mainloop, options.bind_address, port, |
|
257 |
ssl_params=ssl_params, ssl_verify_peer=False, |
|
258 |
request_executor_class= |
|
259 |
JsonErrorRequestExecutor) |
|
260 |
server.Start() |
|
261 |
try: |
|
262 |
mainloop.Run() |
|
263 |
finally: |
|
264 |
server.Stop() |
|
265 |
finally: |
|
266 |
utils.RemovePidFile(daemon_name) |
|
227 |
""" |
|
228 |
parser = optparse.OptionParser(description="Ganeti Remote API", |
|
229 |
usage="%prog [-f] [-d] [-p port] [-b ADDRESS]", |
|
230 |
version="%%prog (ganeti) %s" % constants.RAPI_VERSION) |
|
231 |
parser.add_option("--no-ssl", dest="ssl", |
|
232 |
help="Do not secure HTTP protocol with SSL", |
|
233 |
default=True, action="store_false") |
|
234 |
parser.add_option("-K", "--ssl-key", dest="ssl_key", |
|
235 |
help="SSL key", |
|
236 |
default=constants.RAPI_CERT_FILE, type="string") |
|
237 |
parser.add_option("-C", "--ssl-cert", dest="ssl_cert", |
|
238 |
help="SSL certificate", |
|
239 |
default=constants.RAPI_CERT_FILE, type="string") |
|
240 |
|
|
241 |
dirs = [(val, constants.RUN_DIRS_MODE) for val in constants.SUB_RUN_DIRS] |
|
242 |
dirs.append((constants.LOG_OS_DIR, 0750)) |
|
243 |
daemon.GenericMain(constants.RAPI, parser, dirs, CheckRAPI, ExecRAPI) |
|
267 | 244 |
|
268 | 245 |
|
269 | 246 |
if __name__ == '__main__': |
b/lib/constants.py | ||
---|---|---|
115 | 115 |
RAPI = "ganeti-rapi" |
116 | 116 |
MASTERD = "ganeti-masterd" |
117 | 117 |
|
118 |
MULTITHREADED_DAEMONS = frozenset([MASTERD]) |
|
119 |
|
|
118 | 120 |
DAEMONS_PORTS = { |
119 | 121 |
# daemon-name: ("proto", "default-port") |
120 | 122 |
NODED: ("tcp", 1811), |
b/lib/daemon.py | ||
---|---|---|
26 | 26 |
import signal |
27 | 27 |
import errno |
28 | 28 |
import time |
29 |
import logging |
|
29 | 30 |
|
30 | 31 |
from ganeti import utils |
32 |
from ganeti import constants |
|
31 | 33 |
|
32 | 34 |
|
33 | 35 |
class Timer(object): |
... | ... | |
297 | 299 |
|
298 | 300 |
""" |
299 | 301 |
self._timer_remove.append(timer_id) |
302 |
|
|
303 |
|
|
304 |
def GenericMain(daemon_name, optionparser, dirs, check_fn, exec_fn): |
|
305 |
"""Shared main function for daemons. |
|
306 |
|
|
307 |
@type daemon_name: string |
|
308 |
@param daemon_name: daemon name |
|
309 |
@type optionparser: L{optparse.OptionParser} |
|
310 |
@param optionparser: initialized optionparser with daemon-specific options |
|
311 |
(common -f -d options will be handled by this module) |
|
312 |
@type options: object @param options: OptionParser result, should contain at |
|
313 |
least the fork and the debug options |
|
314 |
@type dirs: list of strings |
|
315 |
@param dirs: list of directories that must exist for this daemon to work |
|
316 |
@type check_fn: function which accepts (options, args) |
|
317 |
@param check_fn: function that checks start conditions and exits if they're |
|
318 |
not met |
|
319 |
@type exec_fn: function which accepts (options, args) |
|
320 |
@param exec_fn: function that's executed with the daemon's pid file held, and |
|
321 |
runs the daemon itself. |
|
322 |
|
|
323 |
""" |
|
324 |
optionparser.add_option("-f", "--foreground", dest="fork", |
|
325 |
help="Don't detach from the current terminal", |
|
326 |
default=True, action="store_false") |
|
327 |
optionparser.add_option("-d", "--debug", dest="debug", |
|
328 |
help="Enable some debug messages", |
|
329 |
default=False, action="store_true") |
|
330 |
if daemon_name in constants.DAEMONS_PORTS: |
|
331 |
# for networked daemons we also allow choosing the bind port and address. |
|
332 |
# by default we use the port provided by utils.GetDaemonPort, and bind to |
|
333 |
# 0.0.0.0 (which is represented by and empty bind address. |
|
334 |
port = utils.GetDaemonPort(daemon_name) |
|
335 |
optionparser.add_option("-p", "--port", dest="port", |
|
336 |
help="Network port (%s default)." % port, |
|
337 |
default=port, type="int") |
|
338 |
optionparser.add_option("-b", "--bind", dest="bind_address", |
|
339 |
help="Bind address", |
|
340 |
default="", metavar="ADDRESS") |
|
341 |
|
|
342 |
multithread = utils.no_fork = daemon_name in constants.MULTITHREADED_DAEMONS |
|
343 |
|
|
344 |
options, args = optionparser.parse_args() |
|
345 |
|
|
346 |
check_fn(options, args) |
|
347 |
utils.EnsureDirs(dirs) |
|
348 |
|
|
349 |
if options.fork: |
|
350 |
utils.CloseFDs() |
|
351 |
utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name]) |
|
352 |
|
|
353 |
utils.WritePidFile(daemon_name) |
|
354 |
try: |
|
355 |
utils.SetupLogging(logfile=constants.DAEMONS_LOGFILES[daemon_name], |
|
356 |
debug=options.debug, |
|
357 |
stderr_logging=not options.fork, |
|
358 |
multithreaded=multithread) |
|
359 |
logging.info("%s daemon startup" % daemon_name) |
|
360 |
exec_fn(options, args) |
|
361 |
finally: |
|
362 |
utils.RemovePidFile(daemon_name) |
|
363 |
|
Also available in: Unified diff