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] I907b69eb689cf6c169a4869cfc7889308ca419d5

Change-Id: I8bca5d84c37d02331d2f9968a674f3398c1a8f5b
Closes-Bug: #1832720
This commit is contained in:
Surya Seetharaman 2019-06-18 13:59:47 +02:00
parent a628d2f09a
commit 5b1c9dd05c
2 changed files with 18 additions and 3 deletions

View File

@ -1281,7 +1281,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

View File

@ -1168,8 +1168,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):
@ -1641,6 +1642,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 = []