]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Storwize/SVC: Clone between different size volumes
authorXiaoqin Li <lixqin@cn.ibm.com>
Wed, 13 Jan 2016 06:47:42 +0000 (22:47 -0800)
committerXiaoqin Li <lixqin@cn.ibm.com>
Wed, 2 Mar 2016 07:29:38 +0000 (23:29 -0800)
The source volume size is equal to target volume size
in most cases of create_cloned_volume. But in some
scenario, the target volume size may be bigger
than the source volume size. SVC driver should
support such scenario.

Change-Id: I1598381037a516dca611f5060d3f41195bbe3e17
Closes-Bug: 1533188

cinder/tests/unit/test_storwize_svc.py
cinder/volume/drivers/ibm/storwize_svc/storwize_svc_common.py

index e189528419d72047f088ac52d8dedc2cd33c6521..a9776a0b71e55332044337357ea2ced98d85b34a 100644 (file)
@@ -2925,7 +2925,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
         snap1 = self._generate_vol_info(vol1['name'], vol1['id'])
         self.driver.create_snapshot(snap1)
         vol2 = self._generate_vol_info(None, None)
-        vol3 = self._generate_vol_info(None, None)
+        vol3 = testutils.create_volume(self.ctxt)
+        vol4 = testutils.create_volume(self.ctxt)
 
         # Try to create a volume from a non-existing snapshot
         snap_novol = self._generate_vol_info('undefined-vol', '12345')
@@ -2958,14 +2959,15 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
         self.driver.create_volume_from_snapshot(vol2, snap1)
         self._assert_vol_exists(vol2['name'], True)
 
-        # Try to clone where source size != target size
-        vol3['size'] += 1
+        # Try to clone where source size > target size
+        vol2['size'] = vol3['size'] + 1
         self.assertRaises(exception.InvalidInput,
                           self.driver.create_cloned_volume,
                           vol3, vol2)
         self._assert_vol_exists(vol3['name'], False)
-        vol3['size'] -= 1
 
+        # Try to clone where source size = target size
+        vol2['size'] = vol3['size']
         if self.USESIM:
             self.sim.error_injection('lsfcmap', 'speed_up')
         self.driver.create_cloned_volume(vol3, vol2)
@@ -2976,7 +2978,21 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
                     self.assertEqual('49', fcmap['copyrate'])
         self._assert_vol_exists(vol3['name'], True)
 
+        # Try to clone where  source size < target size
+        vol4['size'] = vol2['size'] + 1
+        if self.USESIM:
+            self.sim.error_injection('lsfcmap', 'speed_up')
+        self.driver.create_cloned_volume(vol4, vol2)
+        if self.USESIM:
+            # Validate copyrate was set on the flash copy
+            for i, fcmap in self.sim._fcmappings_list.items():
+                if fcmap['target'] == vol2['name']:
+                    self.assertEqual('49', fcmap['copyrate'])
+        self._assert_vol_exists(vol4['name'], True)
+
         # Delete in the 'opposite' order to make sure it works
+        self.driver.delete_volume(vol4)
+        self._assert_vol_exists(vol4['name'], False)
         self.driver.delete_volume(vol3)
         self._assert_vol_exists(vol3['name'], False)
         self.driver.delete_volume(vol2)
index 3f32bde35420bd62e1818ac9c98274b21f55c23b..f58f77a9f39f66532b9c92281aa5675d44e5f464 100644 (file)
@@ -2190,9 +2190,16 @@ class StorwizeSVCCommonDriver(san.SanDriver,
                 return replica_status
 
     def create_cloned_volume(self, tgt_volume, src_volume):
-        if src_volume['size'] != tgt_volume['size']:
-            msg = (_('create_cloned_volume: Source and destination '
-                     'size differ.'))
+        """Creates a clone of the specified volume."""
+
+        if src_volume['size'] > tgt_volume['size']:
+            msg = (_("create_cloned_volume: source volume %(src_vol)s "
+                     "size is %(src_size)dGB and doesn't fit in target "
+                     "volume %(tgt_vol)s of size %(tgt_size)dGB.") %
+                   {'src_vol': src_volume['name'],
+                    'src_size': src_volume['size'],
+                    'tgt_vol': tgt_volume['name'],
+                    'tgt_size': tgt_volume['size']})
             LOG.error(msg)
             raise exception.InvalidInput(message=msg)
 
@@ -2203,6 +2210,19 @@ class StorwizeSVCCommonDriver(san.SanDriver,
         self._helpers.create_copy(src_volume['name'], tgt_volume['name'],
                                   src_volume['id'], self.configuration,
                                   opts, True, pool=pool)
+
+        # The source volume size is equal to target volume size
+        # in most of the cases. But in some scenario, the target
+        # volume size may be bigger than the source volume size.
+        # SVC does not support flashcopy between two volumes
+        # with two different size. So use source volume size to
+        # create target volume first and then extend target
+        # volume to orginal size.
+        if tgt_volume['size'] > src_volume['size']:
+            # extend the new created target volume to expected size.
+            self._extend_volume_op(tgt_volume, tgt_volume['size'],
+                                   src_volume['size'])
+
         if opts['qos']:
             self._helpers.add_vdisk_qos(tgt_volume['name'], opts['qos'])
 
@@ -2221,16 +2241,21 @@ class StorwizeSVCCommonDriver(san.SanDriver,
                 return replica_status
 
     def extend_volume(self, volume, new_size):
-        LOG.debug('enter: extend_volume: volume %s', volume['id'])
+        self._extend_volume_op(volume, new_size)
+
+    def _extend_volume_op(self, volume, new_size, old_size=None):
+        LOG.debug('enter: _extend_volume_op: volume %s', volume['id'])
         ret = self._helpers.ensure_vdisk_no_fc_mappings(volume['name'],
                                                         allow_snaps=False)
         if not ret:
-            msg = (_('extend_volume: Extending a volume with snapshots is not '
-                     'supported.'))
+            msg = (_('_extend_volume_op: Extending a volume with snapshots is '
+                     'not supported.'))
             LOG.error(msg)
             raise exception.VolumeDriverException(message=msg)
 
-        extend_amt = int(new_size) - volume['size']
+        if old_size is None:
+            old_size = volume['size']
+        extend_amt = int(new_size) - old_size
         ctxt = context.get_admin_context()
         rep_mirror_type = self._get_volume_replicated_type_mirror(ctxt,
                                                                   volume)
@@ -2257,7 +2282,7 @@ class StorwizeSVCCommonDriver(san.SanDriver,
         if rep_mirror_type and rep_status != "failed-over":
             self.replications.get(rep_mirror_type).create_relationship(
                 volume, target_vol_name)
-        LOG.debug('leave: extend_volume: volume %s', volume['id'])
+        LOG.debug('leave: _extend_volume_op: volume %s', volume['id'])
 
     def add_vdisk_copy(self, volume, dest_pool, vol_type):
         return self._helpers.add_vdisk_copy(volume, dest_pool,