Dell SC: Missing volume creation options.

The Dell SC driver is missing options for Data Reduction,
Group QOS and Volume QOS. Added.

Change-Id: I01951e41eea9985471830b5410892be37e13805a
This commit is contained in:
Tom Swanson 2016-12-05 17:16:40 -06:00
parent 94b5afc75f
commit c5368a7394
6 changed files with 1045 additions and 129 deletions

View File

@ -898,6 +898,10 @@ class DellDriverRetryableException(VolumeBackendAPIException):
message = _("Retryable Dell Exception encountered")
class DellDriverUnknownSpec(VolumeDriverException):
message = _("Dell driver failure: %(reason)s")
# Pure Storage
class PureDriverException(VolumeDriverException):
message = _("Pure Storage Cinder driver failure: %(reason)s")

View File

@ -568,10 +568,8 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
mock_init):
volume = {'id': fake.VOLUME_ID, 'size': 1}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(fake.VOLUME_ID,
1,
None,
None)
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, None, None, None, None, None)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_replay_profile',
@ -591,13 +589,65 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
volume = {'id': fake.VOLUME_ID, 'size': 1,
'consistencygroup_id': fake.CONSISTENCY_GROUP_ID}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(fake.VOLUME_ID,
1,
None,
None)
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, None, None, None, None, None)
self.assertTrue(mock_find_replay_profile.called)
self.assertTrue(mock_update_cg_volumes.called)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_volume',
return_value=VOLUME)
@mock.patch.object(
volume_types,
'get_volume_type_extra_specs',
return_value={'storagetype:volumeqos': 'volumeqos'})
def test_create_volume_volumeqos_profile(self,
mock_extra,
mock_create_volume,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': fake.VOLUME_ID, 'size': 1, 'volume_type_id': 'abc'}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, None, None, 'volumeqos', None, None)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_volume',
return_value=VOLUME)
@mock.patch.object(
volume_types,
'get_volume_type_extra_specs',
return_value={'storagetype:groupqos': 'groupqos'})
def test_create_volume_groupqos_profile(self,
mock_extra,
mock_create_volume,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': fake.VOLUME_ID, 'size': 1, 'volume_type_id': 'abc'}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, None, None, None, 'groupqos', None)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_volume',
return_value=VOLUME)
@mock.patch.object(
volume_types,
'get_volume_type_extra_specs',
return_value={'storagetype:datareductionprofile': 'drprofile'})
def test_create_volume_data_reduction_profile(self,
mock_extra,
mock_create_volume,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': fake.VOLUME_ID, 'size': 1, 'volume_type_id': 'abc'}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, None, None, None, None, 'drprofile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_volume',
return_value=VOLUME)
@ -613,10 +663,8 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
mock_init):
volume = {'id': fake.VOLUME_ID, 'size': 1, 'volume_type_id': 'abc'}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(fake.VOLUME_ID,
1,
"HighPriority",
None)
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, "HighPriority", None, None, None, None)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_volume',
@ -633,10 +681,8 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
mock_init):
volume = {'id': fake.VOLUME_ID, 'size': 1, 'volume_type_id': 'abc'}
self.driver.create_volume(volume)
mock_create_volume.assert_called_once_with(fake.VOLUME_ID,
1,
None,
'Daily')
mock_create_volume.assert_called_once_with(
fake.VOLUME_ID, 1, None, 'Daily', None, None, None)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_volume',
@ -1492,9 +1538,50 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
snapshot = {'id': fake.SNAPSHOT_ID, 'volume_id': fake.VOLUME_ID,
'volume_size': 1}
res = self.driver.create_volume_from_snapshot(volume, snapshot)
mock_create_view_volume.assert_called_once_with(fake.VOLUME_ID,
'fake',
None)
mock_create_view_volume.assert_called_once_with(
fake.VOLUME_ID, 'fake', None, None, None, None)
self.assertTrue(mock_find_replay.called)
self.assertTrue(mock_find_volume.called)
self.assertFalse(mock_find_replay_profile.called)
# This just makes sure that we created
self.assertTrue(mock_create_replications.called)
self.assertEqual(model_update, res)
@mock.patch.object(dell_storagecenter_iscsi.DellStorageCenterISCSIDriver,
'_create_replications')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_replay_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_replay')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_view_volume')
@mock.patch.object(dell_storagecenter_iscsi.DellStorageCenterISCSIDriver,
'_get_volume_extra_specs')
def test_create_volume_from_snapshot_with_profiles(
self, mock_get_volume_extra_specs, mock_create_view_volume,
mock_find_replay, mock_find_volume, mock_find_replay_profile,
mock_create_replications, mock_close_connection,
mock_open_connection, mock_init):
mock_get_volume_extra_specs.return_value = {
'storagetype:replayprofiles': 'replayprofiles',
'storagetype:volumeqos': 'volumeqos',
'storagetype:groupqos': 'groupqos',
'storagetype:datareductionprofile': 'drprofile'}
mock_create_view_volume.return_value = self.VOLUME
mock_find_replay.return_value = 'fake'
mock_find_volume.return_value = self.VOLUME
model_update = {'something': 'something'}
mock_create_replications.return_value = model_update
volume = {'id': fake.VOLUME_ID, 'size': 1}
snapshot = {'id': fake.SNAPSHOT_ID, 'volume_id': fake.VOLUME_ID,
'volume_size': 1}
res = self.driver.create_volume_from_snapshot(volume, snapshot)
mock_create_view_volume.assert_called_once_with(
fake.VOLUME_ID, 'fake', 'replayprofiles', 'volumeqos', 'groupqos',
'drprofile')
self.assertTrue(mock_find_replay.called)
self.assertTrue(mock_find_volume.called)
self.assertFalse(mock_find_replay_profile.called)
@ -1534,9 +1621,8 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
snapshot = {'id': fake.SNAPSHOT_ID, 'volume_id': fake.VOLUME_ID,
'volume_size': 1}
res = self.driver.create_volume_from_snapshot(volume, snapshot)
mock_create_view_volume.assert_called_once_with(fake.VOLUME_ID,
'fake',
None)
mock_create_view_volume.assert_called_once_with(
fake.VOLUME_ID, 'fake', None, None, None, None)
self.assertTrue(mock_find_replay.called)
self.assertTrue(mock_find_volume.called)
self.assertFalse(mock_find_replay_profile.called)
@ -1578,9 +1664,8 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
snapshot = {'id': fake.SNAPSHOT_ID, 'volume_id': fake.VOLUME_ID,
'volume_size': 1}
res = self.driver.create_volume_from_snapshot(volume, snapshot)
mock_create_view_volume.assert_called_once_with(fake.VOLUME_ID,
'fake',
None)
mock_create_view_volume.assert_called_once_with(
fake.VOLUME_ID, 'fake', None, None, None, None)
self.assertTrue(mock_find_replay.called)
self.assertTrue(mock_find_volume.called)
self.assertTrue(mock_find_replay_profile.called)
@ -1700,9 +1785,37 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
src_vref = {'id': fake.VOLUME2_ID, 'size': 1}
ret = self.driver.create_cloned_volume(volume, src_vref)
mock_create_cloned_volume.assert_called_once_with(
fake.VOLUME_ID,
self.VOLUME,
None)
fake.VOLUME_ID, self.VOLUME, None, None, None, None)
self.assertTrue(mock_find_volume.called)
self.assertEqual({'provider_id': provider_id}, ret)
@mock.patch.object(dell_storagecenter_iscsi.DellStorageCenterISCSIDriver,
'_create_replications')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_cloned_volume')
@mock.patch.object(dell_storagecenter_iscsi.DellStorageCenterISCSIDriver,
'_get_volume_extra_specs')
def test_create_cloned_volume_with_profiles(
self, mock_get_volume_extra_specs, mock_create_cloned_volume,
mock_find_volume, mock_create_replications, mock_close_connection,
mock_open_connection, mock_init):
mock_get_volume_extra_specs.return_value = {
'storagetype:replayprofiles': 'replayprofiles',
'storagetype:volumeqos': 'volumeqos',
'storagetype:groupqos': 'groupqos',
'storagetype:datareductionprofile': 'drprofile'}
mock_find_volume.return_value = self.VOLUME
mock_create_cloned_volume.return_value = self.VOLUME
mock_create_replications.return_value = {}
provider_id = self.VOLUME[u'instanceId']
volume = {'id': fake.VOLUME_ID, 'size': 1}
src_vref = {'id': fake.VOLUME2_ID, 'size': 1}
ret = self.driver.create_cloned_volume(volume, src_vref)
mock_create_cloned_volume.assert_called_once_with(
fake.VOLUME_ID, self.VOLUME, 'replayprofiles', 'volumeqos',
'groupqos', 'drprofile')
self.assertTrue(mock_find_volume.called)
self.assertEqual({'provider_id': provider_id}, ret)
@ -1731,9 +1844,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
src_vref = {'id': fake.VOLUME2_ID, 'size': 1}
ret = self.driver.create_cloned_volume(volume, src_vref)
mock_create_cloned_volume.assert_called_once_with(
fake.VOLUME_ID,
self.VOLUME,
None)
fake.VOLUME_ID, self.VOLUME, None, None, None, None)
self.assertTrue(mock_find_volume.called)
self.assertEqual({'provider_id': provider_id}, ret)
self.assertTrue(mock_expand_volume.called)
@ -1847,9 +1958,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
src_vref = {'id': fake.VOLUME2_ID, 'size': 1}
self.driver.create_cloned_volume(volume, src_vref)
mock_create_cloned_volume.assert_called_once_with(
fake.VOLUME_ID,
self.VOLUME,
None)
fake.VOLUME_ID, self.VOLUME, None, None, None, None)
self.assertTrue(mock_find_volume.called)
self.assertTrue(mock_find_replay_profile.called)
self.assertTrue(mock_update_cg_volumes.called)

