3PAR Only remove FC Zone on last volume detach

This patch checks to make sure that we don't
include the initiator_target_map in the return
of terminate_connection if there are volumes
still attached for a particular host.  The
FibreChannel ZoneManager doesn't remove zones
if there isn't an initiator_target_map in the
return of terminate_connection.

Change-Id: I98db5adb6da38454933a6e4b78085193f1d37680
Partial-Bug: #1308318
This commit is contained in:
Walter A. Boring IV 2014-06-27 16:00:01 -07:00
parent 350334dec0
commit 5cf52914bd
2 changed files with 38 additions and 15 deletions

View File

@ -1318,10 +1318,13 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
mock_client = self.setup_driver()
mock_client.getHostVLUNs.return_value = [
{'active': True,
'volumeName': self.VOLUME_3PAR_NAME,
'lun': None, 'type': 0}]
effects = [
[{'active': True, 'volumeName': self.VOLUME_3PAR_NAME,
'lun': None, 'type': 0}],
hpexceptions.HTTPNotFound]
mock_client.getHostVLUNs.side_effect = effects
expected = [
mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
@ -1331,13 +1334,19 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
None,
self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.getPorts(),
mock.call.logout()]
self.driver.terminate_connection(self.volume, self.connector)
conn_info = self.driver.terminate_connection(self.volume,
self.connector)
mock_client.assert_has_calls(expected)
self.assertIn('data', conn_info)
self.assertIn('initiator_target_map', conn_info['data'])
mock_client.reset_mock()
mock_client.getHostVLUNs.side_effect = effects
# mock some deleteHost exceptions that are handled
delete_with_vlun = hpexceptions.HTTPConflict(
error={'message': "has exported VLUN"})
@ -1346,11 +1355,14 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
mock_client.deleteHost = mock.Mock(
side_effect=[delete_with_vlun, delete_with_hostset])
self.driver.terminate_connection(self.volume, self.connector)
conn_info = self.driver.terminate_connection(self.volume,
self.connector)
mock_client.assert_has_calls(expected)
mock_client.reset_mock()
mock_client.getHostVLUNs.side_effect = effects
self.driver.terminate_connection(self.volume, self.connector)
conn_info = self.driver.terminate_connection(self.volume,
self.connector)
mock_client.assert_has_calls(expected)
def test_terminate_connection_more_vols(self):
@ -1373,11 +1385,13 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
self.VOLUME_3PAR_NAME,
None,
self.FAKE_HOST),
mock.call.getPorts(),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.logout()]
self.driver.terminate_connection(self.volume, self.connector)
conn_info = self.driver.terminate_connection(self.volume,
self.connector)
mock_client.assert_has_calls(expect_less)
self.assertNotIn('initiator_target_map', conn_info['data'])
def test_get_volume_stats(self):
# setup_mock_client drive with default configuration

View File

@ -62,10 +62,11 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
2.0.2 - Add back-end assisted volume migrate
2.0.3 - Added initiator-target map for FC Zone Manager
2.0.4 - Added support for managing/unmanaging of volumes
2.0.5 - Only remove FC Zone on last volume detach
"""
VERSION = "2.0.4"
VERSION = "2.0.5"
def __init__(self, *args, **kwargs):
super(HP3PARFCDriver, self).__init__(*args, **kwargs)
@ -229,12 +230,20 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
self.common.terminate_connection(volume, hostname,
wwn=connector['wwpns'])
target_wwns, init_targ_map = self._build_initiator_target_map(
connector)
info = {'driver_volume_type': 'fibre_channel',
'data': {'target_wwn': target_wwns,
'initiator_target_map': init_targ_map}}
'data': {}}
try:
self.common.client.getHostVLUNs(hostname)
except hpexceptions.HTTPNotFound:
# No more exports for this host.
LOG.info(_("Need to remove FC Zone, building initiator "
"target map"))
target_wwns, init_targ_map = self._build_initiator_target_map(
connector)
info['data'] = {'target_wwn': target_wwns,
'initiator_target_map': init_targ_map}
return info
finally: