Merge "Add CHAP support for Huawei driver"

This commit is contained in:
Jenkins 2015-07-23 03:15:42 +00:00 committed by Gerrit Code Review
commit 933ccdfcc1
3 changed files with 152 additions and 7 deletions

View File

@ -737,6 +737,14 @@ MAP_COMMAND_TO_FAKE_RESPONSE['iscsi_initiator?range=[0-256]/GET'] = (
MAP_COMMAND_TO_FAKE_RESPONSE['iscsi_initiator/'] = (
FAKE_ISCSI_INITIATOR_RESPONSE)
MAP_COMMAND_TO_FAKE_RESPONSE['iscsi_initiator/POST'] = (
FAKE_ISCSI_INITIATOR_RESPONSE)
MAP_COMMAND_TO_FAKE_RESPONSE['iscsi_initiator/PUT'] = (
FAKE_ISCSI_INITIATOR_RESPONSE)
MAP_COMMAND_TO_FAKE_RESPONSE['iscsi_initiator/'
'iqn.1993-08.debian:01:ec2bff7ac3a3/PUT'] = (
FAKE_ISCSI_INITIATOR_RESPONSE)
# mock host info map
MAP_COMMAND_TO_FAKE_RESPONSE['host?range=[0-65535]/GET'] = (
FAKE_GET_ALL_HOST_INFO_RESPONSE)
@ -805,6 +813,7 @@ class Fake18000Client(rest_client.RestClient):
self.deviceid = None
self.test_fail = False
self.checkFlag = False
self.remove_chap_flag = False
def _change_file_mode(self, filepath):
pass
@ -1043,6 +1052,34 @@ class Huawei18000ISCSIDriverTestCase(test.TestCase):
self.configuration)
self.assertEqual('0', host_os)
def test_find_chap_info(self):
self.driver.restclient.login()
tmp_dict = {}
iscsi_info = {}
tmp_dict['Name'] = 'iqn.1993-08.debian:01:ec2bff7ac3a3'
tmp_dict['CHAPinfo'] = 'mm-user;mm-user@storage'
ini_list = [tmp_dict]
iscsi_info['Initiator'] = ini_list
initiator_name = FakeConnector['initiator']
chapinfo = self.driver.restclient.find_chap_info(iscsi_info,
initiator_name)
chap_username, chap_password = chapinfo.split(';')
self.assertEqual('mm-user', chap_username)
self.assertEqual('mm-user@storage', chap_password)
def test_find_alua_info(self):
self.driver.restclient.login()
tmp_dict = {}
iscsi_info = {}
tmp_dict['Name'] = 'iqn.1993-08.debian:01:ec2bff7ac3a3'
tmp_dict['ALUA'] = '1'
ini_list = [tmp_dict]
iscsi_info['Initiator'] = ini_list
initiator_name = FakeConnector['initiator']
type = self.driver.restclient._find_alua_info(iscsi_info,
initiator_name)
self.assertEqual('1', type)
def create_fake_conf_file(self):
"""Create a fake Config file.
@ -1115,6 +1152,8 @@ class Huawei18000ISCSIDriverTestCase(test.TestCase):
initiator = doc.createElement('Initiator')
initiator.setAttribute('Name', 'iqn.1993-08.debian:01:ec2bff7ac3a3')
initiator.setAttribute('TargetIP', '192.168.100.2')
initiator.setAttribute('CHAPinfo', 'mm-user;mm-user@storage')
initiator.setAttribute('ALUA', '1')
iscsi.appendChild(initiator)
host = doc.createElement('Host')

View File

@ -354,7 +354,9 @@ class HuaweiBaseDriver(driver.VolumeDriver):
host_name_before_hash)
# Add initiator to the host.
self.restclient.ensure_initiator_added(initiator_name, host_id)
self.restclient.ensure_initiator_added(self.xml_file_path,
initiator_name,
host_id)
hostgroup_id = self.restclient.add_host_into_hostgroup(host_id)
# Mapping lungroup and hostgroup to view.
@ -368,6 +370,9 @@ class HuaweiBaseDriver(driver.VolumeDriver):
LOG.info(_LI("initialize_connection_iscsi, host lun id is: %s."),
hostlun_id)
iscsi_conf = huawei_utils.get_iscsi_conf(self.xml_file_path)
chapinfo = self.restclient.find_chap_info(iscsi_conf,
initiator_name)
# Return iSCSI properties.
properties = {}
properties['target_discovered'] = False
@ -376,6 +381,13 @@ class HuaweiBaseDriver(driver.VolumeDriver):
properties['target_lun'] = int(hostlun_id)
properties['volume_id'] = volume['id']
# If use CHAP, return CHAP info.
if chapinfo:
chap_username, chap_password = chapinfo.split(';')
properties['auth_method'] = 'CHAP'
properties['auth_username'] = chap_username
properties['auth_password'] = chap_password
LOG.info(_LI("initialize_connection_iscsi success. Return data: %s."),
properties)
return {'driver_volume_type': 'iscsi', 'data': properties}
@ -434,6 +446,8 @@ class HuaweiBaseDriver(driver.VolumeDriver):
self.restclient.delete_portgroup_mapping_view(view_id,
portgroup_id)
if view_id and (int(left_lunnum) <= 0):
self.restclient.remove_chap(initiator_name)
if self.restclient.lungroup_associated(view_id, lungroup_id):
self.restclient.delete_lungroup_mapping_view(view_id,
lungroup_id)

View File

@ -388,12 +388,14 @@ class RestClient(object):
return lun_id
def ensure_initiator_added(self, initiator_name, host_id):
def ensure_initiator_added(self, xml_file_path, initiator_name, host_id):
added = self._initiator_is_added_to_array(initiator_name)
if not added:
self._add_initiator_to_array(initiator_name)
if not self.is_initiator_associated_to_host(initiator_name):
self._associate_initiator_to_host(initiator_name, host_id)
self._associate_initiator_to_host(xml_file_path,
initiator_name,
host_id)
def _get_iscsi_tgt_port(self):
url = self.url + "/iscsidevicename"
@ -681,17 +683,107 @@ class RestClient(object):
result = self.call(url, data)
self._assert_rest_result(result, 'Add initiator to array error.')
def _associate_initiator_to_host(self, ininame, host_id):
"""Associate initiator with the host."""
url = self.url + "/iscsi_initiator/" + ininame
def _add_initiator_to_host(self, initiator_name, host_id):
url = self.url + "/iscsi_initiator/" + initiator_name
data = json.dumps({"TYPE": "222",
"ID": ininame,
"ID": initiator_name,
"USECHAP": "false",
"PARENTTYPE": "21",
"PARENTID": host_id})
result = self.call(url, data, "PUT")
self._assert_rest_result(result, 'Associate initiator to host error.')
def _associate_initiator_to_host(self,
xml_file_path,
initiator_name,
host_id):
"""Associate initiator with the host."""
iscsi_conf = huawei_utils.get_iscsi_conf(xml_file_path)
chapinfo = None
multipathtype = None
chapinfo = self.find_chap_info(iscsi_conf,
initiator_name)
multipathtype = self._find_alua_info(iscsi_conf,
initiator_name)
if chapinfo:
LOG.info(_LI('Use CHAP when adding initiator to host.'))
self._use_chap(chapinfo, initiator_name, host_id)
else:
self._add_initiator_to_host(initiator_name, host_id)
if multipathtype:
LOG.info(_LI('Use ALUA when adding initiator to host.'))
self._use_alua(initiator_name, multipathtype)
def find_chap_info(self, iscsi_conf, initiator_name):
"""Find CHAP info from xml."""
chapinfo = None
for ini in iscsi_conf['Initiator']:
if ini['Name'] == initiator_name:
if 'CHAPinfo' in ini:
chapinfo = ini['CHAPinfo']
break
return chapinfo
def _find_alua_info(self, iscsi_conf, initiator_name):
"""Find ALUA info from xml."""
multipathtype = 0
for ini in iscsi_conf['Initiator']:
if ini['Name'] == initiator_name:
if 'ALUA' in ini:
if ini['ALUA'] != '1' and ini['ALUA'] != '0':
msg = (_(
'Invalid ALUA value. '
'ALUA value must be 1 or 0.'))
LOG.error(msg)
raise exception.InvalidInput(msg)
else:
multipathtype = ini['ALUA']
break
return multipathtype
def _use_chap(self, chapinfo, initiator_name, host_id):
"""Use CHAP when adding initiator to host."""
(chap_username, chap_password) = chapinfo.split(";")
url = self.url + "/iscsi_initiator/" + initiator_name
data = json.dumps({"TYPE": "222",
"USECHAP": "true",
"CHAPNAME": chap_username,
"CHAPPASSWORD": chap_password,
"ID": initiator_name,
"PARENTTYPE": "21",
"PARENTID": host_id})
result = self.call(url, data, "PUT")
self._assert_rest_result(result,
'Use CHAP to associate initiator '
'to host error. Please check the CHAP '
'username and password.')
def _use_alua(self, initiator_name, multipathtype):
"""Use ALUA when adding initiator to host."""
url = self.url + "/iscsi_initiator"
data = json.dumps({"ID": initiator_name,
"MULTIPATHTYPE": multipathtype})
result = self.call(url, data, "PUT")
self._assert_rest_result(result,
'Use ALUA to associate initiator '
'to host error.')
def remove_chap(self, initiator_name):
"""Remove CHAP when terminate connection."""
url = self.url + "/iscsi_initiator"
data = json.dumps({"USECHAP": "false",
"MULTIPATHTYPE": "0",
"ID": initiator_name})
result = self.call(url, data, "PUT")
self._assert_rest_result(result, 'Remove CHAP error.')
def find_mapping_view(self, name):
"""Find mapping view."""
url = self.url + "/mappingview?range=[0-8191]"