NetApp fix attach fail for already mapped volume
This patch fixes the error raised during mapping of a volume to the host during attach operation if the volume is already mapped to the host. Change-Id: I4f711e7ac18eea0dfddab65fd85a3601fe967a88 Closes-bug: #1310659
This commit is contained in:
parent
e524456814
commit
dcec1b84f4
@ -666,6 +666,52 @@ class NetAppEseriesIscsiDriverTestCase(test.TestCase):
|
|||||||
self.driver.terminate_connection(self.volume, self.connector)
|
self.driver.terminate_connection(self.volume, self.connector)
|
||||||
self.driver.delete_volume(self.volume)
|
self.driver.delete_volume(self.volume)
|
||||||
|
|
||||||
|
def test_map_already_mapped_same_host(self):
|
||||||
|
self.driver.create_volume(self.volume)
|
||||||
|
|
||||||
|
maps = [{'lunMappingRef': 'hdkjsdhjsdh',
|
||||||
|
'mapRef': '8400000060080E500023C73400300381515BFBA3',
|
||||||
|
'volumeRef': 'CFDXJ67BLJH25DXCZFZD4NSF54',
|
||||||
|
'lun': 2}]
|
||||||
|
self.driver._get_host_mapping_for_vol_frm_array = mock.Mock(
|
||||||
|
return_value=maps)
|
||||||
|
self.driver._get_free_lun = mock.Mock()
|
||||||
|
info = self.driver.initialize_connection(self.volume, self.connector)
|
||||||
|
self.assertEqual(
|
||||||
|
self.driver._get_host_mapping_for_vol_frm_array.call_count, 1)
|
||||||
|
self.assertEqual(self.driver._get_free_lun.call_count, 0)
|
||||||
|
self.assertEqual(info['driver_volume_type'], 'iscsi')
|
||||||
|
properties = info.get('data')
|
||||||
|
self.assertIsNotNone(properties, 'Target portal is none')
|
||||||
|
self.driver.terminate_connection(self.volume, self.connector)
|
||||||
|
self.driver.delete_volume(self.volume)
|
||||||
|
|
||||||
|
def test_map_already_mapped_diff_host(self):
|
||||||
|
self.driver.create_volume(self.volume)
|
||||||
|
|
||||||
|
maps = [{'lunMappingRef': 'hdkjsdhjsdh',
|
||||||
|
'mapRef': '7400000060080E500023C73400300381515BFBA3',
|
||||||
|
'volumeRef': 'CFDXJ67BLJH25DXCZFZD4NSF54',
|
||||||
|
'lun': 2}]
|
||||||
|
self.driver._get_host_mapping_for_vol_frm_array = mock.Mock(
|
||||||
|
return_value=maps)
|
||||||
|
self.driver._get_vol_mapping_for_host_frm_array = mock.Mock(
|
||||||
|
return_value=[])
|
||||||
|
self.driver._get_free_lun = mock.Mock(return_value=0)
|
||||||
|
self.driver._del_vol_mapping_frm_cache = mock.Mock()
|
||||||
|
info = self.driver.initialize_connection(self.volume, self.connector)
|
||||||
|
self.assertEqual(
|
||||||
|
self.driver._get_vol_mapping_for_host_frm_array.call_count, 1)
|
||||||
|
self.assertEqual(
|
||||||
|
self.driver._get_host_mapping_for_vol_frm_array.call_count, 1)
|
||||||
|
self.assertEqual(self.driver._get_free_lun.call_count, 1)
|
||||||
|
self.assertEqual(self.driver._del_vol_mapping_frm_cache.call_count, 1)
|
||||||
|
self.assertEqual(info['driver_volume_type'], 'iscsi')
|
||||||
|
properties = info.get('data')
|
||||||
|
self.assertIsNotNone(properties, 'Target portal is none')
|
||||||
|
self.driver.terminate_connection(self.volume, self.connector)
|
||||||
|
self.driver.delete_volume(self.volume)
|
||||||
|
|
||||||
def test_cloned_volume_destroy(self):
|
def test_cloned_volume_destroy(self):
|
||||||
self.driver.create_volume(self.volume)
|
self.driver.create_volume(self.volume)
|
||||||
self.driver.create_cloned_volume(self.snapshot, self.volume)
|
self.driver.create_cloned_volume(self.snapshot, self.volume)
|
||||||
|
@ -210,6 +210,9 @@ class Driver(driver.ISCSIDriver):
|
|||||||
vol_id = mapping['volumeRef']
|
vol_id = mapping['volumeRef']
|
||||||
volume = self._objects['volumes']['ref_vol'][vol_id]
|
volume = self._objects['volumes']['ref_vol'][vol_id]
|
||||||
volume['listOfMappings'] = volume.get('listOfMappings') or []
|
volume['listOfMappings'] = volume.get('listOfMappings') or []
|
||||||
|
for mapp in volume['listOfMappings']:
|
||||||
|
if mapp['lunMappingRef'] == mapping['lunMappingRef']:
|
||||||
|
return
|
||||||
volume['listOfMappings'].append(mapping)
|
volume['listOfMappings'].append(mapping)
|
||||||
|
|
||||||
def _del_volume_frm_cache(self, label):
|
def _del_volume_frm_cache(self, label):
|
||||||
@ -515,7 +518,15 @@ class Driver(driver.ISCSIDriver):
|
|||||||
def _map_volume_to_host(self, vol, initiator):
|
def _map_volume_to_host(self, vol, initiator):
|
||||||
"""Maps the e-series volume to host with initiator."""
|
"""Maps the e-series volume to host with initiator."""
|
||||||
host = self._get_or_create_host(initiator)
|
host = self._get_or_create_host(initiator)
|
||||||
lun = self._get_free_lun(host)
|
vol_maps = self._get_host_mapping_for_vol_frm_array(vol)
|
||||||
|
for vol_map in vol_maps:
|
||||||
|
if vol_map.get('mapRef') == host['hostRef']:
|
||||||
|
return vol_map
|
||||||
|
else:
|
||||||
|
self._client.delete_volume_mapping(vol_map['lunMappingRef'])
|
||||||
|
self._del_vol_mapping_frm_cache(vol_map)
|
||||||
|
mappings = self._get_vol_mapping_for_host_frm_array(host['hostRef'])
|
||||||
|
lun = self._get_free_lun(host, mappings)
|
||||||
return self._client.create_volume_mapping(vol['volumeRef'],
|
return self._client.create_volume_mapping(vol['volumeRef'],
|
||||||
host['hostRef'], lun)
|
host['hostRef'], lun)
|
||||||
|
|
||||||
@ -559,9 +570,10 @@ class Driver(driver.ISCSIDriver):
|
|||||||
return ht
|
return ht
|
||||||
raise exception.NotFound(_("Host type %s not supported.") % host_type)
|
raise exception.NotFound(_("Host type %s not supported.") % host_type)
|
||||||
|
|
||||||
def _get_free_lun(self, host):
|
def _get_free_lun(self, host, maps=None):
|
||||||
"""Gets free lun for given host."""
|
"""Gets free lun for given host."""
|
||||||
luns = self._get_vol_mapping_for_host_frm_array(host['hostRef'])
|
ref = host['hostRef']
|
||||||
|
luns = maps or self._get_vol_mapping_for_host_frm_array(ref)
|
||||||
used_luns = set(map(lambda lun: int(lun['lun']), luns))
|
used_luns = set(map(lambda lun: int(lun['lun']), luns))
|
||||||
for lun in xrange(self.MAX_LUNS_PER_HOST):
|
for lun in xrange(self.MAX_LUNS_PER_HOST):
|
||||||
if lun not in used_luns:
|
if lun not in used_luns:
|
||||||
@ -571,10 +583,17 @@ class Driver(driver.ISCSIDriver):
|
|||||||
|
|
||||||
def _get_vol_mapping_for_host_frm_array(self, host_ref):
|
def _get_vol_mapping_for_host_frm_array(self, host_ref):
|
||||||
"""Gets all volume mappings for given host from array."""
|
"""Gets all volume mappings for given host from array."""
|
||||||
mappings = self._client.get_volume_mappings()
|
mappings = self._client.get_volume_mappings() or []
|
||||||
host_maps = filter(lambda x: x.get('mapRef') == host_ref, mappings)
|
host_maps = filter(lambda x: x.get('mapRef') == host_ref, mappings)
|
||||||
return host_maps
|
return host_maps
|
||||||
|
|
||||||
|
def _get_host_mapping_for_vol_frm_array(self, volume):
|
||||||
|
"""Gets all host mappings for given volume from array."""
|
||||||
|
mappings = self._client.get_volume_mappings() or []
|
||||||
|
host_maps = filter(lambda x: x.get('volumeRef') == volume['volumeRef'],
|
||||||
|
mappings)
|
||||||
|
return host_maps
|
||||||
|
|
||||||
def terminate_connection(self, volume, connector, **kwargs):
|
def terminate_connection(self, volume, connector, **kwargs):
|
||||||
"""Disallow connection from connector."""
|
"""Disallow connection from connector."""
|
||||||
vol = self._get_volume(volume['id'])
|
vol = self._get_volume(volume['id'])
|
||||||
|
Loading…
Reference in New Issue
Block a user