Merge "NEC Driver: allow more than 4 iSCSI portals"
This commit is contained in:
commit
551f2ecb57
@ -343,6 +343,11 @@ xml_out = '''
|
||||
<UNIT name="LUN(h)">0000</UNIT>
|
||||
<UNIT name="LDN(h)">0000</UNIT>
|
||||
</SECTION>
|
||||
<SECTION name="Target Information For Multi-Target Mode">
|
||||
<UNIT name="Target Name">iqn.2001-03.target0001</UNIT>
|
||||
<UNIT name="LUN(h)">0001</UNIT>
|
||||
<UNIT name="LDN(h)">0006</UNIT>
|
||||
</SECTION>
|
||||
</OBJECT>
|
||||
</CHAPTER>
|
||||
<RETURN_MSG>Command Completed Successfully!!</RETURN_MSG>
|
||||
@ -359,14 +364,20 @@ class DummyVolume(object):
|
||||
self.id = volid
|
||||
self.size = volsize
|
||||
self.status = None
|
||||
self.migration_status = None
|
||||
self.volume_id = None
|
||||
self.volume_type_id = None
|
||||
self.attach_status = None
|
||||
self.volume_attachment = None
|
||||
self.provider_location = None
|
||||
|
||||
|
||||
class DummySnapshot(object):
|
||||
|
||||
def __init__(self, snapid):
|
||||
super(DummySnapshot, self).__init__()
|
||||
self.id = snapid
|
||||
self.volume_id = None
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VolumeIDConvertTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
|
||||
@ -375,13 +386,12 @@ class VolumeIDConvertTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.mock_object(self, '_create_ismview_dir')
|
||||
self._set_config(conf.Configuration(None), 'dummy', 'dummy')
|
||||
self.do_setup(None)
|
||||
self.vol = DummyVolume(constants.VOLUME_ID)
|
||||
|
||||
@ddt.data(("AAAAAAAA", "LX:37mA82"), ("BBBBBBBB", "LX:3R9ZwR"))
|
||||
@ddt.unpack
|
||||
def test_volumeid_should_change_62scale(self, volid, ldname):
|
||||
self.vol.id = volid
|
||||
actual = self._convert_id2name(self.vol)
|
||||
vol = DummyVolume(volid)
|
||||
actual = self._convert_id2name(vol)
|
||||
self.assertEqual(ldname, actual,
|
||||
"ID:%(volid)s should be change to %(ldname)s" %
|
||||
{'volid': volid, 'ldname': ldname})
|
||||
@ -389,21 +399,21 @@ class VolumeIDConvertTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
@ddt.data(("AAAAAAAA", "LX:37mA82"), ("BBBBBBBB", "LX:3R9ZwR"))
|
||||
@ddt.unpack
|
||||
def test_snap_volumeid_should_change_62scale_andpostfix(self,
|
||||
volid,
|
||||
snapid,
|
||||
ldname):
|
||||
self.vol.id = volid
|
||||
actual = self._convert_id2snapname(self.vol)
|
||||
snap = DummySnapshot(snapid)
|
||||
actual = self._convert_id2snapname(snap)
|
||||
self.assertEqual(ldname, actual,
|
||||
"ID:%(volid)s should be change to %(ldname)s" %
|
||||
{'volid': volid, 'ldname': ldname})
|
||||
"ID:%(snapid)s should be change to %(ldname)s" %
|
||||
{'snapid': snapid, 'ldname': ldname})
|
||||
|
||||
@ddt.data(("AAAAAAAA", "LX:37mA82_m"), ("BBBBBBBB", "LX:3R9ZwR_m"))
|
||||
@ddt.unpack
|
||||
def test_ddrsnap_volumeid_should_change_62scale_and_m(self,
|
||||
volid,
|
||||
ldname):
|
||||
self.vol.id = volid
|
||||
actual = self._convert_id2migratename(self.vol)
|
||||
vol = DummyVolume(volid)
|
||||
actual = self._convert_id2migratename(vol)
|
||||
self.assertEqual(ldname, actual,
|
||||
"ID:%(volid)s should be change to %(ldname)s" %
|
||||
{'volid': volid, 'ldname': ldname})
|
||||
@ -439,7 +449,6 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
for var in range(0, 1025):
|
||||
pool_data['ld_list'].append(volume)
|
||||
self.test_pools = [pool_data]
|
||||
self.vol = DummyVolume(constants.VOLUME_ID, 10)
|
||||
|
||||
def test_getxml(self):
|
||||
self.assertIsNotNone(self.xml, "iSMview xml should not be None")
|
||||
@ -449,15 +458,16 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.assertEqual(2, ldn, "selected ldn should be XXX")
|
||||
|
||||
def test_selectpool_for_normalvolume(self):
|
||||
pool = self._select_leastused_poolnumber(self.vol,
|
||||
vol = DummyVolume(constants.VOLUME_ID, 10)
|
||||
pool = self._select_leastused_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml)
|
||||
self.assertEqual(1, pool, "selected pool should be 1")
|
||||
# config:pool_pools=[1]
|
||||
self.vol.size = 999999999999
|
||||
vol.size = 999999999999
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_leastused_poolnumber(self.vol,
|
||||
pool = self._select_leastused_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml)
|
||||
|
||||
@ -465,24 +475,25 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.assertEqual(1, self._return_poolnumber(self.test_pools))
|
||||
|
||||
def test_selectpool_for_migratevolume(self):
|
||||
self.vol.id = "46045673-41e7-44a7-9333-02f07feab04b"
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b")
|
||||
self.VERSION = '9.99.9'
|
||||
dummyhost = {}
|
||||
dummyhost['capabilities'] = self._update_volume_status()
|
||||
pool = self._select_migrate_poolnumber(self.vol,
|
||||
pool = self._select_migrate_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
dummyhost)
|
||||
self.assertEqual(1, pool, "selected pool should be 1")
|
||||
self.vol.id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
pool = self._select_migrate_poolnumber(self.vol,
|
||||
vol.id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
pool = self._select_migrate_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
dummyhost)
|
||||
self.assertEqual(-1, pool, "selected pool is the same pool(return -1)")
|
||||
self.vol.size = 999999999999
|
||||
vol.size = 999999999999
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_migrate_poolnumber(self.vol,
|
||||
pool = self._select_migrate_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
dummyhost)
|
||||
@ -490,7 +501,8 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
def test_selectpool_for_snapvolume(self):
|
||||
savePool1 = self.pools[1]['free']
|
||||
self.pools[1]['free'] = 0
|
||||
pool = self._select_dsv_poolnumber(self.vol, self.pools)
|
||||
vol = DummyVolume(constants.VOLUME_ID, 10)
|
||||
pool = self._select_dsv_poolnumber(vol, self.pools)
|
||||
self.assertEqual(2, pool, "selected pool should be 2")
|
||||
# config:pool_backup_pools=[2]
|
||||
self.pools[1]['free'] = savePool1
|
||||
@ -502,17 +514,18 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.pools[3]['free'] = 0
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_dsv_poolnumber(self.vol, self.pools)
|
||||
pool = self._select_dsv_poolnumber(vol, self.pools)
|
||||
self.pools[2]['free'] = savePool2
|
||||
self.pools[3]['free'] = savePool3
|
||||
|
||||
self.vol.size = 999999999999
|
||||
pool = self._select_dsv_poolnumber(self.vol, self.pools)
|
||||
vol.size = 999999999999
|
||||
pool = self._select_dsv_poolnumber(vol, self.pools)
|
||||
self.assertEqual(2, pool, "selected pool should be 2")
|
||||
# config:pool_backup_pools=[2]
|
||||
|
||||
def test_selectpool_for_ddrvolume(self):
|
||||
pool = self._select_ddr_poolnumber(self.vol,
|
||||
vol = DummyVolume(constants.VOLUME_ID, 10)
|
||||
pool = self._select_ddr_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
10)
|
||||
@ -525,23 +538,24 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.pools[3]['free'] = 0
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_ddr_poolnumber(self.vol,
|
||||
pool = self._select_ddr_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
10)
|
||||
self.pools[2]['free'] = savePool2
|
||||
self.pools[3]['free'] = savePool3
|
||||
|
||||
self.vol.size = 999999999999
|
||||
vol.size = 999999999999
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_ddr_poolnumber(self.vol,
|
||||
pool = self._select_ddr_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
999999999999)
|
||||
|
||||
def test_selectpool_for_volddrvolume(self):
|
||||
pool = self._select_volddr_poolnumber(self.vol,
|
||||
vol = DummyVolume(constants.VOLUME_ID, 10)
|
||||
pool = self._select_volddr_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
10)
|
||||
@ -554,17 +568,17 @@ class NominatePoolLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.pools[1]['free'] = 0
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_volddr_poolnumber(self.vol,
|
||||
pool = self._select_volddr_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
10)
|
||||
self.pools[0]['free'] = savePool0
|
||||
self.pools[1]['free'] = savePool1
|
||||
|
||||
self.vol.size = 999999999999
|
||||
vol.size = 999999999999
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'No available pools found.'):
|
||||
pool = self._select_volddr_poolnumber(self.vol,
|
||||
pool = self._select_volddr_poolnumber(vol,
|
||||
self.pools,
|
||||
self.xml,
|
||||
999999999999)
|
||||
@ -610,35 +624,36 @@ class VolumeCreateTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.mock_object(self._cli, 'view_all', return_value=xml_out)
|
||||
self.do_setup(None)
|
||||
self.xml = xml_out
|
||||
self.vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b", 1)
|
||||
|
||||
def test_validate_migrate_volume(self):
|
||||
self.vol.status = 'available'
|
||||
self._validate_migrate_volume(self.vol, self.xml)
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b", 1)
|
||||
vol.status = 'available'
|
||||
self._validate_migrate_volume(vol, self.xml)
|
||||
|
||||
self.vol.status = 'creating'
|
||||
vol.status = 'creating'
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'Specified Logical Disk'
|
||||
' LX:287RbQoP7VdwR1WsPC2fZT'
|
||||
' is not available.'):
|
||||
self._validate_migrate_volume(self.vol, self.xml)
|
||||
self._validate_migrate_volume(vol, self.xml)
|
||||
|
||||
self.vol.id = "AAAAAAAA"
|
||||
self.vol.status = 'available'
|
||||
vol.id = "AAAAAAAA"
|
||||
vol.status = 'available'
|
||||
with self.assertRaisesRegex(exception.NotFound,
|
||||
'Logical Disk `LX:37mA82`'
|
||||
' could not be found.'):
|
||||
self._validate_migrate_volume(self.vol, self.xml)
|
||||
self._validate_migrate_volume(vol, self.xml)
|
||||
|
||||
def test_extend_volume(self):
|
||||
self.vol.status = 'available'
|
||||
self.extend_volume(self.vol, 10)
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b", 1)
|
||||
vol.status = 'available'
|
||||
self.extend_volume(vol, 10)
|
||||
|
||||
self.vol.id = "00046058-d38e-7f60-67b7-59ed65e54225" # RV
|
||||
vol.id = "00046058-d38e-7f60-67b7-59ed65e54225" # RV
|
||||
with self.assertRaisesRegex(exception.VolumeBackendAPIException,
|
||||
'RPL Attribute Error. '
|
||||
'RPL Attribute = RV.'):
|
||||
self.extend_volume(self.vol, 10)
|
||||
self.extend_volume(vol, 10)
|
||||
|
||||
|
||||
class BindLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
@ -652,27 +667,28 @@ class BindLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.mock_object(self._cli, 'view_all', return_value=xml_out)
|
||||
self.do_setup(None)
|
||||
self.mock_object(self, '_bind_ld', return_value=(0, 0, 0))
|
||||
self.vol = DummyVolume(constants.VOLUME_ID, 1)
|
||||
|
||||
def test_bindld_CreateVolume(self):
|
||||
self.vol.migration_status = "success"
|
||||
self.create_volume(self.vol)
|
||||
vol = DummyVolume(constants.VOLUME_ID, 1)
|
||||
vol.migration_status = "success"
|
||||
self.create_volume(vol)
|
||||
self._bind_ld.assert_called_once_with(
|
||||
self.vol, self.vol.size, None,
|
||||
vol, vol.size, None,
|
||||
self._convert_id2name,
|
||||
self._select_leastused_poolnumber)
|
||||
|
||||
def test_bindld_CreateCloneVolume(self):
|
||||
self.vol.migration_status = "success"
|
||||
self.src = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b", 1)
|
||||
vol = DummyVolume(constants.VOLUME_ID, 1)
|
||||
vol.migration_status = "success"
|
||||
src = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b", 1)
|
||||
self.mock_object(self._cli, 'query_BV_SV_status',
|
||||
return_value='snap/active')
|
||||
self.mock_object(self._cli, 'query_MV_RV_name',
|
||||
return_value='separated')
|
||||
self.mock_object(self._cli, 'backup_restore')
|
||||
self.create_cloned_volume(self.vol, self.src)
|
||||
self.create_cloned_volume(vol, src)
|
||||
self._bind_ld.assert_called_once_with(
|
||||
self.vol, self.vol.size, None,
|
||||
vol, vol.size, None,
|
||||
self._convert_id2name,
|
||||
self._select_leastused_poolnumber)
|
||||
|
||||
@ -682,16 +698,16 @@ class BindLDTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.assertEqual(60, cli.get_sleep_time_for_clone(19))
|
||||
|
||||
def test_delete_volume(self):
|
||||
self.vol.id = "46045673-41e7-44a7-9333-02f07feab04b"
|
||||
detached = self._detach_from_all(self.vol)
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b")
|
||||
detached = self._detach_from_all(vol)
|
||||
self.assertTrue(detached)
|
||||
self.vol.id = constants.VOLUME_ID
|
||||
detached = self._detach_from_all(self.vol)
|
||||
vol.id = constants.VOLUME_ID
|
||||
detached = self._detach_from_all(vol)
|
||||
self.assertFalse(detached)
|
||||
self.vol.id = constants.VOLUME2_ID
|
||||
vol.id = constants.VOLUME2_ID
|
||||
with mock.patch.object(self, '_detach_from_all') as detach_mock:
|
||||
self.delete_volume(self.vol)
|
||||
detach_mock.assert_called_once_with(self.vol)
|
||||
self.delete_volume(vol)
|
||||
detach_mock.assert_called_once_with(vol)
|
||||
|
||||
|
||||
class BindLDTest_Snap(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
@ -706,25 +722,25 @@ class BindLDTest_Snap(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.do_setup(None)
|
||||
self.mock_object(self, '_bind_ld', return_value=(0, 0, 0))
|
||||
self.mock_object(self, '_create_snapshot')
|
||||
self.vol = DummyVolume(constants.VOLUME_ID)
|
||||
self.snap = DummyVolume(constants.SNAPSHOT_ID)
|
||||
|
||||
def test_bindld_CreateSnapshot(self):
|
||||
self.snap.volume_id = constants.VOLUME_ID
|
||||
self.create_snapshot(self.snap)
|
||||
snap = DummySnapshot(constants.SNAPSHOT_ID)
|
||||
snap.volume_id = constants.VOLUME_ID
|
||||
self.create_snapshot(snap)
|
||||
self._create_snapshot.assert_called_once_with(
|
||||
self.snap, self._properties['diskarray_name'])
|
||||
snap, self._properties['diskarray_name'])
|
||||
|
||||
def test_bindld_CreateFromSnapshot(self):
|
||||
self.vol.migration_status = "success"
|
||||
self.snap.id = "63410c76-2f12-4473-873d-74a63dfcd3e2"
|
||||
self.snap.volume_id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
vol = DummyVolume(constants.VOLUME_ID)
|
||||
vol.migration_status = "success"
|
||||
snap = DummySnapshot("63410c76-2f12-4473-873d-74a63dfcd3e2")
|
||||
snap.volume_id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
self.mock_object(self._cli, 'query_BV_SV_status',
|
||||
return_value='snap/active')
|
||||
self.mock_object(self._cli, 'backup_restore')
|
||||
self.create_volume_from_snapshot(self.vol, self.snap)
|
||||
self.create_volume_from_snapshot(vol, snap)
|
||||
self._bind_ld.assert_called_once_with(
|
||||
self.vol, 1, None,
|
||||
vol, 1, None,
|
||||
self._convert_id2name,
|
||||
self._select_volddr_poolnumber, 1)
|
||||
|
||||
@ -739,50 +755,57 @@ class ExportTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
return_value=('success', 0, 0))
|
||||
self.mock_object(self._cli, 'view_all', return_value=xml_out)
|
||||
self.do_setup(None)
|
||||
self.vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b", 10)
|
||||
|
||||
def test_iscsi_portal(self):
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255"}
|
||||
self.iscsi_do_export(None, self.vol, connector,
|
||||
self._properties['diskarray_name'])
|
||||
|
||||
def test_fc_do_export(self):
|
||||
connector = {'wwpns': ["10000090FAA0786A", "10000090FAA0786B"]}
|
||||
self.fc_do_export(None, self.vol, connector)
|
||||
|
||||
def test_iscsi_initialize_connection(self):
|
||||
loc = "127.0.0.1:3260:1 iqn.2010-10.org.openstack:volume-00000001 88"
|
||||
self.vol.provider_location = loc
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b")
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255",
|
||||
'multipath': False}
|
||||
info = self._iscsi_initialize_connection(self.vol, connector)
|
||||
info = self.iscsi_initialize_connection(vol, connector)
|
||||
self.assertEqual('iscsi', info['driver_volume_type'])
|
||||
self.assertEqual('iqn.2010-10.org.openstack:volume-00000001',
|
||||
info['data']['target_iqn'])
|
||||
self.assertEqual('127.0.0.1:3260', info['data']['target_portal'])
|
||||
self.assertEqual(88, info['data']['target_lun'])
|
||||
self.assertEqual('iqn.2001-03.target0000', info['data']['target_iqn'])
|
||||
self.assertIn(info['data']['target_portal'],
|
||||
['192.168.1.90:3260', '192.168.1.91:3260',
|
||||
'192.168.2.92:3260', '192.168.2.93:3260'])
|
||||
self.assertEqual(0, info['data']['target_lun'])
|
||||
|
||||
vol.id = "87d8d42f-7550-4f43-9a2b-fe722bf86941"
|
||||
with self.assertRaisesRegex(exception.NotFound,
|
||||
'Logical Disk `LX:48L3QCi4npuqxPX0Lyeu8H`'
|
||||
' could not be found.'):
|
||||
self.iscsi_initialize_connection(vol, connector)
|
||||
|
||||
def test_iscsi_multipath_initialize_connection(self):
|
||||
self.vol.id = "46045673-41e7-44a7-9333-02f07feab04b"
|
||||
loc = ("1.1.1.1:3260;2.2.2.2:3260,1 "
|
||||
"iqn.2010-10.org.openstack:volume-00000001 88")
|
||||
self.vol.provider_location = loc
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b")
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255",
|
||||
'multipath': True}
|
||||
info = self._iscsi_initialize_connection(self.vol, connector)
|
||||
info = self.iscsi_initialize_connection(vol, connector)
|
||||
self.assertEqual('iscsi', info['driver_volume_type'])
|
||||
self.assertEqual('iqn.2010-10.org.openstack:volume-00000001',
|
||||
self.assertEqual('iqn.2001-03.target0000',
|
||||
info['data']['target_iqn'])
|
||||
self.assertEqual('1.1.1.1:3260', info['data']['target_portal'])
|
||||
self.assertEqual(88, info['data']['target_lun'])
|
||||
self.assertEqual('iqn.2010-10.org.openstack:volume-00000001',
|
||||
self.assertIn(info['data']['target_portal'],
|
||||
['192.168.1.90:3260', '192.168.1.91:3260',
|
||||
'192.168.2.92:3260', '192.168.2.93:3260'])
|
||||
self.assertEqual(0, info['data']['target_lun'])
|
||||
self.assertEqual('iqn.2001-03.target0000',
|
||||
info['data']['target_iqns'][0])
|
||||
self.assertEqual('iqn.2010-10.org.openstack:volume-00000001',
|
||||
self.assertEqual('iqn.2001-03.target0000',
|
||||
info['data']['target_iqns'][1])
|
||||
self.assertEqual('1.1.1.1:3260', info['data']['target_portals'][0])
|
||||
self.assertEqual('2.2.2.2:3260', info['data']['target_portals'][1])
|
||||
self.assertEqual(88, info['data']['target_luns'][0])
|
||||
self.assertEqual(88, info['data']['target_luns'][1])
|
||||
self.assertEqual('iqn.2001-03.target0000',
|
||||
info['data']['target_iqns'][2])
|
||||
self.assertEqual('iqn.2001-03.target0000',
|
||||
info['data']['target_iqns'][3])
|
||||
self.assertEqual(info['data']['target_portals'][0],
|
||||
'192.168.1.90:3260')
|
||||
self.assertEqual(info['data']['target_portals'][1],
|
||||
'192.168.1.91:3260')
|
||||
self.assertEqual(info['data']['target_portals'][2],
|
||||
'192.168.2.92:3260')
|
||||
self.assertEqual(info['data']['target_portals'][3],
|
||||
'192.168.2.93:3260')
|
||||
self.assertEqual(0, info['data']['target_luns'][0])
|
||||
self.assertEqual(0, info['data']['target_luns'][1])
|
||||
self.assertEqual(0, info['data']['target_luns'][2])
|
||||
self.assertEqual(0, info['data']['target_luns'][3])
|
||||
|
||||
def test_iscsi_terminate_connection(self):
|
||||
ctx = context.RequestContext('admin', 'fake', True)
|
||||
@ -1019,25 +1042,6 @@ class ExportTest(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
ret = self._is_multi_attachment(vol, connector)
|
||||
self.assertFalse(ret)
|
||||
|
||||
def test_iscsi_portal_with_controller_node_name(self):
|
||||
self.vol.status = 'downloading'
|
||||
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,
|
||||
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',
|
||||
location['provider_location'])
|
||||
|
||||
def test_fc_do_export_with_controller_node_name(self):
|
||||
self.vol.status = 'downloading'
|
||||
connector = {'wwpns': ["10000090FAA0786A", "10000090FAA0786B"]}
|
||||
self._properties['ldset_controller_node_name'] = 'LX:OpenStack0'
|
||||
location = self.fc_do_export(None, self.vol, connector)
|
||||
self.assertIsNone(location)
|
||||
|
||||
|
||||
class DeleteDSVVolume_test(volume_helper.MStorageDSVDriver,
|
||||
test.TestCase):
|
||||
@ -1050,13 +1054,13 @@ class DeleteDSVVolume_test(volume_helper.MStorageDSVDriver,
|
||||
return_value=('success', 0, 0))
|
||||
self.mock_object(self._cli, 'view_all', return_value=xml_out)
|
||||
self.do_setup(None)
|
||||
self.vol = DummyVolume(constants.SNAPSHOT_ID)
|
||||
self.vol.volume_id = constants.VOLUME_ID
|
||||
|
||||
def test_delete_snapshot(self):
|
||||
self.mock_object(self._cli, 'query_BV_SV_status',
|
||||
return_value='snap/active')
|
||||
ret = self.delete_snapshot(self.vol)
|
||||
snap = DummySnapshot(constants.SNAPSHOT_ID)
|
||||
snap.volume_id = constants.VOLUME_ID
|
||||
ret = self.delete_snapshot(snap)
|
||||
self.assertIsNone(ret)
|
||||
|
||||
|
||||
@ -1070,8 +1074,9 @@ class NonDisruptiveBackup_test(volume_helper.MStorageDSVDriver,
|
||||
self.mock_object(self._cli, '_execute',
|
||||
return_value=('success', 0, 0))
|
||||
self.mock_object(self._cli, 'view_all', return_value=xml_out)
|
||||
self.mock_object(self._cli, 'query_BV_SV_status',
|
||||
return_value='snap/active')
|
||||
self.do_setup(None)
|
||||
self.vol = DummyVolume('46045673-41e7-44a7-9333-02f07feab04b')
|
||||
self.xml = xml_out
|
||||
(self.pools,
|
||||
self.lds,
|
||||
@ -1081,15 +1086,16 @@ class NonDisruptiveBackup_test(volume_helper.MStorageDSVDriver,
|
||||
self.max_ld_count) = self.configs(self.xml)
|
||||
|
||||
def test_validate_ld_exist(self):
|
||||
vol = DummyVolume("46045673-41e7-44a7-9333-02f07feab04b")
|
||||
ldname = self._validate_ld_exist(
|
||||
self.lds, self.vol.id, self._properties['ld_name_format'])
|
||||
self.lds, vol.id, self._properties['ld_name_format'])
|
||||
self.assertEqual('LX:287RbQoP7VdwR1WsPC2fZT', ldname)
|
||||
self.vol.id = "00000000-0000-0000-0000-6b6d96553b4b"
|
||||
vol.id = "00000000-0000-0000-0000-6b6d96553b4b"
|
||||
with self.assertRaisesRegex(exception.NotFound,
|
||||
'Logical Disk `LX:XXXXXXXX`'
|
||||
' could not be found.'):
|
||||
self._validate_ld_exist(
|
||||
self.lds, self.vol.id, self._properties['ld_name_format'])
|
||||
self.lds, vol.id, self._properties['ld_name_format'])
|
||||
|
||||
def test_validate_iscsildset_exist(self):
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255"}
|
||||
@ -1137,7 +1143,6 @@ class NonDisruptiveBackup_test(volume_helper.MStorageDSVDriver,
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255"}
|
||||
ldset = self._validate_iscsildset_exist(self.ldsets, connector)
|
||||
self.assertEqual('LX:OpenStack0', ldset['ldsetname'])
|
||||
self._properties['portal_number'] = 2
|
||||
portal = self._enumerate_iscsi_portals(self.hostports, ldset)
|
||||
self.assertEqual('192.168.1.90:3260', portal[0])
|
||||
self.assertEqual('192.168.1.91:3260', portal[1])
|
||||
@ -1145,50 +1150,52 @@ class NonDisruptiveBackup_test(volume_helper.MStorageDSVDriver,
|
||||
self.assertEqual('192.168.2.93:3260', portal[3])
|
||||
|
||||
def test_initialize_connection_snapshot(self):
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255"}
|
||||
loc = "127.0.0.1:3260:1 iqn.2010-10.org.openstack:volume-00000001 88"
|
||||
self.vol.provider_location = loc
|
||||
ret = self.iscsi_initialize_connection_snapshot(self.vol, connector)
|
||||
snap = DummySnapshot('46045673-41e7-44a7-9333-02f07feab04b')
|
||||
snap.volume_id = "92dbc7f4-dbc3-4a87-aef4-d5a2ada3a9af"
|
||||
connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255",
|
||||
'multipath': True}
|
||||
ret = self.iscsi_initialize_connection_snapshot(snap, connector)
|
||||
self.assertIsNotNone(ret)
|
||||
self.assertEqual('iscsi', ret['driver_volume_type'])
|
||||
|
||||
connector = {'wwpns': ["10000090FAA0786A", "10000090FAA0786B"]}
|
||||
ret = self.fc_initialize_connection_snapshot(self.vol, connector)
|
||||
ret = self.fc_initialize_connection_snapshot(snap, connector)
|
||||
self.assertIsNotNone(ret)
|
||||
self.assertEqual('fibre_channel', ret['driver_volume_type'])
|
||||
|
||||
def test_terminate_connection_snapshot(self):
|
||||
ctx = context.RequestContext('admin', 'fake', True)
|
||||
vol = fake_volume_obj(ctx, id="46045673-41e7-44a7-9333-02f07feab04b")
|
||||
snap = fake_volume_obj(ctx, id="46045673-41e7-44a7-9333-02f07feab04b")
|
||||
connector = {'initiator': 'iqn.1994-05.com.redhat:d1d8e8f23255',
|
||||
'host': 'DummyHost'}
|
||||
attachment = {
|
||||
'id': constants.ATTACHMENT_ID,
|
||||
'volume_id': vol.id,
|
||||
'volume_id': snap.id,
|
||||
'connector': connector
|
||||
}
|
||||
attach_object = volume_attachment.VolumeAttachment(**attachment)
|
||||
attachment = volume_attachment.VolumeAttachmentList(
|
||||
objects=[attach_object])
|
||||
vol.volume_attachment = attachment
|
||||
self.iscsi_terminate_connection_snapshot(vol, connector)
|
||||
snap.volume_attachment = attachment
|
||||
self.iscsi_terminate_connection_snapshot(snap, connector)
|
||||
|
||||
connector = {'wwpns': ["10000090FAA0786A", "10000090FAA0786B"],
|
||||
'host': 'DummyHost'}
|
||||
attachment = {
|
||||
'id': constants.ATTACHMENT_ID,
|
||||
'volume_id': vol.id,
|
||||
'volume_id': snap.id,
|
||||
'connector': connector
|
||||
}
|
||||
attach_object = volume_attachment.VolumeAttachment(**attachment)
|
||||
attachment = volume_attachment.VolumeAttachmentList(
|
||||
objects=[attach_object])
|
||||
vol.volume_attachment = attachment
|
||||
ret = self.fc_terminate_connection_snapshot(vol, connector)
|
||||
snap.volume_attachment = attachment
|
||||
ret = self.fc_terminate_connection_snapshot(snap, connector)
|
||||
self.assertEqual('fibre_channel', ret['driver_volume_type'])
|
||||
|
||||
def test_remove_export_snapshot(self):
|
||||
self.remove_export_snapshot(None, self.vol)
|
||||
snap = DummySnapshot('46045673-41e7-44a7-9333-02f07feab04b')
|
||||
self.remove_export_snapshot(None, snap)
|
||||
|
||||
def test_backup_use_temp_snapshot(self):
|
||||
ret = self.backup_use_temp_snapshot()
|
||||
@ -1204,6 +1211,7 @@ class VolumeStats_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self._properties['cli_fip'] = '10.0.0.1'
|
||||
self._properties['pool_pools'] = {0, 1}
|
||||
self._properties['pool_backup_pools'] = {2, 3}
|
||||
self.VERSION = '9.99.9'
|
||||
|
||||
def test_update_volume_status(self):
|
||||
self.mock_object(volume_common.MStorageVolumeCommon, 'parse_xml',
|
||||
@ -1270,12 +1278,12 @@ class Migrate_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
return_value=('success', 0, 0))
|
||||
self.mock_object(self._cli, 'view_all', return_value=xml_out)
|
||||
self.do_setup(None)
|
||||
self.newvol = DummyVolume(constants.VOLUME_ID)
|
||||
self.sourcevol = DummyVolume(constants.VOLUME2_ID)
|
||||
|
||||
def test_update_migrate_volume(self):
|
||||
update_data = self.update_migrated_volume(None, self.sourcevol,
|
||||
self.newvol, 'available')
|
||||
newvol = DummyVolume(constants.VOLUME_ID)
|
||||
sourcevol = DummyVolume(constants.VOLUME2_ID)
|
||||
update_data = self.update_migrated_volume(None, sourcevol,
|
||||
newvol, 'available')
|
||||
self.assertIsNone(update_data['_name_id'])
|
||||
self.assertIsNone(update_data['provider_location'])
|
||||
|
||||
@ -1290,7 +1298,6 @@ class ManageUnmanage_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.do_setup(None)
|
||||
self._properties['pool_pools'] = {0}
|
||||
self._properties['pool_backup_pools'] = {1}
|
||||
self.newvol = DummyVolume(constants.VOLUME_ID)
|
||||
|
||||
def test_is_manageable_volume(self):
|
||||
ld_ok_iv = {'pool_num': 0, 'RPL Attribute': 'IV', 'Purpose': '---'}
|
||||
@ -1335,22 +1342,24 @@ class ManageUnmanage_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
current_volumes = []
|
||||
volumes = self.get_manageable_volumes(current_volumes, None,
|
||||
100, 0, ['reference'], ['dec'])
|
||||
self.manage_existing(self.newvol, volumes[4]['reference'])
|
||||
newvol = DummyVolume(constants.VOLUME_ID)
|
||||
self.manage_existing(newvol, volumes[4]['reference'])
|
||||
self._cli.changeldname.assert_called_once_with(
|
||||
None, 'LX:vD03hJCiHvGpvP4iSevKk', ' :20000009910200140009')
|
||||
with self.assertRaisesRegex(exception.ManageExistingInvalidReference,
|
||||
'Specified resource is already in-use.'):
|
||||
self.manage_existing(self.newvol, volumes[3]['reference'])
|
||||
self.manage_existing(newvol, volumes[3]['reference'])
|
||||
volume = {'source-name': 'LX:yEUHrXa5AHMjOZZLb93eP'}
|
||||
with self.assertRaisesRegex(exception.ManageExistingVolumeTypeMismatch,
|
||||
'Volume type is unmatched.'):
|
||||
self.manage_existing(self.newvol, volume)
|
||||
self.manage_existing(newvol, volume)
|
||||
|
||||
def test_manage_existing_get_size(self):
|
||||
current_volumes = []
|
||||
volumes = self.get_manageable_volumes(current_volumes, None,
|
||||
100, 0, ['reference'], ['dec'])
|
||||
size_in_gb = self.manage_existing_get_size(self.newvol,
|
||||
newvol = DummyVolume(constants.VOLUME_ID)
|
||||
size_in_gb = self.manage_existing_get_size(newvol,
|
||||
volumes[3]['reference'])
|
||||
self.assertEqual(10, size_in_gb)
|
||||
|
||||
@ -1365,8 +1374,6 @@ class ManageUnmanage_Snap_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
self.do_setup(None)
|
||||
self._properties['pool_pools'] = {0}
|
||||
self._properties['pool_backup_pools'] = {1}
|
||||
self.newsnap = DummyVolume('46045673-41e7-44a7-9333-02f07feab04b')
|
||||
self.newsnap.volume_id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
|
||||
def test_is_manageable_snapshot(self):
|
||||
ld_ok_sv1 = {'pool_num': 1, 'RPL Attribute': 'SV', 'Purpose': 'INV'}
|
||||
@ -1400,23 +1407,25 @@ class ManageUnmanage_Snap_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
current_snapshots = []
|
||||
snaps = self.get_manageable_snapshots(current_snapshots, None,
|
||||
100, 0, ['reference'], ['asc'])
|
||||
self.manage_existing_snapshot(self.newsnap, snaps[0]['reference'])
|
||||
newsnap = DummySnapshot('46045673-41e7-44a7-9333-02f07feab04b')
|
||||
newsnap.volume_id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
self.manage_existing_snapshot(newsnap, snaps[0]['reference'])
|
||||
self._cli.changeldname.assert_called_once_with(
|
||||
None,
|
||||
'LX:287RbQoP7VdwR1WsPC2fZT',
|
||||
'LX:4T7JpyqI3UuPlKeT9D3VQF')
|
||||
|
||||
self.newsnap.volume_id = "AAAAAAAA"
|
||||
newsnap.volume_id = "AAAAAAAA"
|
||||
with self.assertRaisesRegex(exception.ManageExistingInvalidReference,
|
||||
'Snapshot source is unmatch.'):
|
||||
self.manage_existing_snapshot(self.newsnap, snaps[0]['reference'])
|
||||
self.manage_existing_snapshot(newsnap, snaps[0]['reference'])
|
||||
|
||||
self._cli.get_bvname.return_value = "2000000991020012000C"
|
||||
self.newsnap.volume_id = "00046058-d38e-7f60-67b7-59ed6422520c"
|
||||
newsnap.volume_id = "00046058-d38e-7f60-67b7-59ed6422520c"
|
||||
snap = {'source-name': ' :2000000991020012000B'}
|
||||
with self.assertRaisesRegex(exception.ManageExistingVolumeTypeMismatch,
|
||||
'Volume type is unmatched.'):
|
||||
self.manage_existing_snapshot(self.newsnap, snap)
|
||||
self.manage_existing_snapshot(newsnap, snap)
|
||||
|
||||
def test_manage_existing_snapshot_get_size(self):
|
||||
self.mock_object(self._cli, 'get_bvname',
|
||||
@ -1424,7 +1433,9 @@ class ManageUnmanage_Snap_test(volume_helper.MStorageDSVDriver, test.TestCase):
|
||||
current_snapshots = []
|
||||
snaps = self.get_manageable_snapshots(current_snapshots, None,
|
||||
100, 0, ['reference'], ['asc'])
|
||||
newsnap = DummySnapshot('46045673-41e7-44a7-9333-02f07feab04b')
|
||||
newsnap.volume_id = "1febb976-86d0-42ed-9bc0-4aa3e158f27d"
|
||||
size_in_gb = self.manage_existing_snapshot_get_size(
|
||||
self.newsnap,
|
||||
newsnap,
|
||||
snaps[0]['reference'])
|
||||
self.assertEqual(6, size_in_gb)
|
||||
|
@ -149,22 +149,22 @@ class MStorageISMCLI(object):
|
||||
stdin, stdout, stderr = ssh.exec_command(command)
|
||||
stdin.close()
|
||||
channel = stdout.channel
|
||||
_out, _err = [], []
|
||||
tmpout, tmperr = b'', b''
|
||||
while 1:
|
||||
select.select([channel], [], [])
|
||||
if channel.recv_ready():
|
||||
_out.append(channel.recv(4096))
|
||||
tmpout += channel.recv(4096)
|
||||
continue
|
||||
if channel.recv_stderr_ready():
|
||||
_err.append(channel.recv_stderr(4096))
|
||||
tmperr += channel.recv_stderr(4096)
|
||||
continue
|
||||
if channel.exit_status_ready():
|
||||
status = channel.recv_exit_status()
|
||||
break
|
||||
LOG.debug('`%(command)s` done. status=%(status)d.',
|
||||
{'command': command, 'status': status})
|
||||
out = self._join_and_convert_str(_out)
|
||||
err = self._join_and_convert_str(_err)
|
||||
out = utils.convert_str(tmpout)
|
||||
err = utils.convert_str(tmperr)
|
||||
if expected_status is not None and status not in expected_status:
|
||||
LOG.debug('`%(command)s` failed. status=%(status)d, '
|
||||
'out="%(out)s", err="%(err)s".',
|
||||
@ -673,14 +673,6 @@ class MStorageISMCLI(object):
|
||||
'cvnumber': cvnumber})
|
||||
self._execute(cmd)
|
||||
|
||||
def _join_and_convert_str(self, src_list):
|
||||
if len(src_list) == 0:
|
||||
return ''
|
||||
if isinstance(src_list[0], bytes):
|
||||
return utils.convert_str(b''.join(src_list))
|
||||
else:
|
||||
return ''.join(src_list)
|
||||
|
||||
|
||||
class UnpairWait(object):
|
||||
|
||||
|
@ -47,9 +47,12 @@ class MStorageISCSIDriver(volume_helper.MStorageDSVDriver,
|
||||
Fixed bug #1777385: driver removed access permission from
|
||||
the destination node after live-migraion.
|
||||
Fixed bug #1778669: LUNs of detached volumes are never reused.
|
||||
1.11.1 - Add support pytyon 3.
|
||||
Add support for multi-attach.
|
||||
Add support of more than 4 iSCSI portals for a node.
|
||||
"""
|
||||
|
||||
VERSION = '1.10.3'
|
||||
VERSION = '1.11.1'
|
||||
CI_WIKI_NAME = 'NEC_Cinder_CI'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -61,9 +64,6 @@ class MStorageISCSIDriver(volume_helper.MStorageDSVDriver,
|
||||
def get_driver_options():
|
||||
return volume_common.mstorage_opts
|
||||
|
||||
def create_export(self, context, volume, connector):
|
||||
return self.iscsi_do_export(context, volume, connector)
|
||||
|
||||
def ensure_export(self, context, volume):
|
||||
pass
|
||||
|
||||
@ -76,9 +76,6 @@ class MStorageISCSIDriver(volume_helper.MStorageDSVDriver,
|
||||
def terminate_connection(self, volume, connector, **kwargs):
|
||||
return self.iscsi_terminate_connection(volume, connector)
|
||||
|
||||
def create_export_snapshot(self, context, snapshot, connector):
|
||||
return self.iscsi_do_export_snapshot(context, snapshot, connector)
|
||||
|
||||
def initialize_connection_snapshot(self, snapshot, connector, **kwargs):
|
||||
return self.iscsi_initialize_connection_snapshot(snapshot,
|
||||
connector,
|
||||
@ -114,9 +111,12 @@ class MStorageFCDriver(volume_helper.MStorageDSVDriver,
|
||||
Fixed bug #1777385: driver removed access permission from
|
||||
the destination node after live-migraion.
|
||||
Fixed bug #1778669: LUNs of detached volumes are never reused.
|
||||
1.11.1 - Add support pytyon 3.
|
||||
Add support for multi-attach.
|
||||
Add support of more than 4 iSCSI portals for a node.
|
||||
"""
|
||||
|
||||
VERSION = '1.10.3'
|
||||
VERSION = '1.11.1'
|
||||
CI_WIKI_NAME = 'NEC_Cinder_CI'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -128,9 +128,6 @@ class MStorageFCDriver(volume_helper.MStorageDSVDriver,
|
||||
def get_driver_options():
|
||||
return volume_common.mstorage_opts
|
||||
|
||||
def create_export(self, context, volume, connector):
|
||||
return self.fc_do_export(context, volume, connector)
|
||||
|
||||
def ensure_export(self, context, volume):
|
||||
pass
|
||||
|
||||
@ -147,9 +144,6 @@ class MStorageFCDriver(volume_helper.MStorageDSVDriver,
|
||||
fczm_utils.remove_fc_zone(conn_info)
|
||||
return conn_info
|
||||
|
||||
def create_export_snapshot(self, context, snapshot, connector):
|
||||
return self.fc_do_export_snapshot(context, snapshot, connector)
|
||||
|
||||
def initialize_connection_snapshot(self, snapshot, connector, **kwargs):
|
||||
return self.fc_initialize_connection_snapshot(snapshot,
|
||||
connector,
|
||||
|
@ -94,8 +94,12 @@ mstorage_opts = [
|
||||
default=False,
|
||||
help='Use legacy iSMCLI command.'),
|
||||
cfg.IntOpt('nec_iscsi_portals_per_cont',
|
||||
default=1,
|
||||
help='Number of iSCSI portals.'),
|
||||
default=0,
|
||||
deprecated_for_removal=True,
|
||||
help='Max number of iSCSI portals per controller. '
|
||||
'0 => unlimited. '
|
||||
'This option is deprecated and may '
|
||||
'be removed in the next release.'),
|
||||
cfg.BoolOpt('nec_auto_accesscontrol',
|
||||
default=True,
|
||||
help='Configure access control automatically.'),
|
||||
@ -153,9 +157,6 @@ def convert_to_id(value62):
|
||||
class MStorageVolumeCommon(object):
|
||||
"""M-Series Storage volume common class."""
|
||||
|
||||
VERSION = '1.10.2'
|
||||
WIKI_NAME = 'NEC_Cinder_CI'
|
||||
|
||||
def do_setup(self, context):
|
||||
self._context = context
|
||||
|
||||
|
@ -274,30 +274,30 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
return ldset
|
||||
|
||||
def _enumerate_iscsi_portals(self, hostports, ldset, prefered_director=0):
|
||||
nominated = []
|
||||
portals = []
|
||||
for director in [prefered_director, 1 - prefered_director]:
|
||||
if director not in hostports:
|
||||
continue
|
||||
dirportal = []
|
||||
dirportals = []
|
||||
for port in hostports[director]:
|
||||
if not port['protocol'].lower() == 'iscsi':
|
||||
continue
|
||||
for portal in ldset['portal_list']:
|
||||
if portal.startswith(port['ip'] + ':'):
|
||||
dirportal.append(portal)
|
||||
dirportals.append(portal)
|
||||
break
|
||||
if (self._properties['portal_number'] > 0 and
|
||||
len(dirportal) > self._properties['portal_number']):
|
||||
nominated.extend(
|
||||
dirportal[0:self._properties['portal_number']])
|
||||
len(dirportals) > self._properties['portal_number']):
|
||||
portals.extend(
|
||||
dirportals[0:self._properties['portal_number']])
|
||||
else:
|
||||
nominated.extend(dirportal)
|
||||
portals.extend(dirportals)
|
||||
|
||||
if len(nominated) == 0:
|
||||
if len(portals) == 0:
|
||||
raise exception.NotFound(
|
||||
_('No portal matches to any host ports.'))
|
||||
|
||||
return nominated
|
||||
return portals
|
||||
|
||||
def create_volume(self, volume):
|
||||
msgparm = ('Volume ID = %(id)s, Size = %(size)dGB'
|
||||
@ -708,121 +708,15 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
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,
|
||||
self._properties['diskarray_name'])
|
||||
LOG.info('Created iSCSI Export (%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.warning('Failed to Create iSCSI Export '
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
def create_export(self, context, volume, connector):
|
||||
pass
|
||||
|
||||
def create_export_snapshot(self, context, snapshot, connector):
|
||||
pass
|
||||
|
||||
@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})
|
||||
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
# find LD Set.
|
||||
ldset = self._validate_iscsildset_exist(
|
||||
ldsets, connector)
|
||||
ldname = self.get_ldname(
|
||||
volume.id, self._properties['ld_name_format'])
|
||||
|
||||
# add LD to LD set.
|
||||
if ldname not in lds:
|
||||
msg = _('Logical Disk `%s` could not be found.') % ldname
|
||||
raise exception.NotFound(msg)
|
||||
ld = lds[ldname]
|
||||
|
||||
if ld['ldn'] not in ldset['lds']:
|
||||
# assign the LD to LD Set.
|
||||
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 = (
|
||||
self.configs(xml))
|
||||
ldset = self._validate_iscsildset_exist(ldsets, connector)
|
||||
LOG.debug('Add LD `%(ld)s` to LD Set `%(ldset)s`.',
|
||||
{'ld': ldname, 'ldset': ldset['ldsetname']})
|
||||
|
||||
# enumerate portals for iscsi multipath.
|
||||
prefered_director = ld['pool_num'] % 2
|
||||
nominated = self._enumerate_iscsi_portals(hostports, ldset,
|
||||
prefered_director)
|
||||
location = ('%(list)s,1 %(iqn)s %(lun)d'
|
||||
% {'list': ';'.join(nominated),
|
||||
'iqn': ldset['lds'][ld['ldn']]['iqn'],
|
||||
'lun': ldset['lds'][ld['ldn']]['lun']})
|
||||
|
||||
LOG.debug('%(ensure)sexport LD `%(name)s` via `%(location)s`.',
|
||||
{'ensure': 'ensure_' if ensure else '',
|
||||
'name': ldname,
|
||||
'location': location})
|
||||
return {'provider_location': location}
|
||||
|
||||
def fc_do_export(self, _ctx, volume, connector, ensure=False):
|
||||
msgparm = ('Volume ID = %(id)s, '
|
||||
'Initiator WWPNs = %(wwpns)s'
|
||||
% {'id': volume.id,
|
||||
'wwpns': connector['wwpns']})
|
||||
try:
|
||||
ret = self._fc_do_export(_ctx, volume, connector, ensure,
|
||||
self._properties['diskarray_name'])
|
||||
LOG.info('Created FC Export (%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.warning('Failed to Create FC Export '
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
@coordination.synchronized('mstorage_bind_execute_{diskarray_name}')
|
||||
def _fc_do_export(self, _ctx, volume, connector, ensure, diskarray_name):
|
||||
LOG.debug('_fc_do_export'
|
||||
'(Volume ID = %(id)s, connector = %(connector)s) Start.',
|
||||
{'id': volume.id, 'connector': connector})
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
# get target LD Set.
|
||||
ldset = self._validate_fcldset_exist(ldsets, connector)
|
||||
ldname = self.get_ldname(volume.id, self._properties['ld_name_format'])
|
||||
|
||||
# add LD to LD set.
|
||||
if ldname not in lds:
|
||||
msg = _('Logical Disk `%s` could not be found.') % ldname
|
||||
raise exception.NotFound(msg)
|
||||
ld = lds[ldname]
|
||||
|
||||
if ld['ldn'] not in ldset['lds']:
|
||||
# assign the LD to LD Set.
|
||||
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']})
|
||||
|
||||
LOG.debug('%(ensure)sexport LD `%(ld)s`.',
|
||||
{'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):
|
||||
def _create_snapshot_and_link(self, 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))
|
||||
@ -864,78 +758,6 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
{'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
|
||||
try:
|
||||
ret = self._iscsi_do_export_snapshot(
|
||||
context, snapshot, connector,
|
||||
self._properties['diskarray_name'])
|
||||
LOG.info('Create Export Snapshot (%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.warning('Failed to Create Export Snapshot '
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
def _iscsi_do_export_snapshot(self, context, snapshot, connector,
|
||||
diskarray_name):
|
||||
LOG.debug('_iscsi_do_export_snapshot(Snapshot ID = %s) Start.',
|
||||
snapshot.id)
|
||||
|
||||
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 = (
|
||||
self.configs(xml))
|
||||
ld = lds[lvname]
|
||||
ldset = self._validate_iscsildset_exist(ldsets, connector)
|
||||
|
||||
LOG.debug('enumerate portals for iscsi multipath.')
|
||||
prefered_director = ld['pool_num'] % 2
|
||||
nominated = self._enumerate_iscsi_portals(hostports, ldset,
|
||||
prefered_director)
|
||||
location = ('%(list)s,1 %(iqn)s %(lun)d'
|
||||
% {'list': ';'.join(nominated),
|
||||
'iqn': ldset['lds'][ld['ldn']]['iqn'],
|
||||
'lun': ldset['lds'][ld['ldn']]['lun']})
|
||||
|
||||
LOG.debug('create_export_snapshot location:(%s)', location)
|
||||
return {'provider_location': location}
|
||||
|
||||
def fc_do_export_snapshot(self, context, snapshot, connector,
|
||||
ensure=False):
|
||||
msgparm = ('Volume ID = %(id)s, '
|
||||
'Initiator WWPNs = %(wwpns)s'
|
||||
% {'id': snapshot.id,
|
||||
'wwpns': connector['wwpns']})
|
||||
try:
|
||||
ret = self._fc_do_export_snapshot(
|
||||
context, snapshot, connector, ensure,
|
||||
self._properties['diskarray_name'])
|
||||
LOG.info('Created FC Export snapshot(%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.warning('Failed to Create FC Export snapshot'
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
def _fc_do_export_snapshot(self, context, snapshot, connector, ensure,
|
||||
diskarray_name):
|
||||
LOG.debug('_fc_do_export_snapshot(Snapshot ID = %s) Start.',
|
||||
snapshot.id)
|
||||
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})
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
pass
|
||||
|
||||
@ -1055,6 +877,28 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
LOG.debug('_remove_export_snapshot(Snapshot ID = %s) End.',
|
||||
snapshot.id)
|
||||
|
||||
@coordination.synchronized('mstorage_bind_execute_{diskarray_name}')
|
||||
def _export_volume(self, volume, connector, diskarray_name,
|
||||
validate_exist):
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
ldset = validate_exist(ldsets, connector)
|
||||
ldname = self.get_ldname(
|
||||
volume.id, self._properties['ld_name_format'])
|
||||
if ldname not in lds:
|
||||
msg = _('Logical Disk `%s` could not be found.') % ldname
|
||||
raise exception.NotFound(msg)
|
||||
ld = lds[ldname]
|
||||
if ld['ldn'] not in ldset['lds']:
|
||||
self._cli.addldsetld(ldset['ldsetname'], ldname,
|
||||
self._get_free_lun(ldset))
|
||||
# update local info.
|
||||
LOG.debug('Add LD `%(ld)s` to LD Set `%(ldset)s`.',
|
||||
{'ld': ldname, 'ldset': ldset['ldsetname']})
|
||||
|
||||
return ldname
|
||||
|
||||
def iscsi_initialize_connection(self, volume, connector):
|
||||
msgparm = ('Volume ID = %(id)s, Connector = %(connector)s'
|
||||
% {'id': volume.id, 'connector': connector})
|
||||
@ -1069,7 +913,8 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
def _iscsi_initialize_connection(self, volume, connector):
|
||||
def _iscsi_initialize_connection(self, volume, connector,
|
||||
is_snapshot=False):
|
||||
"""Initializes the connection and returns connection info.
|
||||
|
||||
The iscsi driver returns a driver_volume_type of 'iscsi'.
|
||||
@ -1089,27 +934,48 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
|
||||
"""
|
||||
LOG.debug('_iscsi_initialize_connection'
|
||||
'(Volume ID = %(id)s, connector = %(connector)s) Start.',
|
||||
{'id': volume.id, 'connector': connector})
|
||||
'(Volume ID = %(id)s, connector = %(connector)s, '
|
||||
'snapshot = %(snapshot)s) Start.',
|
||||
{'id': volume.id, 'connector': connector,
|
||||
'snapshot': is_snapshot})
|
||||
|
||||
# configure access control
|
||||
if is_snapshot:
|
||||
ldname = self._create_snapshot_and_link(
|
||||
volume, connector,
|
||||
self._properties['diskarray_name'],
|
||||
self._validate_iscsildset_exist)
|
||||
else:
|
||||
ldname = self._export_volume(volume, connector,
|
||||
self._properties['diskarray_name'],
|
||||
self._validate_iscsildset_exist)
|
||||
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
# enumerate portals for iscsi multipath.
|
||||
ld = lds[ldname]
|
||||
ldset = self._validate_iscsildset_exist(ldsets, connector)
|
||||
prefered_director = ld['pool_num'] % 2
|
||||
portals = self._enumerate_iscsi_portals(hostports, ldset,
|
||||
prefered_director)
|
||||
|
||||
provider_location = volume.provider_location
|
||||
provider_location = provider_location.split()
|
||||
info = {'driver_volume_type': 'iscsi',
|
||||
'data': {'target_portal':
|
||||
provider_location[0][0:-2].split(";")[0],
|
||||
'target_iqn': provider_location[1],
|
||||
'target_lun': int(provider_location[2]),
|
||||
portals[int(volume.id[:1], 16) % len(portals)],
|
||||
'target_iqn': ldset['lds'][ld['ldn']]['iqn'],
|
||||
'target_lun': ldset['lds'][ld['ldn']]['lun'],
|
||||
'target_discovered': False,
|
||||
'volume_id': volume.id}
|
||||
}
|
||||
if connector.get('multipath'):
|
||||
portals_len = len(provider_location[0][0:-2].split(";"))
|
||||
info['data'].update({'target_portals':
|
||||
provider_location[0][0:-2].split(";"),
|
||||
'target_iqns': [provider_location[1]] *
|
||||
portals_len,
|
||||
'target_luns': [int(provider_location[2])] *
|
||||
portals_len})
|
||||
portals_len = len(portals)
|
||||
info['data'].update({'target_portals': portals,
|
||||
'target_iqns': [ldset['lds'][ld['ldn']]
|
||||
['iqn']] * portals_len,
|
||||
'target_luns': [ldset['lds'][ld['ldn']]
|
||||
['lun']] * portals_len})
|
||||
LOG.debug('_iscsi_initialize_connection'
|
||||
'(Volume ID = %(id)s, connector = %(connector)s, '
|
||||
'info = %(info)s) End.',
|
||||
@ -1133,7 +999,8 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
% {'id': snapshot.id, 'connector': connector})
|
||||
|
||||
try:
|
||||
ret = self._iscsi_initialize_connection(snapshot, connector)
|
||||
ret = self._iscsi_initialize_connection(snapshot, connector,
|
||||
is_snapshot=True)
|
||||
LOG.info('Initialized iSCSI Connection snapshot(%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
@ -1217,7 +1084,7 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
'(%(msgparm)s) (%(exception)s)',
|
||||
{'msgparm': msgparm, 'exception': e})
|
||||
|
||||
def _fc_initialize_connection(self, volume, connector):
|
||||
def _fc_initialize_connection(self, volume, connector, is_snapshot=False):
|
||||
"""Initializes the connection and returns connection info.
|
||||
|
||||
The driver returns a driver_volume_type of 'fibre_channel'.
|
||||
@ -1249,15 +1116,27 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
"""
|
||||
|
||||
LOG.debug('_fc_initialize_connection'
|
||||
'(Volume ID = %(id)s, connector = %(connector)s) Start.',
|
||||
{'id': volume.id, 'connector': connector})
|
||||
'(Volume ID = %(id)s, connector = %(connector)s, '
|
||||
'snapshot = %(snapshot)s) Start.',
|
||||
{'id': volume.id, 'connector': connector,
|
||||
'snapshot': is_snapshot})
|
||||
|
||||
if is_snapshot:
|
||||
ldname = self._create_snapshot_and_link(
|
||||
volume, connector,
|
||||
self._properties['diskarray_name'],
|
||||
self._validate_fcldset_exist)
|
||||
else:
|
||||
ldname = self._export_volume(volume, connector,
|
||||
self._properties['diskarray_name'],
|
||||
self._validate_fcldset_exist)
|
||||
|
||||
# update local info.
|
||||
xml = self._cli.view_all(self._properties['ismview_path'])
|
||||
pools, lds, ldsets, used_ldns, hostports, max_ld_count = (
|
||||
self.configs(xml))
|
||||
|
||||
# get target wwpns and initiator/target map.
|
||||
|
||||
fc_ports = []
|
||||
for director, hostport in hostports.items():
|
||||
for port in hostport:
|
||||
@ -1266,16 +1145,9 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
target_wwns, init_targ_map = (
|
||||
self._build_initiator_target_map(connector, fc_ports))
|
||||
|
||||
# get link volume number
|
||||
ldname = self.get_ldname(
|
||||
volume.id, self._properties['ld_name_format'])
|
||||
|
||||
# get lun.
|
||||
if ldname not in lds:
|
||||
msg = (_('Logical Disk %(ld)s has unbound already. '
|
||||
'volume_id = %(id)s.') %
|
||||
{'ld': ldname, 'id': volume.id})
|
||||
LOG.error(msg)
|
||||
raise exception.NotFound(msg)
|
||||
lvname = ldname + '_l'
|
||||
if lvname in lds:
|
||||
ldn = lds[lvname]['ldn']
|
||||
@ -1307,7 +1179,8 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
% {'id': snapshot.id, 'connector': connector})
|
||||
|
||||
try:
|
||||
ret = self._fc_initialize_connection(snapshot, connector)
|
||||
ret = self._fc_initialize_connection(snapshot, connector,
|
||||
is_snapshot=True)
|
||||
LOG.info('Initialized FC Connection snapshot(%s)', msgparm)
|
||||
return ret
|
||||
except exception.CinderException as e:
|
||||
@ -1451,7 +1324,8 @@ class MStorageDriver(volume_common.MStorageVolumeCommon):
|
||||
data['multiattach'] = True
|
||||
data['location_info'] = (self._properties['cli_fip'] + ":"
|
||||
+ (','.join(map(str,
|
||||
self._properties['pool_pools']))))
|
||||
self._properties['pool_pools']
|
||||
))))
|
||||
|
||||
# Get xml data from file and parse.
|
||||
try:
|
||||
|
@ -86,8 +86,6 @@ For details of each command, see the NEC Storage Manager Command Reference
|
||||
#. Set IP addresses of each iSCSI port. (iSMcfg setiscsiport)
|
||||
#. Create LD Sets for each node.
|
||||
(iSMcfg addldset)
|
||||
#. Delete some iSCSI portal settings of each LD Sets to set to
|
||||
``nec_iscsi_portals_per_cont`` parameter. (iSMcfg delldsetportal)
|
||||
#. Register initiator names of each node to the corresponding LD Set.
|
||||
(iSMcfg addldsetinitiator)
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
NEC Driver: Added support of more than 4 iSCSI portals
|
||||
for a node.
|
||||
deprecations:
|
||||
- |
|
||||
NEC Driver: Deprecated ``nec_iscsi_portals_per_cont``
|
||||
config option. The option was used to limit number of
|
||||
portals and is no longer needed.
|
||||
|
Loading…
Reference in New Issue
Block a user