diff --git a/nova/compute/api.py b/nova/compute/api.py index fa413fdb10..677c8d0e94 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1292,6 +1292,7 @@ class API(base.Base): # layer overhaul. sys_metadata = self.db.instance_system_metadata_get(context, instance['uuid']) + orig_sys_metadata = dict(sys_metadata) # Remove the old keys for key in sys_metadata.keys(): if key.startswith('image_'): @@ -1302,6 +1303,7 @@ class API(base.Base): sys_metadata['image_%s' % key] = new_value self.db.instance_system_metadata_update(context, instance['uuid'], sys_metadata, True) + return orig_sys_metadata instance = self.update(context, instance, task_state=task_states.REBUILDING, @@ -1313,11 +1315,12 @@ class API(base.Base): # On a rebuild, since we're potentially changing images, we need to # wipe out the old image properties that we're storing as instance # system metadata... and copy in the properties for the new image. - _reset_image_metadata() + orig_sys_metadata = _reset_image_metadata() self.compute_rpcapi.rebuild_instance(context, instance=instance, new_pass=admin_password, injected_files=files_to_inject, - image_ref=image_href, orig_image_ref=orig_image_ref) + image_ref=image_href, orig_image_ref=orig_image_ref, + orig_sys_metadata=orig_sys_metadata) @wrap_check_policy @check_instance_lock diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f6acefc3ff..1d864e267e 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -213,7 +213,7 @@ def _get_image_meta(context, image_ref): class ComputeManager(manager.SchedulerDependentManager): """Manages the running instances from creation to destruction.""" - RPC_API_VERSION = '2.0' + RPC_API_VERSION = '2.1' def __init__(self, compute_driver=None, *args, **kwargs): """Load configuration options and connect to the hypervisor.""" @@ -968,9 +968,8 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @reverts_task_state @wrap_instance_fault - def rebuild_instance(self, context, instance, - orig_image_ref, image_ref, - injected_files, new_pass): + def rebuild_instance(self, context, instance, orig_image_ref, image_ref, + injected_files, new_pass, orig_sys_metadata=None): """Destroy and re-make this instance. A 'rebuild' effectively purges all existing data from the system and @@ -982,6 +981,7 @@ class ComputeManager(manager.SchedulerDependentManager): :param image_ref: New image_ref for rebuild :param injected_files: Files to inject :param new_pass: password to set on rebuilt instance + :param orig_sys_metadata: instance system metadata from pre-rebuild """ context = context.elevated() with self._error_out_instance_on_exception(context, instance['uuid']): @@ -996,7 +996,8 @@ class ComputeManager(manager.SchedulerDependentManager): orig_image_ref_url = utils.generate_image_url(orig_image_ref) extra_usage_info = {'image_ref_url': orig_image_ref_url} compute_utils.notify_usage_exists(context, instance, - current_period=True, extra_usage_info=extra_usage_info) + current_period=True, system_metadata=orig_sys_metadata, + extra_usage_info=extra_usage_info) # This message should contain the new image_ref extra_usage_info = {'image_name': image_meta['name']} diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py index 328351c35e..24576881f2 100644 --- a/nova/compute/rpcapi.py +++ b/nova/compute/rpcapi.py @@ -127,9 +127,10 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): 1.44 - Adds reserve_block_device_name() 2.0 - Remove 1.x backwards compat + 2.1 - Adds orig_sys_metadata to rebuild() ''' - BASE_RPC_API_VERSION = '2.0' + BASE_RPC_API_VERSION = '2.1' def __init__(self): super(ComputeAPI, self).__init__( @@ -332,12 +333,13 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): topic=_compute_topic(self.topic, ctxt, None, instance)) def rebuild_instance(self, ctxt, instance, new_pass, injected_files, - image_ref, orig_image_ref): + image_ref, orig_image_ref, orig_sys_metadata): instance_p = jsonutils.to_primitive(instance) self.cast(ctxt, self.make_msg('rebuild_instance', instance=instance_p, new_pass=new_pass, injected_files=injected_files, image_ref=image_ref, - orig_image_ref=orig_image_ref), + orig_image_ref=orig_image_ref, + orig_sys_metadata=orig_sys_metadata), topic=_compute_topic(self.topic, ctxt, None, instance)) def refresh_provider_fw_rules(self, ctxt, host): diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 13fa4b6444..35d3f54497 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -663,14 +663,16 @@ class ComputeTestCase(BaseTestCase): """Ensure instance can be rebuilt""" instance = jsonutils.to_primitive(self._create_fake_instance()) image_ref = instance['image_ref'] - + sys_metadata = db.instance_system_metadata_get(self.context, + instance['uuid']) self.compute.run_instance(self.context, instance=instance) db.instance_update(self.context, instance['uuid'], {"task_state": task_states.REBUILDING}) self.compute.rebuild_instance(self.context, instance, image_ref, image_ref, injected_files=[], - new_pass="new_password") + new_pass="new_password", + orig_sys_metadata=sys_metadata) self.compute.terminate_instance(self.context, instance=instance) def test_rebuild_launch_time(self): @@ -1389,7 +1391,8 @@ class ComputeTestCase(BaseTestCase): test_notifier.NOTIFICATIONS = [] instance = db.instance_get_by_uuid(self.context, inst_ref['uuid']) - + orig_sys_metadata = db.instance_system_metadata_get(self.context, + inst_ref['uuid']) image_ref = instance["image_ref"] new_image_ref = image_ref + '-new_image_ref' db.instance_update(self.context, inst_ref['uuid'], @@ -1405,7 +1408,8 @@ class ComputeTestCase(BaseTestCase): jsonutils.to_primitive(instance), image_ref, new_image_ref, injected_files=[], - new_pass=password) + new_pass=password, + orig_sys_metadata=orig_sys_metadata) instance = db.instance_get_by_uuid(self.context, inst_ref['uuid']) @@ -4256,7 +4260,8 @@ class ComputeAPITestCase(BaseTestCase): rpc.cast(self.context, topic, {"method": "refresh_instance_security_rules", "args": {'instance': jsonutils.to_primitive(instance)}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}) + "version": + compute_rpcapi.SecurityGroupAPI.BASE_RPC_API_VERSION}) self.mox.ReplayAll() self.security_group_api.trigger_members_refresh(self.context, [1]) @@ -4284,7 +4289,8 @@ class ComputeAPITestCase(BaseTestCase): rpc.cast(self.context, topic, {"method": "refresh_instance_security_rules", "args": {'instance': jsonutils.to_primitive(instance)}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}) + "version": + compute_rpcapi.SecurityGroupAPI.BASE_RPC_API_VERSION}) self.mox.ReplayAll() self.security_group_api.trigger_members_refresh(self.context, [1, 2]) @@ -4324,7 +4330,8 @@ class ComputeAPITestCase(BaseTestCase): rpc.cast(self.context, topic, {"method": "refresh_instance_security_rules", "args": {'instance': jsonutils.to_primitive(instance)}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}) + "version": + compute_rpcapi.SecurityGroupAPI.BASE_RPC_API_VERSION}) self.mox.ReplayAll() self.security_group_api.trigger_rules_refresh(self.context, [1]) @@ -4344,7 +4351,8 @@ class ComputeAPITestCase(BaseTestCase): rpc.cast(self.context, topic, {"method": "refresh_instance_security_rules", "args": {'instance': jsonutils.to_primitive(instance)}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}) + "version": + compute_rpcapi.SecurityGroupAPI.BASE_RPC_API_VERSION}) self.mox.ReplayAll() self.security_group_api.trigger_rules_refresh(self.context, [1, 2]) diff --git a/nova/tests/compute/test_rpcapi.py b/nova/tests/compute/test_rpcapi.py index 1dde75fbc1..eb78a53e75 100644 --- a/nova/tests/compute/test_rpcapi.py +++ b/nova/tests/compute/test_rpcapi.py @@ -226,7 +226,8 @@ class ComputeRpcAPITestCase(test.TestCase): self._test_compute_api('rebuild_instance', 'cast', instance=self.fake_instance, new_pass='pass', injected_files='files', image_ref='ref', - orig_image_ref='orig_ref') + orig_image_ref='orig_ref', + orig_sys_metadata='orig_sys_metadata') def test_reserve_block_device_name(self): self._test_compute_api('reserve_block_device_name', 'call',