Merge "Raise InstanceFaultRollback for UnableToMigrateToSelf from _prep_resize" into stable/stein
This commit is contained in:
@@ -4370,8 +4370,12 @@ class ComputeManager(manager.Manager):
|
||||
# check driver whether support migrate to same host
|
||||
if not self.driver.capabilities.get(
|
||||
'supports_migrate_to_same_host', False):
|
||||
raise exception.UnableToMigrateToSelf(
|
||||
instance_id=instance.uuid, host=self.host)
|
||||
# Raise InstanceFaultRollback so that the
|
||||
# _error_out_instance_on_exception context manager in
|
||||
# prep_resize will set the instance.vm_state properly.
|
||||
raise exception.InstanceFaultRollback(
|
||||
inner_exception=exception.UnableToMigrateToSelf(
|
||||
instance_id=instance.uuid, host=self.host))
|
||||
|
||||
# NOTE(danms): Stash the new instance_type to avoid having to
|
||||
# look it up in the database later
|
||||
@@ -4445,8 +4449,13 @@ class ComputeManager(manager.Manager):
|
||||
if node is None:
|
||||
node = self._get_nodename(instance, refresh=True)
|
||||
|
||||
with self._error_out_instance_on_exception(context, instance), \
|
||||
errors_out_migration_ctxt(migration):
|
||||
# Pass instance_state=instance.vm_state because we can resize
|
||||
# a STOPPED server and we don't want to set it back to ACTIVE
|
||||
# in case _prep_resize fails.
|
||||
instance_state = instance.vm_state
|
||||
with self._error_out_instance_on_exception(
|
||||
context, instance, instance_state=instance_state),\
|
||||
errors_out_migration_ctxt(migration):
|
||||
self._send_prep_resize_notifications(
|
||||
context, instance, fields.NotificationPhase.START,
|
||||
instance_type)
|
||||
|
||||
@@ -8850,6 +8850,68 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase,
|
||||
|
||||
doit()
|
||||
|
||||
def test_prep_resize_fails_unable_to_migrate_to_self(self):
|
||||
"""Asserts that _prep_resize handles UnableToMigrateToSelf when
|
||||
_prep_resize is called on the host on which the instance lives and
|
||||
the flavor is not changing.
|
||||
"""
|
||||
instance = fake_instance.fake_instance_obj(
|
||||
self.context, host=self.compute.host,
|
||||
expected_attrs=['system_metadata', 'flavor'])
|
||||
migration = mock.MagicMock(spec='nova.objects.Migration')
|
||||
with mock.patch.dict(self.compute.driver.capabilities,
|
||||
{'supports_migrate_to_same_host': False}):
|
||||
ex = self.assertRaises(
|
||||
exception.InstanceFaultRollback, self.compute._prep_resize,
|
||||
self.context, instance.image_meta, instance, instance.flavor,
|
||||
filter_properties={}, node=instance.node, migration=migration)
|
||||
self.assertIsInstance(
|
||||
ex.inner_exception, exception.UnableToMigrateToSelf)
|
||||
|
||||
@mock.patch('nova.compute.utils.notify_usage_exists')
|
||||
@mock.patch('nova.compute.manager.ComputeManager.'
|
||||
'_notify_about_instance_usage')
|
||||
@mock.patch('nova.compute.utils.notify_about_resize_prep_instance')
|
||||
@mock.patch('nova.objects.Instance.save')
|
||||
@mock.patch('nova.compute.manager.ComputeManager._revert_allocation')
|
||||
@mock.patch('nova.compute.manager.ComputeManager.'
|
||||
'_reschedule_resize_or_reraise')
|
||||
@mock.patch('nova.compute.utils.add_instance_fault_from_exc')
|
||||
def test_prep_resize_fails_rollback(
|
||||
self, add_instance_fault_from_exc, _reschedule_resize_or_reraise,
|
||||
_revert_allocation, mock_instance_save,
|
||||
notify_about_resize_prep_instance, _notify_about_instance_usage,
|
||||
notify_usage_exists):
|
||||
"""Tests that if _prep_resize raises InstanceFaultRollback, the
|
||||
instance.vm_state is reset properly in _error_out_instance_on_exception
|
||||
"""
|
||||
instance = fake_instance.fake_instance_obj(
|
||||
self.context, host=self.compute.host, vm_state=vm_states.STOPPED,
|
||||
expected_attrs=['system_metadata', 'flavor'])
|
||||
migration = mock.MagicMock(spec='nova.objects.Migration')
|
||||
request_spec = mock.MagicMock(spec='nova.objects.RequestSpec')
|
||||
ex = exception.InstanceFaultRollback(
|
||||
inner_exception=exception.UnableToMigrateToSelf(
|
||||
instance_id=instance.uuid, host=instance.host))
|
||||
|
||||
def fake_reschedule_resize_or_reraise(*args, **kwargs):
|
||||
raise ex
|
||||
|
||||
_reschedule_resize_or_reraise.side_effect = (
|
||||
fake_reschedule_resize_or_reraise)
|
||||
|
||||
with mock.patch.object(self.compute, '_prep_resize', side_effect=ex):
|
||||
self.assertRaises(
|
||||
# _error_out_instance_on_exception should reraise the
|
||||
# UnableToMigrateToSelf inside InstanceFaultRollback.
|
||||
exception.UnableToMigrateToSelf, self.compute.prep_resize,
|
||||
self.context, instance.image_meta, instance, instance.flavor,
|
||||
request_spec, filter_properties={}, node=instance.node,
|
||||
clean_shutdown=True, migration=migration, host_list=[])
|
||||
# The instance.vm_state should remain unchanged
|
||||
# (_error_out_instance_on_exception will set to ACTIVE by default).
|
||||
self.assertEqual(vm_states.STOPPED, instance.vm_state)
|
||||
|
||||
def test_get_updated_nw_info_with_pci_mapping(self):
|
||||
old_dev = objects.PciDevice(address='0000:04:00.2')
|
||||
new_dev = objects.PciDevice(address='0000:05:00.3')
|
||||
|
||||
@@ -132,6 +132,9 @@ def fake_instance_obj(context, obj_instance_class=None, **updates):
|
||||
inst.vcpus = flavor.vcpus
|
||||
if 'memory_mb' in flavor and 'memory_mb' not in updates:
|
||||
inst.memory_mb = flavor.memory_mb
|
||||
if ('instance_type_id' not in inst or inst.instance_type_id is None
|
||||
and 'id' in flavor):
|
||||
inst.instance_type_id = flavor.id
|
||||
inst.old_flavor = None
|
||||
inst.new_flavor = None
|
||||
inst.obj_reset_changes()
|
||||
|
||||
Reference in New Issue
Block a user