Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-confd @ 6b7d5878

History | View | Annotate | Download (12.2 kB)

1 b84cb9a0 Guido Trotter
#!/usr/bin/python
2 b84cb9a0 Guido Trotter
#
3 b84cb9a0 Guido Trotter
4 b84cb9a0 Guido Trotter
# Copyright (C) 2009, Google Inc.
5 b84cb9a0 Guido Trotter
#
6 b84cb9a0 Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 b84cb9a0 Guido Trotter
# it under the terms of the GNU General Public License as published by
8 b84cb9a0 Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 b84cb9a0 Guido Trotter
# (at your option) any later version.
10 b84cb9a0 Guido Trotter
#
11 b84cb9a0 Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 b84cb9a0 Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 b84cb9a0 Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 b84cb9a0 Guido Trotter
# General Public License for more details.
15 b84cb9a0 Guido Trotter
#
16 b84cb9a0 Guido Trotter
# You should have received a copy of the GNU General Public License
17 b84cb9a0 Guido Trotter
# along with this program; if not, write to the Free Software
18 b84cb9a0 Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 b84cb9a0 Guido Trotter
# 02110-1301, USA.
20 b84cb9a0 Guido Trotter
21 b84cb9a0 Guido Trotter
22 b84cb9a0 Guido Trotter
"""Ganeti configuration daemon
23 b84cb9a0 Guido Trotter
24 b84cb9a0 Guido Trotter
Ganeti-confd is a daemon to query master candidates for configuration values.
25 b84cb9a0 Guido Trotter
It uses UDP+HMAC for authentication with a global cluster key.
26 b84cb9a0 Guido Trotter
27 b84cb9a0 Guido Trotter
"""
28 b84cb9a0 Guido Trotter
29 7260cfbe Iustin Pop
# pylint: disable-msg=C0103
30 7260cfbe Iustin Pop
# C0103: Invalid name ganeti-confd
31 7260cfbe Iustin Pop
32 b84cb9a0 Guido Trotter
import os
33 b84cb9a0 Guido Trotter
import sys
34 b84cb9a0 Guido Trotter
import logging
35 e2be81cf Guido Trotter
import time
36 b84cb9a0 Guido Trotter
37 ad54f3d2 Guido Trotter
try:
38 7260cfbe Iustin Pop
  # pylint: disable-msg=E0611
39 ad54f3d2 Guido Trotter
  from pyinotify import pyinotify
40 ad54f3d2 Guido Trotter
except ImportError:
41 ad54f3d2 Guido Trotter
  import pyinotify
42 ad54f3d2 Guido Trotter
43 b84cb9a0 Guido Trotter
from optparse import OptionParser
44 b84cb9a0 Guido Trotter
45 e1081705 Guido Trotter
from ganeti import asyncnotifier
46 e1081705 Guido Trotter
from ganeti import confd
47 e1081705 Guido Trotter
from ganeti.confd import server as confd_server
48 b84cb9a0 Guido Trotter
from ganeti import constants
49 b84cb9a0 Guido Trotter
from ganeti import errors
50 b84cb9a0 Guido Trotter
from ganeti import daemon
51 b84cb9a0 Guido Trotter
52 b84cb9a0 Guido Trotter
53 5f3269fc Guido Trotter
class ConfdAsyncUDPServer(daemon.AsyncUDPSocket):
54 b84cb9a0 Guido Trotter
  """The confd udp server, suitable for use with asyncore.
55 b84cb9a0 Guido Trotter
56 b84cb9a0 Guido Trotter
  """
57 b84cb9a0 Guido Trotter
  def __init__(self, bind_address, port, processor):
