/**
 * Validate RSL attributes
 *
 * Checks that all of the RSL attributes in the request's RSL match
 * a validation record. If an RSL has an enumerated list of values,
 * then the value of the RSL is compared against that list.
 *
 * @param request
 *        The job request containing the RSL to validate.
 * @param when
 *        Which RSL validation time scope we will use to decide
 *        whether to use the default values or not.
 */
static
int
globus_l_gram_job_manager_check_rsl_attributes(
    globus_gram_jobmanager_request_t *  request,
    globus_rsl_t *                      rsl,
    globus_gram_job_manager_validation_when_t
                                        when)
{
    globus_list_t *                     operands;
    globus_list_t *                     node;
    globus_rsl_t *                      relation;
    char *                              attribute;
    char *                              value_str;
    globus_rvf_record_t *               record;
    globus_rsl_value_t *                value;
    int                                 rc = GLOBUS_SUCCESS;
    static const char *                 operation_types[] =
    {
        "??",
        "=",
        "!=",
        ">",
        ">=",
        "<",
        "<=",
        "??",
        "&",
        "|",
        "+"
    };

    operands = globus_rsl_boolean_get_operand_list(rsl);

    /* Check to make sure that every attribute is recognized by this
     * job manager.
     */
    while(!globus_list_empty(operands))
    {
        relation = globus_list_first(operands);
        operands = globus_list_rest(operands);

        if (!globus_rsl_is_relation(relation))
        {
            int operator = globus_rsl_boolean_get_operator(relation);
            if (operator > 10 || operator < 0)
            {
                operator = 0;
            }

            globus_gram_job_manager_request_log(
                    request,
                    GLOBUS_GRAM_JOB_MANAGER_LOG_ERROR,
                    "event=gram.validate_rsl.end "
                    "level=ERROR "
                    "msg=\"Required RSL relation, got boolean\" "
                    "operator=%s "
                    "status=%d "
                    "\n",
                    operation_types[operator],
                    -GLOBUS_GRAM_PROTOCOL_ERROR_BAD_RSL);
            if (request->gt3_failure_message == NULL)
            {
                request->gt3_failure_message = globus_common_create_string(
                        "Required RSL relation, got boolean %s",
                        operation_types[operator]);
            }
        }
        else if (!globus_rsl_is_relation_eq(relation))
        {
            int operator = globus_rsl_relation_get_operator(relation);

            if (operator > 10 || operator < 0)
            {
                operator = 0;
            }

            globus_gram_job_manager_request_log(
                    request,
                    GLOBUS_GRAM_JOB_MANAGER_LOG_ERROR,
                    "event=gram.validate_rsl.end "
                    "level=ERROR "
                    "msg=\"Unsupported RSL operation\" "
                    "attribute=%s "
                    "operator=%s "
                    "status=%d "
                    "\n",
                    globus_rsl_relation_get_attribute(relation),
                    operation_types[operator],
                    -GLOBUS_GRAM_PROTOCOL_ERROR_BAD_RSL);

            if (request->gt3_failure_message == NULL)
            {
                request->gt3_failure_message = globus_common_create_string(
                        "the job manager does not support the RSL operator "
                        "\"%s\" for the %s attribute",
                        operation_types[operator],
                        globus_rsl_relation_get_attribute(relation));
            }
            return GLOBUS_GRAM_PROTOCOL_ERROR_BAD_RSL;
        }
        attribute = globus_rsl_relation_get_attribute(relation);

        node = globus_list_search_pred(
                request->manager->validation_records,
                globus_l_gram_job_manager_attribute_match,
                attribute);

        if(!node)
        {
            globus_gram_job_manager_request_log(
                    request,
                    GLOBUS_GRAM_JOB_MANAGER_LOG_ERROR,
                    "event=gram.validate_rsl.end "
                    "level=ERROR "
                    "msg=\"Unsupported RSL attribute\" "
                    "attribute=%s "
                    "status=%d "
                    "\n",
                    globus_rsl_relation_get_attribute(relation),
                    -GLOBUS_GRAM_PROTOCOL_ERROR_BAD_RSL);

            if (request->gt3_failure_message == NULL)
            {
                request->gt3_failure_message = globus_common_create_string(
                        "the RSL attribute \"%s\" is not supported by the LRM adapter",
                        globus_rsl_relation_get_attribute(relation));
            }
            return GLOBUS_GRAM_PROTOCOL_ERROR_PARAMETER_NOT_SUPPORTED;
        }

        record = globus_list_first(node);

        /* Check valid_when */
        if((record->valid_when & when) == 0)
        {
            const char * whenstr = "unknown operation";

            switch(when)
            {
              case GLOBUS_GRAM_VALIDATE_JOB_SUBMIT:
                whenstr = "submit";
                rc = GLOBUS_GRAM_PROTOCOL_ERROR_INVALID_SUBMIT_ATTRIBUTE;
                break;
              case GLOBUS_GRAM_VALIDATE_JOB_MANAGER_RESTART:
                whenstr = "restart";
                rc = GLOBUS_GRAM_PROTOCOL_ERROR_INVALID_RESTART_ATTRIBUTE;
                break;
              case GLOBUS_GRAM_VALIDATE_STDIO_UPDATE:
                whenstr = "stdio_update";
                rc = GLOBUS_GRAM_PROTOCOL_ERROR_INVALID_STDIO_UPDATE_ATTRIBUTE;
                break;
            }

            globus_gram_job_manager_request_log(
                    request,
                    GLOBUS_GRAM_JOB_MANAGER_LOG_ERROR,
                    "event=gram.validate_rsl.end "
                    "level=ERROR "
                    "msg=\"Invalid RSL attribute for operation\" "
                    "attribute=%s "
                    "operation=%s "
                    "status=%d "
                    "\n",
                    globus_rsl_relation_get_attribute(relation),
                    whenstr,
                    -rc);
            if (request->gt3_failure_message == NULL)
            {
                request->gt3_failure_message = globus_common_create_string(
                        "Invalid RSL attribute \"%s\" for %s",
                        globus_rsl_relation_get_attribute(relation),
                        whenstr);
            }
            return rc;
        }
        /* Check enumerated values if applicable */
        if(record->enumerated_values)
        {
            value = globus_rsl_relation_get_single_value(relation);

            if(!value)
            {
                return
                    globus_l_gram_job_manager_validation_rsl_error(attribute);
            }
            value_str = globus_rsl_value_literal_get_string(value);
            if(!value_str)
            {
                return globus_l_gram_job_manager_validation_rsl_error(
                        attribute);
            }
            if(strstr(record->enumerated_values, value_str) == GLOBUS_NULL)
            {
                rc = globus_l_gram_job_manager_validation_value_error(
                            request,
                            attribute,
                            value_str,
                            record->enumerated_values);

                globus_gram_job_manager_request_log(
                        request,
                        GLOBUS_GRAM_JOB_MANAGER_LOG_ERROR,
                        "event=gram.validate_rsl.end "
                        "level=ERROR "
                        "msg=\"RSL attribute value not in enumeration\" "
                        "attribute=%s "
                        "value=%s "
                        "enumeration=\"%s\" "
                        "status=%d "
                        "\n",
                        record->attribute,
                        value_str,
                        record->enumerated_values,
                        -rc);

                return rc;
            }
        }
    }

    return GLOBUS_SUCCESS;
}
Beispiel #2
0
static bool
value_to_expr(globus_rsl_value_t * value, classad::ExprTree*& expr)
{
    if (globus_rsl_value_is_literal(value))
    {
        char * literal = globus_rsl_value_literal_get_string(value);
        if (!literal) { return false; }
        classad::Value val;
        try
        {
            val.SetIntegerValue(boost::lexical_cast<long long>(literal));
        }
        catch (const boost::bad_lexical_cast &)
        {
            try
            {
                val.SetRealValue(boost::lexical_cast<double>(literal));
            }
            catch (const boost::bad_lexical_cast &)
            {
                std::string lower = literal;
                boost::algorithm::to_lower(lower);
                if (lower == "true") { val.SetBooleanValue(true); }
                else if (lower == "false") { val.SetBooleanValue(false); }
                else { val.SetStringValue(literal); }
            }
        }
        expr = classad::Literal::MakeLiteral(val);
        if (!expr) { return false; }
        return true;
    }
    else if (globus_rsl_value_is_sequence(value))
    {
        globus_list_t * value_list = globus_rsl_value_sequence_get_value_list(value);
        if (!value_list) { return false; }

        classad::ExprList expr_list;
        while (!globus_list_empty(value_list))
        {
            globus_rsl_value_t *list_item = static_cast<globus_rsl_value_t*>(globus_list_first(value_list));
            value_list = globus_list_rest(value_list);
            if (!list_item) { continue; }

            classad::ExprTree *expr_item = NULL;
            if (!value_to_expr(list_item, expr_item) || !expr_item) { continue; }

            expr_list.push_back(expr_item);
        }
        expr = expr_list.Copy();
        return expr ? true : false;
    }
    else if (globus_rsl_value_is_concatenation(value))
    {
        globus_rsl_value_t *left_value = globus_rsl_value_concatenation_get_left(value);
        globus_rsl_value_t *right_value = globus_rsl_value_concatenation_get_right(value);
        if (!left_value || !right_value) { return false; }

        classad::ExprTree *left_expr = NULL, *right_expr = NULL;
        if (!value_to_expr(left_value, left_expr) || !left_expr || !value_to_expr(right_value, right_expr) || !right_expr) { return false; }
        std::vector<classad::ExprTree*> argList; argList.push_back(left_expr); argList.push_back(right_expr);

        expr = classad::FunctionCall::MakeFunctionCall("strcat", argList);
        return expr ? true : false;
    }
    else if (globus_rsl_value_is_variable(value))
    {
        char * char_variable_name = globus_rsl_value_variable_get_name(value);
        char * default_value = globus_rsl_value_variable_get_default(value);
        if (!char_variable_name) { return false; }

        // Canonical forms of Globus RSL strip out all underscores and makes the string
        // lowercase.  As ClassAds are case-preserving (and underscores are significant),
        // we just do the former transform.
        std::string variable_name(char_variable_name);
        boost::algorithm::replace_all(variable_name, "_", "");

        if (default_value)
        {
            // ifThenElse(isUndefined(variable_name), default_value, variable_name)
            std::vector<classad::ExprTree*> ifArgList;

            classad::ExprTree *attr1 = classad::AttributeReference::MakeAttributeReference(NULL, variable_name);
            if (!attr1) { return false; }
            std::vector<classad::ExprTree*> argList; argList.push_back(attr1);
            classad::ExprTree *isUndefined = classad::FunctionCall::MakeFunctionCall("isUndefined", argList);
            ifArgList.push_back(isUndefined);

            classad::Value val; val.SetStringValue(default_value);
            classad::ExprTree *lit = classad::Literal::MakeLiteral(val);
            if (!lit) { return false; }
            ifArgList.push_back(lit);

            classad::ExprTree *attr2 = classad::AttributeReference::MakeAttributeReference(NULL, variable_name);
            if (!attr2) { return false; }
            ifArgList.push_back(attr2);

            expr = classad::FunctionCall::MakeFunctionCall("ifThenElse", ifArgList);
        }
        else
        {
            expr = classad::AttributeReference::MakeAttributeReference(NULL, variable_name);
        }
        return expr ? true : false;
    }
    return false;
}