From 796b51522c2cf68ea6b6a2944a1a2373d51d72cb Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Tue, 27 Nov 2012 10:27:00 +0100 Subject: [PATCH] Factorize logging setup in tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most tools had their own βSetupLoggingβ function, but they were all essentially the same. This patch adds a generic version to βutils.logβ and provides unit tests. Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Guido Trotter <ultrotter@google.com> --- lib/tools/ensure_dirs.py | 22 +--------- lib/tools/prepare_node_join.py | 22 +--------- lib/utils/log.py | 46 +++++++++++++++++++++ test/ganeti.utils.log_unittest.py | 68 +++++++++++++++++++++++++++++++ tools/cluster-merge | 24 +---------- tools/move-instance | 29 +------------ tools/ovfconverter | 28 ++----------- 7 files changed, 122 insertions(+), 117 deletions(-) diff --git a/lib/tools/ensure_dirs.py b/lib/tools/ensure_dirs.py index afe4877cd..48a7b4415 100644 --- a/lib/tools/ensure_dirs.py +++ b/lib/tools/ensure_dirs.py @@ -201,26 +201,6 @@ def GetPaths(): return paths -def SetupLogging(opts): - """Configures the logging module. - - """ - formatter = logging.Formatter("%(asctime)s: %(message)s") - - stderr_handler = logging.StreamHandler() - stderr_handler.setFormatter(formatter) - if opts.debug: - stderr_handler.setLevel(logging.NOTSET) - elif opts.verbose: - stderr_handler.setLevel(logging.INFO) - else: - stderr_handler.setLevel(logging.WARNING) - - root_logger = logging.getLogger("") - root_logger.setLevel(logging.NOTSET) - root_logger.addHandler(stderr_handler) - - def ParseOptions(): """Parses the options passed to the program. @@ -246,7 +226,7 @@ def Main(): """ (opts, args) = ParseOptions() - SetupLogging(opts) + utils.SetupToolLogging(opts.debug, opts.verbose) if args: logging.error("No arguments are expected") diff --git a/lib/tools/prepare_node_join.py b/lib/tools/prepare_node_join.py index 37bd0bccc..deedd0b32 100644 --- a/lib/tools/prepare_node_join.py +++ b/lib/tools/prepare_node_join.py @@ -94,26 +94,6 @@ def VerifyOptions(parser, opts, args): return opts -def SetupLogging(opts): - """Configures the logging module. - - """ - formatter = logging.Formatter("%(asctime)s: %(message)s") - - stderr_handler = logging.StreamHandler() - stderr_handler.setFormatter(formatter) - if opts.debug: - stderr_handler.setLevel(logging.NOTSET) - elif opts.verbose: - stderr_handler.setLevel(logging.INFO) - else: - stderr_handler.setLevel(logging.WARNING) - - root_logger = logging.getLogger("") - root_logger.setLevel(logging.NOTSET) - root_logger.addHandler(stderr_handler) - - def _VerifyCertificate(cert, _noded_cert_file=pathutils.NODED_CERT_FILE): """Verifies a certificate against the local node daemon certificate. @@ -319,7 +299,7 @@ def Main(): """ opts = ParseOptions() - SetupLogging(opts) + utils.SetupToolLogging(opts.debug, opts.verbose) try: data = LoadData(sys.stdin.read()) diff --git a/lib/utils/log.py b/lib/utils/log.py index 281f59045..2afbfd2f2 100644 --- a/lib/utils/log.py +++ b/lib/utils/log.py @@ -25,6 +25,7 @@ import os.path import logging import logging.handlers +from cStringIO import StringIO from ganeti import constants from ganeti import compat @@ -269,3 +270,48 @@ def SetupLogging(logfile, program, debug=0, stderr_logging=False, raise return compat.partial(_ReopenLogFiles, reopen_handlers) + + +def SetupToolLogging(debug, verbose, threadname=False, + _root_logger=None, _stream=None): + """Configures the logging module for tools. + + All log messages are sent to stderr. + + @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 _root_logger is None: + root_logger = logging.getLogger("") + else: + root_logger = _root_logger + + fmt = StringIO() + fmt.write("%(asctime)s:") + + if threadname: + fmt.write(" %(threadName)s") + + if debug or verbose: + fmt.write(" %(levelname)s") + + fmt.write(" %(message)s") + + formatter = logging.Formatter(fmt.getvalue()) + + stderr_handler = logging.StreamHandler(_stream) + stderr_handler.setFormatter(formatter) + if debug: + stderr_handler.setLevel(logging.NOTSET) + elif verbose: + stderr_handler.setLevel(logging.INFO) + else: + stderr_handler.setLevel(logging.WARNING) + + root_logger.setLevel(logging.NOTSET) + root_logger.addHandler(stderr_handler) diff --git a/test/ganeti.utils.log_unittest.py b/test/ganeti.utils.log_unittest.py index 5ae860bbb..517694c72 100755 --- a/test/ganeti.utils.log_unittest.py +++ b/test/ganeti.utils.log_unittest.py @@ -26,9 +26,12 @@ import unittest import logging import tempfile import shutil +import threading +from cStringIO import StringIO from ganeti import constants from ganeti import errors +from ganeti import compat from ganeti import utils import testutils @@ -192,5 +195,70 @@ class TestSetupLogging(unittest.TestCase): self.assertTrue(utils.ReadFile(logfile2).endswith("This is a test\n")) +class TestSetupToolLogging(unittest.TestCase): + def test(self): + error_name = logging.getLevelName(logging.ERROR) + warn_name = logging.getLevelName(logging.WARNING) + info_name = logging.getLevelName(logging.INFO) + debug_name = logging.getLevelName(logging.DEBUG) + + for debug in [False, True]: + for verbose in [False, True]: + logger = logging.Logger("TestLogger") + buf = StringIO() + + utils.SetupToolLogging(debug, verbose, _root_logger=logger, _stream=buf) + + logger.error("level=error") + logger.warning("level=warning") + logger.info("level=info") + logger.debug("level=debug") + + lines = buf.getvalue().splitlines() + + self.assertTrue(compat.all(line.count(":") == 3 for line in lines)) + + messages = [line.split(":", 3)[-1].strip() for line in lines] + + if debug: + self.assertEqual(messages, [ + "%s level=error" % error_name, + "%s level=warning" % warn_name, + "%s level=info" % info_name, + "%s level=debug" % debug_name, + ]) + elif verbose: + self.assertEqual(messages, [ + "%s level=error" % error_name, + "%s level=warning" % warn_name, + "%s level=info" % info_name, + ]) + else: + self.assertEqual(messages, [ + "level=error", + "level=warning", + ]) + + def testThreadName(self): + thread_name = threading.currentThread().getName() + + for enable_threadname in [False, True]: + logger = logging.Logger("TestLogger") + buf = StringIO() + + utils.SetupToolLogging(True, True, threadname=enable_threadname, + _root_logger=logger, _stream=buf) + + logger.debug("test134042376") + + lines = buf.getvalue().splitlines() + self.assertEqual(len(lines), 1) + + if enable_threadname: + self.assertTrue((" %s " % thread_name) in lines[0]) + else: + self.assertTrue(thread_name not in lines[0]) + + if __name__ == "__main__": testutils.GanetiTestProgram() diff --git a/tools/cluster-merge b/tools/cluster-merge index d45d38148..a066335f4 100755 --- a/tools/cluster-merge +++ b/tools/cluster-merge @@ -781,28 +781,6 @@ class Merger(object): shutil.rmtree(self.work_dir) -def SetupLogging(options): - """Setting up logging infrastructure. - - @param options: Parsed command line options - - """ - formatter = logging.Formatter("%(asctime)s: %(levelname)s %(message)s") - - stderr_handler = logging.StreamHandler() - stderr_handler.setFormatter(formatter) - if options.debug: - stderr_handler.setLevel(logging.NOTSET) - elif options.verbose: - stderr_handler.setLevel(logging.INFO) - else: - stderr_handler.setLevel(logging.WARNING) - - root_logger = logging.getLogger("") - root_logger.setLevel(logging.NOTSET) - root_logger.addHandler(stderr_handler) - - def main(): """Main routine. @@ -821,7 +799,7 @@ def main(): (options, args) = parser.parse_args() - SetupLogging(options) + utils.SetupToolLogging(options.debug, options.verbose) if not args: parser.error("No clusters specified") diff --git a/tools/move-instance b/tools/move-instance index 8490ecf9d..24bb49612 100755 --- a/tools/move-instance +++ b/tools/move-instance @@ -719,33 +719,6 @@ def CheckRapiSetup(rapi_factory): logging.info("Destination cluster RAPI version: %s", dest_client.GetVersion()) -def SetupLogging(options): - """Setting up logging infrastructure. - - @param options: Parsed command line options - - """ - fmt = "%(asctime)s: %(threadName)s " - if options.debug or options.verbose: - fmt += "%(levelname)s " - fmt += "%(message)s" - - formatter = logging.Formatter(fmt) - - stderr_handler = logging.StreamHandler() - stderr_handler.setFormatter(formatter) - if options.debug: - stderr_handler.setLevel(logging.NOTSET) - elif options.verbose: - stderr_handler.setLevel(logging.INFO) - else: - stderr_handler.setLevel(logging.ERROR) - - root_logger = logging.getLogger("") - root_logger.setLevel(logging.NOTSET) - root_logger.addHandler(stderr_handler) - - def ParseOptions(): """Parses options passed to program. @@ -845,7 +818,7 @@ def main(): """ (parser, options, args) = ParseOptions() - SetupLogging(options) + utils.SetupToolLogging(options.debug, options.verbose, threadname=True) (src_cluster_name, dest_cluster_name, instance_names) = \ CheckOptions(parser, options, args) diff --git a/tools/ovfconverter b/tools/ovfconverter index 17024bf20..fd7aa4364 100755 --- a/tools/ovfconverter +++ b/tools/ovfconverter @@ -31,6 +31,7 @@ from ganeti import cli from ganeti import constants from ganeti import errors from ganeti import ovf +from ganeti import utils IMPORT_MODE = "import" @@ -161,35 +162,14 @@ def ParseOptions(): return (mode, input_path, options) -def SetupLogging(options): - """Setting up logging infrastructure. - - @type options: optparse.Values - @param options: parsed command line options - - """ - formatter = logging.Formatter("%(asctime)s: %(levelname)s %(message)s") - - stderr_handler = logging.StreamHandler() - stderr_handler.setFormatter(formatter) - if options.debug: - stderr_handler.setLevel(logging.NOTSET) - elif options.verbose: - stderr_handler.setLevel(logging.INFO) - else: - stderr_handler.setLevel(logging.WARNING) - - root_logger = logging.getLogger("") - root_logger.setLevel(logging.NOTSET) - root_logger.addHandler(stderr_handler) - - def main(): """Main routine. """ (mode, input_path, options) = ParseOptions() - SetupLogging(options) + + utils.SetupToolLogging(options.debug, options.verbose) + logging.info("Chosen %s mode, reading the %s file", mode, input_path) assert mode in (IMPORT_MODE, EXPORT_MODE) converter = None -- GitLab