From: Anthony Lee Date: Tue, 9 Dec 2014 01:12:27 +0000 (-0800) Subject: Fixing 3PAR connection name cache error X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=9c50182b4a2ea86a305c5d33ec767340574a522e;p=openstack-build%2Fcinder-build.git Fixing 3PAR connection name cache error The 3PAR driver had a connection name cache in 3PAR common. If Cinder was restarted or the common object was destroyed the cache was lost. Instead of having the cache in 3PAR common, the 3PAR driver can query the backend to see if there is a host already available. Replacing the name cache with a backend query had minimal impact on performance of the driver and eliminates the problem of the cache being destroyed/lost. Closes-Bug: #1398914 Change-Id: Ie5467abc38946cceb4896fe9cbbd1606c7fbfba2 --- diff --git a/cinder/tests/test_hp3par.py b/cinder/tests/test_hp3par.py index 93719067f..abdd6a44d 100644 --- a/cinder/tests/test_hp3par.py +++ b/cinder/tests/test_hp3par.py @@ -1801,6 +1801,12 @@ class HP3PARBaseDriver(object): 'volumeName': self.VOLUME_3PAR_NAME, 'lun': None, 'type': 0}] + mock_client.queryHost.return_value = { + 'members': [{ + 'name': self.FAKE_HOST + }] + } + with mock.patch.object(hpcommon.HP3PARCommon, '_create_client')\ as mock_create_client: mock_create_client.return_value = mock_client @@ -1810,6 +1816,7 @@ class HP3PARBaseDriver(object): force=True) expected = [ + mock.call.queryHost(iqns=[self.connector['initiator']]), mock.call.getHostVLUNs(self.FAKE_HOST), mock.call.deleteVLUN( self.VOLUME_3PAR_NAME, @@ -2789,7 +2796,14 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase): mock_client.getHostVLUNs.side_effect = effects + mock_client.queryHost.return_value = { + 'members': [{ + 'name': self.FAKE_HOST + }] + } + expected = [ + mock.call.queryHost(wwns=['123456789012345', '123456789054321']), mock.call.getHostVLUNs(self.FAKE_HOST), mock.call.deleteVLUN( self.VOLUME_3PAR_NAME, @@ -2859,9 +2873,16 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase): 'lun': None, 'type': 0}], hpexceptions.HTTPNotFound] + mock_client.queryHost.return_value = { + 'members': [{ + 'name': self.FAKE_HOST + }] + } + mock_client.getHostVLUNs.side_effect = effects expected = [ + mock.call.queryHost(wwns=['123456789012345', '123456789054321']), mock.call.getHostVLUNs(self.FAKE_HOST), mock.call.deleteVLUN( self.VOLUME_3PAR_NAME, @@ -2923,7 +2944,14 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase): 'lun': None, 'type': 0}, ] + mock_client.queryHost.return_value = { + 'members': [{ + 'name': self.FAKE_HOST + }] + } + expect_less = [ + mock.call.queryHost(wwns=['123456789012345', '123456789054321']), mock.call.getHostVLUNs(self.FAKE_HOST), mock.call.deleteVLUN( self.VOLUME_3PAR_NAME, diff --git a/cinder/volume/drivers/san/hp/hp_3par_common.py b/cinder/volume/drivers/san/hp/hp_3par_common.py index 0a697799b..9b60ad16c 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_common.py +++ b/cinder/volume/drivers/san/hp/hp_3par_common.py @@ -160,10 +160,11 @@ class HP3PARCommon(object): 2.0.28 - Removing locks bug #1381190 2.0.29 - Report a limitless cpg's stats better bug #1398651 2.0.30 - Update the minimum hp3parclient version bug #1402115 + 2.0.31 - Removed usage of host name cache #1398914 """ - VERSION = "2.0.30" + VERSION = "2.0.31" stats = {} @@ -199,7 +200,6 @@ class HP3PARCommon(object): def __init__(self, config): self.config = config - self.hosts_naming_dict = dict() self.client = None self.uuid = uuid.uuid4() @@ -767,7 +767,6 @@ class HP3PARCommon(object): try: self._delete_3par_host(hostname) - self._remove_hosts_naming_dict_host(hostname) except Exception as ex: # Any exception down here is only logged. The vlun is deleted. @@ -786,15 +785,6 @@ class HP3PARCommon(object): 'reason': ex.get_description()}) LOG.info(msg) - def _remove_hosts_naming_dict_host(self, hostname): - items = self.hosts_naming_dict.items() - lkey = None - for key, value in items: - if value == hostname: - lkey = key - if lkey is not None: - del self.hosts_naming_dict[lkey] - def _get_volume_type(self, type_id): ctxt = context.get_admin_context() return volume_types.get_volume_type(ctxt, type_id) @@ -1606,10 +1596,17 @@ class HP3PARCommon(object): def terminate_connection(self, volume, hostname, wwn=None, iqn=None): """Driver entry point to unattach a volume from an instance.""" + # does 3par know this host by a different name? + hosts = None + if wwn: + hosts = self.client.queryHost(wwns=wwn) + elif iqn: + hosts = self.client.queryHost(iqns=[iqn]) + + if hosts and hosts['members'] and 'name' in hosts['members'][0]: + hostname = hosts['members'][0]['name'] + try: - # does 3par know this host by a different name? - if hostname in self.hosts_naming_dict: - hostname = self.hosts_naming_dict.get(hostname) self.delete_vlun(volume, hostname) return except hpexceptions.HTTPNotFound as e: diff --git a/cinder/volume/drivers/san/hp/hp_3par_fc.py b/cinder/volume/drivers/san/hp/hp_3par_fc.py index dcf9453b8..4bec1a7ec 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_fc.py +++ b/cinder/volume/drivers/san/hp/hp_3par_fc.py @@ -74,10 +74,11 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver): 2.0.11 - Removing locks bug #1381190 2.0.12 - Fix queryHost call to specify wwns bug #1398206 2.0.13 - Fix missing host name during attach bug #1398206 + 2.0.14 - Removed usage of host name cache #1398914 """ - VERSION = "2.0.13" + VERSION = "2.0.14" def __init__(self, *args, **kwargs): super(HP3PARFCDriver, self).__init__(*args, **kwargs) @@ -325,7 +326,6 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver): host_found = hosts['members'][0]['name'] if host_found is not None: - common.hosts_naming_dict[hostname] = host_found return host_found else: persona_id = int(persona_id) diff --git a/cinder/volume/drivers/san/hp/hp_3par_iscsi.py b/cinder/volume/drivers/san/hp/hp_3par_iscsi.py index 612160a39..7a433c958 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_iscsi.py +++ b/cinder/volume/drivers/san/hp/hp_3par_iscsi.py @@ -78,10 +78,11 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver): 2.0.9 - Removing locks bug #1381190 2.0.10 - Add call to queryHost instead SSH based findHost #1398206 2.0.11 - Added missing host name during attach fix #1398206 + 2.0.12 - Removed usage of host name cache #1398914 """ - VERSION = "2.0.11" + VERSION = "2.0.12" def __init__(self, *args, **kwargs): super(HP3PARISCSIDriver, self).__init__(*args, **kwargs) @@ -361,7 +362,6 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver): host_found = hosts['members'][0]['name'] if host_found is not None: - common.hosts_naming_dict[hostname] = host_found return host_found else: if isinstance(iscsi_iqn, str) or isinstance(iscsi_iqn, unicode):