Exemple #1
0
    def create_export(self, context, volume, connector):
        """Driver entry point to get the export info for a new volume."""
        target_name = self._get_target_name(volume)
        updates = {}

        if not self._tgt_utils.iscsi_target_exists(target_name):
            self._tgt_utils.create_iscsi_target(target_name)
            updates['provider_location'] = target_name

            if self.configuration.use_chap_auth:
                chap_username = (self.configuration.chap_username
                                 or volume_utils.generate_username())
                chap_password = (self.configuration.chap_password
                                 or volume_utils.generate_password())

                self._tgt_utils.set_chap_credentials(target_name,
                                                     chap_username,
                                                     chap_password)

                updates['provider_auth'] = ' '.join(
                    ('CHAP', chap_username, chap_password))

        # This operation is idempotent
        self._tgt_utils.add_disk_to_target(volume.name, target_name)

        return updates
Exemple #2
0
    def create_export(self, context, volume, volume_path):
        """Creates an export for a logical volume."""
        # 'iscsi_name': 'iqn.2010-10.org.openstack:volume-00000001'
        iscsi_name = "%s%s" % (self.configuration.target_prefix,
                               volume['name'])
        iscsi_target, lun = self._get_target_and_lun(context, volume)

        # Verify we haven't setup a CHAP creds file already
        # if DNE no big deal, we'll just create it
        chap_auth = self._get_target_chap_auth(context, volume)
        if not chap_auth:
            chap_auth = (volume_utils.generate_username(),
                         volume_utils.generate_password())

        # Get portals ips and port
        portals_config = self._get_portals_config()

        # NOTE(jdg): For TgtAdm case iscsi_name is the ONLY param we need
        # should clean this all up at some point in the future
        tid = self.create_iscsi_target(iscsi_name,
                                       iscsi_target,
                                       lun,
                                       volume_path,
                                       chap_auth,
                                       **portals_config)
        data = {}
        data['location'] = self._iscsi_location(
            self.configuration.target_ip_address, tid, iscsi_name, lun,
            self.configuration.iscsi_secondary_ip_addresses)
        LOG.debug('Set provider_location to: %s', data['location'])
        data['auth'] = self._iscsi_authentication(
            'CHAP', *chap_auth)
        return data
Exemple #3
0
    def _get_provider_auth(self):
        """Get provider authentication for the volume.

        :return: string of auth method and credentials
        """
        chap_user = volume_utils.generate_password(
            length=8,
            symbolgroups=(string.ascii_lowercase + string.ascii_uppercase))

        chap_password = volume_utils.generate_password(
            length=self.jovian_chap_pass_len,
            symbolgroups=(string.ascii_lowercase + string.ascii_uppercase +
                          string.digits))

        return 'CHAP {user} {passwd}'.format(user=chap_user,
                                             passwd=chap_password)
Exemple #4
0
    def _configure_chap(self, initiator_name):
        password = volume_utils.generate_password(na_utils.CHAP_SECRET_LENGTH)
        username = na_utils.DEFAULT_CHAP_USER_NAME

        self.zapi_client.set_iscsi_chap_authentication(initiator_name,
                                                       username, password)
        LOG.debug("Set iSCSI CHAP authentication.")

        return username, password
Exemple #5
0
def get_chap_credentials():
    """Generate CHAP credentials.

    :return: CHAP username and secret
    """

    return {
        "chap_single_username": CHAP_DEFAULT_USERNAME,
        "chap_single_password": volume_utils.generate_password(
            CHAP_DEFAULT_SECRET_LENGTH
        )
    }
