X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/fe759e4c195bce5bef72068075a8710c32b20909..b13dfb92ab93b63c3feb238d27e8b5cd2a495fce:/daemons/ganeti-confd diff --git a/daemons/ganeti-confd b/daemons/ganeti-confd index c08426e..b7198d0 100755 --- a/daemons/ganeti-confd +++ b/daemons/ganeti-confd @@ -26,23 +26,28 @@ It uses UDP+HMAC for authentication with a global cluster key. """ +# pylint: disable-msg=C0103 +# C0103: Invalid name ganeti-confd + import os import sys import logging -import asyncore -import socket -import pyinotify import time -import errno + +try: + # pylint: disable-msg=E0611 + from pyinotify import pyinotify +except ImportError: + import pyinotify from optparse import OptionParser +from ganeti import asyncnotifier +from ganeti import confd +from ganeti.confd import server as confd_server from ganeti import constants from ganeti import errors from ganeti import daemon -from ganeti import ssconf -from ganeti.asyncnotifier import AsyncNotifier -from ganeti.confd.server import ConfdProcessor class ConfdAsyncUDPServer(daemon.AsyncUDPSocket): @@ -65,35 +70,46 @@ class ConfdAsyncUDPServer(daemon.AsyncUDPSocket): self.port = port self.processor = processor self.bind((bind_address, port)) - logging.debug("listening on ('%s':%d)" % (bind_address, port)) + logging.debug("listening on ('%s':%d)", bind_address, port) # this method is overriding a daemon.AsyncUDPSocket method def handle_datagram(self, payload_in, ip, port): - payload_out = self.processor.ExecQuery(payload_in, ip, port) - if payload_out is not None: - self.enqueue_send(ip, port, payload_out) + try: + query = confd.UnpackMagic(payload_in) + except errors.ConfdMagicError, err: + logging.debug(err) + return + + answer = self.processor.ExecQuery(query, ip, port) + if answer is not None: + try: + self.enqueue_send(ip, port, confd.PackMagic(answer)) + except errors.UdpDataSizeError: + logging.error("Reply too big to fit in an udp packet.") class ConfdInotifyEventHandler(pyinotify.ProcessEvent): def __init__(self, watch_manager, callback, - file=constants.CLUSTER_CONF_FILE): + filename=constants.CLUSTER_CONF_FILE): """Constructor for ConfdInotifyEventHandler @type watch_manager: L{pyinotify.WatchManager} @param watch_manager: ganeti-confd inotify watch manager @type callback: function accepting a boolean @param callback: function to call when an inotify event happens - @type file: string - @param file: config file to watch + @type filename: string + @param filename: config file to watch """ # no need to call the parent's constructor self.watch_manager = watch_manager self.callback = callback + # pylint: disable-msg=E1103 + # pylint for some reason doesn't see the below constants self.mask = pyinotify.EventsCodes.IN_IGNORED | \ pyinotify.EventsCodes.IN_MODIFY - self.file = file + self.file = filename self.watch_handle = None def enable(self): @@ -123,7 +139,7 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): # IN_IGNORED event from inotify, because of the file removal (which is # contextual with the replacement). In such a case we need to create # another watcher for the "new" file. - logging.debug("Received 'ignored' inotify event for %s" % event.path) + logging.debug("Received 'ignored' inotify event for %s", event.path) self.watch_handle = None try: @@ -133,7 +149,7 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): # going to realod the file after setting up the new watch. self.callback(False) except errors.ConfdFatalError, err: - logging.critical("Critical error, shutting down: %s" % err) + logging.critical("Critical error, shutting down: %s", err) sys.exit(constants.EXIT_FAILURE) except: # we need to catch any exception here, log it, but proceed, because even @@ -146,12 +162,12 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): # usually happen in Ganeti, as the config file is normally replaced by a # new one, at filesystem level, rather than actually modified (see # utils.WriteFile) - logging.debug("Received 'modify' inotify event for %s" % event.path) + logging.debug("Received 'modify' inotify event for %s", event.path) try: self.callback(True) except errors.ConfdFatalError, err: - logging.critical("Critical error, shutting down: %s" % err) + logging.critical("Critical error, shutting down: %s", err) sys.exit(constants.EXIT_FAILURE) except: # we need to catch any exception here, log it, but proceed, because even @@ -160,7 +176,7 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): logging.error("Unexpected exception", exc_info=True) def process_default(self, event): - logging.error("Received unhandled inotify event: %s" % event) + logging.error("Received unhandled inotify event: %s", event) class ConfdConfigurationReloader(object): @@ -189,7 +205,7 @@ class ConfdConfigurationReloader(object): # Asyncronous inotify handler for config changes self.wm = pyinotify.WatchManager() self.inotify_handler = ConfdInotifyEventHandler(self.wm, self.OnInotify) - self.notifier = AsyncNotifier(self.wm, self.inotify_handler) + self.notifier = asyncnotifier.AsyncNotifier(self.wm, self.inotify_handler) self.timer_handle = None self._EnableTimer() @@ -308,10 +324,14 @@ class ConfdConfigurationReloader(object): self._ResetTimer() -def CheckConfd(options, args): +def CheckConfd(_, args): """Initial checks whether to run exit with a failure. """ + if args: # confd doesn't take any arguments + print >> sys.stderr, ("Usage: %s [-f] [-d] [-b ADDRESS]" % sys.argv[0]) + sys.exit(constants.EXIT_FAILURE) + # TODO: collapse HMAC daemons handling in daemons GenericMain, when we'll # have more than one. if not os.path.isfile(constants.HMAC_CLUSTER_KEY): @@ -319,21 +339,24 @@ def CheckConfd(options, args): sys.exit(constants.EXIT_FAILURE) -def ExecConfd(options, args): +def ExecConfd(options, _): """Main confd function, executed with PID file held """ + # TODO: clarify how the server and reloader variables work (they are + # not used) + # pylint: disable-msg=W0612 mainloop = daemon.Mainloop() # Asyncronous confd UDP server - processor = ConfdProcessor() + processor = confd_server.ConfdProcessor() try: processor.Enable() except errors.ConfigurationError: # If enabling the processor has failed, we can still go on, but confd will # be disabled logging.warning("Confd is starting in disabled mode") - pass + server = ConfdAsyncUDPServer(options.bind_address, options.port, processor) # Configuration reloader @@ -352,7 +375,6 @@ def main(): constants.RELEASE_VERSION) dirs = [(val, constants.RUN_DIRS_MODE) for val in constants.SUB_RUN_DIRS] - dirs.append((constants.LOG_OS_DIR, 0750)) dirs.append((constants.LOCK_DIR, 1777)) daemon.GenericMain(constants.CONFD, parser, dirs, CheckConfd, ExecConfd)