58 b84cb9a0 Guido Trotter
    """Constructor for ConfdAsyncUDPServer
59 b84cb9a0 Guido Trotter
60 b84cb9a0 Guido Trotter
    @type bind_address: string
61 b84cb9a0 Guido Trotter
    @param bind_address: socket bind address ('' for all)
62 b84cb9a0 Guido Trotter
    @type port: int
63 b84cb9a0 Guido Trotter
    @param port: udp port
64 b84cb9a0 Guido Trotter
    @type processor: L{confd.server.ConfdProcessor}
65 fe759e4c Guido Trotter
    @param processor: ConfdProcessor to use to handle queries
66 b84cb9a0 Guido Trotter
67 b84cb9a0 Guido Trotter
    """
68 5f3269fc Guido Trotter
    daemon.AsyncUDPSocket.__init__(self)
69 b84cb9a0 Guido Trotter
    self.bind_address = bind_address
70 b84cb9a0 Guido Trotter
    self.port = port
71 b84cb9a0 Guido Trotter
    self.processor = processor
72 b84cb9a0 Guido Trotter
    self.bind((bind_address, port))
73 07b8a2b5 Iustin Pop
    logging.debug("listening on ('%s':%d)", bind_address, port)
74 b84cb9a0 Guido Trotter
75 5f3269fc Guido Trotter
  # this method is overriding a daemon.AsyncUDPSocket method
76 5f3269fc Guido Trotter
  def handle_datagram(self, payload_in, ip, port):
77 9748ab35 Guido Trotter
    try:
78 e1081705 Guido Trotter
      query = confd.UnpackMagic(payload_in)
79 9748ab35 Guido Trotter
    except errors.ConfdMagicError, err:
80 9748ab35 Guido Trotter
      logging.debug(err)
81 a3758ab2 Guido Trotter
      return
82 a3758ab2 Guido Trotter
83 a3758ab2 Guido Trotter
    answer =  self.processor.ExecQuery(query, ip, port)
84 a3758ab2 Guido Trotter
    if answer is not None:
85 86488201 Guido Trotter
      try:
86 e1081705 Guido Trotter
        self.enqueue_send(ip, port, confd.PackMagic(answer))
87 86488201 Guido Trotter
      except errors.UdpDataSizeError:
88 86488201 Guido Trotter
        logging.error("Reply too big to fit in an udp packet.")
89 b84cb9a0 Guido Trotter
90 b84cb9a0 Guido Trotter
91 b84cb9a0 Guido Trotter
class ConfdInotifyEventHandler(pyinotify.ProcessEvent):
92 b84cb9a0 Guido Trotter
93 4afe249b Guido Trotter
  def __init__(self, watch_manager, callback,
94 e2e10467 Iustin Pop
               filename=constants.CLUSTER_CONF_FILE):
95 b84cb9a0 Guido Trotter
    """Constructor for ConfdInotifyEventHandler
96 b84cb9a0 Guido Trotter
97 b84cb9a0 Guido Trotter
    @type watch_manager: L{pyinotify.WatchManager}
98 b84cb9a0 Guido Trotter
    @param watch_manager: ganeti-confd inotify watch manager
99 4afe249b Guido Trotter
    @type callback: function accepting a boolean
100 4afe249b Guido Trotter
    @param callback: function to call when an inotify event happens
101 e2e10467 Iustin Pop
    @type filename: string
102 e2e10467 Iustin Pop
    @param filename: config file to watch
103 b84cb9a0 Guido Trotter
104 b84cb9a0 Guido Trotter
    """
105 4eea1739 Guido Trotter
    # pylint: disable-msg=W0231
106 b84cb9a0 Guido Trotter
    # no need to call the parent's constructor
107 b84cb9a0 Guido Trotter
    self.watch_manager = watch_manager
108 4afe249b Guido Trotter
    self.callback = callback
109 7260cfbe Iustin Pop
    # pylint: disable-msg=E1103
110 7260cfbe Iustin Pop
    # pylint for some reason doesn't see the below constants
111 b84cb9a0 Guido Trotter
    self.mask = pyinotify.EventsCodes.IN_IGNORED | \
112 b84cb9a0 Guido Trotter
                pyinotify.EventsCodes.IN_MODIFY
113 e2e10467 Iustin Pop
    self.file = filename
114 46c9b31d Guido Trotter
    self.watch_handle = None
