Merge "Add CHAP support for Huawei driver"
This commit is contained in:
commit
933ccdfcc1
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]"
|
||||
|
|
Loading…
Reference in New Issue