+++ /dev/null
-# 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)
'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):
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,
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"
...
]
-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
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
... 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')
"""
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()
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=[
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
'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)
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
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'] = {}
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',
_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,
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:
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
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))
+++ /dev/null
-# 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!')
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
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',