def _get_service_target(self, volume): """Get the available service parameters Get the available service parameters for a given volume using its type. :param volume: dictionary volume reference """ hdp = self._get_service(volume) info = _loc_info(volume['provider_location']) (arid, lun_name) = info['id_lu'] evsid = self.bend.get_evs(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], hdp) svc_label = utils.extract_host(volume['host'], level='pool') svc = self.config['services'][svc_label] LOG.info(_LI("_get_service_target hdp: %s."), hdp) LOG.info(_LI("config[services]: %s."), self.config['services']) mapped, lunid, tgt = self.bend.check_lu(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], lun_name, hdp) LOG.info(_LI("Target is %(map)s! Targetlist = %(tgtl)s."), { 'map': "mapped" if mapped else "not mapped", 'tgtl': tgt }) # The volume is already mapped to a LUN, so no need to create any # targets if mapped: service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], hdp, tgt['alias'], tgt['secret']) return service # Each EVS can have up to 32 targets. Each target can have up to 32 # LUNs attached and have the name format 'evs<id>-tgt<0-N>'. We run # from the first 'evs1-tgt0' until we find a target that is not already # created in the BE or is created but have slots to place new targets. found_tgt = False for i in range(0, MAX_HNAS_ISCSI_TARGETS): tgt_alias = 'evs' + evsid + '-tgt' + six.text_type(i) # TODO(erlon): we need to go to the BE 32 times here tgt_exist, tgt = self.bend.check_target(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], hdp, tgt_alias) if tgt_exist and len(tgt['luns']) < 32 or not tgt_exist: # Target exists and has free space or, target does not exist # yet. Proceed and use the target or create a target using this # name. found_tgt = True break # If we've got here and found_tgt is not True, we run out of targets, # raise and go away. if not found_tgt: LOG.error(_LE("No more targets avaliable.")) raise exception.NoMoreTargets(param=tgt_alias) LOG.info(_LI("Using target label: %s."), tgt_alias) # Check if we have a secret stored for this target so we don't have to # go to BE on every query if 'targets' not in self.config.keys(): self.config['targets'] = {} if tgt_alias not in self.config['targets'].keys(): self.config['targets'][tgt_alias] = {} tgt_info = self.config['targets'][tgt_alias] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled'] == 'True': # It may not exist, create and set secret. if 'iscsi_secret' not in tgt_info.keys(): LOG.info(_LI("Retrieving secret for service: %s."), tgt_alias) out = self.bend.get_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp) tgt_info['iscsi_secret'] = out if tgt_info['iscsi_secret'] == "": randon_secret = utils.generate_password()[0:15] tgt_info['iscsi_secret'] = randon_secret self.bend.set_targetsecret(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp, tgt_info['iscsi_secret']) LOG.info(_LI("Set tgt CHAP secret for service: %s."), tgt_alias) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exists in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in tgt_info.keys(): # Warns in the first time LOG.info(_LI("CHAP authentication disabled.")) tgt_info['iscsi_secret'] = "" if 'tgt_iqn' not in tgt_info: LOG.info(_LI("Retrieving target for service: %s."), tgt_alias) out = self.bend.get_targetiqn(self.config['hnas_cmd'], self.config['mgmt_ip0'], self.config['username'], self.config['password'], tgt_alias, hdp, tgt_info['iscsi_secret']) tgt_info['tgt_iqn'] = out self.config['targets'][tgt_alias] = tgt_info service = (svc['iscsi_ip'], svc['iscsi_port'], svc['ctl'], svc['port'], hdp, tgt_alias, tgt_info['iscsi_secret']) return service
def _get_service_target(self, volume): """Gets the available service parameters Gets the available service parameters for a given volume using its type. :param volume: dictionary volume reference :returns: service target information or raises error :raises: NoMoreTargets """ fs_label = self._get_service(volume) evs_id = self.backend.get_evs(fs_label) svc_label = utils.extract_host(volume.host, level='pool') svc = self.config['services'][svc_label] lu_info = self.backend.check_lu(volume.name, fs_label) # The volume is already mapped to a LU, so no need to create any # targets if lu_info['mapped']: service = (svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'], fs_label, lu_info['tgt']['alias'], lu_info['tgt']['secret']) LOG.info( _LI("Volume %(vol_name)s already mapped on target " "%(tgt)s to LUN %(lunid)s."), { 'vol_name': volume.name, 'tgt': lu_info['tgt']['alias'], 'lunid': lu_info['id'] }) return service # Each EVS can have up to 32 targets. Each target can have up to 32 # LUs attached and have the name format 'evs<id>-tgt<0-N>'. We run # from the first 'evs1-tgt0' until we find a target that is not already # created in the BE or is created but have slots to place new LUs. tgt_alias = '' for i in range(0, MAX_HNAS_ISCSI_TARGETS): tgt_alias = 'evs' + evs_id + '-tgt' + six.text_type(i) tgt = self.backend.check_target(fs_label, tgt_alias) if (tgt['found'] and len(tgt['tgt']['lus']) < MAX_HNAS_LUS_PER_TARGET or not tgt['found']): # Target exists and has free space or, target does not exist # yet. Proceed and use the target or create a target using this # name. break else: # If we've got here, we run out of targets, raise and go away. LOG.error(_LE("No more targets available.")) raise exception.NoMoreTargets(param=tgt_alias) LOG.info(_LI("Using target label: %(tgt)s."), {'tgt': tgt_alias}) # Check if we have a secret stored for this target so we don't have to # go to BE on every query if 'targets' not in self.config.keys(): self.config['targets'] = {} if tgt_alias not in self.config['targets'].keys(): self.config['targets'][tgt_alias] = {} tgt_info = self.config['targets'][tgt_alias] # HNAS - one time lookup # see if the client supports CHAP authentication and if # iscsi_secret has already been set, retrieve the secret if # available, otherwise generate and store if self.config['chap_enabled']: # CHAP support is enabled. Tries to get the target secret. if 'iscsi_secret' not in tgt_info.keys(): LOG.info(_LI("Retrieving secret for service: %(tgt)s."), {'tgt': tgt_alias}) out = self.backend.get_target_secret(tgt_alias, fs_label) tgt_info['iscsi_secret'] = out # CHAP supported and the target has no secret yet. So, the # secret is created for the target if tgt_info['iscsi_secret'] == "": random_secret = utils.generate_password()[0:15] tgt_info['iscsi_secret'] = random_secret LOG.info(_LI("Set tgt CHAP secret for service: %(tgt)s."), {'tgt': tgt_alias}) else: # We set blank password when the client does not # support CHAP. Later on, if the client tries to create a new # target that does not exist in the backend, we check for this # value and use a temporary dummy password. if 'iscsi_secret' not in tgt_info.keys(): # Warns in the first time LOG.info(_LI("CHAP authentication disabled.")) tgt_info['iscsi_secret'] = "''" # If the target does not exist, it should be created if not tgt['found']: self.backend.create_target(tgt_alias, fs_label, tgt_info['iscsi_secret']) elif (tgt['tgt']['secret'] == "" and self.config['chap_enabled']): # The target exists, has no secret and chap is enabled self.backend.set_target_secret(tgt_alias, fs_label, tgt_info['iscsi_secret']) if 'tgt_iqn' not in tgt_info: LOG.info(_LI("Retrieving IQN for service: %(tgt)s."), {'tgt': tgt_alias}) out = self.backend.get_target_iqn(tgt_alias, fs_label) tgt_info['tgt_iqn'] = out self.config['targets'][tgt_alias] = tgt_info service = (svc['iscsi_ip'], svc['iscsi_port'], svc['evs'], svc['port'], fs_label, tgt_alias, tgt_info['iscsi_secret']) return service