diff --git a/NEWS b/NEWS index 22e5a08d22f1247298a589fb810eb942ebee7ae9..16162cbe653f40cc7725c16973cdc7a561ea20b8 100644 --- a/NEWS +++ b/NEWS @@ -111,6 +111,9 @@ documents those changes that are of interest to users and admins. together across clusters or within clusters that are not related. Use the --wckey option in srun, sbatch or salloc or set the SLURM_WCKEY env var to have this set. Use sreport with the wckey option to view reports. + THIS CHANGES THE RPC LEVEL IN THE SLURMDBD. YOU MUST UPGRADE YOUR SLURMDBD + BEFORE YOU UPGRADE THE REST OF YOUR CLUSTERS. THE NEW SLURMDBD WILL TALK + TO OLDER VERSIONS OF SLURM FINE. -- Added configuration parameter BatchStartTimeout to control how long to allow for a batch job prolog and environment loading (for Moab) to run. See "man slurm.conf" for details. diff --git a/src/common/assoc_mgr.c b/src/common/assoc_mgr.c index a823c6ad059f64c5833a8d057600829439a38be6..4bd59e1a63773e49d5f4363f8a3910fea329afc6 100644 --- a/src/common/assoc_mgr.c +++ b/src/common/assoc_mgr.c @@ -930,7 +930,7 @@ extern int assoc_mgr_fill_in_assoc(void *db_conn, acct_association_rec_t *assoc, } assoc->user = user.name; assoc->acct = user.default_acct; - } + } if(!assoc->cluster) assoc->cluster = assoc_mgr_cluster_name; @@ -1220,7 +1220,17 @@ extern int assoc_mgr_fill_in_wckey(void *db_conn, acct_wckey_rec_t *wckey, } wckey->user = user.name; wckey->name = user.default_wckey; - } + } else if(wckey->uid == (uint32_t)NO_VAL) { + if(enforce) { + error("get_wckey_id: " + "Not enough info 2 to " + "get an wckey"); + return SLURM_ERROR; + } else { + return SLURM_SUCCESS; + } + } + if(!wckey->cluster) wckey->cluster = assoc_mgr_cluster_name; @@ -1273,7 +1283,7 @@ extern int assoc_mgr_fill_in_wckey(void *db_conn, acct_wckey_rec_t *wckey, else return SLURM_SUCCESS; } - debug3("found correct wckey"); + debug3("found correct wckey %u", ret_wckey->id); if (wckey_pptr) *wckey_pptr = ret_wckey; diff --git a/src/common/hostlist.c b/src/common/hostlist.c index 1d05091df777ca8d224dba2e466adc4bd8d6dc49..4ab2a8700c42fa6d160fe279adbf91f9cef09f54 100644 --- a/src/common/hostlist.c +++ b/src/common/hostlist.c @@ -1678,7 +1678,7 @@ static int _push_range_list(hostlist_t hl, char *prefix, struct _range *range, int n) { - int i, j, k, nr; + int i, k, nr; char *p, *q; char new_prefix[1024], tmp_prefix[1024]; @@ -1687,6 +1687,7 @@ _push_range_list(hostlist_t hl, char *prefix, struct _range *range, ((q = strrchr(p, ']')) != NULL)) { struct _range prefix_range[MAX_RANGES]; struct _range *saved_range = range, *pre_range = prefix_range; + unsigned long j, prefix_cnt = 0; *p++ = '\0'; *q++ = '\0'; if (strrchr(tmp_prefix, '[') != NULL) @@ -1695,9 +1696,16 @@ _push_range_list(hostlist_t hl, char *prefix, struct _range *range, if (nr < 0) return -1; /* bad numeric expression */ for (i = 0; i < nr; i++) { + prefix_cnt += pre_range->hi - pre_range->lo + 1; + if (prefix_cnt > MAX_PREFIX_CNT) { + /* Prevent overflow of memory with user input + * of something like "a[0-999999999].b[0-9]" */ + return -1; + } for (j = pre_range->lo; j <= pre_range->hi; j++) { snprintf(new_prefix, sizeof(new_prefix), - "%s%d%s", tmp_prefix, j, q); + "%s%0*lu%s", tmp_prefix, + pre_range->width, j, q); range = saved_range; for (k = 0; k < n; k++) { hostlist_push_hr(hl, new_prefix, @@ -1748,17 +1756,14 @@ _hostlist_create_bracketed(const char *hostlist, char *sep, char *r_op) *p++ = '\0'; if ((q = strchr(p, ']'))) { - if ((q[1] != ',') && (q[1] != '\0')) { - errno = EINVAL; /* Invalid suffix */ + if ((q[1] != ',') && (q[1] != '\0')) goto error; - } *q = '\0'; nr = _parse_range_list(p, ranges, MAX_RANGES); if (nr < 0) goto error; if (_push_range_list(new, prefix, ranges, nr)) goto error; - } else { /* The hostname itself contains a '[' @@ -1775,7 +1780,7 @@ _hostlist_create_bracketed(const char *hostlist, char *sep, char *r_op) return new; error: - err = errno; + err = errno = EINVAL; hostlist_destroy(new); free(orig); seterrno_ret(err, NULL); diff --git a/src/common/hostlist.h b/src/common/hostlist.h index 41a8501899e651115922d83d7309dd07656160de..2f4d074a8da4359df4f46bb020477573b58e3b9e 100644 --- a/src/common/hostlist.h +++ b/src/common/hostlist.h @@ -45,6 +45,12 @@ /* max size of internal hostrange buffer */ #define MAXHOSTRANGELEN 8192 +/* Since users can specify a numeric range in the prefix, we need to prevent + * expressions that can consume all of the memory on a system and crash the + * daemons (e.g. "a[0-999999999].b[0-9]", which generates 1 billion distinct + * prefix records in the hostlist) */ +#define MAX_PREFIX_CNT 1024 + #ifdef HAVE_BG #define HOSTLIST_BASE 36 #else diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c index 5d9de3521e3435f30934a2d84ee34aecfc4d498e..eeb0c3b7bb12a7f3a1dbd3e27c76c4699046321a 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c @@ -143,6 +143,9 @@ extern List acct_storage_p_get_associations( mysql_conn_t *mysql_conn, uid_t uid, acct_association_cond_t *assoc_cond); +extern List acct_storage_p_get_wckeys(mysql_conn_t *mysql_conn, uid_t uid, + acct_wckey_cond_t *wckey_cond); + extern int acct_storage_p_get_usage(mysql_conn_t *mysql_conn, uid_t uid, void *in, slurmdbd_msg_type_t type, time_t start, time_t end); @@ -6600,6 +6603,7 @@ extern List acct_storage_p_get_users(mysql_conn_t *mysql_conn, uid_t uid, MYSQL_ROW row; uint16_t private_data = 0; acct_user_rec_t user; + acct_wckey_cond_t *wckey_cond = NULL; /* if this changes you will need to edit the corresponding enum */ char *user_req_inx[] = { @@ -6739,11 +6743,28 @@ empty: this list in the user->name so we don't free it here */ + if(!user_cond->assoc_cond) + user_cond->assoc_cond = xmalloc( + sizeof(acct_association_cond_t)); + if(user_cond->assoc_cond->user_list) list_destroy(user_cond->assoc_cond->user_list); user_cond->assoc_cond->user_list = list_create(NULL); } + if(user_cond && user_cond->with_wckeys) { + /* We are going to be freeing the inners of + this list in the user->name so we don't + free it here + */ + wckey_cond = xmalloc(sizeof(acct_wckey_cond_t)); + wckey_cond->user_list = list_create(NULL); + + if(user_cond->assoc_cond && user_cond->assoc_cond->cluster_list) + wckey_cond->cluster_list = + user_cond->assoc_cond->cluster_list; + } + while((row = mysql_fetch_row(result))) { acct_user_rec_t *user = xmalloc(sizeof(acct_user_rec_t)); /* uid_t pw_uid; */ @@ -6751,8 +6772,11 @@ empty: user->name = xstrdup(row[USER_REQ_NAME]); user->default_acct = xstrdup(row[USER_REQ_DA]); - if(row[USER_REQ_DW] && row[USER_REQ_DW][0]) + if(row[USER_REQ_DW]) user->default_wckey = xstrdup(row[USER_REQ_DW]); + else + user->default_wckey = xstrdup(""); + user->admin_level = atoi(row[USER_REQ_AL]); /* user id will be set on the client since this could be on a @@ -6765,19 +6789,16 @@ empty: /* else */ /* user->uid = passwd_ptr->pw_uid; */ - if(user_cond && user_cond->with_coords) { + if(user_cond && user_cond->with_coords) _get_user_coords(mysql_conn, user); - } - - if(user_cond && user_cond->with_assocs) { - if(!user_cond->assoc_cond) { - user_cond->assoc_cond = xmalloc( - sizeof(acct_association_cond_t)); - } + + if(user_cond && user_cond->with_assocs) list_append(user_cond->assoc_cond->user_list, user->name); - } + + if(user_cond && user_cond->with_wckeys) + list_append(wckey_cond->user_list, user->name); } mysql_free_result(result); @@ -6791,7 +6812,7 @@ empty: if(!assoc_list) { error("no associations"); - return user_list; + goto get_wckeys; } itr = list_iterator_create(user_list); @@ -6808,8 +6829,6 @@ empty: list_remove(assoc_itr); } list_iterator_reset(assoc_itr); - if(!user->assoc_list) - list_remove(itr); } list_iterator_destroy(itr); list_iterator_destroy(assoc_itr); @@ -6817,6 +6836,43 @@ empty: list_destroy(assoc_list); } +get_wckeys: + if(wckey_cond) { + ListIterator wckey_itr = NULL; + acct_user_rec_t *user = NULL; + acct_wckey_rec_t *wckey = NULL; + List wckey_list = acct_storage_p_get_wckeys( + mysql_conn, uid, wckey_cond); + + wckey_cond->cluster_list = NULL; + destroy_acct_wckey_cond(wckey_cond); + + if(!wckey_list) { + error("no wckeys"); + return user_list; + } + + itr = list_iterator_create(user_list); + wckey_itr = list_iterator_create(wckey_list); + while((user = list_next(itr))) { + while((wckey = list_next(wckey_itr))) { + if(strcmp(wckey->user, user->name)) + continue; + + if(!user->wckey_list) + user->wckey_list = list_create( + destroy_acct_wckey_rec); + list_append(user->wckey_list, wckey); + list_remove(wckey_itr); + } + list_iterator_reset(wckey_itr); + } + list_iterator_destroy(itr); + list_iterator_destroy(wckey_itr); + + list_destroy(wckey_list); + } + return user_list; #else return NULL; @@ -8085,8 +8141,11 @@ empty: wckey->id = atoi(row[WCKEY_REQ_ID]); wckey->user = xstrdup(row[WCKEY_REQ_USER]); - if(row[WCKEY_REQ_NAME] && row[WCKEY_REQ_NAME][0]) + /* we want a blank wckey if the name is null */ + if(row[WCKEY_REQ_NAME]) wckey->name = xstrdup(row[WCKEY_REQ_NAME]); + else + wckey->name = xstrdup(""); wckey->cluster = xstrdup(row[WCKEY_REQ_CLUSTER]); @@ -9491,6 +9550,7 @@ extern int jobacct_storage_p_job_start(mysql_conn_t *mysql_conn, mysql_free_result(result); list_destroy(wckey_list); } + //info("got wckeyid of %d", wckey_rec.id); wckeyid = wckey_rec.id; } no_wckeyid: diff --git a/src/sacctmgr/cluster_functions.c b/src/sacctmgr/cluster_functions.c index cead7eb9040129fc568713e8095e4a8f50c3c9bc..400eefb86835675a5d8e12b99e0baeb20b46e939 100644 --- a/src/sacctmgr/cluster_functions.c +++ b/src/sacctmgr/cluster_functions.c @@ -907,35 +907,6 @@ extern int sacctmgr_dump_cluster (int argc, char *argv[]) int i, command_len = 0; FILE *fd = NULL; - memset(&user_cond, 0, sizeof(acct_user_cond_t)); - user_cond.with_coords = 1; - - user_list = acct_storage_g_get_users(db_conn, my_uid, &user_cond); - /* make sure this person running is an admin */ - user_name = uid_to_string(my_uid); - if(!(user = sacctmgr_find_user_from_list(user_list, user_name))) { - exit_code=1; - fprintf(stderr, " Your uid (%u) is not in the " - "accounting system, can't dump cluster.\n", my_uid); - xfree(user_name); - if(user_list) - list_destroy(user_list); - return SLURM_ERROR; - - } else { - if(my_uid != slurm_get_slurm_user_id() && my_uid != 0 - && user->admin_level < ACCT_ADMIN_SUPER_USER) { - exit_code=1; - fprintf(stderr, " Your user does not have sufficient " - "privileges to dump clusters.\n"); - if(user_list) - list_destroy(user_list); - xfree(user_name); - return SLURM_ERROR; - } - } - xfree(user_name); - for (i=0; i<argc; i++) { int end = parse_option_end(argv[i]); int option = 0; @@ -986,12 +957,47 @@ extern int sacctmgr_dump_cluster (int argc, char *argv[]) printf(" No filename given, using %s.\n", file_name); } + memset(&user_cond, 0, sizeof(acct_user_cond_t)); + user_cond.with_coords = 1; + user_cond.with_wckeys = 1; + memset(&assoc_cond, 0, sizeof(acct_association_cond_t)); assoc_cond.without_parent_limits = 1; assoc_cond.with_raw_qos = 1; assoc_cond.cluster_list = list_create(NULL); list_append(assoc_cond.cluster_list, cluster_name); + /* this is needed for getting the correct wckeys */ + user_cond.assoc_cond = &assoc_cond; + + user_list = acct_storage_g_get_users(db_conn, my_uid, &user_cond); + /* make sure this person running is an admin */ + user_name = uid_to_string(my_uid); + if(!(user = sacctmgr_find_user_from_list(user_list, user_name))) { + exit_code=1; + fprintf(stderr, " Your uid (%u) is not in the " + "accounting system, can't dump cluster.\n", my_uid); + xfree(user_name); + if(user_list) + list_destroy(user_list); + list_destroy(assoc_cond.cluster_list); + return SLURM_ERROR; + + } else { + if(my_uid != slurm_get_slurm_user_id() && my_uid != 0 + && user->admin_level < ACCT_ADMIN_SUPER_USER) { + exit_code=1; + fprintf(stderr, " Your user does not have sufficient " + "privileges to dump clusters.\n"); + if(user_list) + list_destroy(user_list); + xfree(user_name); + list_destroy(assoc_cond.cluster_list); + return SLURM_ERROR; + } + } + xfree(user_name); + /* assoc_cond is set up above */ assoc_list = acct_storage_g_get_associations(db_conn, my_uid, &assoc_cond); @@ -1013,7 +1019,6 @@ extern int sacctmgr_dump_cluster (int argc, char *argv[]) acct_hierarchical_rec_list = get_acct_hierarchical_rec_list(assoc_list); acct_list = acct_storage_g_get_accounts(db_conn, my_uid, NULL); - fd = fopen(file_name, "w"); /* Add header */ @@ -1066,7 +1071,7 @@ extern int sacctmgr_dump_cluster (int argc, char *argv[]) print_file_acct_hierarchical_rec_list( fd, acct_hierarchical_rec_list, user_list, acct_list); - + xfree(cluster_name); xfree(file_name); list_destroy(acct_hierarchical_rec_list); diff --git a/src/sacctmgr/common.c b/src/sacctmgr/common.c index 867f4e078f57345d2debfc4ee8000a7dc4699649..8cf4ce85289c3e6816b28904f45443bbac9e419f 100644 --- a/src/sacctmgr/common.c +++ b/src/sacctmgr/common.c @@ -105,10 +105,13 @@ extern int parse_option_end(char *option) if(!option) return 0; - while(option[end] && (option[end] != '=' - && option[end] != '+' - && option[end] != '-')) - end++; + while(option[end]) { + if((option[end] == '=') + || (option[end] == '+' && option[end+1] == '=') + || (option[end] == '-' && option[end+1] == '=')) + break; + end++; + } if(!option[end]) return 0; diff --git a/src/sacctmgr/file_functions.c b/src/sacctmgr/file_functions.c index 69cb7454a0d62d13b8343caa391977223802f234..b4841bdb19a5a2092eea824663a7d785a079576c 100644 --- a/src/sacctmgr/file_functions.c +++ b/src/sacctmgr/file_functions.c @@ -44,6 +44,7 @@ typedef struct { acct_admin_level_t admin; List coord_list; /* char *list */ char *def_acct; + char *def_wckey; char *desc; uint32_t fairshare; @@ -65,6 +66,7 @@ typedef struct { char *org; char *part; List qos_list; + List wckey_list; } sacctmgr_file_opts_t; enum { @@ -73,6 +75,7 @@ enum { PRINT_CLUSTER, PRINT_COORDS, PRINT_DACCT, + PRINT_DWCKEY, PRINT_DESC, PRINT_FAIRSHARE, PRINT_GRPCM, @@ -95,7 +98,8 @@ enum { PRINT_PID, PRINT_PARENT, PRINT_PART, - PRINT_USER + PRINT_USER, + PRINT_WCKEYS }; typedef enum { @@ -238,10 +242,13 @@ static void _destroy_sacctmgr_file_opts(void *object) if(file_opts->coord_list) list_destroy(file_opts->coord_list); xfree(file_opts->def_acct); + xfree(file_opts->def_wckey); xfree(file_opts->desc); xfree(file_opts->name); xfree(file_opts->org); xfree(file_opts->part); + if(file_opts->wckey_list) + list_destroy(file_opts->wckey_list); xfree(file_opts); } } @@ -316,8 +323,15 @@ static sacctmgr_file_opts_t *_parse_options(char *options) list_create(slurm_destroy_char); slurm_addto_char_list(file_opts->coord_list, option); } else if (!strncasecmp (sub, "DefaultAccount", - MAX(command_len, 3))) { + MAX(command_len, 8))) { file_opts->def_acct = xstrdup(option); + } else if (!strncasecmp (sub, "DefaultWCKey", + MAX(command_len, 8))) { + file_opts->def_wckey = xstrdup(option); + if(!file_opts->wckey_list) + file_opts->wckey_list = + list_create(slurm_destroy_char); + slurm_addto_char_list(file_opts->wckey_list, option); } else if (!strncasecmp (sub, "Description", MAX(command_len, 3))) { file_opts->desc = xstrdup(option); @@ -479,6 +493,12 @@ static sacctmgr_file_opts_t *_parse_options(char *options) addto_qos_char_list(file_opts->qos_list, qos_list, option, option2); + } else if (!strncasecmp (sub, "WCKeys", + MAX(command_len, 2))) { + if(!file_opts->wckey_list) + file_opts->wckey_list = + list_create(slurm_destroy_char); + slurm_addto_char_list(file_opts->wckey_list, option); } else { exit_code=1; fprintf(stderr, " Unknown option: %s\n", sub); @@ -679,6 +699,12 @@ static List _set_up_print_fields(List format_list) field->name = xstrdup("User"); field->len = 10; field->print_routine = print_fields_str; + } else if(!strncasecmp("WCKeys", object, + MAX(command_len, 2))) { + field->type = PRINT_WCKEYS; + field->name = xstrdup("WCKeys"); + field->len = 20; + field->print_routine = print_fields_char_list; } else { exit_code=1; fprintf(stderr, "Unknown field '%s'\n", object); @@ -904,12 +930,12 @@ static int _mod_acct(sacctmgr_file_opts_t *file_opts, } static int _mod_user(sacctmgr_file_opts_t *file_opts, - acct_user_rec_t *user, char *parent) + acct_user_rec_t *user, char *cluster, char *parent) { int rc; int set = 0; int changed = 0; - char *def_acct = NULL, *my_info = NULL; + char *def_acct = NULL, *def_wckey = NULL, *my_info = NULL; acct_user_rec_t mod_user; acct_user_cond_t user_cond; List ret_list = NULL; @@ -940,9 +966,23 @@ static int _mod_user(sacctmgr_file_opts_t *file_opts, def_acct); mod_user.default_acct = def_acct; changed = 1; - } else - xfree(def_acct); + } + if(file_opts->def_wckey) + def_wckey = xstrdup(file_opts->def_wckey); + + if(def_wckey && + (!user->default_wckey || strcmp(def_wckey, user->default_wckey))) { + xstrfmtcat(my_info, + "%-30.30s for %-7.7s %-10.10s %8s -> %s\n", + " Changed Default WCKey", "User", + user->name, + user->default_wckey, + def_wckey); + mod_user.default_wckey = def_wckey; + changed = 1; + } + if(user->admin_level != ACCT_ADMIN_NOTSET && file_opts->admin != ACCT_ADMIN_NOTSET && user->admin_level != file_opts->admin) { @@ -984,6 +1024,7 @@ static int _mod_user(sacctmgr_file_opts_t *file_opts, xfree(my_info); } xfree(def_acct); + xfree(def_wckey); if((!user->coord_accts || !list_count(user->coord_accts)) && (file_opts->coord_list @@ -1061,6 +1102,82 @@ static int _mod_user(sacctmgr_file_opts_t *file_opts, } list_destroy(add_list); } + + if((!user->wckey_list || !list_count(user->wckey_list)) + && (file_opts->wckey_list + && list_count(file_opts->wckey_list))) { + ListIterator wckey_itr = NULL; + char *temp_char = NULL; + acct_wckey_rec_t *wckey = NULL; + int first = 1; + + user->wckey_list = list_create(destroy_acct_wckey_rec); + wckey_itr = list_iterator_create(file_opts->wckey_list); + printf(" Adding WCKey(s) '"); + while((temp_char = list_next(wckey_itr))) { + wckey = xmalloc(sizeof(acct_wckey_rec_t)); + wckey->name = xstrdup(temp_char); + wckey->cluster = xstrdup(cluster); + wckey->user = xstrdup(user->name); + list_push(user->wckey_list, wckey); + + if(first) { + printf(" %s", temp_char); + first = 0; + } else + printf(", %s", temp_char); + } + list_iterator_destroy(wckey_itr); + printf("' for user '%s'\n", user->name); + set = 1; + notice_thread_init(); + rc = acct_storage_g_add_wckeys(db_conn, my_uid, + user->wckey_list); + notice_thread_fini(); + } else if((user->wckey_list && list_count(user->wckey_list)) + && (file_opts->wckey_list + && list_count(file_opts->wckey_list))) { + ListIterator wckey_itr = NULL; + ListIterator char_itr = NULL; + char *temp_char = NULL; + acct_wckey_rec_t *wckey = NULL; + List add_list = list_create(destroy_acct_wckey_rec); + + wckey_itr = list_iterator_create(user->wckey_list); + char_itr = list_iterator_create(file_opts->wckey_list); + + while((temp_char = list_next(char_itr))) { + while((wckey = list_next(wckey_itr))) { + if(!strcmp(wckey->name, temp_char)) + break; + } + if(!wckey) { + printf(" Adding WCKey '%s' to User '%s'\n", + temp_char, user->name); + wckey = xmalloc(sizeof(acct_wckey_rec_t)); + wckey->name = xstrdup(temp_char); + wckey->cluster = xstrdup(cluster); + wckey->user = xstrdup(user->name); + + list_append(add_list, wckey); + } + list_iterator_reset(wckey_itr); + } + + list_iterator_destroy(char_itr); + list_iterator_destroy(wckey_itr); + + if(list_count(add_list)) { + notice_thread_init(); + rc = acct_storage_g_add_wckeys(db_conn, my_uid, + add_list); + notice_thread_fini(); + set = 1; + } + list_transfer(user->wckey_list, add_list); + list_destroy(add_list); + } + list_destroy(assoc_cond.user_list); return set; @@ -1376,7 +1493,7 @@ static int _mod_assoc(sacctmgr_file_opts_t *file_opts, } static acct_user_rec_t *_set_user_up(sacctmgr_file_opts_t *file_opts, - char *parent) + char *cluster, char *parent) { acct_user_rec_t *user = xmalloc(sizeof(acct_user_rec_t)); @@ -1388,6 +1505,11 @@ static acct_user_rec_t *_set_user_up(sacctmgr_file_opts_t *file_opts, else user->default_acct = xstrdup(parent); + if(file_opts->def_wckey) + user->default_wckey = xstrdup(file_opts->def_wckey); + else + user->default_wckey = xstrdup(""); + user->admin_level = file_opts->admin; if(file_opts->coord_list) { @@ -1419,6 +1541,26 @@ static acct_user_rec_t *_set_user_up(sacctmgr_file_opts_t *file_opts, } list_iterator_destroy(coord_itr); } + + if(file_opts->wckey_list) { + ListIterator wckey_itr = NULL; + char *temp_char = NULL; + acct_wckey_rec_t *wckey = NULL; + + user->wckey_list = list_create(destroy_acct_wckey_rec); + wckey_itr = list_iterator_create(file_opts->wckey_list); + while((temp_char = list_next(wckey_itr))) { + wckey = xmalloc(sizeof(acct_wckey_rec_t)); + wckey->name = xstrdup(temp_char); + wckey->user = xstrdup(user->name); + wckey->cluster = xstrdup(cluster); + list_push(user->wckey_list, wckey); + } + list_iterator_destroy(wckey_itr); + notice_thread_init(); + acct_storage_g_add_wckeys(db_conn, my_uid, user->wckey_list); + notice_thread_fini(); + } return user; } @@ -1522,6 +1664,7 @@ static int _print_file_acct_hierarchical_rec_childern(FILE *fd, char *line = NULL; acct_user_rec_t *user_rec = NULL; acct_account_rec_t *acct_rec = NULL; + uint16_t track_wckey = slurm_get_track_wckey(); itr = list_iterator_create(acct_hierarchical_rec_list); while((acct_hierarchical_rec = list_next(itr))) { @@ -1537,6 +1680,10 @@ static int _print_file_acct_hierarchical_rec_childern(FILE *fd, if(user_rec) { xstrfmtcat(line, ":DefaultAccount='%s'", user_rec->default_acct); + if(track_wckey) + xstrfmtcat(line, ":DefaultWCKey='%s'", + user_rec->default_wckey); + if(user_rec->admin_level > ACCT_ADMIN_NONE) xstrfmtcat(line, ":AdminLevel='%s'", acct_admin_level_str( @@ -1573,6 +1720,30 @@ static int _print_file_acct_hierarchical_rec_childern(FILE *fd, xstrcat(line, "'"); list_iterator_destroy(itr2); } + + if(user_rec->wckey_list + && list_count(user_rec->wckey_list)) { + ListIterator itr2 = NULL; + acct_wckey_rec_t *wckey = NULL; + int first_wckey = 1; + itr2 = list_iterator_create( + user_rec->wckey_list); + while((wckey = list_next(itr2))) { + if(first_wckey) { + xstrfmtcat( + line, + ":WCKeys='%s", + wckey->name); + first_wckey = 0; + } else { + xstrfmtcat(line, ",%s", + wckey->name); + } + } + if(!first_wckey) + xstrcat(line, "'"); + list_iterator_destroy(itr2); + } } } else { acct_rec = sacctmgr_find_account_from_list( @@ -1594,9 +1765,11 @@ static int _print_file_acct_hierarchical_rec_childern(FILE *fd, if(fprintf(fd, "%s\n", line) < 0) { exit_code=1; fprintf(stderr, " Can't write to file"); + xfree(line); return SLURM_ERROR; } info("%s", line); + xfree(line); } list_iterator_destroy(itr); print_file_acct_hierarchical_rec_list(fd, acct_hierarchical_rec_list, @@ -1762,35 +1935,6 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) /* reset the connection to get the most recent stuff */ acct_storage_g_commit(db_conn, 0); - memset(&user_cond, 0, sizeof(acct_user_cond_t)); - user_cond.with_coords = 1; - curr_user_list = acct_storage_g_get_users(db_conn, my_uid, &user_cond); - - /* make sure this person running is an admin */ - user_name = uid_to_string(my_uid); - if(!(user = sacctmgr_find_user_from_list(curr_user_list, user_name))) { - exit_code=1; - fprintf(stderr, " Your uid (%u) is not in the " - "accounting system, can't load file.\n", my_uid); - if(curr_user_list) - list_destroy(curr_user_list); - xfree(user_name); - return; - - } else { - if(my_uid != slurm_get_slurm_user_id() && my_uid != 0 - && user->admin_level < ACCT_ADMIN_SUPER_USER) { - exit_code=1; - fprintf(stderr, " Your user does not have sufficient " - "privileges to load files.\n"); - if(curr_user_list) - list_destroy(curr_user_list); - xfree(user_name); - return; - } - } - xfree(user_name); - for (i=0; i<argc; i++) { int option = 0; int end = parse_option_end(argv[i]); @@ -1926,6 +2070,56 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) if(!cluster_name_set) cluster_name = xstrdup(file_opts->name); + + /* we have to do this here since this is the + first place we have the cluster_name + */ + memset(&user_cond, 0, sizeof(acct_user_cond_t)); + user_cond.with_coords = 1; + user_cond.with_wckeys = 1; + + memset(&assoc_cond, 0, sizeof(acct_association_cond_t)); + assoc_cond.cluster_list = list_create(NULL); + assoc_cond.with_raw_qos = 1; + assoc_cond.without_parent_limits = 1; + list_append(assoc_cond.cluster_list, cluster_name); + user_cond.assoc_cond = &assoc_cond; + + curr_user_list = acct_storage_g_get_users( + db_conn, my_uid, &user_cond); + user_cond.assoc_cond = NULL; + + /* make sure this person running is an admin */ + user_name = uid_to_string(my_uid); + if(!(user = sacctmgr_find_user_from_list( + curr_user_list, user_name))) { + exit_code=1; + fprintf(stderr, " Your uid (%u) is not in the " + "accounting system, can't load file.\n", + my_uid); + if(curr_user_list) + list_destroy(curr_user_list); + xfree(user_name); + return; + + } else { + if(my_uid != slurm_get_slurm_user_id() + && my_uid != 0 + && (user->admin_level + < ACCT_ADMIN_SUPER_USER)) { + exit_code=1; + fprintf(stderr, + " Your user does not have " + "sufficient " + "privileges to load files.\n"); + if(curr_user_list) + list_destroy(curr_user_list); + xfree(user_name); + return; + } + } + xfree(user_name); + if(start_clean) { acct_cluster_cond_t cluster_cond; List ret_list = NULL; @@ -1962,9 +2156,9 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) curr_cluster_list = acct_storage_g_get_clusters( db_conn, my_uid, NULL); - if(cluster_name) + if(cluster_name) info("For cluster %s", cluster_name); - + if(!(cluster = sacctmgr_find_cluster_from_list( curr_cluster_list, cluster_name))) { List temp_assoc_list = list_create(NULL); @@ -2005,11 +2199,7 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) _destroy_sacctmgr_file_opts(file_opts); - memset(&assoc_cond, 0, sizeof(acct_association_cond_t)); - assoc_cond.cluster_list = list_create(NULL); - assoc_cond.with_raw_qos = 1; - assoc_cond.without_parent_limits = 1; - list_append(assoc_cond.cluster_list, cluster_name); + /* assoc_cond if set up above */ curr_assoc_list = acct_storage_g_get_associations( db_conn, my_uid, &assoc_cond); list_destroy(assoc_cond.cluster_list); @@ -2174,7 +2364,8 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) && !sacctmgr_find_user_from_list( user_list, file_opts->name)) { - user = _set_user_up(file_opts, parent); + user = _set_user_up(file_opts, cluster_name, + parent); list_append(user_list, user); /* don't add anything to the curr_user_list */ @@ -2212,7 +2403,8 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) sizeof(acct_user_rec_t)); list_append(mod_user_list, user2); user2->name = xstrdup(file_opts->name); - if(_mod_user(file_opts, user, parent)) + if(_mod_user(file_opts, user, + cluster_name, parent)) set = 1; } else { debug2("already modified this user"); @@ -2232,7 +2424,8 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) sizeof(acct_user_rec_t)); list_append(mod_user_list, user2); user2->name = xstrdup(file_opts->name); - if(_mod_user(file_opts, user, parent)) + if(_mod_user(file_opts, user, + cluster_name, parent)) set = 1; } else { debug2("already modified this user"); @@ -2331,7 +2524,7 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) printf("Users\n"); slurm_addto_char_list(format_list, - "Name,Default,QOS,Admin,Coord"); + "Name,DefaultA,DefaultW,QOS,Admin,Coord"); print_fields_list = _set_up_print_fields(format_list); list_flush(format_list); @@ -2358,10 +2551,19 @@ extern void load_sacctmgr_cfg_file (int argc, char *argv[]) field, user->default_acct); break; + case PRINT_DWCKEY: + field->print_routine( + field, + user->default_wckey); + break; case PRINT_NAME: field->print_routine( field, user->name); break; + case PRINT_WCKEYS: + field->print_routine( + field, user->wckey_list); + break; default: field->print_routine( field, NULL); diff --git a/src/sacctmgr/user_functions.c b/src/sacctmgr/user_functions.c index d8fad55a894cfcf1da2f8fda8e667419f4253e24..210fb3c51251d494039e3660538e1ba9e51ba626 100644 --- a/src/sacctmgr/user_functions.c +++ b/src/sacctmgr/user_functions.c @@ -644,7 +644,6 @@ extern int sacctmgr_add_user(int argc, char *argv[]) char *default_acct = NULL; char *default_wckey = NULL; acct_association_cond_t *assoc_cond = NULL; - acct_association_cond_t query_assoc_cond; acct_wckey_rec_t *wckey = NULL; acct_wckey_cond_t *wckey_cond = NULL; List qos_list = NULL; @@ -880,32 +879,6 @@ extern int sacctmgr_add_user(int argc, char *argv[]) } - if(!list_count(assoc_cond->acct_list)) { - destroy_acct_association_cond(assoc_cond); - exit_code=1; - fprintf(stderr, " Need name of acct to add user to.\n"); - return SLURM_ERROR; - } else { - acct_account_cond_t account_cond; - - memset(&account_cond, 0, sizeof(acct_account_cond_t)); - account_cond.assoc_cond = assoc_cond; - - local_acct_list = acct_storage_g_get_accounts( - db_conn, my_uid, &account_cond); - } - - if(!local_acct_list) { - exit_code=1; - fprintf(stderr, " Problem getting accounts from database. " - "Contact your admin.\n"); - list_destroy(local_user_list); - destroy_acct_wckey_cond(wckey_cond); - destroy_acct_association_cond(assoc_cond); - return SLURM_ERROR; - } - - if(!list_count(assoc_cond->cluster_list)) { List cluster_list = NULL; acct_cluster_rec_t *cluster_rec = NULL; @@ -920,7 +893,8 @@ extern int sacctmgr_add_user(int argc, char *argv[]) destroy_acct_wckey_cond(wckey_cond); destroy_acct_association_cond(assoc_cond); list_destroy(local_user_list); - list_destroy(local_acct_list); + if(local_acct_list) + list_destroy(local_acct_list); return SLURM_ERROR; } @@ -939,14 +913,105 @@ extern int sacctmgr_add_user(int argc, char *argv[]) destroy_acct_wckey_cond(wckey_cond); destroy_acct_association_cond(assoc_cond); list_destroy(local_user_list); - list_destroy(local_acct_list); + if(local_acct_list) + list_destroy(local_acct_list); + return SLURM_ERROR; + } + } else { + List temp_list = NULL; + acct_cluster_cond_t cluster_cond; + + memset(&cluster_cond, 0, sizeof(acct_cluster_cond_t)); + cluster_cond.cluster_list = assoc_cond->cluster_list; + + temp_list = acct_storage_g_get_clusters(db_conn, my_uid, + &cluster_cond); + + itr_c = list_iterator_create(assoc_cond->cluster_list); + itr = list_iterator_create(temp_list); + while((cluster = list_next(itr_c))) { + acct_cluster_rec_t *cluster_rec = NULL; + + list_iterator_reset(itr); + while((cluster_rec = list_next(itr))) { + if(!strcasecmp(cluster_rec->name, cluster)) + break; + } + if(!cluster_rec) { + exit_code=1; + fprintf(stderr, " This cluster '%s' " + "doesn't exist.\n" + " Contact your admin " + "to add it to accounting.\n", + cluster); + list_delete_item(itr_c); + } + } + list_iterator_destroy(itr); + list_iterator_destroy(itr_c); + list_destroy(temp_list); + + if(!list_count(assoc_cond->cluster_list)) { + destroy_acct_wckey_cond(wckey_cond); + destroy_acct_association_cond(assoc_cond); + list_destroy(local_user_list); + if(local_acct_list) + list_destroy(local_acct_list); return SLURM_ERROR; } } - if(!default_acct) - default_acct = xstrdup(list_peek(assoc_cond->acct_list)); + if(!list_count(assoc_cond->acct_list)) { + if(!list_count(wckey_cond->name_list)) { + destroy_acct_wckey_cond(wckey_cond); + destroy_acct_association_cond(assoc_cond); + exit_code=1; + fprintf(stderr, " Need name of acct to " + "add user to.\n"); + return SLURM_ERROR; + } + } else { + acct_account_cond_t account_cond; + acct_association_cond_t query_assoc_cond; + + memset(&account_cond, 0, sizeof(acct_account_cond_t)); + account_cond.assoc_cond = assoc_cond; + local_acct_list = acct_storage_g_get_accounts( + db_conn, my_uid, &account_cond); + + if(!local_acct_list) { + exit_code=1; + fprintf(stderr, " Problem getting accounts " + "from database. Contact your admin.\n"); + list_destroy(local_user_list); + destroy_acct_wckey_cond(wckey_cond); + destroy_acct_association_cond(assoc_cond); + return SLURM_ERROR; + } + + if(!default_acct) + default_acct = + xstrdup(list_peek(assoc_cond->acct_list)); + + memset(&query_assoc_cond, 0, sizeof(acct_association_cond_t)); + query_assoc_cond.acct_list = assoc_cond->acct_list; + query_assoc_cond.cluster_list = assoc_cond->cluster_list; + local_assoc_list = acct_storage_g_get_associations( + db_conn, my_uid, &query_assoc_cond); + + if(!local_assoc_list) { + exit_code=1; + fprintf(stderr, " Problem getting associations " + "from database. Contact your admin.\n"); + list_destroy(local_user_list); + list_destroy(local_acct_list); + destroy_acct_wckey_cond(wckey_cond); + destroy_acct_association_cond(assoc_cond); + return SLURM_ERROR; + } + } + if(track_wckey) { /* add a blank one there for default just in case it wasn't * there before. */ @@ -969,13 +1034,6 @@ extern int sacctmgr_add_user(int argc, char *argv[]) assoc_list = list_create(destroy_acct_association_rec); wckey_list = list_create(destroy_acct_wckey_rec); - memset(&query_assoc_cond, 0, sizeof(acct_association_cond_t)); - query_assoc_cond.acct_list = assoc_cond->acct_list; - query_assoc_cond.cluster_list = assoc_cond->cluster_list; - local_assoc_list = acct_storage_g_get_associations( - db_conn, my_uid, &query_assoc_cond); - - itr = list_iterator_create(assoc_cond->user_list); while((name = list_next(itr))) { user = NULL; @@ -1216,8 +1274,10 @@ extern int sacctmgr_add_user(int argc, char *argv[]) no_default: list_iterator_destroy(itr); list_destroy(local_user_list); - list_destroy(local_acct_list); - list_destroy(local_assoc_list); + if(local_acct_list) + list_destroy(local_acct_list); + if(local_assoc_list) + list_destroy(local_assoc_list); if(local_wckey_list) list_destroy(local_wckey_list); destroy_acct_wckey_cond(wckey_cond); @@ -1227,9 +1287,9 @@ no_default: && !list_count(wckey_list)) { printf(" Nothing new added.\n"); goto end_it; - } else if(!assoc_str) { + } else if(!assoc_str && !wckey_str) { exit_code=1; - fprintf(stderr, " No associations created.\n"); + fprintf(stderr, " No associations or wckeys created.\n"); goto end_it; } @@ -1238,7 +1298,7 @@ no_default: printf(" Settings =\n"); printf(" Default Account = %s\n", default_acct); if(track_wckey) - printf(" Default WCKey = %s\n", default_wckey); + printf(" Default WCKey = %s\n", default_wckey); if(admin_level != ACCT_ADMIN_NOTSET) printf(" Admin Level = %s\n", diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index 12c3af5ab329217ef0d46598513dc8aeb0d75383..746007e9ff6af979a90ce6f1d953e61cba6f008f 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -2914,6 +2914,20 @@ _copy_job_desc_to_job_record(job_desc_msg_t * job_desc, if (job_desc->name) job_ptr->name = xstrdup(job_desc->name); + + if(slurm_get_track_wckey() && !strchr(job_ptr->name, '\"')) { + /* get the default wckey for this user since none was + * given */ + acct_user_rec_t user_rec; + memset(&user_rec, 0, sizeof(acct_user_rec_t)); + user_rec.uid = job_desc->user_id; + assoc_mgr_fill_in_user(acct_db_conn, &user_rec, + accounting_enforce, NULL); + if(user_rec.default_wckey) + xstrfmtcat(job_ptr->name, "\"%s", + user_rec.default_wckey); + } + job_ptr->user_id = (uid_t) job_desc->user_id; job_ptr->group_id = (gid_t) job_desc->group_id; job_ptr->job_state = JOB_PENDING; @@ -4475,12 +4489,12 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid) xfree(job_ptr->name); if(jname) { - xstrfmtcat(job_ptr->name,"%s", jname); + xstrfmtcat(job_ptr->name, "%s", jname); xfree(jname); } if(wckey) { - xstrfmtcat(job_ptr->name,"\"%s", wckey); + xstrfmtcat(job_ptr->name, "\"%s", wckey); xfree(wckey); }