diff --git a/NEWS b/NEWS index 1339748d6d1f7398605709553474c0fd8a348794..912665216c971956e6dd5391af7ea0229d43decc 100644 --- a/NEWS +++ b/NEWS @@ -128,6 +128,12 @@ documents those changes that are of interest to users and admins. to modify a job's name. -- Add configuration check for sys/syslog.h and include it as needed. -- Add --propagate option to sbatch for control over limit propagation. + -- Added Gold interface to the jobacct plugin. To configure in the config + file specify... + JobAcctType=jobacct/gold + JobAcctLogFile=CLUSTER_NAME:GOLD_AUTH_KEY_FILE:GOLDD_HOST:GOLDD_PORT7112 + -- In slurmctld job record, set begin_time to time when all of a job's + dependencies are met. * Changes in SLURM 1.2.20 ========================= diff --git a/src/plugins/select/bluegene/plugin/sfree.c b/src/plugins/select/bluegene/plugin/sfree.c index 1b8ceecbe4fa27fa73743548dfe18c1ec38bbc77..6dcd10c50d03ed72872e6560c677c050cf66168f 100644 --- a/src/plugins/select/bluegene/plugin/sfree.c +++ b/src/plugins/select/bluegene/plugin/sfree.c @@ -113,7 +113,10 @@ int main(int argc, char *argv[]) bridge_init(); if (!have_db2) { - printf("must be on BG SN to resolve.\n"); + error("Required libraries can not be found " + "to access the Bluegene system.\nPlease " + "set your LD_LIBRARY_PATH correctly to " + "point to them."); exit(0); } diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index 8ce3c6a3122f9d45b29f0f0b3d09e783e2066472..16b8d2a4bb3c311d6a02cae00bfe1f394550ab88 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -918,6 +918,7 @@ static void *_slurmctld_background(void *no_data) last_sched_time = now; if (schedule()) last_checkpoint_time = 0; /* force state save */ + set_job_elig_time(); } if (difftime(now, last_trigger) > TRIGGER_INTERVAL) { diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index 5d3a1a9bba8a19ff6a5a53df8384026f1be5289e..f7e8677ca93609db31cae8a75418bfdd8fa9ab84 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -1378,13 +1378,14 @@ extern int job_allocate(job_desc_msg_t * job_specs, int immediate, error_code = _job_create(job_specs, allocate, will_run, &job_ptr, submit_uid); *job_pptr = job_ptr; + time_t now = time(NULL); if (error_code) { if (immediate && job_ptr) { job_ptr->job_state = JOB_FAILED; job_ptr->exit_code = 1; job_ptr->state_reason = FAIL_BAD_CONSTRAINTS; - job_ptr->start_time = job_ptr->end_time = time(NULL); + job_ptr->start_time = job_ptr->end_time = now; jobacct_storage_g_job_start(job_ptr); job_completion_logger(job_ptr); } @@ -1417,7 +1418,7 @@ extern int job_allocate(job_desc_msg_t * job_specs, int immediate, job_ptr->job_state = JOB_FAILED; job_ptr->exit_code = 1; job_ptr->state_reason = FAIL_BAD_CONSTRAINTS; - job_ptr->start_time = job_ptr->end_time = time(NULL); + job_ptr->start_time = job_ptr->end_time = now; jobacct_storage_g_job_start(job_ptr); job_completion_logger(job_ptr); if (!independent) @@ -1435,18 +1436,23 @@ extern int job_allocate(job_desc_msg_t * job_specs, int immediate, error_code = select_nodes(job_ptr, no_alloc, NULL); jobacct_storage_g_job_start(job_ptr); if (!test_only) { - last_job_update = time(NULL); + last_job_update = now; slurm_sched_schedule(); /* work for external scheduler */ } - if ((error_code == ESLURM_NODES_BUSY) - || (error_code == ESLURM_JOB_HELD) - || (error_code == ESLURM_REQUESTED_PART_CONFIG_UNAVAILABLE)) { + if (independent && + (job_ptr->details && (job_ptr->details->begin_time == 0)) && + ((error_code == SLURM_SUCCESS) || (error_code == ESLURM_NODES_BUSY))) + job_ptr->details->begin_time = now; + + if ((error_code == ESLURM_NODES_BUSY) || + (error_code == ESLURM_JOB_HELD) || + (error_code == ESLURM_REQUESTED_PART_CONFIG_UNAVAILABLE)) { /* Not fatal error, but job can't be scheduled right now */ if (immediate) { job_ptr->job_state = JOB_FAILED; job_ptr->exit_code = 1; job_ptr->state_reason = FAIL_BAD_CONSTRAINTS; - job_ptr->start_time = job_ptr->end_time = time(NULL); + job_ptr->start_time = job_ptr->end_time = now; job_completion_logger(job_ptr); } else { /* job remains queued */ if (error_code == ESLURM_NODES_BUSY) { @@ -1460,7 +1466,7 @@ extern int job_allocate(job_desc_msg_t * job_specs, int immediate, job_ptr->job_state = JOB_FAILED; job_ptr->exit_code = 1; job_ptr->state_reason = FAIL_BAD_CONSTRAINTS; - job_ptr->start_time = job_ptr->end_time = time(NULL); + job_ptr->start_time = job_ptr->end_time = now; job_completion_logger(job_ptr); return error_code; } @@ -1468,7 +1474,7 @@ extern int job_allocate(job_desc_msg_t * job_specs, int immediate, if (will_run) { /* job would run, flag job destruction */ job_ptr->job_state = JOB_FAILED; job_ptr->exit_code = 1; - job_ptr->start_time = job_ptr->end_time = time(NULL); + job_ptr->start_time = job_ptr->end_time = now; } return SLURM_SUCCESS; } diff --git a/src/slurmctld/job_scheduler.c b/src/slurmctld/job_scheduler.c index e4eb5a25b23f5eb2e294d4c45c9e05483e3633f3..74f096ce540d36891dd02b6d1f2526fafc08ba91 100644 --- a/src/slurmctld/job_scheduler.c +++ b/src/slurmctld/job_scheduler.c @@ -144,6 +144,46 @@ extern bool job_is_completing(void) return completing; } +/* + * set_job_elig_time - set the eligible time for pending jobs once their + * dependencies are lifted (in job->details->begin_time) + */ +extern void set_job_elig_time(void) +{ + struct job_record *job_ptr = NULL; + struct part_record *part_ptr = NULL; + ListIterator job_iterator; + slurmctld_lock_t job_write_lock = + { READ_LOCK, WRITE_LOCK, WRITE_LOCK, READ_LOCK }; + time_t now = time(NULL); + + lock_slurmctld(job_write_lock); + job_iterator = list_iterator_create(job_list); + while ((job_ptr = (struct job_record *) list_next(job_iterator))) { + part_ptr = job_ptr->part_ptr; + if (job_ptr->job_state != JOB_PENDING) + continue; + if (part_ptr == NULL) + continue; + if ((job_ptr->details == NULL) || job_ptr->details->begin_time) + continue; + if (part_ptr->state_up == 0) + continue; + if ((job_ptr->time_limit != NO_VAL) && + (job_ptr->time_limit > part_ptr->max_time)) + continue; + if ((job_ptr->details->max_nodes != 0) && + ((job_ptr->details->max_nodes < part_ptr->min_nodes) || + (job_ptr->details->min_nodes > part_ptr->max_nodes))) + continue; + if (!job_independent(job_ptr)) + continue; + job_ptr->details->begin_time = now; + } + list_iterator_destroy(job_iterator); + unlock_slurmctld(job_write_lock); +} + /* * schedule - attempt to schedule all pending jobs * pending jobs for each partition will be scheduled in priority diff --git a/src/slurmctld/node_scheduler.c b/src/slurmctld/node_scheduler.c index 3c1231b92735f98c8a7d974fed8e45a26be4d8fd..3a420fb94bfc7863da0acc792787c2348fba96b0 100644 --- a/src/slurmctld/node_scheduler.c +++ b/src/slurmctld/node_scheduler.c @@ -1148,6 +1148,7 @@ extern int select_nodes(struct job_record *job_ptr, bool test_only, uint32_t min_nodes, max_nodes, req_nodes; int super_user = false; enum job_state_reason fail_reason; + time_t now = time(NULL); xassert(job_ptr); xassert(job_ptr->magic == JOB_MAGIC); @@ -1181,7 +1182,7 @@ extern int select_nodes(struct job_record *job_ptr, bool test_only, fail_reason = WAIT_PART_NODE_LIMIT; if (fail_reason != WAIT_NO_REASON) { job_ptr->state_reason = fail_reason; - last_job_update = time(NULL); + last_job_update = now; if (job_ptr->priority == 0) /* user/admin hold */ return ESLURM_JOB_HELD; job_ptr->priority = 1; /* sys hold, move to end of queue */ @@ -1248,7 +1249,7 @@ extern int select_nodes(struct job_record *job_ptr, bool test_only, job_ptr->job_id); if (job_ptr->priority != 0) /* Move to end of queue */ job_ptr->priority = 1; - last_job_update = time(NULL); + last_job_update = now; } else if (error_code == ESLURM_NODES_BUSY) slurm_sched_job_is_pending(); goto cleanup; @@ -1284,7 +1285,7 @@ extern int select_nodes(struct job_record *job_ptr, bool test_only, error("select_g_update_nodeinfo(%u): %m", job_ptr->job_id); /* not critical ... by now */ } - job_ptr->start_time = job_ptr->time_last_active = time(NULL); + job_ptr->start_time = job_ptr->time_last_active = now; if (job_ptr->time_limit == NO_VAL) job_ptr->time_limit = part_ptr->max_time; if (job_ptr->time_limit == INFINITE) @@ -1719,6 +1720,7 @@ extern void build_node_details(struct job_record *job_ptr) int error_code = SLURM_SUCCESS; int node_inx = 0, cpu_inx = -1; int cr_count = 0; + uint32_t total_procs = 0; if ((job_ptr->node_bitmap == NULL) || (job_ptr->nodes == NULL)) { /* No nodes allocated, we're done... */ @@ -1768,6 +1770,7 @@ extern void build_node_details(struct job_record *job_ptr) job_ptr->cpus_per_node[cpu_inx] = job_ptr->num_procs; + total_procs += job_ptr->num_procs; job_ptr->cpu_count_reps[cpu_inx] = 1; job_ptr->alloc_lps[0] = job_ptr->num_procs; job_ptr->used_lps[0] = 0; @@ -1803,7 +1806,8 @@ extern void build_node_details(struct job_record *job_ptr) job_ptr->cpu_count_reps[cpu_inx] = 1; } else job_ptr->cpu_count_reps[cpu_inx]++; - + total_procs += usable_lps; + } else { error("Invalid node %s in JobId=%u", this_node_name, job_ptr->job_id); @@ -1819,6 +1823,8 @@ extern void build_node_details(struct job_record *job_ptr) job_ptr->job_id, job_ptr->node_cnt, node_inx); } job_ptr->num_cpu_groups = cpu_inx + 1; + if (job_ptr->details) + job_ptr->details->total_procs = total_procs; } /* diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h index 7521fe356f0062a5aff921b4343fd77ee9e96d55..e60860582910b6c458643e1f757cef9a6862129b 100644 --- a/src/slurmctld/slurmctld.h +++ b/src/slurmctld/slurmctld.h @@ -320,7 +320,9 @@ struct job_details { uint32_t total_procs; /* number of allocated processors, for accounting */ time_t submit_time; /* time of submission */ - time_t begin_time; /* start after this time */ + time_t begin_time; /* start at this time (srun --being), + * resets to time first eligible + * (all dependencies satisfied) */ char *work_dir; /* pathname of working directory */ char **argv; /* arguments for a batch job script */ uint16_t argc; /* count of argv elements */ @@ -350,7 +352,7 @@ struct job_record { char *nodes_completing; /* nodes still in completing state * for this job, used to insure * epilog is not re-run for job */ - uint32_t num_procs; /* count of required/allocated processors */ + uint32_t num_procs; /* count of required processors */ uint32_t time_limit; /* time_limit minutes or INFINITE, * NO_VAL implies partition max_time */ time_t start_time; /* time execution begins, @@ -1249,6 +1251,12 @@ extern void save_all_state(void); */ extern int schedule (void); +/* + * set_job_elig_time - set the eligible time for pending jobs once their + * dependencies are lifted (in job->details->begin_time) + */ +extern void set_job_elig_time(void); + /* * set_node_down - make the specified node's state DOWN if possible * (not in a DRAIN state), kill jobs as needed diff --git a/src/smap/smap.c b/src/smap/smap.c index e66bd702f85c6f5d233fbfd19afb76d7ed3fe522..be0c3473a5b316e0b05eb9d946e2844631209949 100644 --- a/src/smap/smap.c +++ b/src/smap/smap.c @@ -64,7 +64,7 @@ int main_xcord = 1; int main_ycord = 1; WINDOW *grid_win = NULL; WINDOW *text_win = NULL; - + /************ * Functions * ************/ @@ -111,7 +111,10 @@ int main(int argc, char *argv[]) #ifdef HAVE_BG_FILES if (!have_db2) { - printf("must be on BG SN to resolve.\n"); + printf("Required libraries can not be found " + "to access the Bluegene system.\nPlease " + "set your LD_LIBRARY_PATH correctly to " + "point to them.\n"); goto part_fini; } @@ -149,7 +152,7 @@ int main(int argc, char *argv[]) } part_fini: #else - printf("must be on BG SN to resolve.\n"); + printf("Must be on BG System to resolve.\n"); #endif ba_fini(); exit(0); @@ -245,7 +248,7 @@ part_fini: break; #else default: - error("must be on a BG SYSTEM to run this command"); + error("Must be on a BG SYSTEM to run this command"); endwin(); ba_fini(); exit(0);