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 SLURM_ERROR; } if (!part_msg_ptr) { error("scontrol_parse_part_options internal error, " "part_msg_ptr == NULL"); exit_code = 1; return SLURM_ERROR; } 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 SLURM_ERROR; } if (xstrncasecmp(tag, "PartitionName", MAX(taglen, 2)) == 0) { part_msg_ptr->name = val; (*update_cnt_ptr)++; } else if (xstrncasecmp(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 SLURM_ERROR; } part_msg_ptr->max_time = max_time; (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "CpuBind", MAX(taglen, 7)) == 0) { if (xlate_cpu_bind_str(val, &part_msg_ptr->cpu_bind) != SLURM_SUCCESS) { exit_code = 1; error("Invalid input %s", argv[i]); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(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 SLURM_ERROR; } part_msg_ptr->default_time = default_time; (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "MaxCPUsPerNode", MAX(taglen, 4)) == 0) { if ((xstrcasecmp(val,"UNLIMITED") == 0) || (xstrcasecmp(val,"INFINITE") == 0)) { part_msg_ptr->max_cpus_per_node = INFINITE; } else if (parse_uint32(val, &part_msg_ptr-> max_cpus_per_node)) { error("Invalid MaxCPUsPerNode value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "MaxNodes", MAX(taglen, 4)) == 0) { if ((xstrcasecmp(val,"UNLIMITED") == 0) || (xstrcasecmp(val,"INFINITE") == 0)) part_msg_ptr->max_nodes = INFINITE; else { min = 1; get_resource_arg_range(val, "MaxNodes", &min, &max, true); part_msg_ptr->max_nodes = min; } (*update_cnt_ptr)++; } else if (xstrncasecmp(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 (xstrncasecmp(tag, "Default", MAX(taglen, 7)) == 0) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_DEFAULT_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "DisableRootJobs", MAX(taglen, 1))) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_NO_ROOT_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "ExclusiveUser", MAX(taglen, 1))) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_EXC_USER_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "Hidden", MAX(taglen, 1)) == 0) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_HIDDEN_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "LLN", MAX(taglen, 1)) == 0) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_LLN_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "RootOnly", MAX(taglen, 3)) == 0) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_ROOT_ONLY_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "ReqResv", MAX(taglen, 3)) == 0) { if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) part_msg_ptr->flags |= PART_FLAG_REQ_RESV_CLR; else if (xstrncasecmp(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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "OverSubscribe", MAX(taglen, 5)) || !xstrncasecmp(tag, "Shared", MAX(taglen, 2))) { char *colon_pos = strchr(val, ':'); if (colon_pos) { *colon_pos = '\0'; vallen = strlen(val); } if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0) { part_msg_ptr->max_share = 1; } else if (xstrncasecmp(val, "EXCLUSIVE", MAX(vallen, 1)) == 0) { part_msg_ptr->max_share = 0; } else if (xstrncasecmp(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 (xstrncasecmp(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 OverSubscribe values are " "NO, EXCLUSIVE, YES:#, and FORCE:#"); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "OverTimeLimit", MAX(taglen, 5)) == 0) { if ((xstrcasecmp(val,"UNLIMITED") == 0) || (xstrcasecmp(val,"INFINITE") == 0)) { part_msg_ptr->over_time_limit = INFINITE16; } else if (parse_uint16(val, &part_msg_ptr-> over_time_limit)) { error("Invalid OverTimeLimit value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (xstrncasecmp(tag, "PreemptMode", MAX(taglen, 3)) == 0) { uint16_t new_mode = preempt_mode_num(val); if (new_mode != NO_VAL16) part_msg_ptr->preempt_mode = new_mode; else { error("Invalid input: %s", argv[i]); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "Priority", MAX(taglen, 3))) { if (parse_uint16(val, &part_msg_ptr->priority_tier)) { error("Invalid Priority value: %s", val); return SLURM_ERROR; } part_msg_ptr->priority_job_factor = part_msg_ptr->priority_tier; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag,"PriorityJobFactor",MAX(taglen, 3))) { if (parse_uint16(val, &part_msg_ptr->priority_job_factor)) { error("Invalid PriorityJobFactor value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "PriorityTier", MAX(taglen, 3))) { if (parse_uint16(val, &part_msg_ptr->priority_tier)) { error("Invalid PriorityTier value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "State", MAX(taglen, 2))) { if (!xstrncasecmp(val, "INACTIVE", MAX(vallen, 1))) part_msg_ptr->state_up = PARTITION_INACTIVE; else if (!xstrncasecmp(val, "DOWN", MAX(vallen, 1))) part_msg_ptr->state_up = PARTITION_DOWN; else if (!xstrncasecmp(val, "UP", MAX(vallen, 1))) part_msg_ptr->state_up = PARTITION_UP; else if (!xstrncasecmp(val, "DRAIN", MAX(vallen, 1))) 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 SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "Nodes", MAX(taglen, 1))) { part_msg_ptr->nodes = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "AllowGroups", MAX(taglen, 6))) { part_msg_ptr->allow_groups = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "AllowAccounts", MAX(taglen, 6))) { part_msg_ptr->allow_accounts = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "AllowQos", MAX(taglen, 6))) { part_msg_ptr->allow_qos = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "DenyAccounts", MAX(taglen, 5))) { part_msg_ptr->deny_accounts = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "DenyQos", MAX(taglen, 5))) { part_msg_ptr->deny_qos = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "AllocNodes", MAX(taglen, 6))) { part_msg_ptr->allow_alloc_nodes = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "Alternate", MAX(taglen, 3))) { part_msg_ptr->alternate = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "GraceTime", MAX(taglen, 5))) { if (parse_uint32(val, &part_msg_ptr->grace_time)) { error ("Invalid GraceTime value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "DefMemPerCPU", MAX(taglen, 10))) { if (parse_uint64(val, &part_msg_ptr->def_mem_per_cpu)) { error ("Invalid DefMemPerCPU value: %s", val); return SLURM_ERROR; } part_msg_ptr->def_mem_per_cpu |= MEM_PER_CPU; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "DefMemPerNode", MAX(taglen, 10))) { if (parse_uint64(val, &part_msg_ptr->def_mem_per_cpu)) { error ("Invalid DefMemPerNode value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "MaxMemPerCPU", MAX(taglen, 10))) { if (parse_uint64(val, &part_msg_ptr->max_mem_per_cpu)) { error ("Invalid MaxMemPerCPU value: %s", val); return SLURM_ERROR; } part_msg_ptr->max_mem_per_cpu |= MEM_PER_CPU; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "MaxMemPerNode", MAX(taglen, 10))) { if (parse_uint64(val, &part_msg_ptr->max_mem_per_cpu)) { error ("Invalid MaxMemPerNode value: %s", val); return SLURM_ERROR; } (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "QoS", MAX(taglen, 3))) { part_msg_ptr->qos_char = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "JobDefaults", MAX(taglen, 4))) { part_msg_ptr->job_defaults_str = val; (*update_cnt_ptr)++; } else if (!xstrncasecmp(tag, "TresBillingWeights", MAX(taglen, 1))) { part_msg_ptr->billing_weights_str = val; (*update_cnt_ptr)++; } else { exit_code = 1; error("Update of this parameter is not " "supported: %s\n", argv[i]); error("Request aborted"); return SLURM_ERROR; } } return SLURM_SUCCESS; }
/* * scontrol_update_node - update the slurm node 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_node (int argc, char **argv) { int i, j, rc = 0, update_cnt = 0; uint16_t state_val; update_node_msg_t node_msg; char *reason_str = NULL; char *tag, *val; int tag_len, val_len; slurm_init_update_node_msg(&node_msg); for (i = 0; i < argc; i++) { tag = argv[i]; val = strchr(argv[i], '='); if (val) { tag_len = val - argv[i]; val++; val_len = strlen(val); } else { exit_code = 1; error("Invalid input: %s Request aborted", argv[i]); return -1; } if (xstrncasecmp(tag, "NodeAddr", MAX(tag_len, 5)) == 0) { node_msg.node_addr = val; update_cnt++; } else if (xstrncasecmp(tag, "NodeHostName", MAX(tag_len, 5)) == 0) { node_msg.node_hostname = val; update_cnt++; } else if (xstrncasecmp(tag, "NodeName", MAX(tag_len, 1)) == 0) { node_msg.node_names = val; } else if (!xstrncasecmp(tag, "ActiveFeatures", MAX(tag_len,3))) { node_msg.features_act = val; update_cnt++; } else if (xstrncasecmp(tag, "CpuBind", MAX(tag_len, 7)) == 0) { if (xlate_cpu_bind_str(val, &node_msg.cpu_bind) != SLURM_SUCCESS) { exit_code = 1; error("Invalid input %s", argv[i]); return -1; } update_cnt++; } else if (!xstrncasecmp(tag, "Features", MAX(tag_len, 1)) || !xstrncasecmp(tag, "AvailableFeatures", MAX(tag_len,3))) { node_msg.features = val; update_cnt++; } else if (xstrncasecmp(tag, "Gres", MAX(tag_len, 1)) == 0) { node_msg.gres = val; update_cnt++; } else if (xstrncasecmp(tag, "Weight", MAX(tag_len,1)) == 0) { /* Logic borrowed from function _handle_uint32 */ char *endptr; unsigned long num; errno = 0; num = strtoul(val, &endptr, 0); if ((endptr[0] == 'k') || (endptr[0] == 'K')) { num *= 1024; endptr++; } if ((num == 0 && errno == EINVAL) || (*endptr != '\0')) { if ((xstrcasecmp(val, "UNLIMITED") == 0) || (xstrcasecmp(val, "INFINITE") == 0)) { num = INFINITE; } else { error("Weight value (%s) is not a " "valid number", val); break; } } else if (errno == ERANGE) { error("Weight value (%s) is out of range", val); break; } else if (val[0] == '-') { error("Weight value (%s) is less than zero", val); break; } else if (num > 0xfffffff0) { error("Weight value (%s) is greater than %u", val, 0xfffffff0); break; } node_msg.weight = num; update_cnt++; } else if (xstrncasecmp(tag, "Reason", MAX(tag_len, 1)) == 0) { int len = strlen(val); reason_str = xmalloc(len+1); if (*val == '"') strcpy(reason_str, val+1); else strcpy(reason_str, val); len = strlen(reason_str) - 1; if ((len >= 0) && (reason_str[len] == '"')) reason_str[len] = '\0'; node_msg.reason = reason_str; if ((getlogin() == NULL) || (uid_from_string(getlogin(), &node_msg.reason_uid) < 0)) { node_msg.reason_uid = getuid(); } update_cnt++; } else if (xstrncasecmp(tag, "State", MAX(tag_len, 1)) == 0) { if (cluster_flags & CLUSTER_FLAG_CRAY_A) { fprintf (stderr, "%s can not be changed through" " SLURM. Use native Cray tools such as" " xtprocadmin(8)\n", argv[i]); fprintf (stderr, "Request aborted\n"); exit_code = 1; goto done; } if (xstrncasecmp(val, "NoResp", MAX(val_len, 3)) == 0) { node_msg.node_state = NODE_STATE_NO_RESPOND; update_cnt++; } else if (xstrncasecmp(val, "DRAIN", MAX(val_len, 3)) == 0) { node_msg.node_state = NODE_STATE_DRAIN; update_cnt++; } else if (xstrncasecmp(val, "FAIL", MAX(val_len, 3)) == 0) { node_msg.node_state = NODE_STATE_FAIL; update_cnt++; } else if (xstrncasecmp(val, "FUTURE", MAX(val_len, 3)) == 0) { node_msg.node_state = NODE_STATE_FUTURE; update_cnt++; } else if (xstrncasecmp(val, "RESUME", MAX(val_len, 3)) == 0) { node_msg.node_state = NODE_RESUME; update_cnt++; } else if (xstrncasecmp(val, "POWER_DOWN", MAX(val_len, 7)) == 0) { node_msg.node_state = NODE_STATE_POWER_SAVE; update_cnt++; } else if (xstrncasecmp(val, "POWER_UP", MAX(val_len, 7)) == 0) { node_msg.node_state = NODE_STATE_POWER_UP; update_cnt++; } else if (xstrncasecmp(val, "UNDRAIN", MAX(val_len, 3)) == 0) { node_msg.node_state = NODE_STATE_UNDRAIN; update_cnt++; } else { state_val = NO_VAL16; for (j = 0; j < NODE_STATE_END; j++) { if (xstrncasecmp(node_state_string(j), val, MAX(val_len, 3)) == 0){ state_val = (uint16_t) j; break; } } if (j == NODE_STATE_END) { exit_code = 1; fprintf(stderr, "Invalid input: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); fprintf (stderr, "Valid states are: "); fprintf (stderr, "NoResp DRAIN FAIL FUTURE RESUME " "POWER_DOWN POWER_UP UNDRAIN"); fprintf (stderr, "\n"); fprintf (stderr, "Not all states are valid " "given a node's prior " "state\n"); goto done; } node_msg.node_state = state_val; update_cnt++; } } else { exit_code = 1; fprintf (stderr, "Update of this parameter is not " "supported: %s\n", argv[i]); fprintf (stderr, "Request aborted\n"); goto done; } } if (((node_msg.node_state == NODE_STATE_DOWN) || (node_msg.node_state == NODE_STATE_DRAIN) || (node_msg.node_state == NODE_STATE_FAIL)) && ((node_msg.reason == NULL) || (strlen(node_msg.reason) == 0))) { fprintf(stderr, "You must specify a reason when DOWNING or " "DRAINING a node. Request denied\n"); goto done; } if (update_cnt == 0) { exit_code = 1; fprintf (stderr, "No changes specified\n"); return 0; } rc = slurm_update_node(&node_msg); done: xfree(reason_str); if (rc) { exit_code = 1; return slurm_get_errno (); } else return 0; }