View File

@ -2097,6 +2097,84 @@ class DellSCSanAPITestCase(test.TestCase):
mock_find_volume_folder.assert_called_once_with(True)
self.assertEqual(self.VOLUME, res, 'Unexpected ScVolume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_volume_folder')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_storage_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_replay_profiles')
def test_create_volume_with_profiles(self,
mock_find_replay_profiles,
mock_find_storage_profile,
mock_find_data_reduction_profile,
mock_find_qos_profile,
mock_post,
mock_find_volume_folder,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
mock_find_replay_profiles.return_value = (['12345.4'], [])
mock_get_json.return_value = self.VOLUME
mock_find_volume_folder.return_value = {'instanceId': '12345.200'}
mock_post.return_value = self.RESPONSE_201
mock_find_storage_profile.return_value = {'instanceId': '12345.0'}
mock_find_data_reduction_profile.return_value = {'instanceId':
'12345.1'}
mock_find_qos_profile.side_effect = [{'instanceId': '12345.2'},
{'instanceId': '12345.3'}]
res = self.scapi.create_volume(self.volume_name, 1, 'storage_profile',
'replay_profile_string', 'volume_qos',
'group_qos', 'datareductionprofile')
expected_payload = {'Name': self.volume_name,
'Notes': 'Created by Dell Cinder Driver',
'Size': '1 GB',
'StorageCenter': 12345,
'VolumeFolder': '12345.200',
'StorageProfile': '12345.0',
'VolumeQosProfile': '12345.2',
'GroupQosProfile': '12345.3',
'DataReductionProfile': '12345.1',
'ReplayProfileList': ['12345.4']}
mock_find_volume_folder.assert_called_once_with(True)
mock_post.assert_called_once_with('StorageCenter/ScVolume',
expected_payload, True)
self.assertEqual(self.VOLUME, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_volume_folder')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_storage_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_replay_profiles')
def test_create_volume_profile_not_found(self,
mock_find_replay_profiles,
mock_find_storage_profile,
mock_find_qos_profile,
mock_find_volume_folder,
mock_close_connection,
mock_open_connection,
mock_init):
mock_find_replay_profiles.return_value = (['12345.4'], [])
mock_find_volume_folder.return_value = self.FLDR
mock_find_storage_profile.return_value = [{'instanceId': '12345.0'}]
# Failure is on the volumeqosprofile.
mock_find_qos_profile.return_value = None
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.create_volume, self.volume_name, 1,
'storage_profile', 'replay_profile_string',
'volume_qos', 'group_qos', 'datareductionprofile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_storage_profile',
return_value=None)
@ -4351,9 +4429,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_init):
vol_name = u'Test_create_vol'
res = self.scapi.create_view_volume(
vol_name,
self.TST_RPLAY,
None)
vol_name, self.TST_RPLAY, None, None, None, None)
self.assertTrue(mock_post.called)
mock_find_volume_folder.assert_called_once_with(True)
self.assertTrue(mock_first_result.called)
@ -4378,9 +4454,7 @@ class DellSCSanAPITestCase(test.TestCase):
# Test case where volume folder does not exist and must be created
vol_name = u'Test_create_vol'
res = self.scapi.create_view_volume(
vol_name,
self.TST_RPLAY,
None)
vol_name, self.TST_RPLAY, None, None, None, None)
self.assertTrue(mock_post.called)
mock_find_volume_folder.assert_called_once_with(True)
self.assertTrue(mock_first_result.called)
@ -4405,9 +4479,7 @@ class DellSCSanAPITestCase(test.TestCase):
# Test case where volume folder does not exist and cannot be created
vol_name = u'Test_create_vol'
res = self.scapi.create_view_volume(
vol_name,
self.TST_RPLAY,
None)
vol_name, self.TST_RPLAY, None, None, None, None)
self.assertTrue(mock_post.called)
mock_find_volume_folder.assert_called_once_with(True)
self.assertTrue(mock_first_result.called)
@ -4428,13 +4500,148 @@ class DellSCSanAPITestCase(test.TestCase):
# Test case where view volume create fails
vol_name = u'Test_create_vol'
res = self.scapi.create_view_volume(
vol_name,
self.TST_RPLAY,
None)
vol_name, self.TST_RPLAY, None, None, None, None)
self.assertTrue(mock_post.called)
mock_find_volume_folder.assert_called_once_with(True)
self.assertIsNone(res, 'Expected None')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_first_result')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_volume_folder')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_replay_profiles')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'update_datareduction_profile')
def test_create_view_volume_with_profiles(
self, mock_update_datareduction_profile, mock_find_replay_profiles,
mock_find_qos_profile, mock_post, mock_find_volume_folder,
mock_first_result, mock_close_connection, mock_open_connection,
mock_init):
mock_find_replay_profiles.return_value = (['12345.4'], [])
mock_first_result.return_value = {'name': 'name'}
mock_post.return_value = self.RESPONSE_200
mock_find_volume_folder.return_value = {'instanceId': '12345.200'}
mock_find_qos_profile.side_effect = [{'instanceId': '12345.2'},
{'instanceId': '12345.3'}]
screplay = {'instanceId': '12345.100.1'}
res = self.scapi.create_view_volume(
'name', screplay, 'replay_profile_string', 'volume_qos',
'group_qos', 'datareductionprofile')
expected_payload = {'Name': 'name',
'Notes': 'Created by Dell Cinder Driver',
'VolumeFolder': '12345.200',
'ReplayProfileList': ['12345.4'],
'VolumeQosProfile': '12345.2',
'GroupQosProfile': '12345.3'}
mock_find_volume_folder.assert_called_once_with(True)
mock_post.assert_called_once_with(
'StorageCenter/ScReplay/12345.100.1/CreateView', expected_payload,
True)
mock_update_datareduction_profile.assert_called_once_with(
{'name': 'name'}, 'datareductionprofile')
self.assertEqual({'name': 'name'}, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_first_result')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_volume_folder')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_replay_profiles')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'update_datareduction_profile')
def test_create_view_volume_with_profiles_no_dr(
self, mock_update_datareduction_profile, mock_find_replay_profiles,
mock_find_qos_profile, mock_post, mock_find_volume_folder,
mock_first_result, mock_close_connection, mock_open_connection,
mock_init):
mock_find_replay_profiles.return_value = (['12345.4'], [])
mock_first_result.return_value = {'name': 'name'}
mock_post.return_value = self.RESPONSE_200
mock_find_volume_folder.return_value = {'instanceId': '12345.200'}
mock_find_qos_profile.side_effect = [{'instanceId': '12345.2'},
{'instanceId': '12345.3'}]
screplay = {'instanceId': '12345.100.1'}
res = self.scapi.create_view_volume('name', screplay,
'replay_profile_string',
'volume_qos',
'group_qos',
None)
expected_payload = {'Name': 'name',
'Notes': 'Created by Dell Cinder Driver',
'VolumeFolder': '12345.200',
'ReplayProfileList': ['12345.4'],
'VolumeQosProfile': '12345.2',
'GroupQosProfile': '12345.3'}
mock_find_volume_folder.assert_called_once_with(True)
mock_post.assert_called_once_with(
'StorageCenter/ScReplay/12345.100.1/CreateView', expected_payload,
True)
mock_update_datareduction_profile.assert_not_called()
self.assertEqual({'name': 'name'}, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_first_result')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_volume_folder')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_create_view_volume_with_profiles_no_replayprofiles(
self, mock_find_qos_profile, mock_post, mock_find_volume_folder,
mock_first_result, mock_close_connection, mock_open_connection,
mock_init):
mock_first_result.return_value = {'name': 'name'}
mock_post.return_value = self.RESPONSE_200
mock_find_volume_folder.return_value = {'instanceId': '12345.200'}
mock_find_qos_profile.side_effect = [{'instanceId': '12345.2'},
{'instanceId': '12345.3'}]
screplay = {'instanceId': '12345.100.1'}
res = self.scapi.create_view_volume('name', screplay,
None,
'volume_qos',
'group_qos',
None)
expected_payload = {'Name': 'name',
'Notes': 'Created by Dell Cinder Driver',
'VolumeFolder': '12345.200',
'VolumeQosProfile': '12345.2',
'GroupQosProfile': '12345.3'}
mock_find_volume_folder.assert_called_once_with(True)
mock_post.assert_called_once_with(
'StorageCenter/ScReplay/12345.100.1/CreateView', expected_payload,
True)
self.assertEqual({'name': 'name'}, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_volume_folder')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_replay_profiles')
def test_create_view_volume_with_profiles_not_found(
self, mock_find_replay_profiles, mock_find_qos_profile,
mock_find_volume_folder, mock_close_connection,
mock_open_connection, mock_init):
mock_find_replay_profiles.return_value = (['12345.4'], [])
mock_find_volume_folder.return_value = {'instanceId': '12345.200'}
# Our qos profile isn't found.
mock_find_qos_profile.return_value = None
screplay = {'instanceId': '12345.100.1'}
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.create_view_volume,
'name', screplay, 'replay_profile_string',
'volume_qos', 'group_qos', 'datareductionprofile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'create_view_volume',
return_value=VOLUME)
@ -4449,16 +4656,14 @@ class DellSCSanAPITestCase(test.TestCase):
mock_init):
vol_name = u'Test_create_clone_vol'
res = self.scapi.create_cloned_volume(
vol_name,
self.VOLUME,
['Daily'])
vol_name, self.VOLUME, ['Daily'],
'volume_qos', 'group_qos', 'dr_profile')
mock_create_replay.assert_called_once_with(self.VOLUME,
'Cinder Clone Replay',
60)
mock_create_view_volume.assert_called_once_with(
vol_name,
self.RPLAY,
['Daily'])
vol_name, self.RPLAY, ['Daily'],
'volume_qos', 'group_qos', 'dr_profile')
self.assertEqual(self.VOLUME, res, 'Unexpected ScVolume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -4477,9 +4682,7 @@ class DellSCSanAPITestCase(test.TestCase):
vol_name = u'Test_create_clone_vol'
mock_create_replay.return_value = None
res = self.scapi.create_cloned_volume(
vol_name,
self.VOLUME,
['Daily'])
vol_name, self.VOLUME, ['Daily'], None, None, None)
mock_create_replay.assert_called_once_with(self.VOLUME,
'Cinder Clone Replay',
60)
@ -4488,13 +4691,11 @@ class DellSCSanAPITestCase(test.TestCase):
# Again buy let create_view_volume fail.
mock_create_replay.return_value = self.RPLAY
res = self.scapi.create_cloned_volume(
vol_name,
self.VOLUME,
['Daily'])
vol_name, self.VOLUME, ['Daily'],
'volume_qos', 'group_qos', 'dr_profile')
mock_create_view_volume.assert_called_once_with(
vol_name,
self.RPLAY,
['Daily'])
vol_name, self.RPLAY, ['Daily'],
'volume_qos', 'group_qos', 'dr_profile')
self.assertIsNone(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -7107,6 +7308,441 @@ class DellSCSanAPITestCase(test.TestCase):
True)
self.assertFalse(ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test_swap_roles_live_volume(self,
mock_post,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_200
lv = {'instanceId': '12345.0'}
ret = self.scapi.swap_roles_live_volume(lv)
self.assertTrue(ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test_swap_roles_live_volume_fail(self,
mock_post,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_400
lv = {'instanceId': '12345.0'}
ret = self.scapi.swap_roles_live_volume(lv)
self.assertFalse(ret)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_qos_profile(self,
mock_post,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_200
mock_get_json.return_value = [{'instanceId': '12345.0'}]
expected_payload = {'filter': {'filterType': 'AND', 'filters': [
{'filterType': 'Equals', 'attributeName': 'ScSerialNumber',
'attributeValue': 12345},
{'filterType': 'Equals', 'attributeName': 'Name',
'attributeValue': 'Default'},
{'filterType': 'Equals', 'attributeName': 'profileType',
'attributeValue': 'VolumeQosProfile'}]}}
ret = self.scapi._find_qos_profile('Default', False)
self.assertEqual({'instanceId': '12345.0'}, ret)
mock_post.assert_called_once_with('StorageCenter/ScQosProfile/GetList',
expected_payload)
def test__find_qos_no_qosprofile(self,
mock_close_connection,
mock_open_connection,
mock_init):
ret = self.scapi._find_qos_profile('', False)
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_qos_error(self,
mock_post,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_400
ret = self.scapi._find_qos_profile('Default', False)
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_qos_profile_empty_list(self,
mock_post,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_200
mock_get_json.return_value = []
ret = self.scapi._find_qos_profile('Default', False)
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_qos_profile_group(self,
mock_post,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_200
mock_get_json.return_value = [{'instanceId': '12345.0'}]
expected_payload = {'filter': {'filterType': 'AND', 'filters': [
{'filterType': 'Equals', 'attributeName': 'ScSerialNumber',
'attributeValue': 12345},
{'filterType': 'Equals', 'attributeName': 'Name',
'attributeValue': 'Default'},
{'filterType': 'Equals', 'attributeName': 'profileType',
'attributeValue': 'GroupQosProfile'}]}}
ret = self.scapi._find_qos_profile('Default', True)
self.assertEqual({'instanceId': '12345.0'}, ret)
mock_post.assert_called_once_with('StorageCenter/ScQosProfile/GetList',
expected_payload)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_datareduction_profile(self,
mock_post,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_200
mock_get_json.return_value = [{'instanceId': '12345.0'}]
expected_payload = {'filter': {'filterType': 'AND', 'filters': [
{'filterType': 'Equals', 'attributeName': 'ScSerialNumber',
'attributeValue': 12345},
{'filterType': 'Equals', 'attributeName': 'instanceName',
'attributeValue': 'Compression'}]}}
ret = self.scapi._find_data_reduction_profile('Compression')
self.assertEqual({'instanceId': '12345.0'}, ret)
mock_post.assert_called_once_with(
'StorageCenter/ScDataReductionProfile/GetList', expected_payload)
def test__find_datareduction_profile_no_drprofile(self,
mock_close_connection,
mock_open_connection,
mock_init):
ret = self.scapi._find_data_reduction_profile('')
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_datareduction_profile_error(self,
mock_post,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_400
ret = self.scapi._find_data_reduction_profile('Compression')
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post')
def test__find_datareduction_profile_empty_list(self,
mock_post,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
mock_post.return_value = self.RESPONSE_200
mock_get_json.return_value = []
ret = self.scapi._find_data_reduction_profile('Compression')
self.assertIsNone(ret)
def test__check_add_profile_payload(self,
mock_close_connection,
mock_open_connection,
mock_init):
payload = {}
profile = {'instanceId': '12345.0'}
self.scapi._check_add_profile_payload(payload, profile,
'Profile1', 'GroupQosProfile')
self.assertEqual({'GroupQosProfile': '12345.0'}, payload)
def test__check_add_profile_payload_no_name(self,
mock_close_connection,
mock_open_connection,
mock_init):
payload = {}
profile = {'instanceId': '12345.0'}
self.scapi._check_add_profile_payload(payload, profile,
None, 'GroupQosProfile')
self.assertEqual({}, payload)
def test__check_add_profile_payload_no_profile(self,
mock_close_connection,
mock_open_connection,
mock_init):
payload = {}
profile = None
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi._check_add_profile_payload,
payload, profile, 'Profile1',
'VolumeQosProfile')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'put')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile(
self, mock_find_datareduction_profile, mock_put, mock_prefs,
mock_close_connection, mock_open_connection, mock_init):
# Test we get and set our default
mock_find_datareduction_profile.return_value = {}
mock_prefs.return_value = {
'allowDataReductionSelection': True,
'dataReductionProfile': {'name': 'Default',
'instanceId': '12345.0'}}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
mock_put.return_value = self.RESPONSE_200
expected = {'dataReductionProfile': '12345.0'}
res = self.scapi.update_datareduction_profile(scvolume, None)
self.assertTrue(res)
mock_put.assert_called_once_with(
'StorageCenter/ScVolumeConfiguration/12345.101', expected, True)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'put')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile_error(
self, mock_find_datareduction_profile, mock_put, mock_prefs,
mock_close_connection, mock_open_connection, mock_init):
# Test we get and set our default
mock_find_datareduction_profile.return_value = {}
mock_prefs.return_value = {
'allowDataReductionSelection': True,
'dataReductionProfile': {'name': 'Default',
'instanceId': '12345.0'}}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
mock_put.return_value = self.RESPONSE_400
expected = {'dataReductionProfile': '12345.0'}
res = self.scapi.update_datareduction_profile(scvolume, None)
self.assertFalse(res)
mock_put.assert_called_once_with(
'StorageCenter/ScVolumeConfiguration/12345.101', expected, True)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile_not_found(
self, mock_find_datareduction_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_datareduction_profile.return_value = None
mock_prefs.return_value = {'allowDataReductionSelection': True}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_datareduction_profile(scvolume, 'Profile')
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile_not_allowed(
self, mock_find_datareduction_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_datareduction_profile.return_value = None
mock_prefs.return_value = {'allowDataReductionSelection': False}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_datareduction_profile(scvolume, None)
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile_prefs_not_found(
self, mock_find_datareduction_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_datareduction_profile.return_value = None
mock_prefs.return_value = None
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_datareduction_profile(scvolume, None)
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile_default_not_found(
self, mock_find_datareduction_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_datareduction_profile.return_value = None
mock_prefs.return_value = {'allowDataReductionSelection': True}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_datareduction_profile(scvolume, None)
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'put',
return_value=RESPONSE_200)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_datareduction_profile_default(
self, mock_find_datareduction_profile, mock_put, mock_prefs,
mock_close_connection, mock_open_connection, mock_init):
# Test we get and set our default
mock_find_datareduction_profile.return_value = None
mock_prefs.return_value = {
'allowDataReductionSelection': True,
'dataReductionProfile': {'name': 'Default',
'instanceId': '12345.0'}}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_datareduction_profile(scvolume, None)
self.assertTrue(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'put')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_update_qos_profile(
self, mock_find_qos_profile, mock_put, mock_prefs,
mock_close_connection, mock_open_connection, mock_init):
# Test we get and set our default
mock_find_qos_profile.return_value = {}
mock_prefs.return_value = {
'allowQosProfileSelection': True,
'volumeQosProfile': {'name': 'Default',
'instanceId': '12345.0'}}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
mock_put.return_value = self.RESPONSE_200
expected = {'volumeQosProfile': '12345.0'}
res = self.scapi.update_qos_profile(scvolume, None)
self.assertTrue(res)
mock_put.assert_called_once_with(
'StorageCenter/ScVolumeConfiguration/12345.101', expected, True)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'put')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_data_reduction_profile')
def test_update_qos_profile_error(
self, mock_find_qos_profile, mock_put, mock_prefs,
mock_close_connection, mock_open_connection, mock_init):
# Test we get and set our default
mock_find_qos_profile.return_value = {}
mock_prefs.return_value = {
'allowQosProfileSelection': True,
'volumeQosProfile': {'name': 'Default',
'instanceId': '12345.0'}}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
mock_put.return_value = self.RESPONSE_400
expected = {'volumeQosProfile': '12345.0'}
res = self.scapi.update_qos_profile(scvolume, None)
self.assertFalse(res)
mock_put.assert_called_once_with(
'StorageCenter/ScVolumeConfiguration/12345.101', expected, True)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_update_qos_profile_not_found(
self, mock_find_qos_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_qos_profile.return_value = None
mock_prefs.return_value = {'allowQosProfileSelection': True}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_qos_profile(scvolume, 'Profile')
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_update_qos_profile_not_allowed(
self, mock_find_qos_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_qos_profile.return_value = None
mock_prefs.return_value = {'allowQosProfileSelection': False}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_qos_profile(scvolume, None)
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_update_qos_profile_prefs_not_found(
self, mock_find_qos_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_qos_profile.return_value = None
mock_prefs.return_value = None
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_qos_profile(scvolume, None)
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_update_qos_profile_default_not_found(
self, mock_find_qos_profile, mock_prefs,
mock_close_connection, mock_open_connection,
mock_init):
mock_find_qos_profile.return_value = None
mock_prefs.return_value = {'allowQosProfileSelection': True}
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_qos_profile(scvolume, None)
self.assertFalse(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')
@mock.patch.object(dell_storagecenter_api.HttpClient,
'put')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_qos_profile')
def test_update_qos_profile_default(
self, mock_find_qos_profile, mock_put, mock_prefs,
mock_close_connection, mock_open_connection, mock_init):
# Test we get and set our default
mock_find_qos_profile.return_value = None
mock_prefs.return_value = {
'allowQosProfileSelection': True,
'volumeQosProfile': {'name': 'Default',
'instanceId': '12345.0'}}
mock_put.return_value = self.RESPONSE_200
scvolume = {'name': fake.VOLUME_ID, 'instanceId': '12345.101'}
res = self.scapi.update_qos_profile(scvolume, None)
self.assertTrue(res)
class DellSCSanAPIConnectionTestCase(test.TestCase):

View File

@ -1000,8 +1000,17 @@ class StorageCenterApi(object):
return False
return True
def _check_add_profile_payload(self, payload, profile, name, type):
if name:
if profile is None:
msg = _('Profile %s not found.') % name
raise exception.VolumeBackendAPIException(data=msg)
else:
payload[type] = self._get_id(profile)
def create_volume(self, name, size, storage_profile=None,
replay_profile_string=None):
replay_profile_string=None, volume_qos=None,
group_qos=None, datareductionprofile=None):
"""Creates a new volume on the Storage Center.
It will create it in a folder called self.vfname. If self.vfname
@ -1014,15 +1023,22 @@ class StorageCenterApi(object):
:param storage_profile: Optional storage profile to set for the volume.
:param replay_profile_string: Optional replay profile to set for
the volume.
:param volume_qos: Volume QOS profile name.
:param group_qos: Group QOS profile name.
:param datareductionprofile: Data reduction profile name
:returns: Dell Volume object or None.
"""
LOG.debug('create_volume: %(name)s %(ssn)s %(folder)s %(profile)s',
LOG.debug('create_volume: %(name)s %(ssn)s %(folder)s %(profile)s '
'%(vqos)r %(gqos)r %(dup)r',
{'name': name,
'ssn': self.ssn,
'folder': self.vfname,
'profile': storage_profile,
'replay': replay_profile_string
})
'replay': replay_profile_string,
'vqos': volume_qos,
'gqos': group_qos,
'dup': datareductionprofile})
# Find our folder
folder = self._find_volume_folder(True)
@ -1031,12 +1047,6 @@ class StorageCenterApi(object):
if folder is None:
LOG.warning(_LW('Unable to create folder %s'), self.vfname)
# See if we need a storage profile
profile = self._find_storage_profile(storage_profile)
if storage_profile and profile is None:
msg = _('Storage Profile %s not found.') % storage_profile
raise exception.VolumeBackendAPIException(data=msg)
# Find our replay_profiles.
addids, removeids = self._find_replay_profiles(replay_profile_string)
@ -1051,11 +1061,27 @@ class StorageCenterApi(object):
payload['StorageCenter'] = self.ssn
if folder is not None:
payload['VolumeFolder'] = self._get_id(folder)
if profile:
payload['StorageProfile'] = self._get_id(profile)
# Add our storage profile.
self._check_add_profile_payload(
payload, self._find_storage_profile(storage_profile),
storage_profile, 'StorageProfile')
# Add our Volume QOS Profile.
self._check_add_profile_payload(
payload, self._find_qos_profile(volume_qos), volume_qos,
'VolumeQosProfile')
# Add our Group QOS Profile.
self._check_add_profile_payload(
payload, self._find_qos_profile(group_qos, True), group_qos,
'GroupQosProfile')
# Add our Data Reduction Proflie.
self._check_add_profile_payload(
payload, self._find_data_reduction_profile(datareductionprofile),
datareductionprofile, 'DataReductionProfile')
# This is a new volume so there is nothing to remove.
if addids:
payload['ReplayProfileList'] = addids
r = self.client.post('StorageCenter/ScVolume', payload, True)
if self._check_result(r):
# Our volume should be in the return.
@ -2063,12 +2089,16 @@ class StorageCenterApi(object):
# If we couldn't find it we call that a success.
return ret
def create_view_volume(self, volname, screplay, replay_profile_string):
def create_view_volume(self, volname, screplay, replay_profile_string,
volume_qos, group_qos, dr_profile):
"""Creates a new volume named volname from the screplay.
:param volname: Name of new volume. This is the cinder volume ID.
:param screplay: Dell replay object from which to make a new volume.
:param replay_profile_string: Profiles to be applied to the volume
:param volume_qos: Volume QOS Profile to use.
:param group_qos: Group QOS Profile to use.
:param dr_profile: Data reduction profile to use.
:returns: Dell volume object or None.
"""
folder = self._find_volume_folder(True)
@ -2084,19 +2114,34 @@ class StorageCenterApi(object):
payload['VolumeFolder'] = self._get_id(folder)
if addids:
payload['ReplayProfileList'] = addids
# Add our Volume QOS Profile.
self._check_add_profile_payload(
payload, self._find_qos_profile(volume_qos), volume_qos,
'VolumeQosProfile')
# Add our Group QOS Profile.
self._check_add_profile_payload(
payload, self._find_qos_profile(group_qos, True), group_qos,
'GroupQosProfile')
r = self.client.post('StorageCenter/ScReplay/%s/CreateView'
% self._get_id(screplay), payload, True)
volume = None
if self._check_result(r):
volume = self._first_result(r)
# If we have a dr_profile to apply we should do so now.
if dr_profile and not self.update_datareduction_profile(volume,
dr_profile):
LOG.error(_LE('Unable to apply %s to volume.'), dr_profile)
volume = None
if volume is None:
LOG.error(_LE('Unable to create volume %s from replay'),
volname)
return volume
def create_cloned_volume(self, volumename, scvolume, replay_profile_list):
def create_cloned_volume(self, volumename, scvolume, replay_profile_list,
volume_qos, group_qos, dr_profile):
"""Creates a volume named volumename from a copy of scvolume.
This is done by creating a replay and then a view volume from
@ -2108,12 +2153,16 @@ class StorageCenterApi(object):
:param volumename: Name of new volume. This is the cinder volume ID.
:param scvolume: Dell volume object.
:param replay_profile_list: List of snapshot profiles.
:param volume_qos: Volume QOS Profile to use.
:param group_qos: Group QOS Profile to use.
:param dr_profile: Data reduction profile to use.
:returns: The new volume's Dell volume object.
"""
replay = self.create_replay(scvolume, 'Cinder Clone Replay', 60)
if replay is not None:
return self.create_view_volume(volumename, replay,
replay_profile_list)
replay_profile_list, volume_qos,
group_qos, dr_profile)
LOG.error(_LE('Error: unable to snap replay'))
return None
@ -2162,6 +2211,48 @@ class StorageCenterApi(object):
'name': name})
return False
def _update_profile(self, scvolume, profile, profilename,
profiletype, restname, allowprefname,
continuewithoutdefault=False):
prefs = self._get_user_preferences()
if not prefs:
return False
if not prefs.get(allowprefname):
LOG.error(_LE('User does not have permission to change '
'%s selection.'), profiletype)
return False
if profilename:
if not profile:
LOG.error(_LE('%(ptype)s %(pname)s was not found.'),
{'ptype': profiletype,
'pname': profilename})
return False
else:
# Going from specific profile to the user default
profile = prefs.get(restname)
if not profile and not continuewithoutdefault:
LOG.error(_LE('Default %s was not found.'), profiletype)
return False
LOG.info(_LI('Switching volume %(vol)s to profile %(prof)s.'),
{'vol': scvolume['name'],
'prof': profile.get('name')})
payload = {}
payload[restname] = self._get_id(profile) if profile else None
r = self.client.put('StorageCenter/ScVolumeConfiguration/%s'
% self._get_id(scvolume), payload, True)
if self._check_result(r):
return True
LOG.error(_LE('Error changing %(ptype)s for volume '
'%(original)s to %(name)s'),
{'ptype': profiletype,
'original': scvolume['name'],
'name': profilename})
return False
def update_storage_profile(self, scvolume, storage_profile):
"""Update a volume's Storage Profile.
@ -2173,43 +2264,45 @@ class StorageCenterApi(object):
:param storage_profile: The requested Storage Profile name.
:returns: True if successful, False otherwise.
"""
prefs = self._get_user_preferences()
if not prefs:
return False
if not prefs.get('allowStorageProfileSelection'):
LOG.error(_LE('User does not have permission to change '
'Storage Profile selection.'))
return False
profile = self._find_storage_profile(storage_profile)
if storage_profile:
if not profile:
LOG.error(_LE('Storage Profile %s was not found.'),
storage_profile)
return False
else:
# Going from specific profile to the user default
profile = prefs.get('storageProfile')
if not profile:
LOG.error(_LE('Default Storage Profile was not found.'))
return False
return self._update_profile(scvolume, profile, storage_profile,
'Storage Profile', 'storageProfile',
'allowStorageProfileSelection')
LOG.info(_LI('Switching volume %(vol)s to profile %(prof)s.'),
{'vol': scvolume['name'],
'prof': profile.get('name')})
payload = {}
payload['StorageProfile'] = self._get_id(profile)
r = self.client.put('StorageCenter/ScVolumeConfiguration/%s'
% self._get_id(scvolume), payload, True)
if self._check_result(r):
return True
def update_datareduction_profile(self, scvolume, dr_profile):
"""Update a volume's Data Reduction Profile
LOG.error(_LE('Error changing Storage Profile for volume '
'%(original)s to %(name)s'),
{'original': scvolume['name'],
'name': storage_profile})
return False
Changes the volume setting to use a different data reduction profile.
If dr_profile is None, will reset to the default profile for the
cinder user account.
:param scvolume: The Storage Center volume to be updated.
:param dr_profile: The requested data reduction profile name.
:returns: True if successful, False otherwise.
"""
profile = self._find_data_reduction_profile(dr_profile)
return self._update_profile(scvolume, profile, dr_profile,
'Data Reduction Profile',
'dataReductionProfile',
'allowDataReductionSelection')
def update_qos_profile(self, scvolume, qosprofile, grouptype=False):
"""Update a volume's QOS profile
Changes the volume setting to use a different QOS Profile.
:param scvolume: The Storage Center volume to be updated.
:param qosprofile: The requested QOS profile name.
:param grouptype: Is this a group QOS profile?
:returns: True if successful, False otherwise.
"""
profiletype = 'groupQosProfile' if grouptype else 'volumeQosProfile'
profile = self._find_qos_profile(qosprofile, grouptype)
return self._update_profile(scvolume, profile, qosprofile,
'Qos Profile', profiletype,
'allowQosProfileSelection',
grouptype)
def _get_user_preferences(self):
"""Gets the preferences and defaults for this user.
@ -3277,3 +3370,33 @@ class StorageCenterApi(object):
if self._check_result(r):
return True
return False
def _find_qos_profile(self, qosprofile, grouptype=False):
if qosprofile:
pf = self._get_payload_filter()
pf.append('ScSerialNumber', self.ssn)
pf.append('Name', qosprofile)
if grouptype:
pf.append('profileType', 'GroupQosProfile')
else:
pf.append('profileType', 'VolumeQosProfile')
r = self.client.post('StorageCenter/ScQosProfile/GetList',
pf.payload)
if self._check_result(r):
qosprofiles = self._get_json(r)
if len(qosprofiles):
return qosprofiles[0]
return None
def _find_data_reduction_profile(self, drprofile):
if drprofile:
pf = self._get_payload_filter()
pf.append('ScSerialNumber', self.ssn)
pf.append('instanceName', drprofile)
r = self.client.post(
'StorageCenter/ScDataReductionProfile/GetList', pf.payload)
if self._check_result(r):
drps = self._get_json(r)
if len(drps):
return drps[0]
return None

View File

@ -287,21 +287,21 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
# Look for our volume
volume_size = volume.get('size')
# See if we have any extra specs.
specs = self._get_volume_extra_specs(volume)
storage_profile = specs.get('storagetype:storageprofile')
replay_profile_string = specs.get('storagetype:replayprofiles')
LOG.debug('Creating volume %(name)s of size %(size)s',
{'name': volume_name,
'size': volume_size})
scvolume = None
with self._client.open_connection() as api:
try:
scvolume = api.create_volume(volume_name,
volume_size,
storage_profile,
replay_profile_string)
# Get our extra specs.
specs = self._get_volume_extra_specs(volume)
scvolume = api.create_volume(
volume_name, volume_size,
specs.get('storagetype:storageprofile'),
specs.get('storagetype:replayprofiles'),
specs.get('storagetype:volumeqos'),
specs.get('storagetype:groupqos'),
specs.get('storagetype:datareductionprofile'))
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume %s') %
@ -494,10 +494,12 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
if replay is not None:
# See if we have any extra specs.
specs = self._get_volume_extra_specs(volume)
replay_profile_string = specs.get(
'storagetype:replayprofiles')
scvolume = api.create_view_volume(
volume_name, replay, replay_profile_string)
volume_name, replay,
specs.get('storagetype:replayprofiles'),
specs.get('storagetype:volumeqos'),
specs.get('storagetype:groupqos'),
specs.get('storagetype:datareductionprofile'))
# Extend Volume
if scvolume and (volume['size'] >
@ -555,13 +557,15 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
try:
srcvol = api.find_volume(src_volume_name, src_provider_id)
if srcvol is not None:
# See if we have any extra specs.
# Get our specs.
specs = self._get_volume_extra_specs(volume)
replay_profile_string = specs.get(
'storagetype:replayprofiles')
# Create our volume
scvolume = api.create_cloned_volume(
volume_name, srcvol, replay_profile_string)
volume_name, srcvol,
specs.get('storagetype:replayprofiles'),
specs.get('storagetype:volumeqos'),
specs.get('storagetype:groupqos'),
specs.get('storagetype:datareductionprofile'))
# Extend Volume
if scvolume and volume['size'] > src_vref['size']:
@ -1094,6 +1098,40 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
LOG.error(_LE('Failed to update replay profiles'))
return False
# Volume QOS profiles.
current, requested = (
self._get_retype_spec(diff, volume_name,
'Volume QOS Profile',
'storagetype:volumeqos'))
if current != requested:
if not api.update_qos_profile(scvolume, requested):
LOG.error(_LE('Failed to update volume '
'qos profile'))
# Group QOS profiles.
current, requested = (
self._get_retype_spec(diff, volume_name,
'Group QOS Profile',
'storagetype:groupqos'))
if current != requested:
if not api.update_qos_profile(scvolume, requested,
True):
LOG.error(_LE('Failed to update group '
'qos profile'))
return False
# Data reduction profiles.
current, requested = (
self._get_retype_spec(
diff, volume_name, 'Data Reduction Profile',
'storagetype:datareductionprofile'))
if current != requested:
if not api.update_datareduction_profile(scvolume,
requested):
LOG.error(_LE('Failed to update data reduction '
'profile'))
return False
# Replication_enabled.
current, requested = (
self._get_retype_spec(diff,
@ -1124,8 +1162,6 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
'replication:activereplay setting'))
return False
# TODO(tswanson): replaytype once it actually works.
except exception.VolumeBackendAPIException:
# We do nothing with this. We simply return failure.
return False
@ -1187,7 +1223,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
return qosnode
def _parse_extraspecs(self, volume):
# Digest our extra specs.
# Digest our extra specs for replication.
extraspecs = {}
specs = self._get_volume_extra_specs(volume)
if specs.get('replication_type') == '<in> sync':

View File

@ -0,0 +1,8 @@
---
features:
- Dell SC - Compression and Dedupe support
added for Storage Centers that support the
options.
- Dell SC - Volume and Group QOS support
added for Storage Centers that support and
have enabled the option.