# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
mock_client = self.setup_driver()
- mock_client.getVLUN.return_value = {'lun': None, 'type': 0}
+ mock_client.getHostVLUNs.return_value = [
+ {'active': True,
+ 'volumeName': self.VOLUME_3PAR_NAME,
+ 'lun': None, 'type': 0}]
self.driver.terminate_connection(
self.volume,
expected = [
mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
- mock.call.getVLUN(self.VOLUME_3PAR_NAME),
+ mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteVLUN(
self.VOLUME_3PAR_NAME,
None,
'vendor': None,
'wwn': self.wwn[1]}]}]
mock_client.findHost.return_value = self.FAKE_HOST
- mock_client.getVLUN.return_value = {'lun': 90}
+ mock_client.getHostVLUNs.return_value = [
+ {'active': True,
+ 'volumeName': self.VOLUME_3PAR_NAME,
+ 'lun': 90, 'type': 0}]
mock_client.getPorts.return_value = {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}
expected = [
mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
- mock.call.getVolume('osv-0DM4qZEVSKON-DXN-NwVpw'),
+ mock.call.getVolume(self.VOLUME_3PAR_NAME),
mock.call.getCPG(HP3PAR_CPG),
mock.call.getHost(self.FAKE_HOST),
mock.ANY,
mock.call.getHost(self.FAKE_HOST),
mock.call.createVLUN(
- 'osv-0DM4qZEVSKON-DXN-NwVpw',
+ self.VOLUME_3PAR_NAME,
auto=True,
hostname=self.FAKE_HOST),
- mock.call.getVLUN('osv-0DM4qZEVSKON-DXN-NwVpw'),
+ mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.getPorts(),
mock.call.logout()]
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
mock_client = self.setup_driver()
- mock_client.getVLUN.return_value = {'lun': None, 'type': 0}
+ mock_client.getHostVLUNs.return_value = [
+ {'active': True,
+ 'volumeName': self.VOLUME_3PAR_NAME,
+ 'lun': None, 'type': 0}]
mock_client.getPorts.return_value = {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}
expected = [
mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
- mock.call.getVLUN(self.VOLUME_3PAR_NAME),
+ mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteVLUN(
self.VOLUME_3PAR_NAME,
None,
hpexceptions.HTTPNotFound('fake'),
{'name': self.FAKE_HOST}]
mock_client.findHost.return_value = self.FAKE_HOST
- mock_client.getVLUN.return_value = {'lun': self.TARGET_LUN}
+ mock_client.getHostVLUNs.return_value = [
+ {'active': True,
+ 'volumeName': self.VOLUME_3PAR_NAME,
+ 'lun': self.TARGET_LUN, 'type': 0}]
result = self.driver.initialize_connection(self.volume, self.connector)
expected = [
mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
- mock.call.getVolume('osv-0DM4qZEVSKON-DXN-NwVpw'),
+ mock.call.getVolume(self.VOLUME_3PAR_NAME),
mock.call.getCPG(HP3PAR_CPG),
mock.call.getHost(self.FAKE_HOST),
mock.call.findHost(iqn='iqn.1993-08.org.debian:01:222'),
mock.call.getHost(self.FAKE_HOST),
mock.call.createVLUN(
- 'osv-0DM4qZEVSKON-DXN-NwVpw',
+ self.VOLUME_3PAR_NAME,
auto=True,
hostname='fakehost',
portPos={'node': 8, 'slot': 1, 'cardPort': 1}),
- mock.call.getVLUN('osv-0DM4qZEVSKON-DXN-NwVpw'),
+ mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.logout()]
mock_client.assert_has_calls(expected)
2.0.5 - Fix extend volume units bug #1284368
2.0.6 - use loopingcall.wait instead of time.sleep
2.0.7 - Allow extend volume based on snapshot bug #1285906
+ 2.0.8 - Fix detach issue for multiple hosts Bug #1288927
"""
- VERSION = "2.0.7"
+ VERSION = "2.0.8"
stats = {}
'hp3par_cpg')})
self.stats = stats
+ def _get_vlun(self, volume_name, hostname):
+ """find a VLUN on a 3PAR host."""
+ vluns = self.client.getHostVLUNs(hostname)
+ found_vlun = None
+ for vlun in vluns:
+ if volume_name in vlun['volumeName']:
+ found_vlun = vlun
+ break
+
+ msg = (_("3PAR vlun %(name)s not found on host %(host)s") %
+ {'name': volume_name, 'host': hostname})
+ if found_vlun is None:
+ LOG.warn(msg)
+ return found_vlun
+
def create_vlun(self, volume, host, nsp=None):
"""Create a VLUN.
"""
volume_name = self._get_3par_vol_name(volume['id'])
self._create_3par_vlun(volume_name, host['name'], nsp)
- return self.client.getVLUN(volume_name)
+ return self._get_vlun(volume_name, host['name'])
def delete_vlun(self, volume, hostname):
volume_name = self._get_3par_vol_name(volume['id'])
- vlun = self.client.getVLUN(volume_name)
- # 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)
+ vlun = self._get_vlun(volume_name, hostname)
+
+ if vlun is not None:
+ # 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)
try:
self._delete_3par_host(hostname)