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
7365232f56
commit
e0534442b5
|
@ -4323,7 +4323,11 @@ class ComputeManager(manager.Manager):
|
|||
expected_state = shelving_state_map[expected_state]
|
||||
instance.task_state = task_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.driver.snapshot(context, instance, image_id, update_task_state)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ from oslo_utils import fixture as utils_fixture
|
|||
from oslo_utils import timeutils
|
||||
|
||||
from nova.compute import claims
|
||||
from nova.compute import power_state
|
||||
from nova.compute import task_states
|
||||
from nova.compute import vm_states
|
||||
import nova.conf
|
||||
|
@ -55,12 +56,14 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||
def _shelve_instance(self, shelved_offload_time, mock_notify,
|
||||
mock_notify_instance_usage, mock_get_power_state,
|
||||
mock_snapshot, mock_power_off, mock_terminate,
|
||||
clean_shutdown=True):
|
||||
clean_shutdown=True,
|
||||
guest_power_state=power_state.RUNNING):
|
||||
mock_get_power_state.return_value = 123
|
||||
|
||||
CONF.set_override('shelved_offload_time', shelved_offload_time)
|
||||
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'
|
||||
host = 'fake-mini'
|
||||
self.useFixture(utils_fixture.TimeFixture())
|
||||
|
@ -130,9 +133,12 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||
mock_cleanup_call_list = []
|
||||
|
||||
if clean_shutdown:
|
||||
mock_power_off_call_list.append(
|
||||
mock.call(instance, CONF.shutdown_timeout,
|
||||
self.compute.SHUTDOWN_RETRY_INTERVAL))
|
||||
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.call(instance, CONF.shutdown_timeout,
|
||||
self.compute.SHUTDOWN_RETRY_INTERVAL))
|
||||
else:
|
||||
mock_power_off_call_list.append(mock.call(instance, 0, 0))
|
||||
|
||||
|
@ -170,6 +176,9 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||
def test_shelve_and_offload(self):
|
||||
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')
|
||||
def test_shelve_offload(self, mock_power_off):
|
||||
instance = self._shelve_offload()
|
||||
|
|
Loading…
Reference in New Issue