diff --git a/openstack/common/service.py b/openstack/common/service.py index cbd300b73..a41a29538 100644 --- a/openstack/common/service.py +++ b/openstack/common/service.py @@ -434,8 +434,8 @@ def reset(self): 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 2f9f774b6..4d9ecc098 100644 --- a/tests/unit/test_service.py +++ b/tests/unit/test_service.py @@ -273,7 +273,6 @@ def stop(self): class LauncherTest(test_base.BaseTestCase): - def setUp(self): super(LauncherTest, self).setUp() self.mox = self.useFixture(moxstubout.MoxStubout()).mox @@ -387,3 +386,38 @@ def test_stop(self): 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))