Revision e2be81cf daemons/ganeti-confd
b/daemons/ganeti-confd | ||
---|---|---|
32 | 32 |
import asyncore |
33 | 33 |
import socket |
34 | 34 |
import pyinotify |
35 |
import time |
|
35 | 36 |
|
36 | 37 |
from optparse import OptionParser |
37 | 38 |
|
... | ... | |
191 | 192 |
check, to verify that the reload hasn't failed. |
192 | 193 |
|
193 | 194 |
""" |
194 |
def __init__(self, reader): |
|
195 |
def __init__(self, reader, mainloop):
|
|
195 | 196 |
"""Constructor for ConfdConfigurationReloader |
196 | 197 |
|
197 | 198 |
@type reader: L{ssconf.SimpleConfigReader} |
198 | 199 |
@param reader: ganeti-confd SimpleConfigReader |
200 |
@type mainloop: L{daemon.Mainloop} |
|
201 |
@param mainloop: ganeti-confd mainloop |
|
199 | 202 |
|
200 | 203 |
""" |
201 | 204 |
self.reader = reader |
205 |
self.mainloop = mainloop |
|
206 |
|
|
207 |
self.polling = False |
|
208 |
self.last_notification = 0 |
|
202 | 209 |
|
203 | 210 |
# Asyncronous inotify handler for config changes |
204 | 211 |
self.wm = pyinotify.WatchManager() |
205 | 212 |
self.inotify_handler = ConfdInotifyEventHandler(self.wm, self.OnInotify) |
206 | 213 |
self.notifier = AsyncNotifier(self.wm, self.inotify_handler) |
207 | 214 |
|
215 |
self.timer_handle = None |
|
216 |
self._EnableTimer() |
|
217 |
|
|
208 | 218 |
def OnInotify(self, notifier_enabled): |
209 | 219 |
"""Receive an inotify notification. |
210 | 220 |
|
... | ... | |
212 | 222 |
@param notifier_enabled: whether the notifier is still enabled |
213 | 223 |
|
214 | 224 |
""" |
215 |
if not notifier_enabled: |
|
225 |
current_time = time.time() |
|
226 |
time_delta = current_time - self.last_notification |
|
227 |
self.last_notification = current_time |
|
228 |
|
|
229 |
if time_delta < constants.CONFD_CONFIG_RELOAD_RATELIMIT: |
|
230 |
logging.debug("Moving from inotify mode to polling mode") |
|
231 |
self.polling = True |
|
232 |
if notifier_enabled: |
|
233 |
self.confd_event_handler.disable() |
|
234 |
|
|
235 |
if not self.polling and not notifier_enabled: |
|
216 | 236 |
try: |
217 | 237 |
self.inotify_handler.enable() |
218 | 238 |
except errors.InotifyError: |
... | ... | |
229 | 249 |
# to quit. |
230 | 250 |
raise errors.ConfdFatalError(err) |
231 | 251 |
|
252 |
# Reset the timer. If we're polling it will go to the polling rate, if |
|
253 |
# we're not it will delay it again to its base safe timeout. |
|
254 |
self._DisableTimer() |
|
255 |
self._EnableTimer() |
|
256 |
|
|
257 |
def _DisableTimer(self): |
|
258 |
if self.timer_handle is not None: |
|
259 |
self.mainloop.scheduler.cancel(self.timer_handle) |
|
260 |
self.timer_handle = None |
|
261 |
|
|
262 |
def _EnableTimer(self): |
|
263 |
if self.polling: |
|
264 |
timeout = constants.CONFD_CONFIG_RELOAD_RATELIMIT |
|
265 |
else: |
|
266 |
timeout = constants.CONFD_CONFIG_RELOAD_TIMEOUT |
|
267 |
|
|
268 |
if self.timer_handle is None: |
|
269 |
self.timer_handle = self.mainloop.scheduler.enter( |
|
270 |
timeout, 1, self.OnTimer, []) |
|
271 |
|
|
272 |
def OnTimer(self): |
|
273 |
"""Function called when the timer fires |
|
274 |
|
|
275 |
""" |
|
276 |
self.timer_handle = None |
|
277 |
try: |
|
278 |
reloaded = self.reader.Reload() |
|
279 |
except errors.ConfigurationError: |
|
280 |
# transform a ConfigurationError in a fatal error, that will cause confd |
|
281 |
# to quit. |
|
282 |
raise errors.ConfdFatalError(err) |
|
283 |
|
|
284 |
if self.polling and reloaded: |
|
285 |
logging.info("Reloaded ganeti config") |
|
286 |
elif reloaded: |
|
287 |
# We have reloaded the config files, but received no inotify event. If |
|
288 |
# an event is pending though, we just happen to have timed out before |
|
289 |
# receiving it, so this is not a problem, and we shouldn't alert |
|
290 |
if not self.notifier.check_events(): |
|
291 |
logging.warning("Config file reload at timeout (inotify failure)") |
|
292 |
elif self.polling: |
|
293 |
# We're polling, but we haven't reloaded the config: |
|
294 |
# Going back to inotify mode |
|
295 |
logging.debug("Moving from polling mode to inotify mode") |
|
296 |
self.polling = False |
|
297 |
self.inotify_handler.enable() |
|
298 |
else: |
|
299 |
logging.debug("Performed configuration check") |
|
300 |
|
|
301 |
self._EnableTimer() |
|
232 | 302 |
|
233 | 303 |
|
234 | 304 |
def CheckConfd(options, args): |
... | ... | |
258 | 328 |
server = ConfdAsyncUDPServer(options.bind_address, options.port, processor) |
259 | 329 |
|
260 | 330 |
# Configuration reloader |
261 |
reloader = ConfdConfigurationReloader(reader) |
|
331 |
reloader = ConfdConfigurationReloader(reader, mainloop)
|
|
262 | 332 |
|
263 | 333 |
mainloop.Run() |
264 | 334 |
|
Also available in: Unified diff