diff --git a/cinder/tests/unit/volume/drivers/nec/test_volume.py b/cinder/tests/unit/volume/drivers/nec/test_volume.py
index a322991226a..aff3043e936 100644
--- a/cinder/tests/unit/volume/drivers/nec/test_volume.py
+++ b/cinder/tests/unit/volume/drivers/nec/test_volume.py
@@ -343,6 +343,11 @@ xml_out = '''
0000
0000
+
+ iqn.2001-03.target0001
+ 0001
+ 0006
+
Command Completed Successfully!!
@@ -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)
diff --git a/cinder/volume/drivers/nec/cli.py b/cinder/volume/drivers/nec/cli.py
index e726bb137da..6aa612314ad 100644
--- a/cinder/volume/drivers/nec/cli.py
+++ b/cinder/volume/drivers/nec/cli.py
@@ -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):
diff --git a/cinder/volume/drivers/nec/volume.py b/cinder/volume/drivers/nec/volume.py
index a077e6b30da..5f9b5f1f5c6 100644
--- a/cinder/volume/drivers/nec/volume.py
+++ b/cinder/volume/drivers/nec/volume.py
@@ -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,
diff --git a/cinder/volume/drivers/nec/volume_common.py b/cinder/volume/drivers/nec/volume_common.py
index 3c2b142deda..37144a01f51 100644
--- a/cinder/volume/drivers/nec/volume_common.py
+++ b/cinder/volume/drivers/nec/volume_common.py
@@ -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
diff --git a/cinder/volume/drivers/nec/volume_helper.py b/cinder/volume/drivers/nec/volume_helper.py
index 5ed12e18e55..2f5dedb70d9 100644
--- a/cinder/volume/drivers/nec/volume_helper.py
+++ b/cinder/volume/drivers/nec/volume_helper.py
@@ -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:
diff --git a/doc/source/configuration/block-storage/drivers/nec-storage-m-series-driver.rst b/doc/source/configuration/block-storage/drivers/nec-storage-m-series-driver.rst
index ed8bbdd2b1b..3504a675ddd 100644
--- a/doc/source/configuration/block-storage/drivers/nec-storage-m-series-driver.rst
+++ b/doc/source/configuration/block-storage/drivers/nec-storage-m-series-driver.rst
@@ -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)
diff --git a/releasenotes/notes/nec-allow-more-than-4iSCSI-portals-8342defe64491f81.yaml b/releasenotes/notes/nec-allow-more-than-4iSCSI-portals-8342defe64491f81.yaml
new file mode 100644
index 00000000000..a9458b18773
--- /dev/null
+++ b/releasenotes/notes/nec-allow-more-than-4iSCSI-portals-8342defe64491f81.yaml
@@ -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.
+