]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
3PAR: Create consistency group from source CG
authorAlex O'Rourke <alex.orourke@hpe.com>
Mon, 1 Feb 2016 21:58:33 +0000 (13:58 -0800)
committerAlex O'Rourke <alex.orourke@hpe.com>
Mon, 8 Feb 2016 18:29:28 +0000 (10:29 -0800)
Supports creating a consistency group from a source consistency group
in the HPE 3PAR driver.

This makes use of temporary snapshots, which are not managed by Cinder.
Upon volume/CG deleteion, these temp snapshots will automatically be
cleaned up.

Change-Id: I033c2c4d45689d02dec96a0e58794629053efbc4
Implements: blueprint hpe-3par-create-cg-from-source
DocImpact

cinder/tests/unit/test_hpe3par.py
cinder/volume/drivers/hpe/hpe_3par_common.py
releasenotes/notes/3par-create-cg-from-source-cg-5634dcf9feb813f6.yaml [new file with mode: 0644]

index 677e25736b45f1e8362502d7a06c0143b71b37ec..4cc2c1d1eb5bd7b0e1c314f832ceca764585b373 100644 (file)
@@ -91,11 +91,13 @@ class Comment(object):
 class HPE3PARBaseDriver(object):
 
     VOLUME_ID = 'd03338a9-9115-48a3-8dfc-35cdfcdc15a7'
+    SRC_CG_VOLUME_ID = 'bd21d11b-c765-4c68-896c-6b07f63cfcb6'
     CLONE_ID = 'd03338a9-9115-48a3-8dfc-000000000000'
     VOLUME_TYPE_ID_REPLICATED = 'be9181f1-4040-46f2-8298-e7532f2bf9db'
     VOLUME_TYPE_ID_DEDUP = 'd03338a9-9115-48a3-8dfc-11111111111'
     VOLUME_TYPE_ID_FLASH_CACHE = 'd03338a9-9115-48a3-8dfc-22222222222'
     VOLUME_NAME = 'volume-' + VOLUME_ID
+    SRC_CG_VOLUME_NAME = 'volume-' + SRC_CG_VOLUME_ID
     VOLUME_NAME_3PAR = 'osv-0DM4qZEVSKON-DXN-NwVpw'
     SNAPSHOT_ID = '2f823bdc-e36e-4dc8-bd15-de1c7a28ff31'
     SNAPSHOT_NAME = 'snapshot-2f823bdc-e36e-4dc8-bd15-de1c7a28ff31'
@@ -104,6 +106,8 @@ class HPE3PARBaseDriver(object):
     RCG_3PAR_NAME = 'rcg-0DM4qZEVSKON-DXN-N'
     CONSIS_GROUP_ID = '6044fedf-c889-4752-900f-2039d247a5df'
     CONSIS_GROUP_NAME = 'vvs-YET.38iJR1KQDyA50kel3w'
+    SRC_CONSIS_GROUP_ID = '7d7dfa02-ac6e-48cb-96af-8a0cd3008d47'
+    SRC_CONSIS_GROUP_NAME = 'vvs-fX36AqxuSMuWr4oM0wCNRw'
     CGSNAPSHOT_ID = 'e91c5ed5-daee-4e84-8724-1c9e31e7a1f2'
     CGSNAPSHOT_BASE_NAME = 'oss-6Rxe1druToSHJByeMeeh8g'
     CLIENT_ID = "12345"
@@ -148,6 +152,14 @@ class HPE3PARBaseDriver(object):
               'volume_type': None,
               'volume_type_id': None}
 
+    volume_src_cg = {'name': SRC_CG_VOLUME_NAME,
+                     'id': SRC_CG_VOLUME_ID,
+                     'display_name': 'Foo Volume',
+                     'size': 2,
+                     'host': FAKE_CINDER_HOST,
+                     'volume_type': None,
+                     'volume_type_id': None}
+
     volume_replicated = {'name': VOLUME_NAME,
                          'id': VOLUME_ID,
                          'display_name': 'Foo Volume',
@@ -585,18 +597,20 @@ class HPE3PARBaseDriver(object):
         mock.call.logout()]
 
     class fake_consistencygroup_object(object):
