Merge "Dell EMC SC: Terminate_connection chokes on None."

This commit is contained in:
Jenkins 2017-07-14 17:24:47 +00:00 committed by Gerrit Code Review
commit 26f03386f6
4 changed files with 87 additions and 50 deletions

View File

@ -1386,28 +1386,25 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
self.assertIsNone(res, 'None expected')
self.assertTrue(mock_terminate_secondary.called)
@mock.patch.object(storagecenter_api.SCApi,
'find_server',
return_value=None)
@mock.patch.object(storagecenter_api.SCApi,
'find_volume',
return_value=VOLUME)
@mock.patch.object(storagecenter_api.SCApi,
'unmap_volume',
'unmap_all',
return_value=True)
def test_terminate_connection_no_server(self,
mock_unmap_volume,
mock_unmap_all,
mock_find_volume,
mock_find_server,
mock_close_connection,
mock_open_connection,
mock_init):
volume = {'id': fake.VOLUME_ID}
volume = {'id': fake.VOLUME_ID, 'provider_id': '101.101'}
connector = {'initiator': ''}
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.terminate_connection,
volume,
connector)
res = self.driver.terminate_connection(volume, connector)
mock_find_volume.assert_called_once_with(fake.VOLUME_ID, '101.101',
False)
mock_unmap_all.assert_called_once_with(self.VOLUME)
self.assertIsNone(res)
@mock.patch.object(storagecenter_api.SCApi,
'find_server',

View File

@ -1972,6 +1972,12 @@ class SCApi(object):
# return true/false.
return rtn
def unmap_all(self, scvolume):
volumeid = self._get_id(scvolume)
r = self.client.post('StorageCenter/ScVolume/%s/Unmap' % volumeid,
{}, True)
return self._check_result(r)
def get_storage_usage(self):
"""Gets the storage usage object from the Dell backend.

View File

@ -75,6 +75,14 @@ class SCFCDriver(storagecenter_common.SCCommonDriver,
self.configuration.safe_get('volume_backend_name') or 'Dell-FC'
self.storage_protocol = 'FC'
def validate_connector(self, connector):
"""Fail if connector doesn't contain all the data needed by driver.
Do a check on the connector and ensure that it has wwnns, wwpns.
"""
self.validate_connector_has_setting(connector, 'wwpns')
self.validate_connector_has_setting(connector, 'wwnns')
@fczm_utils.add_fc_zone
def initialize_connection(self, volume, connector):
"""Initializes the connection and returns connection info.
@ -155,7 +163,8 @@ class SCFCDriver(storagecenter_common.SCCommonDriver,
LOG.error('Failed to initialize connection.')
# We get here because our mapping is none so blow up.
raise exception.VolumeBackendAPIException(_('Unable to map volume.'))
raise exception.VolumeBackendAPIException(
data=_('Unable to map volume.'))
def _find_server(self, api, wwns, ssn=-1):
for wwn in wwns:
@ -196,20 +205,22 @@ class SCFCDriver(storagecenter_common.SCCommonDriver,
@fczm_utils.remove_fc_zone
def terminate_connection(self, volume, connector, force=False, **kwargs):
# Get our volume name
# Grab some quick info.
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
islivevol = self._is_live_vol(volume)
LOG.debug('Terminate connection: %s', volume_name)
with self._client.open_connection() as api:
try:
wwpns = connector.get('wwpns')
wwpns = [] if not connector else connector.get('wwpns', [])
# Find the volume on the storage center.
islivevol = self._is_live_vol(volume)
scvolume = api.find_volume(volume_name, provider_id, islivevol)
if scvolume:
# Get the SSN it is on.
ssn = scvolume['instanceId'].split('.')[0]
# Will be None if we have no wwpns.
scserver = self._find_server(api, wwpns, ssn)
# Get our target map so we can return it to free up a zone.
@ -232,14 +243,14 @@ class SCFCDriver(storagecenter_common.SCCommonDriver,
targets += lvtargets
init_targ_map.update(lvinit_targ_map)
# If we have a server and a volume lets unmap them.
if (scserver is not None and
scvolume is not None and
if (wwpns and scserver and
api.unmap_volume(scvolume, scserver) is True):
LOG.debug('Connection terminated')
elif not wwpns and api.unmap_all(scvolume):
LOG.debug('All connections terminated')
else:
raise exception.VolumeBackendAPIException(
_('Terminate connection failed'))
data=_('Terminate connection failed'))
# basic return info...
info = {'driver_volume_type': 'fibre_channel',
@ -247,7 +258,7 @@ class SCFCDriver(storagecenter_common.SCCommonDriver,
# if not then we return the target map so that
# the zone can be freed up.
if api.get_volume_count(scserver) == 0:
if scserver and api.get_volume_count(scserver) == 0:
info['data'] = {'target_wwn': targets,
'initiator_target_map': init_targ_map}
return info
@ -256,25 +267,39 @@ class SCFCDriver(storagecenter_common.SCCommonDriver,
with excutils.save_and_reraise_exception():
LOG.error('Failed to terminate connection')
raise exception.VolumeBackendAPIException(
_('Terminate connection unable to connect to backend.'))
data=_('Terminate connection unable to connect to backend.'))
def terminate_secondary(self, api, sclivevolume, wwns):
# Find our server.
secondary = self._find_server(
api, wwns, sclivevolume['secondaryScSerialNumber'])
lun = None
targets = []
init_targ_map = {}
# Get our volume.
secondaryvol = api.get_volume(
sclivevolume['secondaryVolume']['instanceId'])
if secondary and secondaryvol:
# Get our map.
lun, targets, init_targ_map = api.find_wwns(secondaryvol,
secondary)
# If we have a server and a volume lets unmap them.
ret = api.unmap_volume(secondaryvol, secondary)
LOG.debug('terminate_secondary: secondary volume %(name)s unmap '
'to secondary server %(server)s result: %(result)r',
{'name': secondaryvol['name'],
'server': secondary['name'],
'result': ret})
# return info for
return lun, targets, init_targ_map
return None, [], {}
# We have one so let's get to work.
if secondaryvol:
# Are we unmapping a specific server?
if wwns:
# Find our server.
secondary = self._find_server(
api, wwns, sclivevolume['secondaryScSerialNumber'])
# Get our map.
lun, targets, init_targ_map = api.find_wwns(secondaryvol,
secondary)
# If we have a server and a volume lets unmap them.
ret = api.unmap_volume(secondaryvol, secondary)
LOG.debug('terminate_secondary: '
'secondary volume %(name)s unmap '
'to secondary server %(server)s result: %(result)r',
{'name': secondaryvol['name'],
'server': secondary['name'], 'result': ret})
else:
# Just unmap all.
ret = api.unmap_all(secondaryvol)
LOG.debug('terminate_secondary: secondary volume %(name)s '
'unmap all result: %(result)r',
{'name': secondaryvol['name'], 'result': ret})
else:
LOG.debug('terminate_secondary: secondary volume not found.')
# return info if any
return lun, targets, init_targ_map

View File

@ -220,25 +220,24 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver,
return data
def terminate_connection(self, volume, connector, force=False, **kwargs):
# Grab some initial info.
initiator_name = connector.get('initiator')
# Grab some quick info.
volume_name = volume.get('id')
provider_id = volume.get('provider_id')
islivevol = self._is_live_vol(volume)
initiator_name = None if not connector else connector.get('initiator')
LOG.debug('Terminate connection: %(vol)s:%(initiator)s',
{'vol': volume_name,
'initiator': initiator_name})
with self._client.open_connection() as api:
try:
# Find the volume on the storage center. Note that if this
# is live volume and we are swapped this will be the back
# half of the live volume.
islivevol = self._is_live_vol(volume)
scvolume = api.find_volume(volume_name, provider_id, islivevol)
if scvolume:
# Get the SSN it is on.
ssn = scvolume['instanceId'].split('.')[0]
# Find our server.
scserver = api.find_server(initiator_name, ssn)
# Unmap our secondary if not failed over..
if islivevol:
@ -249,10 +248,14 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver,
self.terminate_secondary(api, sclivevolume,
initiator_name)
# Find our server.
scserver = (None if not initiator_name else
api.find_server(initiator_name, ssn))
# If we have a server and a volume lets pull them apart.
if (scserver is not None and
scvolume is not None and
api.unmap_volume(scvolume, scserver) is True):
if ((scserver and
api.unmap_volume(scvolume, scserver) is True) or
(not scserver and api.unmap_all(scvolume))):
LOG.debug('Connection terminated')
return
except Exception:
@ -265,9 +268,15 @@ class SCISCSIDriver(storagecenter_common.SCCommonDriver,
_('Terminate connection failed'))
def terminate_secondary(self, api, sclivevolume, initiatorname):
# Find our server.
secondary = api.find_server(initiatorname,
sclivevolume['secondaryScSerialNumber'])
secondaryvol = api.get_volume(
sclivevolume['secondaryVolume']['instanceId'])
return api.unmap_volume(secondaryvol, secondary)
if secondaryvol:
if initiatorname:
# Find our server.
secondary = api.find_server(
initiatorname, sclivevolume['secondaryScSerialNumber'])
return api.unmap_volume(secondaryvol, secondary)
else:
return api.unmap_all(secondaryvol)
else:
LOG.debug('terminate_secondary: secondary volume not found.')