Use oslo log and oslo concurrency
To make patches small and easy to review, the task (using oslo) is implemented in a series of patches. In this patch, some codes under tacker/openstack/common are changed temporarily, but they will be removed totally in later patches. Change-Id: I5396e8e569ff8b26b387e99f2442ccfa3f27d684 Partial-Bug: #1552282
This commit is contained in:
parent
617f28a93e
commit
82772a0ecd
|
@ -23,7 +23,9 @@ python-keystoneclient!=1.8.0,!=2.1.0,>=1.7.0 # Apache-2.0
|
|||
alembic>=0.8.4 # MIT
|
||||
six>=1.9.0 # MIT
|
||||
stevedore>=1.10.0 # Apache-2.0
|
||||
oslo.concurrency>=3.8.0 # Apache-2.0
|
||||
oslo.config>=3.9.0 # Apache-2.0
|
||||
oslo.log>=1.14.0 # Apache-2.0
|
||||
oslo.messaging>=4.5.0 # Apache-2.0
|
||||
oslo.rootwrap>=2.0.0 # Apache-2.0
|
||||
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
|
||||
|
|
|
@ -22,10 +22,10 @@ import tempfile
|
|||
|
||||
from eventlet.green import subprocess
|
||||
from eventlet import greenthread
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.common import utils
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from six import iteritems
|
||||
from six.moves.urllib import parse as urllib_parse
|
||||
from webob import exc
|
||||
|
||||
from tacker.common import constants
|
||||
from tacker.common import exceptions
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -19,6 +19,7 @@ import imp
|
|||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import routes
|
||||
import six
|
||||
import webob.dec
|
||||
|
@ -27,7 +28,6 @@ import webob.exc
|
|||
from tacker.api.v1 import attributes
|
||||
from tacker.common import exceptions
|
||||
import tacker.extensions
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker import policy
|
||||
from tacker import wsgi
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
import re
|
||||
|
||||
import netaddr
|
||||
from oslo_log import log as logging
|
||||
from six import iteritems
|
||||
|
||||
from tacker.common import constants
|
||||
from tacker.common import exceptions as n_exc
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import uuidutils
|
||||
|
||||
|
||||
|
|
|
@ -17,12 +17,13 @@ import netaddr
|
|||
from six import iteritems
|
||||
import webob.exc
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.api import api_common
|
||||
from tacker.api.v1 import attributes
|
||||
from tacker.api.v1 import resource as wsgi_resource
|
||||
from tacker.common import exceptions
|
||||
from tacker.common import rpc as n_rpc
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker import policy
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ Utility methods for working with WSGI servers redux
|
|||
import sys
|
||||
|
||||
import netaddr
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
import webob.dec
|
||||
import webob.exc
|
||||
|
@ -27,7 +28,6 @@ import webob.exc
|
|||
from tacker.api.v1 import attributes
|
||||
from tacker.common import exceptions
|
||||
from tacker.openstack.common import gettextutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker import wsgi
|
||||
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import webob.dec
|
||||
import webob.exc
|
||||
|
||||
from tacker import context
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common.middleware import request_id
|
||||
from tacker import wsgi
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ Routines for configuring Tacker
|
|||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import oslo_messaging
|
||||
from paste import deploy
|
||||
|
||||
from tacker.common import utils
|
||||
from tacker.openstack.common.db import options as db_options
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker import version
|
||||
|
||||
|
||||
|
@ -88,6 +88,7 @@ core_cli_opts = [
|
|||
"This directory must be writable by the agent.")),
|
||||
]
|
||||
|
||||
logging.register_options(cfg.CONF)
|
||||
# Register the configuration options
|
||||
cfg.CONF.register_opts(core_opts)
|
||||
cfg.CONF.register_cli_opts(core_cli_opts)
|
||||
|
@ -119,7 +120,7 @@ def setup_logging(conf):
|
|||
:param conf: a cfg.ConfOpts object
|
||||
"""
|
||||
product_name = "tacker"
|
||||
logging.setup(product_name)
|
||||
logging.setup(conf, product_name)
|
||||
LOG.info(_("Logging enabled!"))
|
||||
|
||||
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
# under the License.
|
||||
#
|
||||
|
||||
import logging as log
|
||||
from oslo_log import log as logging
|
||||
|
||||
import stevedore.named
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DriverManager(object):
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
"""Log helper functions."""
|
||||
|
||||
from tacker.openstack.common import log as logging
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import oslo_messaging
|
||||
|
||||
from tacker.common import rpc as n_rpc
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import service
|
||||
|
||||
|
||||
|
|
|
@ -32,15 +32,15 @@ import uuid
|
|||
|
||||
from eventlet.green import subprocess
|
||||
import netaddr
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import importutils
|
||||
from six import iteritems
|
||||
from stevedore import driver
|
||||
|
||||
from tacker.common import constants as q_const
|
||||
from tacker.i18n import _LE
|
||||
from tacker.openstack.common import lockutils
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
import copy
|
||||
import datetime
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.db import api as db_api
|
||||
from tacker.openstack.common import context as common_context
|
||||
from tacker.openstack.common import local
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker import policy
|
||||
|
||||
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import sqlalchemy as sql
|
||||
|
||||
from tacker.db import model_base
|
||||
from tacker.openstack.common.db.sqlalchemy import session
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import uuid
|
||||
|
||||
from oslo_log import log as logging
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy.orm import exc as orm_exc
|
||||
|
@ -28,7 +29,6 @@ from tacker.db import model_base
|
|||
from tacker.db import models_v1
|
||||
from tacker.extensions import vnfm
|
||||
from tacker import manager
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import uuidutils
|
||||
from tacker.plugins.common import constants
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
|
||||
import abc
|
||||
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from tacker.api import extensions
|
||||
from tacker.api.v1 import attributes as attr
|
||||
from tacker.api.v1 import resource_helper
|
||||
from tacker.common import exceptions
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
from tacker.services import service_base
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.common import rpc_compat
|
||||
from tacker.common import utils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import periodic_task
|
||||
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ import os
|
|||
|
||||
from keystoneclient import exceptions
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.common import log
|
||||
from tacker.extensions import nfvo
|
||||
from tacker.nfvo.drivers.vim import abstract_vim_driver
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm import keystone
|
||||
|
||||
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.common import driver_manager
|
||||
from tacker.common import log
|
||||
from tacker.common import utils
|
||||
from tacker.db.nfvo import nfvo_db
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ import eventlet
|
|||
import eventlet.backdoor
|
||||
import greenlet
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
help_for_backdoor_port = (
|
||||
"Acceptable values are 0, <port>, and <start>:<end>, where 0 results "
|
||||
|
|
|
@ -1,137 +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 contextlib
|
||||
import errno
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
_FILE_CACHE = {}
|
||||
|
||||
|
||||
def ensure_tree(path):
|
||||
"""Create a directory (and any ancestor directories required)
|
||||
|
||||
:param path: Directory to create
|
||||
"""
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
if not os.path.isdir(path):
|
||||
raise
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def read_cached_file(filename, force_reload=False):
|
||||
"""Read from a file if it has been modified.
|
||||
|
||||
:param force_reload: Whether to reload the file.
|
||||
:returns: A tuple with a boolean specifying if the data is fresh
|
||||
or not.
|
||||
"""
|
||||
global _FILE_CACHE
|
||||
|
||||
if force_reload and filename in _FILE_CACHE:
|
||||
del _FILE_CACHE[filename]
|
||||
|
||||
reloaded = False
|
||||
mtime = os.path.getmtime(filename)
|
||||
cache_info = _FILE_CACHE.setdefault(filename, {})
|
||||
|
||||
if not cache_info or mtime > cache_info.get('mtime', 0):
|
||||
LOG.debug(_("Reloading cached file %s"), filename)
|
||||
with open(filename) as fap:
|
||||
cache_info['data'] = fap.read()
|
||||
cache_info['mtime'] = mtime
|
||||
reloaded = True
|
||||
return (reloaded, cache_info['data'])
|
||||
|
||||
|
||||
def delete_if_exists(path, remove=os.unlink):
|
||||
"""Delete a file, but ignore file not found error.
|
||||
|
||||
:param path: File to delete
|
||||
:param remove: Optional function to remove passed path
|
||||
"""
|
||||
|
||||
try:
|
||||
remove(path)
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def remove_path_on_error(path, remove=delete_if_exists):
|
||||
"""Protect code that wants to operate on PATH atomically.
|
||||
Any exception will cause PATH to be removed.
|
||||
|
||||
:param path: File to work with
|
||||
:param remove: Optional function to remove passed path
|
||||
"""
|
||||
|
||||
try:
|
||||
yield
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
remove(path)
|
||||
|
||||
|
||||
def file_open(*args, **kwargs):
|
||||
"""Open file
|
||||
|
||||
see built-in file() documentation for more details
|
||||
|
||||
Note: The reason this is kept in a separate module is to easily
|
||||
be able to provide a stub module that doesn't alter system
|
||||
state at all (for unit tests)
|
||||
"""
|
||||
return file(*args, **kwargs)
|
||||
|
||||
|
||||
def write_to_tempfile(content, path=None, suffix='', prefix='tmp'):
|
||||
"""Create temporary file or use existing file.
|
||||
|
||||
This util is needed for creating temporary file with
|
||||
specified content, suffix and prefix. If path is not None,
|
||||
it will be used for writing content. If the path doesn't
|
||||
exist it'll be created.
|
||||
|
||||
:param content: content for temporary file.
|
||||
:param path: same as parameter 'dir' for mkstemp
|
||||
:param suffix: same as parameter 'suffix' for mkstemp
|
||||
:param prefix: same as parameter 'prefix' for mkstemp
|
||||
|
||||
For example: it can be used in database tests for creating
|
||||
configuration files.
|
||||
"""
|
||||
if path:
|
||||
ensure_tree(path)
|
||||
|
||||
(fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix)
|
||||
try:
|
||||
os.write(fd, content)
|
||||
finally:
|
||||
os.close(fd)
|
||||
return path
|
|
@ -1,303 +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 contextlib
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import weakref
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from tacker.openstack.common import fileutils
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import local
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
util_opts = [
|
||||
cfg.BoolOpt('disable_process_locking', default=False,
|
||||
help='Whether to disable inter-process locks'),
|
||||
cfg.StrOpt('lock_path',
|
||||
default=os.environ.get("TACKER_LOCK_PATH"),
|
||||
help=('Directory to use for lock files.'))
|
||||
]
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(util_opts)
|
||||
|
||||
|
||||
def set_defaults(lock_path):
|
||||
cfg.set_defaults(util_opts, lock_path=lock_path)
|
||||
|
||||
|
||||
class _InterProcessLock(object):
|
||||
"""Lock implementation which allows multiple locks, working around
|
||||
issues like bugs.debian.org/cgi-bin/bugreport.cgi?bug=632857 and does
|
||||
not require any cleanup. Since the lock is always held on a file
|
||||
descriptor rather than outside of the process, the lock gets dropped
|
||||
automatically if the process crashes, even if __exit__ is not executed.
|
||||
|
||||
There are no guarantees regarding usage by multiple green threads in a
|
||||
single process here. This lock works only between processes. Exclusive
|
||||
access between local threads should be achieved using the semaphores
|
||||
in the @synchronized decorator.
|
||||
|
||||
Note these locks are released when the descriptor is closed, so it's not
|
||||
safe to close the file descriptor while another green thread holds the
|
||||
lock. Just opening and closing the lock file can break synchronisation,
|
||||
so lock files must be accessed only using this abstraction.
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
self.lockfile = None
|
||||
self.fname = name
|
||||
|
||||
def __enter__(self):
|
||||
self.lockfile = open(self.fname, 'w')
|
||||
|
||||
while True:
|
||||
try:
|
||||
# Using non-blocking locks since green threads are not
|
||||
# patched to deal with blocking locking calls.
|
||||
# Also upon reading the MSDN docs for locking(), it seems
|
||||
# to have a laughable 10 attempts "blocking" mechanism.
|
||||
self.trylock()
|
||||
return self
|
||||
except IOError as e:
|
||||
if e.errno in (errno.EACCES, errno.EAGAIN):
|
||||
# external locks synchronise things like iptables
|
||||
# updates - give it some time to prevent busy spinning
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
raise
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
try:
|
||||
self.unlock()
|
||||
self.lockfile.close()
|
||||
except IOError:
|
||||
LOG.exception(_("Could not release the acquired lock `%s`"),
|
||||
self.fname)
|
||||
|
||||
def trylock(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def unlock(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class _WindowsLock(_InterProcessLock):
|
||||
def trylock(self):
|
||||
msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1)
|
||||
|
||||
def unlock(self):
|
||||
msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1)
|
||||
|
||||
|
||||
class _PosixLock(_InterProcessLock):
|
||||
def trylock(self):
|
||||
fcntl.lockf(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
|
||||
def unlock(self):
|
||||
fcntl.lockf(self.lockfile, fcntl.LOCK_UN)
|
||||
|
||||
|
||||
if os.name == 'nt':
|
||||
import msvcrt
|
||||
InterProcessLock = _WindowsLock
|
||||
else:
|
||||
import fcntl
|
||||
InterProcessLock = _PosixLock
|
||||
|
||||
_semaphores = weakref.WeakValueDictionary()
|
||||
_semaphores_lock = threading.Lock()
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def lock(name, lock_file_prefix=None, external=False, lock_path=None):
|
||||
"""Context based lock
|
||||
|
||||
This function yields a `threading.Semaphore` instance (if we don't use
|
||||
eventlet.monkey_patch(), else `semaphore.Semaphore`) unless external is
|
||||
True, in which case, it'll yield an InterProcessLock instance.
|
||||
|
||||
:param lock_file_prefix: The lock_file_prefix argument is used to provide
|
||||
lock files on disk with a meaningful prefix.
|
||||
|
||||
:param external: The external keyword argument denotes whether this lock
|
||||
should work across multiple processes. This means that if two different
|
||||
workers both run a a method decorated with @synchronized('mylock',
|
||||
external=True), only one of them will execute at a time.
|
||||
|
||||
:param lock_path: The lock_path keyword argument is used to specify a
|
||||
special location for external lock files to live. If nothing is set, then
|
||||
CONF.lock_path is used as a default.
|
||||
"""
|
||||
with _semaphores_lock:
|
||||
try:
|
||||
sem = _semaphores[name]
|
||||
except KeyError:
|
||||
sem = threading.Semaphore()
|
||||
_semaphores[name] = sem
|
||||
|
||||
with sem:
|
||||
LOG.debug(_('Got semaphore "%(lock)s"'), {'lock': name})
|
||||
|
||||
# NOTE(mikal): I know this looks odd
|
||||
if not hasattr(local.strong_store, 'locks_held'):
|
||||
local.strong_store.locks_held = []
|
||||
local.strong_store.locks_held.append(name)
|
||||
|
||||
try:
|
||||
if external and not CONF.disable_process_locking:
|
||||
LOG.debug(_('Attempting to grab file lock "%(lock)s"'),
|
||||
{'lock': name})
|
||||
|
||||
# We need a copy of lock_path because it is non-local
|
||||
local_lock_path = lock_path or CONF.lock_path
|
||||
if not local_lock_path:
|
||||
raise cfg.RequiredOptError('lock_path')
|
||||
|
||||
if not os.path.exists(local_lock_path):
|
||||
fileutils.ensure_tree(local_lock_path)
|
||||
LOG.info(_('Created lock path: %s'), local_lock_path)
|
||||
|
||||
def add_prefix(name, prefix):
|
||||
if not prefix:
|
||||
return name
|
||||
sep = '' if prefix.endswith('-') else '-'
|
||||
return '%s%s%s' % (prefix, sep, name)
|
||||
|
||||
# NOTE(mikal): the lock name cannot contain directory
|
||||
# separators
|
||||
lock_file_name = add_prefix(name.replace(os.sep, '_'),
|
||||
lock_file_prefix)
|
||||
|
||||
lock_file_path = os.path.join(local_lock_path, lock_file_name)
|
||||
|
||||
try:
|
||||
lock = InterProcessLock(lock_file_path)
|
||||
with lock as lock:
|
||||
LOG.debug(_('Got file lock "%(lock)s" at %(path)s'),
|
||||
{'lock': name, 'path': lock_file_path})
|
||||
yield lock
|
||||
finally:
|
||||
LOG.debug(_('Released file lock "%(lock)s" at %(path)s'),
|
||||
{'lock': name, 'path': lock_file_path})
|
||||
else:
|
||||
yield sem
|
||||
|
||||
finally:
|
||||
local.strong_store.locks_held.remove(name)
|
||||
|
||||
|
||||
def synchronized(name, lock_file_prefix=None, external=False, lock_path=None):
|
||||
"""Synchronization decorator.
|
||||
|
||||
Decorating a method like so::
|
||||
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
|
||||
ensures that only one thread will execute the foo method at a time.
|
||||
|
||||
Different methods can share the same lock::
|
||||
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
|
||||
@synchronized('mylock')
|
||||
def bar(self, *args):
|
||||
...
|
||||
|
||||
This way only one of either foo or bar can be executing at a time.
|
||||
"""
|
||||
|
||||
def wrap(f):
|
||||
@functools.wraps(f)
|
||||
def inner(*args, **kwargs):
|
||||
try:
|
||||
with lock(name, lock_file_prefix, external, lock_path):
|
||||
LOG.debug(_('Got semaphore / lock "%(function)s"'),
|
||||
{'function': f.__name__})
|
||||
return f(*args, **kwargs)
|
||||
finally:
|
||||
LOG.debug(_('Semaphore / lock released "%(function)s"'),
|
||||
{'function': f.__name__})
|
||||
return inner
|
||||
return wrap
|
||||
|
||||
|
||||
def synchronized_with_prefix(lock_file_prefix):
|
||||
"""Partial object generator for the synchronization decorator.
|
||||
|
||||
Redefine @synchronized in each project like so::
|
||||
|
||||
(in nova/utils.py)
|
||||
from nova.openstack.common import lockutils
|
||||
|
||||
synchronized = lockutils.synchronized_with_prefix('nova-')
|
||||
|
||||
|
||||
(in nova/foo.py)
|
||||
from nova import utils
|
||||
|
||||
@utils.synchronized('mylock')
|
||||
def bar(self, *args):
|
||||
...
|
||||
|
||||
The lock_file_prefix argument is used to provide lock files on disk with a
|
||||
meaningful prefix.
|
||||
"""
|
||||
|
||||
return functools.partial(synchronized, lock_file_prefix=lock_file_prefix)
|
||||
|
||||
|
||||
def main(argv):
|
||||
"""Create a dir for locks and pass it to command from arguments
|
||||
|
||||
If you run this:
|
||||
python -m openstack.common.lockutils python setup.py testr <etc>
|
||||
|
||||
a temporary directory will be created for all your locks and passed to all
|
||||
your tests in an environment variable. The temporary dir will be deleted
|
||||
afterwards and the return value will be preserved.
|
||||
"""
|
||||
|
||||
lock_dir = tempfile.mkdtemp()
|
||||
os.environ["TACKER_LOCK_PATH"] = lock_dir
|
||||
try:
|
||||
ret_val = subprocess.call(argv[1:])
|
||||
finally:
|
||||
shutil.rmtree(lock_dir, ignore_errors=True)
|
||||
return ret_val
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
|
@ -1,626 +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
|
||||
import six
|
||||
from six import moves
|
||||
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import importutils
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.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>).*?(</%(key)s>)',
|
||||
r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])',
|
||||
r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])']
|
||||
|
||||
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 logging configuration file. It does not '
|
||||
'disable existing loggers, but just appends specified '
|
||||
'logging configuration to any other existing logging '
|
||||
'options. Please see the Python logging module '
|
||||
'documentation for details on logging configuration '
|
||||
'files.'),
|
||||
cfg.StrOpt('log-format',
|
||||
default=None,
|
||||
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.'),
|
||||
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',
|
||||
'iso8601=WARN',
|
||||
],
|
||||
help='list of logger=LEVEL pairs'),
|
||||
cfg.BoolOpt('publish_errors',
|
||||
default=False,
|
||||
help='publish error events'),
|
||||
cfg.BoolOpt('fatal_deprecations',
|
||||
default=False,
|
||||
help='make deprecations fatal'),
|
||||
|
||||
# NOTE(mikal): there are two options here because sometimes we are handed
|
||||
# a full instance (and could include more information), and other times we
|
||||
# are just handed a UUID for the instance.
|
||||
cfg.StrOpt('instance_format',
|
||||
default='[instance: %(uuid)s] ',
|
||||
help='If an instance is passed with the log message, format '
|
||||
'it like this'),
|
||||
cfg.StrOpt('instance_uuid_format',
|
||||
default='[instance: %(uuid)s] ',
|
||||
help='If an instance UUID is passed with the log message, '
|
||||
'format it like this'),
|
||||
]
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def handlers(self):
|
||||
return self.logger.handlers
|
||||
|
||||
def deprecated(self, msg, *args, **kwargs):
|
||||
stdmsg = _("Deprecated: %s") % msg
|
||||
if CONF.fatal_deprecations:
|
||||
self.critical(stdmsg, *args, **kwargs)
|
||||
raise DeprecatedConfig(msg=stdmsg)
|
||||
else:
|
||||
self.warn(stdmsg, *args, **kwargs)
|
||||
|
||||
def process(self, msg, kwargs):
|
||||
# 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', None) 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 = {}
|
||||
if CONF.verbose:
|
||||
extra['exc_info'] = (exc_type, value, tb)
|
||||
getLogger(product_name).critical(str(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, str(exc))
|
||||
|
||||
|
||||
def setup(product_name):
|
||||
"""Setup logging."""
|
||||
if CONF.log_config_append:
|
||||
_load_log_config(CONF.log_config_append)
|
||||
else:
|
||||
_setup_logging_from_conf()
|
||||
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
|
||||
|
||||
|
||||
def _setup_logging_from_conf():
|
||||
log_root = getLogger(None).logger
|
||||
for handler in log_root.handlers:
|
||||
log_root.removeHandler(handler)
|
||||
|
||||
if CONF.use_syslog:
|
||||
facility = _find_facility_from_conf()
|
||||
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(
|
||||
"tacker.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(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('=')
|
||||
level = logging.getLevelName(level_name)
|
||||
logger = logging.getLogger(mod)
|
||||
logger.setLevel(level)
|
||||
|
||||
_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)
|
||||
|
||||
|
||||
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
|
||||
|
||||
"""
|
||||
|
||||
def format(self, record):
|
||||
"""Uses contextstring if request_id is set, otherwise default."""
|
||||
# NOTE(sdague): default the fancier formating params
|
||||
# to an empty string so we don't throw an exception if
|
||||
# they get used
|
||||
for key in ('instance', 'color'):
|
||||
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 formated 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))
|
|
@ -1,30 +0,0 @@
|
|||
# Copyright 2013 IBM Corp.
|
||||
#
|
||||
# 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
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from tacker.openstack.common import notifier
|
||||
|
||||
|
||||
class PublishErrorsHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
if ('tacker.openstack.common.notifier.log_notifier' in
|
||||
cfg.CONF.notification_driver):
|
||||
return
|
||||
notifier.api.notify(None, 'error.publisher',
|
||||
'error_notification',
|
||||
notifier.api.ERROR,
|
||||
dict(error=record.getMessage()))
|
|
@ -19,9 +19,9 @@ import sys
|
|||
|
||||
from eventlet import event
|
||||
from eventlet import greenthread
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import timeutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -19,11 +19,11 @@ It catches all exceptions from subsequent applications in WSGI pipeline
|
|||
to hide internal errors from API response.
|
||||
"""
|
||||
|
||||
from oslo_log import log as logging
|
||||
import webob.dec
|
||||
import webob.exc
|
||||
|
||||
from tacker.openstack.common.gettextutils import _ # noqa
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common.middleware import base
|
||||
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ import os.path
|
|||
import sys
|
||||
import traceback as tb
|
||||
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
import webob.dec
|
||||
|
||||
from tacker.openstack.common import context
|
||||
from tacker.openstack.common.gettextutils import _LE
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common.middleware import base
|
||||
from tacker.openstack.common.notifier import api
|
||||
|
||||
|
|
|
@ -14,11 +14,10 @@
|
|||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from tacker.openstack.common.gettextutils import _, _LE, _LI
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
periodic_opts = [
|
||||
cfg.BoolOpt('run_external_periodic_tasks',
|
||||
|
|
|
@ -57,14 +57,13 @@ as it allows particular rules to be explicitly disabled.
|
|||
import abc
|
||||
import re
|
||||
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from six.moves.urllib import parse as urllib_parse
|
||||
from six.moves.urllib import request as urlrequest
|
||||
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -25,9 +25,9 @@ import signal
|
|||
|
||||
from eventlet.green import subprocess
|
||||
from eventlet import greenthread
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -36,11 +36,11 @@ except ImportError:
|
|||
import eventlet
|
||||
from eventlet import event
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.openstack.common import eventlet_backdoor
|
||||
from tacker.openstack.common.gettextutils import _LE, _LI, _LW
|
||||
from tacker.openstack.common import importutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import systemd
|
||||
from tacker.openstack.common import threadgroup
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import os
|
|||
import socket
|
||||
import sys
|
||||
|
||||
from tacker.openstack.common import log as logging
|
||||
from oslo_log import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
import eventlet
|
||||
from eventlet import greenpool
|
||||
from eventlet import greenthread
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import loopingcall
|
||||
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@ Helpers for comparing version strings.
|
|||
"""
|
||||
|
||||
import functools
|
||||
from oslo_log import log as logging
|
||||
import pkg_resources
|
||||
|
||||
from tacker.openstack.common.gettextutils import _
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -20,6 +20,7 @@ import itertools
|
|||
import re
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from tacker.api.v1 import attributes
|
||||
|
@ -27,7 +28,6 @@ from tacker.common import exceptions
|
|||
import tacker.common.utils as utils
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import importutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import policy
|
||||
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
import logging as std_logging
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.common import config
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker import wsgi
|
||||
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
import os
|
||||
|
||||
import fixtures
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.agent.linux import utils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.tests import base
|
||||
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
|
||||
"""stubs.py provides interface methods for the database test cases"""
|
||||
|
||||
from tacker.db import api as db
|
||||
from tacker.openstack.common import log as logging
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.db import api as db
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import abc
|
||||
|
||||
import mock
|
||||
from oslo_log import log as logging
|
||||
import routes
|
||||
import webob
|
||||
import webtest
|
||||
|
@ -24,7 +25,6 @@ from tacker.api import extensions
|
|||
from tacker.common import config
|
||||
from tacker.common import exceptions
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
from tacker.tests import base
|
||||
from tacker.tests.unit import extension_stubs as ext_stubs
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
import random
|
||||
|
||||
from oslo_log import log as logging
|
||||
import sqlalchemy as sa
|
||||
|
||||
from tacker.db.vm import vm_db
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import time
|
|||
|
||||
from heatclient import exc as heatException
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from six import iteritems
|
||||
from toscaparser.tosca_template import ToscaTemplate
|
||||
from toscaparser.utils import yamlparser
|
||||
|
@ -29,7 +30,6 @@ from tacker.common import clients
|
|||
from tacker.common import log
|
||||
from tacker.extensions import vnfm
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.infra_drivers import abstract_driver
|
||||
from tacker.vm.tosca import utils as toscautils
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
# TODO(yamahata): once unittests are impletemted, move this there
|
||||
import uuid
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.common import log
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.infra_drivers import abstract_driver
|
||||
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@ from keystoneclient import auth as ks_auth
|
|||
from keystoneclient.auth.identity import v2 as v2_auth
|
||||
from keystoneclient import session as ks_session
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from six import iteritems
|
||||
|
||||
from tacker.api.v1 import attributes
|
||||
from tacker.i18n import _LE, _LW
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import versionutils
|
||||
from tacker.vm.infra_drivers import abstract_driver
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ from keystoneclient import client
|
|||
from keystoneclient import exceptions
|
||||
from keystoneclient import session
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tacker.openstack.common import log as logging
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.vm.mgmt_drivers import abstract_driver
|
||||
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import yaml
|
||||
|
||||
from tacker.agent.linux import utils
|
||||
from tacker.common import log
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.mgmt_drivers import abstract_driver
|
||||
from tacker.vm.mgmt_drivers import constants as mgmt_constants
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import threading
|
|||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
|
||||
|
@ -27,7 +28,6 @@ from tacker.common import clients
|
|||
from tacker.common import driver_manager
|
||||
from tacker import context as t_context
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.infra_drivers.heat import heat
|
||||
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
#
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import six.moves.urllib.error as urlerr
|
||||
import six.moves.urllib.request as urlreq
|
||||
|
||||
from tacker.common import log
|
||||
from tacker.i18n import _LW
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.monitor_drivers import abstract_driver
|
||||
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
#
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.agent.linux import utils as linux_utils
|
||||
from tacker.common import log
|
||||
from tacker.i18n import _LW
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.vm.monitor_drivers import abstract_driver
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import six
|
|||
|
||||
import eventlet
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.api.v1 import attributes
|
||||
from tacker.common import driver_manager
|
||||
|
@ -27,7 +28,6 @@ from tacker.db.vm import vm_db
|
|||
from tacker.extensions import vnfm
|
||||
from tacker.i18n import _LE
|
||||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
from tacker.vm.mgmt_drivers import constants as mgmt_constants
|
||||
from tacker.vm import monitor
|
||||
|
|
|
@ -16,15 +16,15 @@ import re
|
|||
import sys
|
||||
import yaml
|
||||
|
||||
from tacker.common import log
|
||||
from tacker.common import utils
|
||||
from tacker.extensions import vnfm
|
||||
from tacker.openstack.common import log as logging
|
||||
|
||||
from oslo_log import log as logging
|
||||
from six import iteritems
|
||||
from toscaparser.properties import Property
|
||||
from toscaparser.utils import yamlparser
|
||||
|
||||
from tacker.common import log
|
||||
from tacker.common import utils
|
||||
from tacker.extensions import vnfm
|
||||
|
||||
|
||||
FAILURE = 'tosca.policies.tacker.Failure'
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -17,10 +17,10 @@ import os
|
|||
|
||||
from cryptography.fernet import Fernet
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.extensions import nfvo
|
||||
from tacker import manager
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.plugins.common import constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -30,6 +30,7 @@ from xml.parsers import expat
|
|||
import eventlet.wsgi
|
||||
# eventlet.patcher.monkey_patch(all=False, socket=True, thread=True)
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import routes.middleware
|
||||
import six
|
||||
import webob.dec
|
||||
|
@ -42,7 +43,6 @@ from tacker.db import api
|
|||
from tacker.openstack.common import excutils
|
||||
from tacker.openstack.common import gettextutils
|
||||
from tacker.openstack.common import jsonutils
|
||||
from tacker.openstack.common import log as logging
|
||||
from tacker.openstack.common import service as common_service
|
||||
from tacker.openstack.common import systemd
|
||||
|
||||
|
@ -247,7 +247,7 @@ class Server(object):
|
|||
def _run(self, application, socket):
|
||||
"""Start a WSGI server in a new green thread."""
|
||||
eventlet.wsgi.server(socket, application, custom_pool=self.pool,
|
||||
log=logging.WritableLogger(LOG))
|
||||
log=LOG)
|
||||
|
||||
|
||||
class Middleware(object):
|
||||
|
|
4
tox.ini
4
tox.ini
|
@ -19,7 +19,7 @@ deps = -r{toxinidir}/requirements.txt
|
|||
-r{toxinidir}/test-requirements.txt
|
||||
setuptools-git>=0.4
|
||||
commands =
|
||||
python -m tacker.openstack.common.lockutils python setup.py testr --slowest --testr-args='{posargs}'
|
||||
{toxinidir}/tools/ostestr_compat_shim.sh {posargs}
|
||||
|
||||
[testenv:functional]
|
||||
setenv = OS_TEST_PATH=./tacker/tests/functional
|
||||
|
@ -28,7 +28,7 @@ deps =
|
|||
|
||||
[testenv:dsvm-functional]
|
||||
basepython = python2.7
|
||||
setenv = {[testenv]setenv}
|
||||
setenv = {[testenv]setenv}
|
||||
{[testenv:functional]setenv}
|
||||
deps =
|
||||
{[testenv:functional]deps}
|
||||
|
|
Loading…
Reference in New Issue