summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openstack/common/log.py18
-rw-r--r--openstack/common/log_handler.py31
-rw-r--r--openstack/common/periodic_task.py1
-rw-r--r--openstack/common/rootwrap/filters.py4
-rw-r--r--openstack/common/rpc/common.py4
-rw-r--r--openstack/common/rpc/proxy.py14
-rw-r--r--openstack/common/service.py3
-rw-r--r--openstack/common/threadgroup.py7
-rw-r--r--tests/unit/db/sqlalchemy/test_sqlalchemy.py2
-rw-r--r--tests/unit/rpc/common.py2
-rw-r--r--tests/unit/rpc/test_common.py2
-rw-r--r--tests/unit/rpc/test_kombu.py2
-rw-r--r--tests/unit/rpc/test_proxy.py8
-rw-r--r--tests/unit/rpc/test_qpid.py2
-rw-r--r--tests/unit/test_log.py3
-rw-r--r--tests/unit/test_rootwrap.py12
-rw-r--r--tests/unit/test_service.py10
-rw-r--r--tests/unit/test_setup.py2
-rw-r--r--tests/unit/test_threadgroup.py50
-rw-r--r--tests/utils.py2
20 files changed, 153 insertions, 26 deletions
diff --git a/openstack/common/log.py b/openstack/common/log.py
index d7ba467..d125d90 100644
--- a/openstack/common/log.py
+++ b/openstack/common/log.py
@@ -43,9 +43,9 @@ import traceback
from oslo.config import cfg
from openstack.common.gettextutils import _
+from openstack.common import importutils
from openstack.common import jsonutils
from openstack.common import local
-from openstack.common import notifier
_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
@@ -322,17 +322,6 @@ class JSONFormatter(logging.Formatter):
return jsonutils.dumps(message)
-class PublishErrorsHandler(logging.Handler):
- def emit(self, record):
- if ('openstack.common.notifier.log_notifier' in
- CONF.notification_driver):
- return
- notifier.api.notify(None, 'error.publisher',
- 'error_notification',
- notifier.api.ERROR,
- dict(error=record.msg))
-
-
def _create_logging_excepthook(product_name):
def logging_excepthook(type, value, tb):
extra = {}
@@ -428,7 +417,10 @@ def _setup_logging_from_conf():
log_root.addHandler(streamlog)
if CONF.publish_errors:
- log_root.addHandler(PublishErrorsHandler(logging.ERROR))
+ handler = importutils.import_object(
+ "openstack.common.log_handler.PublishErrorsHandler",
+ logging.ERROR)
+ log_root.addHandler(handler)
datefmt = CONF.log_date_format
for handler in log_root.handlers:
diff --git a/openstack/common/log_handler.py b/openstack/common/log_handler.py
new file mode 100644
index 0000000..1f90948
--- /dev/null
+++ b/openstack/common/log_handler.py
@@ -0,0 +1,31 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 openstack.common import notifier
+
+from oslo.config import cfg
+
+
+class PublishErrorsHandler(logging.Handler):
+ def emit(self, record):
+ if ('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.msg))
diff --git a/openstack/common/periodic_task.py b/openstack/common/periodic_task.py
index c48d8b9..4fbb0fe 100644
--- a/openstack/common/periodic_task.py
+++ b/openstack/common/periodic_task.py
@@ -15,6 +15,7 @@
import datetime
import time
+
from oslo.config import cfg
from openstack.common.gettextutils import _
diff --git a/openstack/common/rootwrap/filters.py b/openstack/common/rootwrap/filters.py
index 58121cb..ae7c62c 100644
--- a/openstack/common/rootwrap/filters.py
+++ b/openstack/common/rootwrap/filters.py
@@ -194,6 +194,10 @@ class KillFilter(CommandFilter):
return False
try:
command = os.readlink("/proc/%d/exe" % int(args[1]))
+ # NOTE(yufang521247): /proc/PID/exe may have '\0' on the
+ # end, because python doen't stop at '\0' when read the
+ # target path.
+ command = command.split('\0')[0]
# NOTE(dprince): /proc/PID/exe may have ' (deleted)' on
# the end if an executable is updated or deleted
if command.endswith(" (deleted)"):
diff --git a/openstack/common/rpc/common.py b/openstack/common/rpc/common.py
index d74425d..5a7e525 100644
--- a/openstack/common/rpc/common.py
+++ b/openstack/common/rpc/common.py
@@ -158,6 +158,10 @@ class UnsupportedRpcEnvelopeVersion(RPCException):
"not supported by this endpoint.")
+class RpcVersionCapError(RPCException):
+ message = _("Specified RPC version cap, %(version_cap)s, is too low")
+
+
class Connection(object):
"""A connection, returned by rpc.create_connection().
diff --git a/openstack/common/rpc/proxy.py b/openstack/common/rpc/proxy.py
index 284f375..0b311de 100644
--- a/openstack/common/rpc/proxy.py
+++ b/openstack/common/rpc/proxy.py
@@ -1,6 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2012 Red Hat, Inc.
+# Copyright 2012-2013 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
@@ -23,6 +23,7 @@ For more information about rpc API version numbers, see:
from openstack.common import rpc
+from openstack.common.rpc import common as rpc_common
class RpcProxy(object):
@@ -34,16 +35,19 @@ class RpcProxy(object):
rpc API.
"""
- def __init__(self, topic, default_version):
+ def __init__(self, topic, default_version, version_cap=None):
"""Initialize an RpcProxy.
:param topic: The topic to use for all messages.
:param default_version: The default API version to request in all
outgoing messages. This can be overridden on a per-message
basis.
+ :param version_cap: Optionally cap the maximum version used for sent
+ messages.
"""
self.topic = topic
self.default_version = default_version
+ self.version_cap = version_cap
super(RpcProxy, self).__init__()
def _set_version(self, msg, vers):
@@ -52,7 +56,11 @@ class RpcProxy(object):
:param msg: The message having a version added to it.
:param vers: The version number to add to the message.
"""
- msg['version'] = vers if vers else self.default_version
+ v = vers if vers else self.default_version
+ if (self.version_cap and not
+ rpc_common.version_is_compatible(self.version_cap, v)):
+ raise rpc_common.RpcVersionCapError(version=self.version_cap)
+ msg['version'] = v
def _get_topic(self, topic):
"""Return the topic to use for a message."""
diff --git a/openstack/common/service.py b/openstack/common/service.py
index 6ebeefd..eb46164 100644
--- a/openstack/common/service.py
+++ b/openstack/common/service.py
@@ -52,7 +52,7 @@ class Launcher(object):
"""
self._services = threadgroup.ThreadGroup()
- eventlet_backdoor.initialize_if_enabled()
+ self.backdoor_port = eventlet_backdoor.initialize_if_enabled()
@staticmethod
def run_service(service):
@@ -72,6 +72,7 @@ class Launcher(object):
:returns: None
"""
+ service.backdoor_port = self.backdoor_port
self._services.add_thread(self.run_service, service)
def stop(self):
diff --git a/openstack/common/threadgroup.py b/openstack/common/threadgroup.py
index 3558b73..6cafbaf 100644
--- a/openstack/common/threadgroup.py
+++ b/openstack/common/threadgroup.py
@@ -61,6 +61,13 @@ class ThreadGroup(object):
self.threads = []
self.timers = []
+ def add_dynamic_timer(self, callback, initial_delay=None,
+ periodic_interval_max=None, *args, **kwargs):
+ timer = loopingcall.DynamicLoopingCall(callback, *args, **kwargs)
+ timer.start(initial_delay=initial_delay,
+ periodic_interval_max=periodic_interval_max)
+ self.timers.append(timer)
+
def add_timer(self, interval, callback, initial_delay=None,
*args, **kwargs):
pulse = loopingcall.FixedIntervalLoopingCall(callback, *args, **kwargs)
diff --git a/tests/unit/db/sqlalchemy/test_sqlalchemy.py b/tests/unit/db/sqlalchemy/test_sqlalchemy.py
index efe0264..7cbe31d 100644
--- a/tests/unit/db/sqlalchemy/test_sqlalchemy.py
+++ b/tests/unit/db/sqlalchemy/test_sqlalchemy.py
@@ -19,8 +19,8 @@
"""Unit tests for SQLAlchemy specific code."""
from sqlalchemy import Column, MetaData, Table, UniqueConstraint
-from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import DateTime, Integer, String
+from sqlalchemy.ext.declarative import declarative_base
from openstack.common.db import exception as db_exc
from openstack.common.db.sqlalchemy import models
diff --git a/tests/unit/rpc/common.py b/tests/unit/rpc/common.py
index c4362b2..32f2a9b 100644
--- a/tests/unit/rpc/common.py
+++ b/tests/unit/rpc/common.py
@@ -19,9 +19,9 @@
Unit Tests for remote procedure calls shared between all implementations
"""
+import datetime
import logging
import time
-import datetime
import eventlet
from oslo.config import cfg
diff --git a/tests/unit/rpc/test_common.py b/tests/unit/rpc/test_common.py
index 1f07ff7..73ca63b 100644
--- a/tests/unit/rpc/test_common.py
+++ b/tests/unit/rpc/test_common.py
@@ -20,8 +20,8 @@ Unit Tests for 'common' functons used through rpc code.
import logging
import sys
-import six
from oslo.config import cfg
+import six
from openstack.common import exception
from openstack.common import importutils
diff --git a/tests/unit/rpc/test_kombu.py b/tests/unit/rpc/test_kombu.py
index 73ce2ce..ebc29ea 100644
--- a/tests/unit/rpc/test_kombu.py
+++ b/tests/unit/rpc/test_kombu.py
@@ -26,8 +26,8 @@ import contextlib
import logging
import mock
-import six
from oslo.config import cfg
+import six
from openstack.common import exception
from openstack.common.rpc import amqp as rpc_amqp
diff --git a/tests/unit/rpc/test_proxy.py b/tests/unit/rpc/test_proxy.py
index a84a7ea..63360ba 100644
--- a/tests/unit/rpc/test_proxy.py
+++ b/tests/unit/rpc/test_proxy.py
@@ -25,8 +25,8 @@ import six
from openstack.common import context
from openstack.common import lockutils
from openstack.common import rpc
-from openstack.common.rpc import proxy
from openstack.common.rpc import common as rpc_common
+from openstack.common.rpc import proxy
from tests import utils
@@ -85,6 +85,12 @@ class RpcProxyTestCase(utils.BaseTestCase):
new_msg['version'] = '1.1'
_check_args(ctxt, topic, new_msg)
+ # override the version to be above a specified cap
+ rpc_proxy.version_cap = '1.0'
+ self.assertRaises(rpc_common.RpcVersionCapError,
+ getattr(rpc_proxy, rpc_method), *args, version='1.1')
+ rpc_proxy.version_cap = None
+
if has_timeout:
# Set a timeout
retval = getattr(rpc_proxy, rpc_method)(ctxt, msg, timeout=42)
diff --git a/tests/unit/rpc/test_qpid.py b/tests/unit/rpc/test_qpid.py
index 0ee05cf..82cc119 100644
--- a/tests/unit/rpc/test_qpid.py
+++ b/tests/unit/rpc/test_qpid.py
@@ -29,8 +29,8 @@ from oslo.config import cfg
from openstack.common import context
from openstack.common.rpc import amqp as rpc_amqp
-from tests import utils
from openstack.common.rpc import common as rpc_common
+from tests import utils
try:
import qpid
diff --git a/tests/unit/test_log.py b/tests/unit/test_log.py
index c73f67a..301e3a8 100644
--- a/tests/unit/test_log.py
+++ b/tests/unit/test_log.py
@@ -10,6 +10,7 @@ from oslo.config import cfg
from openstack.common import context
from openstack.common import jsonutils
from openstack.common import log
+from openstack.common.log_handler import PublishErrorsHandler
from openstack.common.notifier import api as notifier
from tests import utils as test_utils
@@ -114,7 +115,7 @@ class PublishErrorsHandlerTestCase(test_utils.BaseTestCase):
"""Tests for log.PublishErrorsHandler"""
def setUp(self):
super(PublishErrorsHandlerTestCase, self).setUp()
- self.publiserrorshandler = log.PublishErrorsHandler(logging.ERROR)
+ self.publiserrorshandler = PublishErrorsHandler(logging.ERROR)
def test_emit_cfg_log_notifier_in_notifier_drivers(self):
self.config(notification_driver=[
diff --git a/tests/unit/test_rootwrap.py b/tests/unit/test_rootwrap.py
index ea6ccbb..5a5d9ca 100644
--- a/tests/unit/test_rootwrap.py
+++ b/tests/unit/test_rootwrap.py
@@ -134,6 +134,18 @@ class RootwrapTestCase(utils.BaseTestCase):
self.stubs.Set(os, 'readlink', fake_readlink)
self.assertTrue(f.match(usercmd))
+ def test_KillFilter_upgraded_exe(self):
+ """Makes sure upgraded exe's are killed correctly"""
+ # See bug #1179793.
+ def fake_readlink(blah):
+ return '/bin/commandddddd\0\05190bfb2 (deleted)'
+
+ f = filters.KillFilter("root", "/bin/commandddddd")
+ usercmd = ['kill', 1234]
+
+ self.stubs.Set(os, 'readlink', fake_readlink)
+ self.assertTrue(f.match(usercmd))
+
def test_ReadFileFilter(self):
goodfn = '/good/file.name'
f = filters.ReadFileFilter(goodfn)
diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py
index 77cf7ff..b7ba4f7 100644
--- a/tests/unit/test_service.py
+++ b/tests/unit/test_service.py
@@ -190,3 +190,13 @@ class ServiceLauncherTest(utils.BaseTestCase):
status = self._reap_test()
self.assertTrue(os.WIFEXITED(status))
self.assertEqual(os.WEXITSTATUS(status), 0)
+
+
+class LauncherTest(utils.BaseTestCase):
+ def test_backdoor_port(self):
+ # backdoor port should get passed to the service being launched
+ self.config(backdoor_port=1234)
+ svc = service.Service()
+ launcher = service.launch(svc)
+ self.assertEqual(1234, svc.backdoor_port)
+ launcher.stop()
diff --git a/tests/unit/test_setup.py b/tests/unit/test_setup.py
index c032592..626d71b 100644
--- a/tests/unit/test_setup.py
+++ b/tests/unit/test_setup.py
@@ -17,8 +17,8 @@
import io
import os
-import sys
import StringIO
+import sys
from tempfile import mkstemp
import fixtures
diff --git a/tests/unit/test_threadgroup.py b/tests/unit/test_threadgroup.py
new file mode 100644
index 0000000..f627215
--- /dev/null
+++ b/tests/unit/test_threadgroup.py
@@ -0,0 +1,50 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2012 Rackspace Hosting
+# 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.
+
+"""
+Unit Tests for thread groups
+"""
+
+from openstack.common import log as logging
+from openstack.common import threadgroup
+from tests import utils
+
+LOG = logging.getLogger(__name__)
+
+
+class ThreadGroupTestCase(utils.BaseTestCase):
+ """Test cases for thread group"""
+ def setUp(self):
+ super(ThreadGroupTestCase, self).setUp()
+ self.tg = threadgroup.ThreadGroup()
+ self.addCleanup(self.tg.stop)
+
+ def test_add_dynamic_timer(self):
+
+ def foo(*args, **kwargs):
+ pass
+ initial_delay = 1
+ periodic_interval_max = 2
+ self.tg.add_dynamic_timer(foo, initial_delay, periodic_interval_max,
+ 'arg', kwarg='kwarg')
+
+ self.assertEqual(1, len(self.tg.timers))
+
+ timer = self.tg.timers[0]
+ self.assertTrue(timer._running)
+ self.assertEqual(('arg',), timer.args)
+ self.assertEqual({'kwarg': 'kwarg'}, timer.kw)
diff --git a/tests/utils.py b/tests/utils.py
index 591ebef..c5c7c00 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -21,8 +21,8 @@ import fixtures
from oslo.config import cfg
import testtools
-from openstack.common.fixture import moxstubout
from openstack.common import exception
+from openstack.common.fixture import moxstubout
CONF = cfg.CONF