Exemple #6
0
    def initialize_connection(self, volume, connector):
        """Export a volume to a host."""
        # create client
        initiator_iqn = connector['initiator']
        self.create_client(initiator_iqn)
        auth = self._get_auth_for_client(initiator_iqn)
        username = initiator_iqn
        if not auth['password']:
            password = volume_utils.generate_password(length=self.CHAP_LENGTH)
            self._set_chap_for_client(initiator_iqn, username, password)
        else:
            LOG.debug("using existing CHAP password")
            password = auth['password']

        # add disk for export
        iscsi_config = self._get_config()

        # First have to ensure that the disk is registered with
        # the gateways.
        self.create_disk(volume.name)
        self.register_disk(self.target_iqn, volume.name)

        iscsi_config = self._get_config()
        # Now export the disk to the initiator
        lun = self.export_disk(initiator_iqn, volume.name, iscsi_config)

        # fetch the updated config so we can get the lun id
        iscsi_config = self._get_config()
        target_info = iscsi_config['targets'][self.target_iqn]
        ips = target_info['ip_list']

        target_portal = ips[0]
        if netutils.is_valid_ipv6(target_portal):
            target_portal = "[%s]:3260" % target_portal
        else:
            target_portal = "%s:3260" % target_portal

        data = {
            'driver_volume_type': 'iscsi',
            'data': {
                'target_iqn': self.target_iqn,
                'target_portal': target_portal,
                'target_lun': lun['id'],
                'auth_method': 'CHAP',
                'auth_username': username,
                'auth_password': password,
            }
        }
        return data
Exemple #7
0
    def create_nvmeof_target(self, volume_id, subsystem_name, target_ip,
                             target_port, transport_type, nvmet_port_id, ns_id,
                             volume_path):

        LOG.debug('SPDK create target')

        nqn = self._get_nqn_with_volume_name(volume_id)

        if nqn is None:
            node = self._get_first_free_node()
            nqn = '%s:cnode%s' % (subsystem_name, node)
            choice = string.ascii_uppercase + string.digits
            serial = ''.join(
                volume_utils.generate_password(length=12, symbolgroups=choice))

            params = {
                'nqn': nqn,
                'allow_any_host': True,
                'serial_number': serial,
            }
            self._rpc_call('nvmf_create_subsystem', params)

            listen_address = {
                'trtype': transport_type,
                'traddr': target_ip,
                'trsvcid': str(target_port),
            }
            params = {
                'nqn': nqn,
                'listen_address': listen_address,
            }
            self._rpc_call('nvmf_subsystem_add_listener', params)

            ns = {
                'bdev_name': self._get_spdk_volume_name(volume_id),
                'nsid': ns_id,
            }
            params = {
                'nqn': nqn,
                'namespace': ns,
            }
            self._rpc_call('nvmf_subsystem_add_ns', params)

        location = self.get_nvmeof_location(nqn, target_ip, target_port,
                                            transport_type, ns_id)

        return {'location': location, 'auth': '', 'provider_id': nqn}
Exemple #8
0
    def _target_create(self, identifier):
        if not identifier:
            err = _('Param [identifier] is invalid.')
            raise exception.InvalidParameterValue(err=err)

        # 0 for no auth, 1 for single chap, 2 for mutual chap
        auth_type = 0
        chap_username = ''
        chap_password = ''
        provider_auth = ''
        if self.config.safe_get('use_chap_auth') and self.config.use_chap_auth:
            auth_type = 1
            chap_username = (self.config.safe_get('chap_username')
                             or volume_utils.generate_username(12))
            chap_password = (self.config.safe_get('chap_password')
                             or volume_utils.generate_password())
            provider_auth = ' '.join(('CHAP', chap_username, chap_password))

        trg_prefix = self.config.safe_get('target_prefix')
        trg_name = (self.TARGET_NAME_PREFIX + '%s') % identifier
        iqn = trg_prefix + trg_name

        try:
            out = self.exec_webapi('SYNO.Core.ISCSI.Target',
                                   'create',
                                   1,
                                   name=trg_name,
                                   iqn=iqn,
                                   auth_type=auth_type,
                                   user=chap_username,
                                   password=chap_password,
                                   max_sessions=0)

            self.check_response(out)

        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception('Failed to _target_create. [%s]', identifier)

        if not self.check_value_valid(out, ['data', 'target_id']):
            msg = _('Failed to get target_id of target [%s]') % trg_name
            raise exception.VolumeDriverException(message=msg)

        trg_id = out['data']['target_id']

        return iqn, trg_id, provider_auth
