]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Dell: Added support for update_migrated_volume
authorTom Swanson <tom_swanson@dell.com>
Thu, 7 May 2015 21:39:26 +0000 (16:39 -0500)
committerTom Swanson <tom_swanson@dell.com>
Fri, 8 May 2015 22:43:41 +0000 (17:43 -0500)
Added support for updated_migrated_volume to common driver.
Added rename_volume to dell_storagecenter_api to support it.
Added tests to test_dellsc.py and test_dellapi.py.

The only thing we do in this rename the newly migrated volume
destination volume on the Dell Storage center to be the same
as the original volume ID.  Since we identify the volumes
by volume ID this prevents them from being lost.

Change-Id: I531e24853cf5db8b7c34d91460d3abe786a652de
Closes-bug: 1452919
(cherry picked from commit fc09713f2c8102d4b04c8df57fc401a34525d79e)

cinder/tests/test_dellsc.py
cinder/tests/test_dellscapi.py
cinder/volume/drivers/dell/dell_storagecenter_api.py
cinder/volume/drivers/dell/dell_storagecenter_common.py

index 19c60bb434193cc657da0a130f3c9936f8f7cd5c..3a9b4f2ab58b2ed962f6b43e69c5f1644397a48c 100644 (file)
@@ -1025,3 +1025,78 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
         stats = self.driver.get_volume_stats(False)
         self.assertEqual(stats['storage_protocol'], 'iSCSI')
         assert mock_get_storage_usage.called is False
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'find_sc',
+                       return_value=12345)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'find_volume',
+                       return_value=VOLUME)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'rename_volume',
+                       return_value=True)
+    def test_update_migrated_volume(self,
+                                    mock_rename_volume,
+                                    mock_find_volume,
+                                    mock_find_sc,
+                                    mock_close_connection,
+                                    mock_open_connection,
+                                    mock_init):
+        volume = {'id': 111}
+        backend_volume = {'id': 112}
+        model_update = {'_name_id': None}
+        rt = self.driver.update_migrated_volume(None, volume, backend_volume)
+        mock_rename_volume.assert_called_once_with(self.VOLUME,
+                                                   volume['id'])
+        self.assertEqual(model_update, rt)
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'find_sc',
+                       return_value=12345)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'find_volume',
+                       return_value=VOLUME)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'rename_volume',
+                       return_value=False)
+    def test_update_migrated_volume_rename_fail(self,
+                                                mock_rename_volume,
+                                                mock_find_volume,
+                                                mock_find_sc,
+                                                mock_close_connection,
+                                                mock_open_connection,
+                                                mock_init):
+        volume = {'id': 111}
+        backend_volume = {'id': 112}
+        rt = self.driver.update_migrated_volume(None, volume, backend_volume)
+        mock_rename_volume.assert_called_once_with(self.VOLUME,
+                                                   volume['id'])
+        self.assertEqual(None, rt)
+
+    def test_update_migrated_volume_no_volume_id(self,
+                                                 mock_close_connection,
+                                                 mock_open_connection,
+                                                 mock_init):
+        volume = {'id': None}
+        backend_volume = {'id': 112}
+        rt = self.driver.update_migrated_volume(None, volume, backend_volume)
+        self.assertEqual(None, rt)
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'find_sc',
+                       return_value=12345)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       'find_volume',
+                       return_value=None)
+    def test_update_migrated_volume_no_backend_id(self,
+                                                  mock_find_volume,
+                                                  mock_find_sc,
+                                                  mock_close_connection,
+                                                  mock_open_connection,
+                                                  mock_init):
+        volume = {'id': 111}
+        backend_volume = {'id': None}
+        rt = self.driver.update_migrated_volume(None, volume, backend_volume)
+        mock_find_sc.assert_called_once_with(12345)
+        mock_find_volume.assert_called_once_with(12345, None)
+        self.assertEqual(None, rt)
index 85f38ebeb9d79a0bc129e83712bcab86d0551b94..934f4fd6bde82f5b8cba23293dca8cb4f5a858cb 100644 (file)
@@ -3587,6 +3587,30 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_post.called)
         self.assertIsNone(res, 'Expected None')
 
+    @mock.patch.object(dell_storagecenter_api.HttpClient,
+                       'post',
+                       return_value=RESPONSE_200)
+    def test_rename_volume(self,
+                           mock_post,
+                           mock_close_connection,
+                           mock_open_connection,
+                           mock_init):
+        res = self.scapi.rename_volume(self.VOLUME, 'newname')
+        self.assertTrue(mock_post.called)
+        self.assertTrue(res)
+
+    @mock.patch.object(dell_storagecenter_api.HttpClient,
+                       'post',
+                       return_value=RESPONSE_204)
+    def test_rename_volume_failure(self,
+                                   mock_post,
+                                   mock_close_connection,
+                                   mock_open_connection,
+                                   mock_init):
+        res = self.scapi.rename_volume(self.VOLUME, 'newname')
+        self.assertTrue(mock_post.called)
+        self.assertFalse(res)
+
     @mock.patch.object(dell_storagecenter_api.HttpClient,
                        'delete',
                        return_value=RESPONSE_200)
index 3f1d39625b063ca58158b665b55a563864652a22..e09c7a38748e8a1cec532d42a7ea676a3b4236d7 100644 (file)
@@ -1130,6 +1130,21 @@ class StorageCenterApi(object):
                        's': vol['configuredSize']})
         return vol
 
+    def rename_volume(self, scvolume, name):
+        payload = {}
+        payload['Name'] = name
+        r = self.client.post('StorageCenter/ScVolume/%s/Modify'
+                             % self._get_id(scvolume),
+                             payload)
+        if r.status_code != 200:
+            LOG.error(_LE('Error renaming volume %(o)s to %(n)s: %(c)d %(r)s'),
+                      {'o': scvolume['name'],
+                       'n': name,
+                       'c': r.status_code,
+                       'r': r.reason})
+            return False
+        return True
+
     def _delete_server(self, scserver):
         '''_delete_server
 
index 47511ab7b49cb137a4344a9e05c61ca5bc103671..207f1840d16a34411a3b0795fb66f5f265db7245 100644 (file)
@@ -348,3 +348,33 @@ class DellCommonDriver(san.SanDriver):
             LOG.debug('Total cap %(t)s Free cap %(f)s',
                       {'t': totalcapacitygb,
                        'f': freespacegb})
+
+    def update_migrated_volume(self, ctxt, volume, new_volume):
+        """Return model update for migrated volume.
+
+        :param volume: The original volume that was migrated to this backend
+        :param new_volume: The migration volume object that was created on
+                           this backend as part of the migration process
+        :return model_update to update DB with any needed changes
+        """
+        # We use id as our volume name so we need to rename the backend
+        # volume to the original volume name.
+        original_volume_name = volume.get('id')
+        current_name = new_volume.get('id')
+        LOG.debug('update_migrated_volume: %(c)s to %(o)s',
+                  {'c': current_name,
+                   'o': original_volume_name})
+        if original_volume_name:
+            with self._client.open_connection() as api:
+                ssn = api.find_sc(self.configuration.dell_sc_ssn)
+                if ssn is not None:
+                    scvolume = api.find_volume(ssn,
+                                               current_name)
+                    if scvolume:
+                        if api.rename_volume(scvolume, original_volume_name):
+                            model_update = {'_name_id': None}
+                            return model_update
+        # The world was horrible to us so we should error and leave.
+        LOG.error(_LE('Unabled to rename the logical volume for volume: %s'),
+                  original_volume_name)
+        return None