]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
PureISCSIDriver consistency group updates.
authorPatrick East <patrick.east@purestorage.com>
Fri, 13 Feb 2015 21:35:51 +0000 (13:35 -0800)
committerPatrick East <patrick.east@purestorage.com>
Mon, 9 Mar 2015 17:54:32 +0000 (10:54 -0700)
This will enable the driver to add and remove volumes from Purity
protection groups that correspond to Cinders consistency groups, as well
as create a consistency group from a cgsnapshot.

Implements: blueprint pure-iscsi-update-cg
Change-Id: I662e705a1b531a64900304782183041600e13354

cinder/tests/test_pure.py
cinder/volume/drivers/pure.py

index 949775c8c157c3f0f7a385ebb108be59232d928e..3cb4289e4ad27f00ddbbc5972e91399cc583262a 100644 (file)
@@ -784,6 +784,46 @@ class PureISCSIDriverTestCase(test.TestCase):
             [self.array.create_pgroup],
             self.driver.create_consistencygroup, None, mock_cgroup)
 
+    @mock.patch(DRIVER_OBJ + ".create_volume_from_snapshot")
+    @mock.patch(DRIVER_OBJ + ".create_consistencygroup")
+    def test_create_consistencygroup_from_src(self, mock_create_cg,
+                                              mock_create_vol):
+        mock_context = mock.Mock()
+        mock_group = mock.Mock()
+        mock_cgsnapshot = mock.Mock()
+        mock_snapshots = [mock.Mock() for i in range(5)]
+        mock_volumes = [mock.Mock() for i in range(5)]
+        self.driver.create_consistencygroup_from_src(
+            mock_context,
+            mock_group,
+            mock_volumes,
+            cgsnapshot=mock_cgsnapshot,
+            snapshots=mock_snapshots
+        )
+        mock_create_cg.assert_called_with(mock_context, mock_group)
+        expected_calls = [mock.call(vol, snap)
+                          for vol, snap in zip(mock_volumes, mock_snapshots)]
+        mock_create_vol.assert_has_calls(expected_calls,
+                                         any_order=True)
+
+        self.assert_error_propagates(
+            [mock_create_vol, mock_create_cg],
+            self.driver.create_consistencygroup_from_src,
+            mock_context,
+            mock_group,
+            mock_volumes,
+            cgsnapshot=mock_cgsnapshot,
+            snapshots=mock_snapshots
+        )
+
+    def test_create_consistencygroup_from_src_no_snap(self):
+        # Expect an error when no cgsnapshot or snapshots are provided
+        self.assertRaises(exception.InvalidInput,
+                          self.driver.create_consistencygroup_from_src,
+                          mock.Mock(),  # context
+                          mock.Mock(),  # group
+                          [mock.Mock()])  # volumes
+
     @mock.patch(DRIVER_OBJ + ".delete_volume", autospec=True)
     def test_delete_consistencygroup(self, mock_delete_volume):
         mock_cgroup = mock.MagicMock()
@@ -847,6 +887,77 @@ class PureISCSIDriverTestCase(test.TestCase):
             [self.array.destroy_pgroup],
             self.driver.delete_consistencygroup, mock_context, mock_cgroup)
 