115 b84cb9a0 Guido Trotter
116 46c9b31d Guido Trotter
  def enable(self):
117 46c9b31d Guido Trotter
    """Watch the given file
118 b84cb9a0 Guido Trotter
119 b84cb9a0 Guido Trotter
    """
120 46c9b31d Guido Trotter
    if self.watch_handle is None:
121 46c9b31d Guido Trotter
      result = self.watch_manager.add_watch(self.file, self.mask)
122 46c9b31d Guido Trotter
      if not self.file in result or result[self.file] <= 0:
123 ef4ca33b Guido Trotter
        raise errors.InotifyError("Could not add inotify watcher")
124 46c9b31d Guido Trotter
      else:
125 46c9b31d Guido Trotter
        self.watch_handle = result[self.file]
126 46c9b31d Guido Trotter
127 46c9b31d Guido Trotter
  def disable(self):
128 46c9b31d Guido Trotter
    """Stop watching the given file
129 46c9b31d Guido Trotter
130 46c9b31d Guido Trotter
    """
131 46c9b31d Guido Trotter
    if self.watch_handle is not None:
132 46c9b31d Guido Trotter
      result = self.watch_manager.rm_watch(self.watch_handle)
133 46c9b31d Guido Trotter
      if result[self.watch_handle]:
134 46c9b31d Guido Trotter
        self.watch_handle = None
135 b84cb9a0 Guido Trotter
136 b84cb9a0 Guido Trotter
  def process_IN_IGNORED(self, event):
137 b84cb9a0 Guido Trotter
    # Due to the fact that we monitor just for the cluster config file (rather
138 b84cb9a0 Guido Trotter
    # than for the whole data dir) when the file is replaced with another one
139 b84cb9a0 Guido Trotter
    # (which is what happens normally in ganeti) we're going to receive an
140 b84cb9a0 Guido Trotter
    # IN_IGNORED event from inotify, because of the file removal (which is
141 b84cb9a0 Guido Trotter
    # contextual with the replacement). In such a case we need to create
142 b84cb9a0 Guido Trotter
    # another watcher for the "new" file.
143 07b8a2b5 Iustin Pop
    logging.debug("Received 'ignored' inotify event for %s", event.path)
144 46c9b31d Guido Trotter
    self.watch_handle = None
145 b84cb9a0 Guido Trotter
146 b84cb9a0 Guido Trotter
    try:
147 b84cb9a0 Guido Trotter
      # Since the kernel believes the file we were interested in is gone, it's
148 b84cb9a0 Guido Trotter
      # not going to notify us of any other events, until we set up, here, the
149 b84cb9a0 Guido Trotter
      # new watch. This is not a race condition, though, since we're anyway
150 b84cb9a0 Guido Trotter
      # going to realod the file after setting up the new watch.
151 4afe249b Guido Trotter
      self.callback(False)
152 b84cb9a0 Guido Trotter
    except errors.ConfdFatalError, err:
153 07b8a2b5 Iustin Pop
      logging.critical("Critical error, shutting down: %s", err)
154 b84cb9a0 Guido Trotter
      sys.exit(constants.EXIT_FAILURE)
155 b84cb9a0 Guido Trotter
    except:
156 b84cb9a0 Guido Trotter
      # we need to catch any exception here, log it, but proceed, because even
157 b84cb9a0 Guido Trotter
      # if we failed handling a single request, we still want the confd to
158 b84cb9a0 Guido Trotter
      # continue working.
159 b84cb9a0 Guido Trotter
      logging.error("Unexpected exception", exc_info=True)
160 b84cb9a0 Guido Trotter
161 b84cb9a0 Guido Trotter
  def process_IN_MODIFY(self, event):
162 b84cb9a0 Guido Trotter
    # This gets called when the config file is modified. Note that this doesn't
163 b84cb9a0 Guido Trotter
    # usually happen in Ganeti, as the config file is normally replaced by a
