Statistics
| Branch: | Tag: | Revision:

root / lib / daemon.py @ 1fe93c75

History | View | Annotate | Download (11.8 kB)

1 821d9e43 Michael Hanselmann
#
2 821d9e43 Michael Hanselmann
#
3 821d9e43 Michael Hanselmann
4 821d9e43 Michael Hanselmann
# Copyright (C) 2006, 2007, 2008 Google Inc.
5 821d9e43 Michael Hanselmann
#
6 821d9e43 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 821d9e43 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 821d9e43 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 821d9e43 Michael Hanselmann
# (at your option) any later version.
10 821d9e43 Michael Hanselmann
#
11 821d9e43 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 821d9e43 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 821d9e43 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 821d9e43 Michael Hanselmann
# General Public License for more details.
15 821d9e43 Michael Hanselmann
#
16 821d9e43 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 821d9e43 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 821d9e43 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 821d9e43 Michael Hanselmann
# 02110-1301, USA.
20 821d9e43 Michael Hanselmann
21 821d9e43 Michael Hanselmann
22 821d9e43 Michael Hanselmann
"""Module with helper classes and functions for daemons"""
23 821d9e43 Michael Hanselmann
24 821d9e43 Michael Hanselmann
25 3b1b0cb6 Guido Trotter
import os
26 821d9e43 Michael Hanselmann
import select
27 821d9e43 Michael Hanselmann
import signal
28 821d9e43 Michael Hanselmann
import errno
29 b11c9e5c Michael Hanselmann
import time
30 04ccf5e9 Guido Trotter
import logging
31 821d9e43 Michael Hanselmann
32 821d9e43 Michael Hanselmann
from ganeti import utils
33 04ccf5e9 Guido Trotter
from ganeti import constants
34 821d9e43 Michael Hanselmann
35 821d9e43 Michael Hanselmann
36 b11c9e5c Michael Hanselmann
class Timer(object):
37 b11c9e5c Michael Hanselmann
  def __init__(self, owner, timer_id, start, interval, repeat):
38 b11c9e5c Michael Hanselmann
    self.owner = owner
39 b11c9e5c Michael Hanselmann
    self.timer_id = timer_id
40 b11c9e5c Michael Hanselmann
    self.start = start
41 b11c9e5c Michael Hanselmann
    self.interval = interval
42 b11c9e5c Michael Hanselmann
    self.repeat = repeat
43 b11c9e5c Michael Hanselmann
44 b11c9e5c Michael Hanselmann
45 821d9e43 Michael Hanselmann
class Mainloop(object):
46 821d9e43 Michael Hanselmann
  """Generic mainloop for daemons
47 821d9e43 Michael Hanselmann

48 821d9e43 Michael Hanselmann
  """
49 821d9e43 Michael Hanselmann
  def __init__(self):
50 b14b975f Michael Hanselmann
    """Constructs a new Mainloop instance.
51 b14b975f Michael Hanselmann

52 b14b975f Michael Hanselmann
    """
53 b14b975f Michael Hanselmann
    self._io_wait = {}
54 b14b975f Michael Hanselmann
    self._io_wait_add = []
55 b14b975f Michael Hanselmann
    self._io_wait_remove = []
56 821d9e43 Michael Hanselmann
    self._signal_wait = []
57 b11c9e5c Michael Hanselmann
    self._timer_id_last = 0
58 b11c9e5c Michael Hanselmann
    self._timer = {}
59 b11c9e5c Michael Hanselmann
    self._timer_add = []
60 b11c9e5c Michael Hanselmann
    self._timer_remove = []
61 821d9e43 Michael Hanselmann
62 b14b975f Michael Hanselmann
  def Run(self, handle_sigchld=True, handle_sigterm=True, stop_on_empty=False):