Exemple #9
0
    def create_export(self, context, volume, volume_path):
        """Creates an export for a logical volume."""
        iscsi_target, lun = self._get_target_and_lun(context, volume)
        iscsi_name = self._get_iscsi_name(volume)

        if self.chap_username and self.chap_password:
            chap_auth = (self.chap_username, self.chap_password)
        else:
            chap_auth = self._get_target_chap_auth(context, volume)
            if not chap_auth:
                chap_auth = (volume_utils.generate_username(),
                             volume_utils.generate_password())
        tid = self.create_iscsi_target(iscsi_name, volume['id'], iscsi_target,
                                       lun, volume_path, chap_auth)

        data = {}
        data['location'] = self._iscsi_location(
            self.configuration.target_ip_address, tid, iscsi_name, lun)
        LOG.debug('Set provider_location to: %s', data['location'])
        data['auth'] = self._iscsi_authentication('CHAP', *chap_auth)
        return data
Exemple #10
0
    def _initialize_connection_iscsi(self, volume, connector):
        volume_name = self._make_volume_name(volume)
        infinidat_volume = self._get_infinidat_volume_by_name(volume_name)
        port = iqn.IQN(connector['initiator'])
        infinidat_host = self._get_or_create_host(port)
        if self.configuration.use_chap_auth:
            chap_username = (self.configuration.chap_username
                             or volume_utils.generate_username())
            chap_password = (self.configuration.chap_password
                             or volume_utils.generate_password())
            infinidat_host.update_fields(
                security_method='CHAP',
                security_chap_inbound_username=chap_username,
                security_chap_inbound_secret=chap_password)
        mapping = self._get_or_create_mapping(infinidat_host, infinidat_volume)
        lun = mapping.get_lun()
        netspace_names = self.configuration.infinidat_iscsi_netspaces
        target_portals = []
        target_iqns = []
        target_luns = []
        for netspace_name in netspace_names:
            netspace = self._get_iscsi_network_space(netspace_name)
            target_portals.append(self._get_iscsi_portal(netspace))
            target_iqns.append(netspace.get_properties().iscsi_iqn)
            target_luns.append(lun)

        result_data = dict(target_discovered=True,
                           target_portal=target_portals[0],
                           target_iqn=target_iqns[0],
                           target_lun=target_luns[0],
                           target_portals=target_portals,
                           target_iqns=target_iqns,
                           target_luns=target_luns)
        if self.configuration.use_chap_auth:
            result_data.update(
                dict(auth_method='CHAP',
                     auth_username=chap_username,
                     auth_password=chap_password))
        return dict(driver_volume_type='iscsi', data=result_data)
    def _setup_iscsi_chap_authentication(self, targets, initiator):
        iscsi_chap_enabled = self.configuration.datacore_iscsi_chap_enabled

        self._check_iscsi_chap_configuration(iscsi_chap_enabled, targets)

        server_group = self._get_our_server_group()
        update_access_token = False
        access_token = None
        chap_secret = None
        if iscsi_chap_enabled:
            authentication = 'CHAP'
            chap_secret = self._password_storage.get_password(
                server_group.Id, initiator.PortName)
            update_access_token = False
            if not chap_secret:
                chap_secret = volume_utils.generate_password(length=15)
                self._password_storage.set_password(server_group.Id,
                                                    initiator.PortName,
                                                    chap_secret)
                update_access_token = True
            access_token = self._api.build_access_token(
                initiator.PortName, None, None, False, initiator.PortName,
                chap_secret)
        else:
            authentication = 'None'
            if self._password_storage:
                self._password_storage.delete_password(server_group.Id,
                                                       initiator.PortName)
        changed_targets = {}
        try:
            for target in targets:
                if iscsi_chap_enabled:
                    target_iscsi_nodes = getattr(target.iSCSINodes, 'Node', [])
                    iscsi_node = datacore_utils.get_first_or_default(
                        lambda node: node.Name == initiator.PortName,
                        target_iscsi_nodes, None)
                    if (not iscsi_node
                            or not iscsi_node.AccessToken.TargetUsername
                            or update_access_token):
                        self._api.set_access_token(target.Id, access_token)
                properties = target.ServerPortProperties
                if properties.Authentication != authentication:
                    changed_targets[target] = properties.Authentication
                    properties.Authentication = authentication
                    self._api.set_server_port_properties(target.Id, properties)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(
                    "Configuring of iSCSI CHAP authentication for "
                    "initiator %(initiator)s failed.",
                    {'initiator': initiator.PortName})
                try:
                    for target in changed_targets:
                        properties = target.ServerPortProperties
                        properties.Authentication = changed_targets[target]
                        self._api.set_server_port_properties(
                            target.Id, properties)
                except datacore_exception.DataCoreException as e:
                    LOG.warning(
                        "An error occurred on a cleanup after  failed "
                        "configuration of iSCSI CHAP authentication "
                        "on initiator %(initiator)s: %(error)s.", {
                            'initiator': initiator.PortName,
                            'error': e
                        })
        if iscsi_chap_enabled:
            return initiator.PortName, chap_secret
