/** * 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; }
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; }