63 b14b975f Michael Hanselmann
    """Runs the mainloop.
64 b14b975f Michael Hanselmann

65 b14b975f Michael Hanselmann
    @type handle_sigchld: bool
66 b14b975f Michael Hanselmann
    @param handle_sigchld: Whether to install handler for SIGCHLD
67 b14b975f Michael Hanselmann
    @type handle_sigterm: bool
68 b14b975f Michael Hanselmann
    @param handle_sigterm: Whether to install handler for SIGTERM
69 b14b975f Michael Hanselmann
    @type stop_on_empty: bool
70 b14b975f Michael Hanselmann
    @param stop_on_empty: Whether to stop mainloop once all I/O waiters
71 b14b975f Michael Hanselmann
                          unregistered
72 b14b975f Michael Hanselmann

73 b14b975f Michael Hanselmann
    """
74 821d9e43 Michael Hanselmann
    poller = select.poll()
75 821d9e43 Michael Hanselmann
76 b14b975f Michael Hanselmann
    # Setup signal handlers
77 b14b975f Michael Hanselmann
    if handle_sigchld:
78 b14b975f Michael Hanselmann
      sigchld_handler = utils.SignalHandler([signal.SIGCHLD])
79 b14b975f Michael Hanselmann
    else:
80 b14b975f Michael Hanselmann
      sigchld_handler = None
81 821d9e43 Michael Hanselmann
    try:
82 b14b975f Michael Hanselmann
      if handle_sigterm:
83 b14b975f Michael Hanselmann
        sigterm_handler = utils.SignalHandler([signal.SIGTERM])
84 b14b975f Michael Hanselmann
      else:
85 b14b975f Michael Hanselmann
        sigterm_handler = None
86 b14b975f Michael Hanselmann
87 b14b975f Michael Hanselmann
      try:
88 b14b975f Michael Hanselmann
        running = True
89 b11c9e5c Michael Hanselmann
        timeout = None
90 b11c9e5c Michael Hanselmann
        timeout_needs_update = True
91 b14b975f Michael Hanselmann
92 b14b975f Michael Hanselmann
        # Start actual main loop
93 b14b975f Michael Hanselmann
        while running:
94 b14b975f Michael Hanselmann
          # Entries could be added again afterwards, hence removing first
95 b14b975f Michael Hanselmann
          if self._io_wait_remove:
96 b14b975f Michael Hanselmann
            for fd in self._io_wait_remove:
97 b14b975f Michael Hanselmann
              try:
98 b14b975f Michael Hanselmann
                poller.unregister(fd)
99 b14b975f Michael Hanselmann
              except KeyError:
100 b14b975f Michael Hanselmann
                pass
101 b14b975f Michael Hanselmann
              try:
102 b14b975f Michael Hanselmann
                del self._io_wait[fd]
103 b14b975f Michael Hanselmann
              except KeyError:
104 b14b975f Michael Hanselmann
                pass
105 b14b975f Michael Hanselmann
            self._io_wait_remove = []
106 b14b975f Michael Hanselmann
107 b14b975f Michael Hanselmann
          # Add new entries
108 b14b975f Michael Hanselmann
          if self._io_wait_add:
109 b14b975f Michael Hanselmann
            for (owner, fd, conditions) in self._io_wait_add:
110 b14b975f Michael Hanselmann
              self._io_wait[fd] = owner
111 b14b975f Michael Hanselmann
              poller.register(fd, conditions)
112 b14b975f Michael Hanselmann
            self._io_wait_add = []
113 b14b975f Michael Hanselmann
114 b11c9e5c Michael Hanselmann
          # Add new timers
115 b11c9e5c Michael Hanselmann
          if self._timer_add:
116 b11c9e5c Michael Hanselmann
            timeout_needs_update = True
117 b11c9e5c Michael Hanselmann
            for timer in self._timer_add:
118 b11c9e5c Michael Hanselmann
              self._timer[timer.timer_id] = timer
119 b11c9e5c Michael Hanselmann
            del self._timer_add[:]
120 b11c9e5c Michael Hanselmann
121 b11c9e5c Michael Hanselmann
          # Remove timers
122 b11c9e5c Michael Hanselmann
          if self._timer_remove:
