From de864b55cb495d74fa13c4a70ed42e623bbe3f71 Mon Sep 17 00:00:00 2001 From: YAMADA Hideki Date: Wed, 4 Mar 2015 18:11:23 +0000 Subject: [PATCH] Add missing copy_volume_to_image method to Sheepdog driver Copy Volume to Image feature is required since Havana release. The Sheepdog driver has not implemented it. Change-Id: I940095be7ed3721cc8f1bafde821fbb420d305d0 Closes-Bug: #1426431 --- cinder/tests/test_sheepdog.py | 43 +++++++++++++++++++++++++++++++ cinder/volume/drivers/sheepdog.py | 20 ++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/cinder/tests/test_sheepdog.py b/cinder/tests/test_sheepdog.py index 3d0e5365a..b0e138911 100644 --- a/cinder/tests/test_sheepdog.py +++ b/cinder/tests/test_sheepdog.py @@ -137,6 +137,49 @@ class SheepdogTestCase(test.TestCase): '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', diff --git a/cinder/volume/drivers/sheepdog.py b/cinder/volume/drivers/sheepdog.py index 479b0659a..43ec85d9d 100644 --- a/cinder/volume/drivers/sheepdog.py +++ b/cinder/volume/drivers/sheepdog.py @@ -28,6 +28,7 @@ from oslo_utils import units 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 @@ -181,6 +182,25 @@ class SheepdogDriver(driver.VolumeDriver): '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'], -- 2.45.2