164 b84cb9a0 Guido Trotter
    # new one, at filesystem level, rather than actually modified (see
165 b84cb9a0 Guido Trotter
    # utils.WriteFile)
166 07b8a2b5 Iustin Pop
    logging.debug("Received 'modify' inotify event for %s", event.path)
167 b84cb9a0 Guido Trotter
168 b84cb9a0 Guido Trotter
    try:
169 4afe249b Guido Trotter
      self.callback(True)
170 b84cb9a0 Guido Trotter
    except errors.ConfdFatalError, err:
171 07b8a2b5 Iustin Pop
      logging.critical("Critical error, shutting down: %s", err)
172 b84cb9a0 Guido Trotter
      sys.exit(constants.EXIT_FAILURE)
173 b84cb9a0 Guido Trotter
    except:
174 b84cb9a0 Guido Trotter
      # we need to catch any exception here, log it, but proceed, because even
175 b84cb9a0 Guido Trotter
      # if we failed handling a single request, we still want the confd to
176 b84cb9a0 Guido Trotter
      # continue working.
177 b84cb9a0 Guido Trotter
      logging.error("Unexpected exception", exc_info=True)
178 b84cb9a0 Guido Trotter
179 b84cb9a0 Guido Trotter
  def process_default(self, event):
180 07b8a2b5 Iustin Pop
    logging.error("Received unhandled inotify event: %s", event)
181 b84cb9a0 Guido Trotter
182 b84cb9a0 Guido Trotter
183 562bee4d Guido Trotter
class ConfdConfigurationReloader(object):
184 562bee4d Guido Trotter
  """Logic to control when to reload the ganeti configuration
185 562bee4d Guido Trotter
186 562bee4d Guido Trotter
  This class is able to alter between inotify and polling, to rate-limit the
187 562bee4d Guido Trotter
  number of reloads. When using inotify it also supports a fallback timed
188 562bee4d Guido Trotter
  check, to verify that the reload hasn't failed.
189 562bee4d Guido Trotter
190 562bee4d Guido Trotter
  """
191 05f1ebf3 Guido Trotter
  def __init__(self, processor, mainloop):
192 562bee4d Guido Trotter
    """Constructor for ConfdConfigurationReloader
193 562bee4d Guido Trotter
194 05f1ebf3 Guido Trotter
    @type processor: L{confd.server.ConfdProcessor}
195 05f1ebf3 Guido Trotter
    @param processor: ganeti-confd ConfdProcessor
196 e2be81cf Guido Trotter
    @type mainloop: L{daemon.Mainloop}
197 e2be81cf Guido Trotter
    @param mainloop: ganeti-confd mainloop
198 562bee4d Guido Trotter
199 562bee4d Guido Trotter
    """
200 05f1ebf3 Guido Trotter
    self.processor = processor
201 e2be81cf Guido Trotter
    self.mainloop = mainloop
202 e2be81cf Guido Trotter
203 c6259dbc Guido Trotter
    self.polling = True
204 e2be81cf Guido Trotter
    self.last_notification = 0
205 562bee4d Guido Trotter
206 562bee4d Guido Trotter
    # Asyncronous inotify handler for config changes
207 562bee4d Guido Trotter
    self.wm = pyinotify.WatchManager()
208 4afe249b Guido Trotter
    self.inotify_handler = ConfdInotifyEventHandler(self.wm, self.OnInotify)
209 e1081705 Guido Trotter
    self.notifier = asyncnotifier.AsyncNotifier(self.wm, self.inotify_handler)
210 4afe249b Guido Trotter
211 e2be81cf Guido Trotter
    self.timer_handle = None
212 e2be81cf Guido Trotter
    self._EnableTimer()
213 e2be81cf Guido Trotter
214 4afe249b Guido Trotter
  def OnInotify(self, notifier_enabled):
215 4afe249b Guido Trotter
    """Receive an inotify notification.
216 4afe249b Guido Trotter
217 4afe249b Guido Trotter
    @type notifier_enabled: boolean
218 4afe249b Guido Trotter
    @param notifier_enabled: whether the notifier is still enabled
219 4afe249b Guido Trotter
220 4afe249b Guido Trotter
    """