+    def _create_mock_cg(self):
+        mock_group = mock.MagicMock()
+        mock_group.id = "4a2f7e3a-312a-40c5-96a8-536b8a0fe074"
+        mock_group.status = "Available"
+        mock_group.cg_name = "consisgroup-" + mock_group.id + "-cinder"
+        return mock_group
+
+    def test_update_consistencygroup(self):
+        mock_group = self._create_mock_cg()
+        add_vols = [
+            {'name': 'vol1'},
+            {'name': 'vol2'},
+            {'name': 'vol3'},
+        ]
+        expected_addvollist = [vol['name'] + '-cinder' for vol in add_vols]
+        remove_vols = [
+            {'name': 'vol4'},
+            {'name': 'vol5'}
+        ]
+        expected_remvollist = [vol['name'] + '-cinder' for vol in remove_vols]
+        self.driver.update_consistencygroup(mock.Mock(), mock_group,
+                                            add_vols, remove_vols)
+        self.array.set_pgroup.assert_called_with(
+            mock_group.cg_name,
+            addvollist=expected_addvollist,
+            remvollist=expected_remvollist
+        )
+
+    def test_update_consistencygroup_no_add_vols(self):
+        mock_group = self._create_mock_cg()
+        expected_addvollist = []
+        remove_vols = [
+            {'name': 'vol4'},
+            {'name': 'vol5'}
+        ]
+        expected_remvollist = [vol['name'] + '-cinder' for vol in remove_vols]
+        self.driver.update_consistencygroup(mock.Mock(), mock_group,
+                                            None, remove_vols)
+        self.array.set_pgroup.assert_called_with(
+            mock_group.cg_name,
+            addvollist=expected_addvollist,
+            remvollist=expected_remvollist
+        )
+
+    def test_update_consistencygroup_no_remove_vols(self):
+        mock_group = self._create_mock_cg()
+        add_vols = [
+            {'name': 'vol1'},
+            {'name': 'vol2'},
+            {'name': 'vol3'},
+        ]
+        expected_addvollist = [vol['name'] + '-cinder' for vol in add_vols]
+        expected_remvollist = []
+        self.driver.update_consistencygroup(mock.Mock(), mock_group,
+                                            add_vols, None)
+        self.array.set_pgroup.assert_called_with(
+            mock_group.cg_name,
+            addvollist=expected_addvollist,
+            remvollist=expected_remvollist
+        )
+
+    def test_update_consistencygroup_no_vols(self):
+        mock_group = self._create_mock_cg()
+        self.driver.update_consistencygroup(mock.Mock(), mock_group,
+                                            None, None)
+        self.array.set_pgroup.assert_called_with(
+            mock_group.cg_name,
+            addvollist=[],
+            remvollist=[]
+        )
+
     def test_create_cgsnapshot(self):
         mock_cgsnap = mock.Mock()
         mock_cgsnap.id = "4a2f7e3a-312a-40c5-96a8-536b8a0fe074"
index 4520a8d5a08287529ac559cd15c1aa33febc20fa..ec2cf9f9f7b76c9de15040504af378f55b3cd9ee 100644 (file)
@@ -107,7 +107,7 @@ def _generate_chap_secret():
 class PureISCSIDriver(san.SanISCSIDriver):
     """Performs volume management on Pure Storage FlashArray."""
 
-    VERSION = "2.0.5"
+    VERSION = "2.0.6"
 
     SUPPORTED_REST_API_VERSIONS = ['1.2', '1.3', '1.4']
 
@@ -517,6 +517,22 @@ class PureISCSIDriver(san.SanISCSIDriver):
         LOG.debug("Leave PureISCSIDriver.create_consistencygroup")
         return model_update
 
+    def create_consistencygroup_from_src(self, context, group, volumes,
+                                         cgsnapshot=None, snapshots=None):
+        LOG.debug("Enter PureISCSIDriver.create_consistencygroup_from_src")
+
+        if cgsnapshot and snapshots:
+            self.create_consistencygroup(context, group)
+            for volume, snapshot in zip(volumes, snapshots):
+                self.create_volume_from_snapshot(volume, snapshot)
+        else:
+            msg = _("create_consistencygroup_from_src only supports a"
+                    " cgsnapshot source, other sources cannot be used.")
+            raise exception.InvalidInput(msg)
+
+        LOG.debug("Leave PureISCSIDriver.create_consistencygroup_from_src")
+        return None, None
+
     def delete_consistencygroup(self, context, group):
         """Deletes a consistency group."""
         LOG.debug("Enter PureISCSIDriver.delete_consistencygroup")
@@ -545,6 +561,27 @@ class PureISCSIDriver(san.SanISCSIDriver):
         LOG.debug("Leave PureISCSIDriver.delete_consistencygroup")
         return model_update, volumes
 
+    def update_consistencygroup(self, context, group,
+                                add_volumes=None, remove_volumes=None):
+        LOG.debug("Enter PureISCSIDriver.update_consistencygroup")
+
+        pgroup_name = _get_pgroup_name_from_id(group.id)
+        if add_volumes:
+            addvollist = [_get_vol_name(volume) for volume in add_volumes]
+        else:
+            addvollist = []
+
+        if remove_volumes:
+            remvollist = [_get_vol_name(volume) for volume in remove_volumes]
+        else:
+            remvollist = []
+
+        self._array.set_pgroup(pgroup_name, addvollist=addvollist,
+                               remvollist=remvollist)
+
+        LOG.debug("Leave PureISCSIDriver.update_consistencygroup")
+        return None, None, None
+
     def create_cgsnapshot(self, context, cgsnapshot):
         """Creates a cgsnapshot."""
         LOG.debug("Enter PureISCSIDriver.create_cgsnapshot")