]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
LVM: add the exception handling to volume copy
authorVincent Hou <sbhou@cn.ibm.com>
Mon, 31 Aug 2015 07:14:37 +0000 (15:14 +0800)
committerVincent Hou <sbhou@cn.ibm.com>
Thu, 10 Sep 2015 03:14:08 +0000 (11:14 +0800)
If the volume copy fails from one vg to another one on
the same host, the destination volume on the destination
pool should be removed.

Change-Id: I41922e197e09827582e660a6a00b86aa7044093e
Closes-Bug: #1489335

cinder/tests/unit/test_volume.py
cinder/volume/drivers/lvm.py

index 48201640a85ff4b68bb84abc2375e3a85f0e0661..1b95554a150af2c03cc9587ed9cb9a7b9507f31c 100644 (file)
@@ -6494,6 +6494,29 @@ class LVMISCSIVolumeDriverTestCase(DriverTestCase):
                           self.volume.driver.migrate_volume, self.context,
                           vol, host)
 
+    @mock.patch.object(lvm.LVMVolumeDriver, '_create_volume')
+    @mock.patch.object(brick_lvm.LVM, 'get_all_physical_volumes')
+    @mock.patch.object(brick_lvm.LVM, 'delete')
+    @mock.patch.object(volutils, 'copy_volume',
+                       side_effect=processutils.ProcessExecutionError)
+    @mock.patch.object(volutils, 'get_all_volume_groups',
+                       return_value=[{'name': 'cinder-volumes'}])
+    def test_lvm_migrate_volume_volume_copy_error(self, vgs, copy_volume,
+                                                  mock_delete, mock_pvs,
+                                                  mock_create):
+
+        hostname = socket.gethostname()
+        capabilities = {'location_info': 'LVMVolumeDriver:%s:'
+                        'cinder-volumes:default:0' % hostname}
+        host = {'capabilities': capabilities}
+        vol = {'name': 'test', 'id': 1, 'size': 1, 'status': 'available'}
+        self.volume.driver.vg = fake_lvm.FakeBrickLVM('cinder-volumes-old',
+                                                      False, None, 'default')
+        self.assertRaises(processutils.ProcessExecutionError,
+                          self.volume.driver.migrate_volume, self.context,
+                          vol, host)
+        mock_delete.assert_called_once_with(vol)
+
     def test_lvm_volume_group_missing(self):
         hostname = socket.gethostname()
         capabilities = {'location_info': 'LVMVolumeDriver:%s:'
index d38eeaea8368f6c31c289e3da60e9a9027d052df..fa0c7ec861fa833442a5b7da92ef732a6bbdb2af 100644 (file)
@@ -22,6 +22,7 @@ import socket
 from oslo_concurrency import processutils
 from oslo_config import cfg
 from oslo_log import log as logging
+from oslo_utils import excutils
 from oslo_utils import importutils
 from oslo_utils import units
 import six
@@ -675,12 +676,19 @@ class LVMVolumeDriver(driver.VolumeDriver):
             # copy_volume expects sizes in MiB, we store integer GiB
             # be sure to convert before passing in
             size_in_mb = int(volume['size']) * units.Ki
-            volutils.copy_volume(self.local_path(volume),
-                                 self.local_path(volume, vg=dest_vg),
-                                 size_in_mb,
-                                 self.configuration.volume_dd_blocksize,
-                                 execute=self._execute,
-                                 sparse=self.sparse_copy_volume)
+            try:
+                volutils.copy_volume(self.local_path(volume),
+                                     self.local_path(volume, vg=dest_vg),
+                                     size_in_mb,
+                                     self.configuration.volume_dd_blocksize,
+                                     execute=self._execute,
+                                     sparse=self.sparse_copy_volume)
+            except Exception as e:
+                with excutils.save_and_reraise_exception():
+                    LOG.error(_LE("Volume migration failed due to "
+                                  "exception: %(reason)s."),
+                              {'reason': six.text_type(e)}, resource=volume)
+                    dest_vg_ref.delete(volume)
             self._delete_volume(volume)
 
             return (True, None)