Dell SC: Updated to utilize provider_id

The Dell SC driver was not using provider_id. For volumes it now
stores the Dell SC instanceId in provider_id. For snapshots it stores
the volume's instanceId in the snapshot's provider_id. Snapshots are
still located by description.

Cleaned up some code. Removed the excessive find_sc calls. Updated
error messages.

Updated tests to use fake uuids.

Change-Id: I6e365ce401b72601475c781fe884671d81097d77
This commit is contained in:
Tom Swanson 2016-03-31 11:52:23 -05:00
parent 281ddeb03f
commit 3d6f53e447
7 changed files with 1011 additions and 1149 deletions

View File

@ -17,6 +17,7 @@ import mock
from cinder import context
from cinder import exception
from cinder import test
from cinder.tests.unit import fake_constants as fake
from cinder.volume.drivers.dell import dell_storagecenter_api
from cinder.volume.drivers.dell import dell_storagecenter_fc
@ -171,9 +172,6 @@ class DellSCSanFCDriverTestCase(test.TestCase):
'initiator': 'iqn.1993-08.org.debian:01:e1b1312f9e1',
'wwpns': ['21000024ff30441c', '21000024ff30441d']}
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=None)
@ -183,6 +181,9 @@ class DellSCSanFCDriverTestCase(test.TestCase):
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'map_volume',
return_value=MAPPING)
@ -198,14 +199,14 @@ class DellSCSanFCDriverTestCase(test.TestCase):
def test_initialize_connection(self,
mock_find_wwns,
mock_map_volume,
mock_get_volume,
mock_find_volume,
mock_create_server,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
res = self.driver.initialize_connection(volume, connector)
expected = {'data':
@ -221,18 +222,18 @@ class DellSCSanFCDriverTestCase(test.TestCase):
self.assertEqual(expected, res, 'Unexpected return data')
# verify find_volume has been called and that is has been called twice
mock_find_volume.assert_any_call(self.volume_name)
assert mock_find_volume.call_count == 2
mock_find_volume.assert_called_once_with(fake.volume_id, None)
mock_get_volume.assert_called_once_with(self.VOLUME[u'instanceId'])
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'map_volume',
return_value=MAPPING)
@ -242,22 +243,19 @@ class DellSCSanFCDriverTestCase(test.TestCase):
def test_initialize_connection_no_wwns(self,
mock_find_wwns,
mock_map_volume,
mock_get_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.initialize_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=None)
@ -279,20 +277,16 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_find_volume,
mock_create_server,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.initialize_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -310,20 +304,16 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_map_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'name': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.initialize_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=12345)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -341,21 +331,17 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_map_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case where map_volume returns None (no mappings)
volume = {'id': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.initialize_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -383,11 +369,10 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_unmap_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
res = self.driver.terminate_connection(volume, connector)
mock_unmap_volume.assert_called_once_with(self.VOLUME, self.SCSERVER)
@ -395,9 +380,6 @@ class DellSCSanFCDriverTestCase(test.TestCase):
'data': {}}
self.assertEqual(expected, res, 'Unexpected return data')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=None)
@ -425,20 +407,16 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_unmap_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'name': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.terminate_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -466,20 +444,16 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_unmap_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'name': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.terminate_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -503,11 +477,10 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_unmap_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'name': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
# self.assertRaises(exception.VolumeBackendAPIException,
# self.driver.terminate_connection,
@ -518,9 +491,6 @@ class DellSCSanFCDriverTestCase(test.TestCase):
'data': {}}
self.assertEqual(expected, res, 'Unexpected return data')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -548,20 +518,16 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_unmap_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'name': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.terminate_connection,
volume,
connector)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_server',
return_value=SCSERVER)
@ -589,12 +555,11 @@ class DellSCSanFCDriverTestCase(test.TestCase):
mock_unmap_volume,
mock_find_volume,
mock_find_server,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case where get_volume_count is zero
volume = {'id': self.volume_name}
volume = {'id': fake.volume_id}
connector = self.connector
res = self.driver.terminate_connection(volume, connector)
mock_unmap_volume.assert_called_once_with(self.VOLUME, self.SCSERVER)
@ -607,15 +572,11 @@ class DellSCSanFCDriverTestCase(test.TestCase):
'driver_volume_type': 'fibre_channel'}
self.assertEqual(expected, res, 'Unexpected return data')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_storage_usage',
return_value={'availableSpace': 100, 'freeSpace': 50})
def test_update_volume_stats_with_refresh(self,
mock_get_storage_usage,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):
@ -623,15 +584,11 @@ class DellSCSanFCDriverTestCase(test.TestCase):
self.assertEqual('FC', stats['storage_protocol'])
mock_get_storage_usage.assert_called_once_with()
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_sc',
return_value=64702)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_storage_usage',
return_value={'availableSpace': 100, 'freeSpace': 50})
def test_get_volume_stats_no_refresh(self,
mock_get_storage_usage,
mock_find_sc,
mock_close_connection,
mock_open_connection,
mock_init):

File diff suppressed because it is too large Load Diff

View File

