Huawei: Support iSCSI configuration in replication feature

In most case, users need much more features to attach volume to VM,
such as iSCSI multipath, CHAP, etc. In Huawei cinder driver replication
feature, we need to fit the case when using iSCSI driver.

We add a new key word into replication_device, called iscsi_info. The
detail as follows:

    replication_device = backend_id:huawei-replica-1,
        storage_pool:pool_1,
        san_address:san_url_1;san_url_2,
        iscsi_default_target_ip:192.168.1.100,
        san_user:admin,san_password:passwd,
        iscsi_info: {Name:xxx;CHAPinfo:user#password;ALUA:1;
                     TargetIP:0.0.0.0;TargetPortGroup:xxx};
                    {Name:xxx;CHAPinfo:user#password;ALUA:1;
                     TargetIP:0.0.0.0;TargetPortGroup:xxx}

All key words in iscsi_info are case insensitive. The meaning of them
are the same with that in huawei_config.xml, which always used in
master array.

Change-Id: I4a0cce1858c3a8539a62e7dae6e1092d4e86707f
Closes-Bug: #1588736
This commit is contained in:
Liucheng Jiang 2016-06-06 09:02:32 +08:00 committed by huyang
parent f16cc2f590
commit 3c36251017
4 changed files with 84 additions and 6 deletions

View File

@ -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})

View File

@ -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

View File

@ -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':

View File

@ -0,0 +1,3 @@
---
upgrade:
- Support iSCSI configuration in replication in Huawei driver.