Merge "Update nova's copy of image metadata on rebuild"
This commit is contained in:
@@ -1349,6 +1349,32 @@ class API(BaseAPI):
|
||||
if instance_type['root_gb'] < int(image.get('min_disk') or 0):
|
||||
raise exception.InstanceTypeDiskTooSmall()
|
||||
|
||||
def _reset_image_metadata():
|
||||
"""
|
||||
Remove old image properties that we're storing as instance
|
||||
system metadata. These properties start with 'image_'.
|
||||
Then add the properites for the new image.
|
||||
"""
|
||||
|
||||
# FIXME(comstud): There's a race condition here in that
|
||||
# if the system_metadata for this instance is updated
|
||||
# after we do the get and before we update.. those other
|
||||
# updates will be lost. Since this problem exists in a lot
|
||||
# of other places, I think it should be addressed in a DB
|
||||
# layer overhaul.
|
||||
sys_metadata = self.db.instance_system_metadata_get(context,
|
||||
instance['uuid'])
|
||||
# Remove the old keys
|
||||
for key in sys_metadata.keys():
|
||||
if key.startswith('image_'):
|
||||
del sys_metadata[key]
|
||||
# Add the new ones
|
||||
for key, value in image['properties'].iteritems():
|
||||
new_value = str(value)[:255]
|
||||
sys_metadata['image_%s' % key] = new_value
|
||||
self.db.instance_system_metadata_update(context,
|
||||
instance['uuid'], sys_metadata, True)
|
||||
|
||||
self.update(context,
|
||||
instance,
|
||||
vm_state=vm_states.REBUILDING,
|
||||
@@ -1359,6 +1385,11 @@ class API(BaseAPI):
|
||||
progress=0,
|
||||
**kwargs)
|
||||
|
||||
# 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()
|
||||
|
||||
rebuild_params = {
|
||||
"new_pass": admin_password,
|
||||
"injected_files": files_to_inject,
|
||||
|
||||
@@ -115,7 +115,7 @@ class BaseTestCase(test.TestCase):
|
||||
test_notifier.NOTIFICATIONS = []
|
||||
|
||||
def fake_show(meh, context, id):
|
||||
return {'id': 1, 'min_disk': None, 'min_ram': None,
|
||||
return {'id': id, 'min_disk': None, 'min_ram': None,
|
||||
'properties': {'kernel_id': 'fake_kernel_id',
|
||||
'ramdisk_id': 'fake_ramdisk_id',
|
||||
'something_else': 'meow'}}
|
||||
@@ -2307,6 +2307,15 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
|
||||
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||
self.assertEqual(instance['task_state'], None)
|
||||
# Set some image metadata that should get wiped out and reset
|
||||
# as well as some other metadata that should be preserved.
|
||||
db.instance_system_metadata_update(self.context, instance_uuid,
|
||||
{'image_kernel_id': 'old-data',
|
||||
'image_ramdisk_id': 'old_data',
|
||||
'image_something_else': 'old-data',
|
||||
'image_should_remove': 'bye-bye',
|
||||
'preserved': 'preserve this!'},
|
||||
True)
|
||||
|
||||
# Make sure Compute API updates the image_ref before casting to
|
||||
# compute manager.
|
||||
@@ -2327,7 +2336,13 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
|
||||
instance = db.instance_get_by_uuid(self.context, instance_uuid)
|
||||
self.assertEqual(instance['vm_state'], vm_states.REBUILDING)
|
||||
|
||||
sys_metadata = db.instance_system_metadata_get(self.context,
|
||||
instance_uuid)
|
||||
self.assertEqual(sys_metadata,
|
||||
{'image_kernel_id': 'fake_kernel_id',
|
||||
'image_ramdisk_id': 'fake_ramdisk_id',
|
||||
'image_something_else': 'meow',
|
||||
'preserved': 'preserve this!'})
|
||||
db.instance_destroy(self.context, instance['id'])
|
||||
|
||||
def test_reboot_soft(self):
|
||||
|
||||
Reference in New Issue
Block a user