/* * 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; }
/* * scontrol_update_job - update the slurm job configuration per the supplied * arguments * IN argc - count of arguments * IN argv - list of arguments * RET 0 if no slurm error, errno otherwise. parsing error prints * error message and returns 0 */ extern int scontrol_update_job (int argc, char *argv[]) { bool update_size = false; int i, update_cnt = 0; char *tag, *val; int taglen, vallen; job_desc_msg_t job_msg; slurm_init_job_desc_msg (&job_msg); /* set current user, needed e.g., for AllowGroups checks */ job_msg.user_id = getuid(); for (i=0; i<argc; i++) { tag = argv[i]; val = strchr(argv[i], '='); if (val) { taglen = val - argv[i]; val++; vallen = strlen(val); } else if (strncasecmp(tag, "Nice", MAX(strlen(tag), 2)) == 0){ /* "Nice" is the only tag that might not have an equal sign, so it is handled specially. */ job_msg.nice = NICE_OFFSET + 100; update_cnt++; continue; } else { exit_code = 1; fprintf (stderr, "Invalid input: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return -1; } if (strncasecmp(tag, "JobId", MAX(taglen, 3)) == 0) { job_msg.job_id = (uint32_t) strtol(val, (char **) NULL, 10); } else if (strncasecmp(tag, "Comment", MAX(taglen, 3)) == 0) { job_msg.comment = val; update_cnt++; } else if (strncasecmp(tag, "TimeLimit", MAX(taglen, 5)) == 0) { bool incr, decr; uint32_t job_current_time, time_limit; incr = (val[0] == '+'); decr = (val[0] == '-'); if (incr || decr) val++; time_limit = time_str2mins(val); if ((time_limit < 0) && (time_limit != INFINITE)) { error("Invalid TimeLimit value"); exit_code = 1; return 0; } if (incr || decr) { job_current_time = _get_job_time(job_msg. job_id); if (job_current_time == NO_VAL) { exit_code = 1; return 0; } if (incr) { time_limit += job_current_time; } else if (time_limit > job_current_time) { error("TimeLimit decrement larger than" " current time limit (%u > %u)", time_limit, job_current_time); exit_code = 1; return 0; } else { time_limit = job_current_time - time_limit; } } job_msg.time_limit = time_limit; update_cnt++; } else if (strncasecmp(tag, "TimeMin", MAX(taglen, 5)) == 0) { int time_min = time_str2mins(val); if ((time_min < 0) && (time_min != INFINITE)) { error("Invalid TimeMin value"); exit_code = 1; return 0; } job_msg.time_min = time_min; update_cnt++; } else if (strncasecmp(tag, "Priority", MAX(taglen, 2)) == 0) { job_msg.priority = (uint32_t) strtoll(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "Nice", MAX(taglen, 2)) == 0) { int nice; nice = strtoll(val, (char **) NULL, 10); if (abs(nice) > NICE_OFFSET) { error("Invalid nice value, must be between " "-%d and %d", NICE_OFFSET, NICE_OFFSET); exit_code = 1; return 0; } job_msg.nice = NICE_OFFSET + nice; update_cnt++; } else if (strncasecmp(tag, "NumCPUs", MAX(taglen, 6)) == 0) { int min_cpus, max_cpus=0; if (!get_resource_arg_range(val, "NumCPUs", &min_cpus, &max_cpus, false) || (min_cpus <= 0) || (max_cpus && (max_cpus < min_cpus))) { error("Invalid NumCPUs value: %s", val); exit_code = 1; return 0; } job_msg.min_cpus = min_cpus; if (max_cpus) job_msg.max_cpus = max_cpus; update_cnt++; } /* ReqProcs was removed in SLURM version 2.1 */ else if (strncasecmp(tag, "ReqProcs", MAX(taglen, 8)) == 0) { job_msg.num_tasks = (uint32_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "Requeue", MAX(taglen, 4)) == 0) { job_msg.requeue = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } /* ReqNodes was replaced by NumNodes in SLURM version 2.1 */ else if ((strncasecmp(tag, "ReqNodes", MAX(taglen, 8)) == 0) || (strncasecmp(tag, "NumNodes", MAX(taglen, 8)) == 0)) { int min_nodes, max_nodes, rc; if (strcmp(val, "0") == 0) { job_msg.min_nodes = 0; } else if (strcasecmp(val, "ALL") == 0) { job_msg.min_nodes = INFINITE; } else { min_nodes = (int) job_msg.min_nodes; max_nodes = (int) job_msg.max_nodes; rc = get_resource_arg_range( val, "requested node count", &min_nodes, &max_nodes, false); if (!rc) return rc; job_msg.min_nodes = (uint32_t) min_nodes; job_msg.max_nodes = (uint32_t) max_nodes; } update_size = true; update_cnt++; } else if (strncasecmp(tag, "ReqSockets", MAX(taglen, 4)) == 0) { job_msg.sockets_per_node = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "ReqCores", MAX(taglen, 4)) == 0) { job_msg.cores_per_socket = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "TasksPerNode", MAX(taglen, 2))==0) { job_msg.ntasks_per_node = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "ReqThreads", MAX(taglen, 4)) == 0) { job_msg.threads_per_core = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "MinCPUsNode", MAX(taglen, 4)) == 0) { job_msg.pn_min_cpus = (uint32_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "MinMemoryNode", MAX(taglen, 10)) == 0) { job_msg.pn_min_memory = (uint32_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "MinMemoryCPU", MAX(taglen, 10)) == 0) { job_msg.pn_min_memory = (uint32_t) strtol(val, (char **) NULL, 10); job_msg.pn_min_memory |= MEM_PER_CPU; update_cnt++; } else if (strncasecmp(tag, "MinTmpDiskNode", MAX(taglen, 5)) == 0) { job_msg.pn_min_tmp_disk = (uint32_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "Partition", MAX(taglen, 2)) == 0) { job_msg.partition = val; update_cnt++; } else if (strncasecmp(tag, "QOS", MAX(taglen, 2)) == 0) { job_msg.qos = val; update_cnt++; } else if (strncasecmp(tag, "ReservationName", MAX(taglen, 3)) == 0) { job_msg.reservation = val; update_cnt++; } else if (strncasecmp(tag, "Name", MAX(taglen, 2)) == 0) { job_msg.name = val; update_cnt++; } else if (strncasecmp(tag, "WCKey", MAX(taglen, 1)) == 0) { job_msg.wckey = val; update_cnt++; } else if (strncasecmp(tag, "Switches", MAX(taglen, 5)) == 0) { char *sep_char; job_msg.req_switch = (uint32_t) strtol(val, &sep_char, 10); update_cnt++; if (sep_char && sep_char[0] == '@') { job_msg.wait4switch = time_str2mins(sep_char+1) * 60; } } else if (strncasecmp(tag, "wait-for-switch", MAX(taglen, 5)) == 0) { job_msg.wait4switch = (uint32_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "Shared", MAX(taglen, 2)) == 0) { if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) job_msg.shared = 1; else if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) job_msg.shared = 0; else job_msg.shared = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "Contiguous", MAX(taglen, 3)) == 0) { if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) job_msg.contiguous = 1; else if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) job_msg.contiguous = 0; else job_msg.contiguous = (uint16_t) strtol(val, (char **) NULL, 10); update_cnt++; } else if (strncasecmp(tag, "ExcNodeList", MAX(taglen, 3)) == 0){ job_msg.exc_nodes = val; update_cnt++; } else if (!strncasecmp(tag, "NodeList", MAX(taglen, 8)) || !strncasecmp(tag, "ReqNodeList", MAX(taglen, 8))) { job_msg.req_nodes = val; update_size = true; update_cnt++; } else if (strncasecmp(tag, "Features", MAX(taglen, 1)) == 0) { job_msg.features = val; update_cnt++; } else if (strncasecmp(tag, "Gres", MAX(taglen, 2)) == 0) { if (!strcasecmp(val, "help") || !strcasecmp(val, "list")) { print_gres_help(); } else { job_msg.gres = val; update_cnt++; } } else if (strncasecmp(tag, "Account", MAX(taglen, 1)) == 0) { job_msg.account = val; update_cnt++; } else if (strncasecmp(tag, "Dependency", MAX(taglen, 1)) == 0) { job_msg.dependency = val; update_cnt++; } else if (strncasecmp(tag, "Geometry", MAX(taglen, 2)) == 0) { char* token, *delimiter = ",x", *next_ptr; int j, rc = 0; int dims = slurmdb_setup_cluster_dims(); uint16_t geo[dims]; char* geometry_tmp = xstrdup(val); char* original_ptr = geometry_tmp; token = strtok_r(geometry_tmp, delimiter, &next_ptr); for (j=0; j<dims; j++) { if (token == NULL) { error("insufficient dimensions in " "Geometry"); rc = -1; break; } geo[j] = (uint16_t) atoi(token); if (geo[j] <= 0) { error("invalid --geometry argument"); rc = -1; break; } geometry_tmp = next_ptr; token = strtok_r(geometry_tmp, delimiter, &next_ptr); } if (token != NULL) { error("too many dimensions in Geometry"); rc = -1; } if (original_ptr) xfree(original_ptr); if (rc != 0) exit_code = 1; else { for (j=0; j<dims; j++) job_msg.geometry[j] = geo[j]; update_cnt++; } } else if (strncasecmp(tag, "Rotate", MAX(taglen, 2)) == 0) { uint16_t rotate; if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) rotate = 1; else if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) rotate = 0; else rotate = (uint16_t) strtol(val, (char **) NULL, 10); job_msg.rotate = rotate; update_cnt++; } else if (strncasecmp(tag, "Conn-Type", MAX(taglen, 2)) == 0) { verify_conn_type(val, job_msg.conn_type); if(job_msg.conn_type[0] != (uint16_t)NO_VAL) update_cnt++; } else if (strncasecmp(tag, "Licenses", MAX(taglen, 1)) == 0) { job_msg.licenses = val; update_cnt++; } else if (!strncasecmp(tag, "EligibleTime", MAX(taglen, 2)) || !strncasecmp(tag, "StartTime", MAX(taglen, 2))) { if ((job_msg.begin_time = parse_time(val, 0))) { if (job_msg.begin_time < time(NULL)) job_msg.begin_time = time(NULL); update_cnt++; } } else if (!strncasecmp(tag, "EndTime", MAX(taglen, 2))) { job_msg.end_time = parse_time(val, 0); update_cnt++; } else { exit_code = 1; fprintf (stderr, "Update of this parameter is not " "supported: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return 0; } } if (update_cnt == 0) { exit_code = 1; fprintf (stderr, "No changes specified\n"); return 0; } if (slurm_update_job(&job_msg)) return slurm_get_errno (); if (update_size) _update_job_size(job_msg.job_id); return SLURM_SUCCESS; }
/* * scontrol_update_step - update the slurm step configuration per the supplied * arguments * IN argc - count of arguments * IN argv - list of arguments * RET 0 if no slurm error, errno otherwise. parsing error prints * error message and returns 0 */ extern int scontrol_update_step (int argc, char *argv[]) { int i, update_cnt = 0; char *tag, *val; int taglen; step_update_request_msg_t step_msg; slurm_init_update_step_msg (&step_msg); for (i=0; i<argc; i++) { tag = argv[i]; val = strchr(argv[i], '='); if (val) { taglen = val - argv[i]; val++; } else { exit_code = 1; fprintf (stderr, "Invalid input: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return -1; } if (strncasecmp(tag, "StepId", MAX(taglen, 4)) == 0) { char *end_ptr; step_msg.job_id = (uint32_t) strtol(val, &end_ptr, 10); if (end_ptr[0] == '.') { step_msg.step_id = (uint32_t) strtol(end_ptr+1, (char **) NULL, 10); } else if (end_ptr[0] != '\0') { exit_code = 1; fprintf (stderr, "Invalid StepID parameter: " "%s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return 0; } /* else apply to all steps of this job_id */ } else if (strncasecmp(tag, "TimeLimit", MAX(taglen, 2)) == 0) { bool incr, decr; uint32_t step_current_time, time_limit; incr = (val[0] == '+'); decr = (val[0] == '-'); if (incr || decr) val++; time_limit = time_str2mins(val); if (time_limit == NO_VAL) { error("Invalid TimeLimit value"); exit_code = 1; return 0; } if (incr || decr) { step_current_time = _get_step_time( step_msg.job_id, step_msg.step_id); if (step_current_time == NO_VAL) { exit_code = 1; return 0; } if (incr) { time_limit += step_current_time; } else if (time_limit > step_current_time) { error("TimeLimit decrement larger than" " current time limit (%u > %u)", time_limit, step_current_time); exit_code = 1; return 0; } else { time_limit = step_current_time - time_limit; } } step_msg.time_limit = time_limit; update_cnt++; } else if (strncasecmp(tag, "CompFile", MAX(taglen, 2)) == 0) { if (_parse_comp_file(val, &step_msg)) { exit_code = 1; fprintf(stderr, "Bad completion file (%s) given\n" "Request aborted\n", val); return 0; } update_cnt++; } else { exit_code = 1; fprintf (stderr, "Update of this parameter is not " "supported: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return 0; } } if (update_cnt == 0) { exit_code = 1; fprintf (stderr, "No changes specified\n"); return 0; } if (slurm_update_step(&step_msg)) return slurm_get_errno (); else return 0; }
/* * 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, "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_flags(tmp, msg); xfree(tmp); } else { f = _parse_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; int node_inx = 0; 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, "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, "res", 3) == 0) { continue; } else { exit_code = 1; error("Unknown parameter %s. %s", argv[i], msg); return -1; } } return 0; }
static int _set_rec(int *start, int argc, char *argv[], List name_list, slurmdb_qos_rec_t *qos) { int i, mins; int set = 0; int end = 0; int command_len = 0; int option = 0; for (i=(*start); i<argc; i++) { end = parse_option_end(argv[i]); if(!end) command_len=strlen(argv[i]); else { command_len=end-1; if(argv[i][end] == '=') { option = (int)argv[i][end-1]; end++; } } if (!strncasecmp (argv[i], "Where", MAX(command_len, 5))) { i--; break; } else if(!end && !strncasecmp(argv[i], "set", MAX(command_len, 3))) { continue; } else if(!end || !strncasecmp (argv[i], "Name", MAX(command_len, 1))) { if(name_list) slurm_addto_char_list(name_list, argv[i]+end); } else if (!strncasecmp (argv[i], "Description", MAX(command_len, 1))) { if(!qos->description) qos->description = strip_quotes(argv[i]+end, NULL, 1); set = 1; } else if (!strncasecmp (argv[i], "Flags", MAX(command_len, 2))) { if(!qos) continue; qos->flags = str_2_qos_flags(argv[i]+end, option); if (qos->flags == QOS_FLAG_NOTSET) { char *tmp_char = NULL; qos->flags = INFINITE; qos->flags &= (~QOS_FLAG_NOTSET & ~QOS_FLAG_ADD & ~QOS_FLAG_REMOVE); tmp_char = slurmdb_qos_flags_str(qos->flags); printf(" Unknown QOS flag used in:\n '%s'\n" " Valid QOS flags are\n '%s'\n", argv[i]+end, tmp_char); xfree(tmp_char); exit_code = 1; } else set = 1; } else if (!strncasecmp (argv[i], "GraceTime", MAX(command_len, 3))) { if (!qos) continue; if (get_uint(argv[i]+end, &qos->grace_time, "GraceTime") == SLURM_SUCCESS) { set = 1; } } else if (!strncasecmp (argv[i], "GrpCPUMins", MAX(command_len, 7))) { if(!qos) continue; if (get_uint64(argv[i]+end, &qos->grp_cpu_mins, "GrpCPUMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpCPURunMins", MAX(command_len, 7))) { if(!qos) continue; if (get_uint64(argv[i]+end, &qos->grp_cpu_run_mins, "GrpCPURunMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpCPUs", MAX(command_len, 7))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->grp_cpus, "GrpCPUs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpJobs", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->grp_jobs, "GrpJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpMemory", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->grp_mem, "GrpMemory") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpNodes", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->grp_nodes, "GrpNodes") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpSubmitJobs", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->grp_submit_jobs, "GrpSubmitJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "GrpWall", MAX(command_len, 4))) { if(!qos) continue; mins = time_str2mins(argv[i]+end); if (mins != NO_VAL) { qos->grp_wall = (uint32_t) mins; set = 1; } else { exit_code=1; fprintf(stderr, " Bad GrpWall time format: %s\n", argv[i]); } } else if (!strncasecmp (argv[i], "MaxCPUMinsPerJob", MAX(command_len, 7))) { if(!qos) continue; if (get_uint64(argv[i]+end, &qos->max_cpu_mins_pj, "MaxCPUMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxCPUsPerJob", MAX(command_len, 7))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->max_cpus_pj, "MaxCPUs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxCPUsPerUser", MAX(command_len, 11))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->max_cpus_pu, "MaxCPUsPerUser") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxJobsPerUser", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->max_jobs_pu, "MaxJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxNodesPerJob", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->max_nodes_pj, "MaxNodes") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxNodesPerUser", MAX(command_len, 8))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->max_nodes_pu, "MaxNodesPerUser") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxSubmitJobsPerUser", MAX(command_len, 4))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->max_submit_jobs_pu, "MaxSubmitJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxWallDurationPerJob", MAX(command_len, 4))) { if(!qos) continue; mins = time_str2mins(argv[i]+end); if (mins != NO_VAL) { qos->max_wall_pj = (uint32_t) mins; set = 1; } else { exit_code=1; fprintf(stderr, " Bad MaxWall time format: %s\n", argv[i]); } } else if (!strncasecmp (argv[i], "PreemptMode", MAX(command_len, 8))) { if(!qos) continue; qos->preempt_mode = preempt_mode_num(argv[i]+end); if(qos->preempt_mode == (uint16_t)NO_VAL) { fprintf(stderr, " Bad Preempt Mode given: %s\n", argv[i]); exit_code = 1; } else if (qos->preempt_mode == PREEMPT_MODE_SUSPEND) { printf("PreemptType and PreemptMode " "values incompatible\n"); exit_code = 1; } else set = 1; /* Preempt needs to follow PreemptMode */ } else if (!strncasecmp (argv[i], "Preempt", MAX(command_len, 7))) { if(!qos) continue; if(!qos->preempt_list) qos->preempt_list = list_create(slurm_destroy_char); if(!g_qos_list) g_qos_list = acct_storage_g_get_qos( db_conn, my_uid, NULL); if(slurmdb_addto_qos_char_list(qos->preempt_list, g_qos_list, argv[i]+end, option)) set = 1; else exit_code = 1; } else if (!strncasecmp (argv[i], "Priority", MAX(command_len, 3))) { if(!qos) continue; if (get_uint(argv[i]+end, &qos->priority, "Priority") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "UsageFactor", MAX(command_len, 6))) { if(!qos) continue; if (get_double(argv[i]+end, &qos->usage_factor, "UsageFactor") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "UsageThreshold", MAX(command_len, 6))) { if(!qos) continue; if (get_double(argv[i]+end, &qos->usage_thres, "UsageThreshold") == SLURM_SUCCESS) set = 1; } else { exit_code = 1; printf(" Unknown option: %s\n" " Use keyword 'where' to modify condition\n", argv[i]); } } (*start) = i; return set; }
/* 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_update_job - update the slurm job configuration per the supplied * arguments * IN argc - count of arguments * IN argv - list of arguments * RET 0 if no slurm error, errno otherwise. parsing error prints * error message and returns 0 */ extern int scontrol_update_job(int argc, char **argv) { bool update_size = false; int i, update_cnt = 0, rc = SLURM_SUCCESS, rc2; char *tag, *val; int taglen, vallen; job_desc_msg_t job_msg; job_array_resp_msg_t *resp = NULL; uint32_t job_uid = NO_VAL; slurm_init_job_desc_msg (&job_msg); for (i = 0; i < argc; i++) { char *add_info = NULL; tag = argv[i]; val = strchr(argv[i], '='); if (val) { taglen = val - argv[i]; if ((taglen > 0) && ((val[-1] == '+') || (val[-1] == '-'))) { add_info = val - 1; taglen--; } val++; vallen = strlen(val); } else if (xstrncasecmp(tag, "Nice", MAX(strlen(tag), 2)) == 0){ /* "Nice" is the only tag that might not have an equal sign, so it is handled specially. */ job_msg.nice = NICE_OFFSET + 100; update_cnt++; continue; } else if (!val && argv[i + 1]) { tag = argv[i]; taglen = strlen(tag); val = argv[++i]; vallen = strlen(val); } else { exit_code = 1; fprintf (stderr, "Invalid input: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return -1; } if (xstrncasecmp(tag, "JobId", MAX(taglen, 3)) == 0) { job_msg.job_id_str = val; } else if (xstrncasecmp(tag, "AdminComment", MAX(taglen, 3)) == 0) { if (add_info) { if (add_info[0] == '-') { error("Invalid syntax, AdminComment can not be subtracted from."); exit_code = 1; return 0; } job_msg.admin_comment = add_info; /* * Mark as unset so we know we handled this * correctly as there is a check later to make * sure we know we got a +-. */ add_info = NULL; } else job_msg.admin_comment = val; update_cnt++; } else if (xstrncasecmp(tag, "ArrayTaskThrottle", MAX(taglen, 10)) == 0) { int throttle; throttle = strtoll(val, (char **) NULL, 10); if (throttle < 0) { error("Invalid ArrayTaskThrottle value"); exit_code = 1; return 0; } job_msg.array_inx = val; update_cnt++; } else if (xstrncasecmp(tag, "Comment", MAX(taglen, 3)) == 0) { job_msg.comment = val; update_cnt++; } else if (xstrncasecmp(tag, "Clusters", MAX(taglen, 8)) == 0) { job_msg.clusters = val; update_cnt++; } else if (xstrncasecmp(tag, "ClusterFeatures", MAX(taglen, 8)) == 0) { job_msg.cluster_features = val; update_cnt++; } else if (xstrncasecmp(tag, "DelayBoot", MAX(taglen, 5)) == 0) { int time_sec = time_str2secs(val); if (time_sec == NO_VAL) { error("Invalid DelayBoot value"); exit_code = 1; return 0; } job_msg.delay_boot = time_sec; update_cnt++; } else if (xstrncasecmp(tag, "TimeLimit", MAX(taglen, 5)) == 0) { uint32_t job_current_time, time_limit; if (val && ((val[0] == '+') || (val[0] == '-'))) { if (add_info) { error("Invalid syntax, variations of +=- are not accepted."); exit_code = 1; return 0; } add_info = val; val++; } time_limit = time_str2mins(val); if (time_limit == NO_VAL) { error("Invalid TimeLimit value"); exit_code = 1; return 0; } if (add_info) { if (!job_msg.job_id_str) { error("JobId must precede TimeLimit " "increment or decrement"); exit_code = 1; return 0; } job_current_time = _get_job_time(job_msg. job_id_str); if (job_current_time == NO_VAL) { exit_code = 1; return 0; } if (add_info[0] == '+') { time_limit += job_current_time; } else if (time_limit > job_current_time) { error("TimeLimit decrement larger than" " current time limit (%u > %u)", time_limit, job_current_time); exit_code = 1; return 0; } else { time_limit = job_current_time - time_limit; } /* * Mark as unset so we know we handled this * correctly as there is a check later to make * sure we know we got a +-. */ add_info = NULL; } job_msg.time_limit = time_limit; update_cnt++; } else if (xstrncasecmp(tag, "TimeMin", MAX(taglen, 5)) == 0) { int time_min = time_str2mins(val); if ((time_min < 0) && (time_min != INFINITE)) { error("Invalid TimeMin value"); exit_code = 1; return 0; } job_msg.time_min = time_min; update_cnt++; } else if (xstrncasecmp(tag, "Priority", MAX(taglen, 2)) == 0) { if (parse_uint32(val, &job_msg.priority)) { error ("Invalid Priority value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "Nice", MAX(taglen, 2)) == 0) { long long tmp_nice; tmp_nice = strtoll(val, (char **)NULL, 10); if (llabs(tmp_nice) > (NICE_OFFSET - 3)) { error("Nice value out of range (+/- %u). Value " "ignored", NICE_OFFSET - 3); exit_code = 1; return 0; } job_msg.nice = NICE_OFFSET + tmp_nice; update_cnt++; } else if (!xstrncasecmp(tag, "CPUsPerTask", MAX(taglen, 9))) { if (parse_uint16(val, &job_msg.cpus_per_task)) { error("Invalid CPUsPerTask value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (!xstrncasecmp(tag, "CpusPerTres", MAX(taglen, 9))) { job_msg.cpus_per_tres = val; update_cnt++; } else if (xstrncasecmp(tag, "NumCPUs", MAX(taglen, 6)) == 0) { int min_cpus, max_cpus=0; if (!get_resource_arg_range(val, "NumCPUs", &min_cpus, &max_cpus, false) || (min_cpus <= 0) || (max_cpus && (max_cpus < min_cpus))) { error ("Invalid NumCPUs value: %s", val); exit_code = 1; return 0; } job_msg.min_cpus = min_cpus; if (max_cpus) job_msg.max_cpus = max_cpus; update_cnt++; } /* ReqProcs was removed in Slurm version 2.1 */ else if ((xstrncasecmp(tag, "NumTasks", MAX(taglen, 8)) == 0) || (xstrncasecmp(tag, "ReqProcs", MAX(taglen, 8)) == 0)) { if (parse_uint32(val, &job_msg.num_tasks)) { error ("Invalid NumTasks value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "Requeue", MAX(taglen, 4)) == 0) { if (parse_uint16(val, &job_msg.requeue)) { error ("Invalid Requeue value: %s", val); exit_code = 1; return 0; } update_cnt++; } /* ReqNodes was replaced by NumNodes in Slurm version 2.1 */ else if ((xstrncasecmp(tag, "ReqNodes", MAX(taglen, 8)) == 0) || (xstrncasecmp(tag, "NumNodes", MAX(taglen, 8)) == 0)) { int min_nodes, max_nodes, rc; if (xstrcmp(val, "0") == 0) { job_msg.min_nodes = 0; } else if (xstrcasecmp(val, "ALL") == 0) { job_msg.min_nodes = INFINITE; } else { min_nodes = (int) job_msg.min_nodes; max_nodes = (int) job_msg.max_nodes; rc = get_resource_arg_range( val, "requested node count", &min_nodes, &max_nodes, false); if (!rc) return rc; job_msg.min_nodes = (uint32_t) min_nodes; job_msg.max_nodes = (uint32_t) max_nodes; } update_size = true; update_cnt++; } else if (xstrncasecmp(tag, "ReqSockets", MAX(taglen, 4)) == 0) { if (parse_uint16(val, &job_msg.sockets_per_node)) { error ("Invalid ReqSockets value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "ReqCores", MAX(taglen, 4)) == 0) { if (parse_uint16(val, &job_msg.cores_per_socket)) { error ("Invalid ReqCores value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "TasksPerNode", MAX(taglen, 2))==0) { if (parse_uint16(val, &job_msg.ntasks_per_node)) { error ("Invalid TasksPerNode value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "ReqThreads", MAX(taglen, 4)) == 0) { if (parse_uint16(val, &job_msg.threads_per_core)) { error ("Invalid ReqThreads value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "MinCPUsNode", MAX(taglen, 4)) == 0) { if (parse_uint16(val, &job_msg.pn_min_cpus)) { error ("Invalid MinCPUsNode value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "MinMemoryNode", MAX(taglen, 10)) == 0) { if (parse_uint64(val, &job_msg.pn_min_memory)) { error ("Invalid MinMemoryNode value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "MinMemoryCPU", MAX(taglen, 10)) == 0) { if (parse_uint64(val, &job_msg.pn_min_memory)) { error ("Invalid MinMemoryCPU value: %s", val); exit_code = 1; return 0; } job_msg.pn_min_memory |= MEM_PER_CPU; update_cnt++; } else if (xstrncasecmp(tag, "MinTmpDiskNode", MAX(taglen, 5)) == 0) { if (parse_uint32(val, &job_msg.pn_min_tmp_disk)) { error ("Invalid MinTmpDiskNode value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "Partition", MAX(taglen, 2)) == 0) { job_msg.partition = val; update_cnt++; } else if (xstrncasecmp(tag, "QOS", MAX(taglen, 2)) == 0) { job_msg.qos = val; update_cnt++; } else if (xstrncasecmp(tag, "ReservationName", MAX(taglen, 3)) == 0) { job_msg.reservation = val; update_cnt++; } else if (!xstrncasecmp(tag, "Name", MAX(taglen, 2)) || !xstrncasecmp(tag, "JobName", MAX(taglen, 4))) { job_msg.name = val; update_cnt++; } else if (xstrncasecmp(tag, "WCKey", MAX(taglen, 1)) == 0) { job_msg.wckey = val; update_cnt++; } else if (xstrncasecmp(tag, "StdOut", MAX(taglen, 6)) == 0) { job_msg.std_out = val; update_cnt++; } else if (xstrncasecmp(tag, "Switches", MAX(taglen, 5)) == 0) { char *sep_char; job_msg.req_switch = (uint32_t) strtol(val, &sep_char, 10); update_cnt++; if (sep_char && sep_char[0] == '@') { job_msg.wait4switch = time_str2mins(sep_char+1) * 60; } } else if (xstrncasecmp(tag, "wait-for-switch", MAX(taglen, 5)) == 0) { if (parse_uint32(val, &job_msg.wait4switch)) { error ("Invalid wait-for-switch value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (!xstrncasecmp(tag, "OverSubscribe", MAX(taglen, 2)) || !xstrncasecmp(tag, "Shared", MAX(taglen, 2))) { if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0) job_msg.shared = 1; else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) job_msg.shared = 0; else if (parse_uint16(val, &job_msg.shared)) { error("Invalid OverSubscribe value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "Contiguous", MAX(taglen, 3)) == 0) { if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0) job_msg.contiguous = 1; else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) job_msg.contiguous = 0; else if (parse_uint16(val, &job_msg.contiguous)) { error ("Invalid Contiguous value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (xstrncasecmp(tag, "CoreSpec", MAX(taglen, 4)) == 0) { if (!xstrcmp(val, "-1") || !xstrcmp(val, "*")) job_msg.core_spec = INFINITE16; else if (parse_uint16(val, &job_msg.core_spec)) { error ("Invalid CoreSpec value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (!xstrncasecmp(tag, "MemPerTres", MAX(taglen, 5))) { job_msg.mem_per_tres = val; update_cnt++; } else if (xstrncasecmp(tag, "ThreadSpec", MAX(taglen, 4)) == 0) { if (!xstrcmp(val, "-1") || !xstrcmp(val, "*")) job_msg.core_spec = INFINITE16; else if (parse_uint16(val, &job_msg.core_spec)) { error ("Invalid ThreadSpec value: %s", val); exit_code = 1; return 0; } else job_msg.core_spec |= CORE_SPEC_THREAD; update_cnt++; } else if (!xstrncasecmp(tag, "TresBind", MAX(taglen, 5))) { job_msg.tres_bind = val; update_cnt++; } else if (!xstrncasecmp(tag, "TresFreq", MAX(taglen, 5))) { job_msg.tres_freq = val; update_cnt++; } else if (!xstrncasecmp(tag, "TresPerJob", MAX(taglen, 8))) { job_msg.tres_per_job = val; update_cnt++; } else if (!xstrncasecmp(tag, "TresPerNode", MAX(taglen, 8))) { /* "gres" replaced by "tres_per_node" in v18.08 */ if (job_msg.tres_per_node) xstrfmtcat(job_msg.tres_per_node, ",%s", val); else job_msg.tres_per_node = xstrdup(val); update_cnt++; } else if (!xstrncasecmp(tag, "TresPerSocket", MAX(taglen, 8))) { job_msg.tres_per_socket = val; update_cnt++; } else if (!xstrncasecmp(tag, "TresPerTask", MAX(taglen, 8))) { job_msg.tres_per_task = val; update_cnt++; } else if (xstrncasecmp(tag, "ExcNodeList", MAX(taglen, 3)) == 0){ job_msg.exc_nodes = val; update_cnt++; } else if (!xstrncasecmp(tag, "NodeList", MAX(taglen, 8)) || !xstrncasecmp(tag, "ReqNodeList", MAX(taglen, 8))) { job_msg.req_nodes = val; update_size = true; update_cnt++; } else if (xstrncasecmp(tag, "Features", MAX(taglen, 1)) == 0) { job_msg.features = val; update_cnt++; } else if (xstrncasecmp(tag, "Gres", MAX(taglen, 2)) == 0) { /* "gres" replaced by "tres_per_node" in v18.08 */ if (!xstrcasecmp(val, "help") || !xstrcasecmp(val, "list")) { print_gres_help(); } else if (job_msg.tres_per_node) { xstrfmtcat(job_msg.tres_per_node, ",%s", val); } else { job_msg.tres_per_node = xstrdup(val); update_cnt++; } } else if (xstrncasecmp(tag, "Account", MAX(taglen, 1)) == 0) { job_msg.account = val; update_cnt++; } else if (xstrncasecmp(tag, "BurstBuffer", MAX(taglen, 1)) == 0) { job_msg.burst_buffer = val; update_cnt++; } else if (xstrncasecmp(tag, "Dependency", MAX(taglen, 1)) == 0) { job_msg.dependency = val; update_cnt++; } else if (xstrncasecmp(tag, "Licenses", MAX(taglen, 1)) == 0) { job_msg.licenses = val; update_cnt++; } else if (!xstrncasecmp(tag, "EligibleTime", MAX(taglen, 2)) || !xstrncasecmp(tag, "StartTime", MAX(taglen, 2))) { if ((job_msg.begin_time = parse_time(val, 0))) { if (job_msg.begin_time < time(NULL)) job_msg.begin_time = time(NULL); update_cnt++; } } else if (!xstrncasecmp(tag, "EndTime", MAX(taglen, 2))) { job_msg.end_time = parse_time(val, 0); update_cnt++; } else if (!xstrncasecmp(tag, "Reboot", MAX(taglen, 3))) { if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0) job_msg.reboot = 1; else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) job_msg.reboot = 0; else if (parse_uint16(val, &job_msg.reboot)) { error ("Invalid reboot value: %s", val); exit_code = 1; return 0; } update_cnt++; } else if (!xstrncasecmp(tag, "UserID", MAX(taglen, 3))) { uid_t user_id = 0; if (uid_from_string(val, &user_id) < 0) { exit_code = 1; fprintf (stderr, "Invalid UserID: %s\n", val); fprintf (stderr, "Request aborted\n"); return 0; } job_uid = (uint32_t) user_id; } else if (!xstrncasecmp(tag, "Deadline", MAX(taglen, 3))) { if ((job_msg.deadline = parse_time(val, 0))) { update_cnt++; } } else { exit_code = 1; fprintf (stderr, "Update of this parameter is not " "supported: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); return 0; } if (add_info) { error("Option %s does not accept [+|-]= syntax", tag); exit_code = 1; return 0; } } if (update_cnt == 0) { exit_code = 1; fprintf (stderr, "No changes specified\n"); return 0; } /* If specified, override uid with effective uid provided by * -u <uid> or --uid=<uid> */ if (euid != NO_VAL) job_msg.user_id = euid; if (!job_msg.job_id_str && job_msg.name) { /* Translate name to job ID string */ job_msg.job_id_str = _job_name2id(job_msg.name, job_uid); if (!job_msg.job_id_str) { exit_code = 1; return 0; } } if (!job_msg.job_id_str) { error("No job ID specified"); exit_code = 1; return 0; } if (update_size && !_is_single_job(job_msg.job_id_str)) { exit_code = 1; return 0; } if (_is_job_id(job_msg.job_id_str)) { job_msg.job_id_str = _next_job_id(); while (job_msg.job_id_str) { rc2 = slurm_update_job2(&job_msg, &resp); if (update_size && (rc2 == SLURM_SUCCESS)) { /* See check above for one job ID */ job_msg.job_id = slurm_atoul(job_msg.job_id_str); _update_job_size(job_msg.job_id); } if (rc2 != SLURM_SUCCESS) { rc2 = slurm_get_errno(); rc = MAX(rc, rc2); exit_code = 1; if (quiet_flag != 1) { fprintf(stderr, "%s for job %s\n", slurm_strerror(slurm_get_errno()), job_msg.job_id_str); } } else if (resp) { for (i = 0; i < resp->job_array_count; i++) { if ((resp->error_code[i] == SLURM_SUCCESS) && (resp->job_array_count == 1)) continue; exit_code = 1; if (quiet_flag == 1) continue; fprintf(stderr, "%s: %s\n", resp->job_array_id[i], slurm_strerror(resp-> error_code[i])); } slurm_free_job_array_resp(resp); resp = NULL; } job_msg.job_id_str = _next_job_id(); } } else if (job_msg.job_id_str) { exit_code = 1; rc = ESLURM_INVALID_JOB_ID; slurm_seterrno(rc); if (quiet_flag != 1) { fprintf(stderr, "%s for job %s\n", slurm_strerror(rc), job_msg.job_id_str); } } return rc; }
/* 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; }
void parse_command_line(int argc, char **argv) { extern int optind; int c, i, optionIndex = 0; char *end = NULL, *start = NULL, *acct_type = NULL; slurmdb_selected_step_t *selected_step = NULL; ListIterator itr = NULL; struct stat stat_buf; char *dot = NULL; bool brief_output = FALSE, long_output = FALSE; bool all_users = 0; bool all_clusters = 0; slurmdb_job_cond_t *job_cond = params.job_cond; log_options_t opts = LOG_OPTS_STDERR_ONLY ; int verbosity; /* count of -v options */ bool set; static struct option long_options[] = { {"allusers", no_argument, 0, 'a'}, {"accounts", required_argument, 0, 'A'}, {"allocations", no_argument, ¶ms.opt_allocs, OPT_LONG_ALLOCS}, {"brief", no_argument, 0, 'b'}, {"completion", no_argument, ¶ms.opt_completion, 'c'}, {"duplicates", no_argument, ¶ms.opt_dup, OPT_LONG_DUP}, {"helpformat", no_argument, 0, 'e'}, {"help-fields", no_argument, 0, 'e'}, {"endtime", required_argument, 0, 'E'}, {"file", required_argument, 0, 'f'}, {"gid", required_argument, 0, 'g'}, {"group", required_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {"helpformat", no_argument, ¶ms.opt_help, OPT_LONG_HELP}, {"name", required_argument, 0, OPT_LONG_NAME}, {"nnodes", required_argument, 0, 'i'}, {"ncpus", required_argument, 0, 'I'}, {"jobs", required_argument, 0, 'j'}, {"timelimit-min", required_argument, 0, 'k'}, {"timelimit-max", required_argument, 0, 'K'}, {"long", no_argument, 0, 'l'}, {"allclusters", no_argument, 0, 'L'}, {"cluster", required_argument, 0, 'M'}, {"clusters", required_argument, 0, 'M'}, {"nodelist", required_argument, 0, 'N'}, {"noheader", no_argument, 0, 'n'}, {"fields", required_argument, 0, 'o'}, {"format", required_argument, 0, 'o'}, {"parsable", no_argument, 0, 'p'}, {"parsable2", no_argument, 0, 'P'}, {"qos", required_argument, 0, 'q'}, {"partition", required_argument, 0, 'r'}, {"state", required_argument, 0, 's'}, {"starttime", required_argument, 0, 'S'}, {"truncate", no_argument, 0, 'T'}, {"uid", required_argument, 0, 'u'}, {"usage", no_argument, ¶ms.opt_help, OPT_LONG_USAGE}, {"user", required_argument, 0, 'u'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"wckeys", required_argument, 0, 'W'}, {"associations", required_argument, 0, 'x'}, {0, 0, 0, 0}}; params.opt_uid = getuid(); params.opt_gid = getgid(); verbosity = 0; log_init("sacct", opts, SYSLOG_FACILITY_DAEMON, NULL); opterr = 1; /* Let getopt report problems to the user */ while (1) { /* now cycle through the command line */ c = getopt_long(argc, argv, "aA:bcC:dDeE:f:g:hi:I:j:k:K:lLM:nN:o:OpPq:r:s:S:Ttu:vVW:x:X", long_options, &optionIndex); if (c == -1) break; switch (c) { case 'a': all_users = 1; break; case 'A': if(!job_cond->acct_list) job_cond->acct_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->acct_list, optarg); break; case 'b': brief_output = true; break; case 'c': params.opt_completion = 1; break; case 'C': /* 'C' is deprecated since 'M' is cluster on everything else. */ case 'M': if(!strcasecmp(optarg, "-1")) { all_clusters = 1; break; } all_clusters=0; if(!job_cond->cluster_list) job_cond->cluster_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->cluster_list, optarg); break; case 'D': params.opt_dup = 1; break; case 'e': params.opt_help = 2; break; case 'E': job_cond->usage_end = parse_time(optarg, 1); if (errno == ESLURM_INVALID_TIME_VALUE) exit(1); break; case 'f': xfree(params.opt_filein); params.opt_filein = xstrdup(optarg); break; case 'g': if(!job_cond->groupid_list) job_cond->groupid_list = list_create(slurm_destroy_char); _addto_id_char_list(job_cond->groupid_list, optarg, 1); break; case 'h': params.opt_help = 1; break; case 'i': set = get_resource_arg_range( optarg, "requested node range", (int *)&job_cond->nodes_min, (int *)&job_cond->nodes_max, true); if (set == false) { error("invalid node range -i '%s'", optarg); exit(1); } break; case 'I': set = get_resource_arg_range( optarg, "requested cpu range", (int *)&job_cond->cpus_min, (int *)&job_cond->cpus_max, true); if (set == false) { error("invalid cpu range -i '%s'", optarg); exit(1); } break; case 'j': if ((strspn(optarg, "0123456789, ") < strlen(optarg)) && (strspn(optarg, ".batch0123456789, ") < strlen(optarg))) { fprintf(stderr, "Invalid jobs list: %s\n", optarg); exit(1); } if(!job_cond->step_list) job_cond->step_list = list_create( slurmdb_destroy_selected_step); _addto_step_list(job_cond->step_list, optarg); break; case 'k': job_cond->timelimit_min = time_str2mins(optarg); if (((int32_t)job_cond->timelimit_min <= 0) && (job_cond->timelimit_min != INFINITE)) fatal("Invalid time limit specification"); break; case 'K': job_cond->timelimit_max = time_str2mins(optarg); if (((int32_t)job_cond->timelimit_max <= 0) && (job_cond->timelimit_max != INFINITE)) fatal("Invalid time limit specification"); break; case 'L': all_clusters = 1; break; case 'l': long_output = true; break; case 'n': print_fields_have_header = 0; break; case 'N': if(job_cond->used_nodes) { error("Aleady asked for nodes '%s'", job_cond->used_nodes); break; } job_cond->used_nodes = xstrdup(optarg); break; case OPT_LONG_NAME: if(!job_cond->jobname_list) job_cond->jobname_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->jobname_list, optarg); break; case 'o': xstrfmtcat(params.opt_field_list, "%s,", optarg); break; case 'p': print_fields_parsable_print = PRINT_FIELDS_PARSABLE_ENDING; break; case 'P': print_fields_parsable_print = PRINT_FIELDS_PARSABLE_NO_ENDING; break; case 'q': if (!g_qos_list) { slurmdb_qos_cond_t qos_cond; memset(&qos_cond, 0, sizeof(slurmdb_qos_cond_t)); qos_cond.with_deleted = 1; g_qos_list = slurmdb_qos_get( acct_db_conn, &qos_cond); } if(!job_cond->qos_list) job_cond->qos_list = list_create(slurm_destroy_char); if(!slurmdb_addto_qos_char_list(job_cond->qos_list, g_qos_list, optarg, 0)) fatal("problem processing qos list"); break; case 'r': if(!job_cond->partition_list) job_cond->partition_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->partition_list, optarg); break; case 's': if(!job_cond->state_list) job_cond->state_list = list_create(slurm_destroy_char); _addto_state_char_list(job_cond->state_list, optarg); break; case 'S': job_cond->usage_start = parse_time(optarg, 1); if (errno == ESLURM_INVALID_TIME_VALUE) exit(1); break; case 'T': job_cond->without_usage_truncation = 0; break; case 'U': params.opt_help = 3; break; case 'u': if(!strcmp(optarg, "-1")) { all_users = 1; break; } all_users = 0; if(!job_cond->userid_list) job_cond->userid_list = list_create(slurm_destroy_char); _addto_id_char_list(job_cond->userid_list, optarg, 0); break; case 'v': /* Handle -vvv thusly... */ verbosity++; break; case 'W': if(!job_cond->wckey_list) job_cond->wckey_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->wckey_list, optarg); break; case 'V': print_slurm_version(); exit(0); case 'x': if(!job_cond->associd_list) job_cond->associd_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->associd_list, optarg); break; case 't': case 'X': params.opt_allocs = 1; break; case ':': case '?': /* getopt() has explained it */ exit(1); } } if (verbosity) { opts.stderr_level += verbosity; opts.prefix_level = 1; log_alter(opts, 0, NULL); } /* Now set params.opt_dup, unless they've already done so */ if (params.opt_dup < 0) /* not already set explicitly */ params.opt_dup = 0; job_cond->duplicates = params.opt_dup; job_cond->without_steps = params.opt_allocs; if(!job_cond->usage_start && !job_cond->step_list) { struct tm start_tm; job_cond->usage_start = time(NULL); if (!localtime_r(&job_cond->usage_start, &start_tm)) { error("Couldn't get localtime from %ld", (long)job_cond->usage_start); return; } start_tm.tm_sec = 0; start_tm.tm_min = 0; start_tm.tm_hour = 0; start_tm.tm_isdst = -1; job_cond->usage_start = mktime(&start_tm); } if(verbosity > 0) { char *start_char =NULL, *end_char = NULL; start_char = xstrdup(ctime(&job_cond->usage_start)); /* remove the new line */ start_char[strlen(start_char)-1] = '\0'; if(job_cond->usage_end) { end_char = xstrdup(ctime(&job_cond->usage_end)); /* remove the new line */ end_char[strlen(end_char)-1] = '\0'; } else end_char = xstrdup("Now"); info("Jobs eligible from %s - %s", start_char, end_char); xfree(start_char); xfree(end_char); } debug("Options selected:\n" "\topt_completion=%d\n" "\topt_dup=%d\n" "\topt_field_list=%s\n" "\topt_help=%d\n" "\topt_allocs=%d", params.opt_completion, params.opt_dup, params.opt_field_list, params.opt_help, params.opt_allocs); if(params.opt_completion) { g_slurm_jobcomp_init(params.opt_filein); acct_type = slurm_get_jobcomp_type(); if ((strcmp(acct_type, "jobcomp/none") == 0) && (stat(params.opt_filein, &stat_buf) != 0)) { fprintf(stderr, "SLURM job completion is disabled\n"); exit(1); } xfree(acct_type); } else { slurm_acct_storage_init(params.opt_filein); acct_type = slurm_get_accounting_storage_type(); if ((strcmp(acct_type, "accounting_storage/none") == 0) && (stat(params.opt_filein, &stat_buf) != 0)) { fprintf(stderr, "SLURM accounting storage is disabled\n"); exit(1); } xfree(acct_type); acct_db_conn = slurmdb_connection_get(); if(errno != SLURM_SUCCESS) { error("Problem talking to the database: %m"); exit(1); } } /* specific clusters requested? */ if(all_clusters) { if(job_cond->cluster_list && list_count(job_cond->cluster_list)) { list_destroy(job_cond->cluster_list); job_cond->cluster_list = NULL; } debug2("Clusters requested:\tall"); } else if (job_cond->cluster_list && list_count(job_cond->cluster_list)) { debug2( "Clusters requested:"); itr = list_iterator_create(job_cond->cluster_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } else if(!job_cond->cluster_list || !list_count(job_cond->cluster_list)) { if(!job_cond->cluster_list) job_cond->cluster_list = list_create(slurm_destroy_char); if((start = slurm_get_cluster_name())) { list_append(job_cond->cluster_list, start); debug2("Clusters requested:\t%s", start); } } /* if any jobs or nodes are specified set to look for all users if none are set */ if(!job_cond->userid_list || !list_count(job_cond->userid_list)) if((job_cond->step_list && list_count(job_cond->step_list)) || job_cond->used_nodes) all_users=1; /* set all_users for user root if not requesting any */ if(!job_cond->userid_list && !params.opt_uid) all_users = 1; if(all_users) { if(job_cond->userid_list && list_count(job_cond->userid_list)) { list_destroy(job_cond->userid_list); job_cond->userid_list = NULL; } debug2("Userids requested:\tall"); } else if (job_cond->userid_list && list_count(job_cond->userid_list)) { debug2("Userids requested:"); itr = list_iterator_create(job_cond->userid_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } else if(!job_cond->userid_list || !list_count(job_cond->userid_list)) { if(!job_cond->userid_list) job_cond->userid_list = list_create(slurm_destroy_char); start = xstrdup_printf("%u", params.opt_uid); list_append(job_cond->userid_list, start); debug2("Userid requested\t: %s", start); } if (job_cond->groupid_list && list_count(job_cond->groupid_list)) { debug2("Groupids requested:"); itr = list_iterator_create(job_cond->groupid_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } /* specific partitions requested? */ if (job_cond->partition_list && list_count(job_cond->partition_list)) { debug2("Partitions requested:"); itr = list_iterator_create(job_cond->partition_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } /* specific qos' requested? */ if (job_cond->qos_list && list_count(job_cond->qos_list)) { start = get_qos_complete_str(g_qos_list, job_cond->qos_list); debug2("QOS requested\t: %s\n", start); xfree(start); } /* specific jobs requested? */ if (job_cond->step_list && list_count(job_cond->step_list)) { debug2("Jobs requested:"); itr = list_iterator_create(job_cond->step_list); while((selected_step = list_next(itr))) { if(selected_step->stepid != NO_VAL) debug2("\t: %d.%d", selected_step->jobid, selected_step->stepid); else debug2("\t: %d", selected_step->jobid); } list_iterator_destroy(itr); } /* specific states (completion state) requested? */ if (job_cond->state_list && list_count(job_cond->state_list)) { debug2("States requested:"); itr = list_iterator_create(job_cond->state_list); while((start = list_next(itr))) { debug2("\t: %s", job_state_string(atoi(start))); } list_iterator_destroy(itr); } if (job_cond->wckey_list && list_count(job_cond->wckey_list)) { debug2("Wckeys requested:"); itr = list_iterator_create(job_cond->wckey_list); while((start = list_next(itr))) debug2("\t: %s\n", start); list_iterator_destroy(itr); } if (job_cond->timelimit_min) { char time_str[128], tmp1[32], tmp2[32]; mins2time_str(job_cond->timelimit_min, tmp1, sizeof(tmp1)); sprintf(time_str, "%s", tmp1); if(job_cond->timelimit_max) { int len = strlen(tmp1); mins2time_str(job_cond->timelimit_max, tmp2, sizeof(tmp2)); sprintf(time_str+len, " - %s", tmp2); } debug2("Timelimit requested\t: %s", time_str); } /* specific jobnames requested? */ if (job_cond->jobname_list && list_count(job_cond->jobname_list)) { debug2("Jobnames requested:"); itr = list_iterator_create(job_cond->jobname_list); while((start = list_next(itr))) { debug2("\t: %s", start); } list_iterator_destroy(itr); } /* select the output fields */ if(brief_output) { if(params.opt_completion) dot = BRIEF_COMP_FIELDS; else dot = BRIEF_FIELDS; xstrfmtcat(params.opt_field_list, "%s,", dot); } if(long_output) { if(params.opt_completion) dot = LONG_COMP_FIELDS; else dot = LONG_FIELDS; xstrfmtcat(params.opt_field_list, "%s,", dot); } if (params.opt_field_list==NULL) { if(params.opt_completion) dot = DEFAULT_COMP_FIELDS; else dot = DEFAULT_FIELDS; xstrfmtcat(params.opt_field_list, "%s,", dot); } start = params.opt_field_list; while ((end = strstr(start, ","))) { char *tmp_char = NULL; int command_len = 0; int newlen = 0; *end = 0; while (isspace(*start)) start++; /* discard whitespace */ if(!(int)*start) continue; if((tmp_char = strstr(start, "\%"))) { newlen = atoi(tmp_char+1); tmp_char[0] = '\0'; } command_len = strlen(start); for (i = 0; fields[i].name; i++) { if (!strncasecmp(fields[i].name, start, command_len)) goto foundfield; } error("Invalid field requested: \"%s\"", start); exit(1); foundfield: if(newlen) fields[i].len = newlen; list_append(print_fields_list, &fields[i]); start = end + 1; }
extern int scontrol_parse_part_options (int argc, char *argv[], int *update_cnt_ptr, update_part_msg_t *part_msg_ptr) { int i, min, max; char *tag, *val; int taglen, vallen; if (!update_cnt_ptr) { error("scontrol_parse_part_options internal error, " "update_cnt_ptr == NULL"); exit_code = 1; return -1; } if (!part_msg_ptr) { error("scontrol_parse_part_options internal error, " "part_msg_ptr == NULL"); exit_code = 1; return -1; } for (i=0; i<argc; i++) { tag = argv[i]; val = strchr(argv[i], '='); if (val) { taglen = val - argv[i]; val++; vallen = strlen(val); } else { exit_code = 1; error("Invalid input: %s Request aborted", argv[i]); return -1; } if (strncasecmp(tag, "PartitionName", MAX(taglen, 2)) == 0) { part_msg_ptr->name = val; (*update_cnt_ptr)++; } else if (strncasecmp(tag, "MaxTime", MAX(taglen, 4)) == 0) { int max_time = time_str2mins(val); if ((max_time < 0) && (max_time != INFINITE)) { exit_code = 1; error("Invalid input %s", argv[i]); return -1; } part_msg_ptr->max_time = max_time; (*update_cnt_ptr)++; } else if (strncasecmp(tag, "DefaultTime", MAX(taglen, 8)) == 0){ int default_time = time_str2mins(val); if ((default_time < 0) && (default_time != INFINITE)) { exit_code = 1; error("Invalid input %s", argv[i]); return -1; } part_msg_ptr->default_time = default_time; (*update_cnt_ptr)++; } else if (strncasecmp(tag, "MaxCPUsPerNode", MAX(taglen, 4)) == 0) { if ((xstrcasecmp(val,"UNLIMITED") == 0) || (xstrcasecmp(val,"INFINITE") == 0)) { part_msg_ptr->max_cpus_per_node = (uint32_t) INFINITE; } else if (parse_uint32(val, &part_msg_ptr-> max_cpus_per_node)) { error("Invalid MaxCPUsPerNode value: %s", val); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "MaxNodes", MAX(taglen, 4)) == 0) { if ((xstrcasecmp(val,"UNLIMITED") == 0) || (xstrcasecmp(val,"INFINITE") == 0)) part_msg_ptr->max_nodes = (uint32_t) INFINITE; else { min = 1; get_resource_arg_range(val, "MaxNodes", &min, &max, true); part_msg_ptr->max_nodes = min; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "MinNodes", MAX(taglen, 2)) == 0) { min = 1; verify_node_count(val, &min, &max); part_msg_ptr->min_nodes = min; (*update_cnt_ptr)++; } else if (strncasecmp(tag, "Default", MAX(taglen, 7)) == 0) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_DEFAULT_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_DEFAULT; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable Default values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "DisableRootJobs", MAX(taglen, 1))) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_NO_ROOT_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_NO_ROOT; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable DisableRootJobs values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "ExclusiveUser", MAX(taglen, 1))) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_EXC_USER_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_EXCLUSIVE_USER; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable ExclusiveUser values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "Hidden", MAX(taglen, 1)) == 0) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_HIDDEN_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_HIDDEN; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable Hidden values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "LLN", MAX(taglen, 1)) == 0) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_LLN_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_LLN; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable LLN values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "RootOnly", MAX(taglen, 3)) == 0) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_ROOT_ONLY_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_ROOT_ONLY; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable RootOnly values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "ReqResv", MAX(taglen, 3)) == 0) { if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_REQ_RESV_CLR; else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_REQ_RESV; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable ReqResv values " "are YES and NO"); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "Shared", MAX(taglen, 2)) == 0) { char *colon_pos = strchr(val, ':'); if (colon_pos) { *colon_pos = '\0'; vallen = strlen(val); } if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) { part_msg_ptr->max_share = 1; } else if (strncasecmp(val, "EXCLUSIVE", MAX(vallen, 1)) == 0) { part_msg_ptr->max_share = 0; } else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0) { if (colon_pos) { part_msg_ptr->max_share = (uint16_t) strtol(colon_pos+1, (char **) NULL, 10); } else { part_msg_ptr->max_share = (uint16_t) 4; } } else if (strncasecmp(val, "FORCE", MAX(vallen, 1)) == 0) { if (colon_pos) { part_msg_ptr->max_share = (uint16_t) strtol(colon_pos+1, (char **) NULL, 10) | SHARED_FORCE; } else { part_msg_ptr->max_share = (uint16_t) 4 |SHARED_FORCE; } } else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable Shared values are " "NO, EXCLUSIVE, YES:#, and FORCE:#"); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "PreemptMode", MAX(taglen, 3)) == 0) { uint16_t new_mode = preempt_mode_num(val); if (new_mode != (uint16_t) NO_VAL) part_msg_ptr->preempt_mode = new_mode; else { error("Invalid input: %s", argv[i]); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "Priority", MAX(taglen, 3))) { if (parse_uint16(val, &part_msg_ptr->priority_tier)) { error("Invalid Priority value: %s", val); return -1; } part_msg_ptr->priority_job_factor = part_msg_ptr->priority_tier; (*update_cnt_ptr)++; } else if (!strncasecmp(tag,"PriorityJobFactor",MAX(taglen, 3))) { if (parse_uint16(val, &part_msg_ptr->priority_job_factor)) { error("Invalid PriorityJobFactor value: %s", val); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "PriorityTier", MAX(taglen, 3))) { if (parse_uint16(val, &part_msg_ptr->priority_tier)) { error("Invalid PriorityTier value: %s", val); return -1; } (*update_cnt_ptr)++; } else if (strncasecmp(tag, "State", MAX(taglen, 2)) == 0) { if (strncasecmp(val, "INACTIVE", MAX(vallen, 1)) == 0) part_msg_ptr->state_up = PARTITION_INACTIVE; else if (strncasecmp(val, "DOWN", MAX(vallen, 1)) == 0) part_msg_ptr->state_up = PARTITION_DOWN; else if (strncasecmp(val, "UP", MAX(vallen, 1)) == 0) part_msg_ptr->state_up = PARTITION_UP; else if (strncasecmp(val, "DRAIN", MAX(vallen, 1)) == 0) part_msg_ptr->state_up = PARTITION_DRAIN; else { exit_code = 1; error("Invalid input: %s", argv[i]); error("Acceptable State values " "are UP, DOWN, DRAIN and INACTIVE"); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "Nodes", MAX(taglen, 1))) { part_msg_ptr->nodes = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "AllowGroups", MAX(taglen, 6))) { part_msg_ptr->allow_groups = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "AllowAccounts", MAX(taglen, 6))) { part_msg_ptr->allow_accounts = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "AllowQos", MAX(taglen, 6))) { part_msg_ptr->allow_qos = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "DenyAccounts", MAX(taglen, 5))) { part_msg_ptr->deny_accounts = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "DenyQos", MAX(taglen, 5))) { part_msg_ptr->deny_qos = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "AllocNodes", MAX(taglen, 6))) { part_msg_ptr->allow_alloc_nodes = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "Alternate", MAX(taglen, 3))) { part_msg_ptr->alternate = val; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "GraceTime", MAX(taglen, 5))) { if (parse_uint32(val, &part_msg_ptr->grace_time)) { error ("Invalid GraceTime value: %s", val); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "DefMemPerCPU", MAX(taglen, 10))) { if (parse_uint32(val, &part_msg_ptr->def_mem_per_cpu)) { error ("Invalid DefMemPerCPU value: %s", val); return -1; } part_msg_ptr->def_mem_per_cpu |= MEM_PER_CPU; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "DefMemPerNode", MAX(taglen, 10))) { if (parse_uint32(val, &part_msg_ptr->def_mem_per_cpu)) { error ("Invalid DefMemPerNode value: %s", val); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "MaxMemPerCPU", MAX(taglen, 10))) { if (parse_uint32(val, &part_msg_ptr->max_mem_per_cpu)) { error ("Invalid MaxMemPerCPU value: %s", val); return -1; } part_msg_ptr->max_mem_per_cpu |= MEM_PER_CPU; (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "MaxMemPerNode", MAX(taglen, 10))) { if (parse_uint32(val, &part_msg_ptr->max_mem_per_cpu)) { error ("Invalid MaxMemPerNode value: %s", val); return -1; } (*update_cnt_ptr)++; } else if (!strncasecmp(tag, "QoS", MAX(taglen, 3))) { part_msg_ptr->qos_char = val; (*update_cnt_ptr)++; } else { exit_code = 1; error("Update of this parameter is not " "supported: %s\n", argv[i]); error("Request aborted"); return -1; } } return 0; }
extern int sacctmgr_set_association_rec(slurmdb_association_rec_t *assoc, char *type, char *value, int command_len, int option) { int set = 0; uint32_t mins = NO_VAL; if (!assoc) return set; if (!strncasecmp (type, "DefaultQOS", MAX(command_len, 8))) { if(!g_qos_list) g_qos_list = acct_storage_g_get_qos( db_conn, my_uid, NULL); if(atoi(value) == -1) assoc->def_qos_id = -1; else assoc->def_qos_id = str_2_slurmdb_qos( g_qos_list, value); if(assoc->def_qos_id == NO_VAL) { fprintf(stderr, "You gave a bad default qos '%s'. " "Use 'list qos' to get " "complete list.\n", value); exit_code = 1; } set = 1; } else if (!strncasecmp(type, "FairShare", MAX(command_len, 1)) || !strncasecmp(type, "Shares", MAX(command_len, 1))) { if (!strncasecmp(value, "parent", 6)) { assoc->shares_raw = SLURMDB_FS_USE_PARENT; set = 1; } else if (get_uint(value, &assoc->shares_raw, "FairShare") == SLURM_SUCCESS) { set = 1; } } else if (!strncasecmp(type, "GrpCPUMins", MAX(command_len, 7))) { if (get_uint64(value, &assoc->grp_cpu_mins, "GrpCPUMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "GrpCPURunMins", MAX(command_len, 7))) { if (get_uint64(value, &assoc->grp_cpu_run_mins, "GrpCPURunMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "GrpCpus", MAX(command_len, 7))) { if (get_uint(value, &assoc->grp_cpus, "GrpCpus") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "GrpJobs", MAX(command_len, 4))) { if (get_uint(value, &assoc->grp_jobs, "GrpJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "GrpNodes", MAX(command_len, 4))) { if (get_uint(value, &assoc->grp_nodes, "GrpNodes") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "GrpSubmitJobs", MAX(command_len, 4))) { if (get_uint(value, &assoc->grp_submit_jobs, "GrpSubmitJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "GrpWall", MAX(command_len, 4))) { mins = time_str2mins(value); if (mins != NO_VAL) { assoc->grp_wall = mins; set = 1; } else { exit_code=1; fprintf(stderr, " Bad GrpWall time format: %s\n", type); } } else if (!strncasecmp(type, "MaxCPUMinsPerJob", MAX(command_len, 7))) { if (get_uint64(value, &assoc->max_cpu_mins_pj, "MaxCPUMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "MaxCPURunMins", MAX(command_len, 7))) { if (get_uint64(value, &assoc->max_cpu_run_mins, "MaxCPURunMins") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "MaxCpusPerJob", MAX(command_len, 7))) { if (get_uint(value, &assoc->max_cpus_pj, "MaxCpus") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "MaxJobs", MAX(command_len, 4))) { if (get_uint(value, &assoc->max_jobs, "MaxJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "MaxNodesPerJob", MAX(command_len, 4))) { if (get_uint(value, &assoc->max_nodes_pj, "MaxNodes") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "MaxSubmitJobs", MAX(command_len, 4))) { if (get_uint(value, &assoc->max_submit_jobs, "MaxSubmitJobs") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp(type, "MaxWallDurationPerJob", MAX(command_len, 4))) { mins = time_str2mins(value); if (mins != NO_VAL) { assoc->max_wall_pj = mins; set = 1; } else { exit_code=1; fprintf(stderr, " Bad MaxWall time format: %s\n", type); } } else if (!strncasecmp(type, "Parent", MAX(command_len, 1))) { assoc->parent_acct = strip_quotes(value, NULL, 1); set = 1; } else if (!strncasecmp(type, "QosLevel", MAX(command_len, 1))) { if (!assoc->qos_list) assoc->qos_list = list_create(slurm_destroy_char); if (!g_qos_list) g_qos_list = acct_storage_g_get_qos( db_conn, my_uid, NULL); if (slurmdb_addto_qos_char_list(assoc->qos_list, g_qos_list, value, option)) set = 1; } return set; }