221 e2be81cf Guido Trotter
    current_time = time.time()
222 e2be81cf Guido Trotter
    time_delta = current_time - self.last_notification
223 e2be81cf Guido Trotter
    self.last_notification = current_time
224 e2be81cf Guido Trotter
225 e2be81cf Guido Trotter
    if time_delta < constants.CONFD_CONFIG_RELOAD_RATELIMIT:
226 e2be81cf Guido Trotter
      logging.debug("Moving from inotify mode to polling mode")
227 e2be81cf Guido Trotter
      self.polling = True
228 e2be81cf Guido Trotter
      if notifier_enabled:
229 176d3122 Guido Trotter
        self.inotify_handler.disable()
230 e2be81cf Guido Trotter
231 e2be81cf Guido Trotter
    if not self.polling and not notifier_enabled:
232 ef4ca33b Guido Trotter
      try:
233 ef4ca33b Guido Trotter
        self.inotify_handler.enable()
234 ef4ca33b Guido Trotter
      except errors.InotifyError:
235 22d3e184 Guido Trotter
        self.polling = True
236 4afe249b Guido Trotter
237 4afe249b Guido Trotter
    try:
238 05f1ebf3 Guido Trotter
      reloaded = self.processor.reader.Reload()
239 4afe249b Guido Trotter
      if reloaded:
240 4afe249b Guido Trotter
        logging.info("Reloaded ganeti config")
241 4afe249b Guido Trotter
      else:
242 4afe249b Guido Trotter
        logging.debug("Skipped double config reload")
243 4afe249b Guido Trotter
    except errors.ConfigurationError:
244 22d3e184 Guido Trotter
      self.DisableConfd()
245 22d3e184 Guido Trotter
      self.inotify_handler.disable()
246 22d3e184 Guido Trotter
      return
247 4afe249b Guido Trotter
248 e2be81cf Guido Trotter
    # Reset the timer. If we're polling it will go to the polling rate, if
249 e2be81cf Guido Trotter
    # we're not it will delay it again to its base safe timeout.
250 22d3e184 Guido Trotter
    self._ResetTimer()
251 e2be81cf Guido Trotter
252 e2be81cf Guido Trotter
  def _DisableTimer(self):
253 e2be81cf Guido Trotter
    if self.timer_handle is not None:
254 e2be81cf Guido Trotter
      self.mainloop.scheduler.cancel(self.timer_handle)
255 e2be81cf Guido Trotter
      self.timer_handle = None
256 e2be81cf Guido Trotter
257 e2be81cf Guido Trotter
  def _EnableTimer(self):
258 e2be81cf Guido Trotter
    if self.polling:
259 e2be81cf Guido Trotter
      timeout = constants.CONFD_CONFIG_RELOAD_RATELIMIT
260 e2be81cf Guido Trotter
    else:
261 e2be81cf Guido Trotter
      timeout = constants.CONFD_CONFIG_RELOAD_TIMEOUT
262 e2be81cf Guido Trotter
263 e2be81cf Guido Trotter
    if self.timer_handle is None:
264 e2be81cf Guido Trotter
      self.timer_handle = self.mainloop.scheduler.enter(
265 e2be81cf Guido Trotter
        timeout, 1, self.OnTimer, [])
266 e2be81cf Guido Trotter
267 22d3e184 Guido Trotter
  def _ResetTimer(self):
268 22d3e184 Guido Trotter
    self._DisableTimer()
269 22d3e184 Guido Trotter
    self._EnableTimer()
270 22d3e184 Guido Trotter
271 e2be81cf Guido Trotter
  def OnTimer(self):
272 e2be81cf Guido Trotter
    """Function called when the timer fires
273 e2be81cf Guido Trotter
274 e2be81cf Guido Trotter
    """
275 e2be81cf Guido Trotter
    self.timer_handle = None