-        volume_type_id = '49fa96b5-828e-4653-b622-873a1b7e6f1c'
-        name = 'cg_name'
-        cgsnapshot_id = None
-        host = 'fakehost@foo#OpenStackCPG'
-        id = '6044fedf-c889-4752-900f-2039d247a5df'
-        description = 'consistency group'
+        def __init__(self, cg_id='6044fedf-c889-4752-900f-2039d247a5df'):
+            self.id = cg_id
+            self.volume_type_id = '49fa96b5-828e-4653-b622-873a1b7e6f1c'
+            self.name = 'cg_name'
+            self.cgsnapshot_id = None
+            self.host = 'fakehost@foo#OpenStackCPG'
+            self.description = 'consistency group'
 
     class fake_cgsnapshot_object(object):
-        consistencygroup_id = '6044fedf-c889-4752-900f-2039d247a5df'
-        description = 'cgsnapshot'
-        id = 'e91c5ed5-daee-4e84-8724-1c9e31e7a1f2'
-        readOnly = False
+        def __init__(self, cgsnap_id='e91c5ed5-daee-4e84-8724-1c9e31e7a1f2'):
+            self.id = cgsnap_id
+            self.consistencygroup_id = '6044fedf-c889-4752-900f-2039d247a5df'
+            self.description = 'cgsnapshot'
+            self.readOnly = False
 
     def setup_configuration(self):
         configuration = mock.MagicMock()
@@ -3926,6 +3940,60 @@ class HPE3PARBaseDriver(object):
                 expected +
                 self.standard_logout)
 
+    def test_create_consistency_group_from_src_cg(self):
+        mock_client = self.setup_driver()
+        mock_client.getStorageSystemInfo.return_value = {'id': self.CLIENT_ID}
+        volume = self.volume
+        source_volume = self.volume_src_cg
+
+        cgsnap_optional = (
+            {'expirationHours': 1})
+
+        cg_comment = Comment({
+            'display_name': 'cg_name',
+            'consistency_group_id': self.CONSIS_GROUP_ID,
+            'description': 'consistency group'})
+
+        with mock.patch.object(hpecommon.HPE3PARCommon,
+                               '_create_client') as mock_create_client:
+            mock_create_client.return_value = mock_client
+            mock_client.getCPG.return_value = {'domain': None}
+            group = self.fake_consistencygroup_object()
+            source_group = self.fake_consistencygroup_object(
+                cg_id=self.SRC_CONSIS_GROUP_ID)
+
+            expected = [
+                mock.call.getCPG(HPE3PAR_CPG),
+                mock.call.createVolumeSet(
+                    self.CONSIS_GROUP_NAME,
+                    domain=None,
+                    comment=cg_comment),
+                mock.call.createSnapshotOfVolumeSet(
+                    mock.ANY,
+                    self.SRC_CONSIS_GROUP_NAME,
+                    optional=cgsnap_optional),
+                mock.call.copyVolume(
+                    mock.ANY,
+                    self.VOLUME_NAME_3PAR,
+                    HPE3PAR_CPG,
+                    {'snapCPG': HPE3PAR_CPG, 'online': True}),
+                mock.call.addVolumeToVolumeSet(
+                    self.CONSIS_GROUP_NAME,
+                    self.VOLUME_NAME_3PAR)]
+
+            # Create a consistency group from a source consistency group.
+            self.driver.create_consistencygroup_from_src(
+                context.get_admin_context(), group,
+                [volume], source_cg=source_group,
+                source_vols=[source_volume])
+
+            mock_client.assert_has_calls(
+                self.get_id_login +
+                self.standard_logout +
+                self.standard_login +
+                expected +
+                self.standard_logout)
+
     def test_delete_consistency_group(self):
         mock_client = self.setup_driver()
         mock_client.getStorageSystemInfo.return_value = {'id': self.CLIENT_ID}
