diff --git a/cinder/tests/unit/test_huawei_drivers.py b/cinder/tests/unit/test_huawei_drivers.py index 28f823518be..5288939ebda 100644 --- a/cinder/tests/unit/test_huawei_drivers.py +++ b/cinder/tests/unit/test_huawei_drivers.py @@ -1886,12 +1886,20 @@ class FakeHuaweiConf(huawei_conf.HuaweiConf): 'TargetPortGroup': 'portgroup-test', } setattr(self.conf, 'iscsi_info', [iscsi_info]) + rmt_iscsi_info = ('{ Name: iqn.1993-08.debian:01:ec2bff7acxxx;\n' + 'TargetIP:1.1.1.1;CHAPinfo:mm-user#mm-user@storage;' + 'ALUA:1; TargetPortGroup:portgroup-test};\t\n ' + '{ Name: iqn.1993-08.debian:01:ec2bff7acyyy;\n' + 'TargetIP:2.2.2.2;CHAPinfo:nn-user#nn-user@storage;' + 'ALUA:0; TargetPortGroup:portgroup-test1}\t\n') + targets = [{'backend_id': REPLICA_BACKEND_ID, 'storage_pool': 'OpenStack_Pool', 'san_address': 'https://192.0.2.69:8088/deviceManager/rest/', 'san_user': 'admin', - 'san_password': 'Admin@storage1'}] + 'san_password': 'Admin@storage1', + 'iscsi_info': rmt_iscsi_info}] setattr(self.conf, 'replication_device', targets) setattr(self.conf, 'safe_get', self.safe_get) @@ -2032,6 +2040,27 @@ class HuaweiISCSIDriverTestCase(test.TestCase): self.portgroup_id = 11 self.driver.client.login() + def test_parse_rmt_iscsi_info(self): + rmt_devs = self.driver.huawei_conf.get_replication_devices() + iscsi_info = rmt_devs[0]['iscsi_info'] + expected_iscsi_info = [{'Name': 'iqn.1993-08.debian:01:ec2bff7acxxx', + 'TargetIP': '1.1.1.1', + 'CHAPinfo': 'mm-user;mm-user@storage', + 'ALUA': '1', + 'TargetPortGroup': 'portgroup-test'}, + {'Name': 'iqn.1993-08.debian:01:ec2bff7acyyy', + 'TargetIP': '2.2.2.2', + 'CHAPinfo': 'nn-user;nn-user@storage', + 'ALUA': '0', + 'TargetPortGroup': 'portgroup-test1'}] + self.assertEqual(expected_iscsi_info, iscsi_info) + + def test_parse_rmt_iscsi_info_without_iscsi_configuration(self): + self.configuration.replication_device[0]['iscsi_info'] = '' + rmt_devs = self.driver.huawei_conf.get_replication_devices() + iscsi_info = rmt_devs[0]['iscsi_info'] + self.assertEqual([], iscsi_info) + def test_login_success(self): device_id = self.driver.client.login() self.assertEqual('210235G7J20000000000', device_id) @@ -2136,7 +2165,7 @@ class HuaweiISCSIDriverTestCase(test.TestCase): def test_get_volume_status(self): data = self.driver.get_volume_stats() - self.assertEqual('2.0.5', data['driver_version']) + self.assertEqual('2.0.6', data['driver_version']) @mock.patch.object(rest_client.RestClient, 'get_lun_info', return_value={"CAPACITY": 6291456}) diff --git a/cinder/volume/drivers/huawei/huawei_conf.py b/cinder/volume/drivers/huawei/huawei_conf.py index 6a7a9b7670a..462276bbe13 100644 --- a/cinder/volume/drivers/huawei/huawei_conf.py +++ b/cinder/volume/drivers/huawei/huawei_conf.py @@ -252,6 +252,50 @@ class HuaweiConf(object): setattr(self.conf, 'iscsi_info', iscsi_info) + def _parse_rmt_iscsi_info(self, iscsi_info): + if not (iscsi_info and iscsi_info.strip()): + return [] + + # Consider iscsi_info value: + # ' {Name:xxx ;;TargetPortGroup: xxx};\n' + # '{Name:\t\rxxx;CHAPinfo: mm-usr#mm-pwd} ' + + # Step 1, ignore whitespace characters, convert to: + # '{Name:xxx;;TargetPortGroup:xxx};{Name:xxx;CHAPinfo:mm-usr#mm-pwd}' + iscsi_info = ''.join(iscsi_info.split()) + + # Step 2, make initiators configure list, convert to: + # ['Name:xxx;;TargetPortGroup:xxx', 'Name:xxx;CHAPinfo:mm-usr#mm-pwd'] + initiator_infos = iscsi_info[1:-1].split('};{') + + # Step 3, get initiator configure pairs, convert to: + # [['Name:xxx', '', 'TargetPortGroup:xxx'], + # ['Name:xxx', 'CHAPinfo:mm-usr#mm-pwd']] + initiator_infos = map(lambda x: x.split(';'), initiator_infos) + + # Step 4, remove invalid configure pairs, convert to: + # [['Name:xxx', 'TargetPortGroup:xxx'], + # ['Name:xxx', 'CHAPinfo:mm-usr#mm-pwd']] + initiator_infos = map(lambda x: filter(lambda y: y, x), + initiator_infos) + + # Step 5, make initiators configure dict, convert to: + # [{'TargetPortGroup': 'xxx', 'Name': 'xxx'}, + # {'Name': 'xxx', 'CHAPinfo': 'mm-usr#mm-pwd'}] + get_opts = lambda x: x.split(':', 1) + initiator_infos = map(lambda x: dict(map(get_opts, x)), + initiator_infos) + # Convert generator to list for py3 compatibility. + initiator_infos = list(initiator_infos) + + # Step 6, replace CHAPinfo 'user#pwd' to 'user;pwd' + key = 'CHAPinfo' + for info in initiator_infos: + if key in info: + info[key] = info[key].replace('#', ';', 1) + + return initiator_infos + def get_replication_devices(self): devs = self.conf.safe_get('replication_device') if not devs: @@ -265,7 +309,8 @@ class HuaweiConf(object): dev_config['san_user'] = dev['san_user'] dev_config['san_password'] = dev['san_password'] dev_config['storage_pool'] = dev['storage_pool'].split(';') - dev_config['iscsi_info'] = [] + dev_config['iscsi_info'] = self._parse_rmt_iscsi_info( + dev.get('iscsi_info')) dev_config['iscsi_default_target_ip'] = ( dev['iscsi_default_target_ip'].split(';') if 'iscsi_default_target_ip' in dev diff --git a/cinder/volume/drivers/huawei/huawei_driver.py b/cinder/volume/drivers/huawei/huawei_driver.py index 704ec67a41f..6b8bab6ff54 100644 --- a/cinder/volume/drivers/huawei/huawei_driver.py +++ b/cinder/volume/drivers/huawei/huawei_driver.py @@ -1607,9 +1607,10 @@ class HuaweiISCSIDriver(HuaweiBaseDriver, driver.ISCSIDriver): 2.0.2 - Refactor HuaweiISCSIDriver 2.0.3 - Manage/unmanage snapshot support 2.0.5 - Replication V2 support + 2.0.6 - Support iSCSI configuration in Replication """ - VERSION = "2.0.5" + VERSION = "2.0.6" def __init__(self, *args, **kwargs): super(HuaweiISCSIDriver, self).__init__(*args, **kwargs) @@ -1667,7 +1668,7 @@ class HuaweiISCSIDriver(HuaweiBaseDriver, driver.ISCSIDriver): LOG.info(_LI("initialize_connection, host lun id is: %s."), hostlun_id) - chapinfo = self.client.find_chap_info(self.configuration.iscsi_info, + chapinfo = self.client.find_chap_info(self.client.iscsi_info, initiator_name) # Return iSCSI properties. @@ -1716,7 +1717,7 @@ class HuaweiISCSIDriver(HuaweiBaseDriver, driver.ISCSIDriver): portgroup_id = None view_id = None left_lunnum = -1 - for ini in self.configuration.iscsi_info: + for ini in self.client.iscsi_info: if ini['Name'] == initiator_name: for key in ini: if key == 'TargetPortGroup': diff --git a/releasenotes/notes/huawei-support-iscsi-configuration-in-replication-7ec53737b95ffa54.yaml b/releasenotes/notes/huawei-support-iscsi-configuration-in-replication-7ec53737b95ffa54.yaml new file mode 100644 index 00000000000..3b79696f65e --- /dev/null +++ b/releasenotes/notes/huawei-support-iscsi-configuration-in-replication-7ec53737b95ffa54.yaml @@ -0,0 +1,3 @@ +--- +upgrade: + - Support iSCSI configuration in replication in Huawei driver.