276 22d3e184 Guido Trotter
    reloaded = False
277 22d3e184 Guido Trotter
    was_disabled = False
278 e2be81cf Guido Trotter
    try:
279 22d3e184 Guido Trotter
      if self.processor.reader is None:
280 22d3e184 Guido Trotter
        was_disabled = True
281 22d3e184 Guido Trotter
        self.EnableConfd()
282 22d3e184 Guido Trotter
        reloaded = True
283 22d3e184 Guido Trotter
      else:
284 22d3e184 Guido Trotter
        reloaded = self.processor.reader.Reload()
285 e2be81cf Guido Trotter
    except errors.ConfigurationError:
286 a544f755 Guido Trotter
      self.DisableConfd(silent=was_disabled)
287 22d3e184 Guido Trotter
      return
288 e2be81cf Guido Trotter
289 e2be81cf Guido Trotter
    if self.polling and reloaded:
290 e2be81cf Guido Trotter
      logging.info("Reloaded ganeti config")
291 e2be81cf Guido Trotter
    elif reloaded:
292 e2be81cf Guido Trotter
      # We have reloaded the config files, but received no inotify event.  If
293 e2be81cf Guido Trotter
      # an event is pending though, we just happen to have timed out before
294 e2be81cf Guido Trotter
      # receiving it, so this is not a problem, and we shouldn't alert
295 22d3e184 Guido Trotter
      if not self.notifier.check_events() and not was_disabled:
296 e2be81cf Guido Trotter
        logging.warning("Config file reload at timeout (inotify failure)")
297 e2be81cf Guido Trotter
    elif self.polling:
298 e2be81cf Guido Trotter
      # We're polling, but we haven't reloaded the config:
299 e2be81cf Guido Trotter
      # Going back to inotify mode
300 e2be81cf Guido Trotter
      logging.debug("Moving from polling mode to inotify mode")
301 e2be81cf Guido Trotter
      self.polling = False
302 22d3e184 Guido Trotter
      try:
303 22d3e184 Guido Trotter
        self.inotify_handler.enable()
304 22d3e184 Guido Trotter
      except errors.InotifyError:
305 22d3e184 Guido Trotter
        self.polling = True
306 e2be81cf Guido Trotter
    else:
307 e2be81cf Guido Trotter
      logging.debug("Performed configuration check")
308 e2be81cf Guido Trotter
309 e2be81cf Guido Trotter
    self._EnableTimer()
310 562bee4d Guido Trotter
311 a544f755 Guido Trotter
  def DisableConfd(self, silent=False):
312 22d3e184 Guido Trotter
    """Puts confd in non-serving mode
313 22d3e184 Guido Trotter
314 22d3e184 Guido Trotter
    """
315 a544f755 Guido Trotter
    if not silent:
316 a544f755 Guido Trotter
      logging.warning("Confd is being disabled")
317 22d3e184 Guido Trotter
    self.processor.Disable()
318 22d3e184 Guido Trotter
    self.polling = False
319 22d3e184 Guido Trotter
    self._ResetTimer()
320 22d3e184 Guido Trotter
321 22d3e184 Guido Trotter
  def EnableConfd(self):
322 22d3e184 Guido Trotter
    self.processor.Enable()
323 22d3e184 Guido Trotter
    logging.warning("Confd is being enabled")
324 22d3e184 Guido Trotter
    self.polling = True
325 22d3e184 Guido Trotter
    self._ResetTimer()
326 22d3e184 Guido Trotter
327 562bee4d Guido Trotter
328 2d54e29c Iustin Pop
def CheckConfd(_, args):
329 6c948699 Michael Hanselmann
  """Initial checks whether to run exit with a failure.
330 b84cb9a0 Guido Trotter
331 b84cb9a0 Guido Trotter
  """
332 f93427cd Iustin Pop
  if args: # confd doesn't take any arguments
333 f93427cd Iustin Pop
    print >> sys.stderr, ("Usage: %s [-f] [-d] [-b ADDRESS]" % sys.argv[0])
