/* * 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; }
extern int parse_blockreq(void **dest, slurm_parser_enum_t type, const char *key, const char *value, const char *line, char **leftover) { s_p_options_t block_options[] = { {"Type", S_P_STRING}, {"32CNBlocks", S_P_UINT16}, {"128CNBlocks", S_P_UINT16}, #ifdef HAVE_BGL {"Nodecards", S_P_UINT16}, {"Quarters", S_P_UINT16}, {"BlrtsImage", S_P_STRING}, {"LinuxImage", S_P_STRING}, {"RamDiskImage", S_P_STRING}, #else #ifdef HAVE_BGP {"16CNBlocks", S_P_UINT16}, {"CnloadImage", S_P_STRING}, {"IoloadImage", S_P_STRING}, #endif {"64CNBlocks", S_P_UINT16}, {"256CNBlocks", S_P_UINT16}, #endif {"MloaderImage", S_P_STRING}, {NULL} }; s_p_hashtbl_t *tbl; char *tmp = NULL; select_ba_request_t *n = NULL; hostlist_t hl = NULL; tbl = s_p_hashtbl_create(block_options); s_p_parse_line(tbl, *leftover, leftover); if (!value) { return 0; } n = xmalloc(sizeof(select_ba_request_t)); hl = hostlist_create(value); n->save_name = hostlist_ranged_string_xmalloc(hl); hostlist_destroy(hl); #ifdef HAVE_BGL s_p_get_string(&n->blrtsimage, "BlrtsImage", tbl); s_p_get_string(&n->linuximage, "LinuxImage", tbl); s_p_get_string(&n->ramdiskimage, "RamDiskImage", tbl); #elif defined HAVE_BGP s_p_get_string(&n->linuximage, "CnloadImage", tbl); s_p_get_string(&n->ramdiskimage, "IoloadImage", tbl); #endif s_p_get_string(&n->mloaderimage, "MloaderImage", tbl); s_p_get_string(&tmp, "Type", tbl); if (tmp) { verify_conn_type(tmp, n->conn_type); xfree(tmp); } if (!s_p_get_uint16(&n->small32, "32CNBlocks", tbl)) { #ifdef HAVE_BGL s_p_get_uint16(&n->small32, "Nodecards", tbl); #else ; #endif } if (!s_p_get_uint16(&n->small128, "128CNBlocks", tbl)) { #ifdef HAVE_BGL s_p_get_uint16(&n->small128, "Quarters", tbl); #else ; #endif } #ifndef HAVE_BGL #ifdef HAVE_BGP s_p_get_uint16(&n->small16, "16CNBlocks", tbl); #endif s_p_get_uint16(&n->small64, "64CNBlocks", tbl); s_p_get_uint16(&n->small256, "256CNBlocks", tbl); #endif if (n->small16 || n->small32 || n->small64 || n->small128 || n->small256) { if (n->conn_type[0] < SELECT_SMALL) { error("Block def on midplane(s) %s is " "asking for small blocks but given " "TYPE=%s, setting it to Small", n->save_name, conn_type_string(n->conn_type[0])); n->conn_type[0] = SELECT_SMALL; } } else { if (n->conn_type[0] == (uint16_t)NO_VAL) { n->conn_type[0] = bg_conf->default_conn_type[0]; } else if (n->conn_type[0] >= SELECT_SMALL) { error("Block def on midplane(s) %s is given " "TYPE=%s but isn't asking for any small " "blocks. Giving it %s.", n->save_name, conn_type_string(n->conn_type[0]), conn_type_string( bg_conf->default_conn_type[0])); n->conn_type[0] = bg_conf->default_conn_type[0]; } #ifndef HAVE_BG_L_P int i; for (i=1; i<SYSTEM_DIMENSIONS; i++) { if (n->conn_type[i] == (uint16_t)NO_VAL) n->conn_type[i] = bg_conf->default_conn_type[i]; else if (n->conn_type[i] >= SELECT_SMALL) { error("Block def on midplane(s) %s dim %d " "is given TYPE=%s but isn't asking " "for any small blocks. Giving it %s.", n->save_name, i, conn_type_string(n->conn_type[i]), conn_type_string( bg_conf->default_conn_type[i])); n->conn_type[i] = bg_conf->default_conn_type[i]; } } #endif } s_p_hashtbl_destroy(tbl); *dest = (void *)n; return 1; }
/* * Read and process the bluegene.conf configuration file so to interpret what * blocks are static/dynamic, torus/mesh, etc. */ extern int read_bg_conf(void) { int i; bool tmp_bool = 0; int count = 0; s_p_hashtbl_t *tbl = NULL; char *tmp_char = NULL; select_ba_request_t **blockreq_array = NULL; image_t **image_array = NULL; image_t *image = NULL; static time_t last_config_update = (time_t) 0; struct stat config_stat; ListIterator itr = NULL; char* bg_conf_file = NULL; static int *dims = NULL; if (!dims) dims = select_g_ba_get_dims(); if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("Reading the bluegene.conf file"); /* check if config file has changed */ bg_conf_file = get_extra_conf_path("bluegene.conf"); if (stat(bg_conf_file, &config_stat) < 0) fatal("can't stat bluegene.conf file %s: %m", bg_conf_file); if (last_config_update) { _reopen_bridge_log(); if (last_config_update == config_stat.st_mtime) { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("%s unchanged", bg_conf_file); } else { info("Restart slurmctld for %s changes " "to take effect", bg_conf_file); } last_config_update = config_stat.st_mtime; xfree(bg_conf_file); return SLURM_SUCCESS; } last_config_update = config_stat.st_mtime; /* initialization */ /* bg_conf defined in bg_node_alloc.h */ if (!(tbl = config_make_tbl(bg_conf_file))) fatal("something wrong with opening/reading bluegene " "conf file"); xfree(bg_conf_file); #ifdef HAVE_BGL if (s_p_get_array((void ***)&image_array, &count, "AltBlrtsImage", tbl)) { for (i = 0; i < count; i++) { list_append(bg_conf->blrts_list, image_array[i]); image_array[i] = NULL; } } if (!s_p_get_string(&bg_conf->default_blrtsimage, "BlrtsImage", tbl)) { if (!list_count(bg_conf->blrts_list)) fatal("BlrtsImage not configured " "in bluegene.conf"); itr = list_iterator_create(bg_conf->blrts_list); image = list_next(itr); image->def = true; list_iterator_destroy(itr); bg_conf->default_blrtsimage = xstrdup(image->name); info("Warning: using %s as the default BlrtsImage. " "If this isn't correct please set BlrtsImage", bg_conf->default_blrtsimage); } else { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("default BlrtsImage %s", bg_conf->default_blrtsimage); image = xmalloc(sizeof(image_t)); image->name = xstrdup(bg_conf->default_blrtsimage); image->def = true; image->groups = NULL; /* we want it to be first */ list_push(bg_conf->blrts_list, image); } if (s_p_get_array((void ***)&image_array, &count, "AltLinuxImage", tbl)) { for (i = 0; i < count; i++) { list_append(bg_conf->linux_list, image_array[i]); image_array[i] = NULL; } } if (!s_p_get_string(&bg_conf->default_linuximage, "LinuxImage", tbl)) { if (!list_count(bg_conf->linux_list)) fatal("LinuxImage not configured " "in bluegene.conf"); itr = list_iterator_create(bg_conf->linux_list); image = list_next(itr); image->def = true; list_iterator_destroy(itr); bg_conf->default_linuximage = xstrdup(image->name); info("Warning: using %s as the default LinuxImage. " "If this isn't correct please set LinuxImage", bg_conf->default_linuximage); } else { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("default LinuxImage %s", bg_conf->default_linuximage); image = xmalloc(sizeof(image_t)); image->name = xstrdup(bg_conf->default_linuximage); image->def = true; image->groups = NULL; /* we want it to be first */ list_push(bg_conf->linux_list, image); } if (s_p_get_array((void ***)&image_array, &count, "AltRamDiskImage", tbl)) { for (i = 0; i < count; i++) { list_append(bg_conf->ramdisk_list, image_array[i]); image_array[i] = NULL; } } if (!s_p_get_string(&bg_conf->default_ramdiskimage, "RamDiskImage", tbl)) { if (!list_count(bg_conf->ramdisk_list)) fatal("RamDiskImage not configured " "in bluegene.conf"); itr = list_iterator_create(bg_conf->ramdisk_list); image = list_next(itr); image->def = true; list_iterator_destroy(itr); bg_conf->default_ramdiskimage = xstrdup(image->name); info("Warning: using %s as the default RamDiskImage. " "If this isn't correct please set RamDiskImage", bg_conf->default_ramdiskimage); } else { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("default RamDiskImage %s", bg_conf->default_ramdiskimage); image = xmalloc(sizeof(image_t)); image->name = xstrdup(bg_conf->default_ramdiskimage); image->def = true; image->groups = NULL; /* we want it to be first */ list_push(bg_conf->ramdisk_list, image); } #elif defined HAVE_BGP if (s_p_get_array((void ***)&image_array, &count, "AltCnloadImage", tbl)) { for (i = 0; i < count; i++) { list_append(bg_conf->linux_list, image_array[i]); image_array[i] = NULL; } } if (!s_p_get_string(&bg_conf->default_linuximage, "CnloadImage", tbl)) { if (!list_count(bg_conf->linux_list)) fatal("CnloadImage not configured " "in bluegene.conf"); itr = list_iterator_create(bg_conf->linux_list); image = list_next(itr); image->def = true; list_iterator_destroy(itr); bg_conf->default_linuximage = xstrdup(image->name); info("Warning: using %s as the default CnloadImage. " "If this isn't correct please set CnloadImage", bg_conf->default_linuximage); } else { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("default CnloadImage %s", bg_conf->default_linuximage); image = xmalloc(sizeof(image_t)); image->name = xstrdup(bg_conf->default_linuximage); image->def = true; image->groups = NULL; /* we want it to be first */ list_push(bg_conf->linux_list, image); } if (s_p_get_array((void ***)&image_array, &count, "AltIoloadImage", tbl)) { for (i = 0; i < count; i++) { list_append(bg_conf->ramdisk_list, image_array[i]); image_array[i] = NULL; } } if (!s_p_get_string(&bg_conf->default_ramdiskimage, "IoloadImage", tbl)) { if (!list_count(bg_conf->ramdisk_list)) fatal("IoloadImage not configured " "in bluegene.conf"); itr = list_iterator_create(bg_conf->ramdisk_list); image = list_next(itr); image->def = true; list_iterator_destroy(itr); bg_conf->default_ramdiskimage = xstrdup(image->name); info("Warning: using %s as the default IoloadImage. " "If this isn't correct please set IoloadImage", bg_conf->default_ramdiskimage); } else { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("default IoloadImage %s", bg_conf->default_ramdiskimage); image = xmalloc(sizeof(image_t)); image->name = xstrdup(bg_conf->default_ramdiskimage); image->def = true; image->groups = NULL; /* we want it to be first */ list_push(bg_conf->ramdisk_list, image); } #endif if (s_p_get_array((void ***)&image_array, &count, "AltMloaderImage", tbl)) { for (i = 0; i < count; i++) { list_append(bg_conf->mloader_list, image_array[i]); image_array[i] = NULL; } } if (!s_p_get_string(&bg_conf->default_mloaderimage, "MloaderImage", tbl)) { if (!list_count(bg_conf->mloader_list)) fatal("MloaderImage not configured " "in bluegene.conf"); itr = list_iterator_create(bg_conf->mloader_list); image = list_next(itr); image->def = true; list_iterator_destroy(itr); bg_conf->default_mloaderimage = xstrdup(image->name); info("Warning: using %s as the default MloaderImage. " "If this isn't correct please set MloaderImage", bg_conf->default_mloaderimage); } else { if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("default MloaderImage %s", bg_conf->default_mloaderimage); image = xmalloc(sizeof(image_t)); image->name = xstrdup(bg_conf->default_mloaderimage); image->def = true; image->groups = NULL; /* we want it to be first */ list_push(bg_conf->mloader_list, image); } if (!s_p_get_uint16(&bg_conf->mp_cnode_cnt, "MidplaneNodeCnt", tbl)) { if (!s_p_get_uint16(&bg_conf->mp_cnode_cnt, "BasePartitionNodeCnt", tbl)) { error("MidplaneNodeCnt not configured in bluegene.conf " "defaulting to 512 as MidplaneNodeCnt"); bg_conf->mp_cnode_cnt = 512; } } if (bg_conf->mp_cnode_cnt <= 0) fatal("You should have more than 0 nodes " "per midplane"); bg_conf->actual_cnodes_per_mp = bg_conf->mp_cnode_cnt; bg_conf->quarter_cnode_cnt = bg_conf->mp_cnode_cnt/4; /* bg_conf->cpus_per_mp should had already been set from the * node_init */ if (bg_conf->cpus_per_mp < bg_conf->mp_cnode_cnt) { fatal("For some reason we have only %u cpus per mp, but " "have %u cnodes per mp. You need at least the same " "number of cpus as you have cnodes per mp. " "Check the NodeName CPUs= " "definition in the slurm.conf.", bg_conf->cpus_per_mp, bg_conf->mp_cnode_cnt); } bg_conf->cpu_ratio = bg_conf->cpus_per_mp/bg_conf->mp_cnode_cnt; if (!bg_conf->cpu_ratio) fatal("We appear to have less than 1 cpu on a cnode. " "You specified %u for MidplaneNodeCnt " "in the blugene.conf and %u cpus " "for each node in the slurm.conf", bg_conf->mp_cnode_cnt, bg_conf->cpus_per_mp); num_unused_cpus = 1; for (i = 0; i<SYSTEM_DIMENSIONS; i++) num_unused_cpus *= dims[i]; num_unused_cpus *= bg_conf->cpus_per_mp; num_possible_unused_cpus = num_unused_cpus; if (!s_p_get_uint16(&bg_conf->nodecard_cnode_cnt, "NodeBoardNodeCnt", tbl)) { if (!s_p_get_uint16(&bg_conf->nodecard_cnode_cnt, "NodeCardNodeCnt", tbl)) { error("NodeCardNodeCnt not configured in bluegene.conf " "defaulting to 32 as NodeCardNodeCnt"); bg_conf->nodecard_cnode_cnt = 32; } } if (bg_conf->nodecard_cnode_cnt <= 0) fatal("You should have more than 0 nodes per nodecard"); bg_conf->mp_nodecard_cnt = bg_conf->mp_cnode_cnt / bg_conf->nodecard_cnode_cnt; if (!s_p_get_uint16(&bg_conf->ionodes_per_mp, "IONodesPerMP", tbl)) if (!s_p_get_uint16(&bg_conf->ionodes_per_mp, "Numpsets", tbl)) fatal("Warning: IONodesPerMP not configured " "in bluegene.conf"); s_p_get_uint16(&bg_conf->max_block_err, "MaxBlockInError", tbl); tmp_bool = 0; s_p_get_boolean(&tmp_bool, "SubMidplaneSystem", tbl); bg_conf->sub_mp_sys = tmp_bool; #ifdef HAVE_BGQ tmp_bool = 0; s_p_get_boolean(&tmp_bool, "AllowSubBlockAllocations", tbl); bg_conf->sub_blocks = tmp_bool; /* You can only have 16 ionodes per midplane */ if (bg_conf->ionodes_per_mp > bg_conf->mp_nodecard_cnt) bg_conf->ionodes_per_mp = bg_conf->mp_nodecard_cnt; #endif for (i=0; i<SYSTEM_DIMENSIONS; i++) bg_conf->default_conn_type[i] = (uint16_t)NO_VAL; s_p_get_string(&tmp_char, "DefaultConnType", tbl); if (tmp_char) { verify_conn_type(tmp_char, bg_conf->default_conn_type); if ((bg_conf->default_conn_type[0] != SELECT_MESH) && (bg_conf->default_conn_type[0] != SELECT_TORUS)) fatal("Can't have a DefaultConnType of %s " "(only Mesh or Torus values are valid).", tmp_char); xfree(tmp_char); } else bg_conf->default_conn_type[0] = SELECT_TORUS; #ifndef HAVE_BG_L_P int first_conn_type = bg_conf->default_conn_type[0]; for (i=1; i<SYSTEM_DIMENSIONS; i++) { if (bg_conf->default_conn_type[i] == (uint16_t)NO_VAL) bg_conf->default_conn_type[i] = first_conn_type; else if (bg_conf->default_conn_type[i] >= SELECT_SMALL) fatal("Can't have a DefaultConnType of %s " "(only Mesh or Torus values are valid).", tmp_char); } #endif if (bg_conf->ionodes_per_mp) { bitstr_t *tmp_bitmap = NULL; int small_size = 1; /* THIS IS A HACK TO MAKE A 1 NODECARD SYSTEM WORK, * Sometime on a Q system the nodecard isn't in the 0 * spot so only do this if you know it is in that * spot. Otherwise say the whole midplane is there * and just make blocks over the whole thing. They * you can error out the blocks that aren't usable. */ if (bg_conf->sub_mp_sys && bg_conf->mp_cnode_cnt == bg_conf->nodecard_cnode_cnt) { #ifdef HAVE_BGQ bg_conf->quarter_ionode_cnt = 1; bg_conf->nodecard_ionode_cnt = 1; #else bg_conf->quarter_ionode_cnt = 2; bg_conf->nodecard_ionode_cnt = 2; #endif } else { bg_conf->quarter_ionode_cnt = bg_conf->ionodes_per_mp/4; bg_conf->nodecard_ionode_cnt = bg_conf->quarter_ionode_cnt/4; } /* How many nodecards per ionode */ bg_conf->nc_ratio = ((double)bg_conf->mp_cnode_cnt / (double)bg_conf->nodecard_cnode_cnt) / (double)bg_conf->ionodes_per_mp; /* How many ionodes per nodecard */ bg_conf->io_ratio = (double)bg_conf->ionodes_per_mp / ((double)bg_conf->mp_cnode_cnt / (double)bg_conf->nodecard_cnode_cnt); /* How many cnodes per ionode */ bg_conf->ionode_cnode_cnt = bg_conf->nodecard_cnode_cnt * bg_conf->nc_ratio; //info("got %f %f", bg_conf->nc_ratio, bg_conf->io_ratio); /* figure out the smallest block we can have on the system */ #ifdef HAVE_BGL if (bg_conf->io_ratio >= 1) bg_conf->smallest_block=32; else bg_conf->smallest_block=128; #else if (bg_conf->io_ratio >= 2) bg_conf->smallest_block=16; else if (bg_conf->io_ratio == 1) bg_conf->smallest_block=32; else if (bg_conf->io_ratio == .5) bg_conf->smallest_block=64; else if (bg_conf->io_ratio == .25) bg_conf->smallest_block=128; else if (bg_conf->io_ratio == .125) bg_conf->smallest_block=256; else { error("unknown ioratio %f. Can't figure out " "smallest block size, setting it to midplane", bg_conf->io_ratio); bg_conf->smallest_block = 512; } #endif if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("Smallest block possible on this system is %u", bg_conf->smallest_block); /* below we are creating all the possible bitmaps for * each size of small block */ if ((int)bg_conf->nodecard_ionode_cnt < 1) { bg_conf->nodecard_ionode_cnt = 0; } else { bg_lists->valid_small32 = list_create(_destroy_bitmap); /* This is suppose to be = and not ==, we only want to decrement when small_size equals something. */ if ((small_size = bg_conf->nodecard_ionode_cnt)) small_size--; i = 0; while (i<bg_conf->ionodes_per_mp) { tmp_bitmap = bit_alloc(bg_conf->ionodes_per_mp); bit_nset(tmp_bitmap, i, i+small_size); i += small_size+1; list_append(bg_lists->valid_small32, tmp_bitmap); } } /* If we only have 1 nodecard just jump to the end since this will never need to happen below. Pretty much a hack to avoid seg fault;). */ if (bg_conf->mp_cnode_cnt == bg_conf->nodecard_cnode_cnt) goto no_calc; bg_lists->valid_small128 = list_create(_destroy_bitmap); if ((small_size = bg_conf->quarter_ionode_cnt)) small_size--; i = 0; while (i<bg_conf->ionodes_per_mp) { tmp_bitmap = bit_alloc(bg_conf->ionodes_per_mp); bit_nset(tmp_bitmap, i, i+small_size); i += small_size+1; list_append(bg_lists->valid_small128, tmp_bitmap); } #ifndef HAVE_BGL bg_lists->valid_small64 = list_create(_destroy_bitmap); if ((small_size = bg_conf->nodecard_ionode_cnt * 2)) small_size--; i = 0; while (i<bg_conf->ionodes_per_mp) { tmp_bitmap = bit_alloc(bg_conf->ionodes_per_mp); bit_nset(tmp_bitmap, i, i+small_size); i += small_size+1; list_append(bg_lists->valid_small64, tmp_bitmap); } bg_lists->valid_small256 = list_create(_destroy_bitmap); if ((small_size = bg_conf->quarter_ionode_cnt * 2)) small_size--; i = 0; while (i<bg_conf->ionodes_per_mp) { tmp_bitmap = bit_alloc(bg_conf->ionodes_per_mp); bit_nset(tmp_bitmap, i, i+small_size); i += small_size+1; list_append(bg_lists->valid_small256, tmp_bitmap); } #endif } else { fatal("your ionodes_per_mp is 0"); } no_calc: if (!s_p_get_uint16(&bg_conf->bridge_api_verb, "BridgeAPIVerbose", tbl)) info("Warning: BridgeAPIVerbose not configured " "in bluegene.conf"); if (!s_p_get_string(&bg_conf->bridge_api_file, "BridgeAPILogFile", tbl)) info("BridgeAPILogFile not configured in bluegene.conf"); else _reopen_bridge_log(); if (s_p_get_string(&tmp_char, "DenyPassthrough", tbl)) { if (strstr(tmp_char, "A")) ba_deny_pass |= PASS_DENY_A; if (strstr(tmp_char, "X")) ba_deny_pass |= PASS_DENY_X; if (strstr(tmp_char, "Y")) ba_deny_pass |= PASS_DENY_Y; if (strstr(tmp_char, "Z")) ba_deny_pass |= PASS_DENY_Z; if (!xstrcasecmp(tmp_char, "ALL")) ba_deny_pass |= PASS_DENY_ALL; bg_conf->deny_pass = ba_deny_pass; xfree(tmp_char); } if (!s_p_get_string(&tmp_char, "LayoutMode", tbl)) { info("Warning: LayoutMode was not specified in bluegene.conf " "defaulting to STATIC partitioning"); bg_conf->layout_mode = LAYOUT_STATIC; } else { if (!xstrcasecmp(tmp_char,"STATIC")) bg_conf->layout_mode = LAYOUT_STATIC; else if (!xstrcasecmp(tmp_char,"OVERLAP")) bg_conf->layout_mode = LAYOUT_OVERLAP; else if (!xstrcasecmp(tmp_char,"DYNAMIC")) bg_conf->layout_mode = LAYOUT_DYNAMIC; else { fatal("I don't understand this LayoutMode = %s", tmp_char); } xfree(tmp_char); } /* add blocks defined in file */ if (bg_conf->layout_mode != LAYOUT_DYNAMIC) { if (!s_p_get_array((void ***)&blockreq_array, &count, "MPs", tbl)) { if (!s_p_get_array((void ***)&blockreq_array, &count, "BPs", tbl)) { info("WARNING: no blocks defined in " "bluegene.conf, " "only making full system block"); /* create_full_system_block(NULL); */ if (bg_conf->sub_mp_sys || (bg_conf->mp_cnode_cnt == bg_conf->nodecard_cnode_cnt)) fatal("On a sub-midplane system you " "need to define the blocks you " "want on your system."); } } for (i = 0; i < count; i++) { add_bg_record(bg_lists->main, NULL, blockreq_array[i], 0, 0); } } else if (bg_conf->sub_mp_sys || (bg_conf->mp_cnode_cnt == bg_conf->nodecard_cnode_cnt)) /* we can't do dynamic here on a sub-midplane system */ fatal("On a sub-midplane system we can only do OVERLAP or " "STATIC LayoutMode. Please update your bluegene.conf."); #ifdef HAVE_BGQ if ((bg_recover != NOT_FROM_CONTROLLER) && assoc_mgr_qos_list && s_p_get_string(&tmp_char, "RebootQOSList", tbl)) { bool valid; char *token, *last = NULL; slurmdb_qos_rec_t *qos = NULL; assoc_mgr_lock_t locks = { NO_LOCK, NO_LOCK, NO_LOCK, READ_LOCK, NO_LOCK, NO_LOCK, NO_LOCK }; /* Lock here to avoid g_qos_count changing under us */ assoc_mgr_lock(&locks); bg_conf->reboot_qos_bitmap = bit_alloc(g_qos_count); itr = list_iterator_create(assoc_mgr_qos_list); token = strtok_r(tmp_char, ",", &last); while (token) { valid = false; while((qos = list_next(itr))) { if (!xstrcasecmp(token, qos->name)) { bit_set(bg_conf->reboot_qos_bitmap, qos->id); valid = true; break; } } if (!valid) error("Invalid RebootQOSList value: %s", token); list_iterator_reset(itr); token = strtok_r(NULL, ",", &last); } list_iterator_destroy(itr); xfree(tmp_char); assoc_mgr_unlock(&locks); } #endif s_p_hashtbl_destroy(tbl); return SLURM_SUCCESS; }
static int _create_allocation(char *com, List allocated_blocks) { int i=6, j, geoi=-1, starti=-1, i2=0, small32=-1, small128=-1; int len = strlen(com); select_ba_request_t *request; char fini_char; int diff=0; #ifndef HAVE_BGL #ifdef HAVE_BGP int small16=-1; #endif int small64=-1, small256=-1; #endif request = (select_ba_request_t*) xmalloc(sizeof(select_ba_request_t)); request->rotate = false; request->elongate = false; request->start_req = 0; request->size = 0; request->small32 = 0; request->small128 = 0; request->deny_pass = 0; request->avail_mp_bitmap = NULL; for (j = 0; j < params.cluster_dims; j++) { request->geometry[j] = (uint16_t) NO_VAL; request->conn_type[j] = SELECT_TORUS; } while (i < len) { if (!strncasecmp(com+i, "mesh", 4) || !strncasecmp(com+i, "small", 5) || !strncasecmp(com+i, "torus", 5)) { char conn_type[200]; j = i; while (j < len) { if (com[j] == ' ') break; conn_type[j-i] = com[j]; j++; if (j >= 200) break; } conn_type[(j-i)+1] = '\0'; verify_conn_type(conn_type, request->conn_type); i += j; } else if (!strncasecmp(com+i, "deny", 4)) { i += 4; if (strstr(com+i, "A")) request->deny_pass |= PASS_DENY_A; if (strstr(com+i, "X")) request->deny_pass |= PASS_DENY_X; if (strstr(com+i, "Y")) request->deny_pass |= PASS_DENY_Y; if (strstr(com+i, "Z")) request->deny_pass |= PASS_DENY_Z; if (!strcasecmp(com+i, "ALL")) request->deny_pass |= PASS_DENY_ALL; } else if (!strncasecmp(com+i, "nodecard", 8)) { small32 = 0; i += 8; } else if (!strncasecmp(com+i, "quarter", 7)) { small128 = 0; i += 7; } else if (!strncasecmp(com+i, "32CN", 4)) { small32 = 0; i += 4; } else if (!strncasecmp(com+i, "128CN", 5)) { small128 = 0; i += 5; } else if (!strncasecmp(com+i, "rotate", 6)) { request->rotate = true; i += 6; } else if (!strncasecmp(com+i, "elongate", 8)) { request->elongate = true; i += 8; } else if (!strncasecmp(com+i, "start", 5)) { request->start_req = 1; i += 5; } else if (request->start_req && (starti < 0) && (((com[i] >= '0') && (com[i] <= '9')) || ((com[i] >= 'A') && (com[i] <= 'Z')))) { starti = i; i++; } else if (small32 == 0 && (com[i] >= '0' && com[i] <= '9')) { small32 = i; i++; } else if (small128 == 0 && (com[i] >= '0' && com[i] <= '9')) { small128 = i; i++; } #ifdef HAVE_BGP else if (!strncasecmp(com+i, "16CN", 4)) { small16 = 0; i += 4; } else if (small16 == 0 && (com[i] >= '0' && com[i] <= '9')) { small16 = i; i++; } #endif #ifndef HAVE_BGL else if (!strncasecmp(com+i, "64CN", 4)) { small64 = 0; i += 4; } else if (!strncasecmp(com+i, "256CN", 5)) { small256 = 0; i += 5; } else if (small64 == 0 && (com[i] >= '0' && com[i] <= '9')) { small64 = i; i++; } else if (small256 == 0 && (com[i] >= '0' && com[i] <= '9')) { small256 = i; i++; } #endif else if ((geoi < 0) && (((com[i] >= '0') && (com[i] <= '9')) || ((com[i] >= 'A') && (com[i] <= 'Z')))) { geoi = i; i++; } else { i++; } } if (request->conn_type[0] >= SELECT_SMALL) { int total = 512; #ifdef HAVE_BGP if (small16 > 0) { request->small16 = atoi(&com[small16]); total -= request->small16 * 16; } #endif #ifndef HAVE_BGL if (small64 > 0) { request->small64 = atoi(&com[small64]); total -= request->small64 * 64; } if (small256 > 0) { request->small256 = atoi(&com[small256]); total -= request->small256 * 256; } #endif if (small32 > 0) { request->small32 = atoi(&com[small32]); total -= request->small32 * 32; } if (small128 > 0) { request->small128 = atoi(&com[small128]); total -= request->small128 * 128; } if (total < 0) { sprintf(error_string, "You asked for %d more nodes than " "are in a Midplane\n", total * 2); geoi = -1; } #ifndef HAVE_BGL while (total > 0) { if (total >= 256) { request->small256++; total -= 256; } else if (total >= 128) { request->small128++; total -= 128; } else if (total >= 64) { request->small64++; total -= 64; } else if (total >= 32) { request->small32++; total -= 32; } #ifdef HAVE_BGP else if (total >= 16) { request->small16++; total -= 16; } #endif else break; } #else while (total > 0) { if (total >= 128) { request->small128++; total -= 128; } else if (total >= 32) { request->small32++; total -= 32; } else break; } #endif request->size = 1; /* sprintf(error_string, */ /* "got %d %d %d %d %d %d", */ /* total, request->small16, request->small32, */ /* request->small64, request->small128, */ /* request->small256); */ } if ((geoi < 0) && !request->size) { memset(error_string, 0, 255); sprintf(error_string, "No size or dimension specified, please re-enter"); } else { i2 = geoi; while (i2 < len) { if (request->size) break; if ((com[i2] == ' ') || (i2 == (len-1))) { char *p; /* for size */ request->size = strtol(&com[geoi], &p, 10); if (*p == 'k' || *p == 'K') { request->size *= 2; /* (1024 / 512) */ p++; } break; } if (com[i2]=='x') { request->size = -1; diff = i2 - geoi; /* for geometery */ request->geometry[0] = _xlate_coord(&com[geoi], diff); for (j = 1; j < params.cluster_dims; j++) { geoi += diff; diff = geoi; while ((com[geoi-1]!='x') && com[geoi]) geoi++; if (com[geoi] == '\0') goto geo_error_message; diff = geoi - diff; request->geometry[j] = _xlate_coord(&com[geoi], diff); } break; } i2++; } if (request->start_req) { i2 = starti; while (com[i2]!='x' && i2<len) i2++; diff = i2-starti; request->start[0] = _xlate_coord(&com[starti], diff); for (j = 1; j < params.cluster_dims; j++) { starti += diff; if (starti == len) goto start_request; starti++; i2 = starti; if (j == (params.cluster_dims - 1)) fini_char = ' '; else fini_char = 'x'; while ((com[i2] != fini_char) && com[i2]) i2++; diff = i2 - starti; request->start[j] = _xlate_coord(&com[starti], diff); } } start_request: if(!_full_request(request, NULL, allocated_blocks)) destroy_select_ba_request(request); } return 1; geo_error_message: destroy_select_ba_request(request); memset(error_string, 0, 255); sprintf(error_string, "Error in geo dimension specified, please re-enter"); return 0; }