diff --git a/lib/tools/ensure_dirs.py b/lib/tools/ensure_dirs.py index afe4877cd8050441626b873ab21cf5d364c4acd3..48a7b441511933e9fa2c91c920c323f740a862ec 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 37bd0bccc77de33a309493060384250438066297..deedd0b3207228415e5b01ea2058fc224c503f28 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 281f59045ac8e7e7ae2505e154d55f6fdf4f1d84..2afbfd2f25243a56c6d76672e32719637e7927e7 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 5ae860bbb1e509bc637433e9b76cfd380450f421..517694c7208e1d1922a3e7d9d0e13fc9a585f85f 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 d45d38148b31a6be60966dc562d7752d395d891f..a066335f408dc98f984df274b82f4ac35b12f875 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 8490ecf9db2060e943048293c001f71976d86931..24bb496128943a9bdbf6eaa99d04af714d0aaf15 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 17024bf202bd9ed20fa07f4f4a833b3ed456cdf1..fd7aa436475cfa0ef1eadf800547ee54e887408e 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