Storwize: remove SCSI LUN ID for volume attaching

The VDisk-to-host mapping may fail due to the SCSI LUN
id is already used by other VDisk mapping to this host,
which is caused by serveral cinder volume nodes run
parallelly and serveral volumes attaching parallelly.

storwize volume driver does not need to calculate SCSI LUN
ID locally for volume attaching. The SCSI LUN ID can be
decided by storage backend correctly.

Closes-Bug: 1603282
Change-Id: Ic8d229b539f1b2b79f530f966eb09154e5f13a2c
This commit is contained in:
Xiaoqin Li 2016-08-25 17:47:50 +08:00
parent ca9038628e
commit f3d1be2319
2 changed files with 61 additions and 36 deletions

View File

@ -1084,14 +1084,14 @@ port_speed!N/A
def _cmd_mkvdiskhostmap(self, **kwargs):
mapping_info = {}
mapping_info['id'] = self._find_unused_id(self._mappings_list)
if 'host' not in kwargs:
return self._errors['CMMVC5707E']
mapping_info['host'] = kwargs['host'].strip('\'\"')
if 'scsi' not in kwargs:
return self._errors['CMMVC5707E']
mapping_info['lun'] = kwargs['scsi'].strip('\'\"')
if 'scsi' in kwargs:
mapping_info['lun'] = kwargs['scsi'].strip('\'\"')
else:
mapping_info['lun'] = mapping_info['id']
if 'obj' not in kwargs:
return self._errors['CMMVC5707E']
@ -1112,7 +1112,7 @@ port_speed!N/A
return self._errors['CMMVC5879E']
for v in self._mappings_list.values():
if (v['lun'] == mapping_info['lun']) and ('force' not in kwargs):
if (v['vol'] == mapping_info['vol']) and ('force' not in kwargs):
return self._errors['CMMVC6071E']
self._mappings_list[mapping_info['id']] = mapping_info
@ -1169,7 +1169,7 @@ port_speed!N/A
# List information about vdisk->host mappings
def _cmd_lsvdiskhostmap(self, **kwargs):
mappings_found = 0
vdisk_name = kwargs['obj']
vdisk_name = kwargs['obj'].strip('\'\"')
if vdisk_name not in self._volumes_list:
return self._errors['CMMVC5753E']
@ -1183,7 +1183,7 @@ port_speed!N/A
mappings_found += 1
volume = self._volumes_list[mapping['vol']]
host = self._hosts_list[mapping['host']]
rows.append([volume['id'], volume['name'], host['id'],
rows.append([volume['id'], mapping['lun'], host['id'],
host['host_name'], volume['uid'],
volume['IO_group_id'], volume['IO_group_name']])
@ -5187,23 +5187,42 @@ class StorwizeHelpersTestCase(test.TestCase):
class StorwizeSSHTestCase(test.TestCase):
def setUp(self):
super(StorwizeSSHTestCase, self).setUp()
self.storwize_ssh = storwize_svc_common.StorwizeSSH(None)
self.fake_driver = StorwizeSVCISCSIFakeDriver(
configuration=conf.Configuration(None))
sim = StorwizeSVCManagementSimulator(['openstack'])
self.fake_driver.set_fake_storage(sim)
self.storwize_ssh = storwize_svc_common.StorwizeSSH(
self.fake_driver._run_ssh)
def test_mkvdiskhostmap(self):
# mkvdiskhostmap should not be returning anything
self.fake_driver.fake_storage._volumes_list['9999'] = {
'name': ' 9999', 'id': '0', 'uid': '0',
'IO_group_id': '0', 'IO_group_name': 'fakepool'}
self.fake_driver.fake_storage._hosts_list['HOST1'] = {
'name': 'HOST1', 'id': '0', 'host_name': 'HOST1'}
self.fake_driver.fake_storage._hosts_list['HOST2'] = {
'name': 'HOST2', 'id': '1', 'host_name': 'HOST2'}
self.fake_driver.fake_storage._hosts_list['HOST3'] = {
'name': 'HOST3', 'id': '2', 'host_name': 'HOST3'}
ret = self.storwize_ssh.mkvdiskhostmap('HOST1', '9999', '511', False)
self.assertEqual('511', ret)
ret = self.storwize_ssh.mkvdiskhostmap('HOST2', '9999', '512', True)
self.assertEqual('512', ret)
ret = self.storwize_ssh.mkvdiskhostmap('HOST3', '9999', None, True)
self.assertIsNotNone(ret)
with mock.patch.object(
storwize_svc_common.StorwizeSSH,
'run_ssh_check_created') as run_ssh_check_created:
run_ssh_check_created.return_value = None
ret = self.storwize_ssh.mkvdiskhostmap('HOST1', 9999, 511, False)
self.assertIsNone(ret)
ret = self.storwize_ssh.mkvdiskhostmap('HOST2', 9999, 511, True)
self.assertIsNone(ret)
ex = exception.VolumeBackendAPIException(data='CMMVC6071E')
run_ssh_check_created.side_effect = ex
self.assertRaises(exception.VolumeBackendAPIException,
self.storwize_ssh.mkvdiskhostmap,
'HOST3', 9999, 511, True)
'HOST3', '9999', 511, True)
class StorwizeSVCReplicationMirrorTestCase(test.TestCase):

View File

@ -254,12 +254,26 @@ class StorwizeSSH(object):
If vdisk already mapped and multihostmap is True, use the force flag.
"""
ssh_cmd = ['svctask', 'mkvdiskhostmap', '-host', '"%s"' % host,
'-scsi', lun, '"%s"' % vdisk]
ssh_cmd = ['svctask', 'mkvdiskhostmap', '-host', '"%s"' % host, vdisk]
if lun:
ssh_cmd.insert(ssh_cmd.index(vdisk), '-scsi')
ssh_cmd.insert(ssh_cmd.index(vdisk), lun)
if multihostmap:
ssh_cmd.insert(ssh_cmd.index('mkvdiskhostmap') + 1, '-force')
try:
self.run_ssh_check_created(ssh_cmd)
result_lun = self.get_vdiskhostmapid(vdisk, host)
if result_lun is None or (lun and lun != result_lun):
msg = (_('mkvdiskhostmap error:\n command: %(cmd)s\n '
'lun: %(lun)s\n result_lun: %(result_lun)s') %
{'cmd': ssh_cmd,
'lun': lun,
'result_lun': result_lun})
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
return result_lun
except Exception as ex:
if (not multihostmap and hasattr(ex, 'message') and
'CMMVC6071E' in ex.message):
@ -347,6 +361,14 @@ class StorwizeSSH(object):
ssh_cmd = ['svcinfo', 'lshostvdiskmap', '-delim', '!', '"%s"' % host]
return self.run_ssh_info(ssh_cmd, with_header=True)
def get_vdiskhostmapid(self, vdisk, host):
resp = self.lsvdiskhostmap(vdisk)
for mapping_info in resp:
if mapping_info['host_name'] == host:
lun_id = mapping_info['SCSI_id']
return lun_id
return None
def rmhost(self, host):
ssh_cmd = ['svctask', 'rmhost', '"%s"' % host]
self.run_ssh_assert_no_output(ssh_cmd)
@ -852,26 +874,10 @@ class StorwizeHelpers(object):
{'volume_name': volume_name, 'host_name': host_name})
# Check if this volume is already mapped to this host
mapped = False
luns_used = []
result_lun = '-1'
resp = self.ssh.lshostvdiskmap(host_name)
for mapping_info in resp:
luns_used.append(int(mapping_info['SCSI_id']))
if mapping_info['vdisk_name'] == volume_name:
mapped = True
result_lun = mapping_info['SCSI_id']
if not mapped:
# Find unused lun
luns_used.sort()
result_lun = str(len(luns_used))
for index, n in enumerate(luns_used):
if n > index:
result_lun = str(index)
break
self.ssh.mkvdiskhostmap(host_name, volume_name, result_lun,
multihostmap)
result_lun = self.ssh.get_vdiskhostmapid(volume_name, host_name)
if result_lun is None:
result_lun = self.ssh.mkvdiskhostmap(host_name, volume_name, None,
multihostmap)
LOG.debug('Leave: map_vol_to_host: LUN %(result_lun)s, volume '
'%(volume_name)s, host %(host_name)s.',