Improve import/export timeout settings
[ganeti-local] / lib / daemon.py
index eceeac4..c3c4761 100644 (file)
@@ -491,8 +491,8 @@ class Mainloop(object):
 def _VerifyDaemonUser(daemon_name):
   """Verifies the process uid matches the configured uid.
 
-  This method verifies that a daemon is started as the user it is intended to be
-  run
+  This method verifies that a daemon is started as the user it is
+  intended to be run
 
   @param daemon_name: The name of daemon to be started
   @return: A tuple with the first item indicating success or not,
@@ -512,6 +512,33 @@ def _VerifyDaemonUser(daemon_name):
           daemon_uids[daemon_name])
 
 
+def _BeautifyError(err):
+  """Try to format an error better.
+
+  Since we're dealing with daemon startup errors, in many cases this
+  will be due to socket error and such, so we try to format these cases better.
+
+  @param err: an exception object
+  @rtype: string
+  @return: the formatted error description
+
+  """
+  try:
+    if isinstance(err, socket.error):
+      return "Socket-related error: %s (errno=%s)" % (err.args[1], err.args[0])
+    elif isinstance(err, EnvironmentError):
+      if err.filename is None:
+        return "%s (errno=%s)" % (err.strerror, err.errno)
+      else:
+        return "%s (file %s) (errno=%s)" % (err.strerror, err.filename,
+                                            err.errno)
+    else:
+      return str(err)
+  except Exception: # pylint: disable-msg=W0703
+    logging.exception("Error while handling existing error %s", err)
+    return "%s" % str(err)
+
+
 def GenericMain(daemon_name, optionparser,
                 check_fn, prepare_fn, exec_fn,
                 multithreaded=False, console_logging=False,
@@ -624,22 +651,33 @@ def GenericMain(daemon_name, optionparser,
 
   if options.fork:
     utils.CloseFDs()
-    utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name])
+    wpipe = utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name])
+  else:
+    wpipe = None
 
   utils.WritePidFile(utils.DaemonPidFileName(daemon_name))
   try:
-    utils.SetupLogging(logfile=constants.DAEMONS_LOGFILES[daemon_name],
-                       debug=options.debug,
-                       stderr_logging=not options.fork,
-                       multithreaded=multithreaded,
-                       program=daemon_name,
-                       syslog=options.syslog,
-                       console_logging=console_logging)
-    logging.info("%s daemon startup", daemon_name)
-    if callable(prepare_fn):
-      prep_results = prepare_fn(options, args)
-    else:
-      prep_results = None
+    try:
+      utils.SetupLogging(logfile=constants.DAEMONS_LOGFILES[daemon_name],
+                         debug=options.debug,
+                         stderr_logging=not options.fork,
+                         multithreaded=multithreaded,
+                         program=daemon_name,
+                         syslog=options.syslog,
+                         console_logging=console_logging)
+      if callable(prepare_fn):
+        prep_results = prepare_fn(options, args)
+      else:
+        prep_results = None
+      logging.info("%s daemon startup", daemon_name)
+    except Exception, err:
+      utils.WriteErrorToFD(wpipe, _BeautifyError(err))
+      raise
+
+    if wpipe is not None:
+      # we're done with the preparation phase, we close the pipe to
+      # let the parent know it's safe to exit
+      os.close(wpipe)
 
     exec_fn(options, args, prep_results)
   finally: