static int _parse_resv_tres(char *val, resv_desc_msg_t *resv_msg_ptr, int *free_tres_license, int *free_tres_bb, int *free_tres_corecnt, int *free_tres_nodecnt) { int i, ret, len; char *tres_bb = NULL, *tres_license = NULL, *tres_corecnt = NULL, *tres_nodecnt = NULL, *token, *type = NULL, *saveptr1 = NULL, *value_str = NULL, *name = NULL, *compound = NULL, *tmp = NULL; bool discard, first; *free_tres_license = 0; *free_tres_bb = 0; *free_tres_corecnt = 0; *free_tres_nodecnt = 0; token = strtok_r(val, ",", &saveptr1); while (token) { compound = strtok_r(token, "=", &value_str); if (!value_str || !*value_str) { error("TRES component '%s' has an invalid value '%s'", type, token); goto error; } if (strchr(compound, '/')) { tmp = xstrdup(compound); type = strtok_r(tmp, "/", &name); } else type = compound; if (_is_configured_tres(compound) < 0) goto error; if (!strcasecmp(type, "license")) { if (tres_license && tres_license[0] != '\0') xstrcatchar(tres_license, ','); xstrfmtcat(tres_license, "%s:%s", name, value_str); token = strtok_r(NULL, ",", &saveptr1); if (tmp) xfree(tmp); } else if (strcasecmp(type, "bb") == 0) { if (tres_bb && tres_bb[0] != '\0') xstrcatchar(tres_bb, ','); xstrfmtcat(tres_bb, "%s:%s", name, value_str); token = strtok_r(NULL, ",", &saveptr1); if (tmp) xfree(tmp); } else if (strcasecmp(type, "cpu") == 0) { first = true; discard = false; do { len = strlen(value_str); for (i = 0; i < len; i++) { if (!isdigit(value_str[i])) { if (first) { error("TRES value '%s' " "is invalid", value_str); goto error; } else discard = true; break; } } first = false; if (!discard) { if (tres_corecnt && tres_corecnt[0] != '\0') xstrcatchar(tres_corecnt, ','); xstrcat(tres_corecnt, value_str); token = strtok_r(NULL, ",", &saveptr1); value_str = token; } } while (!discard && token); } else if (strcasecmp(type, "node") == 0) { if (tres_nodecnt && tres_nodecnt[0] != '\0') xstrcatchar(tres_nodecnt, ','); xstrcat(tres_nodecnt, value_str); token = strtok_r(NULL, ",", &saveptr1); } else { error("TRES type '%s' not supported with reservations", compound); goto error; } } if (tres_corecnt && tres_corecnt[0] != '\0') { ret = _parse_resv_core_cnt(resv_msg_ptr, tres_corecnt, true); xfree(tres_corecnt); if (ret != SLURM_SUCCESS) goto error; *free_tres_corecnt = 1; } if (tres_nodecnt && tres_nodecnt[0] != '\0') { ret = _parse_resv_node_cnt(resv_msg_ptr, tres_nodecnt, true); xfree(tres_nodecnt); if (ret != SLURM_SUCCESS) goto error; *free_tres_nodecnt = 1; } if (tres_license && tres_license[0] != '\0') { resv_msg_ptr->licenses = tres_license; *free_tres_license = 1; } if (tres_bb && tres_bb[0] != '\0') { resv_msg_ptr->burst_buffer = tres_bb; *free_tres_bb = 1; } return SLURM_SUCCESS; error: xfree(tres_nodecnt); xfree(tres_corecnt); exit_code = 1; return SLURM_ERROR; }
/* * scontrol_parse_res_options parse options for creating or updating a reservation * IN argc - count of arguments * IN argv - list of arguments * IN msg - a string to append to any error message * OUT resv_msg_ptr - struct holding reservation parameters * OUT free_user_str - bool indicating that resv_msg_ptr->users should be freed * OUT free_acct_str - bool indicating that resv_msg_ptr->accounts should be * freed * RET 0 on success, -1 on err and prints message */ extern int scontrol_parse_res_options(int argc, char *argv[], const char *msg, resv_desc_msg_t *resv_msg_ptr, int *free_user_str, int *free_acct_str, int *free_tres_license, int *free_tres_bb, int *free_tres_corecnt, int *free_tres_nodecnt) { int i; int duration = -3; /* -1 == INFINITE, -2 == error, -3 == not set */ *free_user_str = 0; *free_acct_str = 0; *free_tres_license = 0; *free_tres_bb = 0; *free_tres_corecnt = 0; *free_tres_nodecnt = 0; for (i=0; i<argc; i++) { char *tag = argv[i]; int taglen = 0; char plus_minus = '\0'; char *val = strchr(argv[i], '='); taglen = val - argv[i]; if (!val && strncasecmp(argv[i], "res", 3) == 0) { continue; } else if (!val || taglen == 0) { exit_code = 1; error("Unknown parameter %s. %s", argv[i], msg); return SLURM_ERROR; } if (val[-1] == '+' || val[-1] == '-') { plus_minus = val[-1]; taglen--; } val++; if (strncasecmp(tag, "ReservationName", MAX(taglen, 1)) == 0) { resv_msg_ptr->name = val; } else if (strncasecmp(tag, "Accounts", MAX(taglen, 1)) == 0) { if (plus_minus) { resv_msg_ptr->accounts = _process_plus_minus(plus_minus, val); *free_acct_str = 1; } else { resv_msg_ptr->accounts = val; } } else if (strncasecmp(tag, "BurstBuffer", MAX(taglen, 2)) == 0) { resv_msg_ptr->burst_buffer = val; } else if (strncasecmp(tag, "StartTime", MAX(taglen, 1)) == 0) { time_t t = parse_time(val, 0); if (errno == ESLURM_INVALID_TIME_VALUE) { exit_code = 1; error("Invalid start time %s. %s", argv[i], msg); return SLURM_ERROR; } resv_msg_ptr->start_time = t; } else if (strncasecmp(tag, "EndTime", MAX(taglen, 1)) == 0) { time_t t = parse_time(val, 0); if (errno == ESLURM_INVALID_TIME_VALUE) { exit_code = 1; error("Invalid end time %s. %s", argv[i],msg); return SLURM_ERROR; } resv_msg_ptr->end_time = t; } else if (strncasecmp(tag, "Duration", MAX(taglen, 1)) == 0) { /* -1 == INFINITE, -2 == error, -3 == not set */ duration = time_str2mins(val); if (duration < 0 && duration != INFINITE) { exit_code = 1; error("Invalid duration %s. %s", argv[i],msg); return SLURM_ERROR; } resv_msg_ptr->duration = (uint32_t)duration; } else if (strncasecmp(tag, "Flags", MAX(taglen, 2)) == 0) { uint32_t f; if (plus_minus) { char *tmp = _process_plus_minus(plus_minus, val); f = parse_resv_flags(tmp, msg); xfree(tmp); } else { f = parse_resv_flags(val, msg); } if (f == 0xffffffff) { return SLURM_ERROR; } else { resv_msg_ptr->flags = f; } } else if (strncasecmp(tag, "NodeCnt", MAX(taglen,5)) == 0 || strncasecmp(tag, "NodeCount", MAX(taglen,5)) == 0) { if (_parse_resv_node_cnt(resv_msg_ptr, val, false) == SLURM_ERROR) return SLURM_ERROR; } else if (strncasecmp(tag, "CoreCnt", MAX(taglen,5)) == 0 || strncasecmp(tag, "CoreCount", MAX(taglen,5)) == 0 || strncasecmp(tag, "CPUCnt", MAX(taglen,5)) == 0 || strncasecmp(tag, "CPUCount", MAX(taglen,5)) == 0) { if (_parse_resv_core_cnt(resv_msg_ptr, val, false) == SLURM_ERROR) return SLURM_ERROR; } else if (strncasecmp(tag, "Nodes", MAX(taglen, 5)) == 0) { resv_msg_ptr->node_list = val; } else if (strncasecmp(tag, "Features", MAX(taglen, 2)) == 0) { resv_msg_ptr->features = val; } else if (strncasecmp(tag, "Licenses", MAX(taglen, 2)) == 0) { resv_msg_ptr->licenses = val; } else if (strncasecmp(tag, "PartitionName", MAX(taglen, 1)) == 0) { resv_msg_ptr->partition = val; } else if (strncasecmp(tag, "TRES", MAX(taglen, 1)) == 0) { if (_parse_resv_tres(val, resv_msg_ptr, free_tres_license, free_tres_bb, free_tres_corecnt, free_tres_nodecnt) == SLURM_ERROR) return SLURM_ERROR; } else if (strncasecmp(tag, "Users", MAX(taglen, 1)) == 0) { if (plus_minus) { resv_msg_ptr->users = _process_plus_minus(plus_minus, val); *free_user_str = 1; } else { resv_msg_ptr->users = val; } } else if (strncasecmp(tag, "Watts", MAX(taglen, 1)) == 0) { if (parse_uint32(val, &(resv_msg_ptr->resv_watts))) { error("Invalid Watts value: %s", val); return SLURM_ERROR; } } else if (strncasecmp(tag, "res", 3) == 0) { continue; } else { exit_code = 1; error("Unknown parameter %s. %s", argv[i], msg); return SLURM_ERROR; } } return SLURM_SUCCESS; }
/* don't free this char */ static const char *_set_resv_msg(resv_desc_msg_t *resv_msg, const char *new_text, int column) { char *type = "", *temp_str; char *tmp_text, *last = NULL, *tok; int block_inx, temp_int = 0; uint32_t f; /* need to clear global_edit_error here (just in case) */ global_edit_error = 0; if (global_edit_error_msg) g_free(global_edit_error_msg); if (!resv_msg) return NULL; switch (column) { case SORTID_ACCOUNTS: resv_msg->accounts = xstrdup(new_text); type = "accounts"; break; case SORTID_ACTION: xfree(got_edit_signal); if (!xstrcasecmp(new_text, "None")) got_edit_signal = NULL; else got_edit_signal = xstrdup(new_text); break; case SORTID_BURST_BUFFER: resv_msg->burst_buffer = xstrdup(new_text); type = "burst_buffer"; break; case SORTID_CORE_CNT: if (cluster_flags & CLUSTER_FLAG_BG) type = "Cnode Count"; else type = "Core Count"; if (_parse_resv_core_cnt(resv_msg, new_text) == SLURM_ERROR) { global_edit_error_msg = g_strdup_printf( "Can't use %s when system " "is not running cons_res select plugin", type); goto return_error; } break; case SORTID_DURATION: temp_int = time_str2mins((char *)new_text); if (temp_int <= 0) goto return_error; resv_msg->duration = temp_int; type = "duration"; break; case SORTID_TIME_END: resv_msg->end_time = parse_time((char *)new_text, 0); type = "end time"; break; case SORTID_FEATURES: resv_msg->features = xstrdup(new_text); type = "features"; break; case SORTID_FLAGS: f = parse_resv_flags(new_text, __func__); type = "flags"; if (f == (uint32_t)NO_VAL) goto return_error; resv_msg->flags = f; break; case SORTID_LICENSES: resv_msg->licenses = xstrdup(new_text); type = "licenses"; break; case SORTID_NAME: resv_msg->name = xstrdup(new_text); type = "name"; break; case SORTID_NODE_CNT: if (cluster_flags & CLUSTER_FLAG_BG) type = "Midplane Count"; else type = "Node Count"; block_inx = 0; tmp_text = xstrdup(new_text); tok = strtok_r(tmp_text, ",", &last); while (tok) { temp_int = strtol(tok, &temp_str, 10); if ((temp_str[0] == 'k') || (temp_str[0] == 'k')) temp_int *= 1024; if ((temp_str[0] == 'm') || (temp_str[0] == 'm')) temp_int *= (1024 * 1024); xrealloc(resv_msg->node_cnt, (sizeof(uint32_t) * (block_inx + 2))); resv_msg->node_cnt[block_inx++] = temp_int; if (temp_int <= 0) { xfree(tmp_text); xfree(resv_msg->node_cnt); goto return_error; } tok = strtok_r(NULL, ",", &last); } xfree(tmp_text); break; case SORTID_NODELIST: resv_msg->node_list = xstrdup(new_text); if (cluster_flags & CLUSTER_FLAG_BG) type = "Midplane List"; else type = "Node List"; break; case SORTID_PARTITION: resv_msg->partition = xstrdup(new_text); type = "partition"; break; case SORTID_TIME_START: resv_msg->start_time = parse_time((char *)new_text, 0); type = "start time"; break; case SORTID_USERS: resv_msg->users = xstrdup(new_text); type = "users"; break; case SORTID_WATTS: resv_msg->resv_watts = _parse_watts((char *) new_text); type = "watts"; break; default: type = "unknown"; break; } if (xstrcmp(type, "unknown")) global_send_update_msg = 1; return type; return_error: global_edit_error = 1; return type; }