From e4ce1aa9624f647535643d67496d2d4c3021391b Mon Sep 17 00:00:00 2001 From: Danny Auble <da@llnl.gov> Date: Thu, 13 Aug 2009 21:15:49 +0000 Subject: [PATCH] -- Added functionality for sacctmgr show problems. Current problems include Accounts/Users with no associations, Accounts with no users or subaccounts attached in a cluster, and Users with No UID on the system. -- Added new option for sacctmgr list assoc and list cluster WOLimits. This gives a smaller default format without the limit information. This may be the new default for list assocations and list clusters. -- Users are now required to have an association with there default account. Sacctmgr will now complain when you try to modify a users default account which they are not associated anywhere. --- NEWS | 9 + doc/man/man1/sacctmgr.1 | 10 + src/common/slurm_accounting_storage.c | 45 +++ src/common/slurm_accounting_storage.h | 9 +- .../mysql/accounting_storage_mysql.c | 24 +- .../accounting_storage/mysql/mysql_problems.c | 307 +++++++++++++++++- .../accounting_storage/mysql/mysql_problems.h | 13 +- src/sacctmgr/association_functions.c | 19 +- src/sacctmgr/cluster_functions.c | 11 +- src/sacctmgr/problem_functions.c | 43 +-- src/sacctmgr/sacctmgr.c | 6 +- src/sacctmgr/user_functions.c | 72 +++- 12 files changed, 495 insertions(+), 73 deletions(-) diff --git a/NEWS b/NEWS index 9534fa90d05..4c1e2357404 100644 --- a/NEWS +++ b/NEWS @@ -49,6 +49,15 @@ documents those changes that are of interest to users and admins. and is packaged as a separate RPM. -- Added configuration parameter MaxTasksPerNode. -- Remove configuration parameter SrunIOTimeout. + -- Added functionality for sacctmgr show problems. Current problems include + Accounts/Users with no associations, Accounts with no users or subaccounts + attached in a cluster, and Users with No UID on the system. + -- Added new option for sacctmgr list assoc and list cluster WOLimits. This + gives a smaller default format without the limit information. This may + be the new default for list assocations and list clusters. + -- Users are now required to have an association with there default account. + Sacctmgr will now complain when you try to modify a users default account + which they are not associated anywhere. * Changes in SLURM 2.1.0-pre2 ============================= diff --git a/doc/man/man1/sacctmgr.1 b/doc/man/man1/sacctmgr.1 index 72edafa0b54..f3323d75c8f 100644 --- a/doc/man/man1/sacctmgr.1 +++ b/doc/man/man1/sacctmgr.1 @@ -443,6 +443,11 @@ Display information with subaccounts. Only really valuable when used with the account= option. This will display all the subaccount associations along with the accounts listed in the option. +.TP +\fIWOLimits\fP +Display information without limit information. This is for a smaller +default format of Cluster,Account,User,Partition + .TP \fIWOPInfo\fP Display information without parent information. (i.e. parent id, and @@ -465,6 +470,11 @@ The name of a cluster. This should be equal to the \fIClusterName\fR parameter in the \fIslurm.conf\fR configuration file for some Slurm\-managed cluster. +.TP +\fIWOLimits\fP +Display information without limit information. This is for a smaller +default format of Cluster,ControlHost,ControlPort,RPC + .SH "" NOTE: You can also use the general specifications list above in the \fIGENERAL SPECIFICATIONS FOR ASSOCIATION BASED ENTITIES\fP section. diff --git a/src/common/slurm_accounting_storage.c b/src/common/slurm_accounting_storage.c index a1817029dc4..2d5d79a4166 100644 --- a/src/common/slurm_accounting_storage.c +++ b/src/common/slurm_accounting_storage.c @@ -7299,6 +7299,51 @@ extern uint16_t str_2_classification(char *class) return type; } +extern char *get_acct_problem_str(uint16_t problem) +{ + acct_problem_type_t type = problem; + + switch(type) { + case ACCT_PROBLEM_NOT_SET: + return NULL; + break; + case ACCT_PROBLEM_ACCT_NO_ASSOC: + return "Account has no Associations"; + break; + case ACCT_PROBLEM_ACCT_NO_USERS: + return "Account has no users"; + break; + case ACCT_PROBLEM_USER_NO_ASSOC: + return "User has no Associations"; + break; + case ACCT_PROBLEM_USER_NO_UID: + return "User does not have a uid"; + break; + default: + return "Unknown"; + break; + } +} + +extern uint16_t str_2_acct_problem(char *problem) +{ + uint16_t type = 0; + + if(!problem) + return type; + + if(slurm_strcasestr(problem, "account no associations")) + type = ACCT_PROBLEM_USER_NO_ASSOC; + else if(slurm_strcasestr(problem, "account no users")) + type = ACCT_PROBLEM_ACCT_NO_USERS; + else if(slurm_strcasestr(problem, "user no associations")) + type = ACCT_PROBLEM_USER_NO_ASSOC; + else if(slurm_strcasestr(problem, "user no uid")) + type = ACCT_PROBLEM_USER_NO_UID; + + return type; +} + extern void log_assoc_rec(acct_association_rec_t *assoc_ptr, List qos_list) { xassert(assoc_ptr); diff --git a/src/common/slurm_accounting_storage.h b/src/common/slurm_accounting_storage.h index 03eb6d4e0ea..23b862391b7 100644 --- a/src/common/slurm_accounting_storage.h +++ b/src/common/slurm_accounting_storage.h @@ -82,10 +82,10 @@ typedef enum { typedef enum { ACCT_PROBLEM_NOT_SET, + ACCT_PROBLEM_ACCT_NO_ASSOC, + ACCT_PROBLEM_ACCT_NO_USERS, ACCT_PROBLEM_USER_NO_ASSOC, - ACCT_PROBLEM_USER_NO_DEFAULT, - ACCT_PROBLEM_ACCT_NO_CHILD, - ACCT_PROBLEM_CLUS_ONLY_ROOT, + ACCT_PROBLEM_USER_NO_UID, } acct_problem_type_t; #define ACCT_CLASSIFIED_FLAG 0x0100 @@ -694,6 +694,9 @@ extern char *get_qos_complete_str(List qos_list, List num_qos_list); extern char *get_classification_str(uint16_t class); extern uint16_t str_2_classification(char *class); +extern char *get_acct_problem_str(uint16_t problem); +extern uint16_t str_2_acct_problem(char *problem); + extern void log_assoc_rec(acct_association_rec_t *assoc_ptr, List qos_list); extern int slurm_acct_storage_init(char *loc); /* load the plugin */ diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c index f3ef8ea9649..985f56a7dd9 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c @@ -50,6 +50,7 @@ #include <strings.h> #include "mysql_jobacct_process.h" #include "mysql_rollup.h" +#include "mysql_problems.h" #include "src/common/slurmdbd_defs.h" #include "src/common/slurm_auth.h" #include "src/common/uid.h" @@ -8280,7 +8281,7 @@ extern List acct_storage_p_get_associations(mysql_conn_t *mysql_conn, set = _setup_association_cond_limits(assoc_cond, &extra); with_raw_qos = assoc_cond->with_raw_qos; - with_usage = assoc_cond->with_usage; + with_usage = assoc_cond->with_usage; without_parent_limits = assoc_cond->without_parent_limits; without_parent_info = assoc_cond->without_parent_info; @@ -8638,8 +8639,27 @@ empty: extern List acct_storage_p_get_problems(mysql_conn_t *mysql_conn, uint32_t uid, acct_association_cond_t *assoc_cond) { + List ret_list = NULL; - return NULL; + if(_check_connection(mysql_conn) != SLURM_SUCCESS) + return NULL; + + ret_list = list_create(destroy_acct_association_rec); + + if(mysql_acct_no_assocs(mysql_conn, assoc_cond, ret_list) + != SLURM_SUCCESS) + goto end_it; + if(mysql_acct_no_users(mysql_conn, assoc_cond, ret_list) + != SLURM_SUCCESS) + goto end_it; + + if(mysql_user_no_assocs_or_default(mysql_conn, assoc_cond, ret_list) + != SLURM_SUCCESS) + goto end_it; + +end_it: + + return ret_list; } extern List acct_storage_p_get_config(void *db_conn) diff --git a/src/plugins/accounting_storage/mysql/mysql_problems.c b/src/plugins/accounting_storage/mysql/mysql_problems.c index 2afa764ac63..a5e114adce7 100644 --- a/src/plugins/accounting_storage/mysql/mysql_problems.c +++ b/src/plugins/accounting_storage/mysql/mysql_problems.c @@ -39,18 +39,313 @@ \*****************************************************************************/ #include "mysql_problems.h" +#include "src/common/uid.h" -extern List mysql_acct_no_assocs(mysql_conn_t *mysql_conn) +static int _setup_association_cond_limits(acct_association_cond_t *assoc_cond, + char **extra, bool user_query) { - return NULL; + int set = 0; + ListIterator itr = NULL; + char *object = NULL; + + xstrfmtcat(*extra, "where deleted=0"); + + if(!assoc_cond) + return 0; + + if(assoc_cond->acct_list && list_count(assoc_cond->acct_list)) { + set = 0; + xstrcat(*extra, " && ("); + itr = list_iterator_create(assoc_cond->acct_list); + while((object = list_next(itr))) { + if(set) + xstrcat(*extra, " || "); + xstrfmtcat(*extra, "acct=\"%s\"", object); + set = 1; + } + list_iterator_destroy(itr); + xstrcat(*extra, ")"); + } + + if(assoc_cond->cluster_list && list_count(assoc_cond->cluster_list)) { + set = 0; + xstrcat(*extra, " && ("); + itr = list_iterator_create(assoc_cond->cluster_list); + while((object = list_next(itr))) { + if(set) + xstrcat(*extra, " || "); + xstrfmtcat(*extra, "cluster=\"%s\"", object); + set = 1; + } + list_iterator_destroy(itr); + xstrcat(*extra, ")"); + } + + if(assoc_cond->user_list && list_count(assoc_cond->user_list)) { + set = 0; + xstrcat(*extra, " && ("); + itr = list_iterator_create(assoc_cond->user_list); + while((object = list_next(itr))) { + if(set) + xstrcat(*extra, " || "); + xstrfmtcat(*extra, "user=\"%s\"", object); + set = 1; + } + list_iterator_destroy(itr); + xstrcat(*extra, ")"); + } else if(user_query) { + /* we want all the users, but no non-user associations */ + set = 1; + xstrcat(*extra, " && (user!='')"); + } + + if(assoc_cond->partition_list + && list_count(assoc_cond->partition_list)) { + set = 0; + xstrcat(*extra, " && ("); + itr = list_iterator_create(assoc_cond->partition_list); + while((object = list_next(itr))) { + if(set) + xstrcat(*extra, " || "); + xstrfmtcat(*extra, "partition=\"%s\"", object); + set = 1; + } + list_iterator_destroy(itr); + xstrcat(*extra, ")"); + } + + return set; } -extern List mysql_cluster_no_assocs(mysql_conn_t *mysql_conn) + +extern int mysql_acct_no_assocs(mysql_conn_t *mysql_conn, + acct_association_cond_t *assoc_cond, + List ret_list) { - return NULL; + int rc = SLURM_SUCCESS; + char *query = NULL; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + + xassert(ret_list); + + query = xstrdup_printf("select name from %s where deleted=0", + acct_table); + if(assoc_cond && + assoc_cond->acct_list && list_count(assoc_cond->acct_list)) { + int set = 0; + ListIterator itr = NULL; + char *object = NULL; + xstrcat(query, " && ("); + itr = list_iterator_create(assoc_cond->acct_list); + while((object = list_next(itr))) { + if(set) + xstrcat(query, " || "); + xstrfmtcat(query, "name=\"%s\"", object); + set = 1; + } + list_iterator_destroy(itr); + xstrcat(query, ")"); + } + + if(!(result = mysql_db_query_ret( + mysql_conn->db_conn, query, 0))) { + xfree(query); + return SLURM_ERROR; + } + xfree(query); + + while((row = mysql_fetch_row(result))) { + MYSQL_RES *result2 = NULL; + int cnt = 0; + acct_association_rec_t *assoc = NULL; + /* See if we have at least 1 association in the system */ + query = xstrdup_printf("select distinct id from %s " + "where deleted=0 && " + "acct='%s' limit 1;", + assoc_table, row[0]); + if(!(result2 = mysql_db_query_ret( + mysql_conn->db_conn, query, 0))) { + xfree(query); + rc = SLURM_ERROR; + break; + } + xfree(query); + + cnt = mysql_num_rows(result2); + mysql_free_result(result2); + + if(cnt) + continue; + + assoc = xmalloc(sizeof(acct_association_rec_t)); + list_append(ret_list, assoc); + + assoc->id = ACCT_PROBLEM_ACCT_NO_ASSOC; + assoc->acct = xstrdup(row[0]); + } + mysql_free_result(result); + + return rc; } -extern List mysql_user_no_assocs_or_default(mysql_conn_t *mysql_conn) +extern int mysql_acct_no_users(mysql_conn_t *mysql_conn, + acct_association_cond_t *assoc_cond, + List ret_list) { - return NULL; + int rc = SLURM_SUCCESS; + char *query = NULL, *tmp = NULL; + char *extra = NULL; + int i = 0; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + + xassert(ret_list); + + _setup_association_cond_limits(assoc_cond, &extra, 0); + + /* if this changes you will need to edit the corresponding enum */ + char *assoc_req_inx[] = { + "id", + "user", + "acct", + "cluster", + "partition", + "parent_acct", + }; + enum { + ASSOC_REQ_ID, + ASSOC_REQ_USER, + ASSOC_REQ_ACCT, + ASSOC_REQ_CLUSTER, + ASSOC_REQ_PART, + ASSOC_REQ_PARENT, + ASSOC_REQ_COUNT + }; + + xfree(tmp); + xstrfmtcat(tmp, "%s", assoc_req_inx[i]); + for(i=1; i<ASSOC_REQ_COUNT; i++) { + xstrfmtcat(tmp, ", %s", assoc_req_inx[i]); + } + + /* only get the account associations */ + query = xstrdup_printf("select distinct %s from %s %s " + "&& user='' && lft=(rgt-1)" + "order by cluster,acct;", + tmp, assoc_table, extra); + xfree(tmp); + xfree(extra); + debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query); + if(!(result = mysql_db_query_ret( + mysql_conn->db_conn, query, 0))) { + xfree(query); + return SLURM_ERROR; + } + xfree(query); + + while((row = mysql_fetch_row(result))) { + acct_association_rec_t *assoc = + xmalloc(sizeof(acct_association_rec_t)); + + list_append(ret_list, assoc); + + assoc->id = ACCT_PROBLEM_ACCT_NO_USERS; + + if(row[ASSOC_REQ_USER][0]) + assoc->user = xstrdup(row[ASSOC_REQ_USER]); + assoc->acct = xstrdup(row[ASSOC_REQ_ACCT]); + assoc->cluster = xstrdup(row[ASSOC_REQ_CLUSTER]); + + if(row[ASSOC_REQ_PARENT][0]) + assoc->parent_acct = xstrdup(row[ASSOC_REQ_PARENT]); + + if(row[ASSOC_REQ_PART][0]) + assoc->partition = xstrdup(row[ASSOC_REQ_PART]); + } + mysql_free_result(result); + + return rc; +} + +extern int mysql_user_no_assocs_or_default(mysql_conn_t *mysql_conn, + acct_association_cond_t *assoc_cond, + List ret_list) +{ + int rc = SLURM_SUCCESS; + char *query = NULL; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + xassert(ret_list); + + query = xstrdup_printf("select name from %s where deleted=0", + user_table); + if(assoc_cond && + assoc_cond->user_list && list_count(assoc_cond->user_list)) { + int set = 0; + ListIterator itr = NULL; + char *object = NULL; + xstrcat(query, " && ("); + itr = list_iterator_create(assoc_cond->user_list); + while((object = list_next(itr))) { + if(set) + xstrcat(query, " || "); + xstrfmtcat(query, "name=\"%s\"", object); + set = 1; + } + list_iterator_destroy(itr); + xstrcat(query, ")"); + } + + if(!(result = mysql_db_query_ret( + mysql_conn->db_conn, query, 0))) { + xfree(query); + return SLURM_ERROR; + } + xfree(query); + + while((row = mysql_fetch_row(result))) { + MYSQL_RES *result2 = NULL; + int cnt = 0; + acct_association_rec_t *assoc = NULL; + uid_t pw_uid; + + if (uid_from_string (row[0], &pw_uid) < 0) { + assoc = xmalloc(sizeof(acct_association_rec_t)); + list_append(ret_list, assoc); + + assoc->id = ACCT_PROBLEM_USER_NO_UID; + assoc->user = xstrdup(row[0]); + + continue; + } + + /* See if we have at least 1 association in the system */ + query = xstrdup_printf("select distinct id from %s " + "where deleted=0 && " + "user='%s' limit 1;", + assoc_table, row[0]); + if(!(result2 = mysql_db_query_ret( + mysql_conn->db_conn, query, 0))) { + xfree(query); + rc = SLURM_ERROR; + break; + } + xfree(query); + + cnt = mysql_num_rows(result2); + mysql_free_result(result2); + + if(cnt) + continue; + + assoc = xmalloc(sizeof(acct_association_rec_t)); + list_append(ret_list, assoc); + + assoc->id = ACCT_PROBLEM_ACCT_NO_ASSOC; + assoc->user = xstrdup(row[0]); + } + mysql_free_result(result); + + return rc; } diff --git a/src/plugins/accounting_storage/mysql/mysql_problems.h b/src/plugins/accounting_storage/mysql/mysql_problems.h index 12a11a5177e..553e737b946 100644 --- a/src/plugins/accounting_storage/mysql/mysql_problems.h +++ b/src/plugins/accounting_storage/mysql/mysql_problems.h @@ -43,7 +43,14 @@ #include "mysql_jobacct_process.h" -extern List mysql_acct_no_assocs(mysql_conn_t *mysql_conn); -extern List mysql_cluster_no_assocs(mysql_conn_t *mysql_conn); -extern List mysql_user_no_assocs_or_default(mysql_conn_t *mysql_conn); +extern int mysql_acct_no_assocs(mysql_conn_t *mysql_conn, + acct_association_cond_t *assoc_cond, + List ret_list); +extern int mysql_acct_no_users(mysql_conn_t *mysql_conn, + acct_association_cond_t *assoc_cond, + List ret_list); +extern int mysql_user_no_assocs_or_no_uid( + mysql_conn_t *mysql_conn, acct_association_cond_t *assoc_cond, + List ret_list); + #endif diff --git a/src/sacctmgr/association_functions.c b/src/sacctmgr/association_functions.c index 6a35a8df4b4..91ab83aa971 100644 --- a/src/sacctmgr/association_functions.c +++ b/src/sacctmgr/association_functions.c @@ -39,6 +39,7 @@ #include "src/sacctmgr/sacctmgr.h" static bool tree_display = 0; +static bool without_limits = 0; static int _set_cond(int *start, int argc, char *argv[], acct_association_cond_t *assoc_cond, @@ -81,6 +82,10 @@ static int _set_cond(int *start, int argc, char *argv[], } else if (!end && !strncasecmp (argv[i], "WOPLimits", MAX(command_len, 4))) { assoc_cond->without_parent_limits = 1; + } else if (!end && !strncasecmp (argv[i], "WOLimits", + MAX(command_len, 3))) { + without_limits = 1; + assoc_cond->without_parent_limits = 1; } else if(!end && !strncasecmp(argv[i], "where", MAX(command_len, 5))) { continue; @@ -362,12 +367,14 @@ extern int sacctmgr_list_association(int argc, char *argv[]) destroy_acct_association_cond(assoc_cond); list_destroy(format_list); return SLURM_ERROR; - } else if(!list_count(format_list)) - slurm_addto_char_list(format_list, - "C,A,U,Part,F," - "GrpCPUMins,GrpJ,GrpN,GrpS,GrpWall," - "MaxJ,MaxN,MaxS,MaxW,QOS"); - + } else if(!list_count(format_list)) { + slurm_addto_char_list(format_list, "C,A,U,Part"); + if(!without_limits) + slurm_addto_char_list(format_list, + "F,GrpCPUMins,GrpJ,GrpN," + "GrpS,GrpWall," + "MaxJ,MaxN,MaxS,MaxW,QOS"); + } print_fields_list = list_create(destroy_print_field); itr = list_iterator_create(format_list); diff --git a/src/sacctmgr/cluster_functions.c b/src/sacctmgr/cluster_functions.c index 18c8c1d3e7f..807275b3336 100644 --- a/src/sacctmgr/cluster_functions.c +++ b/src/sacctmgr/cluster_functions.c @@ -40,6 +40,7 @@ #include "src/sacctmgr/sacctmgr.h" #include "src/common/uid.h" +static bool without_limits = 0; static int _set_cond(int *start, int argc, char *argv[], List cluster_list, @@ -79,6 +80,9 @@ static int _set_cond(int *start, int argc, char *argv[], argv[i]+end)) set = 1; } + } else if (!end && !strncasecmp (argv[i], "WOLimits", + MAX(command_len, 3))) { + without_limits = 1; } else if (!strncasecmp (argv[i], "Classification", MAX(command_len, 3))) { if(classification) { @@ -473,8 +477,11 @@ extern int sacctmgr_list_cluster(int argc, char *argv[]) if(!list_count(format_list)) { slurm_addto_char_list(format_list, - "Cl,Controlh,Controlp,RPC,F," - "GrpJ,GrpN,GrpS,MaxJ,MaxN,MaxS,MaxW,QOS"); + "Cl,Controlh,Controlp,RPC"); + if(!without_limits) + slurm_addto_char_list(format_list, + "F,GrpJ,GrpN,GrpS,MaxJ,MaxN," + "MaxS,MaxW,QOS"); } itr = list_iterator_create(format_list); diff --git a/src/sacctmgr/problem_functions.c b/src/sacctmgr/problem_functions.c index cf22038b40f..1c39597bb60 100644 --- a/src/sacctmgr/problem_functions.c +++ b/src/sacctmgr/problem_functions.c @@ -108,15 +108,6 @@ static int _set_cond(int *start, int argc, char *argv[], slurm_addto_char_list(assoc_cond->partition_list, argv[i]+end); set = 1; - } else if (!strncasecmp (argv[i], "Parent", - MAX(command_len, 4))) { - if(!assoc_cond->parent_acct_list) { - assoc_cond->parent_acct_list = - list_create(slurm_destroy_char); - } - if(slurm_addto_char_list(assoc_cond->parent_acct_list, - argv[i]+end)) - set = 1; } else if (!strncasecmp (argv[i], "Users", MAX(command_len, 1))) { if(!assoc_cond->user_list) @@ -149,7 +140,6 @@ extern int sacctmgr_list_problem(int argc, char *argv[]) ListIterator itr = NULL; ListIterator itr2 = NULL; char *object = NULL; - char *print_acct = NULL, *last_cluster = NULL; List tree_list = NULL; List qos_list = NULL; @@ -265,41 +255,12 @@ extern int sacctmgr_list_problem(int argc, char *argv[]) while((assoc = list_next(itr))) { int curr_inx = 1; - if(!last_cluster || strcmp(last_cluster, assoc->cluster)) { - if(tree_list) { - list_flush(tree_list); - } else { - tree_list = - list_create(destroy_acct_print_tree); - } - last_cluster = assoc->cluster; - } while((field = list_next(itr2))) { switch(field->type) { case PRINT_ACCOUNT: - if(tree_display) { - char *local_acct = NULL; - char *parent_acct = NULL; - if(assoc->user) { - local_acct = xstrdup_printf( - "|%s", assoc->acct); - parent_acct = assoc->acct; - } else { - local_acct = - xstrdup(assoc->acct); - parent_acct = - assoc->parent_acct; - } - print_acct = get_tree_acct_name( - local_acct, - parent_acct, tree_list); - xfree(local_acct); - } else { - print_acct = assoc->acct; - } field->print_routine( field, - print_acct, + assoc->acct, (curr_inx == field_count)); break; case PRINT_CLUSTER: @@ -316,7 +277,7 @@ extern int sacctmgr_list_problem(int argc, char *argv[]) */ field->print_routine( field, - NULL, + get_acct_problem_str(assoc->id), (curr_inx == field_count)); break; case PRINT_USER: diff --git a/src/sacctmgr/sacctmgr.c b/src/sacctmgr/sacctmgr.c index 8296ac30768..45963780770 100644 --- a/src/sacctmgr/sacctmgr.c +++ b/src/sacctmgr/sacctmgr.c @@ -817,10 +817,10 @@ sacctmgr [<OPTION>] [<COMMAND>] \n\ \n\ list associations - Accounts=, Clusters=, Format=, IDs=, \n\ Partitions=, Parent=, Tree, Users=, \n\ - WithSubAccounts, WithDeleted, WOPInfo, \n\ - and WOPLimits \n\ + WithSubAccounts, WithDeleted, WOLimits, \n\ + WOPInfo, and WOPLimits \n\ \n\ - list cluster - Format=, Names= \n\ + list cluster - Format=, Names=, WOLimits \n\ add cluster - Fairshare=, GrpCPUs=, GrpJobs=, \n\ GrpNodes=, GrpSubmitJob=, MaxCPUMins= \n\ MaxJobs=, MaxNodes=, MaxWall=, and Name= \n\ diff --git a/src/sacctmgr/user_functions.c b/src/sacctmgr/user_functions.c index 19d9d76114a..fd8c03840c8 100644 --- a/src/sacctmgr/user_functions.c +++ b/src/sacctmgr/user_functions.c @@ -638,6 +638,25 @@ static int _check_coord_request(acct_user_cond_t *user_cond, bool check) return rc; } +static int _check_user_has_acct(char *user, char *acct) +{ + acct_association_cond_t assoc_cond; + List ret_list = NULL; + + memset(&assoc_cond, 0, sizeof(acct_association_cond_t)); + assoc_cond.acct_list = list_create(NULL); + list_push(assoc_cond.acct_list, acct); + assoc_cond.user_list = list_create(NULL); + list_push(assoc_cond.user_list, user); + ret_list = acct_storage_g_get_associations(db_conn, my_uid, + &assoc_cond); + + if(ret_list && (list_count(ret_list))) + return 1; + + return 0; +} + extern int sacctmgr_add_user(int argc, char *argv[]) { int rc = SLURM_SUCCESS; @@ -735,7 +754,7 @@ extern int sacctmgr_add_user(int argc, char *argv[]) } default_acct = strip_quotes(argv[i]+end, NULL, 1); slurm_addto_char_list(assoc_cond->acct_list, - default_acct); + default_acct); } else if (!strncasecmp (argv[i], "DefaultWCKey", MAX(command_len, 8))) { if(default_wckey) { @@ -2109,7 +2128,7 @@ extern int sacctmgr_modify_user(int argc, char *argv[]) return SLURM_SUCCESS; } } - + notice_thread_init(); if(rec_set == 3 || rec_set == 1) { // process the account changes if(cond_set == 2) { @@ -2137,18 +2156,57 @@ extern int sacctmgr_modify_user(int argc, char *argv[]) } notice_thread_init(); } - + ret_list = acct_storage_g_modify_users( db_conn, my_uid, user_cond, user); if(ret_list && list_count(ret_list)) { char *object = NULL; + List regret_list = NULL; ListIterator itr = list_iterator_create(ret_list); - printf(" Modified users...\n"); + while((object = list_next(itr))) { - printf(" %s\n", object); + /* We have to check here for the user names to + * make sure the user has an association with + * the new default account. We have to wait + * until we get the ret_list of names since + * names are required to change a user since + * you can specfy a user by something else + * like default_account or something. If the + * user doesn't have the account make + * note of it. + */ + if(user->default_acct && + !_check_user_has_acct( + object, user->default_acct)) { + if(!regret_list) + regret_list = list_create(NULL); + list_append(regret_list, object); + continue; + } + } + if(regret_list) { + list_iterator_destroy(itr); + itr = list_iterator_create(regret_list); + printf(" Can modify because these users " + "aren't associated with new " + "default account '%s'...\n", + user->default_acct); + while((object = list_next(itr))) { + printf(" %s\n", object); + } + list_iterator_destroy(itr); + exit_code=1; + rc = SLURM_ERROR; + list_destroy(regret_list); + } else { + list_iterator_reset(itr); + printf(" Modified users...\n"); + while((object = list_next(itr))) { + printf(" %s\n", object); + } + list_iterator_destroy(itr); + set = 1; } - list_iterator_destroy(itr); - set = 1; } else if(ret_list) { printf(" Nothing modified\n"); } else { -- GitLab