Skip to content

Commit b3a26d6

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Raise InstanceFaultRollback for UnableToMigrateToSelf from _prep_resize" into stable/stein
2 parents 9d7003c + 1a11d5c commit b3a26d6

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

nova/compute/manager.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4370,8 +4370,12 @@ def _prep_resize(self, context, image, instance, instance_type,
43704370
# check driver whether support migrate to same host
43714371
if not self.driver.capabilities.get(
43724372
'supports_migrate_to_same_host', False):
4373-
raise exception.UnableToMigrateToSelf(
4374-
instance_id=instance.uuid, host=self.host)
4373+
# Raise InstanceFaultRollback so that the
4374+
# _error_out_instance_on_exception context manager in
4375+
# prep_resize will set the instance.vm_state properly.
4376+
raise exception.InstanceFaultRollback(
4377+
inner_exception=exception.UnableToMigrateToSelf(
4378+
instance_id=instance.uuid, host=self.host))
43754379

43764380
# NOTE(danms): Stash the new instance_type to avoid having to
43774381
# look it up in the database later
@@ -4445,8 +4449,13 @@ def prep_resize(self, context, image, instance, instance_type,
44454449
if node is None:
44464450
node = self._get_nodename(instance, refresh=True)
44474451

4448-
with self._error_out_instance_on_exception(context, instance), \
4449-
errors_out_migration_ctxt(migration):
4452+
# Pass instance_state=instance.vm_state because we can resize
4453+
# a STOPPED server and we don't want to set it back to ACTIVE
4454+
# in case _prep_resize fails.
4455+
instance_state = instance.vm_state
4456+
with self._error_out_instance_on_exception(
4457+
context, instance, instance_state=instance_state),\
4458+
errors_out_migration_ctxt(migration):
44504459
self._send_prep_resize_notifications(
44514460
context, instance, fields.NotificationPhase.START,
44524461
instance_type)

nova/tests/unit/compute/test_compute_mgr.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8850,6 +8850,68 @@ def doit(mock_pr, mock_r):
88508850

88518851
doit()
88528852

8853+
def test_prep_resize_fails_unable_to_migrate_to_self(self):
8854+
"""Asserts that _prep_resize handles UnableToMigrateToSelf when
8855+
_prep_resize is called on the host on which the instance lives and
8856+
the flavor is not changing.
8857+
"""
8858+
instance = fake_instance.fake_instance_obj(
8859+
self.context, host=self.compute.host,
8860+
expected_attrs=['system_metadata', 'flavor'])
8861+
migration = mock.MagicMock(spec='nova.objects.Migration')
8862+
with mock.patch.dict(self.compute.driver.capabilities,
8863+
{'supports_migrate_to_same_host': False}):
8864+
ex = self.assertRaises(
8865+
exception.InstanceFaultRollback, self.compute._prep_resize,
8866+
self.context, instance.image_meta, instance, instance.flavor,
8867+
filter_properties={}, node=instance.node, migration=migration)
8868+
self.assertIsInstance(
8869+
ex.inner_exception, exception.UnableToMigrateToSelf)
8870+
8871+
@mock.patch('nova.compute.utils.notify_usage_exists')
8872+
@mock.patch('nova.compute.manager.ComputeManager.'
8873+
'_notify_about_instance_usage')
8874+
@mock.patch('nova.compute.utils.notify_about_resize_prep_instance')
8875+
@mock.patch('nova.objects.Instance.save')
8876+
@mock.patch('nova.compute.manager.ComputeManager._revert_allocation')
8877+
@mock.patch('nova.compute.manager.ComputeManager.'
8878+
'_reschedule_resize_or_reraise')
8879+
@mock.patch('nova.compute.utils.add_instance_fault_from_exc')
8880+
def test_prep_resize_fails_rollback(
8881+
self, add_instance_fault_from_exc, _reschedule_resize_or_reraise,
8882+
_revert_allocation, mock_instance_save,
8883+
notify_about_resize_prep_instance, _notify_about_instance_usage,
8884+
notify_usage_exists):
8885+
"""Tests that if _prep_resize raises InstanceFaultRollback, the
8886+
instance.vm_state is reset properly in _error_out_instance_on_exception
8887+
"""
8888+
instance = fake_instance.fake_instance_obj(
8889+
self.context, host=self.compute.host, vm_state=vm_states.STOPPED,
8890+
expected_attrs=['system_metadata', 'flavor'])
8891+
migration = mock.MagicMock(spec='nova.objects.Migration')
8892+
request_spec = mock.MagicMock(spec='nova.objects.RequestSpec')
8893+
ex = exception.InstanceFaultRollback(
8894+
inner_exception=exception.UnableToMigrateToSelf(
8895+
instance_id=instance.uuid, host=instance.host))
8896+
8897+
def fake_reschedule_resize_or_reraise(*args, **kwargs):
8898+
raise ex
8899+
8900+
_reschedule_resize_or_reraise.side_effect = (
8901+
fake_reschedule_resize_or_reraise)
8902+
8903+
with mock.patch.object(self.compute, '_prep_resize', side_effect=ex):
8904+
self.assertRaises(
8905+
# _error_out_instance_on_exception should reraise the
8906+
# UnableToMigrateToSelf inside InstanceFaultRollback.
8907+
exception.UnableToMigrateToSelf, self.compute.prep_resize,
8908+
self.context, instance.image_meta, instance, instance.flavor,
8909+
request_spec, filter_properties={}, node=instance.node,
8910+
clean_shutdown=True, migration=migration, host_list=[])
8911+
# The instance.vm_state should remain unchanged
8912+
# (_error_out_instance_on_exception will set to ACTIVE by default).
8913+
self.assertEqual(vm_states.STOPPED, instance.vm_state)
8914+
88538915
def test_get_updated_nw_info_with_pci_mapping(self):
88548916
old_dev = objects.PciDevice(address='0000:04:00.2')
88558917
new_dev = objects.PciDevice(address='0000:05:00.3')

nova/tests/unit/fake_instance.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ def fake_instance_obj(context, obj_instance_class=None, **updates):
132132
inst.vcpus = flavor.vcpus
133133
if 'memory_mb' in flavor and 'memory_mb' not in updates:
134134
inst.memory_mb = flavor.memory_mb
135+
if ('instance_type_id' not in inst or inst.instance_type_id is None
136+
and 'id' in flavor):
137+
inst.instance_type_id = flavor.id
135138
inst.old_flavor = None
136139
inst.new_flavor = None
137140
inst.obj_reset_changes()

0 commit comments

Comments
 (0)