1 /*****************************************************************************\
2 * user_report_functions.c - Interface to functions dealing with user reports.
3 ******************************************************************************
4 * Copyright (C) 2010 Lawrence Livermore National Security.
5 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
6 * Written by Danny Auble da@llnl.gov, et. al.
7 * CODE-OCEC-09-009. All rights reserved.
8 *
9 * This file is part of Slurm, a resource management program.
10 * For details, see <https://slurm.schedmd.com/>.
11 * Please also read the included file: DISCLAIMER.
12 *
13 * Slurm is free software; you can redistribute it and/or modify it under
14 * the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
16 * any later version.
17 *
18 * In addition, as a special exception, the copyright holders give permission
19 * to link the code of portions of this program with the OpenSSL library under
20 * certain conditions as described in each individual source file, and
21 * distribute linked combinations including the two. You must obey the GNU
22 * General Public License in all respects for all of the code used other than
23 * OpenSSL. If you modify file(s) with this exception, you may extend this
24 * exception to your version of the file(s), but you are not obligated to do
25 * so. If you do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source files in
27 * the program, then also delete it here.
28 *
29 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
30 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
32 * details.
33 *
34 * You should have received a copy of the GNU General Public License along
35 * with Slurm; if not, write to the Free Software Foundation, Inc.,
36 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 \*****************************************************************************/
38
39 #include "slurm/slurm.h"
40 #include "slurm/slurm_errno.h"
41 #include "slurm/slurmdb.h"
42
43 #include "src/common/slurmdb_defs.h"
44 #include "src/common/slurm_accounting_storage.h"
45 #include "src/common/xstring.h"
46
slurmdb_report_user_top_usage(void * db_conn,slurmdb_user_cond_t * user_cond,bool group_accounts)47 extern List slurmdb_report_user_top_usage(void *db_conn,
48 slurmdb_user_cond_t *user_cond,
49 bool group_accounts)
50 {
51 List cluster_list = NULL;
52 ListIterator itr = NULL;
53 ListIterator itr2 = NULL;
54 ListIterator itr3 = NULL;
55 ListIterator cluster_itr = NULL;
56 slurmdb_cluster_cond_t cluster_cond;
57 List user_list = NULL;
58 List usage_cluster_list = NULL;
59 char *object = NULL;
60 int exit_code = 0;
61 slurmdb_user_rec_t *user = NULL;
62 slurmdb_cluster_rec_t *cluster = NULL;
63 slurmdb_assoc_rec_t *assoc = NULL;
64 slurmdb_report_user_rec_t *slurmdb_report_user = NULL;
65 slurmdb_report_cluster_rec_t *slurmdb_report_cluster = NULL;
66 uid_t my_uid = getuid();
67 bool delete_user_cond = 0, delete_assoc_cond = 0,
68 delete_cluster_list = 0;
69 time_t start_time, end_time;
70
71 if (!user_cond) {
72 delete_user_cond = 1;
73 user_cond = xmalloc(sizeof(slurmdb_user_cond_t));
74 }
75
76 if (!user_cond->assoc_cond) {
77 delete_assoc_cond = 1;
78 user_cond->assoc_cond =
79 xmalloc(sizeof(slurmdb_assoc_cond_t));
80 }
81
82 if (!user_cond->assoc_cond->cluster_list) {
83 delete_cluster_list = 1;
84 user_cond->assoc_cond->cluster_list = list_create(xfree_ptr);
85 }
86
87 user_cond->with_deleted = 1;
88 user_cond->with_assocs = 1;
89 user_cond->assoc_cond->with_usage = 1;
90 user_cond->assoc_cond->without_parent_info = 1;
91
92 /* This needs to be done on some systems to make sure
93 assoc_cond isn't messed up. This has happened on some 64
94 bit machines and this is here to be on the safe side.
95 */
96 start_time = user_cond->assoc_cond->usage_start;
97 end_time = user_cond->assoc_cond->usage_end;
98 slurmdb_report_set_start_end_time(&start_time, &end_time);
99 user_cond->assoc_cond->usage_start = start_time;
100 user_cond->assoc_cond->usage_end = end_time;
101
102 user_list = acct_storage_g_get_users(db_conn, my_uid, user_cond);
103 if (!user_list) {
104 exit_code=1;
105 fprintf(stderr, " Problem with user query.\n");
106 goto end_it;
107 }
108
109 /* We have to get the clusters here or we will be unable to
110 get the correct total time for the cluster if associations
111 are not enforced.
112 */
113 slurmdb_init_cluster_cond(&cluster_cond, 0);
114 cluster_cond.with_usage = 1;
115 cluster_cond.with_deleted = 1;
116 cluster_cond.usage_end = user_cond->assoc_cond->usage_end;
117 cluster_cond.usage_start = user_cond->assoc_cond->usage_start;
118 cluster_cond.cluster_list = user_cond->assoc_cond->cluster_list;
119
120 usage_cluster_list = acct_storage_g_get_clusters(
121 db_conn, my_uid, &cluster_cond);
122 if (!usage_cluster_list) {
123 exit_code=1;
124 fprintf(stderr, " Problem with cluster query.\n");
125 goto end_it;
126 }
127
128 cluster_list = list_create(slurmdb_destroy_report_cluster_rec);
129
130 itr = list_iterator_create(usage_cluster_list);
131 while((cluster = list_next(itr))) {
132 /* check to see if this cluster is around during the
133 time we are looking at */
134 if (!cluster->accounting_list
135 || !list_count(cluster->accounting_list))
136 continue;
137
138 slurmdb_report_cluster = slurmdb_cluster_rec_2_report(cluster);
139
140 list_append(cluster_list, slurmdb_report_cluster);
141
142 slurmdb_report_cluster->user_list =
143 list_create(slurmdb_destroy_report_user_rec);
144 }
145 list_iterator_destroy(itr);
146 FREE_NULL_LIST(usage_cluster_list);
147
148 itr = list_iterator_create(user_list);
149 cluster_itr = list_iterator_create(cluster_list);
150 while((user = list_next(itr))) {
151 struct passwd *passwd_ptr = NULL;
152 if (!user->assoc_list || !list_count(user->assoc_list))
153 continue;
154
155 passwd_ptr = getpwnam(user->name);
156 if (passwd_ptr)
157 user->uid = passwd_ptr->pw_uid;
158 else
159 user->uid = NO_VAL;
160
161 itr2 = list_iterator_create(user->assoc_list);
162 while((assoc = list_next(itr2))) {
163
164 if (!assoc->accounting_list
165 || !list_count(assoc->accounting_list))
166 continue;
167
168 while((slurmdb_report_cluster =
169 list_next(cluster_itr))) {
170 if (!xstrcmp(slurmdb_report_cluster->name,
171 assoc->cluster)) {
172 ListIterator user_itr = NULL;
173 if (!group_accounts) {
174 slurmdb_report_user = NULL;
175 goto new_user;
176 }
177 user_itr = list_iterator_create(
178 slurmdb_report_cluster->
179 user_list);
180 while((slurmdb_report_user
181 = list_next(user_itr))) {
182 if (slurmdb_report_user->uid
183 != NO_VAL) {
184 if (slurmdb_report_user->
185 uid
186 == user->uid)
187 break;
188 } else if (slurmdb_report_user->
189 name
190 && !xstrcasecmp(
191 slurmdb_report_user->
192 name,
193 user->name))
194 break;
195 }
196 list_iterator_destroy(user_itr);
197 new_user:
198 if (!slurmdb_report_user) {
199 slurmdb_report_user = xmalloc(
200 sizeof
201 (slurmdb_report_user_rec_t));
202 slurmdb_report_user->name =
203 xstrdup(assoc->user);
204 slurmdb_report_user->uid =
205 user->uid;
206 slurmdb_report_user->acct_list =
207 list_create(xfree_ptr);
208 list_append(slurmdb_report_cluster->
209 user_list,
210 slurmdb_report_user);
211 }
212 break;
213 }
214 }
215 if (!slurmdb_report_cluster) {
216 error("This cluster '%s' hasn't "
217 "registered yet, but we have jobs "
218 "that ran?", assoc->cluster);
219 slurmdb_report_cluster =
220 xmalloc(sizeof(slurmdb_report_cluster_rec_t));
221 list_append(cluster_list, slurmdb_report_cluster);
222
223 slurmdb_report_cluster->name = xstrdup(assoc->cluster);
224 slurmdb_report_cluster->user_list =
225 list_create(slurmdb_destroy_report_user_rec);
226 slurmdb_report_user =
227 xmalloc(sizeof(slurmdb_report_user_rec_t));
228 slurmdb_report_user->name = xstrdup(assoc->user);
229 slurmdb_report_user->uid = user->uid;
230 slurmdb_report_user->acct_list =
231 list_create(xfree_ptr);
232 list_append(slurmdb_report_cluster->user_list,
233 slurmdb_report_user);
234 }
235 list_iterator_reset(cluster_itr);
236
237 itr3 = list_iterator_create(
238 slurmdb_report_user->acct_list);
239 while((object = list_next(itr3))) {
240 if (!xstrcmp(object, assoc->acct))
241 break;
242 }
243 list_iterator_destroy(itr3);
244
245 if (!object)
246 list_append(slurmdb_report_user->acct_list,
247 xstrdup(assoc->acct));
248 slurmdb_transfer_acct_list_2_tres(
249 assoc->accounting_list,
250 &slurmdb_report_user->tres_list);
251 }
252 list_iterator_destroy(itr2);
253 }
254 list_iterator_destroy(itr);
255 list_iterator_destroy(cluster_itr);
256
257 end_it:
258 if (delete_cluster_list) {
259 FREE_NULL_LIST(user_cond->assoc_cond->cluster_list);
260 user_cond->assoc_cond->cluster_list = NULL;
261 }
262
263 if (delete_assoc_cond) {
264 slurmdb_destroy_assoc_cond(user_cond->assoc_cond);
265 user_cond->assoc_cond = NULL;
266 }
267
268 if (delete_user_cond) {
269 slurmdb_destroy_user_cond(user_cond);
270 user_cond = NULL;
271 }
272
273 FREE_NULL_LIST(user_list);
274
275 if (exit_code) {
276 FREE_NULL_LIST(cluster_list);
277 }
278
279 return cluster_list;
280 }
281