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