Hello community,
here is the log from the commit of package python-oslo.service for openSUSE:Factory checked in at 2016-06-02 09:38:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-oslo.service (Old)
and /work/SRC/openSUSE:Factory/.python-oslo.service.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-oslo.service"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-oslo.service/python-oslo.service.changes 2016-05-04 08:19:59.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-oslo.service.new/python-oslo.service.changes 2016-06-02 09:38:58.000000000 +0200
@@ -1,0 +2,23 @@
+Tue May 31 13:49:31 UTC 2016 - slunkad@suse.com
+
+- update to 1.11.0
+ * Trivial: ignore openstack/common in flake8 exclude list
+- 1.10.0
+ * [Trivial] Remove executable privilege of doc/source/conf.py
+- 1.9.0
+ * Updated from global requirements
+ * Offer mutate_config_files
+ * Make _spawn_service more flexible
+ * Remove direct dependency on babel
+ * Updated from global requirements
+ * Updated from global requirements
+ * Updated from global requirements
+ * Updated from global requirements
+ * Fix argument type for _sd_notify() on python3
+ * Use a timeutils.StopWatch for cancel timing
+ * Add ability to cancel Threads and ThreadGroups
+ * Exception: message need '_' function
+ * Fix Heartbeats stop when time is changed
+ * Updated from global requirements
+
+-------------------------------------------------------------------
Old:
----
oslo.service-1.8.0.tar.gz
New:
----
oslo.service-1.11.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-oslo.service.spec ++++++
--- /var/tmp/diff_new_pack.zwag7s/_old 2016-06-02 09:38:59.000000000 +0200
+++ /var/tmp/diff_new_pack.zwag7s/_new 2016-06-02 09:38:59.000000000 +0200
@@ -16,16 +16,16 @@
#
-%define version_unconverted 1.8.0
+%define version_unconverted 1.11.0
Name: python-oslo.service
-Version: 1.8.0
+Version: 1.11.0
Release: 0
Summary: Oslo service library
License: Apache-2.0
Group: Development/Languages/Python
Url: http://launchpad.net/oslo
-Source: https://pypi.python.org/packages/source/o/oslo.service/oslo.service-%{version}.tar.gz
+Source: https://pypi.python.org/packages/90/4c/c52ea2f34c88594fbe6bfe7b2bf0c287fd953c9058aa93cae41acc66c5a9/oslo.service-%{version}.tar.gz
BuildRequires: openstack-suse-macros
BuildRequires: python-devel
BuildRequires: python-pbr
++++++ oslo.service-1.8.0.tar.gz -> oslo.service-1.11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/AUTHORS new/oslo.service-1.11.0/AUTHORS
--- old/oslo.service-1.8.0/AUTHORS 2016-03-28 05:09:29.000000000 +0200
+++ new/oslo.service-1.11.0/AUTHORS 2016-05-25 00:10:02.000000000 +0200
@@ -1,9 +1,11 @@
Accela Zhao
Alan Pevec
+Alberto Murillo
Alessandro Pilotti
Alex Gaynor
Alex Holden
Alexander Gorodnev
+Alexis Lee
Andreas Jaeger
Andreas Jaeger
Angus Salkeld
@@ -53,6 +55,7 @@
John L. Villalovos
Joshua Harlow
Joshua Harlow
+Joshua Harlow
Julien Danjou
Kevin L. Mitchell
Kiall Mac Innes
@@ -86,6 +89,7 @@
Tom Cammann
Victor Sergeyev
Victor Stinner
+ZhiQiang Fan
Zhongyue Luo
apporc
fujioka yuuichi
@@ -98,3 +102,4 @@
sonu.kumar
stanzgy
venkatamahesh
+zwei
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/ChangeLog new/oslo.service-1.11.0/ChangeLog
--- old/oslo.service-1.8.0/ChangeLog 2016-03-28 05:09:29.000000000 +0200
+++ new/oslo.service-1.11.0/ChangeLog 2016-05-25 00:10:02.000000000 +0200
@@ -1,11 +1,33 @@
CHANGES
=======
-1.8.0
+1.11.0
+------
+
+* Trivial: ignore openstack/common in flake8 exclude list
+
+1.10.0
+------
+
+* [Trivial] Remove executable privilege of doc/source/conf.py
+
+1.9.0
-----
* Updated from global requirements
-* Update .gitreview for stable/mitaka
+* Offer mutate_config_files
+* Make _spawn_service more flexible
+* Remove direct dependency on babel
+* Updated from global requirements
+* Updated from global requirements
+* Updated from global requirements
+* Updated from global requirements
+* Fix argument type for _sd_notify() on python3
+* Use a timeutils.StopWatch for cancel timing
+* Add ability to cancel Threads and ThreadGroups
+* Exception: message need '_' function
+* Fix Heartbeats stop when time is changed
+* Updated from global requirements
1.7.0
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/PKG-INFO new/oslo.service-1.11.0/PKG-INFO
--- old/oslo.service-1.8.0/PKG-INFO 2016-03-28 05:09:30.000000000 +0200
+++ new/oslo.service-1.11.0/PKG-INFO 2016-05-25 00:10:03.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oslo.service
-Version: 1.8.0
+Version: 1.11.0
Summary: oslo.service library
Home-page: http://wiki.openstack.org/wiki/Oslo#oslo.service
Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo.service.egg-info/PKG-INFO new/oslo.service-1.11.0/oslo.service.egg-info/PKG-INFO
--- old/oslo.service-1.8.0/oslo.service.egg-info/PKG-INFO 2016-03-28 05:09:29.000000000 +0200
+++ new/oslo.service-1.11.0/oslo.service.egg-info/PKG-INFO 2016-05-25 00:10:02.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oslo.service
-Version: 1.8.0
+Version: 1.11.0
Summary: oslo.service library
Home-page: http://wiki.openstack.org/wiki/Oslo#oslo.service
Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo.service.egg-info/pbr.json new/oslo.service-1.11.0/oslo.service.egg-info/pbr.json
--- old/oslo.service-1.8.0/oslo.service.egg-info/pbr.json 2016-03-28 05:09:29.000000000 +0200
+++ new/oslo.service-1.11.0/oslo.service.egg-info/pbr.json 2016-05-25 00:10:02.000000000 +0200
@@ -1 +1 @@
-{"git_version": "427b8ad", "is_release": true}
\ No newline at end of file
+{"is_release": true, "git_version": "43343b4"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo.service.egg-info/requires.txt new/oslo.service-1.11.0/oslo.service.egg-info/requires.txt
--- old/oslo.service-1.8.0/oslo.service.egg-info/requires.txt 2016-03-28 05:09:29.000000000 +0200
+++ new/oslo.service-1.11.0/oslo.service.egg-info/requires.txt 2016-05-25 00:10:02.000000000 +0200
@@ -1,19 +1,16 @@
-Babel>=1.3
WebOb>=1.2.3
eventlet!=0.18.3,>=0.18.2
greenlet>=0.3.2
monotonic>=0.6
oslo.utils>=3.5.0
oslo.concurrency>=3.5.0
-oslo.config>=3.7.0
+oslo.config>=3.9.0
oslo.log>=1.14.0
six>=1.9.0
oslo.i18n>=2.1.0
PasteDeploy>=1.5.0
+Routes!=2.0,!=2.1,!=2.3.0,>=1.12.3
Paste
[:(python_version!='2.7')]
-Routes!=2.0,>=1.12.3
-
-[:(python_version=='2.7')]
-Routes!=2.0,!=2.1,>=1.12.3
+Routes!=2.0,!=2.3.0,>=1.12.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/__init__.py new/oslo.service-1.11.0/oslo_service/__init__.py
--- old/oslo.service-1.8.0/oslo_service/__init__.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/__init__.py 2016-05-25 00:08:22.000000000 +0200
@@ -0,0 +1,41 @@
+# 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 os
+
+import eventlet.patcher
+import monotonic
+from oslo_log import log as logging
+
+time = eventlet.patcher.original('time')
+
+
+LOG = logging.getLogger(__name__)
+
+if hasattr(time, 'monotonic'):
+ # Use builtin monotonic clock, Python 3.3+
+ _monotonic = time.monotonic
+else:
+ _monotonic = monotonic.monotonic
+
+
+def service_hub():
+ # NOTE(dims): Add a custom impl for EVENTLET_HUB, so we can
+ # override the clock used in the eventlet hubs. The default
+ # uses time.time() and we need to use a monotonic timer
+ # to ensure that things like loopingcall work properly.
+ hub = eventlet.hubs.get_default_hub().Hub()
+ hub.clock = _monotonic
+ return hub
+
+
+os.environ['EVENTLET_HUB'] = 'oslo_service:service_hub'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/eventlet_backdoor.py new/oslo.service-1.11.0/oslo_service/eventlet_backdoor.py
--- old/oslo.service-1.8.0/oslo_service/eventlet_backdoor.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/eventlet_backdoor.py 2016-05-25 00:08:22.000000000 +0200
@@ -28,7 +28,7 @@
import eventlet.backdoor
import greenlet
-from oslo_service._i18n import _LI
+from oslo_service._i18n import _LI, _
from oslo_service import _options
@@ -37,8 +37,8 @@
class EventletBackdoorConfigValueError(Exception):
def __init__(self, port_range, help_msg, ex):
- msg = ('Invalid backdoor_port configuration %(range)s: %(ex)s. '
- '%(help)s' %
+ msg = (_('Invalid backdoor_port configuration %(range)s: %(ex)s. '
+ '%(help)s') %
{'range': port_range, 'ex': ex, 'help': help_msg})
super(EventletBackdoorConfigValueError, self).__init__(msg)
self.port_range = port_range
@@ -220,7 +220,7 @@
where_running_thread = _initialize_if_enabled(conf)
if not where_running_thread:
- raise RuntimeError("Did not create backdoor at requested location")
+ raise RuntimeError(_("Did not create backdoor at requested location"))
else:
_where_running, thread = where_running_thread
thread.wait()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/loopingcall.py new/oslo.service-1.11.0/oslo_service/loopingcall.py
--- old/oslo.service-1.8.0/oslo_service/loopingcall.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/loopingcall.py 2016-05-25 00:08:22.000000000 +0200
@@ -263,9 +263,9 @@
"""
_RNG = random.SystemRandom()
- _KIND = 'Dynamic backoff interval looping call'
- _RUN_ONLY_ONE_MESSAGE = ("A dynamic backoff interval looping call can"
- " only run one function at a time")
+ _KIND = _('Dynamic backoff interval looping call')
+ _RUN_ONLY_ONE_MESSAGE = _("A dynamic backoff interval looping call can"
+ " only run one function at a time")
def __init__(self, f=None, *args, **kw):
super(BackOffLoopingCall, self).__init__(f=f, *args, **kw)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/service.py new/oslo.service-1.11.0/oslo_service/service.py
--- old/oslo.service-1.8.0/oslo_service/service.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/service.py 2016-05-25 00:08:22.000000000 +0200
@@ -35,7 +35,7 @@
from oslo_concurrency import lockutils
from oslo_service import eventlet_backdoor
-from oslo_service._i18n import _LE, _LI, _LW
+from oslo_service._i18n import _LE, _LI, _LW, _
from oslo_service import _options
from oslo_service import systemd
from oslo_service import threadgroup
@@ -43,6 +43,8 @@
LOG = logging.getLogger(__name__)
+_LAUNCHER_RESTART_METHODS = ['reload', 'mutate']
+
def list_opts():
"""Entry point for oslo-config-generator."""
@@ -81,7 +83,7 @@
def _check_service_base(service):
if not isinstance(service, ServiceBase):
- raise TypeError("Service %(service)s must an instance of %(base)s!"
+ raise TypeError(_("Service %(service)s must an instance of %(base)s!")
% {'service': service, 'base': ServiceBase})
@@ -182,9 +184,12 @@
class Launcher(object):
"""Launch one or more services and wait for them to complete."""
- def __init__(self, conf):
+ def __init__(self, conf, restart_method='reload'):
"""Initialize the service launcher.
+ :param restart_method: If 'reload', calls reload_config_files on
+ SIGHUP. If 'mutate', calls mutate_config_files on SIGHUP. Other
+ values produce a ValueError.
:returns: None
"""
@@ -193,15 +198,23 @@
self.services = Services()
self.backdoor_port = (
eventlet_backdoor.initialize_if_enabled(self.conf))
+ self.restart_method = restart_method
+ if restart_method not in _LAUNCHER_RESTART_METHODS:
+ raise ValueError(_("Invalid restart_method: %s") % restart_method)
- def launch_service(self, service):
+ def launch_service(self, service, workers=1):
"""Load and start the given service.
:param service: The service you would like to start, must be an
instance of :class:`oslo_service.service.ServiceBase`
+ :param workers: This param makes this method compatible with
+ ProcessLauncher.launch_service. It must be None, 1 or
+ omitted.
:returns: None
"""
+ if workers is not None and workers != 1:
+ raise ValueError(_("Launcher asked to start multiple workers"))
_check_service_base(service)
service.backdoor_port = self.backdoor_port
self.services.add(service)
@@ -225,10 +238,14 @@
def restart(self):
"""Reload config files and restart service.
- :returns: None
+ :returns: The return value from reload_config_files or
+ mutate_config_files, according to the restart_method.
"""
- self.conf.reload_config_files()
+ if self.restart_method == 'reload':
+ self.conf.reload_config_files()
+ elif self.restart_method == 'mutate':
+ self.conf.mutate_config_files()
self.services.restart()
@@ -240,12 +257,14 @@
class ServiceLauncher(Launcher):
"""Runs one or more service in a parent process."""
- def __init__(self, conf):
+ def __init__(self, conf, restart_method='reload'):
"""Constructor.
:param conf: an instance of ConfigOpts
+ :param restart_method: passed to super
"""
- super(ServiceLauncher, self).__init__(conf)
+ super(ServiceLauncher, self).__init__(
+ conf, restart_method=restart_method)
self.signal_handler = SignalHandler()
def _graceful_shutdown(self, *args):
@@ -326,12 +345,15 @@
class ProcessLauncher(object):
"""Launch a service with a given number of workers."""
- def __init__(self, conf, wait_interval=0.01):
+ def __init__(self, conf, wait_interval=0.01, restart_method='reload'):
"""Constructor.
:param conf: an instance of ConfigOpts
:param wait_interval: The interval to sleep for between checks
of child process exit.
+ :param restart_method: If 'reload', calls reload_config_files on
+ SIGHUP. If 'mutate', calls mutate_config_files on SIGHUP. Other
+ values produce a ValueError.
"""
self.conf = conf
conf.register_opts(_options.service_opts)
@@ -344,6 +366,9 @@
self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
self.signal_handler = SignalHandler()
self.handle_signal()
+ self.restart_method = restart_method
+ if restart_method not in _LAUNCHER_RESTART_METHODS:
+ raise ValueError(_("Invalid restart_method: %s") % restart_method)
def handle_signal(self):
"""Add instance's signal handlers to class handlers."""
@@ -440,7 +465,7 @@
# Reseed random number generator
random.seed()
- launcher = Launcher(self.conf)
+ launcher = Launcher(self.conf, restart_method=self.restart_method)
launcher.launch_service(service)
return launcher
@@ -555,7 +580,10 @@
if not _is_sighup_and_daemon(self.sigcaught):
break
- self.conf.reload_config_files()
+ if self.restart_method == 'reload':
+ self.conf.reload_config_files()
+ elif self.restart_method == 'mutate':
+ self.conf.mutate_config_files()
for service in set(
[wrap.service for wrap in self.children.values()]):
service.reset()
@@ -685,24 +713,26 @@
done.wait()
-def launch(conf, service, workers=1):
+def launch(conf, service, workers=1, restart_method='reload'):
"""Launch a service with a given number of workers.
:param conf: an instance of ConfigOpts
:param service: a service to launch, must be an instance of
:class:`oslo_service.service.ServiceBase`
:param workers: a number of processes in which a service will be running
+ :param restart_method: Passed to the constructed launcher. If 'reload', the
+ launcher will call reload_config_files on SIGHUP. If 'mutate', it will
+ call mutate_config_files on SIGHUP. Other values produce a ValueError.
:returns: instance of a launcher that was used to launch the service
"""
if workers is not None and workers <= 0:
- raise ValueError("Number of workers should be positive!")
+ raise ValueError(_("Number of workers should be positive!"))
if workers is None or workers == 1:
- launcher = ServiceLauncher(conf)
- launcher.launch_service(service)
+ launcher = ServiceLauncher(conf, restart_method=restart_method)
else:
- launcher = ProcessLauncher(conf)
- launcher.launch_service(service, workers=workers)
+ launcher = ProcessLauncher(conf, restart_method=restart_method)
+ launcher.launch_service(service, workers=workers)
return launcher
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/systemd.py new/oslo.service-1.11.0/oslo_service/systemd.py
--- old/oslo.service-1.8.0/oslo_service/systemd.py 2016-03-28 05:07:07.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/systemd.py 2016-05-25 00:08:22.000000000 +0200
@@ -53,7 +53,7 @@
For details see
http://www.freedesktop.org/software/systemd/man/sd_notify.html
"""
- _sd_notify(False, 'READY=1')
+ _sd_notify(False, b'READY=1')
def notify_once():
@@ -64,7 +64,7 @@
This method removes the NOTIFY_SOCKET environment variable to ensure
notification is sent only once.
"""
- _sd_notify(True, 'READY=1')
+ _sd_notify(True, b'READY=1')
def onready(notify_socket, timeout):
@@ -86,7 +86,7 @@
msg = sock.recv(512)
except socket.timeout:
return 2
- if 'READY=1' in msg:
+ if b'READY=1' == msg:
return 0
else:
return 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/tests/test_loopingcall.py new/oslo.service-1.11.0/oslo_service/tests/test_loopingcall.py
--- old/oslo.service-1.8.0/oslo_service/tests/test_loopingcall.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/tests/test_loopingcall.py 2016-05-25 00:08:22.000000000 +0200
@@ -12,12 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+import eventlet
from eventlet.green import threading as greenthreading
import mock
from oslotest import base as test_base
+import oslo_service
from oslo_service import loopingcall
+threading = eventlet.patcher.original('threading')
+time = eventlet.patcher.original('time')
+
class LoopingCallTestCase(test_base.BaseTestCase):
@@ -32,6 +37,61 @@
timer = loopingcall.FixedIntervalLoopingCall(_raise_it)
self.assertTrue(timer.start(interval=0.5).wait())
+ def test_monotonic_timer(self):
+ def _raise_it():
+ clock = eventlet.hubs.get_hub().clock
+ ok = (clock == oslo_service._monotonic)
+ raise loopingcall.LoopingCallDone(ok)
+
+ timer = loopingcall.FixedIntervalLoopingCall(_raise_it)
+ self.assertTrue(timer.start(interval=0.5).wait())
+
+ def test_eventlet_clock(self):
+ # Make sure that by default the oslo_service.service_hub() kicks in,
+ # test in the main thread
+ hub = eventlet.hubs.get_hub()
+ self.assertEqual(hub.clock,
+ oslo_service._monotonic)
+
+ def test_eventlet_use_hub_override(self):
+ ns = {}
+
+ def task():
+ try:
+ self._test_eventlet_use_hub_override()
+ except Exception as exc:
+ ns['result'] = exc
+ else:
+ ns['result'] = 'ok'
+
+ # test overriding the hub of in a new thread to not modify the hub
+ # of the main thread
+ thread = threading.Thread(target=task)
+ thread.start()
+ thread.join()
+ self.assertEqual(ns['result'], 'ok')
+
+ def _test_eventlet_use_hub_override(self):
+ # Make sure that by default the
+ # oslo_service.service_hub() kicks in
+ old_clock = eventlet.hubs.get_hub().clock
+ self.assertEqual(old_clock,
+ oslo_service._monotonic)
+
+ # eventlet will use time.monotonic() by default, same clock than
+ # oslo.service_hub():
+ # https://github.com/eventlet/eventlet/pull/303
+ if not hasattr(time, 'monotonic'):
+ # If anyone wants to override it
+ try:
+ eventlet.hubs.use_hub('poll')
+ except Exception:
+ eventlet.hubs.use_hub('selects')
+
+ # then we get a new clock and the override works fine too!
+ clock = eventlet.hubs.get_hub().clock
+ self.assertNotEqual(old_clock, clock)
+
def test_return_false(self):
def _raise_it():
raise loopingcall.LoopingCallDone(False)
@@ -132,6 +192,15 @@
timer = loopingcall.DynamicLoopingCall(_raise_it)
self.assertTrue(timer.start().wait())
+
+ def test_monotonic_timer(self):
+ def _raise_it():
+ clock = eventlet.hubs.get_hub().clock
+ ok = (clock == oslo_service._monotonic)
+ raise loopingcall.LoopingCallDone(ok)
+
+ timer = loopingcall.DynamicLoopingCall(_raise_it)
+ self.assertTrue(timer.start().wait())
def test_no_double_start(self):
wait_ev = greenthreading.Event()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/tests/test_service.py new/oslo.service-1.11.0/oslo_service/tests/test_service.py
--- old/oslo.service-1.8.0/oslo_service/tests/test_service.py 2016-03-28 05:07:07.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/tests/test_service.py 2016-05-25 00:08:22.000000000 +0200
@@ -84,8 +84,8 @@
def _spawn_service(self,
workers=1,
- service_to_launch=ServiceWithTimer,
- *args, **kwargs):
+ service_maker=None,
+ launcher_maker=None):
self.workers = workers
pid = os.fork()
if pid == 0:
@@ -99,8 +99,12 @@
# os._exit() which doesn't have this problem.
status = 0
try:
- serv = service_to_launch(*args, **kwargs)
- launcher = service.launch(self.conf, serv, workers=workers)
+ serv = service_maker() if service_maker else ServiceWithTimer()
+ if launcher_maker:
+ launcher = launcher_maker()
+ launcher.launch_service(serv, workers=workers)
+ else:
+ launcher = service.launch(self.conf, serv, workers=workers)
status = launcher.wait()
except SystemExit as exc:
status = exc.code
@@ -212,7 +216,8 @@
self.assertEqual(os.WEXITSTATUS(status), 0)
def test_crashed_service(self):
- self.pid = self._spawn_service(service_to_launch=ServiceCrashOnStart)
+ service_maker = lambda: ServiceCrashOnStart()
+ self.pid = self._spawn_service(service_maker=service_maker)
status = self._reap_test()
self.assertTrue(os.WIFEXITED(status))
self.assertEqual(os.WEXITSTATUS(status), 1)
@@ -251,8 +256,8 @@
def _spawn(self):
ready_event = multiprocessing.Event()
- self.pid = self._spawn_service(workers=1,
- ready_event=ready_event)
+ service_maker = lambda: ServiceWithTimer(ready_event=ready_event)
+ self.pid = self._spawn_service(service_maker=service_maker)
return ready_event
def test_service_restart(self):
@@ -279,6 +284,58 @@
self.assertTrue(os.WIFEXITED(status))
self.assertEqual(os.WEXITSTATUS(status), 0)
+ def test_mutate_hook_service_launcher(self):
+ """Test mutate_config_files is called by ServiceLauncher on SIGHUP.
+
+ Not using _spawn_service because ServiceLauncher doesn't fork and it's
+ simplest to stay all in one process.
+ """
+ mutate = multiprocessing.Event()
+ self.conf.register_mutate_hook(lambda c, f: mutate.set())
+ launcher = service.launch(
+ self.conf, ServiceWithTimer(), restart_method='mutate')
+
+ self.assertFalse(mutate.is_set(), "Hook was called too early")
+ launcher.restart()
+ self.assertTrue(mutate.is_set(), "Hook wasn't called")
+
+ def test_mutate_hook_process_launcher(self):
+ """Test mutate_config_files is called by ProcessLauncher on SIGHUP.
+
+ Forks happen in _spawn_service and ProcessLauncher. So we get three
+ tiers of processes, the top tier being the test process. self.pid
+ refers to the middle tier, which represents our application. Both
+ service_maker and launcher_maker execute in the middle tier. The bottom
+ tier is the workers.
+
+ The behavior we want is that when the application (middle tier)
+ receives a SIGHUP, it catches that, calls mutate_config_files and
+ relaunches all the workers. This causes them to inherit the mutated
+ config.
+ """
+ mutate = multiprocessing.Event()
+ ready = multiprocessing.Event()
+
+ def service_maker():
+ self.conf.register_mutate_hook(lambda c, f: mutate.set())
+ return ServiceWithTimer(ready)
+
+ def launcher_maker():
+ return service.ProcessLauncher(self.conf, restart_method='mutate')
+
+ self.pid = self._spawn_service(1, service_maker, launcher_maker)
+
+ timeout = 5
+ ready.wait(timeout)
+ self.assertTrue(ready.is_set(), 'Service never became ready')
+ ready.clear()
+
+ self.assertFalse(mutate.is_set(), "Hook was called too early")
+ os.kill(self.pid, signal.SIGHUP)
+ ready.wait(timeout)
+ self.assertTrue(ready.is_set(), 'Service never back after SIGHUP')
+ self.assertTrue(mutate.is_set(), "Hook wasn't called")
+
class _Service(service.Service):
def __init__(self):
@@ -315,7 +372,7 @@
def _test_launch_single(self, workers, mock_launch):
svc = service.Service()
service.launch(self.conf, svc, workers=workers)
- mock_launch.assert_called_with(svc)
+ mock_launch.assert_called_with(svc, workers=workers)
def test_launch_none(self):
self._test_launch_single(None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/tests/test_systemd.py new/oslo.service-1.11.0/oslo_service/tests/test_systemd.py
--- old/oslo.service-1.8.0/oslo_service/tests/test_systemd.py 2016-03-28 05:07:07.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/tests/test_systemd.py 2016-05-25 00:08:22.000000000 +0200
@@ -45,7 +45,7 @@
self.closed = True
def sendall(fs, data):
- if data == 'READY=1':
+ if data == b'READY=1':
self.ready = True
with mock.patch.object(socket, 'socket', new=FakeSocket):
@@ -67,7 +67,7 @@
@mock.patch("socket.socket")
def test_onready(self, sock_mock):
- recv_results = ['READY=1', '', socket.timeout]
+ recv_results = [b'READY=1', '', socket.timeout]
expected_results = [0, 1, 2]
for recv, expected in zip(recv_results, expected_results):
if recv == socket.timeout:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/tests/test_threadgroup.py new/oslo.service-1.11.0/oslo_service/tests/test_threadgroup.py
--- old/oslo.service-1.8.0/oslo_service/tests/test_threadgroup.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/tests/test_threadgroup.py 2016-05-25 00:08:22.000000000 +0200
@@ -93,6 +93,35 @@
self.assertEqual(0, len(self.tg.threads))
self.assertTrue(end_time - start_time >= 1)
+ def test_cancel_early(self):
+
+ def foo(*args, **kwargs):
+ time.sleep(1)
+ self.tg.add_thread(foo, 'arg', kwarg='kwarg')
+ self.tg.cancel()
+
+ self.assertEqual(0, len(self.tg.threads))
+
+ def test_cancel_late(self):
+
+ def foo(*args, **kwargs):
+ time.sleep(0.3)
+ self.tg.add_thread(foo, 'arg', kwarg='kwarg')
+ time.sleep(0)
+ self.tg.cancel()
+
+ self.assertEqual(1, len(self.tg.threads))
+
+ def test_cancel_timeout(self):
+
+ def foo(*args, **kwargs):
+ time.sleep(0.3)
+ self.tg.add_thread(foo, 'arg', kwarg='kwarg')
+ time.sleep(0)
+ self.tg.cancel(timeout=0.2, wait_time=0.1)
+
+ self.assertEqual(0, len(self.tg.threads))
+
def test_stop_timers(self):
def foo(*args, **kwargs):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/oslo_service/threadgroup.py new/oslo.service-1.11.0/oslo_service/threadgroup.py
--- old/oslo.service-1.8.0/oslo_service/threadgroup.py 2016-03-28 05:07:08.000000000 +0200
+++ new/oslo.service-1.11.0/oslo_service/threadgroup.py 2016-05-25 00:08:22.000000000 +0200
@@ -11,6 +11,7 @@
# 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
@@ -19,7 +20,7 @@
from oslo_service._i18n import _LE
from oslo_service import loopingcall
-
+from oslo_utils import timeutils
LOG = logging.getLogger(__name__)
@@ -58,6 +59,9 @@
def link(self, func, *args, **kwargs):
self.thread.link(func, *args, **kwargs)
+ def cancel(self, *throw_args):
+ self.thread.cancel(*throw_args)
+
class ThreadGroup(object):
"""The point of the ThreadGroup class is to:
@@ -154,3 +158,31 @@
self._perform_action_on_threads(
lambda x: x.wait(),
lambda x: LOG.exception(_LE('Error waiting on thread.')))
+
+ def _any_threads_alive(self):
+ current = threading.current_thread()
+ for x in self.threads[:]:
+ if x.ident == current.ident:
+ # Don't check current thread.
+ continue
+ if not x.thread.dead:
+ return True
+ return False
+
+ def cancel(self, *throw_args, **kwargs):
+ self._perform_action_on_threads(
+ lambda x: x.cancel(*throw_args),
+ lambda x: LOG.exception(_LE('Error canceling thread.')))
+
+ timeout = kwargs.get('timeout', None)
+ if timeout is None:
+ return
+ wait_time = kwargs.get('wait_time', 1)
+ watch = timeutils.StopWatch(duration=timeout)
+ watch.start()
+ while self._any_threads_alive():
+ if not watch.expired():
+ eventlet.sleep(wait_time)
+ continue
+ LOG.debug("Cancel timeout reached, stopping threads.")
+ self.stop()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/requirements.txt new/oslo.service-1.11.0/requirements.txt
--- old/oslo.service-1.8.0/requirements.txt 2016-03-28 05:07:07.000000000 +0200
+++ new/oslo.service-1.11.0/requirements.txt 2016-05-25 00:08:24.000000000 +0200
@@ -2,18 +2,17 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-Babel>=1.3 # BSD
WebOb>=1.2.3 # MIT
eventlet!=0.18.3,>=0.18.2 # MIT
greenlet>=0.3.2 # MIT
monotonic>=0.6 # Apache-2.0
oslo.utils>=3.5.0 # Apache-2.0
oslo.concurrency>=3.5.0 # Apache-2.0
-oslo.config>=3.7.0 # Apache-2.0
+oslo.config>=3.9.0 # Apache-2.0
oslo.log>=1.14.0 # Apache-2.0
six>=1.9.0 # MIT
oslo.i18n>=2.1.0 # Apache-2.0
PasteDeploy>=1.5.0 # MIT
-Routes!=2.0,!=2.1,>=1.12.3;python_version=='2.7' # MIT
-Routes!=2.0,>=1.12.3;python_version!='2.7' # MIT
+Routes!=2.0,!=2.1,!=2.3.0,>=1.12.3;python_version=='2.7' # MIT
+Routes!=2.0,!=2.3.0,>=1.12.3;python_version!='2.7' # MIT
Paste # MIT
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/setup.cfg new/oslo.service-1.11.0/setup.cfg
--- old/oslo.service-1.8.0/setup.cfg 2016-03-28 05:09:30.000000000 +0200
+++ new/oslo.service-1.11.0/setup.cfg 2016-05-25 00:10:03.000000000 +0200
@@ -59,7 +59,7 @@
universal = true
[egg_info]
-tag_svn_revision = 0
tag_build =
tag_date = 0
+tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/test-requirements.txt new/oslo.service-1.11.0/test-requirements.txt
--- old/oslo.service-1.8.0/test-requirements.txt 2016-03-28 05:07:07.000000000 +0200
+++ new/oslo.service-1.11.0/test-requirements.txt 2016-05-25 00:08:22.000000000 +0200
@@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-fixtures>=1.3.1 # Apache-2.0/BSD
+fixtures<2.0,>=1.3.1 # Apache-2.0/BSD
hacking<0.11,>=0.10.0
mock>=1.2 # BSD
oslotest>=1.10.0 # Apache-2.0
@@ -15,4 +15,4 @@
coverage>=3.6 # Apache-2.0
# Bandit security code scanner
-bandit>=0.17.3 # Apache-2.0
+bandit>=1.0.1 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.service-1.8.0/tox.ini new/oslo.service-1.11.0/tox.ini
--- old/oslo.service-1.8.0/tox.ini 2016-03-28 05:07:07.000000000 +0200
+++ new/oslo.service-1.11.0/tox.ini 2016-05-25 00:08:22.000000000 +0200
@@ -32,7 +32,7 @@
show-source = True
ignore = E123,E125
-exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build
+exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
[hacking]
import_exceptions = oslo_service._i18n