From 0ac4a97204b129a10e9cc7fa1154dc24711281bd Mon Sep 17 00:00:00 2001 From: Surya Seetharaman Date: Tue, 18 Jun 2019 13:59:47 +0200 Subject: [PATCH] Grab fresh power state info from the driver In drivers that use a cache to store the node info (presently only ironic since [1]), the "_get_power_state" function called during instance actions like start or stop grabs the information from the node cache and saves it in the nova database instead of getting fresh information from the driver. This leads to inconsistency between the vm_state and power_state for an instance in the nova database (which remains until a power_sync happens between nova and ironic). This can be confusing for a user when doing "nova list" where the power_state might still be shutdown when the vm_state has already become active. On a default environment this inconsistency lasts for about ten minutes which is the default value for the sync_power_state_interval interval. This patch changes the "use_cache" to False in the compute manager when triggering an action on an instance like start/stop/reboot. [1] I0069cbc327d952d42dbb8fe54949faab89995a7e Change-Id: I8bca5d84c37d02331d2f9968a674f3398c1a8f5b Closes-Bug: #1832720 (cherry picked from commit 5b1c9dd05ccc0488e4d47bfc2442e46adb82b765) (cherry picked from commit 16449cbfe97eef1500f5a73a9d30e7abf4249b99) --- nova/compute/manager.py | 2 +- nova/tests/unit/compute/test_compute_mgr.py | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index a8a66030d809..45087357e706 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1274,7 +1274,7 @@ class ComputeManager(manager.Manager): """Retrieve the power state for the given instance.""" LOG.debug('Checking state', instance=instance) try: - return self.driver.get_info(instance).state + return self.driver.get_info(instance, use_cache=False).state except exception.InstanceNotFound: return power_state.NOSTATE diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 3f69ceedb7cf..5dbe33cb7bdc 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -1152,8 +1152,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): mock_finish.assert_called_once_with(self.context, instance, [], [], power_on) mock_save.assert_called_once_with() - mock_get_info.assert_has_calls([mock.call(instance), - mock.call(instance)]) + mock_get_info.assert_has_calls( + [mock.call(instance, use_cache=False), + mock.call(instance, use_cache=False)]) self.assertIsNone(instance.task_state) def test_init_instance_reverts_crashed_migration_from_active(self): @@ -1625,6 +1626,20 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): self.compute.stop_instance.assert_has_calls([call]) self.assertIsNone(init_return) + def test_get_power_state(self): + instance = objects.Instance(self.context) + instance.uuid = uuids.instance + instance.id = 1 + instance.vm_state = vm_states.STOPPED + instance.task_state = None + instance.host = self.compute.host + with mock.patch.object(self.compute.driver, 'get_info') as mock_info: + mock_info.return_value = hardware.InstanceInfo( + state=power_state.SHUTDOWN) + res = self.compute._get_power_state(self.context, instance) + mock_info.assert_called_once_with(instance, use_cache=False) + self.assertEqual(res, power_state.SHUTDOWN) + @mock.patch('nova.objects.InstanceList.get_by_filters') def test_get_instances_on_driver(self, mock_instance_list): driver_instances = []