예제 #1
0
def all_client_luns(client_iqn):
    """
    Coordinate the addition(PUT) and removal(DELETE) of a disk from a client
    :param client_iqn: (str) IQN of the client
    :param disk: (str) rbd image name of the format pool.image
    **RESTRICTED**
    """

    http_mode = 'https' if settings.config.api_secure else 'http'

    local_gw = this_host()
    logger.debug("this host is {}".format(local_gw))
    gateways = [
        key for key in config.config['gateways']
        if isinstance(config.config['gateways'][key], dict)
    ]
    logger.debug("other gateways - {}".format(gateways))
    gateways.remove(local_gw)

    disk = request.form.get('disk')

    lun_list = config.config['clients'][client_iqn]['luns'].keys()

    if request.method == 'PUT':
        lun_list.append(disk)
    else:
        # this is a delete request
        if disk in lun_list:
            lun_list.remove(disk)
        else:
            return jsonify(message="disk not mapped to client"), 400

    chap_obj = CHAP(config.config['clients'][client_iqn]['auth']['chap'])
    chap = "{}/{}".format(chap_obj.user, chap_obj.password)
    image_list = ','.join(lun_list)

    client_usable = valid_client(mode='disk',
                                 client_iqn=client_iqn,
                                 image_list=image_list)
    if client_usable != 'ok':
        logger.error("Bad disk request for client {} : "
                     "{}".format(client_iqn, client_usable))
        return jsonify(message=client_usable), 400

    # committing host is the local LIO node
    api_vars = {
        "committing_host": local_gw,
        "image_list": image_list,
        "chap": chap
    }

    clientlun_api = '{}://127.0.0.1:{}/api/clientlun/{}'.format(
        http_mode, settings.config.api_port, client_iqn)

    api = APIRequest(clientlun_api, data=api_vars)
    api.put()

    if api.response.status_code == 200:

        logger.info("disk mapping update for {} successful".format(client_iqn))

        for gw in gateways:
            clientlun_api = '{}://{}:{}/api/clientlun/{}'.format(
                http_mode, gw, settings.config.api_port, client_iqn)

            logger.debug("Updating disk map for {} on GW {}".format(
                client_iqn, gw))
            api = APIRequest(clientlun_api, data=api_vars)
            api.put()

            if api.response.status_code == 200:
                logger.debug("gateway '{}' updated".format(gw))
                continue
            else:
                logger.error("disk mapping update on {} failed".format(gw))
                return jsonify(message="disk map updated failed on "
                                       "{}".format(gw)), \
                       api.response.status_code

        return jsonify(message="ok"), 200

    else:
        # disk map update failed at the first hurdle!
        logger.error("disk map update failed on the local LIO instance")
        return jsonify(message="failed to update local LIO instance"), \
               api.response.status_code
