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']
if kernel_uuid is None or kernel_uuid == '':
return
kernel_id = self._get_image_id(context, kernel_uuid)
result[key] = ec2utils.image_ec2_id(kernel_id, 'aki')
result[key] = ec2utils.glance_id_to_ec2_id(context, kernel_uuid, 'aki')
def _format_ramdisk_id(self, context, instance_ref, result, key):
ramdisk_uuid = instance_ref['ramdisk_id']
if ramdisk_uuid is None or ramdisk_uuid == '':
return
ramdisk_id = self._get_image_id(context, ramdisk_uuid)
result[key] = ec2utils.image_ec2_id(ramdisk_id, 'ari')
result[key] = ec2utils.glance_id_to_ec2_id(context, ramdisk_uuid,
'ari')
def describe_instance_attribute(self, context, instance_id, attribute,
**kwargs):
@ -1173,8 +1172,7 @@ class CloudController(object):
ec2_id = ec2utils.id_to_ec2_id(instance_id)
i['instanceId'] = ec2_id
image_uuid = instance['image_ref']
image_id = self._get_image_id(context, image_uuid)
i['imageId'] = ec2utils.image_ec2_id(image_id)
i['imageId'] = ec2utils.glance_id_to_ec2_id(context, image_uuid)
self._format_kernel_id(context, instance, i, 'kernelId')
self._format_ramdisk_id(context, instance, i, 'ramdiskId')
i['instanceState'] = _state_description(
@ -1287,16 +1285,17 @@ class CloudController(object):
max_count = int(kwargs.get('max_count', 1))
if kwargs.get('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'):
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'])
for bdm in kwargs.get('block_device_mapping', []):
_parse_block_device_mapping(bdm)
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:
image_state = self._get_image_state(image)
@ -1383,15 +1382,6 @@ class CloudController(object):
raise exception.ImageNotFound(image_id=ec2_id)
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):
"""Convert from format defined by GlanceImageService to S3 format."""
i = {}

View File

@ -18,6 +18,7 @@
import re
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
@ -46,6 +47,31 @@ def image_type(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):
"""Convert an ec2 ID (i-[base 16 number]) to an instance id (int)"""
try:

View File

@ -30,7 +30,6 @@ import boto.s3.connection
import eventlet
from nova import rpc
import nova.db.api
from nova import exception
from nova import flags
from nova import image
@ -65,35 +64,18 @@ class S3ImageService(object):
self.service = service or image.get_default_image_service()
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):
return [self._translate_uuid_to_id(context, img) for img in images]
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()
try:
image_id = image_copy['id']
image_uuid = image_copy['id']
except KeyError:
pass
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']:
try:
@ -101,7 +83,8 @@ class S3ImageService(object):
except (KeyError, ValueError):
pass
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
@ -113,7 +96,7 @@ class S3ImageService(object):
except KeyError:
pass
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']:
try:
@ -121,7 +104,7 @@ class S3ImageService(object):
except (KeyError, ValueError):
pass
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
return image_copy
@ -136,11 +119,11 @@ class S3ImageService(object):
return image
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)
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)
image = self.service.update(context, image_uuid, metadata, data)
return self._translate_uuid_to_id(context, image)
@ -158,7 +141,7 @@ class S3ImageService(object):
return self._translate_uuids_to_ids(context, images)
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)
return self._translate_uuid_to_id(context, image)
@ -241,8 +224,7 @@ class S3ImageService(object):
properties['architecture'] = arch
def _translate_dependent_image_id(image_key, image_id):
image_id = ec2utils.ec2_id_to_id(image_id)
image_uuid = self.get_image_uuid(context, image_id)
image_uuid = ec2utils.ec2_id_to_glance_id(context, image_id)
properties[image_key] = image_uuid
if kernel_id:
@ -269,7 +251,7 @@ class S3ImageService(object):
# extract the new uuid and generate an int id to present back to user
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 manifest, image, image_uuid