diff options
author | Clif Houck <me@clifhouck.com> | 2014-12-30 15:02:59 -0600 |
---|---|---|
committer | Thom Leggett <thom@tteggel.org> | 2015-01-21 17:36:24 +0000 |
commit | d170edf8b738885cdbe96dcb0c62f8ef00a28117 (patch) | |
tree | 82f2622a1712f9b89e9deb1e5ee7eaa5223681ac | |
parent | 451a69fef02197807a656f3430cf1e8162261e88 (diff) | |
download | oslo-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.py | 4 | ||||
-rw-r--r-- | tests/unit/test_service.py | 36 |
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)) |