Avoid db lookup in info_from_instance().

The method info_from_instance() in nova.notifications was doing a db
lookup for the system_metadata for an instance.  This patch updates that
code to get that data from the instance that's passed in instead.  The
rest of the patch are related changes to make that happen.

metadata_to_dict() was needed here.  It lived in nova.compute.utils.
nova.compute.utils already imported nova.notifications, so using it from
there would have created a circular import.  Move the method to
nova.utils instead and update the tree to use it from its new location.

I also noticed that the xen driver had a copy of metdata_to_dict().
This patch removes it and uses the common implementation in nova.utils.

'system_metadata' was added to _extra_keys of the Instance db model so
that it would show up in a serialized instance.  Tests failed without it
as the result of getting instances via the conductor API did not include
system_metadata.  Now it's there.

Part of bp no-db-compute.

Change-Id: I451355fb26ae29f13b71438f7896c448b59f97b0
This commit is contained in:
Russell Bryant
2013-01-23 17:34:13 -05:00
parent 97a5274f5b
commit e2f2d10e1a
9 changed files with 31 additions and 40 deletions

View File

@@ -1132,8 +1132,7 @@ class ComputeManager(manager.SchedulerDependentManager):
vm_state=vm_states.DELETED,
task_state=None,
terminated_at=timeutils.utcnow())
system_meta = compute_utils.metadata_to_dict(
instance['system_metadata'])
system_meta = utils.metadata_to_dict(instance['system_metadata'])
self.conductor_api.instance_destroy(context, instance)
# ensure block device mappings are not leaked
@@ -1675,8 +1674,7 @@ class ComputeManager(manager.SchedulerDependentManager):
def _get_rescue_image_ref(self, context, instance):
"""Determine what image should be used to boot the rescue VM."""
system_meta = compute_utils.metadata_to_dict(
instance['system_metadata'])
system_meta = utils.metadata_to_dict(instance['system_metadata'])
rescue_image_ref = system_meta.get('image_base_image_ref')

View File

@@ -37,13 +37,6 @@ CONF.import_opt('host', 'nova.netconf')
LOG = log.getLogger(__name__)
def metadata_to_dict(metadata):
result = {}
for item in metadata:
result[item['key']] = item['value']
return result
def add_instance_fault_from_exc(context, instance, fault, exc_info=None):
"""Adds the specified fault to the database."""
@@ -159,7 +152,8 @@ def notify_usage_exists(context, instance_ref, current_period=False,
ignore_missing_network_data)
if system_metadata is None:
system_metadata = metadata_to_dict(instance_ref['system_metadata'])
system_metadata = utils.metadata_to_dict(
instance_ref['system_metadata'])
# add image metadata to the notification:
image_meta = notifications.image_meta(system_metadata)

View File

@@ -221,7 +221,7 @@ class Instance(BASE, NovaBase):
return base_name
def _extra_keys(self):
return ['name']
return ['name', 'system_metadata']
user_id = Column(String(255))
project_id = Column(String(255))

View File

@@ -283,12 +283,8 @@ def info_from_instance(context, instance_ref, network_info,
instance_type_name = instance_ref.get('instance_type', {}).get('name', '')
if system_metadata is None:
try:
system_metadata = db.instance_system_metadata_get(
context, instance_ref['uuid'])
except exception.NotFound:
system_metadata = {}
system_metadata = utils.metadata_to_dict(
instance_ref['system_metadata'])
instance_info = dict(
# Owner properties

View File

@@ -5287,7 +5287,7 @@ class ComputeAPITestCase(BaseTestCase):
_context = context.get_admin_context()
instance = self._create_fake_instance({'metadata': {'key1': 'value1'}})
instance = dict(instance)
instance = dict(instance.iteritems())
metadata = self.compute_api.get_instance_metadata(_context, instance)
self.assertEqual(metadata, {'key1': 'value1'})

View File

@@ -359,6 +359,9 @@ class UsageInfoTestCase(test.TestCase):
extra_usage_info = {'image_name': 'fake_name'}
db.instance_system_metadata_update(self.context, instance['uuid'],
sys_metadata, False)
# NOTE(russellb) Make sure our instance has the latest system_metadata
# in it.
instance = db.instance_get(self.context, instance_id)
compute_utils.notify_about_instance_usage(self.context, instance,
'create.start', extra_usage_info=extra_usage_info)
self.assertEquals(len(test_notifier.NOTIFICATIONS), 1)
@@ -382,14 +385,3 @@ class UsageInfoTestCase(test.TestCase):
image_ref_url = "%s/images/1" % glance.generate_glance_url()
self.assertEquals(payload['image_ref_url'], image_ref_url)
self.compute.terminate_instance(self.context, instance)
class MetadataToDictTestCase(test.TestCase):
def test_metadata_to_dict(self):
self.assertEqual(compute_utils.metadata_to_dict(
[{'key': 'foo1', 'value': 'bar'},
{'key': 'foo2', 'value': 'baz'}]),
{'foo1': 'bar', 'foo2': 'baz'})
def test_metadata_to_dict_empty(self):
self.assertEqual(compute_utils.metadata_to_dict([]), {})

View File

@@ -778,3 +778,14 @@ class IntLikeTestCase(test.TestCase):
self.assertFalse(
utils.is_int_like("0cc3346e-9fef-4445-abe6-5d2b2690ec64"))
self.assertFalse(utils.is_int_like("a1"))
class MetadataToDictTestCase(test.TestCase):
def test_metadata_to_dict(self):
self.assertEqual(utils.metadata_to_dict(
[{'key': 'foo1', 'value': 'bar'},
{'key': 'foo2', 'value': 'baz'}]),
{'foo1': 'bar', 'foo2': 'baz'})
def test_metadata_to_dict_empty(self):
self.assertEqual(utils.metadata_to_dict([]), {})

View File

@@ -1261,3 +1261,10 @@ def last_bytes(file_like_object, num):
remaining = file_like_object.tell()
return (file_like_object.read(), remaining)
def metadata_to_dict(metadata):
result = {}
for item in metadata:
result[item['key']] = item['value']
return result

View File

@@ -196,13 +196,6 @@ class ImageType(object):
}.get(image_type_id)
def _system_metadata_to_dict(system_metadata):
result = {}
for item in system_metadata:
result[item['key']] = item['value']
return result
def create_vm(session, instance, name_label, kernel, ramdisk,
use_pv_kernel=False):
"""Create a VM record. Returns new VM reference.
@@ -994,7 +987,7 @@ def _create_image(context, session, instance, name_label, image_id,
elif cache_images == 'all':
cache = True
elif cache_images == 'some':
sys_meta = _system_metadata_to_dict(instance['system_metadata'])
sys_meta = utils.metadata_to_dict(instance['system_metadata'])
try:
cache = utils.bool_from_str(sys_meta['image_cache_in_nova'])
except KeyError:
@@ -1087,7 +1080,7 @@ def _image_uses_bittorrent(context, instance):
if xenapi_torrent_images == 'all':
bittorrent = True
elif xenapi_torrent_images == 'some':
sys_meta = _system_metadata_to_dict(instance['system_metadata'])
sys_meta = utils.metadata_to_dict(instance['system_metadata'])
try:
bittorrent = utils.bool_from_str(sys_meta['image_bittorrent'])
except KeyError: