Merge "Improve 3PAR driver VLUN creation and deletion"

This commit is contained in:
Jenkins
2015-07-12 05:22:10 +00:00
committed by Gerrit Code Review
4 changed files with 97 additions and 38 deletions

View File

@@ -2096,6 +2096,7 @@ class HP3PARBaseDriver(object):
self.VOLUME_3PAR_NAME,
None,
self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.removeVolumeMetaData(
self.VOLUME_3PAR_NAME, CHAP_USER_KEY),
@@ -2997,6 +2998,8 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'name': self.FAKE_HOST
}]
}
mock_client.getVLUN.side_effect = [
hpexceptions.HTTPNotFound('fake')]
mock_client.getHostVLUNs.return_value = [
{'active': True,
'volumeName': self.VOLUME_3PAR_NAME,
@@ -3023,6 +3026,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'123456789054321']),
mock.call.getHost(self.FAKE_HOST),
mock.call.getPorts(),
mock.call.getVLUN(self.VOLUME_3PAR_NAME),
mock.call.createVLUN(
self.VOLUME_3PAR_NAME,
auto=True,
@@ -3069,6 +3073,8 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'name': self.FAKE_HOST
}]
}
mock_client.getVLUN.side_effect = [
hpexceptions.HTTPNotFound('fake')]
mock_client.getHostVLUNs.return_value = [
{'active': True,
'volumeName': self.VOLUME_3PAR_NAME,
@@ -3109,6 +3115,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
mock.ANY,
mock.call.getHost(self.FAKE_HOST),
mock.call.getPorts(),
mock.call.getVLUN(self.VOLUME_3PAR_NAME),
mock.call.getPorts(),
mock.call.createVLUN(
self.VOLUME_3PAR_NAME,
@@ -3154,6 +3161,8 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'name': self.FAKE_HOST
}]
}
mock_client.getVLUN.side_effect = [
hpexceptions.HTTPNotFound('fake')]
mock_client.getHostVLUNs.return_value = [
{'active': True,
'volumeName': self.VOLUME_3PAR_NAME,
@@ -3180,6 +3189,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'123456789054321']),
mock.call.getHost(self.FAKE_HOST),
mock.call.getPorts(),
mock.call.getVLUN(self.VOLUME_3PAR_NAME),
mock.call.createVLUN(
self.VOLUME_3PAR_NAME,
auto=True,
@@ -3203,6 +3213,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
effects = [
[{'active': True, 'volumeName': self.VOLUME_3PAR_NAME,
'lun': None, 'type': 0}],
hpexceptions.HTTPNotFound,
hpexceptions.HTTPNotFound]
mock_client.getHostVLUNs.side_effect = effects
@@ -3220,6 +3231,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
self.VOLUME_3PAR_NAME,
None,
self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.getPorts()]
@@ -3282,6 +3294,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
effects = [
[{'active': True, 'volumeName': self.VOLUME_3PAR_NAME,
'lun': None, 'type': 0}],
hpexceptions.HTTPNotFound,
hpexceptions.HTTPNotFound]
mock_client.queryHost.return_value = {
@@ -3299,6 +3312,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
self.VOLUME_3PAR_NAME,
None,
self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.getPorts()]
@@ -3368,6 +3382,7 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
self.VOLUME_3PAR_NAME,
None,
self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST)]
with mock.patch.object(hpcommon.HP3PARCommon,
@@ -3739,6 +3754,7 @@ class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
'volumeName': self.VOLUME_3PAR_NAME,
'lun': self.TARGET_LUN, 'type': 0}]
mock_client.getVLUN.return_value = {
'hostname': self.FAKE_HOST,
'lun': self.TARGET_LUN,
'portPos': {'node': 8, 'slot': 1, 'cardPort': 1}}
location = ("%(volume_name)s,%(lun_id)s,%(host)s,%(nsp)s" %
@@ -3761,13 +3777,7 @@ class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
mock.call.getHost(self.FAKE_HOST),
mock.call.queryHost(iqns=['iqn.1993-08.org.debian:01:222']),
mock.call.getHost(self.FAKE_HOST),
mock.call.getVLUN(self.VOLUME_3PAR_NAME),
mock.call.createVLUN(
self.VOLUME_3PAR_NAME,
auto=True,
hostname='fakehost',
portPos={'node': 8, 'slot': 1, 'cardPort': 1}),
mock.call.getHostVLUNs(self.FAKE_HOST)]
mock.call.getVLUN(self.VOLUME_3PAR_NAME)]
mock_client.assert_has_calls(
self.standard_login +
@@ -3795,6 +3805,7 @@ class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
'volumeName': self.VOLUME_3PAR_NAME,
'lun': self.TARGET_LUN, 'type': 0}]
mock_client.getVLUN.return_value = {
'hostname': self.FAKE_HOST,
'lun': self.TARGET_LUN,
'portPos': {'node': 8, 'slot': 1, 'cardPort': 1}}
location = ("%(volume_name)s,%(lun_id)s,%(host)s,%(nsp)s" %
@@ -3817,13 +3828,7 @@ class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
mock.call.getHost(self.FAKE_HOST),
mock.call.queryHost(iqns=['iqn.1993-08.org.debian:01:222']),
mock.call.getHost(self.FAKE_HOST),
mock.call.getVLUN(self.VOLUME_3PAR_NAME),
mock.call.createVLUN(
self.VOLUME_3PAR_NAME,
auto=True,
hostname='fakehost',
portPos={'node': 8, 'slot': 1, 'cardPort': 1}),
mock.call.getHostVLUNs(self.FAKE_HOST)]
mock.call.getVLUN(self.VOLUME_3PAR_NAME)]
mock_client.assert_has_calls(
self.standard_login +

View File

@@ -178,10 +178,11 @@ class HP3PARCommon(object):
2.0.43 - Report the capability of supporting multiattach
2.0.44 - Update help strings to reduce the 3PAR user role requirements
2.0.45 - Python 3 fixes
2.0.46 - Improved VLUN creation and deletion logic. #1469816
"""
VERSION = "2.0.45"
VERSION = "2.0.46"
stats = {}
@@ -794,24 +795,57 @@ class HP3PARCommon(object):
volume_name = self._get_3par_vol_name(volume['id'])
vluns = self.client.getHostVLUNs(hostname)
# Find all the VLUNs associated with the volume. The VLUNs will then
# be split into groups based on the active status of the VLUN. If there
# are active VLUNs detected a delete will be attempted on them. If
# there are no active VLUNs but there are inactive VLUNs, then the
# inactive VLUNs will be deleted. The inactive VLUNs are the templates
# on the 3PAR backend.
active_volume_vluns = []
inactive_volume_vluns = []
volume_vluns = []
for vlun in vluns:
if volume_name in vlun['volumeName']:
break
else:
LOG.info(_LI("3PAR vlun for volume %(name)s not found on host "
"%(host)s"), {'name': volume_name, 'host': hostname})
if vlun['active']:
active_volume_vluns.append(vlun)
else:
inactive_volume_vluns.append(vlun)
if active_volume_vluns:
volume_vluns = active_volume_vluns
elif inactive_volume_vluns:
volume_vluns = inactive_volume_vluns
if not volume_vluns:
msg = (
_LW("3PAR vlun for volume %(name)s not found on "
"host %(host)s"), {'name': volume_name, 'host': hostname})
LOG.warning(msg)
return
# VLUN Type of MATCHED_SET 4 requires the port to be provided
if self.VLUN_TYPE_MATCHED_SET == vlun['type']:
self.client.deleteVLUN(volume_name, vlun['lun'], hostname,
vlun['portPos'])
else:
self.client.deleteVLUN(volume_name, vlun['lun'], hostname)
removed_luns = []
for vlun in volume_vluns:
if self.VLUN_TYPE_MATCHED_SET == vlun['type']:
self.client.deleteVLUN(volume_name, vlun['lun'], hostname,
vlun['portPos'])
else:
# This is HOST_SEES or a type that is not MATCHED_SET.
# By deleting one VLUN, all the others should be deleted, too.
if vlun['lun'] not in removed_luns:
self.client.deleteVLUN(volume_name, vlun['lun'], hostname)
removed_luns.append(vlun['lun'])
# Determine if there are other volumes attached to the host.
# This will determine whether we should try removing host from host set
# and deleting the host.
vluns = []
try:
vluns = self.client.getHostVLUNs(hostname)
except hpexceptions.HTTPNotFound:
LOG.debug("All VLUNs removed from host %s", hostname)
pass
for vlun in vluns:
if volume_name not in vlun['volumeName']:
# Found another volume

View File

@@ -78,10 +78,11 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
2.0.14 - Removed usage of host name cache #1398914
2.0.15 - Added support for updated detach_volume attachment.
2.0.16 - Added encrypted property to initialize_connection #1439917
2.0.17 - Improved VLUN creation and deletion logic. #1469816
"""
VERSION = "2.0.16"
VERSION = "2.0.17"
def __init__(self, *args, **kwargs):
super(HP3PARFCDriver, self).__init__(*args, **kwargs)
@@ -228,17 +229,30 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
target_wwns, init_targ_map, numPaths = \
self._build_initiator_target_map(common, connector)
# now that we have a host, create the VLUN
if self.lookup_service is not None and numPaths == 1:
nsp = None
active_fc_port_list = common.get_active_fc_target_ports()
for port in active_fc_port_list:
if port['portWWN'].lower() == target_wwns[0].lower():
nsp = port['nsp']
break
vlun = common.create_vlun(volume, host, nsp)
# check if a VLUN already exists for this host
existing_vlun = None
try:
vol_name = common._get_3par_vol_name(volume['id'])
existing_vlun = common.client.getVLUN(vol_name)
except hpexceptions.HTTPNotFound:
# ignore, vlun will be created later
pass
vlun = None
if not existing_vlun or host['name'] != existing_vlun['hostname']:
# now that we have a host, create the VLUN
if self.lookup_service is not None and numPaths == 1:
nsp = None
active_fc_port_list = common.get_active_fc_target_ports()
for port in active_fc_port_list:
if port['portWWN'].lower() == target_wwns[0].lower():
nsp = port['nsp']
break
vlun = common.create_vlun(volume, host, nsp)
else:
vlun = common.create_vlun(volume, host)
else:
vlun = common.create_vlun(volume, host)
vlun = existing_vlun
info = {'driver_volume_type': 'fibre_channel',
'data': {'target_lun': vlun['lun'],

View File

@@ -87,10 +87,11 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver):
2.0.15 - Added support for updated detach_volume attachment.
2.0.16 - Added encrypted property to initialize_connection #1439917
2.0.17 - Python 3 fixes
2.0.18 - Improved VLUN creation and deletion logic. #1469816
"""
VERSION = "2.0.17"
VERSION = "2.0.18"
def __init__(self, *args, **kwargs):
super(HP3PARISCSIDriver, self).__init__(*args, **kwargs)
@@ -290,6 +291,7 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver):
connector)
least_used_nsp = None
existing_vlun = None
try:
vol_name = common._get_3par_vol_name(volume['id'])
existing_vlun = common.client.getVLUN(vol_name)
@@ -309,8 +311,12 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver):
common,
host['name'])
# now that we have a host, create the VLUN
vlun = common.create_vlun(volume, host, least_used_nsp)
vlun = None
if not existing_vlun or host['name'] != existing_vlun['hostname']:
# now that we have a host, create the VLUN
vlun = common.create_vlun(volume, host, least_used_nsp)
else:
vlun = existing_vlun
if least_used_nsp is None:
LOG.warning(_LW("Least busy iSCSI port not found, "