123 b11c9e5c Michael Hanselmann
            timeout_needs_update = True
124 b11c9e5c Michael Hanselmann
            for timer_id in self._timer_remove:
125 b11c9e5c Michael Hanselmann
              try:
126 b11c9e5c Michael Hanselmann
                del self._timer[timer_id]
127 b11c9e5c Michael Hanselmann
              except KeyError:
128 b11c9e5c Michael Hanselmann
                pass
129 b11c9e5c Michael Hanselmann
            del self._timer_remove[:]
130 b11c9e5c Michael Hanselmann
131 b14b975f Michael Hanselmann
          # Stop if nothing is listening anymore
132 b11c9e5c Michael Hanselmann
          if stop_on_empty and not (self._io_wait or self._timer):
133 b14b975f Michael Hanselmann
            break
134 b14b975f Michael Hanselmann
135 b11c9e5c Michael Hanselmann
          # Calculate timeout again if required
136 b11c9e5c Michael Hanselmann
          if timeout_needs_update:
137 b11c9e5c Michael Hanselmann
            timeout = self._CalcTimeout(time.time())
138 53d47a06 Guido Trotter
            timeout_needs_update = False
139 b11c9e5c Michael Hanselmann
140 b14b975f Michael Hanselmann
          # Wait for I/O events
141 b14b975f Michael Hanselmann
          try:
142 b11c9e5c Michael Hanselmann
            io_events = poller.poll(timeout)
143 b14b975f Michael Hanselmann
          except select.error, err:
144 b14b975f Michael Hanselmann
            # EINTR can happen when signals are sent
145 b14b975f Michael Hanselmann
            if err.args and err.args[0] in (errno.EINTR,):
146 b14b975f Michael Hanselmann
              io_events = None
147 b14b975f Michael Hanselmann
            else:
148 b14b975f Michael Hanselmann
              raise
149 b14b975f Michael Hanselmann
150 b11c9e5c Michael Hanselmann
          after_poll = time.time()
151 b11c9e5c Michael Hanselmann
152 b14b975f Michael Hanselmann
          if io_events:
153 b14b975f Michael Hanselmann
            # Check for I/O events
154 b14b975f Michael Hanselmann
            for (evfd, evcond) in io_events:
155 b14b975f Michael Hanselmann
              owner = self._io_wait.get(evfd, None)
156 b14b975f Michael Hanselmann
              if owner:
157 b14b975f Michael Hanselmann
                owner.OnIO(evfd, evcond)
158 b14b975f Michael Hanselmann
159 b11c9e5c Michael Hanselmann
          if self._timer:
160 b11c9e5c Michael Hanselmann
            self._CheckTimers(after_poll)
161 b11c9e5c Michael Hanselmann
162 b14b975f Michael Hanselmann
          # Check whether signal was raised
163 b14b975f Michael Hanselmann
          if sigchld_handler and sigchld_handler.called:
164 b14b975f Michael Hanselmann
            self._CallSignalWaiters(signal.SIGCHLD)
165 b14b975f Michael Hanselmann
            sigchld_handler.Clear()
166 b14b975f Michael Hanselmann
167 b14b975f Michael Hanselmann
          if sigterm_handler and sigterm_handler.called:
168 b14b975f Michael Hanselmann
            self._CallSignalWaiters(signal.SIGTERM)
169 b14b975f Michael Hanselmann
            running = False
170 b14b975f Michael Hanselmann
            sigterm_handler.Clear()
171 b14b975f Michael Hanselmann
      finally:
172 b14b975f Michael Hanselmann
        # Restore signal handlers
173 b14b975f Michael Hanselmann
        if sigterm_handler:
174 b14b975f Michael Hanselmann
          sigterm_handler.Reset()
175 821d9e43 Michael Hanselmann
    finally:
176 b14b975f Michael Hanselmann
      if sigchld_handler:
177 b14b975f Michael Hanselmann
        sigchld_handler.Reset()
178 a570e2a8 Guido Trotter
179 b11c9e5c Michael Hanselmann
  def _CalcTimeout(self, now):
