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:
parent
094985ea65
commit
0929e3a289
@ -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 = {}
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user