From: Mark McLoughlin Date: Mon, 21 Jan 2013 16:25:38 +0000 (+0000) Subject: Sync latest cfg and log from oslo-incubator X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=db319b1fc19962eb64b1724db2ef3048cae61769;p=openstack-build%2Fcinder-build.git Sync latest cfg and log from oslo-incubator Main cfg change is: c5984ba Move logging config options into the log module Logging changes include: c5984ba Move logging config options into the log module 751c35b Verbose should not enable debug level logging edcdd25 Improve millisecond logging 9e5912f Fix pep8 E125 errors. edf14e0 Enable millisecond logging by default 9b81289 Allow nova and others to override some logging defaults 90ada0e update deprecated stanza efba202 Adjust the logging_context_format_string. c8cf6f7 move nova.common.deprecated to openstack-common Fixes bug #989269 Use new LOG.deprecated() in place of cinder.common.deprecated.warn(). Also pull this cinder/context.py change from nova: ce098cc Add user/tenant shim to RequestContext to avoid issues caused by a s/user_id/user/ change in the context logging format. Change-Id: I3913ea54465658d93dc56e014dfe5d911b0541d6 --- diff --git a/cinder/common/deprecated.py b/cinder/common/deprecated.py deleted file mode 100644 index 165b53081..000000000 --- a/cinder/common/deprecated.py +++ /dev/null @@ -1,54 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 IBM -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -from cinder import exception -from cinder import flags -from cinder.openstack.common import cfg -from cinder.openstack.common import log as logging - -LOG = logging.getLogger(__name__) - -deprecate_opts = [ - cfg.BoolOpt('fatal_deprecations', - default=False, - help='make deprecations fatal')] -FLAGS = flags.FLAGS -FLAGS.register_opts(deprecate_opts) - - -def _showwarning(message, category, filename, lineno, file=None, line=None): - """ - Redirect warnings into logging. - """ - LOG.warn(str(message)) - - -# Install our warnings handler -warnings.showwarning = _showwarning - - -def warn(msg=""): - """ - Warn of a deprecated config option that an operator has specified. - This should be added in the code where we've made a change in how - we use some operator changeable parameter to indicate that it will - go away in a future version of OpenStack. - """ - warnings.warn(_("Deprecated Config: %s") % msg) - if FLAGS.fatal_deprecations: - raise exception.DeprecatedConfig(msg=msg) diff --git a/cinder/context.py b/cinder/context.py index 9da642982..951496043 100644 --- a/cinder/context.py +++ b/cinder/context.py @@ -112,7 +112,9 @@ class RequestContext(object): 'timestamp': timeutils.strtime(self.timestamp), 'request_id': self.request_id, 'auth_token': self.auth_token, - 'quota_class': self.quota_class} + 'quota_class': self.quota_class, + 'tenant': self.tenant, + 'user': self.user} @classmethod def from_dict(cls, values): @@ -131,6 +133,19 @@ class RequestContext(object): return context + # NOTE(sirp): the openstack/common version of RequestContext uses + # tenant/user whereas the Cinder version uses project_id/user_id. We need + # this shim in order to use context-aware code from openstack/common, like + # logging, until we make the switch to using openstack/common's version of + # RequestContext. + @property + def tenant(self): + return self.project_id + + @property + def user(self): + return self.user_id + def get_admin_context(read_deleted="no"): return RequestContext(user_id=None, diff --git a/cinder/exception.py b/cinder/exception.py index 14e1ba4b7..7e5d02c9f 100644 --- a/cinder/exception.py +++ b/cinder/exception.py @@ -134,10 +134,6 @@ class CinderException(Exception): super(CinderException, self).__init__(message) -class DeprecatedConfig(CinderException): - message = _("Fatal call to deprecated config") + " %(msg)s" - - class GlanceConnectionFailed(CinderException): message = _("Connection to glance failed") + ": %(reason)s" diff --git a/cinder/openstack/common/cfg.py b/cinder/openstack/common/cfg.py index 1e3c09047..617e7147c 100644 --- a/cinder/openstack/common/cfg.py +++ b/cinder/openstack/common/cfg.py @@ -217,7 +217,7 @@ log files:: ... ] -This module also contains a global instance of the CommonConfigOpts class +This module also contains a global instance of the ConfigOpts class in order to support a common usage pattern in OpenStack:: from cinder.openstack.common import cfg @@ -236,10 +236,11 @@ in order to support a common usage pattern in OpenStack:: Positional command line arguments are supported via a 'positional' Opt constructor argument:: - >>> CONF.register_cli_opt(MultiStrOpt('bar', positional=True)) + >>> conf = ConfigOpts() + >>> conf.register_cli_opt(MultiStrOpt('bar', positional=True)) True - >>> CONF(['a', 'b']) - >>> CONF.bar + >>> conf(['a', 'b']) + >>> conf.bar ['a', 'b'] It is also possible to use argparse "sub-parsers" to parse additional @@ -249,10 +250,11 @@ command line arguments using the SubCommandOpt class: ... list_action = subparsers.add_parser('list') ... list_action.add_argument('id') ... - >>> CONF.register_cli_opt(SubCommandOpt('action', handler=add_parsers)) + >>> conf = ConfigOpts() + >>> conf.register_cli_opt(SubCommandOpt('action', handler=add_parsers)) True - >>> CONF(['list', '10']) - >>> CONF.action.name, CONF.action.id + >>> conf(args=['list', '10']) + >>> conf.action.name, conf.action.id ('list', '10') """ @@ -1726,62 +1728,4 @@ class ConfigOpts(collections.Mapping): return value -class CommonConfigOpts(ConfigOpts): - - DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" - DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - - common_cli_opts = [ - BoolOpt('debug', - short='d', - default=False, - help='Print debugging output'), - BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output'), - ] - - logging_cli_opts = [ - StrOpt('log-config', - metavar='PATH', - help='If this option is specified, the logging configuration ' - 'file specified is used and overrides any other logging ' - 'options specified. Please see the Python logging module ' - 'documentation for details on logging configuration ' - 'files.'), - StrOpt('log-format', - default=DEFAULT_LOG_FORMAT, - metavar='FORMAT', - help='A logging.Formatter log message format string which may ' - 'use any of the available logging.LogRecord attributes. ' - 'Default: %(default)s'), - StrOpt('log-date-format', - default=DEFAULT_LOG_DATE_FORMAT, - metavar='DATE_FORMAT', - help='Format string for %%(asctime)s in log records. ' - 'Default: %(default)s'), - StrOpt('log-file', - metavar='PATH', - deprecated_name='logfile', - help='(Optional) Name of log file to output to. ' - 'If not set, logging will go to stdout.'), - StrOpt('log-dir', - deprecated_name='logdir', - help='(Optional) The directory to keep log files in ' - '(will be prepended to --log-file)'), - BoolOpt('use-syslog', - default=False, - help='Use syslog for logging.'), - StrOpt('syslog-log-facility', - default='LOG_USER', - help='syslog facility to receive log lines') - ] - - def __init__(self): - super(CommonConfigOpts, self).__init__() - self.register_cli_opts(self.common_cli_opts) - self.register_cli_opts(self.logging_cli_opts) - - -CONF = CommonConfigOpts() +CONF = ConfigOpts() diff --git a/cinder/openstack/common/log.py b/cinder/openstack/common/log.py index 963dcd043..93c604485 100644 --- a/cinder/openstack/common/log.py +++ b/cinder/openstack/common/log.py @@ -47,21 +47,83 @@ from cinder.openstack.common import local from cinder.openstack.common import notifier +_DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" +_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + +common_cli_opts = [ + cfg.BoolOpt('debug', + short='d', + default=False, + help='Print debugging output (set logging level to ' + 'DEBUG instead of default WARNING level).'), + cfg.BoolOpt('verbose', + short='v', + default=False, + help='Print more verbose output (set logging level to ' + 'INFO instead of default WARNING level).'), +] + +logging_cli_opts = [ + cfg.StrOpt('log-config', + metavar='PATH', + help='If this option is specified, the logging configuration ' + 'file specified is used and overrides any other logging ' + 'options specified. Please see the Python logging module ' + 'documentation for details on logging configuration ' + 'files.'), + cfg.StrOpt('log-format', + default=_DEFAULT_LOG_FORMAT, + metavar='FORMAT', + help='A logging.Formatter log message format string which may ' + 'use any of the available logging.LogRecord attributes. ' + 'Default: %(default)s'), + cfg.StrOpt('log-date-format', + default=_DEFAULT_LOG_DATE_FORMAT, + metavar='DATE_FORMAT', + help='Format string for %%(asctime)s in log records. ' + 'Default: %(default)s'), + cfg.StrOpt('log-file', + metavar='PATH', + deprecated_name='logfile', + help='(Optional) Name of log file to output to. ' + 'If not set, logging will go to stdout.'), + cfg.StrOpt('log-dir', + deprecated_name='logdir', + help='(Optional) The directory to keep log files in ' + '(will be prepended to --log-file)'), + cfg.BoolOpt('use-syslog', + default=False, + help='Use syslog for logging.'), + cfg.StrOpt('syslog-log-facility', + default='LOG_USER', + help='syslog facility to receive log lines') +] + +generic_log_opts = [ + cfg.BoolOpt('use_stderr', + default=True, + help='Log output to standard error'), + cfg.StrOpt('logfile_mode', + default='0644', + help='Default file mode used when creating log files'), +] + log_opts = [ cfg.StrOpt('logging_context_format_string', - default='%(asctime)s %(levelname)s %(name)s [%(request_id)s ' - '%(user_id)s %(project_id)s] %(instance)s' + default='%(asctime)s.%(msecs)03d %(levelname)s %(name)s ' + '[%(request_id)s %(user)s %(tenant)s] %(instance)s' '%(message)s', help='format string to use for log messages with context'), cfg.StrOpt('logging_default_format_string', - default='%(asctime)s %(process)d %(levelname)s %(name)s [-]' - ' %(instance)s%(message)s', + default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' + '%(name)s [-] %(instance)s%(message)s', help='format string to use for log messages without context'), cfg.StrOpt('logging_debug_format_suffix', default='%(funcName)s %(pathname)s:%(lineno)d', help='data to append to log format when level is DEBUG'), cfg.StrOpt('logging_exception_prefix', - default='%(asctime)s %(process)d TRACE %(name)s %(instance)s', + default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s ' + '%(instance)s', help='prefix each line of exception output with this format'), cfg.ListOpt('default_log_levels', default=[ @@ -76,6 +138,9 @@ log_opts = [ cfg.BoolOpt('publish_errors', default=False, help='publish error events'), + cfg.BoolOpt('fatal_deprecations', + default=False, + help='make deprecations fatal'), # NOTE(mikal): there are two options here because sometimes we are handed # a full instance (and could include more information), and other times we @@ -90,24 +155,9 @@ log_opts = [ 'format it like this'), ] - -generic_log_opts = [ - cfg.StrOpt('logdir', - default=None, - help='Log output to a per-service log file in named directory'), - cfg.StrOpt('logfile', - default=None, - help='Log output to a named file'), - cfg.BoolOpt('use_stderr', - default=True, - help='Log output to standard error'), - cfg.StrOpt('logfile_mode', - default='0644', - help='Default file mode used when creating log files'), -] - - CONF = cfg.CONF +CONF.register_cli_opts(common_cli_opts) +CONF.register_cli_opts(logging_cli_opts) CONF.register_opts(generic_log_opts) CONF.register_opts(log_opts) @@ -145,8 +195,8 @@ def _get_binary_name(): def _get_log_file_path(binary=None): - logfile = CONF.log_file or CONF.logfile - logdir = CONF.log_dir or CONF.logdir + logfile = CONF.log_file + logdir = CONF.log_dir if logfile and not logdir: return logfile @@ -170,6 +220,14 @@ class ContextAdapter(logging.LoggerAdapter): def audit(self, msg, *args, **kwargs): self.log(logging.AUDIT, msg, *args, **kwargs) + def deprecated(self, msg, *args, **kwargs): + stdmsg = _("Deprecated: %s") % msg + if CONF.fatal_deprecations: + self.critical(stdmsg, *args, **kwargs) + raise DeprecatedConfig(msg=stdmsg) + else: + self.warn(stdmsg, *args, **kwargs) + def process(self, msg, kwargs): if 'extra' not in kwargs: kwargs['extra'] = {} @@ -247,7 +305,7 @@ class JSONFormatter(logging.Formatter): class PublishErrorsHandler(logging.Handler): def emit(self, record): if ('cinder.openstack.common.notifier.log_notifier' in - CONF.notification_driver): + CONF.notification_driver): return notifier.api.notify(None, 'error.publisher', 'error_notification', @@ -278,6 +336,12 @@ def setup(product_name): _setup_logging_from_conf(product_name) +def set_defaults(logging_context_format_string): + cfg.set_defaults(log_opts, + logging_context_format_string= + logging_context_format_string) + + def _find_facility_from_conf(): facility_names = logging.handlers.SysLogHandler.facility_names facility = getattr(logging.handlers.SysLogHandler, @@ -343,10 +407,12 @@ def _setup_logging_from_conf(product_name): datefmt=datefmt)) handler.setFormatter(LegacyFormatter(datefmt=datefmt)) - if CONF.verbose or CONF.debug: + if CONF.debug: log_root.setLevel(logging.DEBUG) - else: + elif CONF.verbose: log_root.setLevel(logging.INFO) + else: + log_root.setLevel(logging.WARNING) level = logging.NOTSET for pair in CONF.default_log_levels: @@ -407,7 +473,7 @@ class LegacyFormatter(logging.Formatter): self._fmt = CONF.logging_default_format_string if (record.levelno == logging.DEBUG and - CONF.logging_debug_format_suffix): + CONF.logging_debug_format_suffix): self._fmt += " " + CONF.logging_debug_format_suffix # Cache this on the record, Logger will respect our formated copy @@ -450,3 +516,10 @@ class ColorHandler(logging.StreamHandler): def format(self, record): record.color = self.LEVEL_COLORS[record.levelno] return logging.StreamHandler.format(self, record) + + +class DeprecatedConfig(Exception): + message = _("Fatal call to deprecated config: %(msg)s") + + def __init__(self, msg): + super(Exception, self).__init__(self.message % dict(msg=msg)) diff --git a/cinder/tests/test_deprecated.py b/cinder/tests/test_deprecated.py deleted file mode 100644 index 5af5c7602..000000000 --- a/cinder/tests/test_deprecated.py +++ /dev/null @@ -1,46 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# -# Copyright 2010 OpenStack LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinder.common import deprecated -from cinder import exception -from cinder import test - - -class DeprecatedConfigTestCase(test.TestCase): - def setUp(self): - super(DeprecatedConfigTestCase, self).setUp() - self.logbuffer = "" - - def local_log(msg): - self.logbuffer = msg - - self.stubs.Set(deprecated.LOG, 'warn', local_log) - - def test_deprecated(self): - deprecated.warn('test') - self.assertEqual(self.logbuffer, 'Deprecated Config: test') - - def test_deprecated_fatal(self): - self.flags(fatal_deprecations=True) - self.assertRaises(exception.DeprecatedConfig, - deprecated.warn, "test2") - self.assertEqual(self.logbuffer, 'Deprecated Config: test2') - - def test_deprecated_logs_only_once(self): - deprecated.warn('only once!') - deprecated.warn('only once!') - deprecated.warn('only once!') - self.assertEqual(self.logbuffer, 'Deprecated Config: only once!') diff --git a/cinder/utils.py b/cinder/utils.py index 63786e594..bd1296654 100644 --- a/cinder/utils.py +++ b/cinder/utils.py @@ -48,7 +48,6 @@ from eventlet.green import subprocess from eventlet import greenthread from eventlet import pools -from cinder.common import deprecated from cinder import exception from cinder import flags from cinder.openstack.common import excutils @@ -144,11 +143,11 @@ def execute(*cmd, **kwargs): if run_as_root: if FLAGS.rootwrap_config is None or FLAGS.root_helper != 'sudo': - deprecated.warn(_('The root_helper option (which lets you specify ' - 'a root wrapper different from cinder-rootwrap, ' - 'and defaults to using sudo) is now deprecated. ' - 'You should use the rootwrap_config option ' - 'instead.')) + LOG.deprecated(_('The root_helper option (which lets you specify ' + 'a root wrapper different from cinder-rootwrap, ' + 'and defaults to using sudo) is now deprecated. ' + 'You should use the rootwrap_config option ' + 'instead.')) if (FLAGS.rootwrap_config is not None): cmd = ['sudo', 'cinder-rootwrap',