blob: 714a28cbcb25d4f6dacfc368a05cf33703fa0dd5 [file] [log] [blame]
/*****************************************************************************\
* as_mysql_acct.c - functions dealing with accounts.
*****************************************************************************
* 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_acct.h"
#include "as_mysql_user.h"
typedef struct {
slurmdb_account_rec_t *acct_in;
slurmdb_assoc_rec_t *assoc_in;
char *insert_query;
char *insert_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;
char *user_name;
} add_acct_cond_t;
typedef struct {
char *acct;
list_t *acct_list;
char *cluster_name;
slurmdb_assoc_flags_t flags;
mysql_conn_t *mysql_conn;
char *query;
char *query_pos;
list_t *user_list;
} flag_coord_acct_t;
static int _foreach_flag_coord_handle(void *x, void *arg)
{
slurmdb_user_rec_t *user_rec = x;
flag_coord_acct_t *flag_coord_acct = arg;
as_mysql_user_handle_user_coord_flag(
user_rec,
flag_coord_acct->flags,
flag_coord_acct->acct);
return 0;
}
static int _foreach_flag_coord_user(void *x, void *arg)
{
slurmdb_assoc_rec_t *assoc_ptr = x;
flag_coord_acct_t *flag_coord_acct = arg;
int rc = 0;
/* In the children_list the user assocs are always first */
if (assoc_ptr->user) {
slurmdb_user_rec_t *user_rec = as_mysql_user_add_coord_update(
flag_coord_acct->mysql_conn,
&flag_coord_acct->user_list,
assoc_ptr->user,
true);
as_mysql_user_handle_user_coord_flag(
user_rec,
flag_coord_acct->flags,
assoc_ptr->acct);
return 0;
}
/*
* We have a non-user assoc, so add/remove that from the full user list.
*/
if (flag_coord_acct->user_list) {
flag_coord_acct->acct = assoc_ptr->acct;
rc = list_for_each(flag_coord_acct->user_list,
_foreach_flag_coord_handle,
flag_coord_acct);
flag_coord_acct->acct = NULL;
}
/*
* Do not evaluate the assoc_ptr->usage->children_list here, it means we
* would be in a sub-account from the account that has the flag. So any
* users further down the hierarchy shouldn't be part of this flag.
*/
return rc;
}
static int _foreach_flag_coord_acct(void *x, void *arg)
{
flag_coord_acct_t *flag_coord_acct = arg;
slurmdb_assoc_rec_t *assoc_ptr = NULL;
slurmdb_assoc_rec_t assoc_req = {
.cluster = flag_coord_acct->cluster_name,
.acct = x,
.uid = NO_VAL,
};
if (assoc_mgr_fill_in_assoc(flag_coord_acct->mysql_conn,
&assoc_req,
ACCOUNTING_ENFORCE_ASSOCS,
&assoc_ptr,
true) != SLURM_SUCCESS) {
/*
* Return 0 since the account requested might not exist on
* every cluster in the system.
*/
return 0;
}
/* Only change if needed */
if (((assoc_ptr->flags & ASSOC_FLAG_USER_COORD) &&
(flag_coord_acct->flags & ASSOC_FLAG_USER_COORD_NO)) ||
(!(assoc_ptr->flags & ASSOC_FLAG_USER_COORD) &&
(flag_coord_acct->flags & ASSOC_FLAG_USER_COORD))) {
slurmdb_assoc_rec_t *mod_assoc =
xmalloc(sizeof(slurmdb_assoc_rec_t));
slurmdb_init_assoc_rec(mod_assoc, 0);
mod_assoc->id = assoc_ptr->id;
mod_assoc->cluster = xstrdup(assoc_ptr->cluster);
mod_assoc->flags = assoc_ptr->flags;
if (flag_coord_acct->flags & ASSOC_FLAG_USER_COORD_NO)
mod_assoc->flags &= ~ASSOC_FLAG_USER_COORD;
else
mod_assoc->flags |= ASSOC_FLAG_USER_COORD;
if (addto_update_list(flag_coord_acct->mysql_conn->update_list,
SLURMDB_MODIFY_ASSOC, mod_assoc) !=
SLURM_SUCCESS) {
error("Couldn't add removal of coord, this should never happen.");
slurmdb_destroy_user_rec(mod_assoc);
return 0;
}
/* set up query to remove the flag */
if (!flag_coord_acct->query) {
xstrfmtcatat(flag_coord_acct->query,
&flag_coord_acct->query_pos,
"update \"%s_%s\" set flags = %u where id_assoc IN (%u",
mod_assoc->cluster, assoc_table,
mod_assoc->flags, mod_assoc->id);
} else {
xstrfmtcatat(flag_coord_acct->query,
&flag_coord_acct->query_pos,
",%u",
mod_assoc->id);
}
if (assoc_ptr->usage->children_list)
(void) list_for_each(assoc_ptr->usage->children_list,
_foreach_flag_coord_user,
flag_coord_acct);
}
return 0;
}
static int _foreach_flag_coord_cluster(void *x, void *arg)
{
flag_coord_acct_t *flag_coord_acct = arg;
flag_coord_acct->cluster_name = x;
(void) list_for_each_ro(flag_coord_acct->acct_list,
_foreach_flag_coord_acct,
flag_coord_acct);
if (flag_coord_acct->query) {
xstrcatat(flag_coord_acct->query,
&flag_coord_acct->query_pos,
");");
/* Now clear the flag for the associations in the database */
DB_DEBUG(DB_ASSOC, flag_coord_acct->mysql_conn->conn,
"query\n%s",
flag_coord_acct->query);
if (mysql_db_query(flag_coord_acct->mysql_conn,
flag_coord_acct->query) != SLURM_SUCCESS)
error("Couldn't update flags");
xfree(flag_coord_acct->query);
}
/*
* Return 0 since the accounts requested might not exist on
* every cluster in the system.
*/
return 0;
}
static void _handle_flag_coord(flag_coord_acct_t *flag_coord_acct)
{
assoc_mgr_lock_t locks = {
.assoc = READ_LOCK,
.user = READ_LOCK,
};
assoc_mgr_lock(&locks);
(void) list_for_each_ro(as_mysql_cluster_list,
_foreach_flag_coord_cluster,
flag_coord_acct);
assoc_mgr_unlock(&locks);
FREE_NULL_LIST(flag_coord_acct->user_list);
xfree(flag_coord_acct->query);
}
static void _setup_acct_cond_limits(slurmdb_account_cond_t *acct_cond,
char **extra, char **at)
{
list_itr_t *itr = NULL;
char *object = NULL;
if (!acct_cond)
return;
if (acct_cond->assoc_cond &&
acct_cond->assoc_cond->acct_list &&
list_count(acct_cond->assoc_cond->acct_list)) {
int set = 0;
xstrcatat(*extra, at, " && (");
itr = list_iterator_create(acct_cond->assoc_cond->acct_list);
while ((object = list_next(itr))) {
if (set)
xstrcatat(*extra, at, " || ");
xstrfmtcatat(*extra, at, "name='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcatat(*extra, at, ")");
}
if (acct_cond->description_list
&& list_count(acct_cond->description_list)) {
int set = 0;
xstrcatat(*extra, at, " && (");
itr = list_iterator_create(acct_cond->description_list);
while ((object = list_next(itr))) {
if (set)
xstrcatat(*extra, at, " || ");
xstrfmtcatat(*extra, at, "description='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcatat(*extra, at, ")");
}
if (acct_cond->flags != SLURMDB_ACCT_FLAG_NONE) {
if (acct_cond->flags & SLURMDB_ACCT_FLAG_USER_COORD_NO) {
xstrfmtcatat(*extra, at, " && !(flags & %u)",
SLURMDB_ACCT_FLAG_USER_COORD);
} else if (acct_cond->flags & SLURMDB_ACCT_FLAG_USER_COORD) {
xstrfmtcatat(*extra, at, " && (flags & %u)",
SLURMDB_ACCT_FLAG_USER_COORD);
}
}
if (acct_cond->organization_list
&& list_count(acct_cond->organization_list)) {
int set = 0;
xstrcatat(*extra, at, " && (");
itr = list_iterator_create(acct_cond->organization_list);
while ((object = list_next(itr))) {
if (set)
xstrcatat(*extra, at, " || ");
xstrfmtcatat(*extra, at, "organization='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcatat(*extra, at, ")");
}
return;
}
static int _foreach_add_acct(void *x, void *arg)
{
char *name = x;
add_acct_cond_t *add_acct_cond = arg;
slurmdb_account_rec_t *acct;
slurmdb_assoc_rec_t *assoc;
char *desc;
char *org;
char *extra, *tmp_extra;
MYSQL_RES *result = NULL;
int cnt;
char *query;
slurmdb_acct_flags_t base_flags;
/* Check to see if it is already in the acct_table */
query = xstrdup_printf("select name from %s where name='%s' and !deleted",
acct_table, name);
result = mysql_db_query_ret(add_acct_cond->mysql_conn, query, 0);
xfree(query);
if (!result)
return -1;
cnt = mysql_num_rows(result);
mysql_free_result(result);
/* If so, just return */
if (cnt)
return 0;
/* Else, add it */
acct = add_acct_cond->acct_in;
assoc = add_acct_cond->assoc_in;
desc = acct->description ? acct->description : x;
org = acct->organization;
if (!org) {
if (assoc->parent_acct && xstrcmp(assoc->parent_acct, "root"))
org = assoc->parent_acct;
else
org = x;
}
/* Clear flags we don't plan to store */
base_flags = acct->flags & ~SLURMDB_ACCT_FLAG_BASE;
if (!add_acct_cond->ret_str)
xstrcatat(add_acct_cond->ret_str, &add_acct_cond->ret_str_pos,
" Adding Account(s)\n");
xstrfmtcatat(add_acct_cond->ret_str, &add_acct_cond->ret_str_pos,
" %s\n", name);
if (add_acct_cond->insert_query)
xstrfmtcatat(add_acct_cond->insert_query,
&add_acct_cond->insert_query_pos,
", (%ld, %ld, '%s', '%s', '%s', %u)",
add_acct_cond->now, add_acct_cond->now,
name, desc, org, base_flags);
else
xstrfmtcatat(add_acct_cond->insert_query,
&add_acct_cond->insert_query_pos,
"insert into %s (creation_time, mod_time, name, description, organization, flags) values (%ld, %ld, '%s', '%s', '%s', %u)",
acct_table, add_acct_cond->now, add_acct_cond->now,
name, desc, org, base_flags);
extra = xstrdup_printf("description='%s', organization='%s', flags='%u'",
desc, org, base_flags);
tmp_extra = slurm_add_slash_to_quotes(extra);
if (add_acct_cond->txn_query)
xstrfmtcatat(add_acct_cond->txn_query,
&add_acct_cond->txn_query_pos,
", (%ld, %u, '%s', '%s', '%s')",
add_acct_cond->now, DBD_ADD_ACCOUNTS, name,
add_acct_cond->user_name, tmp_extra);
else
xstrfmtcatat(add_acct_cond->txn_query,
&add_acct_cond->txn_query_pos,
"insert into %s (timestamp, action, name, actor, info) values (%ld, %u, '%s', '%s', '%s')",
txn_table,
add_acct_cond->now, DBD_ADD_ACCOUNTS, name,
add_acct_cond->user_name, tmp_extra);
xfree(tmp_extra);
xfree(extra);
return 0;
}
extern int as_mysql_add_accts(mysql_conn_t *mysql_conn, uint32_t uid,
list_t *acct_list)
{
list_itr_t *itr = NULL;
int rc = SLURM_SUCCESS;
slurmdb_account_rec_t *object = NULL;
char *cols = NULL, *vals = NULL, *query = NULL, *txn_query = NULL;
time_t now = time(NULL);
char *user_name = NULL;
char *extra = NULL, *tmp_extra = NULL;
int affect_rows = 0;
list_t *assoc_list;
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
*/
}
if (!acct_list || !list_count(acct_list)) {
error("%s: Trying to add empty account list", __func__);
return ESLURM_EMPTY_LIST;
}
assoc_list = list_create(slurmdb_destroy_assoc_rec);
user_name = uid_to_string((uid_t) uid);
itr = list_iterator_create(acct_list);
while ((object = list_next(itr))) {
slurmdb_acct_flags_t base_flags;
if (!object->name || !object->name[0]
|| !object->description || !object->description[0]
|| !object->organization || !object->organization[0]) {
error("We need an account name, description, and "
"organization to add. %s %s %s",
object->name, object->description,
object->organization);
rc = SLURM_ERROR;
continue;
}
base_flags = object->flags & ~SLURMDB_ACCT_FLAG_BASE;
xstrcat(cols, "creation_time, mod_time, name, "
"description, organization, flags");
xstrfmtcat(vals, "%ld, %ld, '%s', '%s', '%s', %u",
now, now, object->name,
object->description, object->organization,
base_flags);
xstrfmtcat(extra, ", description='%s', organization='%s', flags=%u",
object->description, object->organization,
base_flags);
query = xstrdup_printf(
"insert into %s (%s) values (%s) "
"on duplicate key update deleted=0, mod_time=%ld %s;",
acct_table, cols, vals,
now, extra);
DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s", query);
rc = mysql_db_query(mysql_conn, query);
xfree(cols);
xfree(vals);
xfree(query);
if (rc != SLURM_SUCCESS) {
error("Couldn't add acct");
xfree(extra);
continue;
}
affect_rows = last_affected_rows(mysql_conn);
//DB_DEBUG(DB_ASSOC, mysql_conn->conn, "affected %d",
// affect_rows);
if (!affect_rows) {
DB_DEBUG(DB_ASSOC, mysql_conn->conn, "nothing changed");
xfree(extra);
continue;
}
/* we always have a ', ' as the first 2 chars */
tmp_extra = slurm_add_slash_to_quotes(extra+2);
if (txn_query)
xstrfmtcat(txn_query,
", (%ld, %u, '%s', '%s', '%s')",
now, DBD_ADD_ACCOUNTS, object->name,
user_name, tmp_extra);
else
xstrfmtcat(txn_query,
"insert into %s "
"(timestamp, action, name, actor, info) "
"values (%ld, %u, '%s', '%s', '%s')",
txn_table,
now, DBD_ADD_ACCOUNTS, object->name,
user_name, tmp_extra);
xfree(tmp_extra);
xfree(extra);
if (!object->assoc_list)
continue;
if (!assoc_list)
assoc_list =
list_create(slurmdb_destroy_assoc_rec);
list_transfer(assoc_list, object->assoc_list);
}
list_iterator_destroy(itr);
xfree(user_name);
if (rc != SLURM_ERROR) {
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 (assoc_list && list_count(assoc_list)) {
if ((rc = as_mysql_add_assocs(mysql_conn, uid, assoc_list))
!= SLURM_SUCCESS)
error("Problem adding accounts associations");
}
FREE_NULL_LIST(assoc_list);
as_mysql_user_create_user_coords_list(mysql_conn);
return rc;
}
extern char *as_mysql_add_accts_cond(mysql_conn_t *mysql_conn, uint32_t uid,
slurmdb_add_assoc_cond_t *add_assoc,
slurmdb_account_rec_t *acct)
{
add_acct_cond_t add_acct_cond;
char *ret_str = NULL;
int rc;
if (check_connection(mysql_conn) != SLURM_SUCCESS) {
errno = ESLURM_DB_CONNECTION;
return NULL;
}
if (!add_assoc ||
!add_assoc->acct_list ||
!list_count(add_assoc->acct_list)) {
errno = ESLURM_EMPTY_LIST;
return NULL;
}
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) {
char *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;
}
memset(&user, 0, sizeof(slurmdb_user_rec_t));
user.uid = uid;
if (!is_user_any_coord(mysql_conn, &user)) {
char *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
*/
}
/* Transfer over relevant flags from the account to the association. */
if (acct->flags & SLURMDB_ACCT_FLAG_USER_COORD)
add_assoc->assoc.flags |= ASSOC_FLAG_USER_COORD;
memset(&add_acct_cond, 0, sizeof(add_acct_cond));
add_acct_cond.acct_in = acct;
add_acct_cond.assoc_in = &add_assoc->assoc;
add_acct_cond.mysql_conn = mysql_conn;
add_acct_cond.now = time(NULL);
add_acct_cond.user_name = uid_to_string((uid_t) uid);
/* First add the accounts to the acct_table. */
if (list_for_each_ro(add_assoc->acct_list, _foreach_add_acct,
&add_acct_cond) < 0) {
rc = add_acct_cond.rc;
goto end_it;
}
if (add_acct_cond.insert_query) {
xstrfmtcatat(add_acct_cond.insert_query,
&add_acct_cond.insert_query_pos,
" on duplicate key update deleted=0, description=VALUES(description), mod_time=VALUES(mod_time), organization=VALUES(organization);");
DB_DEBUG(DB_ASSOC, mysql_conn->conn, "query\n%s",
add_acct_cond.insert_query);
rc = mysql_db_query(mysql_conn, add_acct_cond.insert_query);
xfree(add_acct_cond.insert_query);
if (rc != SLURM_SUCCESS) {
error("Couldn't add acct");
xfree(add_acct_cond.ret_str);
goto end_it;
}
/* Success means we add the defaults to the string */
xstrfmtcatat(add_acct_cond.ret_str,
&add_acct_cond.ret_str_pos,
" Settings\n Description = %s\n Organization = %s\n",
acct->description ?
acct->description : "Account Name",
acct->organization ?
acct->organization : "Parent/Account Name");
xstrcatat(add_acct_cond.txn_query,
&add_acct_cond.txn_query_pos,
";");
rc = mysql_db_query(mysql_conn, add_acct_cond.txn_query);
if (rc != SLURM_SUCCESS) {
error("Couldn't add txn");
rc = SLURM_SUCCESS;
}
}
/* Now add the associations */
ret_str = as_mysql_add_assocs_cond(mysql_conn, uid, add_assoc);
rc = errno;
if (rc == SLURM_NO_CHANGE_IN_DATA) {
if (add_acct_cond.ret_str)
rc = SLURM_SUCCESS;
}
end_it:
xfree(add_acct_cond.insert_query);
xfree(add_acct_cond.txn_query);
xfree(add_acct_cond.user_name);
if (rc != SLURM_SUCCESS) {
reset_mysql_conn(mysql_conn);
if (!add_acct_cond.ret_str_err)
xfree(add_acct_cond.ret_str);
else
xfree(ret_str);
errno = rc;
return add_acct_cond.ret_str ? add_acct_cond.ret_str : ret_str;
}
if (ret_str) {
xstrcatat(add_acct_cond.ret_str,
&add_acct_cond.ret_str_pos,
ret_str);
xfree(ret_str);
}
if (!add_acct_cond.ret_str) {
DB_DEBUG(DB_ASSOC, mysql_conn->conn, "didn't affect anything");
errno = SLURM_NO_CHANGE_IN_DATA;
return NULL;
}
as_mysql_user_create_user_coords_list(mysql_conn);
errno = SLURM_SUCCESS;
return add_acct_cond.ret_str;
}
extern list_t *as_mysql_modify_accts(mysql_conn_t *mysql_conn, uint32_t uid,
slurmdb_account_cond_t *acct_cond,
slurmdb_account_rec_t *acct)
{
list_t *ret_list = NULL;
int rc = SLURM_SUCCESS;
char *object = NULL, *at = NULL;
char *vals = NULL, *extra = NULL, *query = NULL, *name_char = NULL;
time_t now = time(NULL);
char *user_name = NULL;
slurmdb_assoc_flags_t assoc_flags = ASSOC_FLAG_NONE;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
if (!acct_cond || !acct) {
error("we need something to change");
return NULL;
}
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) {
errno = ESLURM_ACCESS_DENIED;
return NULL;
}
xstrcatat(extra, &at, "where deleted=0");
_setup_acct_cond_limits(acct_cond, &extra, &at);
if (acct->description)
xstrfmtcat(vals, ", description='%s'", acct->description);
if (acct->organization)
xstrfmtcat(vals, ", organization='%s'", acct->organization);
if (acct->flags & SLURMDB_ACCT_FLAG_USER_COORD_NO) {
xstrfmtcat(vals, ", flags=flags&~%u",
SLURMDB_ACCT_FLAG_USER_COORD);
assoc_flags |= ASSOC_FLAG_USER_COORD_NO;
} else if (acct->flags & SLURMDB_ACCT_FLAG_USER_COORD) {
xstrfmtcat(vals, ", flags=flags|%u",
SLURMDB_ACCT_FLAG_USER_COORD);
assoc_flags |= ASSOC_FLAG_USER_COORD;
}
if (!extra || !vals) {
errno = SLURM_NO_CHANGE_IN_DATA;
error("Nothing to change");
return NULL;
}
query = xstrdup_printf("select name from %s %s;", acct_table, extra);
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);
xfree(vals);
return NULL;
}
rc = 0;
ret_list = list_create(xfree_ptr);
while ((row = mysql_fetch_row(result))) {
object = xstrdup(row[0]);
list_append(ret_list, object);
if (!rc) {
xstrfmtcat(name_char, "(name='%s'", object);
rc = 1;
} else {
xstrfmtcat(name_char, " || name='%s'", object);
}
}
mysql_free_result(result);
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);
xfree(vals);
return ret_list;
}
xfree(query);
xstrcat(name_char, ")");
user_name = uid_to_string((uid_t) uid);
rc = modify_common(mysql_conn, DBD_MODIFY_ACCOUNTS, now,
user_name, acct_table, name_char, vals, NULL);
xfree(user_name);
if (rc == SLURM_ERROR) {
error("Couldn't modify accounts");
FREE_NULL_LIST(ret_list);
errno = SLURM_ERROR;
ret_list = NULL;
}
xfree(name_char);
xfree(vals);
if (ret_list &&
(assoc_flags &
(ASSOC_FLAG_USER_COORD_NO | ASSOC_FLAG_USER_COORD))) {
flag_coord_acct_t flag_coord_acct = {
.acct_list = ret_list,
.flags = assoc_flags,
.mysql_conn = mysql_conn,
};
as_mysql_user_create_user_coords_list(mysql_conn);
/* Update associations based on account flags */
_handle_flag_coord(&flag_coord_acct);
}
return ret_list;
}
extern list_t *as_mysql_remove_accts(mysql_conn_t *mysql_conn, uint32_t uid,
slurmdb_account_cond_t *acct_cond)
{
list_t *ret_list = NULL;
list_t *coord_list = NULL;
int rc = SLURM_SUCCESS;
char *at = NULL;
char *extra = NULL, *query = NULL,
*name_char = NULL, *name_char_pos = NULL,
*assoc_char = NULL, *assoc_char_pos = NULL;
time_t now = time(NULL);
MYSQL_RES *result = NULL;
MYSQL_ROW row;
remove_common_args_t args = {
.default_account = false,
.jobs_running = false,
.mysql_conn = mysql_conn,
.now = now,
.table = acct_table,
.type = DBD_REMOVE_ACCOUNTS,
};
if (!acct_cond) {
error("we need something to change");
return NULL;
}
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) {
errno = ESLURM_ACCESS_DENIED;
return NULL;
}
xstrcatat(extra, &at, "where deleted=0");
_setup_acct_cond_limits(acct_cond, &extra, &at);
if (!extra) {
error("Nothing to remove");
return NULL;
}
query = xstrdup_printf("select name from %s %s;", acct_table, extra);
xfree(extra);
if (!(result = mysql_db_query_ret(
mysql_conn, query, 0))) {
xfree(query);
return NULL;
}
ret_list = list_create(xfree_ptr);
while ((row = mysql_fetch_row(result))) {
char *object = xstrdup(row[0]);
list_append(ret_list, object);
if (name_char)
xstrfmtcatat(name_char, &name_char_pos, ",'%s'",
object);
else
xstrfmtcatat(name_char, &name_char_pos, "name in('%s'",
object);
xstrfmtcatat(assoc_char, &assoc_char_pos,
"%st2.lineage like '%%/%s/%%'",
assoc_char ? " || " : "", object);
}
if (name_char)
xstrcatat(name_char, &name_char_pos, ")");
mysql_free_result(result);
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);
/* We need to remove these accounts from the coord's that have it */
coord_list = as_mysql_remove_coord(
mysql_conn, uid, ret_list, NULL);
FREE_NULL_LIST(coord_list);
args.assoc_char = assoc_char;
args.name_char = name_char;
args.ret_list = ret_list;
args.user_name = uid_to_string((uid_t) uid);
slurm_rwlock_rdlock(&as_mysql_cluster_list_lock);
args.use_cluster_list = list_shallow_copy(as_mysql_cluster_list);
rc = remove_common(&args);
FREE_NULL_LIST(args.use_cluster_list);
slurm_rwlock_unlock(&as_mysql_cluster_list_lock);
xfree(args.user_name);
xfree(name_char);
xfree(assoc_char);
if (rc == SLURM_ERROR) {
FREE_NULL_LIST(ret_list);
return NULL;
}
if (args.default_account)
errno = ESLURM_NO_REMOVE_DEFAULT_ACCOUNT;
else 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_get_accts(mysql_conn_t *mysql_conn, uid_t uid,
slurmdb_account_cond_t *acct_cond)
{
char *query = NULL;
char *extra = NULL, *at = NULL;
char *tmp = NULL;
list_t *acct_list = NULL;
list_itr_t *itr = NULL;
int set = 0;
int i=0, is_admin=1;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
slurmdb_user_rec_t user;
/* if this changes you will need to edit the corresponding enum */
char *acct_req_inx[] = {
"name",
"description",
"organization",
"deleted",
"flags",
};
enum {
SLURMDB_REQ_NAME,
SLURMDB_REQ_DESC,
SLURMDB_REQ_ORG,
SLURMDB_REQ_DELETED,
SLURMDB_REQ_FLAGS,
SLURMDB_REQ_COUNT
};
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
memset(&user, 0, sizeof(slurmdb_user_rec_t));
user.uid = uid;
if (slurm_conf.private_data & PRIVATE_DATA_ACCOUNTS) {
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 add accounts.");
errno = ESLURM_ACCESS_DENIED;
return NULL;
}
if (!is_user_any_coord(mysql_conn, &user)) {
error("Only admins/coordinators "
"can look at account usage");
errno = ESLURM_ACCESS_DENIED;
return NULL;
}
}
}
if (!acct_cond) {
xstrcat(extra, "where deleted=0");
goto empty;
}
if (acct_cond->flags & SLURMDB_ACCT_FLAG_DELETED)
xstrcatat(extra, &at, "where (deleted=0 || deleted=1)");
else
xstrcatat(extra, &at, "where deleted=0");
_setup_acct_cond_limits(acct_cond, &extra, &at);
empty:
xfree(tmp);
xstrfmtcat(tmp, "%s", acct_req_inx[i]);
for(i=1; i<SLURMDB_REQ_COUNT; i++) {
xstrfmtcat(tmp, ", %s", acct_req_inx[i]);
}
/* This is here to make sure we are looking at only this user
* if this flag is set. We also include any accounts they may be
* coordinator of.
*/
if (!is_admin && (slurm_conf.private_data & PRIVATE_DATA_ACCOUNTS)) {
slurmdb_coord_rec_t *coord = NULL;
set = 0;
itr = list_iterator_create(user.coord_accts);
while ((coord = list_next(itr))) {
if (set) {
xstrfmtcat(extra, " || name='%s'",
coord->name);
} else {
set = 1;
xstrfmtcat(extra, " && (name='%s'",
coord->name);
}
}
list_iterator_destroy(itr);
if (set)
xstrcat(extra,")");
}
query = xstrdup_printf("select %s from %s %s", tmp, acct_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);
acct_list = list_create(slurmdb_destroy_account_rec);
if (acct_cond && acct_cond->assoc_cond &&
(acct_cond->flags & SLURMDB_ACCT_FLAG_WASSOC)) {
/* We are going to be freeing the inners of
this list in the acct->name so we don't
free it here
*/
FREE_NULL_LIST(acct_cond->assoc_cond->acct_list);
acct_cond->assoc_cond->acct_list = list_create(NULL);
if (acct_cond->flags & SLURMDB_ACCT_FLAG_DELETED)
acct_cond->assoc_cond->flags |=
ASSOC_COND_FLAG_WITH_DELETED;
}
while ((row = mysql_fetch_row(result))) {
slurmdb_account_rec_t *acct =
xmalloc(sizeof(slurmdb_account_rec_t));
list_append(acct_list, acct);
acct->name = xstrdup(row[SLURMDB_REQ_NAME]);
acct->description = xstrdup(row[SLURMDB_REQ_DESC]);
acct->organization = xstrdup(row[SLURMDB_REQ_ORG]);
acct->flags = slurm_atoul(row[SLURMDB_REQ_FLAGS]);
if (slurm_atoul(row[SLURMDB_REQ_DELETED]))
acct->flags |= SLURMDB_ACCT_FLAG_DELETED;
if (acct_cond && (acct_cond->flags & SLURMDB_ACCT_FLAG_WCOORD))
acct->coordinators =
assoc_mgr_acct_coords(mysql_conn, acct->name);
if (acct_cond && (acct_cond->flags &
SLURMDB_ACCT_FLAG_WASSOC)) {
if (!acct_cond->assoc_cond) {
acct_cond->assoc_cond = xmalloc(
sizeof(slurmdb_assoc_cond_t));
}
list_append(acct_cond->assoc_cond->acct_list,
acct->name);
}
}
mysql_free_result(result);
if (acct_cond &&
(acct_cond->flags & SLURMDB_ACCT_FLAG_WASSOC) &&
acct_cond->assoc_cond
&& list_count(acct_cond->assoc_cond->acct_list)) {
list_itr_t *assoc_itr = NULL;
slurmdb_account_rec_t *acct = NULL;
slurmdb_assoc_rec_t *assoc = NULL;
list_t *assoc_list = as_mysql_get_assocs(
mysql_conn, uid, acct_cond->assoc_cond);
if (!assoc_list) {
error("no associations");
return acct_list;
}
itr = list_iterator_create(acct_list);
assoc_itr = list_iterator_create(assoc_list);
while ((acct = list_next(itr))) {
while ((assoc = list_next(assoc_itr))) {
if (xstrcmp(assoc->acct, acct->name))
continue;
if (!acct->assoc_list)
acct->assoc_list = list_create(
slurmdb_destroy_assoc_rec);
list_append(acct->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);
}
return acct_list;
}