blob: 8c416b941dc31c654c48df16235ece79b02fd2fc [file] [log] [blame]
/*****************************************************************************\
* as_mysql_tres.c - functions dealing with accounts.
*****************************************************************************
* Copyright (C) SchedMD LLC.
*
* 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_tres.h"
#include "as_mysql_usage.h"
#include "src/common/xstring.h"
extern int as_mysql_add_tres(mysql_conn_t *mysql_conn,
uint32_t uid, list_t *tres_list_in)
{
list_itr_t *itr = NULL;
int rc = SLURM_SUCCESS;
slurmdb_tres_rec_t *object = NULL;
char *cols = NULL, *extra = NULL, *vals = NULL, *query = NULL,
*tmp_extra = NULL;
time_t now = time(NULL);
char *user_name = NULL;
int affect_rows = 0;
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return ESLURM_DB_CONNECTION;
if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR))
return ESLURM_ACCESS_DENIED;
if (!tres_list_in || !list_count(tres_list_in)) {
error("%s: Trying to add empty tres list", __func__);
return ESLURM_EMPTY_LIST;
}
user_name = uid_to_string((uid_t) uid);
itr = list_iterator_create(tres_list_in);
while ((object = list_next(itr))) {
if (!object->type || !object->type[0]) {
error("We need a tres type.");
rc = SLURM_ERROR;
continue;
} else if ((!xstrcasecmp(object->type, "gres") ||
!xstrcasecmp(object->type, "bb") ||
!xstrcasecmp(object->type, "license") ||
!xstrcasecmp(object->type, "fs") ||
!xstrcasecmp(object->type, "ic"))) {
if (!object->name) {
error("%s type tres "
"need to have a name, "
"(i.e. Gres/GPU). You gave none",
object->type);
rc = SLURM_ERROR;
continue;
}
} else /* only the above have a name */
xfree(object->name);
xstrcat(cols, "creation_time, type");
xstrfmtcat(vals, "%ld, '%s'", now, object->type);
xstrfmtcat(extra, "type='%s'", object->type);
if (object->name) {
xstrcat(cols, ", name");
xstrfmtcat(vals, ", '%s'", object->name);
xstrfmtcat(extra, ", name='%s'", object->name);
}
xstrfmtcat(query,
"insert into %s (%s) values (%s) "
"on duplicate key update deleted=0, "
"id=LAST_INSERT_ID(id);",
tres_table, cols, vals);
DB_DEBUG(DB_TRES, mysql_conn->conn, "query\n%s", query);
object->id = (uint32_t)mysql_db_insert_ret_id(
mysql_conn, query);
xfree(query);
if (!object->id) {
error("Couldn't add tres %s%s%s", object->type,
object->name ? "/" : "",
object->name ? object->name : "");
xfree(cols);
xfree(extra);
xfree(vals);
break;
}
affect_rows = last_affected_rows(mysql_conn);
if (!affect_rows) {
debug2("nothing changed %d", affect_rows);
xfree(cols);
xfree(extra);
xfree(vals);
continue;
}
tmp_extra = slurm_add_slash_to_quotes(extra);
xstrfmtcat(query,
"insert into %s "
"(timestamp, action, name, actor, info, cluster) "
"values (%ld, %u, 'id=%d', '%s', '%s', '%s');",
txn_table,
now, DBD_ADD_TRES, object->id, user_name,
tmp_extra, mysql_conn->cluster_name);
xfree(tmp_extra);
xfree(cols);
xfree(extra);
xfree(vals);
debug4("query\n%s", query);
rc = mysql_db_query(mysql_conn, query);
xfree(query);
if (rc != SLURM_SUCCESS) {
error("Couldn't add txn");
} else {
if (addto_update_list(mysql_conn->update_list,
SLURMDB_ADD_TRES,
object) == SLURM_SUCCESS)
list_remove(itr);
}
}
list_iterator_destroy(itr);
xfree(user_name);
if (list_count(mysql_conn->update_list)) {
/* We only want to update the local cache DBD or ctld */
assoc_mgr_update(mysql_conn->update_list, 0);
list_flush(mysql_conn->update_list);
}
return rc;
}
extern list_t *as_mysql_get_tres(mysql_conn_t *mysql_conn, uid_t uid,
slurmdb_tres_cond_t *tres_cond)
{
char *query = NULL;
char *extra = NULL;
char *tmp = NULL;
list_t *my_tres_list = NULL;
list_itr_t *itr = NULL;
char *object = NULL;
int set = 0;
int i=0;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
/* if this changes you will need to edit the corresponding enum */
char *tres_req_inx[] = {
"id",
"type",
"name"
};
enum {
SLURMDB_REQ_ID,
SLURMDB_REQ_TYPE,
SLURMDB_REQ_NAME,
SLURMDB_REQ_COUNT
};
if (check_connection(mysql_conn) != SLURM_SUCCESS)
return NULL;
if (!tres_cond) {
xstrcat(extra, "where deleted=0");
goto empty;
}
if (tres_cond->with_deleted)
xstrcat(extra, "where (deleted=0 || deleted=1)");
else
xstrcat(extra, "where deleted=0");
if (tres_cond->id_list
&& list_count(tres_cond->id_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(tres_cond->id_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "id='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (tres_cond->type_list
&& list_count(tres_cond->type_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(tres_cond->type_list);
while ((object = list_next(itr))) {
char *slash;
if (set)
xstrcat(extra, " || ");
if (!(slash = strchr(object, '/')))
xstrfmtcat(extra, "type='%s'", object);
else {
/* This means we have the name
* attached, so split the string and
* handle it this way, only on this type.
*/
char *name = slash;
*slash = '\0';
name++;
xstrfmtcat(extra, "(type='%s' && name='%s')",
object, name);
}
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
if (tres_cond->name_list
&& list_count(tres_cond->name_list)) {
set = 0;
xstrcat(extra, " && (");
itr = list_iterator_create(tres_cond->name_list);
while ((object = list_next(itr))) {
if (set)
xstrcat(extra, " || ");
xstrfmtcat(extra, "name='%s'", object);
set = 1;
}
list_iterator_destroy(itr);
xstrcat(extra, ")");
}
empty:
xfree(tmp);
xstrfmtcat(tmp, "%s", tres_req_inx[i]);
for(i=1; i<SLURMDB_REQ_COUNT; i++) {
xstrfmtcat(tmp, ", %s", tres_req_inx[i]);
}
query = xstrdup_printf("select %s from %s %s order by id",
tmp, tres_table, extra);
xfree(tmp);
xfree(extra);
DB_DEBUG(DB_TRES, mysql_conn->conn, "query\n%s", query);
if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) {
xfree(query);
return NULL;
}
xfree(query);
my_tres_list = list_create(slurmdb_destroy_tres_rec);
while ((row = mysql_fetch_row(result))) {
slurmdb_tres_rec_t *tres =
xmalloc(sizeof(slurmdb_tres_rec_t));
list_append(my_tres_list, tres);
tres->id = slurm_atoul(row[SLURMDB_REQ_ID]);
if (row[SLURMDB_REQ_TYPE] && row[SLURMDB_REQ_TYPE][0])
tres->type = xstrdup(row[SLURMDB_REQ_TYPE]);
if (row[SLURMDB_REQ_NAME] && row[SLURMDB_REQ_NAME][0])
tres->name = xstrdup(row[SLURMDB_REQ_NAME]);
}
mysql_free_result(result);
return my_tres_list;
}