From 4afe249ba9f4ec4fbb1472031490d38091faf97b Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Sun, 23 Aug 2009 16:50:01 +0100 Subject: [PATCH] ConfdInotifyEventHandler, move to a callback ConfdInotifyEventHandler used to reload the config whenever a notification arrived. Moving to a callback system, so that ConfdConfigurationReloader can be responsible for that functionality. Additionally the inotify class no longer reenables itself automatically, but just notifies the callback if it's been disabled, and waits for its call to enable(). This allows, should ConfdConfigurationReloader decide it wants to move to polling, to avoid having a double enable()/disable() call. Signed-off-by: Guido Trotter <ultrotter@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- daemons/ganeti-confd | 51 ++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/daemons/ganeti-confd b/daemons/ganeti-confd index a0e6a0c86..9deb1232f 100755 --- a/daemons/ganeti-confd +++ b/daemons/ganeti-confd @@ -95,21 +95,21 @@ class ConfdAsyncUDPServer(asyncore.dispatcher): class ConfdInotifyEventHandler(pyinotify.ProcessEvent): - def __init__(self, watch_manager, reader, + def __init__(self, watch_manager, callback, file=constants.CLUSTER_CONF_FILE): """Constructor for ConfdInotifyEventHandler @type watch_manager: L{pyinotify.WatchManager} @param watch_manager: ganeti-confd inotify watch manager - @type reader: L{ssconf.SimpleConfigReader} - @param reader: ganeti-confd SimpleConfigReader + @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 """ # no need to call the parent's constructor self.watch_manager = watch_manager - self.reader = reader + self.callback = callback self.mask = pyinotify.EventsCodes.IN_IGNORED | \ pyinotify.EventsCodes.IN_MODIFY self.file = file @@ -136,18 +136,6 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): if result[self.watch_handle]: self.watch_handle = None - def reload_config(self): - try: - reloaded = self.reader.Reload() - if reloaded: - logging.info("Reloaded ganeti config") - else: - logging.debug("Skipped double config reload") - except errors.ConfigurationError: - # transform a ConfigurationError in a fatal error, that will cause confd - # to quit. - raise errors.ConfdFatalError(err) - def process_IN_IGNORED(self, event): # Due to the fact that we monitor just for the cluster config file (rather # than for the whole data dir) when the file is replaced with another one @@ -163,8 +151,7 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): # not going to notify us of any other events, until we set up, here, the # new watch. This is not a race condition, though, since we're anyway # going to realod the file after setting up the new watch. - self.enable() - self.reload_config() + self.callback(False) except errors.ConfdFatalError, err: logging.critical("Critical error, shutting down: %s" % err) sys.exit(constants.EXIT_FAILURE) @@ -182,7 +169,7 @@ class ConfdInotifyEventHandler(pyinotify.ProcessEvent): logging.debug("Received 'modify' inotify event for %s" % event.path) try: - self.reload_config() + self.callback(True) except errors.ConfdFatalError, err: logging.critical("Critical error, shutting down: %s" % err) sys.exit(constants.EXIT_FAILURE) @@ -215,8 +202,30 @@ class ConfdConfigurationReloader(object): # Asyncronous inotify handler for config changes self.wm = pyinotify.WatchManager() - self.inotify_handler = ConfdInotifyEventHandler(self.wm, reader) - self.notifier = AsyncNotifier(self.wm, self.confd_event_handler) + self.inotify_handler = ConfdInotifyEventHandler(self.wm, self.OnInotify) + self.notifier = AsyncNotifier(self.wm, self.inotify_handler) + + def OnInotify(self, notifier_enabled): + """Receive an inotify notification. + + @type notifier_enabled: boolean + @param notifier_enabled: whether the notifier is still enabled + + """ + if not notifier_enabled: + self.inotify_handler.enable() + + try: + reloaded = self.reader.Reload() + if reloaded: + logging.info("Reloaded ganeti config") + else: + logging.debug("Skipped double config reload") + except errors.ConfigurationError: + # transform a ConfigurationError in a fatal error, that will cause confd + # to quit. + raise errors.ConfdFatalError(err) + def CheckConfd(options, args): -- GitLab