Make SetupToolsLogging use tools logfile
[ganeti-github.git] / lib / utils / log.py
index d5d3c3d..c39e96a 100644 (file)
@@ -2,21 +2,30 @@
 #
 
 # Copyright (C) 2006, 2007, 2010, 2011 Google Inc.
+# All rights reserved.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
 #
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
 #
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 """Utility functions for logging.
 
@@ -28,6 +37,7 @@ import logging.handlers
 
 from ganeti import constants
 from ganeti import compat
+from ganeti import pathutils
 
 
 class _ReopenableLogHandler(logging.handlers.BaseRotatingHandler):
@@ -51,13 +61,13 @@ class _ReopenableLogHandler(logging.handlers.BaseRotatingHandler):
 
     self._reopen = False
 
-  def shouldRollover(self, _): # pylint: disable-msg=C0103
+  def shouldRollover(self, _): # pylint: disable=C0103
     """Determine whether log file should be reopened.
 
     """
     return self._reopen or not self.stream
 
-  def doRollover(self): # pylint: disable-msg=C0103
+  def doRollover(self): # pylint: disable=C0103
     """Reopens the log file.
 
     """
@@ -88,7 +98,7 @@ def _LogErrorsToConsole(base):
   This needs to be in a function for unittesting.
 
   """
-  class wrapped(base): # pylint: disable-msg=C0103
+  class wrapped(base): # pylint: disable=C0103
     """Log handler that doesn't fallback to stderr.
 
     When an error occurs while writing on the logfile, logging.FileHandler
@@ -108,7 +118,7 @@ def _LogErrorsToConsole(base):
       assert not hasattr(self, "_console")
       self._console = console
 
-    def handleError(self, record): # pylint: disable-msg=C0103
+    def handleError(self, record): # pylint: disable=C0103
       """Handle errors which occur during an emit() call.
 
       Try to handle errors with FileHandler method, if it fails write to
@@ -117,13 +127,13 @@ def _LogErrorsToConsole(base):
       """
       try:
         base.handleError(record)
-      except Exception: # pylint: disable-msg=W0703
+      except Exception: # pylint: disable=W0703
         if self._console:
           try:
-            # Ignore warning about "self.format", pylint: disable-msg=E1101
+            # Ignore warning about "self.format", pylint: disable=E1101
             self._console.write("Cannot log message:\n%s\n" %
                                 self.format(record))
-          except Exception: # pylint: disable-msg=W0703
+          except Exception: # pylint: disable=W0703
             # Log handler tried everything it could, now just give up
             pass
 
@@ -173,11 +183,13 @@ def _ReopenLogFiles(handlers):
   """
   for handler in handlers:
     handler.RequestReopen()
+  logging.info("Received request to reopen log files")
 
 
 def SetupLogging(logfile, program, debug=0, stderr_logging=False,
                  multithreaded=False, syslog=constants.SYSLOG_USAGE,
-                 console_logging=False, root_logger=None):
+                 console_logging=False, root_logger=None,
+                 verbose=True):
   """Configures the logging module.
 
   @type logfile: str
@@ -201,6 +213,8 @@ def SetupLogging(logfile, program, debug=0, stderr_logging=False,
       the system console if logging fails
   @type root_logger: logging.Logger
   @param root_logger: Root logger to use (for unittests)
+  @type verbose: boolean
+  @param verbose: whether to log at 'info' level already (logfile logging only)
   @raise EnvironmentError: if we can't open the log file and
       syslog/stderr logging is disabled
   @rtype: callable
@@ -256,8 +270,10 @@ def SetupLogging(logfile, program, debug=0, stderr_logging=False,
       logfile_handler.setFormatter(formatter)
       if debug:
         logfile_handler.setLevel(logging.DEBUG)
-      else:
+      elif verbose:
         logfile_handler.setLevel(logging.INFO)
+      else:
+        logfile_handler.setLevel(logging.WARN)
       root_logger.addHandler(logfile_handler)
       reopen_handlers.append(logfile_handler)
     except EnvironmentError:
@@ -268,3 +284,36 @@ def SetupLogging(logfile, program, debug=0, stderr_logging=False,
         raise
 
   return compat.partial(_ReopenLogFiles, reopen_handlers)
+
+
+def SetupToolLogging(debug, verbose, threadname=False,
+                     toolname=None):
+  """Configures the logging module for tools.
+
+  All log messages are sent to the tools.log logfile.
+
+  @type toolname: string
+  @param toolname: name of the tool that's logging
+  @type debug: boolean
+  @param debug: Disable log message filtering
+  @type verbose: boolean
+  @param verbose: Enable verbose log messages
+  @type threadname: boolean
+  @param threadname: Whether to include thread name in output
+
+  """
+  if not toolname:
+    toolname = "unspecified_tool"
+
+  # 'SetupLogging' takes a quite unintuitive 'debug' option that
+  # is '0' for 'log higher than debug level' and '1' for
+  # 'log at NOSET' level. Hence this conversion.
+  debug_int = 0
+  if debug:
+    debug_int = 1
+
+  SetupLogging(pathutils.LOG_TOOLS,
+               program=toolname,
+               debug=debug_int,
+               multithreaded=threadname,
+               verbose=verbose)