| /*****************************************************************************\ |
| * as_mysql_user.c - functions dealing with users and coordinators. |
| ***************************************************************************** |
| * Copyright (C) 2004-2007 The Regents of the University of California. |
| * Copyright (C) 2008-2010 Lawrence Livermore National Security. |
| * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). |
| * Written by Danny Auble <da@llnl.gov> |
| * |
| * This file is part of Slurm, a resource management program. |
| * For details, see <https://slurm.schedmd.com/>. |
| * Please also read the included file: DISCLAIMER. |
| * |
| * Slurm is free software; you can redistribute it and/or modify it under |
| * the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| * |
| * In addition, as a special exception, the copyright holders give permission |
| * to link the code of portions of this program with the OpenSSL library under |
| * certain conditions as described in each individual source file, and |
| * distribute linked combinations including the two. You must obey the GNU |
| * General Public License in all respects for all of the code used other than |
| * OpenSSL. If you modify file(s) with this exception, you may extend this |
| * exception to your version of the file(s), but you are not obligated to do |
| * so. If you do not wish to do so, delete this exception statement from your |
| * version. If you delete this exception statement from all source files in |
| * the program, then also delete it here. |
| * |
| * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| * details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with Slurm; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| \*****************************************************************************/ |
| |
| #include "as_mysql_assoc.h" |
| #include "as_mysql_user.h" |
| #include "as_mysql_wckey.h" |
| |
| typedef struct { |
| list_t *acct_list; /* for coords, a list of just char * instead of |
| * slurmdb_coord_rec_t */ |
| char *coord_query; |
| char *coord_query_pos; |
| mysql_conn_t *mysql_conn; |
| time_t now; |
| int rc; |
| bool ret_str_err; |
| char *ret_str; |
| char *ret_str_pos; |
| char *txn_query; |
| char *txn_query_pos; |
| slurmdb_user_rec_t *user_in; |
| char *user_name; |
| } add_user_cond_t; |
| |
| typedef struct { |
| char *extra; |
| char *query; |
| char *query_pos; |
| } create_string_t; |
| |
| static int _change_user_name(mysql_conn_t *mysql_conn, slurmdb_user_rec_t *user) |
| { |
| int rc = SLURM_SUCCESS; |
| char *query = NULL; |
| list_itr_t *itr = NULL; |
| char *cluster_name = NULL; |
| |
| xassert(user->old_name); |
| xassert(user->name); |
| |
| slurm_rwlock_rdlock(&as_mysql_cluster_list_lock); |
| itr = list_iterator_create(as_mysql_cluster_list); |
| while ((cluster_name = list_next(itr))) { |
| // Change assoc_tables |
| xstrfmtcat(query, "update \"%s_%s\" set user='%s', " |
| "lineage=replace(lineage, '0-%s', '0-%s') " |
| "where user='%s';", cluster_name, assoc_table, |
| user->name, user->old_name, |
| user->name, user->old_name); |
| // Change wckey_tables |
| xstrfmtcat(query, "update \"%s_%s\" set user='%s' " |
| "where user='%s';", cluster_name, wckey_table, |
| user->name, user->old_name); |
| } |
| list_iterator_destroy(itr); |
| slurm_rwlock_unlock(&as_mysql_cluster_list_lock); |
| // Change coord_tables |
| xstrfmtcat(query, "update %s set user='%s' where user='%s';", |
| acct_coord_table, user->name, user->old_name); |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", query); |
| rc = mysql_db_query(mysql_conn, query); |
| xfree(query); |
| |
| if (rc != SLURM_SUCCESS) |
| reset_mysql_conn(mysql_conn); |
| |
| return rc; |
| } |
| |
| static list_t *_get_other_user_names_to_mod(mysql_conn_t *mysql_conn, |
| uint32_t uid, |
| slurmdb_user_cond_t *user_cond) |
| { |
| list_t *tmp_list = NULL; |
| list_t *ret_list = NULL; |
| list_itr_t *itr = NULL; |
| |
| slurmdb_assoc_cond_t assoc_cond; |
| slurmdb_wckey_cond_t wckey_cond; |
| |
| if (!user_cond->def_acct_list || !list_count(user_cond->def_acct_list)) |
| goto no_assocs; |
| |
| /* We have to use a different association_cond here because |
| other things could be set here we don't care about in the |
| user's. (So to be safe just move over the info we care about) */ |
| memset(&assoc_cond, 0, sizeof(slurmdb_assoc_cond_t)); |
| assoc_cond.acct_list = user_cond->def_acct_list; |
| if (user_cond->assoc_cond) { |
| if (user_cond->assoc_cond->cluster_list) |
| assoc_cond.cluster_list = |
| user_cond->assoc_cond->cluster_list; |
| if (user_cond->assoc_cond->user_list) |
| assoc_cond.user_list = user_cond->assoc_cond->user_list; |
| } |
| assoc_cond.flags |= ASSOC_COND_FLAG_ONLY_DEFS; |
| tmp_list = as_mysql_get_assocs(mysql_conn, uid, &assoc_cond); |
| if (tmp_list) { |
| slurmdb_assoc_rec_t *object = NULL; |
| itr = list_iterator_create(tmp_list); |
| while ((object = list_next(itr))) { |
| if (!ret_list) |
| ret_list = list_create(xfree_ptr); |
| slurm_addto_char_list(ret_list, object->user); |
| } |
| list_iterator_destroy(itr); |
| FREE_NULL_LIST(tmp_list); |
| } |
| |
| no_assocs: |
| if (!user_cond->def_wckey_list |
| || !list_count(user_cond->def_wckey_list)) |
| goto no_wckeys; |
| |
| memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t)); |
| if (user_cond->assoc_cond) { |
| if (user_cond->assoc_cond->cluster_list) |
| wckey_cond.cluster_list = |
| user_cond->assoc_cond->cluster_list; |
| if (user_cond->assoc_cond->user_list) |
| wckey_cond.user_list = user_cond->assoc_cond->user_list; |
| } |
| wckey_cond.name_list = user_cond->def_wckey_list; |
| wckey_cond.only_defs = 1; |
| |
| tmp_list = as_mysql_get_wckeys(mysql_conn, uid, &wckey_cond); |
| if (tmp_list) { |
| slurmdb_wckey_rec_t *object = NULL; |
| itr = list_iterator_create(tmp_list); |
| while ((object = list_next(itr))) { |
| if (!ret_list) |
| ret_list = list_create(xfree_ptr); |
| slurm_addto_char_list(ret_list, object->user); |
| } |
| list_iterator_destroy(itr); |
| FREE_NULL_LIST(tmp_list); |
| } |
| |
| no_wckeys: |
| |
| return ret_list; |
| } |
| |
| static int _find_user(void *x, void *arg) |
| { |
| slurmdb_user_rec_t *user_rec = x; |
| char *name = arg; |
| |
| if (!user_rec) |
| return 0; |
| |
| return slurm_find_char_exact_in_list(user_rec->name, name); |
| } |
| |
| static int _transfer_coords(void *x, void *arg) |
| { |
| slurmdb_coord_rec_t *coord = x; |
| slurmdb_user_rec_t *user = arg; |
| slurmdb_coord_rec_t *coord_add; |
| |
| if (assoc_mgr_is_user_acct_coord_user_rec(user, coord->name)) |
| return 0; |
| |
| coord_add = xmalloc(sizeof(*coord_add)); |
| coord_add->name = xstrdup(coord->name); |
| coord_add->direct = coord->direct; |
| list_append(user->coord_accts, coord_add); |
| |
| debug2("adding %s to coord_accts for user %s %s", |
| coord->name, user->name, |
| coord->direct ? "directly" : "indirectly"); |
| |
| return 0; |
| } |
| |
| /* Fill in all the accounts this user is coordinator over. This |
| * will fill in all the sub accounts they are coordinator over also. |
| */ |
| static int _get_user_coords(mysql_conn_t *mysql_conn, slurmdb_user_rec_t *user) |
| { |
| slurmdb_user_rec_t *user2; |
| |
| if (!user) { |
| error("We need a user to fill in."); |
| return SLURM_ERROR; |
| } |
| |
| if (!user->coord_accts) |
| user->coord_accts = list_create(slurmdb_destroy_coord_rec); |
| else |
| list_flush(user->coord_accts); |
| |
| if (g_user_coords_list && |
| (user2 = list_find_first(g_user_coords_list, |
| _find_user, |
| user->name))) { |
| (void) list_for_each(user2->coord_accts, _transfer_coords, |
| user); |
| } |
| return SLURM_SUCCESS; |
| } |
| |
| static int _foreach_add_coord(void *x, void *arg) |
| { |
| slurmdb_coord_rec_t *coord = x; |
| add_user_cond_t *add_user_cond = arg; |
| |
| if (!add_user_cond->coord_query) |
| xstrfmtcatat(add_user_cond->coord_query, |
| &add_user_cond->coord_query_pos, |
| "insert into %s (creation_time, mod_time, acct, user) values ", |
| acct_coord_table); |
| else |
| xstrcatat(add_user_cond->coord_query, |
| &add_user_cond->coord_query_pos, |
| ", "); |
| |
| xstrfmtcatat(add_user_cond->coord_query, |
| &add_user_cond->coord_query_pos, |
| "(%ld, %ld, '%s', '%s')", |
| add_user_cond->now, add_user_cond->now, coord->name, |
| add_user_cond->user_in->name); |
| |
| if (!add_user_cond->txn_query) |
| xstrfmtcatat(add_user_cond->txn_query, |
| &add_user_cond->txn_query_pos, |
| "insert into %s (timestamp, action, name, actor, info) values ", |
| txn_table); |
| else |
| xstrcatat(add_user_cond->txn_query, |
| &add_user_cond->txn_query_pos, |
| ", "); |
| |
| xstrfmtcatat(add_user_cond->txn_query, |
| &add_user_cond->txn_query_pos, |
| "(%ld, %u, '%s', '%s', '%s')", |
| add_user_cond->now, DBD_ADD_ACCOUNT_COORDS, |
| add_user_cond->user_in->name, |
| add_user_cond->user_name, coord->name); |
| |
| return 0; |
| } |
| |
| static int _foreach_add_acct(void *x, void *arg) |
| { |
| char *acct = x; |
| list_t *coord_accts = arg; |
| slurmdb_coord_rec_t *coord = xmalloc(sizeof(*coord)); |
| |
| coord->name = xstrdup(acct); |
| coord->direct = 1; |
| list_append(coord_accts, coord); |
| |
| return 0; |
| } |
| |
| static int _add_coords(add_user_cond_t *add_user_cond) |
| { |
| xassert(add_user_cond); |
| xassert(add_user_cond->mysql_conn); |
| xassert(add_user_cond->user_in); |
| |
| if (add_user_cond->acct_list && list_count(add_user_cond->acct_list)) { |
| if (add_user_cond->user_in->coord_accts) |
| list_flush(add_user_cond->user_in->coord_accts); |
| else |
| add_user_cond->user_in->coord_accts = |
| list_create(slurmdb_destroy_coord_rec); |
| (void) list_for_each(add_user_cond->acct_list, |
| _foreach_add_acct, |
| add_user_cond->user_in->coord_accts); |
| } |
| |
| if (add_user_cond->user_in->coord_accts && |
| list_count(add_user_cond->user_in->coord_accts)) |
| (void) list_for_each(add_user_cond->user_in->coord_accts, |
| _foreach_add_coord, |
| add_user_cond); |
| |
| if (add_user_cond->coord_query) { |
| int rc = SLURM_SUCCESS; |
| xstrfmtcat(add_user_cond->coord_query, |
| " on duplicate key update mod_time=%ld, deleted=0, user=VALUES(user);", |
| add_user_cond->now); |
| DB_DEBUG(DB_ASSOC, add_user_cond->mysql_conn->conn, "query\n%s", |
| add_user_cond->coord_query); |
| rc = mysql_db_query(add_user_cond->mysql_conn, |
| add_user_cond->coord_query); |
| xfree(add_user_cond->coord_query); |
| add_user_cond->coord_query_pos = NULL; |
| |
| if (rc != SLURM_SUCCESS) { |
| error("Couldn't add coords"); |
| return ESLURM_BAD_SQL; |
| } |
| } |
| |
| as_mysql_user_create_user_coords_list(add_user_cond->mysql_conn); |
| _get_user_coords(add_user_cond->mysql_conn, add_user_cond->user_in); |
| |
| return SLURM_SUCCESS; |
| } |
| |
| static int _foreach_add_user(void *x, void *arg) |
| { |
| char *name = x; |
| add_user_cond_t *add_user_cond = arg; |
| slurmdb_user_rec_t *object, check_object; |
| char *extra, *tmp_extra; |
| int rc; |
| char *query; |
| |
| /* Check to see if it is already in the assoc_mgr */ |
| memset(&check_object, 0, sizeof(check_object)); |
| check_object.name = x; |
| check_object.uid = NO_VAL; |
| |
| rc = assoc_mgr_fill_in_user(add_user_cond->mysql_conn, |
| &check_object, |
| ACCOUNTING_ENFORCE_ASSOCS, NULL, false); |
| if (rc == SLURM_SUCCESS) { |
| debug2("User %s is already here, not adding again.", |
| check_object.name); |
| return 0; |
| } |
| |
| /* Else, add it */ |
| object = xmalloc(sizeof(*object)); |
| object->name = xstrdup(x); |
| object->admin_level = add_user_cond->user_in->admin_level; |
| object->coord_accts = slurmdb_list_copy_coord( |
| add_user_cond->user_in->coord_accts); |
| |
| query = xstrdup_printf( |
| "insert into %s (creation_time, mod_time, name, admin_level) values (%ld, %ld, '%s', %u) on duplicate key update deleted=0, mod_time=VALUES(mod_time), admin_level=VALUES(admin_level);", |
| user_table, add_user_cond->now, add_user_cond->now, |
| object->name, object->admin_level); |
| |
| DB_DEBUG(DB_ASSOC, add_user_cond->mysql_conn->conn, "query:\n%s", |
| query); |
| add_user_cond->rc = mysql_db_query(add_user_cond->mysql_conn, query); |
| xfree(query); |
| if (add_user_cond->rc != SLURM_SUCCESS) { |
| add_user_cond->rc = ESLURM_BAD_SQL; |
| add_user_cond->ret_str_err = true; |
| xfree(add_user_cond->ret_str); |
| add_user_cond->ret_str = xstrdup_printf( |
| "Couldn't add user %s: %s", |
| object->name, slurm_strerror(add_user_cond->rc)); |
| slurmdb_destroy_user_rec(object); |
| error("%s", add_user_cond->ret_str); |
| return -1; |
| } |
| |
| if (object->coord_accts) { |
| slurmdb_user_rec_t *user_rec = add_user_cond->user_in; |
| add_user_cond->user_in = object; |
| add_user_cond->rc = _add_coords(add_user_cond); |
| add_user_cond->user_in = user_rec; |
| } else { |
| add_user_cond->rc = |
| _get_user_coords(add_user_cond->mysql_conn, object); |
| } |
| |
| if (add_user_cond->rc != SLURM_SUCCESS) { |
| slurmdb_destroy_user_rec(object); |
| return -1; |
| } |
| |
| extra = xstrdup_printf("admin_level=%u", object->admin_level); |
| tmp_extra = slurm_add_slash_to_quotes(extra); |
| |
| if (!add_user_cond->txn_query) |
| xstrfmtcatat(add_user_cond->txn_query, |
| &add_user_cond->txn_query_pos, |
| "insert into %s (timestamp, action, name, actor, info) values ", |
| txn_table); |
| else |
| xstrcatat(add_user_cond->txn_query, |
| &add_user_cond->txn_query_pos, |
| ", "); |
| |
| xstrfmtcatat(add_user_cond->txn_query, |
| &add_user_cond->txn_query_pos, |
| "(%ld, %u, '%s', '%s', '%s')", |
| add_user_cond->now, DBD_ADD_USERS, name, |
| add_user_cond->user_name, tmp_extra); |
| xfree(tmp_extra); |
| xfree(extra); |
| |
| if (addto_update_list(add_user_cond->mysql_conn->update_list, |
| SLURMDB_ADD_USER, |
| object) == SLURM_SUCCESS) { |
| if (!add_user_cond->ret_str) |
| xstrcatat(add_user_cond->ret_str, |
| &add_user_cond->ret_str_pos, |
| " Adding User(s)\n"); |
| |
| xstrfmtcatat(add_user_cond->ret_str, |
| &add_user_cond->ret_str_pos, |
| " %s\n", object->name); |
| object = NULL; |
| } |
| |
| slurmdb_destroy_user_rec(object); |
| |
| return 0; |
| } |
| |
| extern int as_mysql_add_users(mysql_conn_t *mysql_conn, uint32_t uid, |
| list_t *user_list) |
| { |
| list_itr_t *itr = NULL; |
| int rc = SLURM_SUCCESS; |
| slurmdb_user_rec_t *object = NULL; |
| char *cols = NULL, *vals = NULL, *query = NULL, *txn_query = NULL; |
| char *txn_query_pos = NULL; |
| time_t now = time(NULL); |
| char *user_name = NULL; |
| char *extra = NULL, *tmp_extra = NULL; |
| int affect_rows = 0; |
| list_t *assoc_list; |
| list_t *wckey_list; |
| bool is_admin = false; |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return ESLURM_DB_CONNECTION; |
| |
| if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) { |
| slurmdb_user_rec_t user; |
| |
| if (slurmdbd_conf->flags & DBD_CONF_FLAG_DISABLE_COORD_DBD) { |
| error("Coordinator privilege revoked with DisableCoordDBD, only admins/operators can add accounts."); |
| return ESLURM_ACCESS_DENIED; |
| } |
| |
| memset(&user, 0, sizeof(slurmdb_user_rec_t)); |
| user.uid = uid; |
| |
| if (!is_user_any_coord(mysql_conn, &user)) { |
| error("Only admins/operators/coordinators " |
| "can add accounts"); |
| return ESLURM_ACCESS_DENIED; |
| } |
| /* If the user is a coord of any acct they can add |
| * accounts they are only able to make associations to |
| * these accounts if they are coordinators of the |
| * parent they are trying to add to |
| */ |
| } else { |
| is_admin = true; |
| } |
| |
| if (!user_list || !list_count(user_list)) { |
| error("%s: Trying to add empty user list", __func__); |
| return ESLURM_EMPTY_LIST; |
| } |
| |
| assoc_list = list_create(slurmdb_destroy_assoc_rec); |
| wckey_list = list_create(slurmdb_destroy_wckey_rec); |
| |
| user_name = uid_to_string((uid_t) uid); |
| itr = list_iterator_create(user_list); |
| while ((object = list_next(itr))) { |
| if (!object->name || !object->name[0]) { |
| error("We need a user name and " |
| "default acct to add."); |
| rc = SLURM_ERROR; |
| continue; |
| } |
| |
| xstrcat(cols, "creation_time, mod_time, name"); |
| xstrfmtcat(vals, "%ld, %ld, '%s'", |
| (long)now, (long)now, object->name); |
| |
| if (object->admin_level != SLURMDB_ADMIN_NOTSET) { |
| if (!is_admin) { |
| error("Only admins/operators can add an admin/operator"); |
| rc = ESLURM_ACCESS_DENIED; |
| break; |
| } |
| xstrcat(cols, ", admin_level"); |
| xstrfmtcat(vals, ", %u", object->admin_level); |
| xstrfmtcat(extra, ", admin_level=%u", |
| object->admin_level); |
| } else |
| xstrfmtcat(extra, ", admin_level=%u", |
| SLURMDB_ADMIN_NONE); |
| |
| query = xstrdup_printf( |
| "insert into %s (%s) values (%s) " |
| "on duplicate key update name=VALUES(name), deleted=0, mod_time=%ld %s;", |
| user_table, cols, vals, |
| (long)now, extra); |
| xfree(cols); |
| xfree(vals); |
| |
| rc = mysql_db_query(mysql_conn, query); |
| xfree(query); |
| if (rc != SLURM_SUCCESS) { |
| error("Couldn't add user %s", object->name); |
| xfree(extra); |
| continue; |
| } |
| |
| affect_rows = last_affected_rows(mysql_conn); |
| if (!affect_rows) { |
| debug("nothing changed"); |
| xfree(extra); |
| continue; |
| } |
| |
| if (object->coord_accts) { |
| add_user_cond_t add_user_cond; |
| memset(&add_user_cond, 0, sizeof(add_user_cond)); |
| add_user_cond.user_in = object; |
| add_user_cond.mysql_conn = mysql_conn; |
| add_user_cond.user_name = user_name; |
| add_user_cond.now = now; |
| add_user_cond.txn_query = txn_query; |
| add_user_cond.txn_query_pos = txn_query_pos; |
| rc = _add_coords(&add_user_cond); |
| txn_query = add_user_cond.txn_query; |
| txn_query_pos = add_user_cond.txn_query_pos; |
| } else { |
| rc = _get_user_coords(mysql_conn, object); |
| } |
| |
| if (rc != SLURM_SUCCESS) |
| continue; |
| |
| if (addto_update_list(mysql_conn->update_list, SLURMDB_ADD_USER, |
| object) == SLURM_SUCCESS) |
| list_remove(itr); |
| |
| /* we always have a ', ' as the first 2 chars */ |
| tmp_extra = slurm_add_slash_to_quotes(extra+2); |
| |
| if (txn_query) |
| xstrfmtcatat(txn_query, &txn_query_pos, |
| ", (%ld, %u, '%s', '%s', '%s')", |
| (long)now, DBD_ADD_USERS, object->name, |
| user_name, tmp_extra); |
| else |
| xstrfmtcatat(txn_query, &txn_query_pos, |
| "insert into %s " |
| "(timestamp, action, name, actor, info) " |
| "values (%ld, %u, '%s', '%s', '%s')", |
| txn_table, |
| (long)now, DBD_ADD_USERS, object->name, |
| user_name, tmp_extra); |
| xfree(tmp_extra); |
| xfree(extra); |
| if (object->assoc_list) |
| list_transfer(assoc_list, object->assoc_list); |
| |
| if (object->wckey_list) |
| list_transfer(wckey_list, object->wckey_list); |
| } |
| list_iterator_destroy(itr); |
| xfree(user_name); |
| |
| if (rc == SLURM_SUCCESS) { |
| if (txn_query) { |
| xstrcat(txn_query, ";"); |
| rc = mysql_db_query(mysql_conn, |
| txn_query); |
| xfree(txn_query); |
| if (rc != SLURM_SUCCESS) { |
| error("Couldn't add txn"); |
| rc = SLURM_SUCCESS; |
| } |
| } |
| } else |
| xfree(txn_query); |
| |
| if (list_count(assoc_list)) { |
| if ((rc = as_mysql_add_assocs(mysql_conn, uid, assoc_list)) != |
| SLURM_SUCCESS) |
| error("Problem adding user associations"); |
| } |
| FREE_NULL_LIST(assoc_list); |
| |
| if (rc == SLURM_SUCCESS && list_count(wckey_list)) { |
| if ((rc = as_mysql_add_wckeys(mysql_conn, uid, wckey_list)) != |
| SLURM_SUCCESS) |
| error("Problem adding user wckeys"); |
| } |
| FREE_NULL_LIST(wckey_list); |
| return rc; |
| } |
| |
| extern char *as_mysql_add_users_cond(mysql_conn_t *mysql_conn, uint32_t uid, |
| slurmdb_add_assoc_cond_t *add_assoc, |
| slurmdb_user_rec_t *user) |
| { |
| add_user_cond_t add_user_cond; |
| char *ret_str = NULL; |
| bool admin_set = false; |
| int rc; |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) { |
| errno = ESLURM_DB_CONNECTION; |
| return NULL; |
| } |
| |
| if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) { |
| slurmdb_user_rec_t user_coord = { |
| .uid = uid, |
| }; |
| |
| if (user->admin_level != SLURMDB_ADMIN_NOTSET) { |
| ret_str = xstrdup("Only admins/operators can add an admin/operator"); |
| error("%s", ret_str); |
| errno = ESLURM_ACCESS_DENIED; |
| return ret_str; |
| } |
| |
| if (slurmdbd_conf->flags & DBD_CONF_FLAG_DISABLE_COORD_DBD) { |
| ret_str = xstrdup("Coordinator privilege revoked with DisableCoordDBD, only admins/operators can add accounts."); |
| error("%s", ret_str); |
| errno = ESLURM_ACCESS_DENIED; |
| return ret_str; |
| } |
| |
| if (!is_user_any_coord(mysql_conn, &user_coord)) { |
| ret_str = xstrdup("Only admins/operators/coordinators can add accounts"); |
| error("%s", ret_str); |
| errno = ESLURM_ACCESS_DENIED; |
| return ret_str; |
| } |
| /* |
| * If the user is a coord of any acct they can add |
| * accounts they are only able to make associations to |
| * these accounts if they are coordinators of the |
| * parent they are trying to add to |
| */ |
| } |
| |
| if (user->admin_level == SLURMDB_ADMIN_NOTSET) |
| user->admin_level = SLURMDB_ADMIN_NONE; |
| else |
| admin_set = true; |
| |
| memset(&add_user_cond, 0, sizeof(add_user_cond)); |
| add_user_cond.user_in = user; |
| add_user_cond.mysql_conn = mysql_conn; |
| add_user_cond.now = time(NULL); |
| add_user_cond.user_name = uid_to_string((uid_t) uid); |
| |
| /* First add the accounts to the user_table. */ |
| if (list_for_each_ro(add_assoc->user_list, _foreach_add_user, |
| &add_user_cond) < 0) { |
| xfree(add_user_cond.ret_str); |
| xfree(add_user_cond.txn_query); |
| xfree(add_user_cond.user_name); |
| errno = add_user_cond.rc; |
| return NULL; |
| } |
| |
| if (add_user_cond.txn_query) { |
| /* Success means we add the defaults to the string */ |
| xstrcatat(add_user_cond.ret_str, |
| &add_user_cond.ret_str_pos, |
| " Settings\n"); |
| if (user->default_acct) |
| xstrfmtcatat(add_user_cond.ret_str, |
| &add_user_cond.ret_str_pos, |
| " Default Account = %s\n", |
| user->default_acct); |
| if (user->default_wckey) |
| xstrfmtcatat(add_user_cond.ret_str, |
| &add_user_cond.ret_str_pos, |
| " Default WCKey = %s\n", |
| user->default_wckey); |
| if (admin_set) |
| xstrfmtcatat(add_user_cond.ret_str, |
| &add_user_cond.ret_str_pos, |
| " Admin Level = %s\n", |
| slurmdb_admin_level_str( |
| user->admin_level)); |
| |
| xstrcatat(add_user_cond.txn_query, |
| &add_user_cond.txn_query_pos, |
| ";"); |
| rc = mysql_db_query(mysql_conn, add_user_cond.txn_query); |
| xfree(add_user_cond.txn_query); |
| if (rc != SLURM_SUCCESS) { |
| error("Couldn't add txn"); |
| rc = SLURM_SUCCESS; |
| } |
| } |
| |
| if (add_assoc->acct_list) { |
| /* Now add the associations */ |
| add_assoc->default_acct = user->default_acct; |
| ret_str = as_mysql_add_assocs_cond(mysql_conn, uid, add_assoc); |
| rc = errno; |
| add_assoc->default_acct = NULL; |
| |
| if (rc != SLURM_SUCCESS) { |
| reset_mysql_conn(mysql_conn); |
| if (!add_user_cond.ret_str_err) |
| xfree(add_user_cond.ret_str); |
| else |
| xfree(ret_str); |
| xfree(add_user_cond.txn_query); |
| xfree(add_user_cond.user_name); |
| errno = rc; |
| return add_user_cond.ret_str ? |
| add_user_cond.ret_str : ret_str; |
| } |
| |
| if (ret_str) { |
| xstrcatat(add_user_cond.ret_str, |
| &add_user_cond.ret_str_pos, |
| ret_str); |
| xfree(ret_str); |
| } |
| } |
| |
| if (add_assoc->wckey_list) { |
| ret_str = as_mysql_add_wckeys_cond( |
| mysql_conn, uid, add_assoc, user); |
| rc = errno; |
| |
| if (rc != SLURM_SUCCESS) { |
| reset_mysql_conn(mysql_conn); |
| if (!add_user_cond.ret_str_err) |
| xfree(add_user_cond.ret_str); |
| else |
| xfree(ret_str); |
| xfree(add_user_cond.txn_query); |
| xfree(add_user_cond.user_name); |
| errno = rc; |
| return add_user_cond.ret_str ? |
| add_user_cond.ret_str : ret_str; |
| } |
| |
| if (ret_str) { |
| xstrcatat(add_user_cond.ret_str, |
| &add_user_cond.ret_str_pos, |
| ret_str); |
| xfree(ret_str); |
| } |
| } |
| |
| xfree(add_user_cond.txn_query); |
| xfree(add_user_cond.user_name); |
| |
| if (!add_user_cond.ret_str) { |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "didn't affect anything"); |
| errno = SLURM_NO_CHANGE_IN_DATA; |
| return NULL; |
| } |
| |
| errno = SLURM_SUCCESS; |
| return add_user_cond.ret_str; |
| } |
| |
| extern int as_mysql_add_coord(mysql_conn_t *mysql_conn, uint32_t uid, |
| list_t *acct_list, slurmdb_user_cond_t *user_cond) |
| { |
| char *user = NULL; |
| list_itr_t *itr; |
| int rc = SLURM_SUCCESS; |
| add_user_cond_t add_user_cond; |
| |
| if (!user_cond || !user_cond->assoc_cond |
| || !user_cond->assoc_cond->user_list |
| || !list_count(user_cond->assoc_cond->user_list) |
| || !acct_list || !list_count(acct_list)) { |
| error("we need something to add"); |
| return SLURM_ERROR; |
| } |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return ESLURM_DB_CONNECTION; |
| |
| if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) { |
| slurmdb_user_rec_t user; |
| slurmdb_coord_rec_t *coord = NULL; |
| char *acct = NULL; |
| list_itr_t *itr2; |
| |
| if (slurmdbd_conf->flags & DBD_CONF_FLAG_DISABLE_COORD_DBD) { |
| error("Coordinator privilege revoked with DisableCoordDBD, only admins/operators can add account coordinators."); |
| return ESLURM_ACCESS_DENIED; |
| } |
| |
| memset(&user, 0, sizeof(slurmdb_user_rec_t)); |
| user.uid = uid; |
| |
| if (!is_user_any_coord(mysql_conn, &user)) { |
| error("Only admins/operators/coordinators " |
| "can add account coordinators"); |
| return ESLURM_ACCESS_DENIED; |
| } |
| |
| itr = list_iterator_create(acct_list); |
| itr2 = list_iterator_create(user.coord_accts); |
| while ((acct = list_next(itr))) { |
| while ((coord = list_next(itr2))) { |
| if (!xstrcasecmp(coord->name, acct)) |
| break; |
| } |
| if (!coord) |
| break; |
| list_iterator_reset(itr2); |
| } |
| list_iterator_destroy(itr2); |
| list_iterator_destroy(itr); |
| |
| if (!coord) { |
| error("Coordinator %s(%d) tried to add another " |
| "coordinator to an account they aren't " |
| "coordinator over.", |
| user.name, user.uid); |
| return ESLURM_ACCESS_DENIED; |
| } |
| } |
| |
| memset(&add_user_cond, 0, sizeof(add_user_cond)); |
| add_user_cond.acct_list = acct_list; |
| add_user_cond.mysql_conn = mysql_conn; |
| add_user_cond.user_name = uid_to_string((uid_t) uid); |
| add_user_cond.now = time(NULL); |
| itr = list_iterator_create(user_cond->assoc_cond->user_list); |
| while ((user = list_next(itr))) { |
| if (!user[0]) |
| continue; |
| add_user_cond.user_in = xmalloc(sizeof(slurmdb_user_rec_t)); |
| add_user_cond.user_in->name = xstrdup(user); |
| |
| if ((rc = _add_coords(&add_user_cond)) != SLURM_SUCCESS) { |
| slurmdb_destroy_user_rec(add_user_cond.user_in); |
| xfree(add_user_cond.txn_query); |
| break; |
| } |
| |
| if ((rc = addto_update_list(mysql_conn->update_list, |
| SLURMDB_ADD_COORD, |
| add_user_cond.user_in)) != |
| SLURM_SUCCESS) { |
| slurmdb_destroy_user_rec(add_user_cond.user_in); |
| xfree(add_user_cond.txn_query); |
| break; |
| } |
| add_user_cond.user_in = NULL; |
| } |
| list_iterator_destroy(itr); |
| |
| xfree(add_user_cond.user_name); |
| |
| if (add_user_cond.txn_query) { |
| xstrcatat(add_user_cond.txn_query, |
| &add_user_cond.txn_query_pos, |
| ";"); |
| rc = mysql_db_query(mysql_conn, add_user_cond.txn_query); |
| xfree(add_user_cond.txn_query); |
| if (rc != SLURM_SUCCESS) { |
| error("Couldn't add txn"); |
| rc = SLURM_SUCCESS; |
| } |
| } |
| |
| return rc; |
| } |
| |
| extern list_t *as_mysql_modify_users(mysql_conn_t *mysql_conn, uint32_t uid, |
| slurmdb_user_cond_t *user_cond, |
| slurmdb_user_rec_t *user) |
| { |
| list_itr_t *itr = NULL; |
| list_t *ret_list = NULL; |
| int rc = SLURM_SUCCESS; |
| char *object = NULL; |
| char *vals = NULL, *extra = NULL, *query = NULL, *name_char = NULL; |
| time_t now = time(NULL); |
| char *user_name = NULL; |
| int set = 0; |
| MYSQL_RES *result = NULL; |
| MYSQL_ROW row; |
| |
| if (!user_cond || !user) { |
| error("we need something to change"); |
| return NULL; |
| } |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return NULL; |
| |
| if (user_cond->assoc_cond && user_cond->assoc_cond->user_list |
| && list_count(user_cond->assoc_cond->user_list)) { |
| set = 0; |
| xstrcat(extra, " && ("); |
| itr = list_iterator_create(user_cond->assoc_cond->user_list); |
| while ((object = list_next(itr))) { |
| if (set) |
| xstrcat(extra, " || "); |
| xstrfmtcat(extra, "name='%s'", object); |
| set = 1; |
| } |
| list_iterator_destroy(itr); |
| xstrcat(extra, ")"); |
| } |
| |
| if (user_cond->admin_level != SLURMDB_ADMIN_NOTSET) |
| xstrfmtcat(extra, " && admin_level=%u", |
| user_cond->admin_level); |
| |
| ret_list = _get_other_user_names_to_mod(mysql_conn, uid, user_cond); |
| |
| if (user->name) |
| xstrfmtcat(vals, ", name='%s'", user->name); |
| |
| if (user->admin_level != SLURMDB_ADMIN_NOTSET) |
| xstrfmtcat(vals, ", admin_level=%u", user->admin_level); |
| |
| if ((!extra && !ret_list) |
| || (!vals && !user->default_acct && !user->default_wckey)) { |
| errno = SLURM_NO_CHANGE_IN_DATA; |
| error("Nothing to change"); |
| return NULL; |
| } |
| |
| if (!extra) { |
| /* means we got a ret_list and don't need to look at |
| the user_table. */ |
| goto no_user_table; |
| } |
| |
| query = xstrdup_printf( |
| "select distinct name from %s where deleted=0 %s;", |
| user_table, extra); |
| xfree(extra); |
| if (!(result = mysql_db_query_ret( |
| mysql_conn, query, 0))) { |
| xfree(query); |
| FREE_NULL_LIST(ret_list); |
| return NULL; |
| } |
| |
| if (!ret_list) |
| ret_list = list_create(xfree_ptr); |
| while ((row = mysql_fetch_row(result))) { |
| slurmdb_user_rec_t *user_rec = NULL; |
| |
| object = row[0]; |
| slurm_addto_char_list(ret_list, object); |
| if (!name_char) |
| xstrfmtcat(name_char, "(name='%s'", object); |
| else |
| xstrfmtcat(name_char, " || name='%s'", object); |
| |
| user_rec = xmalloc(sizeof(slurmdb_user_rec_t)); |
| |
| if (!user->name) |
| user_rec->name = xstrdup(object); |
| else { |
| user_rec->name = xstrdup(user->name); |
| user_rec->old_name = xstrdup(object); |
| if (_change_user_name(mysql_conn, user_rec) |
| != SLURM_SUCCESS) |
| break; |
| } |
| |
| user_rec->admin_level = user->admin_level; |
| if (addto_update_list(mysql_conn->update_list, |
| SLURMDB_MODIFY_USER, user_rec) |
| != SLURM_SUCCESS) |
| slurmdb_destroy_user_rec(user_rec); |
| } |
| mysql_free_result(result); |
| |
| no_user_table: |
| if (!list_count(ret_list)) { |
| errno = SLURM_NO_CHANGE_IN_DATA; |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, |
| "didn't affect anything\n%s", query); |
| xfree(vals); |
| xfree(query); |
| return ret_list; |
| } else if (user->name && (list_count(ret_list) != 1)) { |
| errno = ESLURM_ONE_CHANGE; |
| xfree(vals); |
| xfree(query); |
| FREE_NULL_LIST(ret_list); |
| return NULL; |
| } |
| |
| xfree(query); |
| |
| if (name_char && vals) { |
| xstrcat(name_char, ")"); |
| user_name = uid_to_string((uid_t) uid); |
| rc = modify_common(mysql_conn, DBD_MODIFY_USERS, now, |
| user_name, user_table, name_char, |
| vals, NULL); |
| xfree(user_name); |
| } |
| |
| xfree(name_char); |
| xfree(vals); |
| if (rc == SLURM_ERROR) { |
| error("Couldn't modify users"); |
| FREE_NULL_LIST(ret_list); |
| } |
| |
| if (user->default_acct && user->default_acct[0]) { |
| slurmdb_assoc_cond_t assoc_cond; |
| slurmdb_assoc_rec_t assoc; |
| list_t *tmp_list = NULL; |
| memset(&assoc_cond, 0, sizeof(slurmdb_assoc_cond_t)); |
| slurmdb_init_assoc_rec(&assoc, 0); |
| assoc.is_def = 1; |
| assoc_cond.acct_list = list_create(NULL); |
| list_append(assoc_cond.acct_list, user->default_acct); |
| assoc_cond.user_list = ret_list; |
| if (user_cond->assoc_cond |
| && user_cond->assoc_cond->cluster_list) |
| assoc_cond.cluster_list = |
| user_cond->assoc_cond->cluster_list; |
| tmp_list = as_mysql_modify_assocs(mysql_conn, uid, |
| &assoc_cond, &assoc); |
| FREE_NULL_LIST(assoc_cond.acct_list); |
| |
| if (!tmp_list) { |
| FREE_NULL_LIST(ret_list); |
| goto end_it; |
| } |
| /* char *names = NULL; */ |
| /* list_itr_t *itr = list_iterator_create(tmp_list); */ |
| /* while ((names = list_next(itr))) { */ |
| /* info("%s", names); */ |
| /* } */ |
| /* list_iterator_destroy(itr); */ |
| FREE_NULL_LIST(tmp_list); |
| } else if (user->default_acct) { |
| list_t *cluster_list = NULL; |
| if (user_cond->assoc_cond |
| && user_cond->assoc_cond->cluster_list) |
| cluster_list = user_cond->assoc_cond->cluster_list; |
| |
| rc = as_mysql_assoc_remove_default( |
| mysql_conn, ret_list, cluster_list); |
| if (rc != SLURM_SUCCESS) { |
| FREE_NULL_LIST(ret_list); |
| errno = rc; |
| goto end_it; |
| } |
| } |
| |
| if (user->default_wckey) { |
| slurmdb_wckey_cond_t wckey_cond; |
| slurmdb_wckey_rec_t wckey; |
| list_t *tmp_list = NULL; |
| |
| memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t)); |
| slurmdb_init_wckey_rec(&wckey, 0); |
| wckey.is_def = 1; |
| wckey_cond.name_list = list_create(NULL); |
| list_append(wckey_cond.name_list, user->default_wckey); |
| wckey_cond.user_list = ret_list; |
| if (user_cond->assoc_cond |
| && user_cond->assoc_cond->cluster_list) |
| wckey_cond.cluster_list = |
| user_cond->assoc_cond->cluster_list; |
| tmp_list = as_mysql_modify_wckeys(mysql_conn, uid, |
| &wckey_cond, &wckey); |
| FREE_NULL_LIST(wckey_cond.name_list); |
| |
| if (!tmp_list) { |
| FREE_NULL_LIST(ret_list); |
| goto end_it; |
| } |
| /* char *names = NULL; */ |
| /* list_itr_t *itr = list_iterator_create(tmp_list); */ |
| /* while ((names = list_next(itr))) { */ |
| /* info("%s", names); */ |
| /* } */ |
| /* list_iterator_destroy(itr); */ |
| FREE_NULL_LIST(tmp_list); |
| } |
| end_it: |
| errno = rc; |
| return ret_list; |
| } |
| |
| /* |
| * If the coordinator has permissions to modify every account |
| * belonging to each user, return true. Otherwise return false. |
| */ |
| static bool _is_coord_over_all_accts(mysql_conn_t *mysql_conn, |
| char *cluster_name, char *user_char, |
| slurmdb_user_rec_t *coord) |
| { |
| bool has_access; |
| char *query = NULL, *sep_str = ""; |
| MYSQL_RES *result; |
| list_itr_t *itr; |
| slurmdb_coord_rec_t *coord_acct; |
| |
| if (!coord->coord_accts || !list_count(coord->coord_accts)) { |
| /* This should never happen */ |
| error("%s: We are here with no coord accts", __func__); |
| return false; |
| } |
| |
| query = xstrdup_printf("select distinct acct from \"%s_%s\" where deleted=0 && (%s) && (", |
| cluster_name, assoc_table, user_char); |
| |
| /* |
| * Add the accounts we are coordinator of. If anything is returned |
| * outside of this list we will know there are accounts in the request |
| * that we are not coordinator over. |
| */ |
| itr = list_iterator_create(coord->coord_accts); |
| while ((coord_acct = (list_next(itr)))) { |
| xstrfmtcat(query, "%sacct != '%s'", sep_str, coord_acct->name); |
| sep_str = " && "; |
| } |
| list_iterator_destroy(itr); |
| xstrcat(query, ");"); |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", query); |
| if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) { |
| xfree(query); |
| return false; |
| } |
| xfree(query); |
| |
| /* |
| * If nothing was returned we are coordinator over all these accounts |
| * and users. |
| */ |
| has_access = !mysql_num_rows(result); |
| |
| mysql_free_result(result); |
| return has_access; |
| } |
| |
| extern list_t *as_mysql_remove_users(mysql_conn_t *mysql_conn, uint32_t uid, |
| slurmdb_user_cond_t *user_cond) |
| { |
| list_itr_t *itr = NULL; |
| list_t *ret_list = NULL; |
| list_t *coord_list = NULL; |
| int rc = SLURM_SUCCESS; |
| char *object = NULL; |
| char *extra = NULL, *query = NULL, |
| *name_char = NULL, *assoc_char = NULL, *user_char = NULL; |
| char *name_char_pos = NULL, *assoc_char_pos = NULL, |
| *user_char_pos = NULL; |
| time_t now = time(NULL); |
| int set = 0; |
| MYSQL_RES *result = NULL; |
| MYSQL_ROW row; |
| slurmdb_user_cond_t user_coord_cond; |
| slurmdb_user_rec_t user; |
| slurmdb_assoc_cond_t assoc_cond; |
| slurmdb_wckey_cond_t wckey_cond; |
| bool is_coord = false; |
| list_t *use_cluster_list; |
| |
| remove_common_args_t args = { |
| .jobs_running = false, |
| .mysql_conn = mysql_conn, |
| .now = now, |
| .table = user_table, |
| .type = DBD_REMOVE_USERS, |
| }; |
| |
| memset(&user, 0, sizeof(slurmdb_user_rec_t)); |
| user.uid = uid; |
| |
| if (!user_cond) { |
| error("we need something to remove"); |
| return NULL; |
| } |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return NULL; |
| |
| if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) { |
| if (slurmdbd_conf->flags & DBD_CONF_FLAG_DISABLE_COORD_DBD) { |
| error("Coordinator privilege revoked with DisableCoordDBD, only admins/operators can remove users."); |
| errno = ESLURM_ACCESS_DENIED; |
| return NULL; |
| } |
| |
| /* |
| * Allow coordinators to delete users from accounts that |
| * they coordinate. After we have gotten every association that |
| * the users belong to, check that the coordinator has access |
| * to modify every affected account. |
| */ |
| is_coord = is_user_any_coord(mysql_conn, &user); |
| if (!is_coord) { |
| error("Only admins/coordinators can remove users"); |
| errno = ESLURM_ACCESS_DENIED; |
| return NULL; |
| } |
| } |
| |
| if (user_cond->assoc_cond && user_cond->assoc_cond->user_list |
| && list_count(user_cond->assoc_cond->user_list)) { |
| set = 0; |
| itr = list_iterator_create(user_cond->assoc_cond->user_list); |
| while ((object = list_next(itr))) { |
| if (!object[0]) |
| continue; |
| if (set) |
| xstrcat(extra, " || "); |
| else |
| xstrcat(extra, " && ("); |
| |
| xstrfmtcat(extra, "name='%s'", object); |
| set = 1; |
| } |
| list_iterator_destroy(itr); |
| if (extra) |
| xstrcat(extra, ")"); |
| } |
| |
| ret_list = _get_other_user_names_to_mod(mysql_conn, uid, user_cond); |
| |
| if (user_cond->admin_level != SLURMDB_ADMIN_NOTSET) { |
| xstrfmtcat(extra, " && admin_level=%u", user_cond->admin_level); |
| } |
| |
| if (!extra && !ret_list) { |
| errno = SLURM_NO_CHANGE_IN_DATA; |
| error("Nothing to remove"); |
| return NULL; |
| } else if (!extra) { |
| /* means we got a ret_list and don't need to look at |
| the user_table. */ |
| goto no_user_table; |
| } |
| |
| /* Only handle this if we need to actually query the |
| user_table. If a request comes in stating they want to |
| remove all users with default account of whatever then that |
| doesn't deal with the user_table. |
| */ |
| query = xstrdup_printf("select name from %s where deleted=0 %s;", |
| user_table, extra); |
| xfree(extra); |
| if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) { |
| xfree(query); |
| return NULL; |
| } |
| |
| if (!ret_list) |
| ret_list = list_create(xfree_ptr); |
| while ((row = mysql_fetch_row(result))) |
| slurm_addto_char_list(ret_list, row[0]); |
| mysql_free_result(result); |
| |
| no_user_table: |
| |
| if (!list_count(ret_list)) { |
| errno = SLURM_NO_CHANGE_IN_DATA; |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, |
| "didn't affect anything\n%s", query); |
| xfree(query); |
| return ret_list; |
| } |
| xfree(query); |
| |
| memset(&user_coord_cond, 0, sizeof(slurmdb_user_cond_t)); |
| memset(&assoc_cond, 0, sizeof(slurmdb_assoc_cond_t)); |
| /* we do not need to free the objects we put in here since |
| they are also placed in a list that will be freed |
| */ |
| assoc_cond.user_list = list_create(NULL); |
| user_coord_cond.assoc_cond = &assoc_cond; |
| |
| itr = list_iterator_create(ret_list); |
| while ((object = list_next(itr))) { |
| slurmdb_user_rec_t *user_rec; |
| |
| /* |
| * Skip empty names or else will select account associations |
| * and remove all associations. |
| */ |
| if (!object[0]) { |
| list_delete_item(itr); |
| continue; |
| } |
| |
| user_rec = xmalloc(sizeof(slurmdb_user_rec_t)); |
| list_append(assoc_cond.user_list, object); |
| |
| if (name_char) { |
| xstrfmtcatat(name_char, &name_char_pos, ",'%s'", |
| object); |
| xstrfmtcatat(user_char, &user_char_pos, ",'%s'", |
| object); |
| } else { |
| xstrfmtcatat(name_char, &name_char_pos, "name in('%s'", |
| object); |
| xstrfmtcatat(user_char, &user_char_pos, "user in('%s'", |
| object); |
| } |
| xstrfmtcatat(assoc_char, &assoc_char_pos, |
| "%st2.lineage like '%%/0-%s/%%'", |
| assoc_char ? " || " : "", object); |
| |
| user_rec->name = xstrdup(object); |
| if (addto_update_list(mysql_conn->update_list, |
| SLURMDB_REMOVE_USER, user_rec) |
| != SLURM_SUCCESS) |
| slurmdb_destroy_user_rec(user_rec); |
| } |
| list_iterator_destroy(itr); |
| if (name_char) { |
| xstrcatat(name_char, &name_char_pos, ")"); |
| xstrcatat(user_char, &user_char_pos, ")"); |
| } |
| /* We need to remove these accounts from the coord's that have it */ |
| coord_list = as_mysql_remove_coord( |
| mysql_conn, uid, NULL, &user_coord_cond); |
| FREE_NULL_LIST(coord_list); |
| |
| /* We need to remove these users from the wckey table */ |
| memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t)); |
| wckey_cond.user_list = assoc_cond.user_list; |
| coord_list = as_mysql_remove_wckeys(mysql_conn, uid, &wckey_cond); |
| FREE_NULL_LIST(coord_list); |
| |
| FREE_NULL_LIST(assoc_cond.user_list); |
| |
| args.user_name = uid_to_string((uid_t) uid); |
| |
| slurm_rwlock_rdlock(&as_mysql_cluster_list_lock); |
| use_cluster_list = list_shallow_copy(as_mysql_cluster_list); |
| itr = list_iterator_create(use_cluster_list); |
| while ((object = list_next(itr))) { |
| |
| if (is_coord) { |
| if (!_is_coord_over_all_accts(mysql_conn, object, |
| user_char, &user)) { |
| errno = ESLURM_ACCESS_DENIED; |
| rc = SLURM_ERROR; |
| break; |
| } |
| } |
| } |
| list_iterator_destroy(itr); |
| |
| if (!rc) { |
| args.assoc_char = assoc_char; |
| args.name_char = name_char; |
| args.ret_list = ret_list; |
| args.use_cluster_list = use_cluster_list; |
| |
| rc = remove_common(&args); |
| } |
| |
| FREE_NULL_LIST(use_cluster_list); |
| slurm_rwlock_unlock(&as_mysql_cluster_list_lock); |
| |
| xfree(args.user_name); |
| xfree(name_char); |
| xfree(user_char); |
| if (rc == SLURM_ERROR) { |
| FREE_NULL_LIST(ret_list); |
| xfree(assoc_char); |
| return NULL; |
| } |
| |
| query = xstrdup_printf( |
| "update %s set deleted=1, mod_time=%ld where %s", |
| acct_coord_table, (long)now, user_char); |
| xfree(assoc_char); |
| |
| rc = mysql_db_query(mysql_conn, query); |
| xfree(query); |
| if (rc != SLURM_SUCCESS) { |
| error("Couldn't remove user coordinators"); |
| FREE_NULL_LIST(ret_list); |
| return NULL; |
| } |
| |
| if (args.jobs_running) |
| errno = ESLURM_JOBS_RUNNING_ON_ASSOC; |
| else { |
| as_mysql_user_create_user_coords_list(mysql_conn); |
| errno = SLURM_SUCCESS; |
| } |
| return ret_list; |
| } |
| |
| extern list_t *as_mysql_remove_coord(mysql_conn_t *mysql_conn, uint32_t uid, |
| list_t *acct_list, |
| slurmdb_user_cond_t *user_cond) |
| { |
| char *query = NULL, *object = NULL, *extra = NULL, *last_user = NULL; |
| time_t now = time(NULL); |
| int set = 0, is_admin=0, rc = SLURM_SUCCESS; |
| list_itr_t *itr = NULL; |
| slurmdb_user_rec_t *user_rec = NULL; |
| list_t *ret_list = NULL; |
| list_t *user_list = NULL; |
| MYSQL_RES *result = NULL; |
| MYSQL_ROW row; |
| slurmdb_user_rec_t user; |
| |
| remove_common_args_t args = { |
| .mysql_conn = mysql_conn, |
| .now = now, |
| .table = acct_coord_table, |
| .type = DBD_REMOVE_ACCOUNT_COORDS, |
| }; |
| |
| if (!user_cond && !acct_list) { |
| error("we need something to remove"); |
| return NULL; |
| } else if (user_cond && user_cond->assoc_cond) |
| user_list = user_cond->assoc_cond->user_list; |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return NULL; |
| |
| memset(&user, 0, sizeof(slurmdb_user_rec_t)); |
| user.uid = uid; |
| |
| if (!(is_admin = is_user_min_admin_level( |
| mysql_conn, uid, SLURMDB_ADMIN_OPERATOR))) { |
| if (slurmdbd_conf->flags & DBD_CONF_FLAG_DISABLE_COORD_DBD) { |
| error("Coordinator privilege revoked with DisableCoordDBD, only admins/operators can remove coordinators."); |
| errno = ESLURM_ACCESS_DENIED; |
| return NULL; |
| } |
| if (!is_user_any_coord(mysql_conn, &user)) { |
| error("Only admins/coordinators can " |
| "remove coordinators"); |
| errno = ESLURM_ACCESS_DENIED; |
| return NULL; |
| } |
| } |
| |
| /* Leave it this way since we are using extra below */ |
| |
| if (user_list && list_count(user_list)) { |
| set = 0; |
| if (extra) |
| xstrcat(extra, " && ("); |
| else |
| xstrcat(extra, "("); |
| |
| itr = list_iterator_create(user_list); |
| while ((object = list_next(itr))) { |
| if (!object[0]) |
| continue; |
| if (set) |
| xstrcat(extra, " || "); |
| xstrfmtcat(extra, "user='%s'", object); |
| set = 1; |
| } |
| list_iterator_destroy(itr); |
| xstrcat(extra, ")"); |
| } |
| |
| if (acct_list && list_count(acct_list)) { |
| set = 0; |
| if (extra) |
| xstrcat(extra, " && ("); |
| else |
| xstrcat(extra, "("); |
| |
| itr = list_iterator_create(acct_list); |
| while ((object = list_next(itr))) { |
| if (!object[0]) |
| continue; |
| if (set) |
| xstrcat(extra, " || "); |
| xstrfmtcat(extra, "acct='%s'", object); |
| set = 1; |
| } |
| list_iterator_destroy(itr); |
| xstrcat(extra, ")"); |
| } |
| |
| if (!extra) { |
| errno = SLURM_ERROR; |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "No conditions given"); |
| return NULL; |
| } |
| |
| query = xstrdup_printf( |
| "select user, acct from %s where deleted=0 && %s order by user", |
| acct_coord_table, extra); |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", query); |
| if (!(result = |
| mysql_db_query_ret(mysql_conn, query, 0))) { |
| xfree(query); |
| xfree(extra); |
| errno = SLURM_ERROR; |
| return NULL; |
| } |
| xfree(query); |
| ret_list = list_create(xfree_ptr); |
| user_list = list_create(xfree_ptr); |
| while ((row = mysql_fetch_row(result))) { |
| if (!is_admin) { |
| slurmdb_coord_rec_t *coord = NULL; |
| if (!user.coord_accts) { // This should never |
| // happen |
| error("We are here with no coord accts"); |
| errno = ESLURM_ACCESS_DENIED; |
| FREE_NULL_LIST(ret_list); |
| FREE_NULL_LIST(user_list); |
| xfree(extra); |
| mysql_free_result(result); |
| return NULL; |
| } |
| itr = list_iterator_create(user.coord_accts); |
| while ((coord = list_next(itr))) { |
| if (!xstrcasecmp(coord->name, row[1])) |
| break; |
| } |
| list_iterator_destroy(itr); |
| |
| if (!coord) { |
| error("User %s(%d) does not have the " |
| "ability to change this account (%s)", |
| user.name, user.uid, row[1]); |
| errno = ESLURM_ACCESS_DENIED; |
| FREE_NULL_LIST(ret_list); |
| FREE_NULL_LIST(user_list); |
| xfree(extra); |
| mysql_free_result(result); |
| return NULL; |
| } |
| } |
| if (!last_user || xstrcasecmp(last_user, row[0])) { |
| list_append(user_list, xstrdup(row[0])); |
| last_user = row[0]; |
| } |
| list_append(ret_list, xstrdup_printf("U = %-9s A = %-10s", |
| row[0], row[1])); |
| } |
| mysql_free_result(result); |
| |
| args.name_char = extra; |
| args.user_name = uid_to_string((uid_t) uid); |
| |
| rc = remove_common(&args); |
| |
| xfree(args.user_name); |
| xfree(extra); |
| if (rc == SLURM_ERROR) { |
| FREE_NULL_LIST(ret_list); |
| FREE_NULL_LIST(user_list); |
| errno = SLURM_ERROR; |
| return NULL; |
| } |
| |
| as_mysql_user_create_user_coords_list(mysql_conn); |
| |
| /* get the update list set */ |
| itr = list_iterator_create(user_list); |
| while ((last_user = list_next(itr))) { |
| user_rec = xmalloc(sizeof(slurmdb_user_rec_t)); |
| user_rec->name = xstrdup(last_user); |
| _get_user_coords(mysql_conn, user_rec); |
| if (addto_update_list(mysql_conn->update_list, |
| SLURMDB_REMOVE_COORD, user_rec) |
| != SLURM_SUCCESS) |
| slurmdb_destroy_user_rec(user_rec); |
| } |
| list_iterator_destroy(itr); |
| FREE_NULL_LIST(user_list); |
| |
| return ret_list; |
| } |
| |
| extern list_t *as_mysql_get_users(mysql_conn_t *mysql_conn, uid_t uid, |
| slurmdb_user_cond_t *user_cond) |
| { |
| char *query = NULL; |
| char *extra = NULL; |
| char *tmp = NULL; |
| list_t *user_list = NULL; |
| list_itr_t *itr = NULL; |
| char *object = NULL; |
| int set = 0; |
| int i=0; |
| MYSQL_RES *result = NULL; |
| MYSQL_ROW row; |
| slurmdb_user_rec_t user; |
| |
| /* if this changes you will need to edit the corresponding enum */ |
| char *user_req_inx[] = { |
| "name", |
| "admin_level", |
| "deleted", |
| }; |
| enum { |
| USER_REQ_NAME, |
| USER_REQ_AL, |
| USER_REQ_DELETED, |
| USER_REQ_COUNT |
| }; |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return NULL; |
| |
| memset(&user, 0, sizeof(slurmdb_user_rec_t)); |
| user.uid = uid; |
| |
| if (!user_cond) { |
| xstrcat(extra, "where deleted=0"); |
| goto empty; |
| } |
| |
| if (user_cond->with_deleted) |
| xstrcat(extra, "where (deleted=0 || deleted=1)"); |
| else |
| xstrcat(extra, "where deleted=0"); |
| |
| |
| user_list = _get_other_user_names_to_mod(mysql_conn, uid, user_cond); |
| if (user_list) { |
| if (!user_cond->assoc_cond) |
| user_cond->assoc_cond = |
| xmalloc(sizeof(slurmdb_assoc_rec_t)); |
| |
| if (!user_cond->assoc_cond->user_list) |
| user_cond->assoc_cond->user_list = user_list; |
| else { |
| list_transfer(user_cond->assoc_cond->user_list, |
| user_list); |
| FREE_NULL_LIST(user_list); |
| } |
| user_list = NULL; |
| } else if ((user_cond->def_acct_list |
| && list_count(user_cond->def_acct_list)) |
| || (user_cond->def_wckey_list |
| && list_count(user_cond->def_wckey_list))) |
| return NULL; |
| |
| if (user_cond->assoc_cond && |
| user_cond->assoc_cond->user_list |
| && list_count(user_cond->assoc_cond->user_list)) { |
| set = 0; |
| xstrcat(extra, " && ("); |
| itr = list_iterator_create(user_cond->assoc_cond->user_list); |
| while ((object = list_next(itr))) { |
| if (set) |
| xstrcat(extra, " || "); |
| xstrfmtcat(extra, "name='%s'", object); |
| set = 1; |
| } |
| list_iterator_destroy(itr); |
| xstrcat(extra, ")"); |
| } |
| |
| if (user_cond->admin_level != SLURMDB_ADMIN_NOTSET) { |
| xstrfmtcat(extra, " && admin_level=%u", |
| user_cond->admin_level); |
| } |
| |
| empty: |
| /* This is here to make sure we are looking at only this user |
| * if this flag is set. |
| */ |
| if ((slurm_conf.private_data & PRIVATE_DATA_USERS) || |
| (user_cond && user_cond->assoc_cond && |
| (user_cond->assoc_cond->flags & ASSOC_COND_FLAG_WITH_NG_USAGE) && |
| (slurm_conf.private_data & PRIVATE_DATA_USAGE))) { |
| if (!is_user_min_admin_level( |
| mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) { |
| assoc_mgr_fill_in_user( |
| mysql_conn, &user, 1, NULL, false); |
| if (!user.name) { |
| debug("User %u has no associations, and is not admin, so not returning any users.", |
| user.uid); |
| xfree(extra); |
| return NULL; |
| } |
| xstrfmtcat(extra, " && name='%s'", user.name); |
| } |
| } |
| |
| xfree(tmp); |
| xstrfmtcat(tmp, "%s", user_req_inx[0]); |
| for(i=1; i<USER_REQ_COUNT; i++) { |
| xstrfmtcat(tmp, ", %s", user_req_inx[i]); |
| } |
| |
| query = xstrdup_printf("select %s from %s %s", tmp, user_table, extra); |
| xfree(tmp); |
| xfree(extra); |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", query); |
| if (!(result = mysql_db_query_ret( |
| mysql_conn, query, 0))) { |
| xfree(query); |
| return NULL; |
| } |
| xfree(query); |
| |
| user_list = list_create(slurmdb_destroy_user_rec); |
| |
| while ((row = mysql_fetch_row(result))) { |
| slurmdb_user_rec_t *user = xmalloc(sizeof(slurmdb_user_rec_t)); |
| |
| list_append(user_list, user); |
| |
| user->name = xstrdup(row[USER_REQ_NAME]); |
| user->admin_level = slurm_atoul(row[USER_REQ_AL]); |
| |
| if (slurm_atoul(row[USER_REQ_DELETED])) |
| user->flags |= SLURMDB_USER_FLAG_DELETED; |
| |
| if (user_cond && user_cond->with_coords) { |
| /* |
| * On start up the coord list doesn't exist so get it |
| * the SQL way. |
| */ |
| if (!assoc_mgr_coord_list) |
| _get_user_coords(mysql_conn, user); |
| else |
| user->coord_accts = |
| assoc_mgr_user_acct_coords( |
| mysql_conn, user->name); |
| } |
| } |
| mysql_free_result(result); |
| |
| if (user_cond && (user_cond->with_assocs || |
| (user_cond->assoc_cond && |
| (user_cond->assoc_cond->flags & |
| ASSOC_COND_FLAG_ONLY_DEFS)))) { |
| list_itr_t *assoc_itr = NULL; |
| slurmdb_user_rec_t *user = NULL; |
| slurmdb_assoc_rec_t *assoc = NULL; |
| list_t *assoc_list = NULL; |
| |
| /* Make sure we don't get any non-user associations |
| * this is done by at least having a user_list |
| * defined */ |
| if (!user_cond->assoc_cond) |
| user_cond->assoc_cond = |
| xmalloc(sizeof(slurmdb_assoc_cond_t)); |
| |
| if (!user_cond->assoc_cond->user_list) |
| user_cond->assoc_cond->user_list = list_create(NULL); |
| |
| if (user_cond->with_deleted) |
| user_cond->assoc_cond->flags |= |
| ASSOC_COND_FLAG_WITH_DELETED; |
| |
| assoc_list = as_mysql_get_assocs( |
| mysql_conn, uid, user_cond->assoc_cond); |
| |
| if (!assoc_list) { |
| error("no associations"); |
| goto get_wckeys; |
| } |
| |
| itr = list_iterator_create(user_list); |
| assoc_itr = list_iterator_create(assoc_list); |
| while ((user = list_next(itr))) { |
| while ((assoc = list_next(assoc_itr))) { |
| if (xstrcmp(assoc->user, user->name)) |
| continue; |
| /* Set up the default. This is needed |
| * for older versions primarily that |
| * don't have the notion of default |
| * account per cluster. */ |
| if (!user->default_acct && (assoc->is_def == 1)) |
| user->default_acct = |
| xstrdup(assoc->acct); |
| |
| if (!user->def_qos_id && assoc->def_qos_id) |
| user->def_qos_id = assoc->def_qos_id; |
| |
| if (!user_cond->with_assocs) { |
| /* We just got the default so no |
| reason to hang around if we aren't |
| getting the associations. |
| */ |
| if (user->default_acct) |
| break; |
| else |
| continue; |
| } |
| |
| if (!user->assoc_list) |
| user->assoc_list = list_create( |
| slurmdb_destroy_assoc_rec); |
| list_append(user->assoc_list, assoc); |
| list_remove(assoc_itr); |
| } |
| list_iterator_reset(assoc_itr); |
| } |
| list_iterator_destroy(itr); |
| list_iterator_destroy(assoc_itr); |
| FREE_NULL_LIST(assoc_list); |
| } |
| |
| get_wckeys: |
| if (user_cond && (user_cond->with_wckeys || |
| (user_cond->assoc_cond && |
| (user_cond->assoc_cond->flags & |
| ASSOC_COND_FLAG_ONLY_DEFS)))) { |
| list_itr_t *wckey_itr = NULL; |
| slurmdb_user_rec_t *user = NULL; |
| slurmdb_wckey_rec_t *wckey = NULL; |
| list_t *wckey_list = NULL; |
| slurmdb_wckey_cond_t wckey_cond; |
| |
| memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t)); |
| if (user_cond->assoc_cond) { |
| wckey_cond.user_list = |
| user_cond->assoc_cond->user_list; |
| wckey_cond.cluster_list = |
| user_cond->assoc_cond->cluster_list; |
| wckey_cond.only_defs = |
| user_cond->assoc_cond->flags & |
| ASSOC_COND_FLAG_ONLY_DEFS; |
| } |
| wckey_list = as_mysql_get_wckeys(mysql_conn, uid, &wckey_cond); |
| |
| if (!wckey_list) |
| 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 (xstrcmp(wckey->user, user->name)) |
| continue; |
| |
| /* Set up the default. This is needed |
| * for older versions primarily that |
| * don't have the notion of default |
| * wckey per cluster. */ |
| if (!user->default_wckey |
| && (wckey->is_def == 1)) |
| user->default_wckey = |
| xstrdup(wckey->name); |
| |
| /* We just got the default so no |
| reason to hang around if we aren't |
| getting the wckeys. |
| */ |
| if (!user_cond->with_wckeys) { |
| /* We just got the default so no |
| reason to hang around if we aren't |
| getting the wckeys. |
| */ |
| if (user->default_wckey) |
| break; |
| else |
| continue; |
| } |
| |
| if (!user->wckey_list) |
| user->wckey_list = list_create( |
| slurmdb_destroy_wckey_rec); |
| list_append(user->wckey_list, wckey); |
| list_remove(wckey_itr); |
| } |
| list_iterator_reset(wckey_itr); |
| /* If a user doesn't have a default wckey (they |
| might not of had track_wckeys on), set it now. |
| */ |
| if (!user->default_wckey) |
| user->default_wckey = xstrdup(""); |
| } |
| list_iterator_destroy(itr); |
| list_iterator_destroy(wckey_itr); |
| |
| FREE_NULL_LIST(wckey_list); |
| } |
| |
| return user_list; |
| } |
| |
| static slurmdb_user_rec_t *_make_user_rec_with_coords( |
| mysql_conn_t *mysql_conn, char *user, bool locked) |
| { |
| slurmdb_user_rec_t *user_rec = NULL; |
| /* |
| * We can't use user_rec just yet since we get that filled up |
| * with variables that we don't own. We will eventually free it |
| * later which causes issues memory wise. |
| */ |
| slurmdb_user_rec_t user_tmp = { |
| .name = user, |
| .uid = NO_VAL, |
| }; |
| |
| assoc_mgr_lock_t locks = { |
| .user = READ_LOCK, |
| }; |
| |
| if (!locked) |
| assoc_mgr_lock(&locks); |
| |
| xassert(verify_assoc_lock(USER_LOCK, READ_LOCK)); |
| |
| /* Grab the current coord_accts if user exists already */ |
| (void) assoc_mgr_fill_in_user(mysql_conn, &user_tmp, |
| ACCOUNTING_ENFORCE_ASSOCS, |
| NULL, true); |
| |
| /* |
| * The association manager expects the dbd to do all the lifting |
| * here, so we get a full list and then remove from it. |
| */ |
| user_rec = xmalloc(sizeof(slurmdb_user_rec_t)); |
| user_rec->name = xstrdup(user_tmp.name); |
| user_rec->uid = NO_VAL; |
| user_rec->coord_accts = slurmdb_list_copy_coord( |
| user_tmp.coord_accts); |
| |
| /* |
| * This is needed if the user is being added for the first time right |
| * now as they will not be in the assoc mgr just yet. |
| */ |
| if (!user_rec->coord_accts) |
| user_rec->coord_accts = |
| list_create(slurmdb_destroy_coord_rec); |
| |
| if (!locked) |
| assoc_mgr_unlock(&locks); |
| return user_rec; |
| } |
| |
| extern slurmdb_user_rec_t *as_mysql_user_add_coord_update( |
| mysql_conn_t *mysql_conn, list_t **user_list, char *user, bool locked) |
| { |
| slurmdb_user_rec_t *user_rec; |
| |
| xassert(user_list); |
| xassert(user); |
| |
| if (!*user_list) { |
| /* the mysql_conn->update_list will free the contents */ |
| *user_list = list_create(NULL); |
| } |
| |
| /* See if we have already added it. */ |
| if ((user_rec = list_find_first(*user_list, _find_user, user))) |
| return user_rec; |
| |
| user_rec = _make_user_rec_with_coords(mysql_conn, user, locked); |
| |
| if (!user_rec) |
| return NULL; |
| |
| list_append(*user_list, user_rec); |
| |
| /* |
| * NOTE: REMOVE|ADD do the same thing, they both expect the full list so |
| * we can use either one to do the same thing. |
| */ |
| if (addto_update_list(mysql_conn->update_list, |
| SLURMDB_REMOVE_COORD, user_rec) != |
| SLURM_SUCCESS) { |
| error("Couldn't add removal of coord, this should never happen."); |
| slurmdb_destroy_user_rec(user_rec); |
| return NULL; |
| } |
| |
| return user_rec; |
| } |
| |
| extern void as_mysql_user_handle_user_coord_flag(slurmdb_user_rec_t *user_rec, |
| slurmdb_assoc_flags_t flags, |
| char *acct) |
| { |
| xassert(user_rec); |
| xassert(user_rec->coord_accts); |
| xassert(acct); |
| |
| if (flags & ASSOC_FLAG_USER_COORD_NO) { |
| (void) list_delete_first(user_rec->coord_accts, |
| assoc_mgr_find_flag_coord_by_name, |
| acct); |
| debug2("Removing user %s from being a coordinator of account %s", |
| user_rec->name, acct); |
| } else if ((flags & ASSOC_FLAG_USER_COORD) && |
| !list_find_first(user_rec->coord_accts, |
| assoc_mgr_find_coord_in_user, |
| acct)) { |
| slurmdb_coord_rec_t *coord = xmalloc(sizeof(*coord)); |
| |
| coord->name = xstrdup(acct); |
| list_append(user_rec->coord_accts, coord); |
| debug2("Adding user %s as a coordinator of account %s", |
| user_rec->name, acct); |
| } |
| } |
| |
| static int _get_indirect_acct_coords(void *x, void *arg) |
| { |
| char *cluster_name = x; |
| create_string_t *create_string = arg; |
| |
| /* |
| * Here we are doing a join on all the clusters to see what users are |
| * directly in accounts/users listed in the acct_coord_table. |
| */ |
| xstrfmtcatat(create_string->query, &create_string->query_pos, |
| "%sselect distinct t1.user, t2.acct from " |
| "\"%s\" as t1, \"%s_%s\" as t2 where t1.deleted=0 && " |
| "t2.deleted=0 && t2.user='' && (t1.acct != t2.acct) && " |
| "t2.lineage like concat('%%/', t1.acct, '/%%')", |
| create_string->query ? " union " : "", |
| acct_coord_table, |
| cluster_name, assoc_table); |
| return 0; |
| } |
| |
| static int _get_accts_with_user_coords_users(void *x, void *arg) |
| { |
| char *cluster_name = x; |
| create_string_t *create_string = arg; |
| /* |
| * Here we are doing a join on all the clusters to see what users are |
| * directly in accounts with ASSOC_FLAG_USER_COORD set. |
| */ |
| xstrfmtcatat(create_string->query, &create_string->query_pos, |
| "%sselect distinct t2.acct, t2.user from \"%s_%s\" as t1, " |
| "\"%s_%s\" as t2 where t1.deleted=0 && " |
| "t2.deleted=0 && (t1.flags & %u) && t2.lineage like " |
| "concat('%%/', t1.acct, '/0-%%')", |
| create_string->query ? " union " : "", |
| cluster_name, assoc_table, |
| cluster_name, assoc_table, |
| ASSOC_FLAG_USER_COORD); |
| return 0; |
| } |
| |
| static int _get_accts_with_user_coords_indirect(void *x, void *arg) |
| { |
| char *cluster_name = x; |
| create_string_t *create_string = arg; |
| |
| /* |
| * This is used to determine what sub-accounts exist from accounts with |
| * ASSOC_FLAG_USER_COORD set. These will be added as indirect coord |
| * accounts. |
| */ |
| xstrfmtcatat(create_string->query, &create_string->query_pos, |
| "%sselect distinct acct from \"%s_%s\" where deleted=0 && " |
| "user='' && acct!='%s' && lineage like concat('%%/%s/%%')", |
| create_string->query ? " union " : "", |
| cluster_name, assoc_table, |
| create_string->extra, create_string->extra); |
| return 0; |
| } |
| |
| static slurmdb_user_rec_t *_process_coord_results( |
| slurmdb_user_rec_t *user, |
| char *user_name, char *acct_name, |
| uint16_t direct) |
| { |
| if (!user_name || !user_name[0]) |
| return NULL; /* This should never happen */ |
| |
| if (!g_user_coords_list || |
| (!_find_user(user, user_name) && |
| !(user = list_find_first(g_user_coords_list, |
| _find_user, |
| user_name)))) { |
| user = xmalloc(sizeof(*user)); |
| user->name = xstrdup(user_name); |
| user->coord_accts = list_create(slurmdb_destroy_coord_rec); |
| if (!g_user_coords_list) |
| g_user_coords_list = |
| list_create(slurmdb_destroy_user_rec); |
| list_append(g_user_coords_list, user); |
| } |
| |
| (void) slurmdb_add_coord_to_user(user, acct_name, direct); |
| |
| return user; |
| } |
| |
| extern int as_mysql_user_create_user_coords_list(mysql_conn_t *mysql_conn) |
| { |
| MYSQL_RES *result = NULL; |
| MYSQL_ROW row; |
| create_string_t create_string = { 0 }; |
| slurmdb_user_rec_t *user = NULL; |
| |
| if (check_connection(mysql_conn) != SLURM_SUCCESS) |
| return SLURM_ERROR; |
| |
| slurm_rwlock_wrlock(&as_mysql_cluster_list_lock); |
| |
| FREE_NULL_LIST(g_user_coords_list); |
| |
| /* Get the direct list of users coords */ |
| create_string.query = xstrdup_printf( |
| "select user, acct from %s where deleted=0", |
| acct_coord_table); |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", create_string.query); |
| result = mysql_db_query_ret(mysql_conn, create_string.query, 0); |
| xfree(create_string.query); |
| if (!result) |
| goto end_it; |
| while ((row = mysql_fetch_row(result))) { |
| user = _process_coord_results(user, row[0], row[1], 1); |
| } |
| mysql_free_result(result); |
| |
| /* Get the indirect list of users coords */ |
| create_string.query_pos = NULL; |
| (void) list_for_each(as_mysql_cluster_list, _get_indirect_acct_coords, |
| &create_string); |
| |
| /* Empty as_mysql_cluster_list */ |
| if (!create_string.query) |
| goto end_it; |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", create_string.query); |
| result = mysql_db_query_ret(mysql_conn, create_string.query, 0); |
| xfree(create_string.query); |
| if (!result) |
| goto end_it; |
| |
| while ((row = mysql_fetch_row(result))) { |
| user = _process_coord_results(user, row[0], row[1], 0); |
| } |
| mysql_free_result(result); |
| |
| /* Get the list of users */ |
| create_string.query_pos = NULL; |
| (void) list_for_each(as_mysql_cluster_list, |
| _get_accts_with_user_coords_users, |
| &create_string); |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", create_string.query); |
| result = mysql_db_query_ret(mysql_conn, create_string.query, 0); |
| xfree(create_string.query); |
| if (!result) |
| goto end_it; |
| |
| while ((row = mysql_fetch_row(result))) { |
| MYSQL_RES *result2 = NULL; |
| MYSQL_ROW row2; |
| |
| user = _process_coord_results(user, row[1], row[0], |
| COORD_SET_BY_ACCT); |
| if (!user) { |
| error("For some reason we didn't get a user from '%s'. This should never happen.", |
| row[1]); |
| continue; |
| } |
| /* |
| * Now let's get the indirect accounts from this direct account |
| */ |
| create_string.query_pos = NULL; |
| create_string.extra = row[0]; |
| (void) list_for_each(as_mysql_cluster_list, |
| _get_accts_with_user_coords_indirect, |
| &create_string); |
| |
| DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", |
| create_string.query); |
| result2 = mysql_db_query_ret(mysql_conn, |
| create_string.query, 0); |
| xfree(create_string.query); |
| if (!result2) |
| continue; |
| |
| while ((row2 = mysql_fetch_row(result2))) { |
| (void) slurmdb_add_coord_to_user(user, row2[0], 0); |
| } |
| mysql_free_result(result2); |
| } |
| mysql_free_result(result); |
| |
| end_it: |
| slurm_rwlock_unlock(&as_mysql_cluster_list_lock); |
| |
| return SLURM_SUCCESS; |
| } |