예제 #2
0
def all_client(client_iqn):
    """
    Handle the client create/delete actions across gateways
    :param client_iqn: (str) IQN of the client to create or delete
    **RESTRICTED**
    Examples:
    curl --insecure --user admin:admin -X PUT https://192.168.122.69:5001/api/all_client/iqn.1994-05.com.redhat:myhost4
    curl --insecure --user admin:admin -X DELETE https://192.168.122.69:5001/api/all_client/iqn.1994-05.com.redhat:myhost4
    """

    method = {"PUT": 'create', "DELETE": 'delete'}

    http_mode = 'https' if settings.config.api_secure else 'http'
    local_gw = this_host()
    logger.debug("this host is {}".format(local_gw))
    gateways = [
        key for key in config.config['gateways']
        if isinstance(config.config['gateways'][key], dict)
    ]
    logger.debug("other gateways - {}".format(gateways))
    gateways.remove(local_gw)

    # committing host is the node responsible for updating the config object
    api_vars = {"committing_host": local_gw}

    # validate the PUT/DELETE request first
    client_usable = valid_client(mode=method[request.method],
                                 client_iqn=client_iqn)
    if client_usable != 'ok':
        return jsonify(message=client_usable), 400

    if request.method == 'PUT':

        client_api = '{}://127.0.0.1:{}/api/client/{}'.format(
            http_mode, settings.config.api_port, client_iqn)

        logger.debug("Processing client CREATE for {}".format(client_iqn))
        api = APIRequest(client_api, data=api_vars)
        api.put()
        if api.response.status_code == 200:
            logger.info("Client {} added to local LIO".format(client_iqn))

            for gw in gateways:
                client_api = '{}://{}:{}/api/client/{}'.format(
                    http_mode, gw, settings.config.api_port, client_iqn)

                logger.debug("sending request to {} to create {}".format(
                    gw, client_iqn))
                api = APIRequest(client_api, data=api_vars)
                api.put()

                if api.response.status_code == 200:
                    logger.info("Client '{}' added to {}".format(
                        client_iqn, gw))
                    continue
                else:
                    # client create failed against the remote LIO instance
                    msg = api.response.json()['message']
                    logger.error("Client create for {} failed on {} "
                                 ": {}".format(client_iqn, gw, msg))

                    return jsonify(message=msg), 500

            # all gateways processed return a success state to the caller
            return jsonify(message='ok'), 200

        else:
            # client create failed against the local LIO instance
            msg = api.response.json()['message']
            logger.error("Client create on local LIO instance failed "
                         "for {} : {}".format(client_iqn, msg))
            return jsonify(message=msg), 500

    else:
        # DELETE client request
        # Process flow: remote gateways > local > delete config object entry
        for gw in gateways:
            client_api = '{}://{}:{}/api/client/{}'.format(
                http_mode, gw, settings.config.api_port, client_iqn)
            logger.info("- removing '{}' from {}".format(client_iqn, gw))
            api = APIRequest(client_api, data=api_vars)
            api.delete()

            if api.response.status_code == 200:
                logger.info("- '{}' removed".format(client_iqn))
                continue
            elif api.response.status_code == 400:
                logger.error("- '{}' is in use on {}".format(client_iqn, gw))
                return jsonify(message="Client in use"), 400
            else:
                msg = api.response.json()['message']
                logger.error("Failed to remove {} from {}".format(
                    client_iqn, gw))
                return jsonify(message="failed to remove client '{}' on "
                               "{}".format(client_iqn, msg)), 500

        # At this point the other gateways have removed the client, so
        # remove from the local LIO instance
        client_api = '{}://127.0.0.1:{}/api/client/{}'.format(
            http_mode, settings.config.api_port, client_iqn)
        api = APIRequest(client_api, data=api_vars)
        api.delete()

        if api.response.status_code == 200:
            logger.info("successfully removed '{}'".format(client_iqn))
            return jsonify(message="ok"), 200

        else:
            return jsonify(message="Unable to delete {} from local LIO "
                                   "instance".format(client_iqn)), \
                   api.response.status_code
예제 #3
0
def all_client_auth(client_iqn):
    """
    Coordinate client authentication changes across each gateway node
    The following parameters are needed to manage client auth
    :param client_iqn: (str) client IQN name
    :param chap: (str) chap string of the form user/password or ''
    **RESTRICTED**
    """

    http_mode = 'https' if settings.config.api_secure else 'http'
    local_gw = this_host()
    logger.debug("this host is {}".format(local_gw))
    gateways = [
        key for key in config.config['gateways']
        if isinstance(config.config['gateways'][key], dict)
    ]
    logger.debug("other gateways - {}".format(gateways))
    gateways.remove(local_gw)

    lun_list = config.config['clients'][client_iqn]['luns'].keys()
    image_list = ','.join(lun_list)
    chap = request.form.get('chap')

    client_usable = valid_client(mode='auth', client_iqn=client_iqn, chap=chap)
    if client_usable != 'ok':
        logger.error("BAD auth request from {}".format(request.remote_addr))
        return jsonify(message=client_usable), 400

    api_vars = {
        "committing_host": local_gw,
        "image_list": image_list,
        "chap": chap
    }

    clientauth_api = '{}://127.0.0.1:{}/api/clientauth/{}'.format(
        http_mode, settings.config.api_port, client_iqn)
    logger.debug("Issuing client update to local gw for {}".format(client_iqn))

    api = APIRequest(clientauth_api, data=api_vars)
    api.put()

    if api.response.status_code == 200:
        logger.debug("Client update succeeded on local LIO")

        for gw in gateways:
            clientauth_api = '{}://{}:{}/api/clientauth/{}'.format(
                http_mode, gw, settings.config.api_port, client_iqn)
            logger.debug("updating client {} on {}".format(client_iqn, gw))
            api = APIRequest(clientauth_api, data=api_vars)
            api.put()
            if api.response.status_code == 200:
                logger.info("client update successful on {}".format(gw))
                continue
            else:
                return jsonify(message="client update failed on "
                                       "{}".format(gw)), \
                       api.response.status_code

        logger.info("All gateways updated")
        return jsonify(message="ok"), 200

    else:
        # the local update failed, so abort further updates
        return jsonify(message="Client updated failed on local "
                       "LIO instance"), api.response.status_code