'size': 1},
FakeImageService(), None)
+ def test_copy_volume_to_image(self):
+ fake_context = {}
+ fake_volume = {'name': 'volume-00000001'}
+ fake_image_service = mock.Mock()
+ fake_image_service_update = mock.Mock()
+ fake_image_meta = {'id': '10958016-e196-42e3-9e7f-5d8927ae3099'}
+
+ patch = mock.patch.object
+ with patch(self.driver, '_try_execute') as fake_try_execute:
+ with patch(fake_image_service,
+ 'update') as fake_image_service_update:
+ self.driver.copy_volume_to_image(fake_context,
+ fake_volume,
+ fake_image_service,
+ fake_image_meta)
+
+ expected_cmd = ('qemu-img',
+ 'convert',
+ '-f', 'raw',
+ '-t', 'none',
+ '-O', 'raw',
+ 'sheepdog:%s' % fake_volume['name'],
+ mock.ANY)
+ fake_try_execute.assert_called_once_with(*expected_cmd)
+ fake_image_service_update.assert_called_once_with(
+ fake_context, fake_image_meta['id'], mock.ANY, mock.ANY)
+
+ def test_copy_volume_to_image_nonexistent_volume(self):
+ fake_context = {}
+ fake_volume = {
+ 'name': 'nonexistent-volume-82c4539e-c2a5-11e4-a293-0aa186c60fe0'}
+ fake_image_service = mock.Mock()
+ fake_image_meta = {'id': '10958016-e196-42e3-9e7f-5d8927ae3099'}
+
+ # The command is expected to fail, so we don't want to retry it.
+ self.driver._try_execute = self.driver._execute
+
+ args = (fake_context, fake_volume, fake_image_service, fake_image_meta)
+ expected_errors = (processutils.ProcessExecutionError, OSError)
+ self.assertRaises(expected_errors,
+ self.driver.copy_volume_to_image,
+ *args)
+
def test_create_cloned_volume(self):
src_vol = {
'project_id': 'testprjid',
from cinder import exception
from cinder.i18n import _, _LE
from cinder.image import image_utils
+from cinder.openstack.common import fileutils
from cinder.volume import driver
'raw')
self._resize(volume)
+ def copy_volume_to_image(self, context, volume, image_service, image_meta):
+ """Copy the volume to the specified image."""
+ image_id = image_meta['id']
+ with image_utils.temporary_file() as tmp:
+ # image_utils.convert_image doesn't support "sheepdog:" source,
+ # so we use the qemu-img directly.
+ # Sheepdog volume is always raw-formatted.
+ cmd = ('qemu-img',
+ 'convert',
+ '-f', 'raw',
+ '-t', 'none',
+ '-O', 'raw',
+ 'sheepdog:%s' % volume['name'],
+ tmp)
+ self._try_execute(*cmd)
+
+ with fileutils.file_open(tmp, 'rb') as image_file:
+ image_service.update(context, image_id, {}, image_file)
+
def create_snapshot(self, snapshot):
"""Create a sheepdog snapshot."""
self._try_execute('qemu-img', 'snapshot', '-c', snapshot['name'],