180 b11c9e5c Michael Hanselmann
    if not self._timer:
181 b11c9e5c Michael Hanselmann
      return None
182 b11c9e5c Michael Hanselmann
183 b11c9e5c Michael Hanselmann
    timeout = None
184 b11c9e5c Michael Hanselmann
185 b11c9e5c Michael Hanselmann
    # TODO: Repeating timers
186 b11c9e5c Michael Hanselmann
187 b11c9e5c Michael Hanselmann
    min_timeout = 0.001
188 b11c9e5c Michael Hanselmann
189 b11c9e5c Michael Hanselmann
    for timer in self._timer.itervalues():
190 b11c9e5c Michael Hanselmann
      time_left = (timer.start + timer.interval) - now
191 b11c9e5c Michael Hanselmann
      if timeout is None or time_left < timeout:
192 b11c9e5c Michael Hanselmann
        timeout = time_left
193 b11c9e5c Michael Hanselmann
      if timeout < 0:
194 b11c9e5c Michael Hanselmann
        timeout = 0
195 b11c9e5c Michael Hanselmann
        break
196 b11c9e5c Michael Hanselmann
      elif timeout < min_timeout:
197 b11c9e5c Michael Hanselmann
        timeout = min_timeout
198 b11c9e5c Michael Hanselmann
        break
199 b11c9e5c Michael Hanselmann
200 b11c9e5c Michael Hanselmann
    return timeout * 1000.0
201 b11c9e5c Michael Hanselmann
202 b11c9e5c Michael Hanselmann
  def _CheckTimers(self, now):
203 b11c9e5c Michael Hanselmann
    # TODO: Repeating timers
204 b11c9e5c Michael Hanselmann
    for timer in self._timer.itervalues():
205 b11c9e5c Michael Hanselmann
      if now < (timer.start + timer.interval):
206 b11c9e5c Michael Hanselmann
        continue
207 b11c9e5c Michael Hanselmann
208 b11c9e5c Michael Hanselmann
      timer.owner.OnTimer(timer.timer_id)
209 b11c9e5c Michael Hanselmann
210 b11c9e5c Michael Hanselmann
      # TODO: Repeating timers should not be removed
211 b11c9e5c Michael Hanselmann
      self._timer_remove.append(timer.timer_id)
212 b11c9e5c Michael Hanselmann
213 b14b975f Michael Hanselmann
  def _CallSignalWaiters(self, signum):
214 b14b975f Michael Hanselmann
    """Calls all signal waiters for a certain signal.
215 b14b975f Michael Hanselmann

216 b14b975f Michael Hanselmann
    @type signum: int
217 b14b975f Michael Hanselmann
    @param signum: Signal number
218 b14b975f Michael Hanselmann

219 b14b975f Michael Hanselmann
    """
220 b14b975f Michael Hanselmann
    for owner in self._signal_wait:
221 b14b975f Michael Hanselmann
      owner.OnSignal(signal.SIGCHLD)
222 821d9e43 Michael Hanselmann
223 821d9e43 Michael Hanselmann
  def RegisterIO(self, owner, fd, condition):
224 821d9e43 Michael Hanselmann
    """Registers a receiver for I/O notifications
225 821d9e43 Michael Hanselmann

226 821d9e43 Michael Hanselmann
    The receiver must support a "OnIO(self, fd, conditions)" function.
227 821d9e43 Michael Hanselmann

228 821d9e43 Michael Hanselmann
    @type owner: instance
229 821d9e43 Michael Hanselmann
    @param owner: Receiver
230 821d9e43 Michael Hanselmann
    @type fd: int
231 821d9e43 Michael Hanselmann
    @param fd: File descriptor
232 821d9e43 Michael Hanselmann
    @type condition: int
233 821d9e43 Michael Hanselmann
    @param condition: ORed field of conditions to be notified
234 821d9e43 Michael Hanselmann
                      (see select module)
235 821d9e43 Michael Hanselmann

236 821d9e43 Michael Hanselmann
    """
