diff --git a/nova/tests/unit/test_utils.py b/nova/tests/unit/test_utils.py index 7a664030f321..23d06f11a416 100644 --- a/nova/tests/unit/test_utils.py +++ b/nova/tests/unit/test_utils.py @@ -831,6 +831,24 @@ class GetSystemMetadataFromImageTestCase(test.NoDBTestCase): sys_key = "%s%s" % (utils.SM_IMAGE_PROP_PREFIX, key) self.assertEqual(sys_meta[sys_key], expected) + def test_skip_image_properties(self): + image = self.get_image() + image["properties"] = { + "foo1": "bar", "foo2": "baz", + "mappings": "wizz", "img_block_device_mapping": "eek", + } + + sys_meta = utils.get_system_metadata_from_image(image) + + # Verify that we inherit all the image properties + for key, expected in six.iteritems(image["properties"]): + sys_key = "%s%s" % (utils.SM_IMAGE_PROP_PREFIX, key) + + if key in utils.SM_SKIP_KEYS: + self.assertNotIn(sys_key, sys_meta) + else: + self.assertEqual(sys_meta[sys_key], expected) + def test_vhd_min_disk_image(self): image = self.get_image() flavor = self.get_flavor() @@ -873,6 +891,8 @@ class GetImageFromSystemMetadataTestCase(test.NoDBTestCase): sys_meta = self.get_system_metadata() sys_meta["%soo1" % utils.SM_IMAGE_PROP_PREFIX] = "bar" sys_meta["%soo2" % utils.SM_IMAGE_PROP_PREFIX] = "baz" + sys_meta["%simg_block_device_mapping" % + utils.SM_IMAGE_PROP_PREFIX] = "eek" image = utils.get_image_from_system_metadata(sys_meta) @@ -888,6 +908,8 @@ class GetImageFromSystemMetadataTestCase(test.NoDBTestCase): sys_key = "%s%s" % (utils.SM_IMAGE_PROP_PREFIX, key) self.assertEqual(image["properties"][key], sys_meta[sys_key]) + self.assertNotIn("img_block_device_mapping", image["properties"]) + def test_dont_inherit_empty_values(self): sys_meta = self.get_system_metadata() diff --git a/nova/utils.py b/nova/utils.py index a57356c24cd3..264b44b2bea6 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -160,6 +160,15 @@ SM_IMAGE_PROP_PREFIX = "image_" SM_INHERITABLE_KEYS = ( 'min_ram', 'min_disk', 'disk_format', 'container_format', ) +# Keys which hold large structured data that won't fit in the +# size constraints of the system_metadata table, so we avoid +# storing and/or loading them. +SM_SKIP_KEYS = ( + # Legacy names + 'mappings', 'block_device_mapping', + # Modern names + 'img_mappings', 'img_block_device_mapping', +) def vpn_ping(address, port, timeout=0.05, session_id=None): @@ -1103,6 +1112,9 @@ def get_system_metadata_from_image(image_meta, flavor=None): prefix_format = SM_IMAGE_PROP_PREFIX + '%s' for key, value in six.iteritems(image_meta.get('properties', {})): + if key in SM_SKIP_KEYS: + continue + new_value = safe_truncate(six.text_type(value), 255) system_meta[prefix_format % key] = new_value @@ -1139,6 +1151,9 @@ def get_image_from_system_metadata(system_meta): if key.startswith(SM_IMAGE_PROP_PREFIX): key = key[len(SM_IMAGE_PROP_PREFIX):] + if key in SM_SKIP_KEYS: + continue + if key in SM_INHERITABLE_KEYS: image_meta[key] = value else: