blob: a1008d33fb2e2696716ee02f2ca3cacfa7f4ede8 [file] [log] [blame]
/*****************************************************************************\
* user_report_functions.c - Interface to functions dealing with user reports.
******************************************************************************
* Copyright (C) 2010 Lawrence Livermore National Security.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Danny Auble da@llnl.gov, et. al.
* CODE-OCEC-09-009. All rights reserved.
*
* 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 "slurm/slurm.h"
#include "slurm/slurm_errno.h"
#include "slurm/slurmdb.h"
#include "src/common/slurmdb_defs.h"
#include "src/interfaces/accounting_storage.h"
#include "src/common/xstring.h"
extern list_t *slurmdb_report_user_top_usage(void *db_conn,
slurmdb_user_cond_t *user_cond,
bool group_accounts)
{
list_t *cluster_list = NULL;
list_itr_t *itr = NULL, *itr2 = NULL, *itr3 = NULL;
list_itr_t *cluster_itr = NULL;
slurmdb_cluster_cond_t cluster_cond;
list_t *user_list = NULL;
list_t *usage_cluster_list = NULL;
char *object = NULL;
int exit_code = 0;
slurmdb_user_rec_t *user = NULL;
slurmdb_cluster_rec_t *cluster = NULL;
slurmdb_assoc_rec_t *assoc = NULL;
slurmdb_report_user_rec_t *slurmdb_report_user = NULL;
slurmdb_report_cluster_rec_t *slurmdb_report_cluster = NULL;
uid_t my_uid = getuid();
bool delete_user_cond = 0, delete_assoc_cond = 0,
delete_cluster_list = 0;
time_t start_time, end_time;
if (!user_cond) {
delete_user_cond = 1;
user_cond = xmalloc(sizeof(slurmdb_user_cond_t));
}
if (!user_cond->assoc_cond) {
delete_assoc_cond = 1;
user_cond->assoc_cond =
xmalloc(sizeof(slurmdb_assoc_cond_t));
}
if (!user_cond->assoc_cond->cluster_list) {
delete_cluster_list = 1;
user_cond->assoc_cond->cluster_list = list_create(xfree_ptr);
}
user_cond->with_deleted = 1;
user_cond->with_assocs = 1;
user_cond->assoc_cond->flags = ASSOC_COND_FLAG_WITH_NG_USAGE |
ASSOC_COND_FLAG_WOPI;
/* This needs to be done on some systems to make sure
assoc_cond isn't messed up. This has happened on some 64
bit machines and this is here to be on the safe side.
*/
start_time = user_cond->assoc_cond->usage_start;
end_time = user_cond->assoc_cond->usage_end;
slurmdb_report_set_start_end_time(&start_time, &end_time);
user_cond->assoc_cond->usage_start = start_time;
user_cond->assoc_cond->usage_end = end_time;
user_list = acct_storage_g_get_users(db_conn, my_uid, user_cond);
if (!user_list) {
exit_code=1;
fprintf(stderr, " Problem with user query.\n");
goto end_it;
}
/* We have to get the clusters here or we will be unable to
get the correct total time for the cluster if associations
are not enforced.
*/
slurmdb_init_cluster_cond(&cluster_cond, 0);
cluster_cond.with_usage = 1;
cluster_cond.with_deleted = 1;
cluster_cond.usage_end = user_cond->assoc_cond->usage_end;
cluster_cond.usage_start = user_cond->assoc_cond->usage_start;
cluster_cond.cluster_list = user_cond->assoc_cond->cluster_list;
usage_cluster_list = acct_storage_g_get_clusters(
db_conn, my_uid, &cluster_cond);
if (!usage_cluster_list) {
exit_code=1;
fprintf(stderr, " Problem with cluster query.\n");
goto end_it;
}
cluster_list = list_create(slurmdb_destroy_report_cluster_rec);
itr = list_iterator_create(usage_cluster_list);
while((cluster = list_next(itr))) {
/* check to see if this cluster is around during the
time we are looking at */
if (!cluster->accounting_list
|| !list_count(cluster->accounting_list))
continue;
slurmdb_report_cluster = slurmdb_cluster_rec_2_report(cluster);
list_append(cluster_list, slurmdb_report_cluster);
slurmdb_report_cluster->user_list =
list_create(slurmdb_destroy_report_user_rec);
}
list_iterator_destroy(itr);
FREE_NULL_LIST(usage_cluster_list);
itr = list_iterator_create(user_list);
cluster_itr = list_iterator_create(cluster_list);
while((user = list_next(itr))) {
struct passwd *passwd_ptr = NULL;
if (!user->assoc_list || !list_count(user->assoc_list))
continue;
passwd_ptr = getpwnam(user->name);
if (passwd_ptr)
user->uid = passwd_ptr->pw_uid;
else
user->uid = NO_VAL;
itr2 = list_iterator_create(user->assoc_list);
while((assoc = list_next(itr2))) {
if (!assoc->accounting_list
|| !list_count(assoc->accounting_list))
continue;
while((slurmdb_report_cluster =
list_next(cluster_itr))) {
if (!xstrcmp(slurmdb_report_cluster->name,
assoc->cluster)) {
list_itr_t *user_itr = NULL;
if (!group_accounts) {
slurmdb_report_user = NULL;
goto new_user;
}
user_itr = list_iterator_create(
slurmdb_report_cluster->
user_list);
while((slurmdb_report_user
= list_next(user_itr))) {
if (slurmdb_report_user->uid
!= NO_VAL) {
if (slurmdb_report_user->
uid
== user->uid)
break;
} else if (slurmdb_report_user->
name
&& !xstrcasecmp(
slurmdb_report_user->
name,
user->name))
break;
}
list_iterator_destroy(user_itr);
new_user:
if (!slurmdb_report_user) {
slurmdb_report_user = xmalloc(
sizeof
(slurmdb_report_user_rec_t));
slurmdb_report_user->name =
xstrdup(assoc->user);
slurmdb_report_user->uid =
user->uid;
slurmdb_report_user->acct_list =
list_create(xfree_ptr);
slurmdb_report_user->partition =
xstrdup(assoc->partition);
list_append(slurmdb_report_cluster->
user_list,
slurmdb_report_user);
/*
* In order to know that
* partition associations exist
* for reporting we need to add
* an empty partition list to
* user_cond.
*/
if (slurmdb_report_user->
partition &&
!user_cond->assoc_cond->
partition_list) {
user_cond->assoc_cond->
partition_list =
list_create(NULL);
}
}
break;
}
}
if (!slurmdb_report_cluster) {
error("This cluster '%s' hasn't "
"registered yet, but we have jobs "
"that ran?", assoc->cluster);
slurmdb_report_cluster =
xmalloc(sizeof(slurmdb_report_cluster_rec_t));
list_append(cluster_list, slurmdb_report_cluster);
slurmdb_report_cluster->name = xstrdup(assoc->cluster);
slurmdb_report_cluster->user_list =
list_create(slurmdb_destroy_report_user_rec);
slurmdb_report_user =
xmalloc(sizeof(slurmdb_report_user_rec_t));
slurmdb_report_user->name = xstrdup(assoc->user);
slurmdb_report_user->uid = user->uid;
slurmdb_report_user->acct_list =
list_create(xfree_ptr);
list_append(slurmdb_report_cluster->user_list,
slurmdb_report_user);
}
list_iterator_reset(cluster_itr);
itr3 = list_iterator_create(
slurmdb_report_user->acct_list);
while((object = list_next(itr3))) {
if (!xstrcmp(object, assoc->acct))
break;
}
list_iterator_destroy(itr3);
if (!object)
list_append(slurmdb_report_user->acct_list,
xstrdup(assoc->acct));
slurmdb_transfer_acct_list_2_tres(
assoc->accounting_list,
&slurmdb_report_user->tres_list);
}
list_iterator_destroy(itr2);
}
list_iterator_destroy(itr);
list_iterator_destroy(cluster_itr);
end_it:
if (delete_cluster_list) {
FREE_NULL_LIST(user_cond->assoc_cond->cluster_list);
user_cond->assoc_cond->cluster_list = NULL;
}
if (delete_assoc_cond) {
slurmdb_destroy_assoc_cond(user_cond->assoc_cond);
user_cond->assoc_cond = NULL;
}
if (delete_user_cond) {
slurmdb_destroy_user_cond(user_cond);
user_cond = NULL;
}
FREE_NULL_LIST(user_list);
if (exit_code) {
FREE_NULL_LIST(cluster_list);
}
return cluster_list;
}