Sync with latest oslo-incubator
Changes are as follows: f29e865 3/17/15 Store ProcessLauncher signal handlers on class level bf92010 2/19/15 Optimization of waiting subprocesses in ProcessLauncher 2aacb11 1/29/15 Change oslo.config to oslo_config 2fbf506 1/29/15 Remove oslo.log code and clean up versionutils API 0cc741a 1/26/15 switch to oslo_i18n fbd77a7 1/21/15 Allow overriding name for periodic tasks 9896e0e 1/21/15 Separate add_periodic_task from the metaclass __init__ 80c4751 1/5/15 Remove unnecessary import of eventlet 442fc22 12/30/14 Added graceful argument on Service.stop method cf429e5 12/28/14 Remove extra white space in log message 5985b35 12/11/14 Prefer delayed %r formatting over explicit repr use Closes-bug: #1434744 Change-Id: Icf0b52170b3457d570fd87fd2875a1e759b97579
This commit is contained in:
parent
fe80331cef
commit
0789d70056
@ -17,14 +17,14 @@ See http://docs.openstack.org/developer/oslo.i18n/usage.html
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import oslo.i18n
|
import oslo_i18n
|
||||||
|
|
||||||
# NOTE(dhellmann): This reference to o-s-l-o will be replaced by the
|
# NOTE(dhellmann): This reference to o-s-l-o will be replaced by the
|
||||||
# application name when this module is synced into the separate
|
# application name when this module is synced into the separate
|
||||||
# repository. It is OK to have more than one translation function
|
# repository. It is OK to have more than one translation function
|
||||||
# using the same domain, since there will still only be one message
|
# using the same domain, since there will still only be one message
|
||||||
# catalog.
|
# catalog.
|
||||||
_translators = oslo.i18n.TranslatorFactory(domain='magnum')
|
_translators = oslo_i18n.TranslatorFactory(domain='magnum')
|
||||||
|
|
||||||
# The primary translation function using the well-known name "_"
|
# The primary translation function using the well-known name "_"
|
||||||
_ = _translators.primary
|
_ = _translators.primary
|
||||||
@ -40,6 +40,6 @@ try:
|
|||||||
_LC = _translators.log_critical
|
_LC = _translators.log_critical
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# NOTE(dims): Support for cases where a project wants to use
|
# NOTE(dims): Support for cases where a project wants to use
|
||||||
# code from magnum-incubator, but is not ready to be internationalized
|
# code from oslo-incubator, but is not ready to be internationalized
|
||||||
# (like tempest)
|
# (like tempest)
|
||||||
_ = _LI = _LW = _LE = _LC = lambda x: x
|
_ = _LI = _LW = _LE = _LC = lambda x: x
|
||||||
|
@ -19,19 +19,18 @@ from __future__ import print_function
|
|||||||
import copy
|
import copy
|
||||||
import errno
|
import errno
|
||||||
import gc
|
import gc
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import pprint
|
import pprint
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import eventlet
|
|
||||||
import eventlet.backdoor
|
import eventlet.backdoor
|
||||||
import greenlet
|
import greenlet
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from magnum.openstack.common._i18n import _LI
|
from magnum.openstack.common._i18n import _LI
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
|
|
||||||
help_for_backdoor_port = (
|
help_for_backdoor_port = (
|
||||||
"Acceptable values are 0, <port>, and <start>:<end>, where 0 results "
|
"Acceptable values are 0, <port>, and <start>:<end>, where 0 results "
|
||||||
@ -51,7 +50,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def list_opts():
|
def list_opts():
|
||||||
"""Entry point for oslo.config-generator.
|
"""Entry point for oslo-config-generator.
|
||||||
"""
|
"""
|
||||||
return [(None, copy.deepcopy(eventlet_backdoor_opts))]
|
return [(None, copy.deepcopy(eventlet_backdoor_opts))]
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -22,7 +23,6 @@ from eventlet import event
|
|||||||
from eventlet import greenthread
|
from eventlet import greenthread
|
||||||
|
|
||||||
from magnum.openstack.common._i18n import _LE, _LW
|
from magnum.openstack.common._i18n import _LE, _LW
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -84,9 +84,9 @@ class FixedIntervalLoopingCall(LoopingCallBase):
|
|||||||
break
|
break
|
||||||
delay = end - start - interval
|
delay = end - start - interval
|
||||||
if delay > 0:
|
if delay > 0:
|
||||||
LOG.warn(_LW('task %(func_name)s run outlasted '
|
LOG.warn(_LW('task %(func_name)r run outlasted '
|
||||||
'interval by %(delay).2f sec'),
|
'interval by %(delay).2f sec'),
|
||||||
{'func_name': repr(self.f), 'delay': delay})
|
{'func_name': self.f, 'delay': delay})
|
||||||
greenthread.sleep(-delay if delay < 0 else 0)
|
greenthread.sleep(-delay if delay < 0 else 0)
|
||||||
except LoopingCallDone as e:
|
except LoopingCallDone as e:
|
||||||
self.stop()
|
self.stop()
|
||||||
@ -127,9 +127,9 @@ class DynamicLoopingCall(LoopingCallBase):
|
|||||||
|
|
||||||
if periodic_interval_max is not None:
|
if periodic_interval_max is not None:
|
||||||
idle = min(idle, periodic_interval_max)
|
idle = min(idle, periodic_interval_max)
|
||||||
LOG.debug('Dynamic looping call %(func_name)s sleeping '
|
LOG.debug('Dynamic looping call %(func_name)r sleeping '
|
||||||
'for %(idle).02f seconds',
|
'for %(idle).02f seconds',
|
||||||
{'func_name': repr(self.f), 'idle': idle})
|
{'func_name': self.f, 'idle': idle})
|
||||||
greenthread.sleep(idle)
|
greenthread.sleep(idle)
|
||||||
except LoopingCallDone as e:
|
except LoopingCallDone as e:
|
||||||
self.stop()
|
self.stop()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import logging
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -19,7 +20,6 @@ from oslo_config import cfg
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from magnum.openstack.common._i18n import _, _LE, _LI
|
from magnum.openstack.common._i18n import _, _LE, _LI
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
periodic_opts = [
|
periodic_opts = [
|
||||||
@ -38,7 +38,7 @@ DEFAULT_INTERVAL = 60.0
|
|||||||
|
|
||||||
|
|
||||||
def list_opts():
|
def list_opts():
|
||||||
"""Entry point for oslo.config-generator."""
|
"""Entry point for oslo-config-generator."""
|
||||||
return [(None, copy.deepcopy(periodic_opts))]
|
return [(None, copy.deepcopy(periodic_opts))]
|
||||||
|
|
||||||
|
|
||||||
@ -55,14 +55,15 @@ def periodic_task(*args, **kwargs):
|
|||||||
interval of 60 seconds.
|
interval of 60 seconds.
|
||||||
|
|
||||||
2. With arguments:
|
2. With arguments:
|
||||||
@periodic_task(spacing=N [, run_immediately=[True|False]])
|
@periodic_task(spacing=N [, run_immediately=[True|False]]
|
||||||
|
[, name=[None|"string"])
|
||||||
this will be run on approximately every N seconds. If this number is
|
this will be run on approximately every N seconds. If this number is
|
||||||
negative the periodic task will be disabled. If the run_immediately
|
negative the periodic task will be disabled. If the run_immediately
|
||||||
argument is provided and has a value of 'True', the first run of the
|
argument is provided and has a value of 'True', the first run of the
|
||||||
task will be shortly after task scheduler starts. If
|
task will be shortly after task scheduler starts. If
|
||||||
run_immediately is omitted or set to 'False', the first time the
|
run_immediately is omitted or set to 'False', the first time the
|
||||||
task runs will be approximately N seconds after the task scheduler
|
task runs will be approximately N seconds after the task scheduler
|
||||||
starts.
|
starts. If name is not provided, __name__ of function is used.
|
||||||
"""
|
"""
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
# Test for old style invocation
|
# Test for old style invocation
|
||||||
@ -76,6 +77,7 @@ def periodic_task(*args, **kwargs):
|
|||||||
f._periodic_enabled = False
|
f._periodic_enabled = False
|
||||||
else:
|
else:
|
||||||
f._periodic_enabled = kwargs.pop('enabled', True)
|
f._periodic_enabled = kwargs.pop('enabled', True)
|
||||||
|
f._periodic_name = kwargs.pop('name', f.__name__)
|
||||||
|
|
||||||
# Control frequency
|
# Control frequency
|
||||||
f._periodic_spacing = kwargs.pop('spacing', 0)
|
f._periodic_spacing = kwargs.pop('spacing', 0)
|
||||||
@ -105,6 +107,36 @@ def periodic_task(*args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
class _PeriodicTasksMeta(type):
|
class _PeriodicTasksMeta(type):
|
||||||
|
def _add_periodic_task(cls, task):
|
||||||
|
"""Add a periodic task to the list of periodic tasks.
|
||||||
|
|
||||||
|
The task should already be decorated by @periodic_task.
|
||||||
|
|
||||||
|
:return: whether task was actually enabled
|
||||||
|
"""
|
||||||
|
name = task._periodic_name
|
||||||
|
|
||||||
|
if task._periodic_spacing < 0:
|
||||||
|
LOG.info(_LI('Skipping periodic task %(task)s because '
|
||||||
|
'its interval is negative'),
|
||||||
|
{'task': name})
|
||||||
|
return False
|
||||||
|
if not task._periodic_enabled:
|
||||||
|
LOG.info(_LI('Skipping periodic task %(task)s because '
|
||||||
|
'it is disabled'),
|
||||||
|
{'task': name})
|
||||||
|
return False
|
||||||
|
|
||||||
|
# A periodic spacing of zero indicates that this task should
|
||||||
|
# be run on the default interval to avoid running too
|
||||||
|
# frequently.
|
||||||
|
if task._periodic_spacing == 0:
|
||||||
|
task._periodic_spacing = DEFAULT_INTERVAL
|
||||||
|
|
||||||
|
cls._periodic_tasks.append((name, task))
|
||||||
|
cls._periodic_spacing[name] = task._periodic_spacing
|
||||||
|
return True
|
||||||
|
|
||||||
def __init__(cls, names, bases, dict_):
|
def __init__(cls, names, bases, dict_):
|
||||||
"""Metaclass that allows us to collect decorated periodic tasks."""
|
"""Metaclass that allows us to collect decorated periodic tasks."""
|
||||||
super(_PeriodicTasksMeta, cls).__init__(names, bases, dict_)
|
super(_PeriodicTasksMeta, cls).__init__(names, bases, dict_)
|
||||||
@ -125,28 +157,7 @@ class _PeriodicTasksMeta(type):
|
|||||||
|
|
||||||
for value in cls.__dict__.values():
|
for value in cls.__dict__.values():
|
||||||
if getattr(value, '_periodic_task', False):
|
if getattr(value, '_periodic_task', False):
|
||||||
task = value
|
cls._add_periodic_task(value)
|
||||||
name = task.__name__
|
|
||||||
|
|
||||||
if task._periodic_spacing < 0:
|
|
||||||
LOG.info(_LI('Skipping periodic task %(task)s because '
|
|
||||||
'its interval is negative'),
|
|
||||||
{'task': name})
|
|
||||||
continue
|
|
||||||
if not task._periodic_enabled:
|
|
||||||
LOG.info(_LI('Skipping periodic task %(task)s because '
|
|
||||||
'it is disabled'),
|
|
||||||
{'task': name})
|
|
||||||
continue
|
|
||||||
|
|
||||||
# A periodic spacing of zero indicates that this task should
|
|
||||||
# be run on the default interval to avoid running too
|
|
||||||
# frequently.
|
|
||||||
if task._periodic_spacing == 0:
|
|
||||||
task._periodic_spacing = DEFAULT_INTERVAL
|
|
||||||
|
|
||||||
cls._periodic_tasks.append((name, task))
|
|
||||||
cls._periodic_spacing[name] = task._periodic_spacing
|
|
||||||
|
|
||||||
|
|
||||||
def _nearest_boundary(last_run, spacing):
|
def _nearest_boundary(last_run, spacing):
|
||||||
@ -178,6 +189,15 @@ class PeriodicTasks(object):
|
|||||||
for name, task in self._periodic_tasks:
|
for name, task in self._periodic_tasks:
|
||||||
self._periodic_last_run[name] = task._periodic_last_run
|
self._periodic_last_run[name] = task._periodic_last_run
|
||||||
|
|
||||||
|
def add_periodic_task(self, task):
|
||||||
|
"""Add a periodic task to the list of periodic tasks.
|
||||||
|
|
||||||
|
The task should already be decorated by @periodic_task.
|
||||||
|
"""
|
||||||
|
if self.__class__._add_periodic_task(task):
|
||||||
|
self._periodic_last_run[task._periodic_name] = (
|
||||||
|
task._periodic_last_run)
|
||||||
|
|
||||||
def run_periodic_tasks(self, context, raise_on_error=False):
|
def run_periodic_tasks(self, context, raise_on_error=False):
|
||||||
"""Tasks to be run at a periodic interval."""
|
"""Tasks to be run at a periodic interval."""
|
||||||
idle_for = DEFAULT_INTERVAL
|
idle_for = DEFAULT_INTERVAL
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"""Generic Node base class for all workers that run on hosts."""
|
"""Generic Node base class for all workers that run on hosts."""
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
import logging as std_logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import signal
|
import signal
|
||||||
@ -39,7 +39,6 @@ from oslo_config import cfg
|
|||||||
|
|
||||||
from magnum.openstack.common import eventlet_backdoor
|
from magnum.openstack.common import eventlet_backdoor
|
||||||
from magnum.openstack.common._i18n import _LE, _LI, _LW
|
from magnum.openstack.common._i18n import _LE, _LI, _LW
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
from magnum.openstack.common import systemd
|
from magnum.openstack.common import systemd
|
||||||
from magnum.openstack.common import threadgroup
|
from magnum.openstack.common import threadgroup
|
||||||
|
|
||||||
@ -163,7 +162,7 @@ class ServiceLauncher(Launcher):
|
|||||||
signo = 0
|
signo = 0
|
||||||
|
|
||||||
LOG.debug('Full set of CONF:')
|
LOG.debug('Full set of CONF:')
|
||||||
CONF.log_opt_values(LOG, std_logging.DEBUG)
|
CONF.log_opt_values(LOG, logging.DEBUG)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if ready_callback:
|
if ready_callback:
|
||||||
@ -200,22 +199,26 @@ class ServiceWrapper(object):
|
|||||||
|
|
||||||
|
|
||||||
class ProcessLauncher(object):
|
class ProcessLauncher(object):
|
||||||
def __init__(self, wait_interval=0.01):
|
_signal_handlers_set = set()
|
||||||
"""Constructor.
|
|
||||||
|
@classmethod
|
||||||
|
def _handle_class_signals(cls, *args, **kwargs):
|
||||||
|
for handler in cls._signal_handlers_set:
|
||||||
|
handler(*args, **kwargs)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Constructor."""
|
||||||
|
|
||||||
:param wait_interval: The interval to sleep for between checks
|
|
||||||
of child process exit.
|
|
||||||
"""
|
|
||||||
self.children = {}
|
self.children = {}
|
||||||
self.sigcaught = None
|
self.sigcaught = None
|
||||||
self.running = True
|
self.running = True
|
||||||
self.wait_interval = wait_interval
|
|
||||||
rfd, self.writepipe = os.pipe()
|
rfd, self.writepipe = os.pipe()
|
||||||
self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
|
self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
|
||||||
self.handle_signal()
|
self.handle_signal()
|
||||||
|
|
||||||
def handle_signal(self):
|
def handle_signal(self):
|
||||||
_set_signals_handler(self._handle_signal)
|
self._signal_handlers_set.add(self._handle_signal)
|
||||||
|
_set_signals_handler(self._handle_class_signals)
|
||||||
|
|
||||||
def _handle_signal(self, signo, frame):
|
def _handle_signal(self, signo, frame):
|
||||||
self.sigcaught = signo
|
self.sigcaught = signo
|
||||||
@ -334,8 +337,8 @@ class ProcessLauncher(object):
|
|||||||
|
|
||||||
def _wait_child(self):
|
def _wait_child(self):
|
||||||
try:
|
try:
|
||||||
# Don't block if no child processes have exited
|
# Block while any of child processes have exited
|
||||||
pid, status = os.waitpid(0, os.WNOHANG)
|
pid, status = os.waitpid(0, 0)
|
||||||
if not pid:
|
if not pid:
|
||||||
return None
|
return None
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
@ -364,10 +367,6 @@ class ProcessLauncher(object):
|
|||||||
while self.running:
|
while self.running:
|
||||||
wrap = self._wait_child()
|
wrap = self._wait_child()
|
||||||
if not wrap:
|
if not wrap:
|
||||||
# Yield to other threads if no children have exited
|
|
||||||
# Sleep for a short time to avoid excessive CPU usage
|
|
||||||
# (see bug #1095346)
|
|
||||||
eventlet.greenthread.sleep(self.wait_interval)
|
|
||||||
continue
|
continue
|
||||||
while self.running and len(wrap.children) < wrap.workers:
|
while self.running and len(wrap.children) < wrap.workers:
|
||||||
self._start_child(wrap)
|
self._start_child(wrap)
|
||||||
@ -377,7 +376,7 @@ class ProcessLauncher(object):
|
|||||||
|
|
||||||
systemd.notify_once()
|
systemd.notify_once()
|
||||||
LOG.debug('Full set of CONF:')
|
LOG.debug('Full set of CONF:')
|
||||||
CONF.log_opt_values(LOG, std_logging.DEBUG)
|
CONF.log_opt_values(LOG, logging.DEBUG)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
@ -397,7 +396,7 @@ class ProcessLauncher(object):
|
|||||||
self.running = True
|
self.running = True
|
||||||
self.sigcaught = None
|
self.sigcaught = None
|
||||||
except eventlet.greenlet.GreenletExit:
|
except eventlet.greenlet.GreenletExit:
|
||||||
LOG.info(_LI("Wait called after thread killed. Cleaning up."))
|
LOG.info(_LI("Wait called after thread killed. Cleaning up."))
|
||||||
|
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
@ -434,8 +433,8 @@ class Service(object):
|
|||||||
def start(self):
|
def start(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def stop(self):
|
def stop(self, graceful=False):
|
||||||
self.tg.stop()
|
self.tg.stop(graceful)
|
||||||
self.tg.wait()
|
self.tg.wait()
|
||||||
# Signal that service cleanup is done:
|
# Signal that service cleanup is done:
|
||||||
if not self._done.ready():
|
if not self._done.ready():
|
||||||
|
@ -16,12 +16,11 @@
|
|||||||
Helper module for systemd service readiness notification.
|
Helper module for systemd service readiness notification.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
from eventlet import greenpool
|
from eventlet import greenpool
|
||||||
|
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
from magnum.openstack.common import loopingcall
|
from magnum.openstack.common import loopingcall
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,17 +17,33 @@
|
|||||||
Helpers for comparing version strings.
|
Helpers for comparing version strings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import copy
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from magnum.openstack.common._i18n import _
|
from magnum.openstack.common._i18n import _
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
deprecated_opts = [
|
||||||
|
cfg.BoolOpt('fatal_deprecations',
|
||||||
|
default=False,
|
||||||
|
help='Enables or disables fatal status of deprecations.'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_opts():
|
||||||
|
"""Entry point for oslo.config-generator.
|
||||||
|
"""
|
||||||
|
return [(None, copy.deepcopy(deprecated_opts))]
|
||||||
|
|
||||||
|
|
||||||
class deprecated(object):
|
class deprecated(object):
|
||||||
@ -74,6 +90,7 @@ class deprecated(object):
|
|||||||
ICEHOUSE = 'I'
|
ICEHOUSE = 'I'
|
||||||
JUNO = 'J'
|
JUNO = 'J'
|
||||||
KILO = 'K'
|
KILO = 'K'
|
||||||
|
LIBERTY = 'L'
|
||||||
|
|
||||||
_RELEASES = {
|
_RELEASES = {
|
||||||
# NOTE(morganfainberg): Bexar is used for unit test purposes, it is
|
# NOTE(morganfainberg): Bexar is used for unit test purposes, it is
|
||||||
@ -85,6 +102,7 @@ class deprecated(object):
|
|||||||
'I': 'Icehouse',
|
'I': 'Icehouse',
|
||||||
'J': 'Juno',
|
'J': 'Juno',
|
||||||
'K': 'Kilo',
|
'K': 'Kilo',
|
||||||
|
'L': 'Liberty',
|
||||||
}
|
}
|
||||||
|
|
||||||
_deprecated_msg_with_alternative = _(
|
_deprecated_msg_with_alternative = _(
|
||||||
@ -127,7 +145,7 @@ class deprecated(object):
|
|||||||
|
|
||||||
@six.wraps(func_or_cls)
|
@six.wraps(func_or_cls)
|
||||||
def wrapped(*args, **kwargs):
|
def wrapped(*args, **kwargs):
|
||||||
LOG.deprecated(msg, details)
|
report_deprecated_feature(LOG, msg, details)
|
||||||
return func_or_cls(*args, **kwargs)
|
return func_or_cls(*args, **kwargs)
|
||||||
return wrapped
|
return wrapped
|
||||||
elif inspect.isclass(func_or_cls):
|
elif inspect.isclass(func_or_cls):
|
||||||
@ -136,10 +154,10 @@ class deprecated(object):
|
|||||||
# TODO(tsufiev): change `functools` module to `six` as
|
# TODO(tsufiev): change `functools` module to `six` as
|
||||||
# soon as six 1.7.4 (with fix for passing `assigned`
|
# soon as six 1.7.4 (with fix for passing `assigned`
|
||||||
# argument to underlying `functools.wraps`) is released
|
# argument to underlying `functools.wraps`) is released
|
||||||
# and added to the magnum-incubator requrements
|
# and added to the oslo-incubator requrements
|
||||||
@functools.wraps(orig_init, assigned=('__name__', '__doc__'))
|
@functools.wraps(orig_init, assigned=('__name__', '__doc__'))
|
||||||
def new_init(self, *args, **kwargs):
|
def new_init(self, *args, **kwargs):
|
||||||
LOG.deprecated(msg, details)
|
report_deprecated_feature(LOG, msg, details)
|
||||||
orig_init(self, *args, **kwargs)
|
orig_init(self, *args, **kwargs)
|
||||||
func_or_cls.__init__ = new_init
|
func_or_cls.__init__ = new_init
|
||||||
return func_or_cls
|
return func_or_cls
|
||||||
@ -201,3 +219,44 @@ def is_compatible(requested_version, current_version, same_major=True):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
return current_parts >= requested_parts
|
return current_parts >= requested_parts
|
||||||
|
|
||||||
|
|
||||||
|
# Track the messages we have sent already. See
|
||||||
|
# report_deprecated_feature().
|
||||||
|
_deprecated_messages_sent = {}
|
||||||
|
|
||||||
|
|
||||||
|
def report_deprecated_feature(logger, msg, *args, **kwargs):
|
||||||
|
"""Call this function when a deprecated feature is used.
|
||||||
|
|
||||||
|
If the system is configured for fatal deprecations then the message
|
||||||
|
is logged at the 'critical' level and :class:`DeprecatedConfig` will
|
||||||
|
be raised.
|
||||||
|
|
||||||
|
Otherwise, the message will be logged (once) at the 'warn' level.
|
||||||
|
|
||||||
|
:raises: :class:`DeprecatedConfig` if the system is configured for
|
||||||
|
fatal deprecations.
|
||||||
|
"""
|
||||||
|
stdmsg = _("Deprecated: %s") % msg
|
||||||
|
CONF.register_opts(deprecated_opts)
|
||||||
|
if CONF.fatal_deprecations:
|
||||||
|
logger.critical(stdmsg, *args, **kwargs)
|
||||||
|
raise DeprecatedConfig(msg=stdmsg)
|
||||||
|
|
||||||
|
# Using a list because a tuple with dict can't be stored in a set.
|
||||||
|
sent_args = _deprecated_messages_sent.setdefault(msg, list())
|
||||||
|
|
||||||
|
if args in sent_args:
|
||||||
|
# Already logged this message, so don't log it again.
|
||||||
|
return
|
||||||
|
|
||||||
|
sent_args.append(args)
|
||||||
|
logger.warn(stdmsg, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class DeprecatedConfig(Exception):
|
||||||
|
message = _("Fatal call to deprecated config: %(msg)s")
|
||||||
|
|
||||||
|
def __init__(self, msg):
|
||||||
|
super(Exception, self).__init__(self.message % dict(msg=msg))
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
# The list of modules to copy from oslo-incubator.git
|
# The list of modules to copy from oslo-incubator.git
|
||||||
module=eventlet_backdoor
|
module=eventlet_backdoor
|
||||||
module=log
|
|
||||||
module=loopingcall
|
module=loopingcall
|
||||||
module=periodic_task
|
module=periodic_task
|
||||||
module=service
|
module=service
|
||||||
|
Loading…
Reference in New Issue
Block a user