334 f93427cd Iustin Pop
    sys.exit(constants.EXIT_FAILURE)
335 f93427cd Iustin Pop
336 b84cb9a0 Guido Trotter
  # TODO: collapse HMAC daemons handling in daemons GenericMain, when we'll
337 b84cb9a0 Guido Trotter
  # have more than one.
338 6b7d5878 Michael Hanselmann
  if not os.path.isfile(constants.CONFD_HMAC_KEY):
339 6b7d5878 Michael Hanselmann
    print >> sys.stderr, "Need HMAC key %s to run" % constants.CONFD_HMAC_KEY
340 b84cb9a0 Guido Trotter
    sys.exit(constants.EXIT_FAILURE)
341 b84cb9a0 Guido Trotter
342 b84cb9a0 Guido Trotter
343 2d54e29c Iustin Pop
def ExecConfd(options, _):
344 6c948699 Michael Hanselmann
  """Main confd function, executed with PID file held
345 b84cb9a0 Guido Trotter
346 b84cb9a0 Guido Trotter
  """
347 c9ca81c9 Iustin Pop
  # TODO: clarify how the server and reloader variables work (they are
348 c9ca81c9 Iustin Pop
  # not used)
349 c9ca81c9 Iustin Pop
  # pylint: disable-msg=W0612
350 f91c7223 Guido Trotter
  mainloop = daemon.Mainloop()
351 f91c7223 Guido Trotter
352 b84cb9a0 Guido Trotter
  # Asyncronous confd UDP server
353 e1081705 Guido Trotter
  processor = confd_server.ConfdProcessor()
354 e369f21d Guido Trotter
  try:
355 e369f21d Guido Trotter
    processor.Enable()
356 e369f21d Guido Trotter
  except errors.ConfigurationError:
357 4d4a651d Michael Hanselmann
    # If enabling the processor has failed, we can still go on, but confd will
358 4d4a651d Michael Hanselmann
    # be disabled
359 a544f755 Guido Trotter
    logging.warning("Confd is starting in disabled mode")
360 2d54e29c Iustin Pop
361 b84cb9a0 Guido Trotter
  server = ConfdAsyncUDPServer(options.bind_address, options.port, processor)
362 b84cb9a0 Guido Trotter
363 562bee4d Guido Trotter
  # Configuration reloader
364 05f1ebf3 Guido Trotter
  reloader = ConfdConfigurationReloader(processor, mainloop)
365 f91c7223 Guido Trotter
366 f91c7223 Guido Trotter
  mainloop.Run()
367 b84cb9a0 Guido Trotter
368 b84cb9a0 Guido Trotter
369 b84cb9a0 Guido Trotter
def main():
370 b84cb9a0 Guido Trotter
  """Main function for the confd daemon.
371 b84cb9a0 Guido Trotter
372 b84cb9a0 Guido Trotter
  """
373 b84cb9a0 Guido Trotter
  parser = OptionParser(description="Ganeti configuration daemon",
374 b84cb9a0 Guido Trotter
                        usage="%prog [-f] [-d] [-b ADDRESS]",
375 b84cb9a0 Guido Trotter
                        version="%%prog (ganeti) %s" %
376 b84cb9a0 Guido Trotter
                        constants.RELEASE_VERSION)
377 b84cb9a0 Guido Trotter
378 b84cb9a0 Guido Trotter
  dirs = [(val, constants.RUN_DIRS_MODE) for val in constants.SUB_RUN_DIRS]
379 b84cb9a0 Guido Trotter
  dirs.append((constants.LOCK_DIR, 1777))
380 6c948699 Michael Hanselmann
  daemon.GenericMain(constants.CONFD, parser, dirs, CheckConfd, ExecConfd)
381 b84cb9a0 Guido Trotter
382 b84cb9a0 Guido Trotter
383 6c948699 Michael Hanselmann
if __name__ == "__main__":
384 b84cb9a0 Guido Trotter
  main()