Fix shelving a paused instance
It is possible to shelve a paused instance, but in that case the
guest is already shutdown, and some hypervisors will fail when
trying to perform a clean shutdown of a non-running guest. For
example, attempting to shelve a paused libvirt instance will
result in this error:
libvirtError: Requested operation is not valid: domain is not running
Therefore, if the instance is paused, we don't attempt a clean
shutdown while shelving.
Related Tempest test: https://review.openstack.org/564127/
Closes-Bug: #1745529
Change-Id: I8ca25d9847d50001fbe8513a6c1dba8b697c24e4
(cherry picked from commit d5901f613c
)
This commit is contained in:
parent
419e6198fa
commit
f521e03f8e
@ -4760,7 +4760,11 @@ class ComputeManager(manager.Manager):
|
|||||||
expected_state = shelving_state_map[expected_state]
|
expected_state = shelving_state_map[expected_state]
|
||||||
instance.task_state = task_state
|
instance.task_state = task_state
|
||||||
instance.save(expected_task_state=expected_state)
|
instance.save(expected_task_state=expected_state)
|
||||||
|
# Do not attempt a clean shutdown of a paused guest since some
|
||||||
|
# hypervisors will fail the clean shutdown if the guest is not
|
||||||
|
# running.
|
||||||
|
if instance.power_state == power_state.PAUSED:
|
||||||
|
clean_shutdown = False
|
||||||
self._power_off_instance(context, instance, clean_shutdown)
|
self._power_off_instance(context, instance, clean_shutdown)
|
||||||
self.driver.snapshot(context, instance, image_id, update_task_state)
|
self.driver.snapshot(context, instance, image_id, update_task_state)
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from oslo_utils import timeutils
|
|||||||
|
|
||||||
from nova.compute import claims
|
from nova.compute import claims
|
||||||
from nova.compute import instance_actions
|
from nova.compute import instance_actions
|
||||||
|
from nova.compute import power_state
|
||||||
from nova.compute import task_states
|
from nova.compute import task_states
|
||||||
from nova.compute import utils as compute_utils
|
from nova.compute import utils as compute_utils
|
||||||
from nova.compute import vm_states
|
from nova.compute import vm_states
|
||||||
@ -59,12 +60,14 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||||||
def _shelve_instance(self, shelved_offload_time, mock_notify,
|
def _shelve_instance(self, shelved_offload_time, mock_notify,
|
||||||
mock_notify_instance_usage, mock_get_power_state,
|
mock_notify_instance_usage, mock_get_power_state,
|
||||||
mock_snapshot, mock_power_off, mock_terminate,
|
mock_snapshot, mock_power_off, mock_terminate,
|
||||||
mock_get_bdms, clean_shutdown=True):
|
mock_get_bdms, clean_shutdown=True,
|
||||||
|
guest_power_state=power_state.RUNNING):
|
||||||
mock_get_power_state.return_value = 123
|
mock_get_power_state.return_value = 123
|
||||||
|
|
||||||
CONF.set_override('shelved_offload_time', shelved_offload_time)
|
CONF.set_override('shelved_offload_time', shelved_offload_time)
|
||||||
host = 'fake-mini'
|
host = 'fake-mini'
|
||||||
instance = self._create_fake_instance_obj(params={'host': host})
|
instance = self._create_fake_instance_obj(
|
||||||
|
params={'host': host, 'power_state': guest_power_state})
|
||||||
image_id = 'fake_image_id'
|
image_id = 'fake_image_id'
|
||||||
host = 'fake-mini'
|
host = 'fake-mini'
|
||||||
self.useFixture(utils_fixture.TimeFixture())
|
self.useFixture(utils_fixture.TimeFixture())
|
||||||
@ -139,6 +142,9 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||||||
mock_cleanup_call_list = []
|
mock_cleanup_call_list = []
|
||||||
|
|
||||||
if clean_shutdown:
|
if clean_shutdown:
|
||||||
|
if guest_power_state == power_state.PAUSED:
|
||||||
|
mock_power_off_call_list.append(mock.call(instance, 0, 0))
|
||||||
|
else:
|
||||||
mock_power_off_call_list.append(
|
mock_power_off_call_list.append(
|
||||||
mock.call(instance, CONF.shutdown_timeout,
|
mock.call(instance, CONF.shutdown_timeout,
|
||||||
self.compute.SHUTDOWN_RETRY_INTERVAL))
|
self.compute.SHUTDOWN_RETRY_INTERVAL))
|
||||||
@ -179,6 +185,9 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||||||
def test_shelve_and_offload(self):
|
def test_shelve_and_offload(self):
|
||||||
self._shelve_instance(0)
|
self._shelve_instance(0)
|
||||||
|
|
||||||
|
def test_shelve_paused_instance(self):
|
||||||
|
self._shelve_instance(-1, guest_power_state=power_state.PAUSED)
|
||||||
|
|
||||||
@mock.patch.object(nova.virt.fake.SmallFakeDriver, 'power_off')
|
@mock.patch.object(nova.virt.fake.SmallFakeDriver, 'power_off')
|
||||||
def test_shelve_offload(self, mock_power_off):
|
def test_shelve_offload(self, mock_power_off):
|
||||||
instance = self._shelve_offload()
|
instance = self._shelve_offload()
|
||||||
|
Loading…
Reference in New Issue
Block a user