diff --git a/nova/compute/manager.py b/nova/compute/manager.py index b20bbb8885..ae0db22166 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1827,7 +1827,7 @@ class ComputeManager(manager.Manager): 'killed before the manager finishes waiting.', CONF.manager_shutdown_timeout, CONF.graceful_shutdown_timeout) - sleep_time = CONF.graceful_shutdown_timeout - 10 + sleep_time = max(0, CONF.graceful_shutdown_timeout - 10) else: sleep_time = CONF.manager_shutdown_timeout LOG.debug('Compute service manager is waiting for %s seconds to ' diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 253cae84e3..5e3a90c6be 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -218,7 +218,7 @@ class ConductorManager(manager.Manager): 'killed before the manager finishes waiting.', CONF.manager_shutdown_timeout, CONF.graceful_shutdown_timeout) - sleep_time = CONF.graceful_shutdown_timeout - 10 + sleep_time = max(0, CONF.graceful_shutdown_timeout - 10) else: sleep_time = CONF.manager_shutdown_timeout LOG.debug('Conductor service manager is waiting for %s seconds to ' diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 4f5aa1df3a..efff0d9e4a 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -172,7 +172,7 @@ class SchedulerManager(manager.Manager): 'killed before the manager finishes waiting.', CONF.manager_shutdown_timeout, CONF.graceful_shutdown_timeout) - sleep_time = CONF.graceful_shutdown_timeout - 10 + sleep_time = max(0, CONF.graceful_shutdown_timeout - 10) else: sleep_time = CONF.manager_shutdown_timeout LOG.debug('Scheduler service manager is waiting for %s seconds to ' diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index f06bb6ee42..3f88754c92 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -8005,6 +8005,16 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, mock_sleep.assert_called_once_with(20) mock_cleanup.assert_called_once_with() + @mock.patch('time.sleep') + @mock.patch('nova.compute.manager.ComputeManager.cleanup_host') + def test_graceful_shutdown_no_negative_sleep_time( + self, mock_cleanup, mock_sleep): + # If sleep time end up with negative value, fallback to slep(0) + self.flags(manager_shutdown_timeout=50, graceful_shutdown_timeout=5) + self.compute.graceful_shutdown() + mock_sleep.assert_called_once_with(0) + mock_cleanup.assert_called_once_with() + @mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid') @mock.patch('nova.compute.manager.ComputeManager._delete_instance') def test_terminate_instance_no_bdm_volume_id(self, mock_delete_instance, diff --git a/nova/tests/unit/conductor/test_conductor.py b/nova/tests/unit/conductor/test_conductor.py index 03bdfd2920..16f624ee4a 100644 --- a/nova/tests/unit/conductor/test_conductor.py +++ b/nova/tests/unit/conductor/test_conductor.py @@ -320,6 +320,13 @@ class ConductorTestCase(_BaseTestCase, test.TestCase): mock_log.warning.assert_called_once() mock_sleep.assert_called_once_with(20) + @mock.patch('time.sleep') + def test_graceful_shutdown_no_negative_sleep_time(self, mock_sleep): + # If sleep time end up with negative value, fallback to slep(0) + self.flags(manager_shutdown_timeout=50, graceful_shutdown_timeout=5) + self.conductor.graceful_shutdown() + mock_sleep.assert_called_once_with(0) + def test_provider_fw_rule_get_all(self): result = self.conductor.provider_fw_rule_get_all(self.context) self.assertEqual([], result) diff --git a/nova/tests/unit/scheduler/test_manager.py b/nova/tests/unit/scheduler/test_manager.py index e6c3446d09..fb091ca23d 100644 --- a/nova/tests/unit/scheduler/test_manager.py +++ b/nova/tests/unit/scheduler/test_manager.py @@ -1678,6 +1678,13 @@ class SchedulerManagerTestCase(test.NoDBTestCase): mock_log.warning.assert_called_once() mock_sleep.assert_called_once_with(20) + @mock.patch('time.sleep') + def test_graceful_shutdown_no_negative_sleep_time(self, mock_sleep): + # If sleep time end up with negative value, fallback to slep(0) + self.flags(manager_shutdown_timeout=50, graceful_shutdown_timeout=5) + self.manager.graceful_shutdown() + mock_sleep.assert_called_once_with(0) + @mock.patch('nova.objects.service.ServiceList.get_by_binary') @mock.patch('nova.objects.host_mapping.discover_hosts') def test_discover_hosts(self, mock_discover, mock_get_by_binary):