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)
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)
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)
'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
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