index 0ee1ec77f0594722f6c53cb8d426837f8a41db54..4d0d060cf2404bb4138b2206cbc63c585b41fb76 100644 (file)
@@ -225,10 +225,11 @@ class HPE3PARCommon(object):
         3.0.10 - Added additional volumes checks to the manage snapshot API
         3.0.11 - Fix the image cache capability bug #1491088
         3.0.12 - Remove client version checks for replication
+        3.0.13 - Support creating a cg from a source cg
 
     """
 
-    VERSION = "3.0.12"
+    VERSION = "3.0.13"
 
     stats = {}
 
@@ -512,22 +513,35 @@ class HPE3PARCommon(object):
                                          cgsnapshot=None, snapshots=None,
                                          source_cg=None, source_vols=None):
 
+        self.create_consistencygroup(context, group)
+        vvs_name = self._get_3par_vvs_name(group.id)
         if cgsnapshot and snapshots:
-            self.create_consistencygroup(context, group)
-            vvs_name = self._get_3par_vvs_name(group.id)
             cgsnap_name = self._get_3par_snap_name(cgsnapshot.id)
-            for i, (volume, snapshot) in enumerate(zip(volumes, snapshots)):
-                snap_name = cgsnap_name + "-" + six.text_type(i)
-                volume_name = self._get_3par_vol_name(volume['id'])
-                type_info = self.get_volume_settings_from_type(volume)
-                cpg = type_info['cpg']
-                optional = {'online': True, 'snapCPG': cpg}
-                self.client.copyVolume(snap_name, volume_name, cpg, optional)
-                self.client.addVolumeToVolumeSet(vvs_name, volume_name)
-        else:
-            msg = _("create_consistencygroup_from_src only supports a"
-                    " cgsnapshot source, other sources cannot be used.")
-            raise exception.InvalidInput(reason=msg)
+            snap_base = cgsnap_name
+        elif source_cg and source_vols:
+            cg_id = source_cg.id
+            # Create a brand new uuid for the temp snap.
+            snap_uuid = uuid.uuid4().hex
+
+            # Create a temporary snapshot of the volume set in order to
+            # perform an online copy. These temp snapshots will be deleted
+            # when the source consistency group is deleted.
+            temp_snap = self._get_3par_snap_name(snap_uuid, temp_snap=True)
+            snap_shot_name = temp_snap + "-@count@"
+            copy_of_name = self._get_3par_vvs_name(cg_id)
+            optional = {'expirationHours': 1}
+            self.client.createSnapshotOfVolumeSet(snap_shot_name, copy_of_name,
+                                                  optional=optional)
+            snap_base = temp_snap
+
+        for i, volume in enumerate(volumes):
+            snap_name = snap_base + "-" + six.text_type(i)
+            volume_name = self._get_3par_vol_name(volume['id'])
+            type_info = self.get_volume_settings_from_type(volume)
+            cpg = type_info['cpg']
+            optional = {'online': True, 'snapCPG': cpg}
+            self.client.copyVolume(snap_name, volume_name, cpg, optional)
+            self.client.addVolumeToVolumeSet(vvs_name, volume_name)
 
         return None, None
 
diff --git a/releasenotes/notes/3par-create-cg-from-source-cg-5634dcf9feb813f6.yaml b/releasenotes/notes/3par-create-cg-from-source-cg-5634dcf9feb813f6.yaml
new file mode 100644 (file)
index 0000000..ff85b2f
--- /dev/null
@@ -0,0 +1,4 @@
+---
+features:
+  - Added support for creating a consistency group from a source consistency group
+    in the HPE 3PAR driver.