On rebuild, the compute.instance.exists

notification should contain the original image
metadata.

In order to do this, the original system metadata associated
with the instance is preserved and passed along to the
rebuild_instance() in the compute manager.

(Code originally from Iccha Sethi and Rick Harris.)

bug 1044008

Change-Id: Ieb60a2871a2a209ef467e2b51dab375872649a18
This commit is contained in:
Rick Harris 2012-05-03 22:30:32 +00:00 committed by Brian Elliott
parent 0318efe625
commit ce4dbbd7d5
5 changed files with 34 additions and 19 deletions

View File

@ -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

View File

@ -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']}

View File

@ -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):

View File

@ -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])

View File

@ -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',