From 9fdf7552779d518af9cda4e366bf81fddb0cb6f2 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 14 Nov 2012 17:25:43 +0000 Subject: 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 --- nova/compute/manager.py | 18 +++++++++--------- nova/db/sqlalchemy/api.py | 7 +++++++ nova/tests/test_db_api.py | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) (limited to 'nova') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index be20c7a40..a5084d6fe 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -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) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 007e83cbe..3cba27c1e 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -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) diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py index 39d3e1b1f..31d1b01b2 100644 --- a/nova/tests/test_db_api.py +++ b/nova/tests/test_db_api.py @@ -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() -- cgit