Refactor glance id<->internal id conversion for s3

* Moves nova.image.s3.S3ImageService functions for converting
   between glance ('image_uuid') and internal (db) ids to ec2utils:

       get_image_id => ec2utils.glance_id_to_id
       get_image_uuid => ec2utils.id_to_glance_id

 * Refactors ec2utils.glance_id_to_id to create a new S3Image
   object associating a glance id to an internal id if such a
   mapping does not already exist.  Previously, only calls to
   nova.api.ec2.cloud.CloudController.describe_images would
   add new mappings, but now any attempt to convert a glance id
   to an internal id will succeed, resolving bug 948286.

 * Adds 2 convenience methods to ec2utils, as per bcwaldon:

       ec2_id_to_glance_id
       glance_id_to_ec2_id

 * Since this is a strict refactor and only streamlines existing
   well-tested functionality, this change includes no new tests.

Change-Id: I810afe05223228df1bcc20a0ac688d8c62c472b4
This commit is contained in:
Maru Newby 2012-03-12 23:19:16 -07:00 committed by Brian Waldon
parent 094985ea65
commit 0929e3a289
3 changed files with 46 additions and 48 deletions

View File

@ -967,15 +967,14 @@ class CloudController(object):
kernel_uuid = instance_ref['kernel_id'] kernel_uuid = instance_ref['kernel_id']
if kernel_uuid is None or kernel_uuid == '': if kernel_uuid is None or kernel_uuid == '':
return return
kernel_id = self._get_image_id(context, kernel_uuid) result[key] = ec2utils.glance_id_to_ec2_id(context, kernel_uuid, 'aki')
result[key] = ec2utils.image_ec2_id(kernel_id, 'aki')
def _format_ramdisk_id(self, context, instance_ref, result, key): def _format_ramdisk_id(self, context, instance_ref, result, key):
ramdisk_uuid = instance_ref['ramdisk_id'] ramdisk_uuid = instance_ref['ramdisk_id']
if ramdisk_uuid is None or ramdisk_uuid == '': if ramdisk_uuid is None or ramdisk_uuid == '':
return return
ramdisk_id = self._get_image_id(context, ramdisk_uuid) result[key] = ec2utils.glance_id_to_ec2_id(context, ramdisk_uuid,
result[key] = ec2utils.image_ec2_id(ramdisk_id, 'ari') 'ari')
def describe_instance_attribute(self, context, instance_id, attribute, def describe_instance_attribute(self, context, instance_id, attribute,
**kwargs): **kwargs):
@ -1173,8 +1172,7 @@ class CloudController(object):
ec2_id = ec2utils.id_to_ec2_id(instance_id) ec2_id = ec2utils.id_to_ec2_id(instance_id)
i['instanceId'] = ec2_id i['instanceId'] = ec2_id
image_uuid = instance['image_ref'] image_uuid = instance['image_ref']
image_id = self._get_image_id(context, image_uuid) i['imageId'] = ec2utils.glance_id_to_ec2_id(context, image_uuid)
i['imageId'] = ec2utils.image_ec2_id(image_id)
self._format_kernel_id(context, instance, i, 'kernelId') self._format_kernel_id(context, instance, i, 'kernelId')
self._format_ramdisk_id(context, instance, i, 'ramdiskId') self._format_ramdisk_id(context, instance, i, 'ramdiskId')
i['instanceState'] = _state_description( i['instanceState'] = _state_description(
@ -1287,16 +1285,17 @@ class CloudController(object):
max_count = int(kwargs.get('max_count', 1)) max_count = int(kwargs.get('max_count', 1))
if kwargs.get('kernel_id'): if kwargs.get('kernel_id'):
kernel = self._get_image(context, kwargs['kernel_id']) kernel = self._get_image(context, kwargs['kernel_id'])
kwargs['kernel_id'] = self._get_image_uuid(context, kernel['id']) kwargs['kernel_id'] = ec2utils.id_to_glance_id(context,
kernel['id'])
if kwargs.get('ramdisk_id'): if kwargs.get('ramdisk_id'):
ramdisk = self._get_image(context, kwargs['ramdisk_id']) ramdisk = self._get_image(context, kwargs['ramdisk_id'])
kwargs['ramdisk_id'] = self._get_image_uuid(context, kwargs['ramdisk_id'] = ec2utils.id_to_glance_id(context,
ramdisk['id']) ramdisk['id'])
for bdm in kwargs.get('block_device_mapping', []): for bdm in kwargs.get('block_device_mapping', []):
_parse_block_device_mapping(bdm) _parse_block_device_mapping(bdm)
image = self._get_image(context, kwargs['image_id']) image = self._get_image(context, kwargs['image_id'])
image_uuid = self._get_image_uuid(context, image['id']) image_uuid = ec2utils.id_to_glance_id(context, image['id'])
if image: if image:
image_state = self._get_image_state(image) image_state = self._get_image_state(image)
@ -1383,15 +1382,6 @@ class CloudController(object):
raise exception.ImageNotFound(image_id=ec2_id) raise exception.ImageNotFound(image_id=ec2_id)
return image return image
# NOTE(bcwaldon): We need access to the image uuid since we directly
# call the compute api from this class
def _get_image_uuid(self, context, internal_id):
return self.image_service.get_image_uuid(context, internal_id)
# NOTE(bcwaldon): We also need to be able to map image uuids to integers
def _get_image_id(self, context, image_uuid):
return self.image_service.get_image_id(context, image_uuid)
def _format_image(self, image): def _format_image(self, image):
"""Convert from format defined by GlanceImageService to S3 format.""" """Convert from format defined by GlanceImageService to S3 format."""
i = {} i = {}

View File

@ -18,6 +18,7 @@
import re import re
from nova import db
from nova import exception from nova import exception
from nova import flags from nova import flags
from nova import log as logging from nova import log as logging
@ -46,6 +47,31 @@ def image_type(image_type):
return image_type return image_type
def id_to_glance_id(context, image_id):
"""Convert an internal (db) id to a glance id."""
return db.s3_image_get(context, image_id)['uuid']
def glance_id_to_id(context, glance_id):
"""Convert a glance id to an internal (db) id."""
if glance_id is None:
return
try:
return db.s3_image_get_by_uuid(context, glance_id)['id']
except exception.NotFound:
return db.s3_image_create(context, glance_id)['id']
def ec2_id_to_glance_id(context, ec2_id):
image_id = ec2_id_to_id(ec2_id)
return id_to_glance_id(context, image_id)
def glance_id_to_ec2_id(context, glance_id, image_type='ami'):
image_id = glance_id_to_id(context, glance_id)
return image_ec2_id(image_id, image_type=image_type)
def ec2_id_to_id(ec2_id): def ec2_id_to_id(ec2_id):
"""Convert an ec2 ID (i-[base 16 number]) to an instance id (int)""" """Convert an ec2 ID (i-[base 16 number]) to an instance id (int)"""
try: try:

View File

@ -30,7 +30,6 @@ import boto.s3.connection
import eventlet import eventlet
from nova import rpc from nova import rpc
import nova.db.api
from nova import exception from nova import exception
from nova import flags from nova import flags
from nova import image from nova import image
@ -65,35 +64,18 @@ class S3ImageService(object):
self.service = service or image.get_default_image_service() self.service = service or image.get_default_image_service()
self.service.__init__(*args, **kwargs) self.service.__init__(*args, **kwargs)
def get_image_uuid(self, context, image_id):
return nova.db.api.s3_image_get(context, image_id)['uuid']
def get_image_id(self, context, image_uuid):
return nova.db.api.s3_image_get_by_uuid(context, image_uuid)['id']
def _create_image_id(self, context, image_uuid):
return nova.db.api.s3_image_create(context, image_uuid)['id']
def _translate_uuids_to_ids(self, context, images): def _translate_uuids_to_ids(self, context, images):
return [self._translate_uuid_to_id(context, img) for img in images] return [self._translate_uuid_to_id(context, img) for img in images]
def _translate_uuid_to_id(self, context, image): def _translate_uuid_to_id(self, context, image):
def _find_or_create(image_uuid):
if image_uuid is None:
return
try:
return self.get_image_id(context, image_uuid)
except exception.NotFound:
return self._create_image_id(context, image_uuid)
image_copy = image.copy() image_copy = image.copy()
try: try:
image_id = image_copy['id'] image_uuid = image_copy['id']
except KeyError: except KeyError:
pass pass
else: else:
image_copy['id'] = _find_or_create(image_id) image_copy['id'] = ec2utils.glance_id_to_id(context, image_uuid)
for prop in ['kernel_id', 'ramdisk_id']: for prop in ['kernel_id', 'ramdisk_id']:
try: try:
@ -101,7 +83,8 @@ class S3ImageService(object):
except (KeyError, ValueError): except (KeyError, ValueError):
pass pass
else: else:
image_copy['properties'][prop] = _find_or_create(image_uuid) image_id = ec2utils.glance_id_to_id(context, image_uuid)
image_copy['properties'][prop] = image_id
return image_copy return image_copy
@ -113,7 +96,7 @@ class S3ImageService(object):
except KeyError: except KeyError:
pass pass
else: else:
image_copy['id'] = self.get_image_uuid(context, image_id) image_copy['id'] = ec2utils.id_to_glance_id(context, image_id)
for prop in ['kernel_id', 'ramdisk_id']: for prop in ['kernel_id', 'ramdisk_id']:
try: try:
@ -121,7 +104,7 @@ class S3ImageService(object):
except (KeyError, ValueError): except (KeyError, ValueError):
pass pass
else: else:
image_uuid = self.get_image_uuid(context, image_id) image_uuid = ec2utils.id_to_glance_id(context, image_id)
image_copy['properties'][prop] = image_uuid image_copy['properties'][prop] = image_uuid
return image_copy return image_copy
@ -136,11 +119,11 @@ class S3ImageService(object):
return image return image
def delete(self, context, image_id): def delete(self, context, image_id):
image_uuid = self.get_image_uuid(context, image_id) image_uuid = ec2utils.id_to_glance_id(context, image_id)
self.service.delete(context, image_uuid) self.service.delete(context, image_uuid)
def update(self, context, image_id, metadata, data=None): def update(self, context, image_id, metadata, data=None):
image_uuid = self.get_image_uuid(context, image_id) image_uuid = ec2utils.id_to_glance_id(context, image_id)
metadata = self._translate_id_to_uuid(context, metadata) metadata = self._translate_id_to_uuid(context, metadata)
image = self.service.update(context, image_uuid, metadata, data) image = self.service.update(context, image_uuid, metadata, data)
return self._translate_uuid_to_id(context, image) return self._translate_uuid_to_id(context, image)
@ -158,7 +141,7 @@ class S3ImageService(object):
return self._translate_uuids_to_ids(context, images) return self._translate_uuids_to_ids(context, images)
def show(self, context, image_id): def show(self, context, image_id):
image_uuid = self.get_image_uuid(context, image_id) image_uuid = ec2utils.id_to_glance_id(context, image_id)
image = self.service.show(context, image_uuid) image = self.service.show(context, image_uuid)
return self._translate_uuid_to_id(context, image) return self._translate_uuid_to_id(context, image)
@ -241,8 +224,7 @@ class S3ImageService(object):
properties['architecture'] = arch properties['architecture'] = arch
def _translate_dependent_image_id(image_key, image_id): def _translate_dependent_image_id(image_key, image_id):
image_id = ec2utils.ec2_id_to_id(image_id) image_uuid = ec2utils.ec2_id_to_glance_id(context, image_id)
image_uuid = self.get_image_uuid(context, image_id)
properties[image_key] = image_uuid properties[image_key] = image_uuid
if kernel_id: if kernel_id:
@ -269,7 +251,7 @@ class S3ImageService(object):
# extract the new uuid and generate an int id to present back to user # extract the new uuid and generate an int id to present back to user
image_uuid = image['id'] image_uuid = image['id']
image['id'] = self._create_image_id(context, image_uuid) image['id'] = ec2utils.glance_id_to_id(context, image_uuid)
# return image_uuid so the caller can still make use of image_service # return image_uuid so the caller can still make use of image_service
return manifest, image, image_uuid return manifest, image, image_uuid