237 b14b975f Michael Hanselmann
    # select.Poller also supports file() like objects, but we don't.
238 b14b975f Michael Hanselmann
    assert isinstance(fd, (int, long)), \
239 b14b975f Michael Hanselmann
      "Only integers are supported for file descriptors"
240 b14b975f Michael Hanselmann
241 b14b975f Michael Hanselmann
    self._io_wait_add.append((owner, fd, condition))
242 b14b975f Michael Hanselmann
243 b14b975f Michael Hanselmann
  def UnregisterIO(self, fd):
244 b14b975f Michael Hanselmann
    """Unregister a file descriptor.
245 b14b975f Michael Hanselmann

246 b14b975f Michael Hanselmann
    It'll be unregistered the next time the mainloop checks for it.
247 b14b975f Michael Hanselmann

248 b14b975f Michael Hanselmann
    @type fd: int
249 b14b975f Michael Hanselmann
    @param fd: File descriptor
250 b14b975f Michael Hanselmann

251 b14b975f Michael Hanselmann
    """
252 b14b975f Michael Hanselmann
    # select.Poller also supports file() like objects, but we don't.
253 b14b975f Michael Hanselmann
    assert isinstance(fd, (int, long)), \
254 b14b975f Michael Hanselmann
      "Only integers are supported for file descriptors"
255 b14b975f Michael Hanselmann
256 b14b975f Michael Hanselmann
    self._io_wait_remove.append(fd)
257 821d9e43 Michael Hanselmann
258 821d9e43 Michael Hanselmann
  def RegisterSignal(self, owner):
259 821d9e43 Michael Hanselmann
    """Registers a receiver for signal notifications
260 821d9e43 Michael Hanselmann

261 821d9e43 Michael Hanselmann
    The receiver must support a "OnSignal(self, signum)" function.
262 821d9e43 Michael Hanselmann

263 821d9e43 Michael Hanselmann
    @type owner: instance
264 821d9e43 Michael Hanselmann
    @param owner: Receiver
265 821d9e43 Michael Hanselmann

266 821d9e43 Michael Hanselmann
    """
267 821d9e43 Michael Hanselmann
    self._signal_wait.append(owner)
268 b11c9e5c Michael Hanselmann
269 b11c9e5c Michael Hanselmann
  def AddTimer(self, owner, interval, repeat):
270 b11c9e5c Michael Hanselmann
    """Add a new timer.
271 b11c9e5c Michael Hanselmann

272 b11c9e5c Michael Hanselmann
    The receiver must support a "OnTimer(self, timer_id)" function.
273 b11c9e5c Michael Hanselmann

274 b11c9e5c Michael Hanselmann
    @type owner: instance
275 b11c9e5c Michael Hanselmann
    @param owner: Receiver
276 b11c9e5c Michael Hanselmann
    @type interval: int or float
277 b11c9e5c Michael Hanselmann
    @param interval: Timer interval in seconds
278 b11c9e5c Michael Hanselmann
    @type repeat: bool
279 b11c9e5c Michael Hanselmann
    @param repeat: Whether this is a repeating timer or one-off
280 b11c9e5c Michael Hanselmann

281 b11c9e5c Michael Hanselmann
    """
282 b11c9e5c Michael Hanselmann
    # TODO: Implement repeating timers
283 b11c9e5c Michael Hanselmann
    assert not repeat, "Repeating timers are not yet supported"
284 b11c9e5c Michael Hanselmann
285 b11c9e5c Michael Hanselmann
    # Get new ID
286 b11c9e5c Michael Hanselmann
    self._timer_id_last += 1
287 b11c9e5c Michael Hanselmann
288 b11c9e5c Michael Hanselmann
    timer_id = self._timer_id_last
289 b11c9e5c Michael Hanselmann
290 b11c9e5c Michael Hanselmann
    self._timer_add.append(Timer(owner, timer_id, time.time(),
291 b11c9e5c Michael Hanselmann
                                 float(interval), repeat))
