/* * 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 = ""; char *err_msg = NULL; int free_tres_license = 0; int free_tres_bb = 0; int free_tres_corecnt = 0; int free_tres_nodecnt = 0; int temp_int = 0; uint64_t f; /* need to clear global_edit_error here (just in case) */ global_edit_error = 0; 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: type = "Core Count"; if (state_control_corecnt_supported() != SLURM_SUCCESS) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup("CoreCnt or CPUCnt is only supported when SelectType includes select/cons_res or SelectTypeParameters includes OTHER_CONS_RES on a Cray."); goto return_error; } if (state_control_parse_resv_corecnt(resv_msg, (char *)new_text, &free_tres_corecnt, false, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); 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 == INFINITE64) 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: type = "Node Count"; if (parse_resv_nodecnt(resv_msg, (char *)new_text, &free_tres_nodecnt, false, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } break; case SORTID_NODELIST: resv_msg->node_list = xstrdup(new_text); 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_TRES: if (state_control_parse_resv_tres((char *)new_text, resv_msg, &free_tres_license, &free_tres_bb, &free_tres_corecnt, &free_tres_nodecnt, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } break; case SORTID_WATTS: if (state_control_parse_resv_watts((char *) new_text, resv_msg, &err_msg) == SLURM_ERROR) { if (global_edit_error_msg) g_free(global_edit_error_msg); global_edit_error_msg = g_strdup(err_msg); xfree(err_msg); goto return_error; } 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; }
/* 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 (!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 (!strcasecmp(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_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: 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); 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 (strcmp(type, "unknown")) global_send_update_msg = 1; return type; return_error: global_edit_error = 1; return type; }
/* * 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 i; int duration = -3; /* -1 == INFINITE, -2 == error, -3 == not set */ *free_user_str = 0; *free_acct_str = 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 -1; } 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 -1; } 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 -1; } 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 -1; } 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 -1; } else { resv_msg_ptr->flags = f; } } else if (strncasecmp(tag, "NodeCnt", MAX(taglen,5)) == 0 || strncasecmp(tag, "NodeCount", MAX(taglen,5)) == 0) { char *endptr = NULL, *node_cnt, *tok, *ptrptr = NULL; int node_inx = 0; node_cnt = xstrdup(val); tok = strtok_r(node_cnt, ",", &ptrptr); while (tok) { xrealloc(resv_msg_ptr->node_cnt, sizeof(uint32_t) * (node_inx + 2)); resv_msg_ptr->node_cnt[node_inx] = strtol(tok, &endptr, 10); if ((endptr != NULL) && ((endptr[0] == 'k') || (endptr[0] == 'K'))) { resv_msg_ptr->node_cnt[node_inx] *= 1024; } else if ((endptr != NULL) && ((endptr[0] == 'm') || (endptr[0] == 'M'))) { resv_msg_ptr->node_cnt[node_inx] *= 1024 * 1024; } else if ((endptr == NULL) || (endptr[0] != '\0') || (tok[0] == '\0')) { exit_code = 1; error("Invalid node count %s. %s", argv[i], msg); xfree(node_cnt); return -1; } node_inx++; tok = strtok_r(NULL, ",", &ptrptr); } xfree(node_cnt); } 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) { char *endptr = NULL, *core_cnt, *tok, *ptrptr = NULL; char *type; int node_inx = 0; type = slurm_get_select_type(); if (strcasestr(type, "cray")) { int param; param = slurm_get_select_type_param(); if (! (param & CR_OTHER_CONS_RES)) { error("CoreCnt or CPUCnt is only " "suported when " "SelectTypeParameters " "includes OTHER_CONS_RES"); xfree(type); return -1; } } else { if (strcasestr(type, "cons_res") == NULL) { error("CoreCnt or CPUCnt is only " "suported when " "SelectType includes " "select/cons_res"); xfree(type); return -1; } } xfree(type); core_cnt = xstrdup(val); tok = strtok_r(core_cnt, ",", &ptrptr); while (tok) { xrealloc(resv_msg_ptr->core_cnt, sizeof(uint32_t) * (node_inx + 2)); resv_msg_ptr->core_cnt[node_inx] = strtol(tok, &endptr, 10); if ((endptr == NULL) || (endptr[0] != '\0') || (tok[0] == '\0')) { exit_code = 1; error("Invalid core count %s. %s", argv[i], msg); xfree(core_cnt); return -1; } node_inx++; tok = strtok_r(NULL, ",", &ptrptr); } xfree(core_cnt); } 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, "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 -1; } } else if (strncasecmp(tag, "res", 3) == 0) { continue; } else { exit_code = 1; error("Unknown parameter %s. %s", argv[i], msg); return -1; } } return 0; }