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:
parent
f16cc2f590
commit
3c36251017
@ -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})
|
||||
|
@ -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
|
||||
|
@ -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':
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
upgrade:
|
||||
- Support iSCSI configuration in replication in Huawei driver.
|
Loading…
Reference in New Issue
Block a user