Make sure instance data is always refreshed

Fixes bug 1078793

When updating an instance's instance_type_id, the 'instance_type' joined
to the instance is not updated.  This updates that.  A DB API test is added
that failed before and passes now.

Also: Some cases of passing stale instance data within resize_instance()
and finish_resize() were found and addressed.

Change-Id: If335cc286a71597d3100425080e51c75aeec7a50
This commit is contained in:
Chris Behrens 2012-11-14 17:25:43 +00:00
parent 16266a4afb
commit 9fdf755277
3 changed files with 36 additions and 9 deletions

View File

@ -1837,9 +1837,9 @@ class ComputeManager(manager.SchedulerDependentManager):
migration['id'],
{'status': 'migrating'})
self._instance_update(context, instance['uuid'],
task_state=task_states.RESIZE_MIGRATING,
expected_task_state=task_states.RESIZE_PREP)
instance = self._instance_update(context, instance['uuid'],
task_state=task_states.RESIZE_MIGRATING,
expected_task_state=task_states.RESIZE_PREP)
self._notify_about_instance_usage(
context, instance, "resize.start", network_info=network_info)
@ -1861,11 +1861,11 @@ class ComputeManager(manager.SchedulerDependentManager):
migration['id'],
{'status': 'post-migrating'})
self._instance_update(context, instance['uuid'],
host=migration['dest_compute'],
task_state=task_states.RESIZE_MIGRATED,
expected_task_state=task_states.
RESIZE_MIGRATING)
instance = self._instance_update(context, instance['uuid'],
host=migration['dest_compute'],
task_state=task_states.RESIZE_MIGRATED,
expected_task_state=task_states.
RESIZE_MIGRATING)
self.compute_rpcapi.finish_resize(context, instance,
migration, image, disk_info,
@ -1910,7 +1910,7 @@ class ComputeManager(manager.SchedulerDependentManager):
network_info = self._get_instance_nw_info(context, instance)
self._instance_update(context, instance['uuid'],
instance = self._instance_update(context, instance['uuid'],
task_state=task_states.RESIZE_FINISH,
expected_task_state=task_states.RESIZE_MIGRATED)

View File

@ -1813,6 +1813,13 @@ def _instance_update(context, instance_uuid, values, copy_old_instance=False):
instance_ref.update(values)
instance_ref.save(session=session)
if 'instance_type_id' in values:
# NOTE(comstud): It appears that sqlalchemy doesn't refresh
# the instance_type model after you update the ID. You end
# up with an instance_type model that only has 'id' updated,
# but the rest of the model has the data from the old
# instance_type.
session.refresh(instance_ref['instance_type'])
return (old_instance_ref, instance_ref)

View File

@ -272,6 +272,26 @@ class DbApiTestCase(test.TestCase):
system_meta = db.instance_system_metadata_get(ctxt, instance.uuid)
self.assertEqual('baz', system_meta['original_image_ref'])
def test_instance_update_of_instance_type_id(self):
ctxt = context.get_admin_context()
inst_type1 = db.instance_type_get_by_name(ctxt, 'm1.tiny')
inst_type2 = db.instance_type_get_by_name(ctxt, 'm1.small')
values = {'instance_type_id': inst_type1['id']}
instance = db.instance_create(ctxt, values)
self.assertEqual(instance['instance_type']['id'], inst_type1['id'])
self.assertEqual(instance['instance_type']['name'],
inst_type1['name'])
values = {'instance_type_id': inst_type2['id']}
instance = db.instance_update(ctxt, instance['uuid'], values)
self.assertEqual(instance['instance_type']['id'], inst_type2['id'])
self.assertEqual(instance['instance_type']['name'],
inst_type2['name'])
def test_instance_update_with_and_get_original(self):
ctxt = context.get_admin_context()