summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-06-10 20:48:16 +0000
committerGerrit Code Review <review@openstack.org>2012-06-10 20:48:16 +0000
commitc952a8cb1bb775aef5eb6fd10aad81cdd445d01b (patch)
treebb3a8fcc0f061d40eb01e803962e37ac43effb2c
parent168a8a15bea6ee755219f9471ac790e40942e77d (diff)
parent6e83d7869b2492c56ac540a5702314a504b75064 (diff)
Merge changes Ic1378da2,I0f279ce6
* changes: Rename image to image_id. Avoid partially finished cache files.
-rw-r--r--nova/exception.py2
-rw-r--r--nova/virt/xenapi/vm_utils.py87
2 files changed, 55 insertions, 34 deletions
diff --git a/nova/exception.py b/nova/exception.py
index 5904a0014..940a5a410 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -1093,7 +1093,7 @@ class InvalidInstanceIDMalformed(Invalid):
class CouldNotFetchImage(NovaException):
- message = _("Could not fetch image %(image)s")
+ message = _("Could not fetch image %(image_id)s")
def get_context_from_function_and_args(function, args, kwargs):
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index e7fc20639..69478d34f 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -98,7 +98,7 @@ MBR_SIZE_BYTES = MBR_SIZE_SECTORS * SECTOR_SIZE
KERNEL_DIR = '/boot/guest'
-class ImageType:
+class ImageType(object):
"""Enumeration class for distinguishing different image types
| 0 - kernel image (goes on dom0's filesystem)
@@ -413,9 +413,25 @@ def get_sr_path(session):
def find_cached_image(session, image_id, sr_ref):
"""Returns the vdi-ref of the cached image."""
for vdi_ref, vdi_rec in _get_all_vdis_in_sr(session, sr_ref):
- if ('image-id' in vdi_rec['other_config'] and
- vdi_rec['other_config']['image-id'] == image_id):
- return vdi_ref
+ other_config = vdi_rec['other_config']
+
+ try:
+ image_id_match = other_config['image-id'] == image_id
+ except KeyError:
+ image_id_match = False
+
+ # NOTE(sirp): `VDI.copy` stores the partially-completed file in the SR.
+ # In order to avoid these half-baked files, we compare its current size
+ # to the expected size pulled from the original cache file.
+ try:
+ size_match = (other_config['expected_physical_utilisation'] ==
+ vdi_rec['physical_utilisation'])
+ except KeyError:
+ size_match = False
+
+ if image_id_match and size_match:
+ return vdi_ref
+
return None
@@ -564,7 +580,7 @@ def generate_ephemeral(session, instance, vm_ref, userdevice, size_gb):
size_gb * 1024, FLAGS.default_ephemeral_format)
-def create_kernel_image(context, session, instance, image, user_id,
+def create_kernel_image(context, session, instance, image_id, user_id,
project_id, image_type):
"""Creates kernel/ramdisk file from the image stored in the cache.
If the image is not present in the cache, it streams it from glance.
@@ -574,19 +590,19 @@ def create_kernel_image(context, session, instance, image, user_id,
filename = ""
if FLAGS.cache_images:
args = {}
- args['cached-image'] = image
+ args['cached-image'] = image_id
args['new-image-uuid'] = str(uuid.uuid4())
filename = session.call_plugin('glance', 'create_kernel_ramdisk',
args)
if filename == "":
- return fetch_image(context, session, instance, image, image_type)
+ return fetch_image(context, session, instance, image_id, image_type)
else:
vdi_type = ImageType.to_string(image_type)
return {vdi_type: dict(uuid=None, file=filename)}
-def _create_cached_image(context, session, instance, image, image_type):
+def _create_cached_image(context, session, instance, image_id, image_type):
sr_ref = safe_find_sr(session)
sr_type = session.call_xenapi('SR.get_record', sr_ref)["type"]
vdis = {}
@@ -597,17 +613,17 @@ def _create_cached_image(context, session, instance, image, image_type):
"type %(sr_type)s. Ignoring the cow flag.")
% locals())
- root_vdi_ref = find_cached_image(session, image, sr_ref)
+ root_vdi_ref = find_cached_image(session, image_id, sr_ref)
if root_vdi_ref is None:
- fetched_vdis = fetch_image(context, session, instance, image,
+ fetched_vdis = fetch_image(context, session, instance, image_id,
image_type)
root_vdi = fetched_vdis['root']
root_vdi_ref = session.call_xenapi('VDI.get_by_uuid',
root_vdi['uuid'])
- set_vdi_name(session, root_vdi['uuid'], 'Glance Image %s' % image,
+ set_vdi_name(session, root_vdi['uuid'], 'Glance Image %s' % image_id,
'root', vdi_ref=root_vdi_ref)
session.call_xenapi('VDI.add_to_other_config',
- root_vdi_ref, 'image-id', str(image))
+ root_vdi_ref, 'image-id', str(image_id))
for vdi_type, vdi in fetched_vdis.iteritems():
vdi_ref = session.call_xenapi('VDI.get_by_uuid',
@@ -616,6 +632,11 @@ def _create_cached_image(context, session, instance, image, image_type):
vdi_ref, 'nova_disk_type',
vdi_type)
+ vdi_rec = session.call_xenapi('VDI.get_record', vdi_ref)
+ session.call_xenapi('VDI.add_to_other_config',
+ vdi_ref, 'expected_physical_utilisation',
+ vdi_rec['physical_utilisation'])
+
if vdi_type == 'swap':
session.call_xenapi('VDI.add_to_other_config',
root_vdi_ref, 'swap-disk',
@@ -650,20 +671,20 @@ def _create_cached_image(context, session, instance, image, image_type):
return vdis
-def create_image(context, session, instance, image, image_type):
+def create_image(context, session, instance, image_id, image_type):
"""Creates VDI from the image stored in the local cache. If the image
is not present in the cache, it streams it from glance.
Returns: A list of dictionaries that describe VDIs
"""
- if FLAGS.cache_images is True and image_type != ImageType.DISK_ISO:
- vdis = _create_cached_image(context, session, instance, image,
- image_type)
+ if FLAGS.cache_images and image_type != ImageType.DISK_ISO:
+ vdis = _create_cached_image(
+ context, session, instance, image_id, image_type)
else:
# If caching is disabled, we do not have to keep a copy of the
# image. Fetch the image from glance.
- vdis = fetch_image(context, session, instance,
- instance.image_ref, image_type)
+ vdis = fetch_image(
+ context, session, instance, image_id, image_type)
# Set the name label and description to easily identify what
# instance and disk it's for
@@ -673,20 +694,20 @@ def create_image(context, session, instance, image, image_type):
return vdis
-def fetch_image(context, session, instance, image, image_type):
+def fetch_image(context, session, instance, image_id, image_type):
"""Fetch image from glance based on image type.
Returns: A single filename if image_type is KERNEL or RAMDISK
A list of dictionaries that describe VDIs, otherwise
"""
if image_type == ImageType.DISK_VHD:
- return _fetch_image_glance_vhd(context, session, instance, image)
+ return _fetch_image_glance_vhd(context, session, instance, image_id)
else:
- return _fetch_image_glance_disk(context, session, instance, image,
+ return _fetch_image_glance_disk(context, session, instance, image_id,
image_type)
-def _retry_glance_download_vhd(context, session, image):
+def _retry_glance_download_vhd(context, session, image_id):
# NOTE(sirp): The Glance plugin runs under Python 2.4
# which does not have the `uuid` module. To work around this,
# we generate the uuids here (under Python 2.6+) and
@@ -697,7 +718,7 @@ def _retry_glance_download_vhd(context, session, image):
sleep_time = 0.5
for attempt_num in xrange(1, max_attempts + 1):
glance_host, glance_port = glance.pick_glance_api_server()
- params = {'image_id': image,
+ params = {'image_id': image_id,
'glance_host': glance_host,
'glance_port': glance_port,
'uuid_stack': uuid_stack,
@@ -705,7 +726,7 @@ def _retry_glance_download_vhd(context, session, image):
'auth_token': getattr(context, 'auth_token', None)}
kwargs = {'params': pickle.dumps(params)}
- LOG.info(_('download_vhd %(image)s '
+ LOG.info(_('download_vhd %(image_id)s '
'attempt %(attempt_num)d/%(max_attempts)d '
'from %(glance_host)s:%(glance_port)s') % locals())
@@ -723,19 +744,19 @@ def _retry_glance_download_vhd(context, session, image):
time.sleep(sleep_time)
sleep_time = min(2 * sleep_time, 15)
- raise exception.CouldNotFetchImage(image=image)
+ raise exception.CouldNotFetchImage(image_id=image_id)
-def _fetch_image_glance_vhd(context, session, instance, image):
+def _fetch_image_glance_vhd(context, session, instance, image_id):
"""Tell glance to download an image and put the VHDs into the SR
Returns: A list of dictionaries that describe VDIs
"""
- LOG.debug(_("Asking xapi to fetch vhd image %(image)s"), locals(),
+ LOG.debug(_("Asking xapi to fetch vhd image %(image_id)s"), locals(),
instance=instance)
sr_ref = safe_find_sr(session)
- fetched_vdis = _retry_glance_download_vhd(context, session, image)
+ fetched_vdis = _retry_glance_download_vhd(context, session, image_id)
# 'download_vhd' will return a list of dictionaries describing VDIs.
# The dictionary will contain 'vdi_type' and 'vdi_uuid' keys.
@@ -798,7 +819,7 @@ def _check_vdi_size(context, session, instance, vdi_uuid):
raise exception.ImageTooLarge()
-def _fetch_image_glance_disk(context, session, instance, image, image_type):
+def _fetch_image_glance_disk(context, session, instance, image_id, image_type):
"""Fetch the image from Glance
NOTE:
@@ -813,7 +834,7 @@ def _fetch_image_glance_disk(context, session, instance, image, image_type):
# VHD disk, it may be worth using the plugin for both VHD and RAW and
# DISK restores
image_type_str = ImageType.to_string(image_type)
- LOG.debug(_("Fetching image %(image)s, type %(image_type_str)s"),
+ LOG.debug(_("Fetching image %(image_id)s, type %(image_type_str)s"),
locals(), instance=instance)
if image_type == ImageType.DISK_ISO:
@@ -821,12 +842,12 @@ def _fetch_image_glance_disk(context, session, instance, image, image_type):
else:
sr_ref = safe_find_sr(session)
- glance_client, image_id = glance.get_glance_client(context, image)
+ glance_client, image_id = glance.get_glance_client(context, image_id)
glance_client.set_auth_token(getattr(context, 'auth_token', None))
meta, image_file = glance_client.get_image(image_id)
virtual_size = int(meta['size'])
vdi_size = virtual_size
- LOG.debug(_("Size for image %(image)s: %(virtual_size)d"), locals(),
+ LOG.debug(_("Size for image %(image_id)s: %(virtual_size)d"), locals(),
instance=instance)
if image_type == ImageType.DISK:
# Make room for MBR.
@@ -860,7 +881,7 @@ def _fetch_image_glance_disk(context, session, instance, image, image_type):
# Let the plugin copy the correct number of bytes.
args['image-size'] = str(vdi_size)
if FLAGS.cache_images:
- args['cached-image'] = image
+ args['cached-image'] = image_id
filename = session.call_plugin('glance', fn, args)
# Remove the VDI as it is not needed anymore.