NEC driver: Reuse iSCSI LUNs of detached volumes.
Currently, NEC driver does not reuse iSCSI LUNs of detached volumes. The driver always use the LUN of (max(LUNs used) + 1) to attach a volume. If multi-target mode of NEC Storage is enabled, the driver works without the problem because only LUN0s are used in the multi-target mode. This patch changes the using LUN to min(LUNs not used) for reusing a LUN of detached volume with multi-target mode disabled. Change-Id: I067cb09928c4c9d4ebb7159950fff526ee70f1bb Closes-Bug: #1778669
This commit is contained in:
parent
fc19a0dca8
commit
78f104d75c
cinder
@ -838,7 +838,8 @@ class ExportTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.vol.status = None
|
||||
self.vol.migration_status = None
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255"}
|
||||
self.iscsi_do_export(None, self.vol, connector)
|
||||
self.iscsi_do_export(None, self.vol, connector,
|
||||
self._properties['diskarray_name'])
|
||||
|
||||
@mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI._execute',
|
||||
patch_execute)
|
||||
@ -1019,7 +1020,8 @@ class ExportTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255"}
|
||||
self._properties['ldset_controller_node_name'] = 'LX:OpenStack1'
|
||||
self._properties['portal_number'] = 2
|
||||
location = self.iscsi_do_export(None, self.vol, connector)
|
||||
location = self.iscsi_do_export(None, self.vol, connector,
|
||||
self._properties['diskarray_name'])
|
||||
self.assertEqual('192.168.1.90:3260;192.168.1.91:3260;'
|
||||
'192.168.2.92:3260;192.168.2.93:3260'
|
||||
',1 iqn.2001-03.target0000 0',
|
||||
@ -1119,6 +1121,7 @@ class NonDisruptiveBackup_test(volume_helper.MStorageDSVDriver,
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f232XX"}
|
||||
mock_data = {'ldsetname': 'LX:redhatd1d8e8f23',
|
||||
'protocol': 'iSCSI',
|
||||
'mode': 'Multi-Target',
|
||||
'portal_list': ['1.1.1.1:3260', '2.2.2.2:3260'],
|
||||
'lds': {},
|
||||
'initiator_list':
|
||||
@ -1230,6 +1233,50 @@ class VolumeStats_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.assertEqual('0,1', stats.get('location_info').split(':')[1])
|
||||
|
||||
|
||||
class GetFreeLun_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(GetFreeLun_test, self).setUp()
|
||||
self.do_setup(None)
|
||||
|
||||
def test_get_free_lun_iscsi_multi(self):
|
||||
ldset = {'protocol': 'iSCSI',
|
||||
'mode': 'Multi-Target',
|
||||
'lds': {}}
|
||||
target_lun = self._get_free_lun(ldset)
|
||||
self.assertIsNone(target_lun)
|
||||
|
||||
def test_get_free_lun_iscsi_lun0(self):
|
||||
ldset = {'protocol': 'iSCSI',
|
||||
'mode': 'Normal',
|
||||
'lds': {}}
|
||||
target_lun = self._get_free_lun(ldset)
|
||||
self.assertEqual(0, target_lun)
|
||||
|
||||
def test_get_free_lun_iscsi_lun2(self):
|
||||
ld0 = {'lun': 0}
|
||||
ld1 = {'lun': 1}
|
||||
ld3 = {'lun': 3}
|
||||
ldsetlds = {}
|
||||
ldsetlds[0] = ld0
|
||||
ldsetlds[1] = ld1
|
||||
ldsetlds[3] = ld3
|
||||
ldset = {'protocol': 'iSCSI',
|
||||
'mode': 'Normal',
|
||||
'lds': ldsetlds}
|
||||
target_lun = self._get_free_lun(ldset)
|
||||
self.assertEqual(2, target_lun)
|
||||
|
||||
def test_get_free_lun_fc_lun1(self):
|
||||
ld0 = {'lun': 0}
|
||||
ldsetlds = {}
|
||||
ldsetlds[0] = ld0
|
||||
ldset = {'lds': ldsetlds,
|
||||
'protocol': 'FC'}
|
||||
target_lun = self._get_free_lun(ldset)
|
||||
self.assertEqual(1, target_lun)
|
||||
|
||||
|
||||
class Migrate_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
|
||||
@mock.patch('cinder.volume.drivers.nec.volume_common.MStorageVolumeCommon.'
|
||||
|
@ -255,8 +255,7 @@ class MStorageISMCLI(object):
|
||||
|
||||
def addldset_iscsi(self, ldsetname, connector):
|
||||
"""Create new iSCSI LD Set."""
|
||||
cmd = ('iSMcfg addldset -ldset LX:%s -multitarget on'
|
||||
' -type iscsi' % ldsetname)
|
||||
cmd = ('iSMcfg addldset -ldset LX:%s -type iscsi' % ldsetname)
|
||||
out, err, status = self._execute(cmd, [0], False)
|
||||
if status != 0:
|
||||
return False
|
||||
|
@ -656,6 +656,7 @@ class MStorageVolumeCommon(object):
|
||||
{'mode': tmode, 'line': unit.sourceline, 'out': xml})
|
||||
ldset = {'ldsetname': ldsetname,
|
||||
'protocol': 'iSCSI',
|
||||
'mode': tmode,
|
||||
'portal_list': portals,
|
||||
'lds': ldsetlds,
|
||||
'initiator_list': initiators}
|
||||
|
@ -693,13 +693,30 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
def backup_use_temp_snapshot(self):
|
||||
return True
|
||||
|
||||
def _get_free_lun(self, ldset):
|
||||
# Lun can't be specified when multi target mode.
|
||||
if ldset['protocol'] == 'iSCSI' and ldset['mode'] == 'Multi-Target':
|
||||
return None
|
||||
# get free lun.
|
||||
luns = []
|
||||
ldsetlds = ldset['lds']
|
||||
for ld in ldsetlds.values():
|
||||
luns.append(ld['lun'])
|
||||
target_lun = 0
|
||||
for lun in sorted(luns):
|
||||
if target_lun < lun:
|
||||
break
|
||||
target_lun += 1
|
||||
return target_lun
|
||||
|
||||
def iscsi_do_export(self, _ctx, volume, connector, ensure=False):
|
||||
msgparm = ('Volume ID = %(id)s, '
|
||||
'Initiator Name = %(initiator)s'
|
||||
% {'id': volume.id,
|
||||
'initiator': connector['initiator']})
|
||||
try:
|
||||
ret = self._iscsi_do_export(_ctx, volume, connector, ensure)
|
||||
ret = self._iscsi_do_export(_ctx, volume, connector, ensure,
|
||||
self._properties['diskarray_name'])
|
||||
LOG.info('Created iSCSI Export (%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
@ -708,7 +725,9 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
def _iscsi_do_export(self, _ctx, volume, connector, ensure):
|
||||
@coordination.synchronized('mstorage_bind_execute_{diskarray_name}')
|
||||
def _iscsi_do_export(self, _ctx, volume, connector, ensure,
|
||||
diskarray_name):
|
||||
LOG.debug('_iscsi_do_export'
|
||||
'(Volume ID = %(id)s, connector = %(connector)s) Start.',
|
||||
{'id': volume.id, 'connector': connector})
|
||||
@ -731,7 +750,8 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
|
||||
if ld['ldn'] not in ldset['lds']:
|
||||
# assign the LD to LD Set.
|
||||
self._cli.addldsetld(ldset['ldsetname'], ldname)
|
||||
self._cli.addldsetld(ldset['ldsetname'], ldname,
|
||||
self._get_free_lun(ldset))
|
||||
# update local info.
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
@ -784,17 +804,6 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
ldset = self._validate_fcldset_exist(ldsets, connector)
|
||||
ldname = self.get_ldname(volume.id, self._properties['ld_name_format'])
|
||||
|
||||
# get free lun.
|
||||
luns = []
|
||||
ldsetlds = ldset['lds']
|
||||
for ld in ldsetlds.values():
|
||||
luns.append(ld['lun'])
|
||||
target_lun = 0
|
||||
for lun in sorted(luns):
|
||||
if target_lun < lun:
|
||||
break
|
||||
target_lun += 1
|
||||
|
||||
# add LD to LD set.
|
||||
if ldname not in lds:
|
||||
msg = _('Logical Disk `%s` could not be found.') % ldname
|
||||
@ -803,7 +812,8 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
|
||||
if ld['ldn'] not in ldset['lds']:
|
||||
# assign the LD to LD Set.
|
||||
self._cli.addldsetld(ldset['ldsetname'], ldname, target_lun)
|
||||
self._cli.addldsetld(ldset['ldsetname'], ldname,
|
||||
self._get_free_lun(ldset))
|
||||
LOG.debug('Add LD `%(ld)s` to LD Set `%(ldset)s`.',
|
||||
{'ld': ldname, 'ldset': ldset['ldsetname']})
|
||||
|
||||
@ -811,6 +821,50 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
{'ensure': 'ensure_' if ensure else '',
|
||||
'ld': ldname})
|
||||
|
||||
@coordination.synchronized('mstorage_bind_execute_{diskarray_name}')
|
||||
def _create_snapshot_and_link(self, context, snapshot, connector,
|
||||
diskarray_name, validate_ldset_exist):
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
LOG.debug('validate data.')
|
||||
svname = self._validate_ld_exist(
|
||||
lds, snapshot.id, self._properties['ld_name_format'])
|
||||
bvname = self._validate_ld_exist(
|
||||
lds, snapshot.volume_id, self._properties['ld_name_format'])
|
||||
lvname = svname + '_l'
|
||||
ldset = validate_ldset_exist(ldsets, connector)
|
||||
svstatus = self._cli.query_BV_SV_status(bvname[3:], svname[3:])
|
||||
if svstatus != 'snap/active':
|
||||
msg = _('Logical Disk (%s) is invalid snapshot.') % svname
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
lvldn = self._select_ldnumber(used_ldns, max_ld_count)
|
||||
|
||||
LOG.debug('configure backend.')
|
||||
lun0 = [ld for (ldn, ld) in ldset['lds'].items() if ld['lun'] == 0]
|
||||
if not lun0:
|
||||
LOG.debug('create and attach control volume.')
|
||||
used_ldns.append(lvldn)
|
||||
cvldn = self._select_ldnumber(used_ldns, max_ld_count)
|
||||
self._cli.cvbind(lds[bvname]['pool_num'], cvldn)
|
||||
self._cli.changeldname(cvldn,
|
||||
self._properties['cv_name_format'] % cvldn)
|
||||
self._cli.addldsetld(ldset['ldsetname'],
|
||||
self._properties['cv_name_format'] % cvldn,
|
||||
self._get_free_lun(ldset))
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
self._cli.lvbind(bvname, lvname[3:], lvldn)
|
||||
self._cli.lvlink(svname[3:], lvname[3:])
|
||||
self._cli.addldsetld(ldset['ldsetname'], lvname,
|
||||
self._get_free_lun(ldset))
|
||||
LOG.debug('Add LD `%(ld)s` to LD Set `%(ldset)s`.',
|
||||
{'ld': lvname, 'ldset': ldset['ldsetname']})
|
||||
return lvname
|
||||
|
||||
def iscsi_do_export_snapshot(self, context, snapshot, connector):
|
||||
"""Exports the snapshot."""
|
||||
msgparm = 'Snapshot ID = %s' % snapshot.id
|
||||
@ -826,42 +880,15 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
@coordination.synchronized('mstorage_bind_execute_{diskarray_name}')
|
||||
def _iscsi_do_export_snapshot(self, context, snapshot, connector,
|
||||
diskarray_name):
|
||||
LOG.debug('_iscsi_do_export_snapshot(Snapshot ID = %s) Start.',
|
||||
snapshot.id)
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
LOG.debug('validate data.')
|
||||
svname = self._validate_ld_exist(
|
||||
lds, snapshot.id, self._properties['ld_name_format'])
|
||||
bvname = self._validate_ld_exist(
|
||||
lds, snapshot.volume_id, self._properties['ld_name_format'])
|
||||
lvname = svname + '_l'
|
||||
ldset = self._validate_iscsildset_exist(ldsets, connector)
|
||||
svstatus = self._cli.query_BV_SV_status(bvname[3:], svname[3:])
|
||||
if svstatus != 'snap/active':
|
||||
msg = _('Logical Disk (%s) is invalid snapshot.') % svname
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
lvldn = self._select_ldnumber(used_ldns, max_ld_count)
|
||||
|
||||
LOG.debug('configure backend.')
|
||||
if not ldset['lds']:
|
||||
LOG.debug('create and attach control volume.')
|
||||
used_ldns.append(lvldn)
|
||||
cvldn = self._select_ldnumber(used_ldns, max_ld_count)
|
||||
self._cli.cvbind(lds[bvname]['pool_num'], cvldn)
|
||||
self._cli.changeldname(cvldn,
|
||||
self._properties['cv_name_format'] % cvldn)
|
||||
self._cli.addldsetld(ldset['ldsetname'],
|
||||
self._properties['cv_name_format'] % cvldn)
|
||||
|
||||
self._cli.lvbind(bvname, lvname[3:], lvldn)
|
||||
self._cli.lvlink(svname[3:], lvname[3:])
|
||||
self._cli.addldsetld(ldset['ldsetname'], lvname)
|
||||
lvname = (
|
||||
self._create_snapshot_and_link(context, snapshot, connector,
|
||||
diskarray_name,
|
||||
self._validate_iscsildset_exist))
|
||||
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
@ -899,58 +926,13 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
@coordination.synchronized('mstorage_bind_execute_{diskarray_name}')
|
||||
def _fc_do_export_snapshot(self, context, snapshot, connector, ensure,
|
||||
diskarray_name):
|
||||
LOG.debug('_fc_do_export_snapshot(Snapshot ID = %s) Start.',
|
||||
snapshot.id)
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
LOG.debug('validate data.')
|
||||
svname = self._validate_ld_exist(
|
||||
lds, snapshot.id, self._properties['ld_name_format'])
|
||||
bvname = self._validate_ld_exist(
|
||||
lds, snapshot.volume_id, self._properties['ld_name_format'])
|
||||
lvname = svname + '_l'
|
||||
ldset = self._validate_fcldset_exist(ldsets, connector)
|
||||
svstatus = self._cli.query_BV_SV_status(bvname[3:], svname[3:])
|
||||
if svstatus != 'snap/active':
|
||||
msg = _('Logical Disk (%s) is invalid snapshot.') % svname
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
lvldn = self._select_ldnumber(used_ldns, max_ld_count)
|
||||
|
||||
LOG.debug('configure backend.')
|
||||
lun0 = [ld for (ldn, ld) in ldset['lds'].items() if ld['lun'] == 0]
|
||||
if not lun0:
|
||||
LOG.debug('create and attach control volume.')
|
||||
used_ldns.append(lvldn)
|
||||
cvldn = self._select_ldnumber(used_ldns, max_ld_count)
|
||||
self._cli.cvbind(lds[bvname]['pool_num'], cvldn)
|
||||
self._cli.changeldname(cvldn,
|
||||
self._properties['cv_name_format'] % cvldn)
|
||||
self._cli.addldsetld(ldset['ldsetname'],
|
||||
self._properties['cv_name_format'] % cvldn, 0)
|
||||
|
||||
self._cli.lvbind(bvname, lvname[3:], lvldn)
|
||||
self._cli.lvlink(svname[3:], lvname[3:])
|
||||
|
||||
luns = []
|
||||
ldsetlds = ldset['lds']
|
||||
for ld in ldsetlds.values():
|
||||
luns.append(ld['lun'])
|
||||
if 0 not in luns:
|
||||
luns.append(0)
|
||||
target_lun = 0
|
||||
for lun in sorted(luns):
|
||||
if target_lun < lun:
|
||||
break
|
||||
target_lun += 1
|
||||
|
||||
self._cli.addldsetld(ldset['ldsetname'], lvname, target_lun)
|
||||
LOG.debug('Add LD `%(ld)s` to LD Set `%(ldset)s`.',
|
||||
{'ld': lvname, 'ldset': ldset['ldsetname']})
|
||||
lvname = self._create_snapshot_and_link(context, snapshot, connector,
|
||||
diskarray_name,
|
||||
self._validate_fcldset_exist)
|
||||
LOG.debug('%(ensure)sexport LD `%(ld)s`.',
|
||||
{'ensure': 'ensure_' if ensure else '',
|
||||
'ld': lvname})
|
||||
|
Loading…
x
Reference in New Issue
Block a user