summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-01-29 21:01:43 +0000
committerGerrit Code Review <review@openstack.org>2015-01-29 21:01:43 +0000
commite25a1852338bf604762562f73c00608f6eb6f65e (patch)
tree095cfb42237cdaf6ced8e0e4fb249d1e49277d2d
parent734e85fb16480a5eb811394216317bd6d02a9ab6 (diff)
parent2fbf50652664a67a21dbb98a5b5dde26875eb30d (diff)
downloadoslo-incubator-e25a1852338bf604762562f73c00608f6eb6f65e.tar.gz
Merge "Remove oslo.log code and clean up versionutils API"
-rw-r--r--openstack/common/eventlet_backdoor.py2
-rw-r--r--openstack/common/fixture/__init__.py0
-rw-r--r--openstack/common/fixture/logging.py34
-rw-r--r--openstack/common/log.py718
-rw-r--r--openstack/common/loopingcall.py2
-rw-r--r--openstack/common/periodic_task.py2
-rw-r--r--openstack/common/policy.py2
-rw-r--r--openstack/common/quota.py6
-rw-r--r--openstack/common/scheduler/base_filter.py2
-rw-r--r--openstack/common/scheduler/filters/capabilities_filter.py3
-rw-r--r--openstack/common/scheduler/filters/ignore_attempted_hosts_filter.py3
-rw-r--r--openstack/common/service.py7
-rw-r--r--openstack/common/systemd.py3
-rw-r--r--openstack/common/threadgroup.py2
-rw-r--r--openstack/common/versionutils.py56
-rw-r--r--test-requirements.txt1
-rw-r--r--tests/unit/fixture/test_logging.py28
-rw-r--r--tests/unit/test_deprecated.py71
-rw-r--r--tests/unit/test_log.py681
-rw-r--r--tests/unit/test_service.py2
-rw-r--r--tests/unit/test_versionutils.py76
-rw-r--r--tox.ini2
22 files changed, 156 insertions, 1547 deletions
diff --git a/openstack/common/eventlet_backdoor.py b/openstack/common/eventlet_backdoor.py
index 31d7f24c..091cc772 100644
--- a/openstack/common/eventlet_backdoor.py
+++ b/openstack/common/eventlet_backdoor.py
@@ -19,6 +19,7 @@ from __future__ import print_function
import copy
import errno
import gc
+import logging
import os
import pprint
import socket
@@ -30,7 +31,6 @@ import greenlet
from oslo.config import cfg
from openstack.common._i18n import _LI
-from openstack.common import log as logging
help_for_backdoor_port = (
"Acceptable values are 0, <port>, and <start>:<end>, where 0 results "
diff --git a/openstack/common/fixture/__init__.py b/openstack/common/fixture/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/openstack/common/fixture/__init__.py
+++ /dev/null
diff --git a/openstack/common/fixture/logging.py b/openstack/common/fixture/logging.py
deleted file mode 100644
index 3823a035..00000000
--- a/openstack/common/fixture/logging.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# All Rights Reserved.
-#
-# 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 fixtures
-
-
-def get_logging_handle_error_fixture():
- """returns a fixture to make logging raise formatting exceptions.
-
- Usage:
- self.useFixture(logging.get_logging_handle_error_fixture())
- """
- return fixtures.MonkeyPatch('logging.Handler.handleError',
- _handleError)
-
-
-def _handleError(self, record):
- """Monkey patch for logging.Handler.handleError.
-
- The default handleError just logs the error to stderr but we want
- the option of actually raising an exception.
- """
- raise
diff --git a/openstack/common/log.py b/openstack/common/log.py
deleted file mode 100644
index 0ed95e04..00000000
--- a/openstack/common/log.py
+++ /dev/null
@@ -1,718 +0,0 @@
-# Copyright 2011 OpenStack Foundation.
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
-#
-# 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.
-
-"""OpenStack logging handler.
-
-This module adds to logging functionality by adding the option to specify
-a context object when calling the various log methods. If the context object
-is not specified, default formatting is used. Additionally, an instance uuid
-may be passed as part of the log message, which is intended to make it easier
-for admins to find messages related to a specific instance.
-
-It also allows setting of formatting information through conf.
-
-"""
-
-import copy
-import inspect
-import itertools
-import logging
-import logging.config
-import logging.handlers
-import os
-import socket
-import sys
-import traceback
-
-from oslo.config import cfg
-from oslo.utils import importutils
-from oslo_serialization import jsonutils
-import six
-from six import moves
-
-_PY26 = sys.version_info[0:2] == (2, 6)
-
-from openstack.common._i18n import _
-from openstack.common import local
-
-
-_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-append',
- metavar='PATH',
- deprecated_name='log-config',
- help='The name of a logging configuration file. This file '
- 'is appended to any existing logging configuration '
- 'files. For details about logging configuration files, '
- 'see the Python logging module documentation.'),
- cfg.StrOpt('log-format',
- metavar='FORMAT',
- help='DEPRECATED. '
- 'A logging.Formatter log message format string which may '
- 'use any of the available logging.LogRecord attributes. '
- 'This option is deprecated. Please use '
- 'logging_context_format_string and '
- 'logging_default_format_string instead.'),
- 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 no default is set, logging will go to stdout.'),
- cfg.StrOpt('log-dir',
- deprecated_name='logdir',
- help='(Optional) The base directory used for relative '
- '--log-file paths.'),
- cfg.BoolOpt('use-syslog',
- default=False,
- help='Use syslog for logging. '
- 'Existing syslog format is DEPRECATED during I, '
- 'and will change in J to honor RFC5424.'),
- cfg.BoolOpt('use-syslog-rfc-format',
- # TODO(bogdando) remove or use True after existing
- # syslog format deprecation in J
- default=False,
- help='(Optional) Enables or disables syslog rfc5424 format '
- 'for logging. If enabled, prefixes the MSG part of the '
- 'syslog message with APP-NAME (RFC5424). The '
- 'format without the APP-NAME is deprecated in I, '
- 'and will be removed in J.'),
- 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.')
-]
-
-DEFAULT_LOG_LEVELS = ['amqp=WARN', 'amqplib=WARN', 'boto=WARN',
- 'qpid=WARN', 'sqlalchemy=WARN', 'suds=INFO',
- 'oslo.messaging=INFO', 'iso8601=WARN',
- 'requests.packages.urllib3.connectionpool=WARN',
- 'urllib3.connectionpool=WARN', 'websocket=WARN',
- "keystonemiddleware=WARN", "routes.middleware=WARN",
- "stevedore=WARN"]
-
-log_opts = [
- cfg.StrOpt('logging_context_format_string',
- default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
- '%(name)s [%(request_id)s %(user_identity)s] '
- '%(instance)s%(message)s',
- help='Format string to use for log messages with context.'),
- cfg.StrOpt('logging_default_format_string',
- 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.%(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=DEFAULT_LOG_LEVELS,
- help='List of logger=LEVEL pairs.'),
- cfg.BoolOpt('publish_errors',
- default=False,
- help='Enables or disables publication of error events.'),
- cfg.BoolOpt('fatal_deprecations',
- default=False,
- help='Enables or disables fatal status of deprecations.'),
-
- # NOTE(mikal): there are two options here because sometimes we are handed
- # a full instance (and could include more information), and other times we
- # are just handed a UUID for the instance.
- cfg.StrOpt('instance_format',
- default='[instance: %(uuid)s] ',
- help='The format for an instance that is passed with the log '
- 'message.'),
- cfg.StrOpt('instance_uuid_format',
- default='[instance: %(uuid)s] ',
- help='The format for an instance UUID that is passed with the '
- 'log message.'),
-]
-
-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 list_opts():
- """Entry point for oslo-config-generator."""
- return [(None, copy.deepcopy(common_cli_opts)),
- (None, copy.deepcopy(logging_cli_opts)),
- (None, copy.deepcopy(generic_log_opts)),
- (None, copy.deepcopy(log_opts)),
- ]
-
-
-# our new audit level
-# NOTE(jkoelker) Since we synthesized an audit level, make the logging
-# module aware of it so it acts like other levels.
-logging.AUDIT = logging.INFO + 1
-logging.addLevelName(logging.AUDIT, 'AUDIT')
-
-
-try:
- NullHandler = logging.NullHandler
-except AttributeError: # NOTE(jkoelker) NullHandler added in Python 2.7
- class NullHandler(logging.Handler):
- def handle(self, record):
- pass
-
- def emit(self, record):
- pass
-
- def createLock(self):
- self.lock = None
-
-
-def _dictify_context(context):
- if context is None:
- return None
- if not isinstance(context, dict) and getattr(context, 'to_dict', None):
- context = context.to_dict()
- return context
-
-
-def _get_binary_name():
- return os.path.basename(inspect.stack()[-1][1])
-
-
-def _get_log_file_path(binary=None):
- logfile = CONF.log_file
- logdir = CONF.log_dir
-
- if logfile and not logdir:
- return logfile
-
- if logfile and logdir:
- return os.path.join(logdir, logfile)
-
- if logdir:
- binary = binary or _get_binary_name()
- return '%s.log' % (os.path.join(logdir, binary),)
-
- return None
-
-
-class BaseLoggerAdapter(logging.LoggerAdapter):
-
- def audit(self, msg, *args, **kwargs):
- self.log(logging.AUDIT, msg, *args, **kwargs)
-
- def isEnabledFor(self, level):
- if _PY26:
- # This method was added in python 2.7 (and it does the exact
- # same logic, so we need to do the exact same logic so that
- # python 2.6 has this capability as well).
- return self.logger.isEnabledFor(level)
- else:
- return super(BaseLoggerAdapter, self).isEnabledFor(level)
-
-
-class LazyAdapter(BaseLoggerAdapter):
- def __init__(self, name='unknown', version='unknown'):
- self._logger = None
- self.extra = {}
- self.name = name
- self.version = version
-
- @property
- def logger(self):
- if not self._logger:
- self._logger = getLogger(self.name, self.version)
- if six.PY3:
- # In Python 3, the code fails because the 'manager' attribute
- # cannot be found when using a LoggerAdapter as the
- # underlying logger. Work around this issue.
- self._logger.manager = self._logger.logger.manager
- return self._logger
-
-
-class ContextAdapter(BaseLoggerAdapter):
- warn = logging.LoggerAdapter.warning
-
- def __init__(self, logger, project_name, version_string):
- self.logger = logger
- self.project = project_name
- self.version = version_string
- self._deprecated_messages_sent = dict()
-
- @property
- def handlers(self):
- return self.logger.handlers
-
- def deprecated(self, msg, *args, **kwargs):
- """Call this method when a deprecated feature is used.
-
- If the system is configured for fatal deprecations then the message
- is logged at the 'critical' level and :class:`DeprecatedConfig` will
- be raised.
-
- Otherwise, the message will be logged (once) at the 'warn' level.
-
- :raises: :class:`DeprecatedConfig` if the system is configured for
- fatal deprecations.
-
- """
- stdmsg = _("Deprecated: %s") % msg
- if CONF.fatal_deprecations:
- self.critical(stdmsg, *args, **kwargs)
- raise DeprecatedConfig(msg=stdmsg)
-
- # Using a list because a tuple with dict can't be stored in a set.
- sent_args = self._deprecated_messages_sent.setdefault(msg, list())
-
- if args in sent_args:
- # Already logged this message, so don't log it again.
- return
-
- sent_args.append(args)
- self.warn(stdmsg, *args, **kwargs)
-
- def process(self, msg, kwargs):
- # NOTE(jecarey): If msg is not unicode, coerce it into unicode
- # before it can get to the python logging and
- # possibly cause string encoding trouble
- if not isinstance(msg, six.text_type):
- msg = six.text_type(msg)
-
- if 'extra' not in kwargs:
- kwargs['extra'] = {}
- extra = kwargs['extra']
-
- context = kwargs.pop('context', None)
- if not context:
- context = getattr(local.store, 'context', None)
- if context:
- extra.update(_dictify_context(context))
-
- instance = kwargs.pop('instance', None)
- instance_uuid = (extra.get('instance_uuid') or
- kwargs.pop('instance_uuid', None))
- instance_extra = ''
- if instance:
- instance_extra = CONF.instance_format % instance
- elif instance_uuid:
- instance_extra = (CONF.instance_uuid_format
- % {'uuid': instance_uuid})
- extra['instance'] = instance_extra
-
- extra.setdefault('user_identity', kwargs.pop('user_identity', None))
-
- extra['project'] = self.project
- extra['version'] = self.version
- extra['extra'] = extra.copy()
- return msg, kwargs
-
-
-class JSONFormatter(logging.Formatter):
- def __init__(self, fmt=None, datefmt=None):
- # NOTE(jkoelker) we ignore the fmt argument, but its still there
- # since logging.config.fileConfig passes it.
- self.datefmt = datefmt
-
- def formatException(self, ei, strip_newlines=True):
- lines = traceback.format_exception(*ei)
- if strip_newlines:
- lines = [moves.filter(
- lambda x: x,
- line.rstrip().splitlines()) for line in lines]
- lines = list(itertools.chain(*lines))
- return lines
-
- def format(self, record):
- message = {'message': record.getMessage(),
- 'asctime': self.formatTime(record, self.datefmt),
- 'name': record.name,
- 'msg': record.msg,
- 'args': record.args,
- 'levelname': record.levelname,
- 'levelno': record.levelno,
- 'pathname': record.pathname,
- 'filename': record.filename,
- 'module': record.module,
- 'lineno': record.lineno,
- 'funcname': record.funcName,
- 'created': record.created,
- 'msecs': record.msecs,
- 'relative_created': record.relativeCreated,
- 'thread': record.thread,
- 'thread_name': record.threadName,
- 'process_name': record.processName,
- 'process': record.process,
- 'traceback': None}
-
- if hasattr(record, 'extra'):
- message['extra'] = record.extra
-
- if record.exc_info:
- message['traceback'] = self.formatException(record.exc_info)
-
- return jsonutils.dumps(message)
-
-
-def _create_logging_excepthook(product_name):
- def logging_excepthook(exc_type, value, tb):
- extra = {'exc_info': (exc_type, value, tb)}
- getLogger(product_name).critical(
- "".join(traceback.format_exception_only(exc_type, value)),
- **extra)
- return logging_excepthook
-
-
-class LogConfigError(Exception):
-
- message = _('Error loading logging config %(log_config)s: %(err_msg)s')
-
- def __init__(self, log_config, err_msg):
- self.log_config = log_config
- self.err_msg = err_msg
-
- def __str__(self):
- return self.message % dict(log_config=self.log_config,
- err_msg=self.err_msg)
-
-
-def _load_log_config(log_config_append):
- try:
- logging.config.fileConfig(log_config_append,
- disable_existing_loggers=False)
- except (moves.configparser.Error, KeyError) as exc:
- raise LogConfigError(log_config_append, six.text_type(exc))
-
-
-def setup(product_name, version='unknown'):
- """Setup logging."""
- if CONF.log_config_append:
- _load_log_config(CONF.log_config_append)
- else:
- _setup_logging_from_conf(product_name, version)
- sys.excepthook = _create_logging_excepthook(product_name)
-
-
-def set_defaults(logging_context_format_string=None,
- default_log_levels=None):
- # Just in case the caller is not setting the
- # default_log_level. This is insurance because
- # we introduced the default_log_level parameter
- # later in a backwards in-compatible change
- if default_log_levels is not None:
- cfg.set_defaults(
- log_opts,
- default_log_levels=default_log_levels)
- if logging_context_format_string is not None:
- 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,
- CONF.syslog_log_facility,
- None)
-
- if facility is None and CONF.syslog_log_facility in facility_names:
- facility = facility_names.get(CONF.syslog_log_facility)
-
- if facility is None:
- valid_facilities = facility_names.keys()
- consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON',
- 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS',
- 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP',
- 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3',
- 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7']
- valid_facilities.extend(consts)
- raise TypeError(_('syslog facility must be one of: %s') %
- ', '.join("'%s'" % fac
- for fac in valid_facilities))
-
- return facility
-
-
-class RFCSysLogHandler(logging.handlers.SysLogHandler):
- def __init__(self, *args, **kwargs):
- self.binary_name = _get_binary_name()
- # Do not use super() unless type(logging.handlers.SysLogHandler)
- # is 'type' (Python 2.7).
- # Use old style calls, if the type is 'classobj' (Python 2.6)
- logging.handlers.SysLogHandler.__init__(self, *args, **kwargs)
-
- def format(self, record):
- # Do not use super() unless type(logging.handlers.SysLogHandler)
- # is 'type' (Python 2.7).
- # Use old style calls, if the type is 'classobj' (Python 2.6)
- msg = logging.handlers.SysLogHandler.format(self, record)
- msg = self.binary_name + ' ' + msg
- return msg
-
-
-def _setup_logging_from_conf(project, version):
- log_root = getLogger(None).logger
- for handler in log_root.handlers:
- log_root.removeHandler(handler)
-
- logpath = _get_log_file_path()
- if logpath:
- filelog = logging.handlers.WatchedFileHandler(logpath)
- log_root.addHandler(filelog)
-
- if CONF.use_stderr:
- streamlog = ColorHandler()
- log_root.addHandler(streamlog)
-
- elif not logpath:
- # pass sys.stdout as a positional argument
- # python2.6 calls the argument strm, in 2.7 it's stream
- streamlog = logging.StreamHandler(sys.stdout)
- log_root.addHandler(streamlog)
-
- if CONF.publish_errors:
- handler = importutils.import_object(
- "oslo.messaging.notify.log_handler.PublishErrorsHandler",
- logging.ERROR)
- log_root.addHandler(handler)
-
- datefmt = CONF.log_date_format
- for handler in log_root.handlers:
- # NOTE(alaski): CONF.log_format overrides everything currently. This
- # should be deprecated in favor of context aware formatting.
- if CONF.log_format:
- handler.setFormatter(logging.Formatter(fmt=CONF.log_format,
- datefmt=datefmt))
- log_root.info('Deprecated: log_format is now deprecated and will '
- 'be removed in the next release')
- else:
- handler.setFormatter(ContextFormatter(project=project,
- version=version,
- datefmt=datefmt))
-
- if CONF.debug:
- log_root.setLevel(logging.DEBUG)
- elif CONF.verbose:
- log_root.setLevel(logging.INFO)
- else:
- log_root.setLevel(logging.WARNING)
-
- for pair in CONF.default_log_levels:
- mod, _sep, level_name = pair.partition('=')
- logger = logging.getLogger(mod)
- # NOTE(AAzza) in python2.6 Logger.setLevel doesn't convert string name
- # to integer code.
- if sys.version_info < (2, 7):
- level = logging.getLevelName(level_name)
- logger.setLevel(level)
- else:
- logger.setLevel(level_name)
-
- if CONF.use_syslog:
- try:
- facility = _find_facility_from_conf()
- # TODO(bogdando) use the format provided by RFCSysLogHandler
- # after existing syslog format deprecation in J
- if CONF.use_syslog_rfc_format:
- syslog = RFCSysLogHandler(address='/dev/log',
- facility=facility)
- else:
- syslog = logging.handlers.SysLogHandler(address='/dev/log',
- facility=facility)
- log_root.addHandler(syslog)
- except socket.error:
- log_root.error('Unable to add syslog handler. Verify that syslog '
- 'is running.')
-
-
-_loggers = {}
-
-
-def getLogger(name='unknown', version='unknown'):
- if name not in _loggers:
- _loggers[name] = ContextAdapter(logging.getLogger(name),
- name,
- version)
- return _loggers[name]
-
-
-def getLazyLogger(name='unknown', version='unknown'):
- """Returns lazy logger.
-
- Creates a pass-through logger that does not create the real logger
- until it is really needed and delegates all calls to the real logger
- once it is created.
- """
- return LazyAdapter(name, version)
-
-
-class WritableLogger(object):
- """A thin wrapper that responds to `write` and logs."""
-
- def __init__(self, logger, level=logging.INFO):
- self.logger = logger
- self.level = level
-
- def write(self, msg):
- self.logger.log(self.level, msg.rstrip())
-
-
-class ContextFormatter(logging.Formatter):
- """A context.RequestContext aware formatter configured through flags.
-
- The flags used to set format strings are: logging_context_format_string
- and logging_default_format_string. You can also specify
- logging_debug_format_suffix to append extra formatting if the log level is
- debug.
-
- For information about what variables are available for the formatter see:
- http://docs.python.org/library/logging.html#formatter
-
- If available, uses the context value stored in TLS - local.store.context
-
- """
-
- def __init__(self, *args, **kwargs):
- """Initialize ContextFormatter instance
-
- Takes additional keyword arguments which can be used in the message
- format string.
-
- :keyword project: project name
- :type project: string
- :keyword version: project version
- :type version: string
-
- """
-
- self.project = kwargs.pop('project', 'unknown')
- self.version = kwargs.pop('version', 'unknown')
-
- logging.Formatter.__init__(self, *args, **kwargs)
-
- def format(self, record):
- """Uses contextstring if request_id is set, otherwise default."""
-
- # NOTE(jecarey): If msg is not unicode, coerce it into unicode
- # before it can get to the python logging and
- # possibly cause string encoding trouble
- if not isinstance(record.msg, six.text_type):
- record.msg = six.text_type(record.msg)
-
- # store project info
- record.project = self.project
- record.version = self.version
-
- # store request info
- context = getattr(local.store, 'context', None)
- if context:
- d = _dictify_context(context)
- for k, v in d.items():
- setattr(record, k, v)
-
- # NOTE(sdague): default the fancier formatting params
- # to an empty string so we don't throw an exception if
- # they get used
- for key in ('instance', 'color', 'user_identity'):
- if key not in record.__dict__:
- record.__dict__[key] = ''
-
- if record.__dict__.get('request_id'):
- fmt = CONF.logging_context_format_string
- else:
- fmt = CONF.logging_default_format_string
-
- if (record.levelno == logging.DEBUG and
- CONF.logging_debug_format_suffix):
- fmt += " " + CONF.logging_debug_format_suffix
-
- if sys.version_info < (3, 2):
- self._fmt = fmt
- else:
- self._style = logging.PercentStyle(fmt)
- self._fmt = self._style._fmt
- # Cache this on the record, Logger will respect our formatted copy
- if record.exc_info:
- record.exc_text = self.formatException(record.exc_info, record)
- return logging.Formatter.format(self, record)
-
- def formatException(self, exc_info, record=None):
- """Format exception output with CONF.logging_exception_prefix."""
- if not record:
- return logging.Formatter.formatException(self, exc_info)
-
- stringbuffer = moves.StringIO()
- traceback.print_exception(exc_info[0], exc_info[1], exc_info[2],
- None, stringbuffer)
- lines = stringbuffer.getvalue().split('\n')
- stringbuffer.close()
-
- if CONF.logging_exception_prefix.find('%(asctime)') != -1:
- record.asctime = self.formatTime(record, self.datefmt)
-
- formatted_lines = []
- for line in lines:
- pl = CONF.logging_exception_prefix % record.__dict__
- fl = '%s%s' % (pl, line)
- formatted_lines.append(fl)
- return '\n'.join(formatted_lines)
-
-
-class ColorHandler(logging.StreamHandler):
- LEVEL_COLORS = {
- logging.DEBUG: '\033[00;32m', # GREEN
- logging.INFO: '\033[00;36m', # CYAN
- logging.AUDIT: '\033[01;36m', # BOLD CYAN
- logging.WARN: '\033[01;33m', # BOLD YELLOW
- logging.ERROR: '\033[01;31m', # BOLD RED
- logging.CRITICAL: '\033[01;31m', # BOLD RED
- }
-
- 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/openstack/common/loopingcall.py b/openstack/common/loopingcall.py
index 2eaa51d6..ce115467 100644
--- a/openstack/common/loopingcall.py
+++ b/openstack/common/loopingcall.py
@@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import logging
import sys
import time
@@ -22,7 +23,6 @@ from eventlet import event
from eventlet import greenthread
from openstack.common._i18n import _LE, _LW
-from openstack.common import log as logging
LOG = logging.getLogger(__name__)
diff --git a/openstack/common/periodic_task.py b/openstack/common/periodic_task.py
index dbcad8a4..34a16383 100644
--- a/openstack/common/periodic_task.py
+++ b/openstack/common/periodic_task.py
@@ -12,6 +12,7 @@
# under the License.
import copy
+import logging
import random
import time
@@ -19,7 +20,6 @@ from oslo.config import cfg
import six
from openstack.common._i18n import _, _LE, _LI
-from openstack.common import log as logging
periodic_opts = [
diff --git a/openstack/common/policy.py b/openstack/common/policy.py
index 107a39cb..a33edfed 100644
--- a/openstack/common/policy.py
+++ b/openstack/common/policy.py
@@ -91,6 +91,7 @@ as it allows particular rules to be explicitly disabled.
import abc
import ast
import copy
+import logging
import os
import re
@@ -102,7 +103,6 @@ import six.moves.urllib.request as urlrequest
from openstack.common import fileutils
from openstack.common._i18n import _, _LE, _LI
-from openstack.common import log as logging
policy_opts = [
diff --git a/openstack/common/quota.py b/openstack/common/quota.py
index 86e3ca51..d4404662 100644
--- a/openstack/common/quota.py
+++ b/openstack/common/quota.py
@@ -18,6 +18,7 @@
import copy
import datetime
+import logging
from oslo.config import cfg
from oslo.utils import importutils
@@ -25,7 +26,7 @@ from oslo.utils import timeutils
import six
from openstack.common._i18n import _, _LE
-from openstack.common import log as logging
+from openstack.common import versionutils
LOG = logging.getLogger(__name__)
@@ -193,7 +194,8 @@ class DbQuotaDriver(object):
default_quotas = self.db.quota_class_get_default(context)
for resource in resources.values():
if resource.name not in default_quotas:
- LOG.deprecated(
+ versionutils.report_deprecated_feature(
+ LOG,
"Default quota for resource: %(res)s is set "
"by the default quota flag: quota_%(res)s, "
"it is now deprecated. Please use the "
diff --git a/openstack/common/scheduler/base_filter.py b/openstack/common/scheduler/base_filter.py
index aee7c60a..193da286 100644
--- a/openstack/common/scheduler/base_filter.py
+++ b/openstack/common/scheduler/base_filter.py
@@ -16,9 +16,9 @@
"""
Filter support
"""
+import logging
from openstack.common._i18n import _LI
-from openstack.common import log as logging
from openstack.common.scheduler import base_handler
LOG = logging.getLogger(__name__)
diff --git a/openstack/common/scheduler/filters/capabilities_filter.py b/openstack/common/scheduler/filters/capabilities_filter.py
index 011cc371..41df6fc3 100644
--- a/openstack/common/scheduler/filters/capabilities_filter.py
+++ b/openstack/common/scheduler/filters/capabilities_filter.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+import logging
+
import six
-from openstack.common import log as logging
from openstack.common.scheduler import filters
from openstack.common.scheduler.filters import extra_specs_ops
diff --git a/openstack/common/scheduler/filters/ignore_attempted_hosts_filter.py b/openstack/common/scheduler/filters/ignore_attempted_hosts_filter.py
index 0ac14d3f..a09a7e19 100644
--- a/openstack/common/scheduler/filters/ignore_attempted_hosts_filter.py
+++ b/openstack/common/scheduler/filters/ignore_attempted_hosts_filter.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from openstack.common import log as logging
+import logging
+
from openstack.common.scheduler import filters
LOG = logging.getLogger(__name__)
diff --git a/openstack/common/service.py b/openstack/common/service.py
index 579e5c95..c8d2d254 100644
--- a/openstack/common/service.py
+++ b/openstack/common/service.py
@@ -18,7 +18,7 @@
"""Generic Node base class for all workers that run on hosts."""
import errno
-import logging as std_logging
+import logging
import os
import random
import signal
@@ -39,7 +39,6 @@ from oslo.config import cfg
from openstack.common import eventlet_backdoor
from openstack.common._i18n import _LE, _LI, _LW
-from openstack.common import log as logging
from openstack.common import systemd
from openstack.common import threadgroup
@@ -163,7 +162,7 @@ class ServiceLauncher(Launcher):
signo = 0
LOG.debug('Full set of CONF:')
- CONF.log_opt_values(LOG, std_logging.DEBUG)
+ CONF.log_opt_values(LOG, logging.DEBUG)
try:
if ready_callback:
@@ -377,7 +376,7 @@ class ProcessLauncher(object):
systemd.notify_once()
LOG.debug('Full set of CONF:')
- CONF.log_opt_values(LOG, std_logging.DEBUG)
+ CONF.log_opt_values(LOG, logging.DEBUG)
try:
while True:
diff --git a/openstack/common/systemd.py b/openstack/common/systemd.py
index bbb47dfe..36243b34 100644
--- a/openstack/common/systemd.py
+++ b/openstack/common/systemd.py
@@ -16,12 +16,11 @@
Helper module for systemd service readiness notification.
"""
+import logging
import os
import socket
import sys
-from openstack.common import log as logging
-
LOG = logging.getLogger(__name__)
diff --git a/openstack/common/threadgroup.py b/openstack/common/threadgroup.py
index 53940911..ef1207a8 100644
--- a/openstack/common/threadgroup.py
+++ b/openstack/common/threadgroup.py
@@ -11,12 +11,12 @@
# 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 logging
import threading
import eventlet
from eventlet import greenpool
-from openstack.common import log as logging
from openstack.common import loopingcall
diff --git a/openstack/common/versionutils.py b/openstack/common/versionutils.py
index 13259a3b..2865b7db 100644
--- a/openstack/common/versionutils.py
+++ b/openstack/common/versionutils.py
@@ -19,15 +19,24 @@ Helpers for comparing version strings.
import functools
import inspect
+import logging
+from oslo.config import cfg
import pkg_resources
import six
from openstack.common._i18n import _
-from openstack.common import log as logging
LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+opts = [
+ cfg.BoolOpt('fatal_deprecations',
+ default=False,
+ help='Enables or disables fatal status of deprecations.'),
+]
class deprecated(object):
@@ -127,7 +136,7 @@ class deprecated(object):
@six.wraps(func_or_cls)
def wrapped(*args, **kwargs):
- LOG.deprecated(msg, details)
+ report_deprecated_feature(LOG, msg, details)
return func_or_cls(*args, **kwargs)
return wrapped
elif inspect.isclass(func_or_cls):
@@ -139,7 +148,7 @@ class deprecated(object):
# and added to the oslo-incubator requrements
@functools.wraps(orig_init, assigned=('__name__', '__doc__'))
def new_init(self, *args, **kwargs):
- LOG.deprecated(msg, details)
+ report_deprecated_feature(LOG, msg, details)
orig_init(self, *args, **kwargs)
func_or_cls.__init__ = new_init
return func_or_cls
@@ -201,3 +210,44 @@ def is_compatible(requested_version, current_version, same_major=True):
return False
return current_parts >= requested_parts
+
+
+# Track the messages we have sent already. See
+# report_deprecated_feature().
+_deprecated_messages_sent = {}
+
+
+def report_deprecated_feature(logger, msg, *args, **kwargs):
+ """Call this function when a deprecated feature is used.
+
+ If the system is configured for fatal deprecations then the message
+ is logged at the 'critical' level and :class:`DeprecatedConfig` will
+ be raised.
+
+ Otherwise, the message will be logged (once) at the 'warn' level.
+
+ :raises: :class:`DeprecatedConfig` if the system is configured for
+ fatal deprecations.
+ """
+ stdmsg = _("Deprecated: %s") % msg
+ CONF.register_opts(opts)
+ if CONF.fatal_deprecations:
+ logger.critical(stdmsg, *args, **kwargs)
+ raise DeprecatedConfig(msg=stdmsg)
+
+ # Using a list because a tuple with dict can't be stored in a set.
+ sent_args = _deprecated_messages_sent.setdefault(msg, list())
+
+ if args in sent_args:
+ # Already logged this message, so don't log it again.
+ return
+
+ sent_args.append(args)
+ logger.warn(stdmsg, *args, **kwargs)
+
+
+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/test-requirements.txt b/test-requirements.txt
index 640a5234..5392900e 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -4,7 +4,6 @@
coverage>=3.6
discover
-fixtures>=0.3.14
hacking>=0.10.0,<0.11
oslosphinx>=2.2.0 # Apache-2.0
oslotest>=1.2.0 # Apache-2.0
diff --git a/tests/unit/fixture/test_logging.py b/tests/unit/fixture/test_logging.py
deleted file mode 100644
index 22dd72e2..00000000
--- a/tests/unit/fixture/test_logging.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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 oslotest import base
-
-from openstack.common.fixture import logging as logging_fixture
-from openstack.common import log as logging
-
-LOG = logging.getLogger(__name__)
-
-
-class TestLoggingFixture(base.BaseTestCase):
- def test_logging_handle_error(self):
- LOG.info('pid of first child is %(foo)s', 1)
- self.useFixture(logging_fixture.get_logging_handle_error_fixture())
- self.assertRaises(TypeError,
- LOG.error,
- 'pid of first child is %(foo)s',
- 1)
diff --git a/tests/unit/test_deprecated.py b/tests/unit/test_deprecated.py
index a8767635..e29793d3 100644
--- a/tests/unit/test_deprecated.py
+++ b/tests/unit/test_deprecated.py
@@ -13,12 +13,15 @@
# License for the specific language governing permissions and limitations
# under the License.
+import logging
+
import mock
from oslo.config import fixture as config
from oslotest import base as test_base
from oslotest import mockpatch
-from openstack.common import log as logging
+from openstack.common import versionutils
+
LOG = logging.getLogger(__name__)
@@ -33,17 +36,21 @@ class DeprecatedConfigTestCase(test_base.BaseTestCase):
crit_fixture = self.useFixture(mockpatch.PatchObject(LOG, 'critical'))
self.crit_mock = crit_fixture.mock
- self.config = self.useFixture(config.Config()).config
+ self.config_fixture = self.useFixture(config.Config())
+ self.config_fixture.register_opts(versionutils.opts)
+ self.config = self.config_fixture.config
def test_deprecated(self):
- LOG.deprecated('test')
+ versionutils.report_deprecated_feature(LOG, 'test')
self.warn_mock.assert_called_once_with('Deprecated: test')
self.assertFalse(self.crit_mock.called)
def test_deprecated_fatal(self):
self.config(fatal_deprecations=True)
- self.assertRaises(logging.DeprecatedConfig,
- LOG.deprecated, "test2")
+ self.assertRaises(versionutils.DeprecatedConfig,
+ versionutils.report_deprecated_feature,
+ LOG,
+ "test2")
self.crit_mock.assert_called_once_with('Deprecated: test2')
self.assertFalse(self.warn_mock.called)
@@ -51,9 +58,9 @@ class DeprecatedConfigTestCase(test_base.BaseTestCase):
# If the same message is used multiple times then it's only logged
# once.
- LOG.deprecated('only once!')
- LOG.deprecated('only once!')
- LOG.deprecated('only once!')
+ versionutils.report_deprecated_feature(LOG, 'only once!')
+ versionutils.report_deprecated_feature(LOG, 'only once!')
+ versionutils.report_deprecated_feature(LOG, 'only once!')
self.warn_mock.assert_called_once_with('Deprecated: only once!')
@@ -62,12 +69,12 @@ class DeprecatedConfigTestCase(test_base.BaseTestCase):
msg1 = 'tdlodm_message 1'
msg2 = 'tdlodm_message 2'
- LOG.deprecated(msg1)
- LOG.deprecated(msg2)
- LOG.deprecated(msg1)
- LOG.deprecated(msg1)
- LOG.deprecated(msg2)
- LOG.deprecated(msg2)
+ versionutils.report_deprecated_feature(LOG, msg1)
+ versionutils.report_deprecated_feature(LOG, msg2)
+ versionutils.report_deprecated_feature(LOG, msg1)
+ versionutils.report_deprecated_feature(LOG, msg1)
+ versionutils.report_deprecated_feature(LOG, msg2)
+ versionutils.report_deprecated_feature(LOG, msg2)
exp_calls = [
mock.call('Deprecated: tdlodm_message 1'),
@@ -80,10 +87,10 @@ class DeprecatedConfigTestCase(test_base.BaseTestCase):
# If the same message format with different arguments is used then each
# set of message + argument is logged once (for a simple argument)
- LOG.deprecated('only once! %s', 'arg1')
- LOG.deprecated('only once! %s', 'arg1')
- LOG.deprecated('only once! %s', 'arg2')
- LOG.deprecated('only once! %s', 'arg2')
+ versionutils.report_deprecated_feature(LOG, 'only once! %s', 'arg1')
+ versionutils.report_deprecated_feature(LOG, 'only once! %s', 'arg1')
+ versionutils.report_deprecated_feature(LOG, 'only once! %s', 'arg2')
+ versionutils.report_deprecated_feature(LOG, 'only once! %s', 'arg2')
exp_calls = [
mock.call('Deprecated: only once! %s', 'arg1'),
@@ -105,15 +112,25 @@ class DeprecatedConfigTestCase(test_base.BaseTestCase):
msg_fmt_2_arg_2 = 6, None, 'purple'
msg_fmt_2_arg_3 = 6, None, 'something' # same first args.
- LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)
- LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_2) # logged: args different
- LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1) # no log: same msg+args
-
- LOG.deprecated(msg_fmt_2, msg_fmt_2_arg_1)
- LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2) # logged: args different
- LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3) # logged: args different
- LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3) # no log: same msg+args
- LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2) # no log: same msg+args
+ versionutils.report_deprecated_feature(LOG, msg_fmt_1, msg_fmt_1_arg_1)
+ # logged: args different
+ versionutils.report_deprecated_feature(LOG, msg_fmt_1, msg_fmt_1_arg_2)
+ # no log: same msg+args
+ versionutils.report_deprecated_feature(LOG, msg_fmt_1, msg_fmt_1_arg_1)
+
+ versionutils.report_deprecated_feature(LOG, msg_fmt_2, msg_fmt_2_arg_1)
+ # logged: args different
+ versionutils.report_deprecated_feature(LOG, msg_fmt_2,
+ *msg_fmt_2_arg_2)
+ # logged: args different
+ versionutils.report_deprecated_feature(LOG, msg_fmt_2,
+ *msg_fmt_2_arg_3)
+ # no log: same msg+args
+ versionutils.report_deprecated_feature(LOG, msg_fmt_2,
+ *msg_fmt_2_arg_3)
+ # no log: same msg+args
+ versionutils.report_deprecated_feature(LOG, msg_fmt_2,
+ *msg_fmt_2_arg_2)
exp_calls = [
mock.call('Deprecated: %s' % msg_fmt_1, msg_fmt_1_arg_1),
diff --git a/tests/unit/test_log.py b/tests/unit/test_log.py
deleted file mode 100644
index d910d28e..00000000
--- a/tests/unit/test_log.py
+++ /dev/null
@@ -1,681 +0,0 @@
-# Copyright (c) 2011 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
-
-# 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 logging
-import os
-import sys
-import tempfile
-
-import mock
-from oslo.config import cfg
-from oslo.config import fixture as config
-from oslo_context import context
-from oslo_serialization import jsonutils
-from oslotest import base as test_base
-import six
-
-from openstack.common import fileutils
-from openstack.common import local
-from openstack.common import log
-
-
-def _fake_context():
- return context.RequestContext(1, 1)
-
-
-class CommonLoggerTestsMixIn(object):
- """These tests are shared between LoggerTestCase and
- LazyLoggerTestCase.
- """
-
- def setUp(self):
- super(CommonLoggerTestsMixIn, self).setUp()
- self.config = self.useFixture(config.Config()).config
-
- # common context has different fields to the defaults in log.py
- self.config(logging_context_format_string='%(asctime)s %(levelname)s '
- '%(name)s [%(request_id)s '
- '%(user)s %(tenant)s] '
- '%(message)s')
- self.log = None
- log._setup_logging_from_conf('test', 'test')
-
- def test_handlers_have_context_formatter(self):
- formatters = []
- for h in self.log.logger.handlers:
- f = h.formatter
- if isinstance(f, log.ContextFormatter):
- formatters.append(f)
- self.assertTrue(formatters)
- self.assertEqual(len(formatters), len(self.log.logger.handlers))
-
- def test_handles_context_kwarg(self):
- self.log.info("foo", context=_fake_context())
- self.assertTrue(True) # didn't raise exception
-
- def test_audit_handles_context_arg(self):
- self.log.audit("foo", context=_fake_context())
- self.assertTrue(True) # didn't raise exception
-
- def test_will_be_verbose_if_verbose_flag_set(self):
- self.config(verbose=True)
- log.setup("test_is_verbose")
- logger = logging.getLogger("test_is_verbose")
- self.assertEqual(logging.INFO, logger.getEffectiveLevel())
-
- def test_will_be_debug_if_debug_flag_set(self):
- self.config(debug=True)
- log.setup("test_is_debug")
- logger = logging.getLogger("test_is_debug")
- self.assertEqual(logging.DEBUG, logger.getEffectiveLevel())
-
- def test_will_not_be_verbose_if_verbose_flag_not_set(self):
- self.config(verbose=False)
- log.setup("test_is_not_verbose")
- logger = logging.getLogger("test_is_not_verbose")
- self.assertEqual(logging.WARNING, logger.getEffectiveLevel())
-
- def test_no_logging_via_module(self):
- for func in ('critical', 'error', 'exception', 'warning', 'warn',
- 'info', 'debug', 'log', 'audit'):
- self.assertRaises(AttributeError, getattr, log, func)
-
-
-class LoggerTestCase(CommonLoggerTestsMixIn, test_base.BaseTestCase):
- def setUp(self):
- super(LoggerTestCase, self).setUp()
- self.log = log.getLogger(None)
-
-
-class LazyLoggerTestCase(CommonLoggerTestsMixIn, test_base.BaseTestCase):
- def setUp(self):
- super(LazyLoggerTestCase, self).setUp()
- self.log = log.getLazyLogger(None)
-
-
-class LogTestBase(test_base.BaseTestCase):
- """Base test class that provides some convenience functions."""
- def _add_handler_with_cleanup(self, log_instance, handler=None,
- formatter=None):
- """Add a log handler to a log instance.
-
- This function should be used to add handlers to loggers in test cases
- instead of directly adding them to ensure that the handler is
- correctly removed at the end of the test. Otherwise the handler may
- be left on the logger and interfere with subsequent tests.
-
- :param log_instance: The log instance to which the handler will be
- added.
- :param handler: The handler class to be added. Must be the class
- itself, not an instance.
- :param formatter: The formatter class to set on the handler. Must be
- the class itself, not an instance.
- """
- self.stream = six.StringIO()
- if handler is None:
- handler = logging.StreamHandler
- self.handler = handler(self.stream)
- if formatter is None:
- formatter = log.ContextFormatter
- self.handler.setFormatter(formatter())
- log_instance.logger.addHandler(self.handler)
- self.addCleanup(log_instance.logger.removeHandler, self.handler)
-
- def _set_log_level_with_cleanup(self, log_instance, level):
- """Set the log level of a logger for the duration of a test.
-
- Use this function to set the log level of a logger and add the
- necessary cleanup to reset it back to default at the end of the test.
-
- :param log_instance: The logger whose level will be changed.
- :param level: The new log level to use.
- """
- self.level = log_instance.logger.getEffectiveLevel()
- log_instance.logger.setLevel(level)
- self.addCleanup(log_instance.logger.setLevel, self.level)
-
-
-class LogHandlerTestCase(test_base.BaseTestCase):
-
- def setUp(self):
- super(LogHandlerTestCase, self).setUp()
- self.config = self.useFixture(config.Config()).config
-
- def test_log_path_logdir(self):
- self.config(log_dir='/some/path', log_file=None)
- self.assertEqual(log._get_log_file_path(binary='foo-bar'),
- '/some/path/foo-bar.log')
-
- def test_log_path_logfile(self):
- self.config(log_file='/some/path/foo-bar.log')
- self.assertEqual(log._get_log_file_path(binary='foo-bar'),
- '/some/path/foo-bar.log')
-
- def test_log_path_none(self):
- self.config(log_dir=None, log_file=None)
- self.assertIsNone(log._get_log_file_path(binary='foo-bar'))
-
- def test_log_path_logfile_overrides_logdir(self):
- self.config(log_dir='/some/other/path',
- log_file='/some/path/foo-bar.log')
- self.assertEqual(log._get_log_file_path(binary='foo-bar'),
- '/some/path/foo-bar.log')
-
-
-class SysLogHandlersTestCase(test_base.BaseTestCase):
- """Test for standard and RFC compliant Syslog handlers."""
- def setUp(self):
- super(SysLogHandlersTestCase, self).setUp()
- self.facility = logging.handlers.SysLogHandler.LOG_USER
- self.rfclogger = log.RFCSysLogHandler(facility=self.facility)
- self.rfclogger.binary_name = 'Foo_application'
- self.logger = logging.handlers.SysLogHandler(facility=self.facility)
- self.logger.binary_name = 'Foo_application'
-
- def test_rfc_format(self):
- """Ensure syslog msg contains APP-NAME for RFC wrapped handler."""
- logrecord = logging.LogRecord('name', 'WARN', '/tmp', 1,
- 'Message', None, None)
- expected = logging.LogRecord('name', 'WARN', '/tmp', 1,
- 'Foo_application Message', None, None)
- self.assertEqual(self.rfclogger.format(logrecord),
- expected.getMessage())
-
- def test_standard_format(self):
- """Ensure syslog msg isn't modified for standard handler."""
- logrecord = logging.LogRecord('name', 'WARN', '/tmp', 1,
- 'Message', None, None)
- expected = logrecord
- self.assertEqual(self.logger.format(logrecord),
- expected.getMessage())
-
-
-class LogLevelTestCase(test_base.BaseTestCase):
- def setUp(self):
- super(LogLevelTestCase, self).setUp()
- self.CONF = self.useFixture(config.Config()).conf
- levels = self.CONF.default_log_levels
- levels.append("nova-test=AUDIT")
- levels.append("nova-not-debug=WARN")
- self.config = self.useFixture(config.Config()).config
- self.config(default_log_levels=levels,
- verbose=True)
- log.setup('testing')
- self.log = log.getLogger('nova-test')
- self.log_no_debug = log.getLogger('nova-not-debug')
-
- def test_is_enabled_for(self):
- self.assertTrue(self.log.isEnabledFor(logging.AUDIT))
- self.assertFalse(self.log_no_debug.isEnabledFor(logging.DEBUG))
-
- def test_has_level_from_flags(self):
- self.assertEqual(logging.AUDIT, self.log.logger.getEffectiveLevel())
-
- def test_child_log_has_level_of_parent_flag(self):
- l = log.getLogger('nova-test.foo')
- self.assertEqual(logging.AUDIT, l.logger.getEffectiveLevel())
-
-
-class JSONFormatterTestCase(LogTestBase):
- def setUp(self):
- super(JSONFormatterTestCase, self).setUp()
- self.log = log.getLogger('test-json')
- self._add_handler_with_cleanup(self.log, formatter=log.JSONFormatter)
- self._set_log_level_with_cleanup(self.log, logging.DEBUG)
-
- def test_json(self):
- test_msg = 'This is a %(test)s line'
- test_data = {'test': 'log'}
- self.log.debug(test_msg, test_data)
-
- data = jsonutils.loads(self.stream.getvalue())
- self.assertTrue(data)
- self.assertTrue('extra' in data)
- self.assertEqual('test-json', data['name'])
-
- self.assertEqual(test_msg % test_data, data['message'])
- self.assertEqual(test_msg, data['msg'])
- self.assertEqual(test_data, data['args'])
-
- self.assertEqual('test_log.py', data['filename'])
- self.assertEqual('test_json', data['funcname'])
-
- self.assertEqual('DEBUG', data['levelname'])
- self.assertEqual(logging.DEBUG, data['levelno'])
- self.assertFalse(data['traceback'])
-
- def test_json_exception(self):
- test_msg = 'This is %s'
- test_data = 'exceptional'
- try:
- raise Exception('This is exceptional')
- except Exception:
- self.log.exception(test_msg, test_data)
-
- data = jsonutils.loads(self.stream.getvalue())
- self.assertTrue(data)
- self.assertTrue('extra' in data)
- self.assertEqual('test-json', data['name'])
-
- self.assertEqual(test_msg % test_data, data['message'])
- self.assertEqual(test_msg, data['msg'])
- self.assertEqual([test_data], data['args'])
-
- self.assertEqual('ERROR', data['levelname'])
- self.assertEqual(logging.ERROR, data['levelno'])
- self.assertTrue(data['traceback'])
-
-
-class ContextFormatterTestCase(LogTestBase):
- def setUp(self):
- super(ContextFormatterTestCase, self).setUp()
- self.config = self.useFixture(config.Config()).config
- self.config(logging_context_format_string="HAS CONTEXT "
- "[%(request_id)s]: "
- "%(message)s",
- logging_default_format_string="NOCTXT: %(message)s",
- logging_debug_format_suffix="--DBG")
- self.log = log.getLogger('') # obtain root logger instead of 'unknown'
- self._add_handler_with_cleanup(self.log)
- self._set_log_level_with_cleanup(self.log, logging.DEBUG)
-
- def test_uncontextualized_log(self):
- self.log.info("foo")
- self.assertEqual("NOCTXT: foo\n", self.stream.getvalue())
-
- def test_contextualized_log(self):
- ctxt = _fake_context()
- self.log.info("bar", context=ctxt)
- expected = "HAS CONTEXT [%s]: bar\n" % ctxt.request_id
- self.assertEqual(expected, self.stream.getvalue())
-
- def test_context_is_taken_from_tls_variable(self):
- ctxt = _fake_context()
- local.store.context = ctxt
- try:
- self.log.info("bar")
- expected = "HAS CONTEXT [%s]: bar\n" % ctxt.request_id
- self.assertEqual(expected, self.stream.getvalue())
- finally:
- del local.store.context
-
- def test_contextual_information_is_imparted_to_3rd_party_log_records(self):
- ctxt = _fake_context()
- local.store.context = ctxt
- try:
- sa_log = logging.getLogger('sqlalchemy.engine')
- sa_log.setLevel(logging.INFO)
- sa_log.info('emulate logging within sqlalchemy')
-
- expected = ("HAS CONTEXT [%s]: emulate logging within "
- "sqlalchemy\n" % ctxt.request_id)
- self.assertEqual(expected, self.stream.getvalue())
- finally:
- del local.store.context
-
- # def test_message_logging_3rd_party_log_records(self):
- # ctxt = _fake_context()
- # local.store.context = ctxt
- # local.store.context.request_id = six.text_type('99')
- # try:
- # sa_log = logging.getLogger('sqlalchemy.engine')
- # sa_log.setLevel(logging.INFO)
- # message = gettextutils.Message('test ' + six.unichr(128))
- # sa_log.info(message)
-
- # expected = ("HAS CONTEXT [%s]: %s\n" % (ctxt.request_id,
- # six.text_type(message)))
- # self.assertEqual(expected, self.stream.getvalue())
- # finally:
- # del local.store.context
-
- def test_debugging_log(self):
- self.log.debug("baz")
- self.assertEqual("NOCTXT: baz --DBG\n", self.stream.getvalue())
-
- # def test_message_logging(self):
- # # NOTE(luisg): Logging message objects with unicode objects
- # # may cause trouble by the logging mechanism trying to coerce
- # # the Message object, with a wrong encoding. This test case
- # # tests that problem does not occur.
- # ctxt = _fake_context()
- # ctxt.request_id = six.text_type('99')
- # message = gettextutils.Message('test ' + six.unichr(128))
- # self.log.info(message, context=ctxt)
- # expected = "HAS CONTEXT [%s]: %s\n" % (ctxt.request_id,
- # six.text_type(message))
- # self.assertEqual(expected, self.stream.getvalue())
-
- # def test_unicode_conversion_in_adapter(self):
- # ctxt = _fake_context()
- # ctxt.request_id = six.text_type('99')
- # message = "Exception is (%s)"
- # ex = Exception(gettextutils.Message('test' + six.unichr(128)))
- # self.log.debug(message, ex, context=ctxt)
- # message = six.text_type(message) % ex
- # expected = "HAS CONTEXT [%s]: %s --DBG\n" % (ctxt.request_id,
- # message)
- # self.assertEqual(expected, self.stream.getvalue())
-
- # def test_unicode_conversion_in_formatter(self):
- # ctxt = _fake_context()
- # local.store.context = ctxt
- # ctxt.request_id = six.text_type('99')
- # try:
- # no_adapt_log = logging.getLogger('no_adapt')
- # no_adapt_log.setLevel(logging.INFO)
- # message = "Exception is (%s)"
- # ex = Exception(gettextutils.Message('test' + six.unichr(128)))
- # no_adapt_log.info(message, ex)
- # message = six.text_type(message) % ex
- # expected = "HAS CONTEXT [%s]: %s\n" % (ctxt.request_id,
- # message)
- # self.assertEqual(expected, self.stream.getvalue())
- # finally:
- # del local.store.context
-
-
-class ExceptionLoggingTestCase(LogTestBase):
- """Test that Exceptions are logged."""
-
- def test_excepthook_logs_exception(self):
- product_name = 'somename'
- exc_log = log.getLogger(product_name)
-
- self._add_handler_with_cleanup(exc_log)
- excepthook = log._create_logging_excepthook(product_name)
-
- try:
- raise Exception('Some error happened')
- except Exception:
- excepthook(*sys.exc_info())
-
- expected_string = ("CRITICAL somename [-] "
- "Exception: Some error happened")
- self.assertTrue(expected_string in self.stream.getvalue(),
- msg="Exception is not logged")
-
- def test_excepthook_installed(self):
- log.setup("test_excepthook_installed")
- self.assertTrue(sys.excepthook != sys.__excepthook__)
-
-
-class FancyRecordTestCase(LogTestBase):
- """Test how we handle fancy record keys that are not in the
- base python logging.
- """
-
- def setUp(self):
- super(FancyRecordTestCase, self).setUp()
- self.config = self.useFixture(config.Config()).config
- # NOTE(sdague): use the different formatters to demonstrate format
- # string with valid fancy keys and without. Slightly hacky, but given
- # the way log objects layer up seemed to be most concise approach
- self.config(logging_context_format_string="%(color)s "
- "[%(request_id)s]: "
- "%(instance)s"
- "%(message)s",
- logging_default_format_string="%(missing)s: %(message)s")
- self.colorlog = log.getLogger()
- self._add_handler_with_cleanup(self.colorlog, log.ColorHandler)
- self._set_log_level_with_cleanup(self.colorlog, logging.DEBUG)
-
- def test_unsupported_key_in_log_msg(self):
- # NOTE(sdague): exception logging bypasses the main stream
- # and goes to stderr. Suggests on a better way to do this are
- # welcomed.
- error = sys.stderr
- sys.stderr = six.StringIO()
-
- self.colorlog.info("foo")
- self.assertNotEqual(sys.stderr.getvalue().find("KeyError: 'missing'"),
- -1)
-
- sys.stderr = error
-
- def _validate_keys(self, ctxt, keyed_log_string):
- infocolor = '\033[00;36m'
- warncolor = '\033[01;33m'
- infoexpected = "%s %s info\n" % (infocolor, keyed_log_string)
- warnexpected = "%s %s warn\n" % (warncolor, keyed_log_string)
-
- self.colorlog.info("info", context=ctxt)
- self.assertEqual(infoexpected, self.stream.getvalue())
-
- self.colorlog.warn("warn", context=ctxt)
- self.assertEqual(infoexpected + warnexpected, self.stream.getvalue())
-
- def test_fancy_key_in_log_msg(self):
- ctxt = _fake_context()
- self._validate_keys(ctxt, '[%s]:' % ctxt.request_id)
-
-
-class DomainTestCase(LogTestBase):
- def setUp(self):
- super(DomainTestCase, self).setUp()
- self.config = self.useFixture(config.Config()).config
- self.config(logging_context_format_string="[%(request_id)s]: "
- "%(user_identity)s "
- "%(message)s")
- self.mylog = log.getLogger()
- self._add_handler_with_cleanup(self.mylog)
- self._set_log_level_with_cleanup(self.mylog, logging.DEBUG)
-
- def _validate_keys(self, ctxt, keyed_log_string):
- infoexpected = "%s info\n" % (keyed_log_string)
- warnexpected = "%s warn\n" % (keyed_log_string)
-
- self.mylog.info("info", context=ctxt)
- self.assertEqual(infoexpected, self.stream.getvalue())
-
- self.mylog.warn("warn", context=ctxt)
- self.assertEqual(infoexpected + warnexpected, self.stream.getvalue())
-
- def test_domain_in_log_msg(self):
- ctxt = _fake_context()
- ctxt.domain = 'mydomain'
- ctxt.project_domain = 'myprojectdomain'
- ctxt.user_domain = 'myuserdomain'
- user_identity = ctxt.to_dict()['user_identity']
- self.assertTrue(ctxt.domain in user_identity)
- self.assertTrue(ctxt.project_domain in user_identity)
- self.assertTrue(ctxt.user_domain in user_identity)
- self._validate_keys(ctxt, ('[%s]: %s' %
- (ctxt.request_id, user_identity)))
-
-
-class SetDefaultsTestCase(test_base.BaseTestCase):
- class TestConfigOpts(cfg.ConfigOpts):
- def __call__(self, args=None):
- return cfg.ConfigOpts.__call__(self,
- args=args,
- prog='test',
- version='1.0',
- usage='%(prog)s FOO BAR',
- default_config_files=[])
-
- def setUp(self):
- super(SetDefaultsTestCase, self).setUp()
- self.conf = self.TestConfigOpts()
- self.conf.register_opts(log.log_opts)
-
- self._orig_defaults = dict([(o.dest, o.default)
- for o in log.log_opts])
- self.addCleanup(self._restore_log_defaults)
-
- def _restore_log_defaults(self):
- for opt in log.log_opts:
- opt.default = self._orig_defaults[opt.dest]
-
- def test_default_log_level_to_none(self):
- log.set_defaults(logging_context_format_string=None,
- default_log_levels=None)
- self.conf([])
- self.assertEqual(log.DEFAULT_LOG_LEVELS, self.conf.default_log_levels)
-
- def test_change_default(self):
- my_default = '%(asctime)s %(levelname)s %(name)s [%(request_id)s '\
- '%(user_id)s %(project)s] %(instance)s'\
- '%(message)s'
- log.set_defaults(logging_context_format_string=my_default)
- self.conf([])
- self.assertEqual(self.conf.logging_context_format_string, my_default)
-
- def test_change_default_log_level(self):
- log.set_defaults(default_log_levels=['foo=bar'])
- self.conf([])
- self.assertEqual(['foo=bar'], self.conf.default_log_levels)
- self.assertIsNotNone(self.conf.logging_context_format_string)
-
-
-class LogConfigOptsTestCase(test_base.BaseTestCase):
-
- def setUp(self):
- super(LogConfigOptsTestCase, self).setUp()
- self.CONF = self.useFixture(config.Config()).conf
-
- def test_print_help(self):
- f = six.StringIO()
- self.CONF([])
- self.CONF.print_help(file=f)
- self.assertTrue('debug' in f.getvalue())
- self.assertTrue('verbose' in f.getvalue())
- self.assertTrue('log-config' in f.getvalue())
- self.assertTrue('log-format' in f.getvalue())
-
- def test_debug_verbose(self):
- self.CONF(['--debug', '--verbose'])
-
- self.assertEqual(self.CONF.debug, True)
- self.assertEqual(self.CONF.verbose, True)
-
- def test_logging_opts(self):
- self.CONF([])
-
- self.assertIsNone(self.CONF.log_config_append)
- self.assertIsNone(self.CONF.log_file)
- self.assertIsNone(self.CONF.log_dir)
- self.assertIsNone(self.CONF.log_format)
-
- self.assertEqual(self.CONF.log_date_format,
- log._DEFAULT_LOG_DATE_FORMAT)
-
- self.assertEqual(self.CONF.use_syslog, False)
- self.assertEqual(self.CONF.use_syslog_rfc_format, False)
-
- def test_log_file(self):
- log_file = '/some/path/foo-bar.log'
- self.CONF(['--log-file', log_file])
- self.assertEqual(self.CONF.log_file, log_file)
-
- def test_log_dir_handlers(self):
- log_dir = tempfile.mkdtemp()
- self.CONF(['--log-dir', log_dir])
- self.CONF.set_default('use_stderr', False)
- log._setup_logging_from_conf('test', 'test')
- logger = log._loggers[None].logger
- self.assertEqual(1, len(logger.handlers))
- self.assertIsInstance(logger.handlers[0],
- logging.handlers.WatchedFileHandler)
-
- def test_logfile_deprecated(self):
- logfile = '/some/other/path/foo-bar.log'
- self.CONF(['--logfile', logfile])
- self.assertEqual(self.CONF.log_file, logfile)
-
- def test_log_dir(self):
- log_dir = '/some/path/'
- self.CONF(['--log-dir', log_dir])
- self.assertEqual(self.CONF.log_dir, log_dir)
-
- def test_logdir_deprecated(self):
- logdir = '/some/other/path/'
- self.CONF(['--logdir', logdir])
- self.assertEqual(self.CONF.log_dir, logdir)
-
- def test_log_format_overrides_formatter(self):
- self.CONF(['--log-format', '[Any format]'])
- log._setup_logging_from_conf('test', 'test')
- logger = log._loggers[None].logger
- for handler in logger.handlers:
- formatter = handler.formatter
- self.assertTrue(isinstance(formatter, logging.Formatter))
-
- def test_default_formatter(self):
- log._setup_logging_from_conf('test', 'test')
- logger = log._loggers[None].logger
- for handler in logger.handlers:
- formatter = handler.formatter
- self.assertTrue(isinstance(formatter, log.ContextFormatter))
-
-
-class LogConfigTestCase(test_base.BaseTestCase):
-
- minimal_config = b"""[loggers]
-keys=root
-
-[formatters]
-keys=
-
-[handlers]
-keys=
-
-[logger_root]
-handlers=
-"""
-
- def setUp(self):
- super(LogConfigTestCase, self).setUp()
- self.config = self.useFixture(config.Config()).config
- self.log_config_append = \
- fileutils.write_to_tempfile(content=self.minimal_config,
- prefix='logging',
- suffix='.conf'
- )
-
- def test_log_config_append_ok(self):
- self.config(log_config_append=self.log_config_append)
- log.setup('test_log_config_append')
-
- def test_log_config_append_not_exist(self):
- os.remove(self.log_config_append)
- self.config(log_config_append=self.log_config_append)
- self.assertRaises(log.LogConfigError, log.setup,
- 'test_log_config_append')
-
- def test_log_config_append_invalid(self):
- self.log_config_append = \
- fileutils.write_to_tempfile(content=self.minimal_config[5:],
- prefix='logging',
- suffix='.conf'
- )
- self.config(log_config_append=self.log_config_append)
- self.assertRaises(log.LogConfigError, log.setup,
- 'test_log_config_append')
-
- def test_log_config_append_unreadable(self):
- os.chmod(self.log_config_append, 0)
- self.config(log_config_append=self.log_config_append)
- self.assertRaises(log.LogConfigError, log.setup,
- 'test_log_config_append')
-
- def test_log_config_append_disable_existing_loggers(self):
- self.config(log_config_append=self.log_config_append)
- with mock.patch('logging.config.fileConfig') as fileConfig:
- log.setup('test_log_config_append')
-
- fileConfig.assert_called_once_with(self.log_config_append,
- disable_existing_loggers=False)
diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py
index 9c8f83b1..a81f5819 100644
--- a/tests/unit/test_service.py
+++ b/tests/unit/test_service.py
@@ -21,6 +21,7 @@ Unit Tests for service class
from __future__ import print_function
import errno
+import logging
import multiprocessing
import os
import signal
@@ -37,7 +38,6 @@ from oslotest import base as test_base
from oslotest import moxstubout
from openstack.common import eventlet_backdoor
-from openstack.common import log as logging
from openstack.common import service
diff --git a/tests/unit/test_versionutils.py b/tests/unit/test_versionutils.py
index 00481690..4cb3aabb 100644
--- a/tests/unit/test_versionutils.py
+++ b/tests/unit/test_versionutils.py
@@ -21,7 +21,7 @@ from openstack.common import versionutils
class DeprecatedTestCase(test_base.BaseTestCase):
- def assert_deprecated(self, mock_log, no_removal=False,
+ def assert_deprecated(self, mock_reporter, no_removal=False,
**expected_details):
decorator = versionutils.deprecated
if 'in_favor_of' in expected_details:
@@ -38,10 +38,14 @@ class DeprecatedTestCase(test_base.BaseTestCase):
expected_msg = getattr(
decorator,
'_deprecated_msg_with_no_alternative_no_removal')
- mock_log.deprecated.assert_called_with(expected_msg, expected_details)
+ # The first argument is the logger, and we don't care about
+ # that, so ignore it with ANY.
+ mock_reporter.assert_called_with(mock.ANY,
+ expected_msg,
+ expected_details)
- @mock.patch('openstack.common.versionutils.LOG', mock.Mock())
- def test_deprecating_a_function_returns_correct_value(self):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecating_a_function_returns_correct_value(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
def do_outdated_stuff(data):
@@ -52,8 +56,8 @@ class DeprecatedTestCase(test_base.BaseTestCase):
self.assertThat(retval, matchers.Equals(expected_rv))
- @mock.patch('openstack.common.versionutils.LOG', mock.Mock())
- def test_deprecating_a_method_returns_correct_value(self):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecating_a_method_returns_correct_value(self, mock_reporter):
class C(object):
@versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
@@ -64,8 +68,8 @@ class DeprecatedTestCase(test_base.BaseTestCase):
self.assertThat(retval, matchers.Equals((1, 'of anything')))
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_unknown_future_release(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_unknown_future_release(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.BEXAR,
in_favor_of='different_stuff()')
@@ -74,14 +78,14 @@ class DeprecatedTestCase(test_base.BaseTestCase):
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='do_outdated_stuff()',
in_favor_of='different_stuff()',
as_of='Bexar',
remove_in='D')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_known_future_release(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_known_future_release(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
in_favor_of='different_stuff()')
@@ -90,14 +94,14 @@ class DeprecatedTestCase(test_base.BaseTestCase):
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='do_outdated_stuff()',
in_favor_of='different_stuff()',
as_of='Grizzly',
remove_in='Icehouse')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_without_replacement(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_without_replacement(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY)
def do_outdated_stuff():
@@ -105,13 +109,13 @@ class DeprecatedTestCase(test_base.BaseTestCase):
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='do_outdated_stuff()',
as_of='Grizzly',
remove_in='Icehouse')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_custom_what(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_custom_what(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
what='v2.0 API',
@@ -121,14 +125,14 @@ class DeprecatedTestCase(test_base.BaseTestCase):
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='v2.0 API',
in_favor_of='v3 API',
as_of='Grizzly',
remove_in='Icehouse')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_removed_next_release(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_removed_next_release(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
remove_in=1)
@@ -137,13 +141,13 @@ class DeprecatedTestCase(test_base.BaseTestCase):
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='do_outdated_stuff()',
as_of='Grizzly',
remove_in='Havana')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_removed_plus_3(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_removed_plus_3(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
remove_in=+3)
@@ -152,27 +156,27 @@ class DeprecatedTestCase(test_base.BaseTestCase):
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='do_outdated_stuff()',
as_of='Grizzly',
remove_in='Juno')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_removed_zero(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_removed_zero(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
remove_in=0)
def do_outdated_stuff():
return
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
no_removal=True,
what='do_outdated_stuff()',
as_of='Grizzly',
remove_in='Grizzly')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_with_removed_zero_and_alternative(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_with_removed_zero_and_alternative(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
in_favor_of='different_stuff()',
remove_in=0)
@@ -180,15 +184,15 @@ class DeprecatedTestCase(test_base.BaseTestCase):
return
do_outdated_stuff()
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
no_removal=True,
what='do_outdated_stuff()',
as_of='Grizzly',
in_favor_of='different_stuff()',
remove_in='Grizzly')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_class_without_init(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_class_without_init(self, mock_reporter):
@versionutils.deprecated(as_of=versionutils.deprecated.JUNO,
remove_in=+1)
@@ -197,13 +201,13 @@ class DeprecatedTestCase(test_base.BaseTestCase):
obj = OutdatedClass()
self.assertIsInstance(obj, OutdatedClass)
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='OutdatedClass()',
as_of='Juno',
remove_in='Kilo')
- @mock.patch('openstack.common.versionutils.LOG')
- def test_deprecated_class_with_init(self, mock_log):
+ @mock.patch('openstack.common.versionutils.report_deprecated_feature')
+ def test_deprecated_class_with_init(self, mock_reporter):
mock_arguments = mock.MagicMock()
args = (1, 5, 7)
kwargs = {'first': 10, 'second': 20}
@@ -223,7 +227,7 @@ class DeprecatedTestCase(test_base.BaseTestCase):
self.assertEqual('It is __init__ method.', obj.__init__.__doc__)
self.assertEqual(args, mock_arguments.args)
self.assertEqual(kwargs, mock_arguments.kwargs)
- self.assert_deprecated(mock_log,
+ self.assert_deprecated(mock_reporter,
what='OutdatedClass()',
as_of='Juno',
remove_in='Kilo')
diff --git a/tox.ini b/tox.ini
index 5d85675f..678138ed 100644
--- a/tox.ini
+++ b/tox.ini
@@ -64,7 +64,6 @@ commands =
tests.unit.test_fileutils \
tests.unit.test_imageutils \
tests.unit.test_local \
- tests.unit.test_log \
tests.unit.test_memorycache \
tests.unit.test_periodic \
tests.unit.test_policy \
@@ -97,7 +96,6 @@ commands =
tests.unit.test_fileutils \
tests.unit.test_imageutils \
tests.unit.test_local \
- tests.unit.test_log \
tests.unit.test_memorycache \
tests.unit.test_periodic \
tests.unit.test_policy \