]> 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 15:10:21 +0000 (10:10 -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

cinder/tests/unit/test_dellsc.py
cinder/tests/unit/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 215828a53c9355b522aa345341fc19914afc0e9c..6fe4326137ff3ea08f2853e427d0a2dd46ed9f14 100644 (file)
@@ -3588,6 +3588,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 9cdb273beb24abeb5fb64d8f71a0198433d2ec7c..9ed89624369b91c3950ce0c341547debfdb616ac 100644 (file)
@@ -1163,6 +1163,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