summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClif Houck <me@clifhouck.com>2014-12-30 15:02:59 -0600
committerThom Leggett <thom@tteggel.org>2015-01-21 17:36:24 +0000
commitd170edf8b738885cdbe96dcb0c62f8ef00a28117 (patch)
tree82f2622a1712f9b89e9deb1e5ee7eaa5223681ac
parent451a69fef02197807a656f3430cf1e8162261e88 (diff)
downloadoslo-incubator-d170edf8b738885cdbe96dcb0c62f8ef00a28117.tar.gz
Added graceful argument on Service.stop method
This change adds a graceful shutdown arugment to the Service.stop method in order to allow a service to gracefully wait for threads to shutdown. Since threadgroup already supports a graceful shutdown argument for its stop() method, it is trivial to support. Added unit tests to demonstrate the expected behavior between graceful and ungraceful service stop()s. Change-Id: Ibc0df09daef5e2a07f232543f44f2fc4d203511c Closes-Bug: 1406638 (cherry picked from commit 442fc2234e8500fb11633d8d8ee7dfe5492fa4a3)
-rw-r--r--openstack/common/service.py4
-rw-r--r--tests/unit/test_service.py36
2 files changed, 37 insertions, 3 deletions
diff --git a/openstack/common/service.py b/openstack/common/service.py
index f91714e2..dc186558 100644
--- a/openstack/common/service.py
+++ b/openstack/common/service.py
@@ -442,8 +442,8 @@ class Service(object):
def start(self):
pass
- def stop(self):
- self.tg.stop()
+ def stop(self, graceful=False):
+ self.tg.stop(graceful)
self.tg.wait()
# Signal that service cleanup is done:
if not self._done.ready():
diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py
index 97bc3203..50403a3d 100644
--- a/tests/unit/test_service.py
+++ b/tests/unit/test_service.py
@@ -277,7 +277,6 @@ class _Service(service.Service):
class LauncherTest(test_base.BaseTestCase):
-
def setUp(self):
super(LauncherTest, self).setUp()
self.mox = self.useFixture(moxstubout.MoxStubout()).mox
@@ -391,3 +390,38 @@ class ProcessLauncherTest(test_base.BaseTestCase):
self.assertEqual([mock.call(22, signal.SIGTERM),
mock.call(222, signal.SIGTERM)],
mock_kill.mock_calls)
+
+
+class GracefulShutdownTestService(service.Service):
+ def __init__(self):
+ super(GracefulShutdownTestService, self).__init__()
+ self.finished_task = event.Event()
+
+ def start(self, sleep_amount):
+ def sleep_and_send(finish_event):
+ time.sleep(sleep_amount)
+ finish_event.send()
+ self.tg.add_thread(sleep_and_send, self.finished_task)
+
+
+def exercise_graceful_test_service(sleep_amount, time_to_wait, graceful):
+ svc = GracefulShutdownTestService()
+ svc.start(sleep_amount)
+ svc.stop(graceful)
+
+ def wait_for_task(svc):
+ svc.finished_task.wait()
+
+ return eventlet.timeout.with_timeout(time_to_wait, wait_for_task,
+ svc=svc, timeout_value="Timeout!")
+
+
+class ServiceTest(test_base.BaseTestCase):
+ def test_graceful_stop(self):
+ # Here we wait long enough for the task to gracefully finish.
+ self.assertEqual(None, exercise_graceful_test_service(1, 2, True))
+
+ def test_ungraceful_stop(self):
+ # Here we stop ungracefully, and will never see the task finish.
+ self.assertEqual("Timeout!",
+ exercise_graceful_test_service(1, 2, False))