292 b11c9e5c Michael Hanselmann
293 b11c9e5c Michael Hanselmann
    return timer_id
294 b11c9e5c Michael Hanselmann
295 b11c9e5c Michael Hanselmann
  def RemoveTimer(self, timer_id):
296 b11c9e5c Michael Hanselmann
    """Removes a timer.
297 b11c9e5c Michael Hanselmann

298 b11c9e5c Michael Hanselmann
    @type timer_id: int
299 b11c9e5c Michael Hanselmann
    @param timer_id: Timer ID
300 b11c9e5c Michael Hanselmann

301 b11c9e5c Michael Hanselmann
    """
302 b11c9e5c Michael Hanselmann
    self._timer_remove.append(timer_id)
303 04ccf5e9 Guido Trotter
304 04ccf5e9 Guido Trotter
305 04ccf5e9 Guido Trotter
def GenericMain(daemon_name, optionparser, dirs, check_fn, exec_fn):
306 04ccf5e9 Guido Trotter
  """Shared main function for daemons.
307 04ccf5e9 Guido Trotter

308 04ccf5e9 Guido Trotter
  @type daemon_name: string
309 04ccf5e9 Guido Trotter
  @param daemon_name: daemon name
310 04ccf5e9 Guido Trotter
  @type optionparser: L{optparse.OptionParser}
311 04ccf5e9 Guido Trotter
  @param optionparser: initialized optionparser with daemon-specific options
312 04ccf5e9 Guido Trotter
                       (common -f -d options will be handled by this module)
313 04ccf5e9 Guido Trotter
  @type options: object @param options: OptionParser result, should contain at
314 04ccf5e9 Guido Trotter
                 least the fork and the debug options
315 04ccf5e9 Guido Trotter
  @type dirs: list of strings
316 04ccf5e9 Guido Trotter
  @param dirs: list of directories that must exist for this daemon to work
317 04ccf5e9 Guido Trotter
  @type check_fn: function which accepts (options, args)
318 04ccf5e9 Guido Trotter
  @param check_fn: function that checks start conditions and exits if they're
319 04ccf5e9 Guido Trotter
                   not met
320 04ccf5e9 Guido Trotter
  @type exec_fn: function which accepts (options, args)
321 04ccf5e9 Guido Trotter
  @param exec_fn: function that's executed with the daemon's pid file held, and
322 04ccf5e9 Guido Trotter
                  runs the daemon itself.
323 04ccf5e9 Guido Trotter

324 04ccf5e9 Guido Trotter
  """
325 04ccf5e9 Guido Trotter
  optionparser.add_option("-f", "--foreground", dest="fork",
326 04ccf5e9 Guido Trotter
                          help="Don't detach from the current terminal",
327 04ccf5e9 Guido Trotter
                          default=True, action="store_false")
328 04ccf5e9 Guido Trotter
  optionparser.add_option("-d", "--debug", dest="debug",
329 04ccf5e9 Guido Trotter
                          help="Enable some debug messages",
330 04ccf5e9 Guido Trotter
                          default=False, action="store_true")
331 04ccf5e9 Guido Trotter
  if daemon_name in constants.DAEMONS_PORTS:
332 04ccf5e9 Guido Trotter
    # for networked daemons we also allow choosing the bind port and address.
333 04ccf5e9 Guido Trotter
    # by default we use the port provided by utils.GetDaemonPort, and bind to
334 04ccf5e9 Guido Trotter
    # 0.0.0.0 (which is represented by and empty bind address.
335 04ccf5e9 Guido Trotter
    port = utils.GetDaemonPort(daemon_name)
336 04ccf5e9 Guido Trotter
    optionparser.add_option("-p", "--port", dest="port",
337 04ccf5e9 Guido Trotter
                            help="Network port (%s default)." % port,
338 04ccf5e9 Guido Trotter
                            default=port, type="int")
