diff --git a/src/api/allocate.c b/src/api/allocate.c index ef61fcf527a4cd1838b09fcf76bc36ba831aafd8..8fb5cfaf04368c0f222f3343f66bb28cef8631a1 100644 --- a/src/api/allocate.c +++ b/src/api/allocate.c @@ -32,7 +32,7 @@ main (int argc, char *argv[]) char *node_list, *job_id; error_code = slurm_allocate - ("User=1500 Script=/bin/hostname JobName=job01 TotalNodes=400 TotalProcs=1000 ReqNodes=lx[3000-3003] Partition=batch MinRealMemory=1024 MinTmpDisk=2034 Groups=students,employee MinProcs=4 Contiguous=YES Key=1234", + ("User=1500 JobName=job01 TotalNodes=400 TotalProcs=1000 ReqNodes=lx[3000-3003] Partition=batch MinRealMemory=1024 MinTmpDisk=2034 Groups=students,employee MinProcs=4 Contiguous=YES Key=1234", &node_list, &job_id); if (error_code) printf ("allocate error %d\n", error_code); @@ -44,7 +44,7 @@ main (int argc, char *argv[]) while (1) { error_code = slurm_allocate - ("User=1500 Script=/bin/hostname JobName=more TotalProcs=4000 Partition=batch Key=1234 ", + ("User=1500 JobName=more TotalProcs=4000 Partition=batch Key=1234 ", &node_list, &job_id); if (error_code) { printf ("allocate error %d\n", error_code); @@ -59,7 +59,7 @@ main (int argc, char *argv[]) while (1) { error_code = slurm_allocate - ("User=1500 Script=/bin/hostname JobName=more TotalProcs=40 Partition=batch Key=1234 ", + ("User=1500 JobName=more TotalProcs=40 Partition=batch Key=1234 ", &node_list, &job_id); if (error_code) { printf ("allocate error %d\n", error_code); @@ -84,7 +84,7 @@ main (int argc, char *argv[]) * output: job_id - node_list - list of allocated nodes * returns 0 if no error, EINVAL if the request is invalid, * EAGAIN if the request can not be satisfied at present - * NOTE: required specifications include: User=<uid> Script=<pathname> + * NOTE: required specifications include: User=<uid> * optional specifications include: Contiguous=<YES|NO> * Distribution=<BLOCK|CYCLE> Features=<features> Groups=<groups> * JobId=<id> JobName=<name> Key=<credential> MinProcs=<count> diff --git a/src/api/node_info.c b/src/api/node_info.c index 6718800e2f1207236c4538cce1605a14daa193b2..e825248f8346621708266dff6c01a79ead162546 100644 --- a/src/api/node_info.c +++ b/src/api/node_info.c @@ -174,7 +174,7 @@ slurm_load_node (time_t update_time, struct node_buffer **node_buffer_ptr) unpackstr_ptr (&node[i].name, &uint16_tmp, &buf_ptr, &buffer_size); if (node[i].name == NULL) node[i].name = ""; - unpack32 (&node[i].node_state, &buf_ptr, &buffer_size); + unpack16 (&node[i].node_state, &buf_ptr, &buffer_size); unpack32 (&node[i].cpus, &buf_ptr, &buffer_size); unpack32 (&node[i].real_memory, &buf_ptr, &buffer_size); unpack32 (&node[i].tmp_disk, &buf_ptr, &buffer_size); diff --git a/src/api/submit.c b/src/api/submit.c index 5c2097a947ed55dced75a5d65717c9a59ed20274..3c39771653f9291d25f8a59bc6614aa3310f67d1 100644 --- a/src/api/submit.c +++ b/src/api/submit.c @@ -68,6 +68,7 @@ main (int argc, char *argv[]) * job_id - place to store id of submitted job * output: job_id - the job's id * returns 0 if no error, EINVAL if the request is invalid + * NOTE: the caller must free the storage at job_id[0] * NOTE: required specification include: Script=<script_path_name> * User=<uid> * NOTE: optional specifications include: Contiguous=<YES|NO> @@ -76,7 +77,7 @@ main (int argc, char *argv[]) * MinRealMemory=<MB> MinTmpDisk=<MB> Partition=<part_name> * Priority=<integer> ProcsPerTask=<count> ReqNodes=<node_list> * Shared=<YES|NO> TimeLimit=<minutes> TotalNodes=<count> - * TotalProcs=<count> + * TotalProcs=<count> Immediate=<YES|NO> */ int slurm_submit (char *spec, char **job_id) diff --git a/src/common/slurm.h b/src/common/slurm.h index 7fc22650b4766cbdc399670e78164214ecdc3cf9..5f0cddf98377014c558fd128e78db7924d08afdf 100644 --- a/src/common/slurm.h +++ b/src/common/slurm.h @@ -74,7 +74,7 @@ extern time_t last_node_update; /* time of last update to node records */ struct node_record { uint32_t magic; /* magic cookie to test data integrity */ char name[MAX_NAME_LEN]; /* name of the node. a null name indicates defunct node */ - int node_state; /* enum node_states, negative if down */ + uint16_t node_state; /* enum node_states, ORed with STATE_NO_RESPOND if down */ time_t last_response; /* last response from the node */ uint32_t cpus; /* actual count of cpus running on the node */ uint32_t real_memory; /* actual megabytes of real memory on the node */ @@ -398,12 +398,13 @@ extern int job_cancel (char * job_id); * new_job_id - location for storing new job's id * output: new_job_id - the job's ID * returns 0 on success, EINVAL if specification is invalid + * allocate - if set, job allocation only (no script required) * globals: job_list - pointer to global job list * list_part - global list of partition info * default_part_loc - pointer to default partition * NOTE: the calling program must xfree the memory pointed to by new_job_id */ -extern int job_create (char *job_specs, char **new_job_id); +extern int job_create (char *job_specs, char **new_job_id, int allocate); /* job_lock - lock the job information */ extern void job_lock (); diff --git a/src/common/slurmlib.h b/src/common/slurmlib.h index a06f290ae4def5f6ca15658a0eae1b3894d8f0b5..861b40575490336f6e486deafff5bc2ed08cbbfe 100644 --- a/src/common/slurmlib.h +++ b/src/common/slurmlib.h @@ -15,6 +15,7 @@ #define PART_STRUCT_VERSION 1 #define SLURMCTLD_HOST "134.9.55.42" #define SLURMCTLD_PORT 1543 +#define STATE_NO_RESPOND 0x8000 /* INFINITE is used to identify unlimited configurations, */ /* eg. the maximum count of nodes any job may use in some partition */ @@ -38,8 +39,7 @@ enum task_dist { }; /* last entry must be STATE_END, keep in sync with node_state_string */ -/* any value less than or equal to zero is down. if a node was in state */ -/* STATE_BUSY and stops responding, its state becomes -(STATE_BUSY), etc. */ +/* if a node ceases to respond, its last state is ORed with STATE_NO_RESPOND */ enum node_states { STATE_DOWN, /* node is not responding */ STATE_UNKNOWN, /* node's initial state, unknown */ @@ -115,7 +115,7 @@ struct job_buffer { struct node_table { char *name; /* name of the node. a null name indicates defunct node */ - uint32_t node_state; /* state of the node, see node_states */ + uint16_t node_state; /* state of the node, see node_states */ uint32_t cpus; /* count of processors running on the node */ uint32_t real_memory; /* megabytes of real memory on the node */ uint32_t tmp_disk; /* megabytes of total disk in TMP_FS */ @@ -137,9 +137,9 @@ struct part_table { uint32_t max_nodes; /* per job or INFINITE */ uint32_t total_nodes; /* total number of nodes in the partition */ uint32_t total_cpus; /* total number of cpus in the partition */ - uint16_t default_part; /* 1 if if this is default partition */ + uint16_t default_part; /* 1 if this is default partition */ uint16_t key; /* 1 if slurm distributed key is required for use */ - uint16_t shared; /* 1 if >1 job can share a node, 2 if required */ + uint16_t shared; /* 1 if job can share nodes, 2 if job must share nodes */ uint16_t state_up; /* 1 if state is up, 0 if down */ char *nodes; /* comma delimited list names of nodes in partition */ int *node_inx; /* list index pairs into node_table: @@ -161,7 +161,7 @@ struct part_buffer { * output: job_id - node_list - list of allocated nodes * returns 0 if no error, EINVAL if the request is invalid, * EAGAIN if the request can not be satisfied at present - * NOTE: required specifications include: User=<uid> Script=<pathname> + * NOTE: required specifications include: User=<uid> * optional specifications include: Contiguous=<YES|NO> * Distribution=<BLOCK|CYCLE> Features=<features> Groups=<groups> * JobId=<id> JobName=<name> Key=<credential> MinProcs=<count> @@ -170,6 +170,7 @@ struct part_buffer { * Shared=<YES|NO> TimeLimit=<minutes> TotalNodes=<count> * TotalProcs=<count> * NOTE: the calling function must free the allocated storage at node_list[0] + * NOTE: the calling function must free the allocated storage at job_id[0] */ extern int slurm_allocate (char *spec, char **node_list, char **job_id); @@ -269,6 +270,7 @@ extern int slurm_load_part (time_t update_time, struct part_buffer **part_buffer * job_id - place to store id of submitted job * output: job_id - the job's id * returns 0 if no error, EINVAL if the request is invalid + * NOTE: the caller must free the storage at job_id[0] * NOTE: required specification include: Script=<script_path_name> * User=<uid> * NOTE: optional specifications include: Contiguous=<YES|NO> @@ -277,10 +279,29 @@ extern int slurm_load_part (time_t update_time, struct part_buffer **part_buffer * MinRealMemory=<MB> MinTmpDisk=<MB> Partition=<part_name> * Priority=<integer> ProcsPerTask=<count> ReqNodes=<node_list> * Shared=<YES|NO> TimeLimit=<minutes> TotalNodes=<count> - * TotalProcs=<count> + * TotalProcs=<count> Immediate=<YES|NO> */ extern int slurm_submit (char *spec, char **job_id); +/* + * slurm_will_run - determine if a job would execute immediately + * if submitted. + * input: spec - specification of the job's constraints + * job_id - place to store id of submitted job + * output: returns 0 if job would run now, EINVAL if the request + * would never run, EAGAIN if job would run later + * NOTE: required specification include: Script=<script_path_name> + * User=<uid> + * NOTE: optional specifications include: Contiguous=<YES|NO> + * Features=<features> Groups=<groups> + * Key=<key> MinProcs=<count> + * MinRealMemory=<MB> MinTmpDisk=<MB> Partition=<part_name> + * Priority=<integer> ReqNodes=<node_list> + * Shared=<YES|NO> TimeLimit=<minutes> TotalNodes=<count> + * TotalProcs=<count> + */ +extern int slurm_will_run (char *spec, char **job_id); + /* * parse_node_name - parse the node name for regular expressions and return a sprintf format * generate multiple node names as needed. diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index 69c914ce9848f9947e001e2c958d1042af97c1f2..15509745a4f28dbda8ce2f65332bced7f476d0b8 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -366,7 +366,7 @@ slurmctld_req (int sockfd) { /* JobSubmit - submit a job to the slurm queue */ else if (strncmp ("JobSubmit", in_line, 9) == 0) { time_stamp = NULL; - error_code = job_create(&in_line[9], &job_id_ptr); /* skip "JobSubmit" */ + error_code = job_create(&in_line[9], &job_id_ptr, 0); /* skip "JobSubmit" */ if (error_code) info ("slurmctld_req: job_submit error %d, time=%ld", error_code, (long) (clock () - start_time)); diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index 81092fbde86311c140fedbe7c97c60036ea89d59..451b35685c7adf6cbd463da81d51c15b901531f1 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -291,7 +291,7 @@ job_allocate (char *job_specs, char **new_job_id, char **node_list) new_job_id[0] = node_list[0] = NULL; - error_code = job_create (job_specs, new_job_id); + error_code = job_create (job_specs, new_job_id, 1); if (error_code) return error_code; job_ptr = find_job_record (new_job_id[0]); @@ -361,13 +361,14 @@ job_cancel (char * job_id) * new_job_id - location for storing new job's id * output: new_job_id - the job's ID * returns 0 on success, EINVAL if specification is invalid + * allocate - if set, job allocation only (no script required) * globals: job_list - pointer to global job list * list_part - global list of partition info * default_part_loc - pointer to default partition * NOTE: the calling program must xfree the memory pointed to by new_job_id */ int -job_create (char *job_specs, char **new_job_id) +job_create (char *job_specs, char **new_job_id, int allocate) { char *req_features, *req_node_list, *job_name, *req_group; char *req_partition, *script, *job_id; @@ -408,7 +409,7 @@ job_create (char *job_specs, char **new_job_id) error_code = EINVAL; goto cleanup; } - if (script == NULL) { + if (allocate == 0 && script == NULL) { info ("job_create: job failed to specify Script"); error_code = EINVAL; goto cleanup; @@ -1084,7 +1085,6 @@ reset_job_bitmaps () list_iterator_destroy (job_record_iterator); last_job_update = time (NULL); - return 0; } diff --git a/src/slurmctld/node_mgr.c b/src/slurmctld/node_mgr.c index 68f5bf42ced1dce37e474e117ea50a4ab7cf7554..12b594ebaf85c03a4633688ca1c2a763111fea9c 100644 --- a/src/slurmctld/node_mgr.c +++ b/src/slurmctld/node_mgr.c @@ -1002,15 +1002,10 @@ pack_all_node (char **buffer_ptr, int *buffer_size, time_t * update_time) int pack_node (struct node_record *dump_node_ptr, void **buf_ptr, int *buf_len) { - int state; char *partition = NULL; - state = dump_node_ptr->node_state; - if (state < 0) - state = STATE_DOWN; - packstr (dump_node_ptr->name, buf_ptr, buf_len); - pack32 (state, buf_ptr, buf_len); + pack16 (dump_node_ptr->node_state, buf_ptr, buf_len); pack32 (dump_node_ptr->cpus, buf_ptr, buf_len); pack32 (dump_node_ptr->real_memory, buf_ptr, buf_len); pack32 (dump_node_ptr->tmp_disk, buf_ptr, buf_len); @@ -1171,22 +1166,27 @@ update_node (char *node_names, char *spec) } if (state_val != NO_VAL) { - if ((state_val == STATE_DOWN) && - (node_record_point->node_state != STATE_UNKNOWN)) - node_record_point->node_state = - -(node_record_point->node_state); - else - node_record_point->node_state = state_val; - if (state_val != STATE_IDLE) + if (state_val == STATE_DOWN) { + bit_clear (up_node_bitmap, + (int) (node_record_point - + node_record_table_ptr)); bit_clear (idle_node_bitmap, (int) (node_record_point - node_record_table_ptr)); - if (state_val == STATE_DOWN) - bit_clear (up_node_bitmap, + } + else if (state_val != STATE_IDLE) + bit_clear (idle_node_bitmap, (int) (node_record_point - node_record_table_ptr)); + else /* (state_val == STATE_IDLE) */ + bit_set (idle_node_bitmap, + (int) (node_record_point - + node_record_table_ptr)); + + node_record_point->node_state = state_val; info ("update_node: node %s state set to %s", - &node_list[i*MAX_NAME_LEN], node_state_string[state_val]); + &node_list[i*MAX_NAME_LEN], + node_state_string[state_val]); } } @@ -1250,11 +1250,10 @@ validate_node_specs (char *node_name, uint32_t cpus, } else { info ("validate_node_specs: node %s has registered", node_name); + node_ptr->node_state &= (uint16_t) (~STATE_NO_RESPOND); if ((node_ptr->node_state == STATE_DOWN) || (node_ptr->node_state == STATE_UNKNOWN)) node_ptr->node_state = STATE_IDLE; - if (node_ptr->node_state < 0) - node_ptr->node_state = -(node_ptr->node_state); bit_set (up_node_bitmap, (node_ptr - node_record_table_ptr)); } diff --git a/src/slurmctld/read_config.c b/src/slurmctld/read_config.c index 8eeba6917d9649b24feae0bb70128a8020a4011b..d3e1d9d5cd147a455d7e57f4f51f64d8397cdd0c 100644 --- a/src/slurmctld/read_config.c +++ b/src/slurmctld/read_config.c @@ -207,7 +207,8 @@ build_bitmaps () { continue; /* defunct */ if (node_record_table_ptr[i].node_state == STATE_IDLE) bit_set (idle_node_bitmap, i); - if (node_record_table_ptr[i].node_state > STATE_DOWN) + if ((node_record_table_ptr[i].node_state != STATE_DOWN) && + ((node_record_table_ptr[i].node_state & STATE_NO_RESPOND) == 0)) bit_set (up_node_bitmap, i); if (node_record_table_ptr[i].config_ptr) bit_set (node_record_table_ptr[i].config_ptr->node_bitmap, i);