@ -1682,6 +1682,7 @@ class DellSCSanAPITestCase(test.TestCase):
self.volid = str(uuid.uuid4())
self.volume_name = "volume" + self.volid
self.repl_name = "Cinder repl of volume" + self.volid
def test_path_to_array(self,
mock_close_connection,
@ -2006,7 +2007,7 @@ class DellSCSanAPITestCase(test.TestCase):
self.assertEqual(self.FLDR, res, 'Unexpected Folder')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
'get_volume',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'unmap_volume',
@ -2025,7 +2026,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_get_json,
mock_map_volume,
mock_unmap_volume,
mock_find_volume,
mock_get_volume,
mock_close_connection,
mock_open_connection,
mock_init):
@ -2141,7 +2142,7 @@ class DellSCSanAPITestCase(test.TestCase):
self.assertEqual(expected, actual)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
'_search_for_volume',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json',
@ -2156,7 +2157,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_post,
mock_find_volume_folder,
mock_get_json,
mock_find_volume,
mock_search_for_volume,
mock_close_connection,
mock_open_connection,
mock_init):
@ -2167,7 +2168,7 @@ class DellSCSanAPITestCase(test.TestCase):
1)
self.assertTrue(mock_post.called)
self.assertTrue(mock_get_json.called)
self.assertTrue(mock_find_volume.called)
mock_search_for_volume.assert_called_once_with(self.volume_name)
mock_find_volume_folder.assert_called_once_with(True)
self.assertEqual(self.VOLUME, res, 'Unexpected ScVolume')
@ -2277,103 +2278,195 @@ class DellSCSanAPITestCase(test.TestCase):
self.assertIsNone(res, 'None expected')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list',
return_value=VOLUME_LIST)
'_search_for_volume',
return_value=VOLUME)
def test_find_volume(self,
mock_get_vol_list,
mock_search_for_volume,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case to find volume by name
res = self.scapi.find_volume(self.volume_name)
self.assertTrue(mock_get_vol_list.called)
res = self.scapi.find_volume(self.volume_name, None)
mock_search_for_volume.assert_called_once_with(self.volume_name)
self.assertEqual(self.VOLUME, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_search_for_volume',
return_value=None)
def test_find_volume_not_found(self,
mock_search_for_volume,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case to find volume by name
res = self.scapi.find_volume(self.volume_name, None)
mock_search_for_volume.assert_called_once_with(self.volume_name)
self.assertIsNone(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume',
return_value=VOLUME)
def test_find_volume_with_provider_id(self,
mock_get_volume,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
res = self.scapi.find_volume(self.volume_name, provider_id)
mock_get_volume.assert_called_once_with(provider_id)
self.assertEqual(self.VOLUME, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_search_for_volume',
return_value=VOLUME)
def test_find_volume_with_invalid_provider_id(self,
mock_search_for_volume,
mock_get_volume,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = 'WrongSSN.1'
res = self.scapi.find_volume(self.volume_name, provider_id)
mock_search_for_volume.assert_called_once_with(self.volume_name)
self.assertFalse(mock_get_volume.called)
self.assertEqual(self.VOLUME, res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume',
return_value=None)
def test_find_volume_with_provider_id_not_found(self,
mock_get_volume,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
res = self.scapi.find_volume(self.volume_name, provider_id)
mock_get_volume.assert_called_once_with(provider_id)
self.assertIsNone(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_import_one',
return_value=VOLUME)
def test_find_volume_with_provider_id_complete_replication(
self,
mock_import_one,
mock_get_volume,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
# Configure to middle of failover.
self.scapi.failed_over = True
mock_get_volume.return_value = {'name': self.repl_name}
res = self.scapi.find_volume(self.volume_name, provider_id)
self.scapi.failed_over = False
mock_import_one.assert_called_once_with(mock_get_volume.return_value,
self.volume_name)
mock_get_volume.assert_called_once_with(provider_id)
self.assertEqual(self.VOLUME, res, 'Unexpected volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_import_one',
return_value=None)
def test_find_volume_with_provider_id_import_fail(self,
mock_import_one,
mock_get_volume,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
# Configure to middle of failover.
self.scapi.failed_over = True
mock_get_volume.return_value = {'name': self.repl_name}
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_volume, self.volume_name,
provider_id)
self.scapi.failed_over = False
mock_import_one.assert_called_once_with(mock_get_volume.return_value,
self.volume_name)
mock_get_volume.assert_called_once_with(provider_id)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list',
return_value=None)
def test_find_volume_no_name(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
def test_search_for_volume_no_name(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
# Test calling find_volume with no name or instanceid
res = self.scapi.find_volume(None)
self.assertIsNone(res, 'Expected None')
res = self.scapi._search_for_volume(None)
self.assertIsNone(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list')
def test_find_volume_not_found(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
def test_search_for_volume_not_found(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
# Test calling find_volume with result of no volume found
mock_get_volume_list.side_effect = [[], []]
res = self.scapi.find_volume(self.volume_name)
self.assertIsNone(res, 'None expected')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_import_one',
return_value=VOLUME)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list')
def test_find_volume_complete_replication(self,
mock_get_volume_list,
mock_import_one,
mock_close_connection,
mock_open_connection,
mock_init):
self.scapi.failed_over = True
mock_get_volume_list.side_effect = [[], [], self.VOLUME_LIST]
res = self.scapi.find_volume(self.volume_name)
self.assertEqual(self.VOLUME, res, 'Unexpected volume')
self.scapi.failed_over = False
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_import_one',
return_value=None)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list')
def test_find_volume_complete_replication_fail(self,
mock_get_volume_list,
mock_import_one,
mock_close_connection,
mock_open_connection,
mock_init):
self.scapi.failed_over = True
mock_get_volume_list.side_effect = [[], [], self.VOLUME_LIST]
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_volume, self.volume_name)
self.scapi.failed_over = False
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list')
def test_find_volume_complete_replication_multi(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case where multiple repl volumes are found.
mock_get_volume_list.side_effect = [[],
[],
self.VOLUME_LIST_MULTI_VOLS]
self.scapi.failed_over = True
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_volume, self.volume_name)
self.scapi.failed_over = False
res = self.scapi._search_for_volume(self.volume_name)
self.assertIsNone(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_volume_list',
return_value=VOLUME_LIST_MULTI_VOLS)
def test_find_volume_multi_vols_found(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
def test_search_for_volume_multi_vols_found(self,
mock_get_volume_list,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case where multiple volumes are found
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.find_volume, self.volume_name)
self.scapi._search_for_volume, self.volume_name)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'get',
return_value=RESPONSE_200)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json',
return_value=VOLUME)
def test_get_volume(self,
mock_get_json,
mock_get,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
res = self.scapi.get_volume(provider_id)
mock_get.assert_called_once_with(
'StorageCenter/ScVolume/' + provider_id)
self.assertEqual(self.VOLUME, res)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'get',
return_value=RESPONSE_400)
def test_get_volume_error(self,
mock_get,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
res = self.scapi.get_volume(provider_id)
mock_get.assert_called_once_with(
'StorageCenter/ScVolume/' + provider_id)
self.assertIsNone(res)
def test_get_volume_no_id(self,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = None
res = self.scapi.get_volume(provider_id)
self.assertIsNone(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json',
@ -2382,10 +2475,10 @@ class DellSCSanAPITestCase(test.TestCase):
'delete',
return_value=RESPONSE_200)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
'_search_for_volume',
return_value=VOLUME)
def test_delete_volume(self,
mock_find_volume,
mock_search_for_volume,
mock_delete,
mock_get_json,
mock_close_connection,
@ -2393,35 +2486,52 @@ class DellSCSanAPITestCase(test.TestCase):
mock_init):
res = self.scapi.delete_volume(self.volume_name)
self.assertTrue(mock_delete.called)
mock_find_volume.assert_called_once_with(self.volume_name)
mock_search_for_volume.assert_called_once_with(self.volume_name)
self.assertTrue(mock_get_json.called)
self.assertTrue(res)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_json',
return_value=True)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'delete',
return_value=RESPONSE_200)
def test_delete_volume_with_provider_id(self,
mock_delete,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
res = self.scapi.delete_volume(self.volume_name, provider_id)
self.assertTrue(mock_delete.called)
self.assertTrue(mock_get_json.called)
self.assertTrue(res)
@mock.patch.object(dell_storagecenter_api.HttpClient,
'delete',
return_value=RESPONSE_400)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
return_value=VOLUME)
def test_delete_volume_failure(self,
mock_find_volume,
mock_delete,
mock_close_connection,
mock_open_connection,
mock_init):
provider_id = str(self.scapi.ssn) + '.1'
self.assertRaises(exception.VolumeBackendAPIException,
self.scapi.delete_volume, self.volume_name)
self.scapi.delete_volume, self.volume_name,
provider_id)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume',
'_search_for_volume',
return_value=None)
def test_delete_volume_no_vol_found(self,
mock_find_volume,
mock_search_for_volume,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case where volume to be deleted does not exist
res = self.scapi.delete_volume(self.volume_name)
res = self.scapi.delete_volume(self.volume_name, None)
mock_search_for_volume.assert_called_once_with(self.volume_name)
self.assertTrue(res, 'Expected True')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -2484,8 +2594,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
res = self.scapi._add_hba(self.SCSERVER,
self.IQN,
False)
self.IQN)
self.assertTrue(mock_post.called)
self.assertTrue(res)
@ -2497,11 +2606,13 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
saveproto = self.scapi.protocol
self.scapi.protocol = 'FibreChannel'
res = self.scapi._add_hba(self.SCSERVER,
self.WWN,
True)
self.WWN)
self.assertTrue(mock_post.called)
self.assertTrue(res)
self.scapi.protocol = saveproto
@mock.patch.object(dell_storagecenter_api.HttpClient,
'post',
@ -2512,8 +2623,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
res = self.scapi._add_hba(self.SCSERVER,
self.IQN,
False)
self.IQN)
self.assertTrue(mock_post.called)
self.assertFalse(res)
@ -2605,9 +2715,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
res = self.scapi.create_server(
self.IQN,
False)
res = self.scapi.create_server(self.IQN)
self.assertTrue(mock_find_serveros.called)
self.assertTrue(mock_find_server_folder.called)
self.assertTrue(mock_first_result.called)
@ -2638,9 +2746,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
res = self.scapi.create_server(
self.IQN,
False)
res = self.scapi.create_server(self.IQN)
self.assertTrue(mock_find_serveros.called)
self.assertEqual(self.SCSERVER, res, 'Unexpected ScServer')
@ -2668,9 +2774,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
res = self.scapi.create_server(
self.IQN,
False)
res = self.scapi.create_server(self.IQN)
self.assertTrue(mock_find_server_folder.called)
self.assertEqual(self.SCSERVER, res, 'Unexpected ScServer')
@ -2698,9 +2802,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
res = self.scapi.create_server(
self.IQN,
False)
res = self.scapi.create_server(self.IQN)
self.assertIsNone(res, 'None expected')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -2728,9 +2830,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
# Test create server where _first_result is None
res = self.scapi.create_server(
self.IQN,
False)
res = self.scapi.create_server(self.IQN)
self.assertIsNone(res, 'None expected')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -2762,9 +2862,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
# Tests create server where add hba fails
res = self.scapi.create_server(
self.IQN,
False)
res = self.scapi.create_server(self.IQN)
self.assertTrue(mock_delete_server.called)
self.assertIsNone(res, 'None expected')
@ -2891,13 +2989,13 @@ class DellSCSanAPITestCase(test.TestCase):
@mock.patch.object(dell_storagecenter_api.HttpClient,
'get',
return_value=RESPONSE_200)
def test_find_fc_initiators(self,
mock_get,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
res = self.scapi._find_fc_initiators(self.SCSERVER)
def test_find_initiators(self,
mock_get,
mock_get_json,
mock_close_connection,
mock_open_connection,
mock_init):
res = self.scapi._find_initiators(self.SCSERVER)
self.assertTrue(mock_get.called)
self.assertTrue(mock_get_json.called)
self.assertIsNotNone(res, 'Expected WWN list')
@ -2905,13 +3003,13 @@ class DellSCSanAPITestCase(test.TestCase):
@mock.patch.object(dell_storagecenter_api.HttpClient,
'get',
return_value=RESPONSE_400)
def test_find_fc_initiators_error(self,
mock_get,
mock_close_connection,
mock_open_connection,
mock_init):
def test_find_initiators_error(self,
mock_get,
mock_close_connection,
mock_open_connection,
mock_init):
# Test case where get of ScServer HbaList fails
res = self.scapi._find_fc_initiators(self.SCSERVER)
res = self.scapi._find_initiators(self.SCSERVER)
self.assertListEqual([], res, 'Expected empty list')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -3090,10 +3188,10 @@ class DellSCSanAPITestCase(test.TestCase):
'_find_mappings',
return_value=FC_MAPPINGS)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_fc_initiators',
'_find_initiators',
return_value=WWNS)
def test_find_wwns(self,
mock_find_fc_initiators,
mock_find_initiators,
mock_find_mappings,
mock_find_controller_port,
mock_close_connection,
@ -3101,7 +3199,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_init):
lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
self.SCSERVER)
self.assertTrue(mock_find_fc_initiators.called)
self.assertTrue(mock_find_initiators.called)
self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_controller_port.called)
@ -3118,10 +3216,10 @@ class DellSCSanAPITestCase(test.TestCase):
'_find_mappings',
return_value=[])
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_fc_initiators',
'_find_initiators',
return_value=FC_HBAS)
def test_find_wwns_no_mappings(self,
mock_find_fc_initiators,
mock_find_initiators,
mock_find_mappings,
mock_close_connection,
mock_open_connection,
@ -3129,7 +3227,7 @@ class DellSCSanAPITestCase(test.TestCase):
# Test case where there are no ScMapping(s)
lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
self.SCSERVER)
self.assertTrue(mock_find_fc_initiators.called)
self.assertTrue(mock_find_initiators.called)
self.assertTrue(mock_find_mappings.called)
self.assertIsNone(lun, 'Incorrect LUN')
self.assertEqual([], wwns, 'WWNs is not empty')
@ -3142,10 +3240,10 @@ class DellSCSanAPITestCase(test.TestCase):
'_find_mappings',
return_value=FC_MAPPINGS)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_fc_initiators',
'_find_initiators',
return_value=WWNS)
def test_find_wwns_no_ctlr_port(self,
mock_find_fc_initiators,
mock_find_initiators,
mock_find_mappings,
mock_find_controller_port,
mock_close_connection,
@ -3154,7 +3252,7 @@ class DellSCSanAPITestCase(test.TestCase):
# Test case where ScControllerPort is none
lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
self.SCSERVER)
self.assertTrue(mock_find_fc_initiators.called)
self.assertTrue(mock_find_initiators.called)
self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_controller_port.called)
self.assertIsNone(lun, 'Incorrect LUN')
@ -3168,10 +3266,10 @@ class DellSCSanAPITestCase(test.TestCase):
'_find_mappings',
return_value=FC_MAPPINGS)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_fc_initiators',
'_find_initiators',
return_value=WWNS)
def test_find_wwns_wwn_error(self,
mock_find_fc_initiators,
mock_find_initiators,
mock_find_mappings,
mock_find_controller_port,
mock_close_connection,
@ -3181,7 +3279,7 @@ class DellSCSanAPITestCase(test.TestCase):
# property
lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
self.SCSERVER)
self.assertTrue(mock_find_fc_initiators.called)
self.assertTrue(mock_find_initiators.called)
self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_controller_port.called)
@ -3196,11 +3294,11 @@ class DellSCSanAPITestCase(test.TestCase):
'_find_mappings',
return_value=FC_MAPPINGS)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_fc_initiators',
'_find_initiators',
return_value=WWNS_NO_MATCH)
# Test case where HBA name is not found in list of initiators
def test_find_wwns_hbaname_not_found(self,
mock_find_fc_initiators,
mock_find_initiators,
mock_find_mappings,
mock_find_controller_port,
mock_close_connection,
@ -3208,7 +3306,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_init):
lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
self.SCSERVER)
self.assertTrue(mock_find_fc_initiators.called)
self.assertTrue(mock_find_initiators.called)
self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_controller_port.called)
@ -3223,11 +3321,11 @@ class DellSCSanAPITestCase(test.TestCase):
'_find_mappings',
return_value=FC_MAPPINGS_LUN_MISMATCH)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_find_fc_initiators',
'_find_initiators',
return_value=WWNS)
# Test case where FC mappings contain a LUN mismatch
def test_find_wwns_lun_mismatch(self,
mock_find_fc_initiators,
mock_find_initiators,
mock_find_mappings,
mock_find_controller_port,
mock_close_connection,
@ -3235,7 +3333,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_init):
lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
self.SCSERVER)
self.assertTrue(mock_find_fc_initiators.called)
self.assertTrue(mock_find_initiators.called)
self.assertTrue(mock_find_mappings.called)
self.assertTrue(mock_find_controller_port.called)
# The _find_controller_port is Mocked, so all mapping pairs
@ -3887,7 +3985,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
server = {'instanceId': 64702.48}
server = {'instanceId': 64702.48, 'name': 'Server X'}
res = self.scapi.map_volume(self.VOLUME,
server)
self.assertTrue(mock_find_mappings.called)
@ -5008,7 +5106,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
profileid = '100'
add_volumes = [{'id': '1'}]
add_volumes = [{'id': '1', 'provider_id': '1'}]
res = self.scapi._add_cg_volumes(profileid, add_volumes)
self.assertTrue(mock_find_volume.called)
mock_update_volume_profiles.assert_called_once_with(999,
@ -5029,7 +5127,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
profileid = '100'
add_volumes = [{'id': '1'}]
add_volumes = [{'id': '1', 'provider_id': '1'}]
res = self.scapi._add_cg_volumes(profileid, add_volumes)
self.assertTrue(mock_find_volume.called)
mock_update_volume_profiles.assert_called_once_with(999,
@ -5050,7 +5148,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
profileid = '100'
remove_volumes = [{'id': '1'}]
remove_volumes = [{'id': '1', 'provider_id': '1'}]
res = self.scapi._remove_cg_volumes(profileid, remove_volumes)
self.assertTrue(mock_find_volume.called)
mock_update_volume_profiles.assert_called_once_with(999,
@ -5071,7 +5169,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_open_connection,
mock_init):
profileid = '100'
remove_volumes = [{'id': '1'}]
remove_volumes = [{'id': '1', 'provider_id': '1'}]
res = self.scapi._remove_cg_volumes(profileid, remove_volumes)
self.assertTrue(mock_find_volume.called)
mock_update_volume_profiles.assert_called_once_with(999,
@ -6099,7 +6197,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
ret = self.scapi.find_repl_volume('guid', 65495)
ret = self.scapi._find_repl_volume('guid', 65495)
self.assertDictEqual(self.SCREPL[0], ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
@ -6114,7 +6212,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
ret = self.scapi.find_repl_volume('guid', 65495)
ret = self.scapi._find_repl_volume('guid', 65495)
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
@ -6129,7 +6227,7 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
ret = self.scapi.find_repl_volume('guid', 65495)
ret = self.scapi._find_repl_volume('guid', 65495)
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.HttpClient,
@ -6140,13 +6238,13 @@ class DellSCSanAPITestCase(test.TestCase):
mock_close_connection,
mock_open_connection,
mock_init):
ret = self.scapi.find_repl_volume('guid', 65495)
ret = self.scapi._find_repl_volume('guid', 65495)
self.assertIsNone(ret)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'get_screplication')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_repl_volume')
'_find_repl_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'find_volume')
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
@ -6182,19 +6280,18 @@ class DellSCSanAPITestCase(test.TestCase):
True, # 3
True,
False] # 4
# Good path.
ret = self.scapi.break_replication('name', 65495)
self.assertTrue(ret)
ret = self.scapi.break_replication('name', None, 65495)
self.assertEqual(self.VOLUME, ret)
# Source found, screpl not found.
ret = self.scapi.break_replication('name', 65495)
self.assertTrue(ret)
ret = self.scapi.break_replication('name', None, 65495)
self.assertEqual(self.VOLUME, ret)
# No source vol good path.
ret = self.scapi.break_replication('name', 65495)
self.assertTrue(ret)
ret = self.scapi.break_replication('name', None, 65495)
self.assertEqual(self.VOLUME, ret)
# fail remove mappings
ret = self.scapi.break_replication('name', 65495)
self.assertFalse(ret)
ret = self.scapi.break_replication('name', None, 65495)
self.assertEqual(self.VOLUME, ret)
@mock.patch.object(dell_storagecenter_api.StorageCenterApi,
'_get_user_preferences')

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# Copyright 2015 Dell Inc.
# Copyright 2016 Dell Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@ -63,6 +63,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
self.is_direct_connect = False
self.active_backend_id = kwargs.get('active_backend_id', None)
self.failed_over = (self.active_backend_id is not None)
self.storage_protocol = 'iSCSI'
def _bytes_to_gb(self, spacestring):
"""Space is returned in a string like ...
@ -90,7 +91,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
specific helpers.
"""
self._client = dell_storagecenter_api.StorageCenterApiHelper(
self.configuration, self.active_backend_id)
self.configuration, self.active_backend_id, self.storage_protocol)
def check_for_setup_error(self):
"""Validates the configuration information."""
@ -227,15 +228,14 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
scvolume = None
with self._client.open_connection() as api:
try:
if api.find_sc():
scvolume = api.create_volume(volume_name,
volume_size,
storage_profile,
replay_profile_string)
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume %s') %
volume_name)
scvolume = api.create_volume(volume_name,
volume_size,
storage_profile,
replay_profile_string)
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume %s') %
volume_name)
# Update Consistency Group
self._add_volume_to_consistency_group(api, scvolume, volume)
@ -243,6 +243,9 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
# Create replications. (Or not. It checks.)
model_update = self._create_replications(api, volume, scvolume)
# Save our provider_id.
model_update['provider_id'] = scvolume['instanceId']
except Exception:
# if we actually created a volume but failed elsewhere
# clean up the volume now.
@ -288,20 +291,22 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
"""
do_repl, sync = self._do_repl(api, volume)
if do_repl:
volume_name = volume.get('id')
scvol = api.find_volume(volume_name)
replication_driver_data = volume.get('replication_driver_data')
# This is just a string of ssns separated by commas.
ssnstrings = self._split_driver_data(replication_driver_data)
# Trundle through these and delete them all.
for ssnstring in ssnstrings:
ssn = int(ssnstring)
if not api.delete_replication(scvol, ssn):
LOG.warning(_LW('Unable to delete replication of '
'Volume %(vname)s to Storage Center '
'%(sc)s.'),
{'vname': volume_name,
'sc': ssnstring})
if replication_driver_data:
ssnstrings = self._split_driver_data(replication_driver_data)
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
scvol = api.find_volume(volume_name, provider_id)
# This is just a string of ssns separated by commas.
# Trundle through these and delete them all.
for ssnstring in ssnstrings:
ssn = int(ssnstring)
if not api.delete_replication(scvol, ssn):
LOG.warning(_LW('Unable to delete replication of '
'Volume %(vname)s to Storage Center '
'%(sc)s.'),
{'vname': volume_name,
'sc': ssnstring})
# If none of that worked or there was nothing to do doesn't matter.
# Just move on.
@ -309,12 +314,12 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
deleted = False
# We use id as our name as it is unique.
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
LOG.debug('Deleting volume %s', volume_name)
with self._client.open_connection() as api:
try:
if api.find_sc():
self._delete_replications(api, volume)
deleted = api.delete_volume(volume_name)
self._delete_replications(api, volume)
deleted = api.delete_volume(volume_name, provider_id)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Failed to delete volume %s'),
@ -330,22 +335,23 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
"""Create snapshot"""
# our volume name is the volume id
volume_name = snapshot.get('volume_id')
# TODO(tswanson): Is there any reason to think this will be set
# before I create the snapshot? Doesn't hurt to try to get it.
provider_id = snapshot.get('provider_id')
snapshot_id = snapshot.get('id')
LOG.debug('Creating snapshot %(snap)s on volume %(vol)s',
{'snap': snapshot_id,
'vol': volume_name})
with self._client.open_connection() as api:
if api.find_sc():
scvolume = api.find_volume(volume_name)
if scvolume is not None:
if api.create_replay(scvolume,
snapshot_id,
0) is not None:
snapshot['status'] = 'available'
return
else:
LOG.warning(_LW('Unable to locate volume:%s'),
volume_name)
scvolume = api.find_volume(volume_name, provider_id)
if scvolume is not None:
replay = api.create_replay(scvolume, snapshot_id, 0)
if replay:
return {'status': 'available',
'provider_id': scvolume['instanceId']}
else:
LOG.warning(_LW('Unable to locate volume:%s'),
volume_name)
snapshot['status'] = 'error_creating'
msg = _('Failed to create snapshot %s') % snapshot_id
@ -355,6 +361,8 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
"""Create new volume from other volume's snapshot on appliance."""
model_update = {}
scvolume = None
volume_name = volume.get('id')
src_provider_id = snapshot.get('provider_id')
src_volume_name = snapshot.get('volume_id')
# This snapshot could have been created on its own or as part of a
# cgsnapshot. If it was a cgsnapshot it will be identified on the Dell
@ -365,7 +373,6 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
snapshot_id = snapshot.get('cgsnapshot_id')
if not snapshot_id:
snapshot_id = snapshot.get('id')
volume_name = volume.get('id')
LOG.debug(
'Creating new volume %(vol)s from snapshot %(snap)s '
'from vol %(src)s',
@ -374,43 +381,42 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
'src': src_volume_name})
with self._client.open_connection() as api:
try:
if api.find_sc():
srcvol = api.find_volume(src_volume_name)
if srcvol is not None:
replay = api.find_replay(srcvol,
snapshot_id)
if replay is not None:
volume_name = volume.get('id')
# 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)
srcvol = api.find_volume(src_volume_name, src_provider_id)
if srcvol is not None:
replay = api.find_replay(srcvol, snapshot_id)
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)
# Extend Volume
if scvolume and (volume['size'] >
snapshot["volume_size"]):
LOG.debug("Resize the new volume to %s.",
volume['size'])
scvolume = api.expand_volume(scvolume,
volume['size'])
# Extend Volume
if scvolume and (volume['size'] >
snapshot["volume_size"]):
LOG.debug('Resize the new volume to %s.',
volume['size'])
scvolume = api.expand_volume(scvolume,
volume['size'])
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume '
'%(name)s from %(snap)s.') %
{'name': volume_name,
'snap': snapshot_id})
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume '
'%(name)s from %(snap)s.') %
{'name': volume_name,
'snap': snapshot_id})
# Update Consistency Group
self._add_volume_to_consistency_group(api,
scvolume,
volume)
# Replicate if we are supposed to.
model_update = self._create_replications(api,
volume,
scvolume)
# Update Consistency Group
self._add_volume_to_consistency_group(api,
scvolume,
volume)
# Replicate if we are supposed to.
model_update = self._create_replications(api,
volume,
scvolume)
# Save our instanceid.
model_update['provider_id'] = (
scvolume['instanceId'])
except Exception:
# Clean up after ourselves.
@ -433,46 +439,46 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
model_update = {}
scvolume = None
src_volume_name = src_vref.get('id')
src_provider_id = src_vref.get('provider_id')
volume_name = volume.get('id')
LOG.debug('Creating cloned volume %(clone)s from volume %(vol)s',
{'clone': volume_name,
'vol': src_volume_name})
with self._client.open_connection() as api:
try:
if api.find_sc():
srcvol = api.find_volume(src_volume_name)
if srcvol is not None:
# See if we have any extra 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)
srcvol = api.find_volume(src_volume_name, src_provider_id)
if srcvol is not None:
# See if we have any extra 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)
# Extend Volume
if scvolume and volume['size'] > src_vref['size']:
LOG.debug("Resize the new volume to %s.",
volume['size'])
scvolume = api.expand_volume(scvolume,
volume['size'])
# Extend Volume
if scvolume and volume['size'] > src_vref['size']:
LOG.debug('Resize the volume to %s.', volume['size'])
scvolume = api.expand_volume(scvolume, volume['size'])
# If either of those didn't work we bail.
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume '
'%(name)s from %(vol)s.') %
{'name': volume_name,
'vol': src_volume_name})
# If either of those didn't work we bail.
if scvolume is None:
raise exception.VolumeBackendAPIException(
message=_('Unable to create volume '
'%(name)s from %(vol)s.') %
{'name': volume_name,
'vol': src_volume_name})
# Update Consistency Group
self._add_volume_to_consistency_group(api,
scvolume,
volume)
# Replicate if we are supposed to.
model_update = self._create_replications(api,
volume,
scvolume)
# Update Consistency Group
self._add_volume_to_consistency_group(api,
scvolume,
volume)
# Replicate if we are supposed to.
model_update = self._create_replications(api,
volume,
scvolume)
# Save our provider_id.
model_update['provider_id'] = scvolume['instanceId']
except Exception:
# Clean up after ourselves.
self._cleanup_failed_create_volume(api, volume_name)
@ -492,16 +498,14 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
"""delete_snapshot"""
volume_name = snapshot.get('volume_id')
snapshot_id = snapshot.get('id')
provider_id = snapshot.get('provider_id')
LOG.debug('Deleting snapshot %(snap)s from volume %(vol)s',
{'snap': snapshot_id,
'vol': volume_name})
with self._client.open_connection() as api:
if api.find_sc():
scvolume = api.find_volume(volume_name)
if scvolume is not None:
if api.delete_replay(scvolume,
snapshot_id):
return
scvolume = api.find_volume(volume_name, provider_id)
if scvolume and api.delete_replay(scvolume, snapshot_id):
return
# if we are here things went poorly.
snapshot['status'] = 'error_deleting'
msg = _('Failed to delete snapshot %s') % snapshot_id
@ -513,7 +517,6 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
The volume exists on creation and will be visible on
initialize connection. So nothing to do here.
"""
# TODO(tswanson): Move mapping code here.
pass
def ensure_export(self, context, volume):
@ -524,11 +527,11 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
"""
scvolume = None
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
LOG.debug('Checking existence of volume %s', volume_name)
with self._client.open_connection() as api:
try:
if api.find_sc():
scvolume = api.find_volume(volume_name)
scvolume = api.find_volume(volume_name, provider_id)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Failed to ensure export of volume %s'),
@ -548,15 +551,15 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
def extend_volume(self, volume, new_size):
"""Extend the size of the volume."""
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
LOG.debug('Extending volume %(vol)s to %(size)s',
{'vol': volume_name,
'size': new_size})
if volume is not None:
with self._client.open_connection() as api:
if api.find_sc():
scvolume = api.find_volume(volume_name)
if api.expand_volume(scvolume, new_size) is not None:
return
scvolume = api.find_volume(volume_name, provider_id)
if api.expand_volume(scvolume, new_size) is not None:
return
# If we are here nothing good happened.
msg = _('Unable to extend volume %s') % volume_name
raise exception.VolumeBackendAPIException(data=msg)
@ -574,27 +577,25 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
with self._client.open_connection() as api:
storageusage = api.get_storage_usage() if api.find_sc() else None
storageusage = api.get_storage_usage()
if not storageusage:
msg = _('Unable to retrieve volume stats.')
raise exception.VolumeBackendAPIException(message=msg)
# all of this is basically static for now
data = {}
data['volume_backend_name'] = self.backend_name
data['vendor_name'] = 'Dell'
data['driver_version'] = self.VERSION
data['storage_protocol'] = 'iSCSI'
data['storage_protocol'] = self.storage_protocol
data['reserved_percentage'] = 0
data['free_capacity_gb'] = 'unavailable'
data['total_capacity_gb'] = 'unavailable'
data['consistencygroup_support'] = True
# In theory if storageusage is None then we should have
# blown up getting it. If not just report unavailable.
if storageusage is not None:
totalcapacity = storageusage.get('availableSpace')
totalcapacitygb = self._bytes_to_gb(totalcapacity)
data['total_capacity_gb'] = totalcapacitygb
freespace = storageusage.get('freeSpace')
freespacegb = self._bytes_to_gb(freespace)
data['free_capacity_gb'] = freespacegb
totalcapacity = storageusage.get('availableSpace')
totalcapacitygb = self._bytes_to_gb(totalcapacity)
data['total_capacity_gb'] = totalcapacitygb
freespace = storageusage.get('freeSpace')
freespacegb = self._bytes_to_gb(freespace)
data['free_capacity_gb'] = freespacegb
data['QoS_support'] = False
data['replication_enabled'] = self.replication_enabled
if self.replication_enabled:
@ -627,22 +628,24 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
# volume to the original volume name.
original_volume_name = volume.get('id')
current_name = new_volume.get('id')
# We should have this. If we don't we'll set it below.
provider_id = new_volume.get('provider_id')
LOG.debug('update_migrated_volume: %(current)s to %(original)s',
{'current': current_name,
'original': original_volume_name})
if original_volume_name:
with self._client.open_connection() as api:
if api.find_sc():
scvolume = api.find_volume(current_name)
if (scvolume and
api.rename_volume(scvolume, original_volume_name)):
# Replicate if we are supposed to.
model_update = self._create_replications(api,
new_volume,
scvolume)
model_update['_name_id'] = None
scvolume = api.find_volume(current_name, provider_id)
if (scvolume and
api.rename_volume(scvolume, original_volume_name)):
# Replicate if we are supposed to.
model_update = self._create_replications(api,
new_volume,
scvolume)
model_update['_name_id'] = None
model_update['provider_id'] = scvolume['instanceId']
return model_update
return model_update
# The world was horrible to us so we should error and leave.
LOG.error(_LE('Unable to rename the logical volume for volume: %s'),
original_volume_name)
@ -1072,17 +1075,25 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
for volume in volumes:
model_update = {}
if volume.get('replication_driver_data'):
ret = api.break_replication(volume['id'], destssn)
LOG.info(_LI('Failing over volume %(id)s '
'replication: %(res)s.'),
{'id': volume['id'],
'res': ('FAILED', 'SUCCESS')[ret]})
# We should note that we are now failed over.
rvol = api.break_replication(
volume['id'], volume.get('provider_id'),
destssn)
if rvol:
LOG.info(_LI('Success failing over volume %s'),
volume['id'])
else:
LOG.info(_LI('Failed failing over volume %s'),
volume['id'])
# We should note that we are now failed over
# and that we have a new instanceId.
model_update = {
'replication_status': 'failed-over'}
'replication_status': 'failed-over',
'provider_id': rvol['instanceId']}
else:
# Not a replicated volume. Try to unmap it.
scvolume = api.find_volume(volume['id'])
scvolume = api.find_volume(
volume['id'], volume.get('provider_id'))
api.remove_mappings(scvolume)
model_update = {'status': 'error'}
# Either we are failed over or our status is now error.
@ -1152,10 +1163,10 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
backend storage object, raise a ManageExistingInvalidReference
exception.
"""
volume_name = snapshot.get('volume_id')
snapshot_id = snapshot.get('id')
with self._client.open_connection() as api:
# Find our unmanaged snapshot. This will raise on error.
volume_name = snapshot.get('volume_id')
snapshot_id = snapshot.get('id')
screplay = self._get_unmanaged_replay(api, volume_name,
existing_ref)
# Manage means update description and update expiration.
@ -1175,6 +1186,7 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
{'exist': screplay.get('description'),
'volume': volume_name,
'id': snapshot_id})
return {'provider_id': screplay['createVolume']['instanceId']}
# NOTE: Can't use abstractmethod before all drivers implement it
def manage_existing_snapshot_get_size(self, snapshot, existing_ref):
@ -1202,11 +1214,13 @@ class DellCommonDriver(driver.ConsistencyGroupVD, driver.ManageableVD,
NOTE: We do set the expire countdown to 1 day. Once a snapshot is
unmanaged it will expire 24 hours later.
"""
volume_name = snapshot.get('volume_id')
snapshot_id = snapshot.get('id')
with self._client.open_connection() as api:
snapshot_id = snapshot.get('id')
# provider_id is the snapshot's parent volume's instanceId.
provider_id = snapshot.get('provider_id')
volume_name = snapshot.get('volume_id')
# Find our volume.
scvolume = api.find_volume(volume_name)
scvolume = api.find_volume(volume_name, provider_id)
if not scvolume:
# Didn't find it.
msg = (_('unmanage_snapshot: Cannot find volume id %s')

View File

@ -47,14 +47,16 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
2.4.0 - Added Replication V2 support.
2.4.1 - Updated Replication support to V2.1.
2.5.0 - ManageableSnapshotsVD implemented.
3.0.0 - ProviderID utilized.
"""
VERSION = '2.5.0'
VERSION = '3.0.0'
def __init__(self, *args, **kwargs):
super(DellStorageCenterFCDriver, self).__init__(*args, **kwargs)
self.backend_name =\
self.configuration.safe_get('volume_backend_name') or 'Dell-FC'
self.storage_protocol = 'FC'
@fczm_utils.AddFCZone
def initialize_connection(self, volume, connector):
@ -71,10 +73,12 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
# We use id to name the volume name as it is a
# known unique name.
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
LOG.debug('Initialize connection: %s', volume_name)
with self._client.open_connection() as api:
try:
# Find our server.
scserver = None
wwpns = connector.get('wwpns')
for wwn in wwpns:
scserver = api.find_server(wwn)
@ -85,14 +89,13 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
if scserver is None:
scserver = api.create_server_multiple_hbas(wwpns)
# Find the volume on the storage center.
scvolume = api.find_volume(volume_name)
scvolume = api.find_volume(volume_name, provider_id)
if scserver is not None and scvolume is not None:
mapping = api.map_volume(scvolume,
scserver)
mapping = api.map_volume(scvolume, scserver)
if mapping is not None:
# Since we just mapped our volume we had best update
# our sc volume object.
scvolume = api.find_volume(volume_name)
scvolume = api.get_volume(scvolume['instanceId'])
lun, targets, init_targ_map = api.find_wwns(scvolume,
scserver)
if lun is not None and len(targets) > 0:
@ -118,9 +121,11 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
def terminate_connection(self, volume, connector, force=False, **kwargs):
# Get our volume name
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
LOG.debug('Terminate connection: %s', volume_name)
with self._client.open_connection() as api:
try:
scserver = None
wwpns = connector.get('wwpns')
for wwn in wwpns:
scserver = api.find_server(wwn)
@ -128,10 +133,9 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
break
# Find the volume on the storage center.
scvolume = api.find_volume(volume_name)
scvolume = api.find_volume(volume_name, provider_id)
# Get our target map so we can return it to free up a zone.
lun, targets, init_targ_map = api.find_wwns(scvolume,
scserver)
lun, targets, init_targ_map = api.find_wwns(scvolume, scserver)
# If we have a server and a volume lets unmap them.
if (scserver is not None and
scvolume is not None and
@ -157,15 +161,3 @@ class DellStorageCenterFCDriver(dell_storagecenter_common.DellCommonDriver,
LOG.error(_LE('Failed to terminate connection'))
raise exception.VolumeBackendAPIException(
_('Terminate connection unable to connect to backend.'))
def get_volume_stats(self, refresh=False):
"""Get volume status.
If 'refresh' is True, run update the stats first.
"""
if refresh:
self._update_volume_stats()
# Update our protocol to the correct one.
self._stats['storage_protocol'] = 'FC'
return self._stats

View File

@ -46,9 +46,10 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
2.4.0 - Added Replication V2 support.
2.4.1 - Updated Replication support to V2.1.
2.5.0 - ManageableSnapshotsVD implemented.
3.0.0 - ProviderID utilized.
"""
VERSION = '2.5.0'
VERSION = '3.0.0'
def __init__(self, *args, **kwargs):
super(DellStorageCenterISCSIDriver, self).__init__(*args, **kwargs)
@ -72,6 +73,7 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
# We use id to name the volume name as it is a
# known unique name.
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
initiator_name = connector.get('initiator')
multipath = connector.get('multipath', False)
LOG.info(_LI('initialize_ connection: %(vol)s:%(initiator)s'),
@ -86,7 +88,7 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
if server is None:
server = api.create_server(initiator_name)
# Find the volume on the storage center.
scvolume = api.find_volume(volume_name)
scvolume = api.find_volume(volume_name, provider_id)
# if we have a server and a volume lets bring them together.
if server is not None and scvolume is not None:
@ -95,7 +97,7 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
if mapping is not None:
# Since we just mapped our volume we had best update
# our sc volume object.
scvolume = api.find_volume(volume_name)
scvolume = api.get_volume(provider_id)
# Our return.
iscsiprops = {}
ip = None
@ -146,6 +148,7 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
# Grab some initial info.
initiator_name = connector.get('initiator')
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
LOG.debug('Terminate connection: %(vol)s:%(initiator)s',
{'vol': volume_name,
'initiator': initiator_name})
@ -153,7 +156,7 @@ class DellStorageCenterISCSIDriver(dell_storagecenter_common.DellCommonDriver,
try:
scserver = api.find_server(initiator_name)
# Find the volume on the storage center.
scvolume = api.find_volume(volume_name)
scvolume = api.find_volume(volume_name, provider_id)
# If we have a server and a volume lets pull them apart.
if (scserver is not None and