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)
self.deviceid = None
self.test_fail = False
self.checkFlag = False
+ self.remove_chap_flag = False
def _change_file_mode(self, filepath):
pass
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.
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')
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.
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
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}
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)
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"
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]"