339 04ccf5e9 Guido Trotter
    optionparser.add_option("-b", "--bind", dest="bind_address",
340 04ccf5e9 Guido Trotter
                            help="Bind address",
341 04ccf5e9 Guido Trotter
                            default="", metavar="ADDRESS")
342 04ccf5e9 Guido Trotter
343 3b1b0cb6 Guido Trotter
  if daemon_name in constants.DAEMONS_SSL:
344 3b1b0cb6 Guido Trotter
    default_cert, default_key = constants.DAEMONS_SSL[daemon_name]
345 3b1b0cb6 Guido Trotter
    optionparser.add_option("--no-ssl", dest="ssl",
346 3b1b0cb6 Guido Trotter
                            help="Do not secure HTTP protocol with SSL",
347 3b1b0cb6 Guido Trotter
                            default=True, action="store_false")
348 3b1b0cb6 Guido Trotter
    optionparser.add_option("-K", "--ssl-key", dest="ssl_key",
349 3b1b0cb6 Guido Trotter
                            help="SSL key",
350 3b1b0cb6 Guido Trotter
                            default=default_key, type="string")
351 3b1b0cb6 Guido Trotter
    optionparser.add_option("-C", "--ssl-cert", dest="ssl_cert",
352 3b1b0cb6 Guido Trotter
                            help="SSL certificate",
353 3b1b0cb6 Guido Trotter
                            default=default_cert, type="string")
354 3b1b0cb6 Guido Trotter
355 04ccf5e9 Guido Trotter
  multithread = utils.no_fork = daemon_name in constants.MULTITHREADED_DAEMONS
356 04ccf5e9 Guido Trotter
357 04ccf5e9 Guido Trotter
  options, args = optionparser.parse_args()
358 04ccf5e9 Guido Trotter
359 3b1b0cb6 Guido Trotter
  if hasattr(options, 'ssl') and options.ssl:
360 3b1b0cb6 Guido Trotter
    if not (options.ssl_cert and options.ssl_key):
361 3b1b0cb6 Guido Trotter
      print >> sys.stderr, "Need key and certificate to use ssl"
362 3b1b0cb6 Guido Trotter
      sys.exit(constants.EXIT_FAILURE)
363 3b1b0cb6 Guido Trotter
    for fname in (options.ssl_cert, options.ssl_key):
364 3b1b0cb6 Guido Trotter
      if not os.path.isfile(fname):
365 3b1b0cb6 Guido Trotter
        print >> sys.stderr, "Need ssl file %s to run" % fname
366 3b1b0cb6 Guido Trotter
        sys.exit(constants.EXIT_FAILURE)
367 3b1b0cb6 Guido Trotter
368 3b1b0cb6 Guido Trotter
  if check_fn is not None:
369 3b1b0cb6 Guido Trotter
    check_fn(options, args)
370 3b1b0cb6 Guido Trotter
371 04ccf5e9 Guido Trotter
  utils.EnsureDirs(dirs)
372 04ccf5e9 Guido Trotter
373 04ccf5e9 Guido Trotter
  if options.fork:
374 04ccf5e9 Guido Trotter
    utils.CloseFDs()
375 04ccf5e9 Guido Trotter
    utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name])
376 04ccf5e9 Guido Trotter
377 04ccf5e9 Guido Trotter
  utils.WritePidFile(daemon_name)
378 04ccf5e9 Guido Trotter
  try:
379 04ccf5e9 Guido Trotter
    utils.SetupLogging(logfile=constants.DAEMONS_LOGFILES[daemon_name],
380 04ccf5e9 Guido Trotter
                       debug=options.debug,
381 04ccf5e9 Guido Trotter
                       stderr_logging=not options.fork,
382 04ccf5e9 Guido Trotter
                       multithreaded=multithread)
383 04ccf5e9 Guido Trotter
    logging.info("%s daemon startup" % daemon_name)
384 04ccf5e9 Guido Trotter
    exec_fn(options, args)
385 04ccf5e9 Guido Trotter
  finally:
386 04ccf5e9 Guido Trotter
    utils.RemovePidFile(daemon_name)