Merge "Sync with oslo-incubator"
This commit is contained in:
commit
2495849456
|
@ -19,6 +19,7 @@ from __future__ import print_function
|
|||
import copy
|
||||
import errno
|
||||
import gc
|
||||
import logging
|
||||
import os
|
||||
import pprint
|
||||
import socket
|
||||
|
@ -30,7 +31,6 @@ import greenlet
|
|||
from oslo_config import cfg
|
||||
|
||||
from nova.openstack.common._i18n import _LI
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
help_for_backdoor_port = (
|
||||
"Acceptable values are 0, <port>, and <start>:<end>, where 0 results "
|
||||
|
|
|
@ -17,6 +17,7 @@ import contextlib
|
|||
import errno
|
||||
import logging
|
||||
import os
|
||||
import stat
|
||||
import tempfile
|
||||
|
||||
from oslo_utils import excutils
|
||||
|
@ -24,15 +25,17 @@ from oslo_utils import excutils
|
|||
LOG = logging.getLogger(__name__)
|
||||
|
||||
_FILE_CACHE = {}
|
||||
DEFAULT_MODE = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO
|
||||
|
||||
|
||||
def ensure_tree(path):
|
||||
def ensure_tree(path, mode=DEFAULT_MODE):
|
||||
"""Create a directory (and any ancestor directories required)
|
||||
|
||||
:param path: Directory to create
|
||||
:param mode: Directory creation permissions
|
||||
"""
|
||||
try:
|
||||
os.makedirs(path)
|
||||
os.makedirs(path, mode)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
if not os.path.isdir(path):
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
@ -22,7 +23,6 @@ from eventlet import event
|
|||
from eventlet import greenthread
|
||||
|
||||
from nova.openstack.common._i18n import _LE, _LW
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# under the License.
|
||||
|
||||
import copy
|
||||
import logging
|
||||
import random
|
||||
import time
|
||||
|
||||
|
@ -19,7 +20,6 @@ from oslo_config import cfg
|
|||
import six
|
||||
|
||||
from nova.openstack.common._i18n import _, _LE, _LI
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
periodic_opts = [
|
||||
|
@ -55,14 +55,15 @@ def periodic_task(*args, **kwargs):
|
|||
interval of 60 seconds.
|
||||
|
||||
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
|
||||
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
|
||||
task will be shortly after task scheduler starts. If
|
||||
run_immediately is omitted or set to 'False', the first time the
|
||||
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):
|
||||
# Test for old style invocation
|
||||
|
@ -76,6 +77,7 @@ def periodic_task(*args, **kwargs):
|
|||
f._periodic_enabled = False
|
||||
else:
|
||||
f._periodic_enabled = kwargs.pop('enabled', True)
|
||||
f._periodic_name = kwargs.pop('name', f.__name__)
|
||||
|
||||
# Control frequency
|
||||
f._periodic_spacing = kwargs.pop('spacing', 0)
|
||||
|
@ -105,6 +107,36 @@ def periodic_task(*args, **kwargs):
|
|||
|
||||
|
||||
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_):
|
||||
"""Metaclass that allows us to collect decorated periodic tasks."""
|
||||
super(_PeriodicTasksMeta, cls).__init__(names, bases, dict_)
|
||||
|
@ -125,28 +157,7 @@ class _PeriodicTasksMeta(type):
|
|||
|
||||
for value in cls.__dict__.values():
|
||||
if getattr(value, '_periodic_task', False):
|
||||
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
|
||||
cls._add_periodic_task(value)
|
||||
|
||||
|
||||
def _nearest_boundary(last_run, spacing):
|
||||
|
@ -178,6 +189,15 @@ class PeriodicTasks(object):
|
|||
for name, task in self._periodic_tasks:
|
||||
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):
|
||||
"""Tasks to be run at a periodic interval."""
|
||||
idle_for = DEFAULT_INTERVAL
|
||||
|
|
|
@ -91,6 +91,7 @@ as it allows particular rules to be explicitly disabled.
|
|||
import abc
|
||||
import ast
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
|
@ -102,7 +103,6 @@ import six.moves.urllib.request as urlrequest
|
|||
|
||||
from nova.openstack.common import fileutils
|
||||
from nova.openstack.common._i18n import _, _LE, _LI
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
policy_opts = [
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2014 Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Provides process-data generators
|
||||
|
||||
This modules defines a class for generating
|
||||
process data by way of the psutil package.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import psutil
|
||||
|
||||
from nova.openstack.common.report.models import process as pm
|
||||
|
||||
|
||||
class ProcessReportGenerator(object):
|
||||
"""A Process Data Generator
|
||||
|
||||
This generator returns a
|
||||
:class:`openstack.common.report.models.process.ProcessModel`
|
||||
based on the current process (which will also include
|
||||
all subprocesses, recursively) using the :class:`psutil.Process` class`.
|
||||
"""
|
||||
|
||||
def __call__(self):
|
||||
return pm.ProcessModel(psutil.Process(os.getpid()))
|
|
@ -59,6 +59,7 @@ import sys
|
|||
from oslo_utils import timeutils
|
||||
|
||||
from nova.openstack.common.report.generators import conf as cgen
|
||||
from nova.openstack.common.report.generators import process as prgen
|
||||
from nova.openstack.common.report.generators import threading as tgen
|
||||
from nova.openstack.common.report.generators import version as pgen
|
||||
from nova.openstack.common.report import report
|
||||
|
@ -179,6 +180,9 @@ class GuruMeditation(object):
|
|||
self.add_section('Green Threads',
|
||||
tgen.GreenThreadReportGenerator())
|
||||
|
||||
self.add_section('Processes',
|
||||
prgen.ProcessReportGenerator())
|
||||
|
||||
self.add_section('Configuration',
|
||||
cgen.ConfigReportGenerator())
|
||||
|
||||
|
@ -208,6 +212,8 @@ class TextGuruMeditation(GuruMeditation, report.TextReport):
|
|||
|
||||
- Green Threads List
|
||||
|
||||
- Process List
|
||||
|
||||
- Configuration Options
|
||||
|
||||
:param version_obj: the version object for the current product
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright 2014 Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Provides a process model
|
||||
|
||||
This module defines a class representing a process,
|
||||
potentially with subprocesses.
|
||||
"""
|
||||
|
||||
import nova.openstack.common.report.models.with_default_views as mwdv
|
||||
import nova.openstack.common.report.views.text.process as text_views
|
||||
|
||||
|
||||
class ProcessModel(mwdv.ModelWithDefaultViews):
|
||||
"""A Process Model
|
||||
|
||||
This model holds data about a process,
|
||||
including references to any subprocesses
|
||||
|
||||
:param process: a :class:`psutil.Process` object
|
||||
"""
|
||||
|
||||
def __init__(self, process):
|
||||
super(ProcessModel, self).__init__(
|
||||
text_view=text_views.ProcessView())
|
||||
|
||||
self['pid'] = process.pid
|
||||
self['parent_pid'] = process.ppid
|
||||
if hasattr(process, 'uids'):
|
||||
self['uids'] = {'real': process.uids.real,
|
||||
'effective': process.uids.effective,
|
||||
'saved': process.uids.saved}
|
||||
else:
|
||||
self['uids'] = {'real': None,
|
||||
'effective': None,
|
||||
'saved': None}
|
||||
|
||||
if hasattr(process, 'gids'):
|
||||
self['gids'] = {'real': process.gids.real,
|
||||
'effective': process.gids.effective,
|
||||
'saved': process.gids.saved}
|
||||
else:
|
||||
self['gids'] = {'real': None,
|
||||
'effective': None,
|
||||
'saved': None}
|
||||
|
||||
self['username'] = process.username
|
||||
self['command'] = process.cmdline
|
||||
self['state'] = process.status
|
||||
|
||||
self['children'] = [ProcessModel(pr) for pr in process.get_children()]
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2014 Red Hat, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Provides process view
|
||||
|
||||
This module provides a view for
|
||||
visualizing processes in human-readable formm
|
||||
"""
|
||||
|
||||
import nova.openstack.common.report.views.jinja_view as jv
|
||||
|
||||
|
||||
class ProcessView(jv.JinjaView):
|
||||
"""A Process View
|
||||
|
||||
This view displays process models defined by
|
||||
:class:`openstack.common.report.models.process.ProcessModel`
|
||||
"""
|
||||
|
||||
VIEW_TEXT = (
|
||||
"Process {{ pid }} (under {{ parent_pid }}) "
|
||||
"[ run by: {{ username }} ({{ uids.real|default('unknown uid') }}),"
|
||||
" state: {{ state }} ]\n"
|
||||
"{% for child in children %}"
|
||||
" {{ child }}"
|
||||
"{% endfor %}"
|
||||
)
|
|
@ -18,7 +18,7 @@
|
|||
"""Generic Node base class for all workers that run on hosts."""
|
||||
|
||||
import errno
|
||||
import logging as std_logging
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import signal
|
||||
|
@ -39,7 +39,6 @@ from oslo_config import cfg
|
|||
|
||||
from nova.openstack.common import eventlet_backdoor
|
||||
from nova.openstack.common._i18n import _LE, _LI, _LW
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.openstack.common import systemd
|
||||
from nova.openstack.common import threadgroup
|
||||
|
||||
|
@ -163,7 +162,7 @@ class ServiceLauncher(Launcher):
|
|||
signo = 0
|
||||
|
||||
LOG.debug('Full set of CONF:')
|
||||
CONF.log_opt_values(LOG, std_logging.DEBUG)
|
||||
CONF.log_opt_values(LOG, logging.DEBUG)
|
||||
|
||||
try:
|
||||
if ready_callback:
|
||||
|
@ -377,7 +376,7 @@ class ProcessLauncher(object):
|
|||
|
||||
systemd.notify_once()
|
||||
LOG.debug('Full set of CONF:')
|
||||
CONF.log_opt_values(LOG, std_logging.DEBUG)
|
||||
CONF.log_opt_values(LOG, logging.DEBUG)
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
|
|
@ -16,12 +16,11 @@
|
|||
Helper module for systemd service readiness notification.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import logging
|
||||
import threading
|
||||
|
||||
import eventlet
|
||||
from eventlet import greenpool
|
||||
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.openstack.common import loopingcall
|
||||
|
||||
|
||||
|
|
|
@ -19,15 +19,24 @@ Helpers for comparing version strings.
|
|||
|
||||
import functools
|
||||
import inspect
|
||||
import logging
|
||||
|
||||
from oslo.config import cfg
|
||||
import pkg_resources
|
||||
import six
|
||||
|
||||
from nova.openstack.common._i18n import _
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
opts = [
|
||||
cfg.BoolOpt('fatal_deprecations',
|
||||
default=False,
|
||||
help='Enables or disables fatal status of deprecations.'),
|
||||
]
|
||||
|
||||
|
||||
class deprecated(object):
|
||||
|
@ -127,7 +136,7 @@ class deprecated(object):
|
|||
|
||||
@six.wraps(func_or_cls)
|
||||
def wrapped(*args, **kwargs):
|
||||
LOG.deprecated(msg, details)
|
||||
report_deprecated_feature(LOG, msg, details)
|
||||
return func_or_cls(*args, **kwargs)
|
||||
return wrapped
|
||||
elif inspect.isclass(func_or_cls):
|
||||
|
@ -139,7 +148,7 @@ class deprecated(object):
|
|||
# and added to the oslo-incubator requrements
|
||||
@functools.wraps(orig_init, assigned=('__name__', '__doc__'))
|
||||
def new_init(self, *args, **kwargs):
|
||||
LOG.deprecated(msg, details)
|
||||
report_deprecated_feature(LOG, msg, details)
|
||||
orig_init(self, *args, **kwargs)
|
||||
func_or_cls.__init__ = new_init
|
||||
return func_or_cls
|
||||
|
@ -201,3 +210,44 @@ def is_compatible(requested_version, current_version, same_major=True):
|
|||
return False
|
||||
|
||||
return current_parts >= requested_parts
|
||||
|
||||
|
||||
# Track the messages we have sent already. See
|
||||
# report_deprecated_feature().
|
||||
_deprecated_messages_sent = {}
|
||||
|
||||
|
||||
def report_deprecated_feature(logger, msg, *args, **kwargs):
|
||||
"""Call this function when a deprecated feature is used.
|
||||
|
||||
If the system is configured for fatal deprecations then the message
|
||||
is logged at the 'critical' level and :class:`DeprecatedConfig` will
|
||||
be raised.
|
||||
|
||||
Otherwise, the message will be logged (once) at the 'warn' level.
|
||||
|
||||
:raises: :class:`DeprecatedConfig` if the system is configured for
|
||||
fatal deprecations.
|
||||
"""
|
||||
stdmsg = _("Deprecated: %s") % msg
|
||||
CONF.register_opts(opts)
|
||||
if CONF.fatal_deprecations:
|
||||
logger.critical(stdmsg, *args, **kwargs)
|
||||
raise DeprecatedConfig(msg=stdmsg)
|
||||
|
||||
# Using a list because a tuple with dict can't be stored in a set.
|
||||
sent_args = _deprecated_messages_sent.setdefault(msg, list())
|
||||
|
||||
if args in sent_args:
|
||||
# Already logged this message, so don't log it again.
|
||||
return
|
||||
|
||||
sent_args.append(args)
|
||||
logger.warn(stdmsg, *args, **kwargs)
|
||||
|
||||
|
||||
class DeprecatedConfig(Exception):
|
||||
message = _("Fatal call to deprecated config: %(msg)s")
|
||||
|
||||
def __init__(self, msg):
|
||||
super(Exception, self).__init__(self.message % dict(msg=msg))
|
||||
|
|
|
@ -41,3 +41,4 @@ oslo.i18n>=1.3.0 # Apache-2.0
|
|||
rfc3986>=0.2.0 # Apache-2.0
|
||||
oslo.vmware>=0.9.0 # Apache-2.0
|
||||
oslo.middleware>=0.3.0 # Apache-2.0
|
||||
psutil>=1.1.1,<2.0.0
|
||||
|
|
Loading…
Reference in New Issue