Exemple #12
0
    def _do_export(self, common, volume, connector):
        """Gets the associated account, generates CHAP info and updates."""
        model_update = {}

        if not common._client_conf['hpe3par_iscsi_chap_enabled']:
            model_update['provider_auth'] = None
            return model_update

        # CHAP username will be the hostname
        chap_username = connector['host']

        chap_password = None
        try:
            # Get all active VLUNs for the host
            vluns = common.client.getHostVLUNs(chap_username)

            # Host has active VLUNs... is CHAP enabled on host?
            host_info = common.client.getHost(chap_username)

            if not host_info['initiatorChapEnabled']:
                LOG.warning("Host has no CHAP key, but CHAP is enabled.")

        except hpeexceptions.HTTPNotFound:
            chap_password = volume_utils.generate_password(16)
            LOG.warning("No host or VLUNs exist. Generating new " "CHAP key.")
        else:
            # Get a list of all iSCSI VLUNs and see if there is already a CHAP
            # key assigned to one of them.  Use that CHAP key if present,
            # otherwise create a new one.  Skip any VLUNs that are missing
            # CHAP credentials in metadata.
            chap_exists = False
            active_vluns = 0

            for vlun in vluns:
                if not vlun['active']:
                    continue

                active_vluns += 1

                # iSCSI connections start with 'iqn'.
                if ('remoteName' in vlun
                        and re.match('iqn.*', vlun['remoteName'])):
                    try:
                        chap_password = common.client.getVolumeMetaData(
                            vlun['volumeName'], CHAP_PASS_KEY)['value']
                        chap_exists = True
                        break
                    except hpeexceptions.HTTPNotFound:
                        LOG.debug(
                            "The VLUN %s is missing CHAP credentials "
                            "but CHAP is enabled. Skipping.",
                            vlun['remoteName'])
                else:
                    LOG.warning("Non-iSCSI VLUN detected.")

            if not chap_exists:
                chap_password = volume_utils.generate_password(16)
                LOG.warning("No VLUN contained CHAP credentials. "
                            "Generating new CHAP key.")

        # Add CHAP credentials to the volume metadata
        vol_name = common._get_3par_vol_name(volume)
        common.client.setVolumeMetaData(vol_name, CHAP_USER_KEY, chap_username)
        common.client.setVolumeMetaData(vol_name, CHAP_PASS_KEY, chap_password)

        model_update['provider_auth'] = ('CHAP %s %s' %
                                         (chap_username, chap_password))

        return model_update