Move disk space check to run when needed

At the moment, the check for disk space when booting from an image
currently happens regardless if the backend supports cloning or not.

This means that even if a backend can clone the image directly, the
control plane must have enough disk to download the entire image
which can be unreasonable in backend such as RBD.

This patch moves the code which checks for enough disk space to be
in the same function that effectively downloads the image, ensuring
that it only runs when an image has to be downloaded and avoiding
the check if the backend successfully cloned the image.

Closes-Bug: #1744383
Change-Id: Ibfd6f40e8b8ab88d4ec76e9ac27617a0f97b6c29
This commit is contained in:
Mohammed Naser 2018-01-19 11:45:41 -08:00
parent 2a5f80f026
commit f62f8abad1
2 changed files with 24 additions and 30 deletions

View File

@ -1267,8 +1267,9 @@ class CreateVolumeFlowManagerImageCacheTestCase(test.TestCase):
image_meta,
self.mock_image_service)
# Make sure check_available_space is always called
self.assertTrue(mock_check_space.called)
# Make sure check_available_space is not called because the driver
# will clone things for us.
self.assertFalse(mock_check_space.called)
# Make sure clone_image is always called even if the cache is enabled
self.assertTrue(self.mock_driver.clone_image.called)

View File

@ -721,6 +721,27 @@ class CreateVolumeFromSpecTask(flow_utils.CinderTask):
def _create_from_image_cache_or_download(self, context, volume,
image_location, image_id,
image_meta, image_service):
# NOTE(e0ne): check for free space in image_conversion_dir before
# image downloading.
# NOTE(mnaser): This check *only* happens if the backend is not able
# to clone volumes and we have to resort to downloading
# the image from Glance and uploading it.
if (CONF.image_conversion_dir and not
os.path.exists(CONF.image_conversion_dir)):
os.makedirs(CONF.image_conversion_dir)
try:
image_utils.check_available_space(
CONF.image_conversion_dir,
image_meta['size'], image_id)
except exception.ImageTooBig as err:
with excutils.save_and_reraise_exception():
self.message.create(
context,
message_field.Action.COPY_IMAGE_TO_VOLUME,
resource_uuid=volume.id,
detail=message_field.Detail.NOT_ENOUGH_SPACE_FOR_IMAGE,
exception=err)
# Try and use the image cache.
should_create_cache_entry = False
cloned = False
@ -817,34 +838,6 @@ class CreateVolumeFromSpecTask(flow_utils.CinderTask):
{'volume_id': volume.id,
'image_location': image_location, 'image_id': image_id})
# NOTE(e0ne): check for free space in image_conversion_dir before
# image downloading.
if (CONF.image_conversion_dir and not
os.path.exists(CONF.image_conversion_dir)):
os.makedirs(CONF.image_conversion_dir)
try:
# cinder should not check free space in conversion directory
# if it's creating volume from image snapshot (Bug1683228).
# If image disk format is other than raw, cinder should
# convert it (this means free space check will be needed).
if ('cinder' in CONF.allowed_direct_url_schemes and
image_meta.get('disk_format') == 'raw'):
LOG.debug("Creating volume from image snapshot. "
"Skipping free space check on image "
"convert path.")
else:
image_utils.check_available_space(
CONF.image_conversion_dir,
image_meta['size'], image_id)
except exception.ImageTooBig as err:
with excutils.save_and_reraise_exception():
self.message.create(
context,
message_field.Action.COPY_IMAGE_TO_VOLUME,
resource_uuid=volume.id,
detail=message_field.Detail.NOT_ENOUGH_SPACE_FOR_IMAGE,
exception=err)
virtual_size = image_meta.get('virtual_size')
if virtual_size:
virtual_size = image_utils.check_virtual_size(virtual_size,