Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-confd @ 0648750e

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