Merge "Dell EMC SC: Terminate_connection chokes on None."
This commit is contained in:
commit
26f03386f6
@ -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',
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.')
|
||||
|
Loading…
x
Reference in New Issue
Block a user