From 26b47c2e8fb824ea78c6013377781224e8d7082c Mon Sep 17 00:00:00 2001 From: Ronald Bradford Date: Thu, 17 Mar 2016 15:13:34 -0400 Subject: [PATCH] Graduate to oslo.log from Oslo Incubator Implements: graduate-oslo-log [1] [1] https://blueprints.launchpad.net/oslo.log/+spec/graduate-oslo-log Change-Id: Ia78b7fdc8cab695083f83b9124278463f87bc46c Closes-Bug: 1559176 --- README.md | 2 - bareon/actions/bootloader.py | 2 +- bareon/actions/configdrive.py | 2 +- bareon/actions/copyimage.py | 3 +- bareon/actions/partitioning.py | 2 +- bareon/cmd/agent.py | 15 +- bareon/drivers/data/ironic.py | 2 +- bareon/drivers/data/ks_spaces_validator.py | 3 +- bareon/drivers/data/nailgun.py | 2 +- bareon/drivers/deploy/flow.py | 3 +- bareon/drivers/deploy/generic.py | 2 +- bareon/drivers/deploy/mixins.py | 3 +- bareon/drivers/deploy/nailgun.py | 2 +- bareon/drivers/deploy/rsync.py | 3 +- bareon/drivers/deploy/swift.py | 2 +- bareon/objects/partition/parted.py | 4 +- bareon/objects/partition/scheme.py | 4 +- bareon/openstack/common/__init__.py | 17 - bareon/openstack/common/gettextutils.py | 498 -------------- bareon/openstack/common/importutils.py | 73 --- bareon/openstack/common/local.py | 45 -- bareon/openstack/common/log.py | 723 --------------------- bareon/utils/artifact.py | 2 +- bareon/utils/build.py | 3 +- bareon/utils/fs.py | 3 +- bareon/utils/grub.py | 3 +- bareon/utils/hardware.py | 3 +- bareon/utils/lvm.py | 3 +- bareon/utils/md.py | 3 +- bareon/utils/partition.py | 3 +- bareon/utils/utils.py | 2 +- openstack-common.conf | 8 - requirements.txt | 1 + tox.ini | 4 +- 34 files changed, 50 insertions(+), 1400 deletions(-) delete mode 100644 bareon/openstack/common/__init__.py delete mode 100644 bareon/openstack/common/gettextutils.py delete mode 100644 bareon/openstack/common/importutils.py delete mode 100644 bareon/openstack/common/local.py delete mode 100644 bareon/openstack/common/log.py delete mode 100644 openstack-common.conf diff --git a/README.md b/README.md index 895e944..019199d 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,8 @@ bareon │   ├── cmd │   ├── drivers │   ├── objects -│   ├── openstack │   ├── tests │   ├── utils -├── openstack-common.conf ├── README.md ├── LICENSE ├── requirements.txt diff --git a/bareon/actions/bootloader.py b/bareon/actions/bootloader.py index 5adfcd5..b5748d6 100644 --- a/bareon/actions/bootloader.py +++ b/bareon/actions/bootloader.py @@ -17,11 +17,11 @@ from io import open import os from oslo_config import cfg +from oslo_log import log as logging from bareon.actions import base from bareon.drivers.deploy import mixins from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import build as bu from bareon.utils import grub as gu from bareon.utils import hardware as hw diff --git a/bareon/actions/configdrive.py b/bareon/actions/configdrive.py index 71a5b3c..64dbe39 100644 --- a/bareon/actions/configdrive.py +++ b/bareon/actions/configdrive.py @@ -18,11 +18,11 @@ import shutil import tempfile from oslo_config import cfg +from oslo_log import log as logging import six from bareon.actions import base from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import fs as fu from bareon.utils import utils diff --git a/bareon/actions/copyimage.py b/bareon/actions/copyimage.py index 0b43d7d..1219bf3 100644 --- a/bareon/actions/copyimage.py +++ b/bareon/actions/copyimage.py @@ -18,9 +18,10 @@ import shutil import six +from oslo_log import log as logging + from bareon.actions import base from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import artifact as au from bareon.utils import fs as fu from bareon.utils import hardware as hw diff --git a/bareon/actions/partitioning.py b/bareon/actions/partitioning.py index 8d3bf9f..54ff7f9 100644 --- a/bareon/actions/partitioning.py +++ b/bareon/actions/partitioning.py @@ -16,10 +16,10 @@ import os from oslo_config import cfg +from oslo_log import log as logging from bareon.actions import base from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import fs as fu from bareon.utils import hardware as hu from bareon.utils import lvm as lu diff --git a/bareon/cmd/agent.py b/bareon/cmd/agent.py index e9aedde..6aacb1a 100644 --- a/bareon/cmd/agent.py +++ b/bareon/cmd/agent.py @@ -17,11 +17,11 @@ import signal import sys from oslo_config import cfg +from oslo_log import log as logging import six import yaml from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils from bareon import version @@ -59,7 +59,8 @@ cli_opts = [ ] CONF = cfg.CONF -CONF.register_cli_opts(cli_opts) +LOG = logging.getLogger(__name__) +PROJECT = "bareon" def list_opts(): @@ -141,11 +142,13 @@ def main(actions=None): if os.getpid() != os.getpgrp(): os.setpgrp() signal.signal(signal.SIGTERM, handle_sigterm) - CONF(sys.argv[1:], project='bareon', - version=version.version_info.release_string()) - logging.setup('bareon') - LOG = logging.getLogger(__name__) + # Setup logging and process configuration options + logging.register_options(CONF) + CONF.register_cli_opts(cli_opts) + CONF(sys.argv[1:], project=PROJECT, + version=version.version_info.release_string()) + logging.setup(CONF, PROJECT) try: if CONF.input_data: diff --git a/bareon/drivers/data/ironic.py b/bareon/drivers/data/ironic.py index ffd8a5c..8cb87d2 100644 --- a/bareon/drivers/data/ironic.py +++ b/bareon/drivers/data/ironic.py @@ -19,12 +19,12 @@ import math import os from oslo_config import cfg +from oslo_log import log as logging from bareon.drivers.data.generic import GenericDataDriver from bareon.drivers.data import ks_spaces_validator from bareon import errors from bareon import objects -from bareon.openstack.common import log as logging from bareon.utils import hardware as hu from bareon.utils import partition as pu from bareon.utils import utils diff --git a/bareon/drivers/data/ks_spaces_validator.py b/bareon/drivers/data/ks_spaces_validator.py index f261a7d..c5796e2 100644 --- a/bareon/drivers/data/ks_spaces_validator.py +++ b/bareon/drivers/data/ks_spaces_validator.py @@ -16,8 +16,9 @@ import json import jsonschema import os +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/bareon/drivers/data/nailgun.py b/bareon/drivers/data/nailgun.py index 067ee32..16a8905 100644 --- a/bareon/drivers/data/nailgun.py +++ b/bareon/drivers/data/nailgun.py @@ -17,13 +17,13 @@ import math import os from oslo_config import cfg +from oslo_log import log as logging import six from six.moves.urllib.parse import urljoin from six.moves.urllib.parse import urlparse from six.moves.urllib.parse import urlsplit import yaml -from bareon.openstack.common import log as logging from bareon.utils import hardware as hu from bareon.utils import utils diff --git a/bareon/drivers/deploy/flow.py b/bareon/drivers/deploy/flow.py index 4d47143..520d796 100644 --- a/bareon/drivers/deploy/flow.py +++ b/bareon/drivers/deploy/flow.py @@ -13,10 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +from oslo_log import log as logging + from bareon.drivers.deploy import base from bareon.drivers.deploy import mixins from bareon import errors -from bareon.openstack.common import log as logging import stevedore.named diff --git a/bareon/drivers/deploy/generic.py b/bareon/drivers/deploy/generic.py index 6dea335..c046720 100644 --- a/bareon/drivers/deploy/generic.py +++ b/bareon/drivers/deploy/generic.py @@ -18,12 +18,12 @@ import os import re from oslo_config import cfg +from oslo_log import log as logging from bareon.actions import partitioning from bareon.drivers.deploy.base import BaseDeployDriver from bareon.drivers.deploy import mixins from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import grub as gu from bareon.utils import partition as pu from bareon.utils import utils diff --git a/bareon/drivers/deploy/mixins.py b/bareon/drivers/deploy/mixins.py index 7dfb8c7..67602f4 100644 --- a/bareon/drivers/deploy/mixins.py +++ b/bareon/drivers/deploy/mixins.py @@ -18,8 +18,9 @@ import six from contextlib import contextmanager +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import fs as fu from bareon.utils import partition as pu from bareon.utils import utils diff --git a/bareon/drivers/deploy/nailgun.py b/bareon/drivers/deploy/nailgun.py index 94e7949..7c1c7df 100644 --- a/bareon/drivers/deploy/nailgun.py +++ b/bareon/drivers/deploy/nailgun.py @@ -18,6 +18,7 @@ import shutil import signal from oslo_config import cfg +from oslo_log import log as logging import six import yaml @@ -27,7 +28,6 @@ from bareon.actions import copyimage from bareon.actions import partitioning from bareon.drivers.deploy.base import BaseDeployDriver from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import build as bu from bareon.utils import fs as fu from bareon.utils import utils diff --git a/bareon/drivers/deploy/rsync.py b/bareon/drivers/deploy/rsync.py index 74c8cfd..e7e0d9b 100644 --- a/bareon/drivers/deploy/rsync.py +++ b/bareon/drivers/deploy/rsync.py @@ -15,8 +15,9 @@ import os +from oslo_log import log as logging + from bareon.drivers.deploy.generic import GenericDeployDriver -from bareon.openstack.common import log as logging from bareon.utils import utils LOG = logging.getLogger(__name__) diff --git a/bareon/drivers/deploy/swift.py b/bareon/drivers/deploy/swift.py index b730f85..99a784e 100644 --- a/bareon/drivers/deploy/swift.py +++ b/bareon/drivers/deploy/swift.py @@ -14,10 +14,10 @@ # limitations under the License. from oslo_config import cfg +from oslo_log import log as logging from bareon.drivers.deploy.generic import GenericDeployDriver from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import artifact as au from bareon.utils import fs as fu from bareon.utils import utils diff --git a/bareon/objects/partition/parted.py b/bareon/objects/partition/parted.py index 90c214d..1da9800 100644 --- a/bareon/objects/partition/parted.py +++ b/bareon/objects/partition/parted.py @@ -16,9 +16,9 @@ import copy -from bareon.objects import base -from bareon.openstack.common import log as logging +from oslo_log import log as logging +from bareon.objects import base LOG = logging.getLogger(__name__) diff --git a/bareon/objects/partition/scheme.py b/bareon/objects/partition/scheme.py index 88af219..ab591f7 100644 --- a/bareon/objects/partition/scheme.py +++ b/bareon/objects/partition/scheme.py @@ -15,6 +15,8 @@ # under the License. import os +from oslo_log import log as logging + from bareon import errors from bareon.objects.partition.fs import FileSystem from bareon.objects.partition.lv import LogicalVolume @@ -23,8 +25,6 @@ from bareon.objects.partition.parted import Parted from bareon.objects.partition.pv import PhysicalVolume from bareon.objects.partition.vg import VolumeGroup -from bareon.openstack.common import log as logging - LOG = logging.getLogger(__name__) diff --git a/bareon/openstack/common/__init__.py b/bareon/openstack/common/__init__.py deleted file mode 100644 index d1223ea..0000000 --- a/bareon/openstack/common/__init__.py +++ /dev/null @@ -1,17 +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. - -import six - - -six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) diff --git a/bareon/openstack/common/gettextutils.py b/bareon/openstack/common/gettextutils.py deleted file mode 100644 index 68138f6..0000000 --- a/bareon/openstack/common/gettextutils.py +++ /dev/null @@ -1,498 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# 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. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from bareon.openstack.common.gettextutils import _ -""" - -import copy -import functools -import gettext -import locale -from logging import handlers -import os - -from babel import localedata -import six - -_AVAILABLE_LANGUAGES = {} - -# FIXME(dhellmann): Remove this when moving to oslo.i18n. -USE_LAZY = False - - -class TranslatorFactory(object): - """Create translator functions - """ - - def __init__(self, domain, lazy=False, localedir=None): - """Establish a set of translation functions for the domain. - - :param domain: Name of translation domain, - specifying a message catalog. - :type domain: str - :param lazy: Delays translation until a message is emitted. - Defaults to False. - :type lazy: Boolean - :param localedir: Directory with translation catalogs. - :type localedir: str - """ - self.domain = domain - self.lazy = lazy - if localedir is None: - localedir = os.environ.get(domain.upper() + '_LOCALEDIR') - self.localedir = localedir - - def _make_translation_func(self, domain=None): - """Return a new translation function ready for use. - - Takes into account whether or not lazy translation is being - done. - - The domain can be specified to override the default from the - factory, but the localedir from the factory is always used - because we assume the log-level translation catalogs are - installed in the same directory as the main application - catalog. - - """ - if domain is None: - domain = self.domain - if self.lazy: - return functools.partial(Message, domain=domain) - t = gettext.translation( - domain, - localedir=self.localedir, - fallback=True, - ) - if six.PY3: - return t.gettext - return t.ugettext - - @property - def primary(self): - "The default translation function." - return self._make_translation_func() - - def _make_log_translation_func(self, level): - return self._make_translation_func(self.domain + '-log-' + level) - - @property - def log_info(self): - "Translate info-level log messages." - return self._make_log_translation_func('info') - - @property - def log_warning(self): - "Translate warning-level log messages." - return self._make_log_translation_func('warning') - - @property - def log_error(self): - "Translate error-level log messages." - return self._make_log_translation_func('error') - - @property - def log_critical(self): - "Translate critical-level log messages." - return self._make_log_translation_func('critical') - - -# NOTE(dhellmann): When this module moves out of the incubator into -# oslo.i18n, these global variables can be moved to an integration -# module within each application. - -# Create the global translation functions. -_translators = TranslatorFactory('bareon') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical - -# NOTE(dhellmann): End of globals that will move to the application's -# integration module. - - -def enable_lazy(): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - """ - # FIXME(dhellmann): This function will be removed in oslo.i18n, - # because the TranslatorFactory makes it superfluous. - global _, _LI, _LW, _LE, _LC, USE_LAZY - tf = TranslatorFactory('bareon', lazy=True) - _ = tf.primary - _LI = tf.log_info - _LW = tf.log_warning - _LE = tf.log_error - _LC = tf.log_critical - USE_LAZY = True - - -def install(domain, lazy=False): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - :param domain: the translation domain - :param lazy: indicates whether or not to install the lazy _() function. - The lazy _() introduces a way to do deferred translation - of messages by installing a _ that builds Message objects, - instead of strings, which can then be lazily translated into - any available locale. - """ - if lazy: - from six import moves - tf = TranslatorFactory(domain, lazy=True) - moves.builtins.__dict__['_'] = tf.primary - else: - localedir = '%s_LOCALEDIR' % domain.upper() - if six.PY3: - gettext.install(domain, - localedir=os.environ.get(localedir)) - else: - gettext.install(domain, - localedir=os.environ.get(localedir), - unicode=True) - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, - domain='bareon', *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale) - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate_args(self.params, desired_locale) - - translated_message = translated_message % translated_params - - return translated_message - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - if not system_locale[0]: - desired_locale = 'en_US' - else: - desired_locale = system_locale[0] - - locale_dir = os.environ.get(domain.upper() + '_LOCALEDIR') - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - if six.PY3: - translator = lang.gettext - else: - translator = lang.ugettext - - translated_message = translator(msgid) - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the parent class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - params = self._sanitize_mod_params(other) - unicode_mod = super(Message, self).__mod__(params) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=params, - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - # Merge the dictionaries - # Copy each item in case one does not support deep copy. - params = {} - if isinstance(self.params, dict): - for key, val in self.params.items(): - params[key] = self._copy_param(val) - for key, val in other.items(): - params[key] = self._copy_param(val) - else: - params = self._copy_param(other) - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except Exception: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) - - if six.PY2: - def __str__(self): - # NOTE(luisg): Logging in python 2.6 tries to str() log records, - # and it expects specifically a UnicodeError in order to proceed. - msg = _('Message objects do not support str() because they may ' - 'contain non-ascii characters. ' - 'Please use unicode() or translate() instead.') - raise UnicodeError(msg) - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = '%s_LOCALEDIR' % domain.upper() - find = lambda x: gettext.find(domain, - localedir=os.environ.get(localedir), - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - # NOTE(luisg): Babel <1.0 used a function called list(), which was - # renamed to locale_identifiers() in >=1.0, the requirements master list - # requires >=0.9.6, uncapped, so defensively work with both. We can remove - # this check when the master list updates to >=1.0, and update all projects - list_identifiers = (getattr(localedata, 'list', None) or - getattr(localedata, 'locale_identifiers')) - locale_identifiers = list_identifiers() - - for i in locale_identifiers: - if find(i) is not None: - language_list.append(i) - - # NOTE(luisg): Babel>=1.0,<1.3 has a bug where some OpenStack supported - # locales (e.g. 'zh_CN', and 'zh_TW') aren't supported even though they - # are perfectly legitimate locales: - # https://github.com/mitsuhiko/babel/issues/37 - # In Babel 1.3 they fixed the bug and they support these locales, but - # they are still not explicitly "listed" by locale_identifiers(). - # That is why we add the locales here explicitly if necessary so that - # they are listed as supported. - aliases = {'zh': 'zh_CN', - 'zh_Hant_HK': 'zh_HK', - 'zh_Hant': 'zh_TW', - 'fil': 'tl_PH'} - for (locale, alias) in six.iteritems(aliases): - if locale in language_list and alias not in language_list: - language_list.append(alias) - - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - If the locale is None the object is translated to the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - """ - message = obj - if not isinstance(message, Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def _translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = {} - for (k, v) in six.iteritems(args): - translated_v = translate(v, desired_locale) - translated_dict[k] = translated_v - return translated_dict - return translate(args, desired_locale) - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - The TranslationHandler takes a locale and a target logging.Handler object - to forward LogRecord objects to after translating them. This handler - depends on Message objects being logged, instead of regular strings. - - The handler can be configured declaratively in the logging.conf as follows: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = openstack.common.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/bareon/openstack/common/importutils.py b/bareon/openstack/common/importutils.py deleted file mode 100644 index 08299bc..0000000 --- a/bareon/openstack/common/importutils.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# 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 related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - __import__(mod_str) - try: - return getattr(sys.modules[mod_str], class_str) - except AttributeError: - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """Tries to import object from default namespace. - - Imports a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def import_versioned_module(version, submodule=None): - module = 'bareon.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return import_module(module) - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/bareon/openstack/common/local.py b/bareon/openstack/common/local.py deleted file mode 100644 index 0819d5b..0000000 --- a/bareon/openstack/common/local.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# 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. - -"""Local storage of variables using weak references""" - -import threading -import weakref - - -class WeakLocal(threading.local): - def __getattribute__(self, attr): - rval = super(WeakLocal, self).__getattribute__(attr) - if rval: - # NOTE(mikal): this bit is confusing. What is stored is a weak - # reference, not the value itself. We therefore need to lookup - # the weak reference and return the inner value here. - rval = rval() - return rval - - def __setattr__(self, attr, value): - value = weakref.ref(value) - return super(WeakLocal, self).__setattr__(attr, value) - - -# NOTE(mikal): the name "store" should be deprecated in the future -store = WeakLocal() - -# A "weak" store uses weak references and allows an object to fall out of scope -# when it falls out of scope in the code that uses the thread local storage. A -# "strong" store will hold a reference to the object so that it never falls out -# of scope. -weak_store = WeakLocal() -strong_store = threading.local() diff --git a/bareon/openstack/common/log.py b/bareon/openstack/common/log.py deleted file mode 100644 index eff47a8..0000000 --- a/bareon/openstack/common/log.py +++ /dev/null @@ -1,723 +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 inspect -import itertools -import logging -import logging.config -import logging.handlers -import os -import re -import sys -import traceback - -from oslo_config import cfg -from oslo_serialization import jsonutils -import six -from six import moves - -from bareon.openstack.common.gettextutils import _ -from bareon.openstack.common import importutils -from bareon.openstack.common import local - - -_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - -_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password'] - -# NOTE(ldbragst): Let's build a list of regex objects using the list of -# _SANITIZE_KEYS we already have. This way, we only have to add the new key -# to the list of _SANITIZE_KEYS and we can generate regular expressions -# for XML and JSON automatically. -_SANITIZE_PATTERNS = [] -_FORMAT_PATTERNS = [r'(%(key)s\s*[=]\s*[\"\']).*?([\"\'])', - r'(<%(key)s>).*?()', - r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])', - r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])', - r'([\'"].*?%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?[\'"])' - '.*?([\'"])', - r'(%(key)s\s*--?[A-z]+\s*).*?([\s])'] - -for key in _SANITIZE_KEYS: - for pattern in _FORMAT_PATTERNS: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) - _SANITIZE_PATTERNS.append(reg_ex) - - -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.') -] - -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=[ - 'amqp=WARN', - 'amqplib=WARN', - 'boto=WARN', - 'qpid=WARN', - 'sqlalchemy=WARN', - 'suds=INFO', - 'oslo.messaging=INFO', - 'iso8601=WARN', - 'requests.packages.urllib3.connectionpool=WARN' - ], - 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) - -# 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 - - -def mask_password(message, secret="***"): - """Replace password with 'secret' in message. - - :param message: The string which includes security information. - :param secret: value with which to replace passwords. - :returns: The unicode value of message with the password fields masked. - - For example: - - >>> mask_password("'adminPass' : 'aaaaa'") - "'adminPass' : '***'" - >>> mask_password("'admin_pass' : 'aaaaa'") - "'admin_pass' : '***'" - >>> mask_password('"password" : "aaaaa"') - '"password" : "***"' - >>> mask_password("'original_password' : 'aaaaa'") - "'original_password' : '***'" - >>> mask_password("u'original_password' : u'aaaaa'") - "u'original_password' : u'***'" - """ - message = six.text_type(message) - - # NOTE(ldbragst): Check to see if anything in message contains any key - # specified in _SANITIZE_KEYS, if not then just return the message since - # we don't have to mask any passwords. - if not any(key in message for key in _SANITIZE_KEYS): - return message - - secret = r'\g<1>' + secret + r'\g<2>' - for pattern in _SANITIZE_PATTERNS: - message = re.sub(pattern, secret, message) - return message - - -class BaseLoggerAdapter(logging.LoggerAdapter): - - def audit(self, msg, *args, **kwargs): - self.log(logging.AUDIT, msg, *args, **kwargs) - - -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) - 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(mrodden): catch any Message/other object and - # coerce to unicode before they can get - # to the python logging and possibly - # cause string encoding trouble - if not isinstance(msg, six.string_types): - 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 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): - 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) - - if CONF.use_syslog: - 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) - - 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( - "bareon.openstack.common.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) - - -_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.""" - - # 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'): - self._fmt = CONF.logging_context_format_string - else: - self._fmt = CONF.logging_default_format_string - - if (record.levelno == logging.DEBUG and - CONF.logging_debug_format_suffix): - self._fmt += " " + CONF.logging_debug_format_suffix - - # 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/bareon/utils/artifact.py b/bareon/utils/artifact.py index dec5729..66a6547 100644 --- a/bareon/utils/artifact.py +++ b/bareon/utils/artifact.py @@ -19,10 +19,10 @@ import tempfile import zlib from oslo_config import cfg +from oslo_log import log as logging import six from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils LOG = logging.getLogger(__name__) diff --git a/bareon/utils/build.py b/bareon/utils/build.py index 2a36a0f..fd1e9cb 100644 --- a/bareon/utils/build.py +++ b/bareon/utils/build.py @@ -28,8 +28,9 @@ import signal import six import yaml +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import fs as fu from bareon.utils import hardware as hu from bareon.utils import utils diff --git a/bareon/utils/fs.py b/bareon/utils/fs.py index 7551c62..28abc7c 100644 --- a/bareon/utils/fs.py +++ b/bareon/utils/fs.py @@ -16,8 +16,9 @@ import os import tempfile import uuid +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils import six diff --git a/bareon/utils/grub.py b/bareon/utils/grub.py index 8904c67..81f76c4 100644 --- a/bareon/utils/grub.py +++ b/bareon/utils/grub.py @@ -20,8 +20,9 @@ import six from contextlib import contextmanager +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils LOG = logging.getLogger(__name__) diff --git a/bareon/utils/hardware.py b/bareon/utils/hardware.py index 04f7f21..8837cdc 100644 --- a/bareon/utils/hardware.py +++ b/bareon/utils/hardware.py @@ -16,8 +16,9 @@ import os import re import stat +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils diff --git a/bareon/utils/lvm.py b/bareon/utils/lvm.py index c999966..e8ecb82 100644 --- a/bareon/utils/lvm.py +++ b/bareon/utils/lvm.py @@ -12,8 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils diff --git a/bareon/utils/md.py b/bareon/utils/md.py index 3334f96..2fbbfbb 100644 --- a/bareon/utils/md.py +++ b/bareon/utils/md.py @@ -15,8 +15,9 @@ import itertools import re +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import hardware as hu from bareon.utils import utils diff --git a/bareon/utils/partition.py b/bareon/utils/partition.py index c13caf7..0b5672d 100644 --- a/bareon/utils/partition.py +++ b/bareon/utils/partition.py @@ -14,8 +14,9 @@ import time +from oslo_log import log as logging + from bareon import errors -from bareon.openstack.common import log as logging from bareon.utils import utils LOG = logging.getLogger(__name__) diff --git a/bareon/utils/utils.py b/bareon/utils/utils.py index 0af6cf9..1ef9727 100644 --- a/bareon/utils/utils.py +++ b/bareon/utils/utils.py @@ -29,6 +29,7 @@ import time import difflib import jinja2 from oslo_config import cfg +from oslo_log import log as logging import requests import six import stevedore.driver @@ -36,7 +37,6 @@ import urllib3 from bareon import errors -from bareon.openstack.common import log as logging random = _random.SystemRandom() diff --git a/openstack-common.conf b/openstack-common.conf deleted file mode 100644 index 4fe5b17..0000000 --- a/openstack-common.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from oslo-incubator -module=gettextutils -module=log - -# The base module to hold the copy of openstack.common -base=bareon diff --git a/requirements.txt b/requirements.txt index fabb566..dff9a73 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ eventlet!=0.18.3,>=0.18.2 # MIT iso8601>=0.1.9 # MIT jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT oslo.config>=3.7.0 # Apache-2.0 +oslo.log>=1.14.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0 six>=1.9.0 # MIT pbr>=1.6 # Apache-2.0 diff --git a/tox.ini b/tox.ini index 799d257..b4566f8 100644 --- a/tox.ini +++ b/tox.ini @@ -39,10 +39,10 @@ commands = oslo-config-generator --config-file etc/oslo-config-generator/bareon.conf [flake8] -exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,docs +exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,docs show-pep8 = True show-source = True count = True [hacking] -import_exceptions = bareon.openstack.common.gettextutils._,testtools.matchers +import_exceptions = testtools.matchers