Handle image download and conversion errors

Provide message when there is not enough space for image conversion

With rbd as cinder backend, when creating volume from image, two steps
follow to create the volume:

1. image is downloaded to image_conversion_dir
2. image is converted to raw in the same location

If no space left in image_conversion_dir happened in step1, function
fetch() in image_utils.py will catch this (IOError with e.errno ==
errno.ENOSPC), and exception.ImageTooBig will be re-raised. If happened
in step 2, no "space" specific message will be logged in current code.
This patch provided the space specific log to indicate no space.

Change-Id: I56057475cf55e4be77bbd1dfeabf2bf20d3e1311
Co-authored-by: Irina Mihai <irina.mihai@windriver.com>
Signed-off-by: Liang Fang <liang.a.fang@intel.com>
This commit is contained in:
Liang Fang 2018-11-20 17:33:01 +08:00
parent 0b70bd7046
commit 5ca4c3573b
2 changed files with 52 additions and 1 deletions

View File

@ -236,7 +236,23 @@ def _convert_image(prefix, source, dest, out_format,
passphrase_file=passphrase_file)
start_time = timeutils.utcnow()
utils.execute(*cmd, run_as_root=run_as_root)
# If there is not enough space on the conversion partition, include
# the partitions's name in the error message.
try:
utils.execute(*cmd, run_as_root=run_as_root)
except processutils.ProcessExecutionError as ex:
if "No space left" in ex.stderr and CONF.image_conversion_dir in dest:
conversion_dir = CONF.image_conversion_dir
while not os.path.ismount(conversion_dir):
conversion_dir = os.path.dirname(conversion_dir)
message = _("Insufficient free space on %(location)s for image"
"conversion.") % {'location': conversion_dir}
LOG.error(message)
raise
duration = timeutils.delta_seconds(start_time, timeutils.utcnow())
# NOTE(jdg): use a default of 1, mostly for unit test, but in

View File

@ -280,6 +280,41 @@ class TestConvertImage(test.TestCase):
'-O', 'vpc',
source, dest, run_as_root=True)
@mock.patch('cinder.image.image_utils.CONF')
@mock.patch('cinder.volume.utils.check_for_odirect_support',
return_value=True)
@mock.patch('cinder.image.image_utils.qemu_img_info')
@mock.patch('cinder.utils.execute')
@mock.patch('cinder.utils.is_blk_device', return_value=False)
@mock.patch('os.path.dirname', return_value='fakedir')
@mock.patch('os.path.ismount', return_value=True)
@mock.patch('oslo_utils.fileutils.ensure_tree')
@mock.patch('cinder.image.image_utils.utils.tempdir')
@mock.patch.object(image_utils.LOG, 'error')
def test_not_enough_conversion_space(self,
mock_log,
mock_tempdir,
mock_make,
mock_ismount,
mock_dirname,
mock_isblk,
mock_exec,
mock_info,
mock_odirect,
mock_conf):
source = mock.sentinel.source
mock_conf.image_conversion_dir = 'fakedir'
dest = [mock_conf.image_conversion_dir]
out_format = mock.sentinel.out_format
mock_info.side_effect = ValueError
mock_exec.side_effect = processutils.ProcessExecutionError(
stderr='No space left on device')
self.assertRaises(processutils.ProcessExecutionError,
image_utils.convert_image,
source, dest, out_format)
mock_log.assert_called_with('Insufficient free space on fakedir for'
' imageconversion.')
class TestResizeImage(test.TestCase):
@mock.patch('cinder.utils.execute')