]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add missing copy_volume_to_image method to Sheepdog driver
authorYAMADA Hideki <yamada.hideki@lab.ntt.co.jp>
Wed, 4 Mar 2015 18:11:23 +0000 (18:11 +0000)
committerYAMADA Hideki <yamada.hideki@lab.ntt.co.jp>
Tue, 7 Apr 2015 04:56:20 +0000 (04:56 +0000)
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
cinder/volume/drivers/sheepdog.py

index 3d0e5365a4a96d04c38147a72f989cc30bb28ff0..b0e138911a2b84431c93abe8b282156a74356f9d 100644 (file)
@@ -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',
index 479b0659a361e126c10c60f9767e8e51e79b5575..43ec85d9d515e3463c852600dcf0977c4aaa030d 100644 (file)
@@ -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'],