1 /****************************************************************************\
2  *  resource_functions.c - functions dealing with resources in the
3  *                        accounting system.
4  *****************************************************************************
5  *  Copyright (C) 2013 Bull S. A. S.
6  *		Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois.
7  *
8  *  Written by Bill Brophy <bill.brophy@bull.com>
9  *
10  *  This file is part of Slurm, a resource management program.
11  *  For details, see <https://slurm.schedmd.com>.
12  *  Please also read the included file: DISCLAIMER.
13  *
14  *  Slurm is free software; you can redistribute it and/or modify it under
15  *  the terms of the GNU General Public License as published by the Free
16  *  Software Foundation; either version 2 of the License, or (at your option)
17  *  any later version.
18  *
19  *  In addition, as a special exception, the copyright holders give permission
20  *  to link the code of portions of this program with the OpenSSL library under
21  *  certain conditions as described in each individual source file, and
22  *  distribute linked combinations including the two. You must obey the GNU
23  *  General Public License in all respects for all of the code used other than
24  *  OpenSSL. If you modify file(s) with this exception, you may extend this
25  *  exception to your version of the file(s), but you are not obligated to do
26  *  so. If you do not wish to do so, delete this exception statement from your
27  *  version.  If you delete this exception statement from all source files in
28  *  the program, then also delete it here.
29  *
30  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
31  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
32  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
33  *  details.
34  *
35  *  You should have received a copy of the GNU General Public License along
36  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
37  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
38 \****************************************************************************/
39 
40 #include "src/sacctmgr/sacctmgr.h"
41 
_print_overcommit(slurmdb_res_rec_t * res,slurmdb_res_cond_t * res_cond)42 static void _print_overcommit(slurmdb_res_rec_t *res,
43 			      slurmdb_res_cond_t *res_cond)
44 {
45 	List res_list = NULL, cluster_list = NULL;
46 	ListIterator itr, clus_itr = NULL, found_clus_itr = NULL;
47 	slurmdb_res_rec_t *found_res;
48 	slurmdb_clus_res_rec_t *clus_res = NULL;
49 	char *cluster;
50 
51 	if (res->percent_used == NO_VAL16)
52 		return;
53 
54 	/* Don't use the global g_res_list since we are going to
55 	 * change the contents of this one.
56 	 */
57 	res_cond->with_clusters = 1;
58 
59 	if (res_cond->cluster_list) {
60 		cluster_list = res_cond->cluster_list;
61 		res_cond->cluster_list = NULL;
62 	}
63 
64 	res_list = slurmdb_res_get(db_conn, res_cond);
65 	if (!res_list) {
66 		exit_code=1;
67 		fprintf(stderr, " Problem getting system resources "
68 			"from database.  Contact your admin.\n");
69 		return;
70 	}
71 
72 	itr = list_iterator_create(res_list);
73 	while ((found_res = list_next(itr))) {
74 		int total = 0, percent_allowed;
75 		fprintf(stderr, "  %s@%s\n",
76 			found_res->name, found_res->server);
77 		if (cluster_list)
78 			clus_itr = list_iterator_create(cluster_list);
79 		if (found_res->clus_res_list) {
80 			found_clus_itr = list_iterator_create(
81 				found_res->clus_res_list);
82 			while ((clus_res = list_next(found_clus_itr))) {
83 				cluster = NULL;
84 				if (clus_itr) {
85 					while ((cluster = list_next(clus_itr)))
86 						if (!xstrcmp(cluster,
87 							     clus_res->cluster))
88 						    break;
89 					list_iterator_reset(clus_itr);
90 				} else {
91 					/*
92 					 * This means we didn't specify any
93 					 * clusters (All clusters are
94 					 * overwritten with the requested
95 					 * percentage) so just put something
96 					 * there to get the correct
97 					 * percent_allowed.
98 					 */
99 					cluster = "nothing";
100 				}
101 				percent_allowed = cluster ? res->percent_used :
102 					clus_res->percent_allowed;
103 				total += percent_allowed;
104 
105 				fprintf(stderr,
106 					"   Cluster - %s\t %u%%\n",
107 					clus_res->cluster,
108 					percent_allowed);
109 			}
110 		} else if (clus_itr) {
111 			while ((cluster = list_next(clus_itr))) {
112 				total += res->percent_used;
113 				fprintf(stderr,
114 					"   Cluster - %s\t %u%%\n",
115 					cluster,
116 					res->percent_used);
117 			}
118 		}
119 		if (clus_itr)
120 			list_iterator_destroy(clus_itr);
121 		if (found_clus_itr)
122 			list_iterator_destroy(found_clus_itr);
123 		fprintf(stderr, "   total\t\t%u%%\n", total);
124 	}
125 	list_iterator_destroy(itr);
126 
127 	if (cluster_list) {
128 		res_cond->cluster_list = cluster_list;
129 		cluster_list = NULL;
130 	}
131 }
132 
_set_res_cond(int * start,int argc,char ** argv,slurmdb_res_cond_t * res_cond,List format_list)133 static int _set_res_cond(int *start, int argc, char **argv,
134 			     slurmdb_res_cond_t *res_cond,
135 			     List format_list)
136 {
137 	int i;
138 	int set = 0;
139 	int end = 0;
140 	int command_len = 0;
141 
142 	if (!res_cond) {
143 		error("No res_cond given");
144 		return -1;
145 	}
146 
147 	for (i=(*start); i<argc; i++) {
148 		end = parse_option_end(argv[i]);
149 		if (!end)
150 			command_len=strlen(argv[i]);
151 		else {
152 			command_len=end-1;
153 			if (argv[i][end] == '=') {
154 				end++;
155 			}
156 		}
157 
158 		if (!xstrncasecmp(argv[i], "Set", MAX(command_len, 3))) {
159 			i--;
160 			break;
161 		} else if (!end && !xstrncasecmp(argv[i], "WithDeleted",
162 						 MAX(command_len, 5))) {
163 			res_cond->with_deleted = 1;
164 		} else if (!end && !xstrncasecmp(argv[i], "WithClusters",
165 						 MAX(command_len, 5))) {
166 			res_cond->with_clusters = 1;
167 		} else if (!end && !xstrncasecmp(argv[i], "where",
168 						 MAX(command_len, 5))) {
169 			continue;
170 		} else if (!end
171 			   || !xstrncasecmp(argv[i], "Names",
172 					    MAX(command_len, 1))) {
173 			if (!res_cond->name_list) {
174 				res_cond->name_list = list_create(xfree_ptr);
175 			}
176 			if (slurm_addto_char_list(res_cond->name_list,
177 						  argv[i]+end))
178 				set = 1;
179 		} else if (!end
180 			   || !xstrncasecmp(argv[i], "Clusters",
181 					    MAX(command_len, 1))) {
182 			if (!res_cond->cluster_list) {
183 				res_cond->cluster_list = list_create(xfree_ptr);
184 			}
185 
186 			slurm_addto_char_list(res_cond->cluster_list,
187 					      argv[i]+end);
188 			if (sacctmgr_validate_cluster_list(
189 				    res_cond->cluster_list) != SLURM_SUCCESS) {
190 				exit_code=1;
191 				fprintf(stderr,
192 					" Need a valid cluster name to "
193 					"add a cluster resource.\n");
194 			} else
195 				set = 1;
196 		} else if (!xstrncasecmp(argv[i], "Descriptions",
197 					 MAX(command_len, 1))) {
198 			if (!res_cond->description_list) {
199 				res_cond->description_list =
200 					list_create(xfree_ptr);
201 			}
202 			if (slurm_addto_char_list(
203 				    res_cond->description_list,
204 				    argv[i]+end))
205 				set = 1;
206 		} else if (!xstrncasecmp(argv[i], "Format",
207 					 MAX(command_len, 1))) {
208 			if (format_list)
209 				slurm_addto_char_list(format_list, argv[i]+end);
210 		} else if (!xstrncasecmp(argv[i], "Ids", MAX(command_len, 1))) {
211 			ListIterator itr = NULL;
212 			char *temp = NULL;
213 			uint32_t id = 0;
214 
215 			if (!res_cond->id_list) {
216 				res_cond->id_list = list_create(xfree_ptr);
217 			}
218 			if (slurm_addto_char_list(res_cond->id_list,
219 						  argv[i]+end))
220 				set = 1;
221 
222 			/* check to make sure user gave ints here */
223 			itr = list_iterator_create(res_cond->id_list);
224 			while ((temp = list_next(itr))) {
225 				if (get_uint(temp, &id, "RES ID")
226 				    != SLURM_SUCCESS) {
227 					exit_code = 1;
228 					list_delete_item(itr);
229 				}
230 			}
231 			list_iterator_destroy(itr);
232 		} else if (!xstrncasecmp(argv[i], "PercentAllowed",
233 					 MAX(command_len, 1))) {
234 			if (!res_cond->percent_list) {
235 				res_cond->percent_list = list_create(xfree_ptr);
236 			}
237 			if (slurm_addto_char_list(res_cond->percent_list,
238 						  argv[i]+end))
239 				set = 1;
240 		} else if (!xstrncasecmp(argv[i], "ServerType",
241 					 MAX(command_len, 7))) {
242 			if (!res_cond->manager_list) {
243 				res_cond->manager_list = list_create(xfree_ptr);
244 			}
245 			if (slurm_addto_char_list(res_cond->manager_list,
246 						  argv[i]+end))
247 				set = 1;
248 		} else if (!xstrncasecmp(argv[i], "Server",
249 					 MAX(command_len, 2))) {
250 			if (!res_cond->server_list) {
251 				res_cond->server_list = list_create(xfree_ptr);
252 			}
253 			if (slurm_addto_char_list(res_cond->server_list,
254 						  argv[i]+end))
255 				set = 1;
256 		} else {
257 			exit_code=1;
258 			fprintf(stderr, " Unknown condition: %s\n"
259 				" Use keyword 'set' to modify "
260 				"SLURM_PRINT_VALUE\n", argv[i]);
261 		}
262 	}
263 
264 	(*start) = i;
265 	return set;
266 }
267 
_set_res_rec(int * start,int argc,char ** argv,List name_list,List cluster_list,slurmdb_res_rec_t * res)268 static int _set_res_rec(int *start, int argc, char **argv,
269 			List name_list, List cluster_list,
270 			slurmdb_res_rec_t *res)
271 {
272 	int i;
273 	int set = 0;
274 	int end = 0;
275 	int command_len = 0;
276 	int option = 0;
277 
278 	xassert(res);
279 
280 	for (i=(*start); i<argc; i++) {
281 		end = parse_option_end(argv[i]);
282 		if (!end)
283 			command_len=strlen(argv[i]);
284 		else {
285 			command_len=end-1;
286 			if (argv[i][end] == '=') {
287 				option = (int)argv[i][end-1];
288 				end++;
289 			}
290 		}
291 
292 		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))) {
293 			i--;
294 			break;
295 		} else if (!end && !xstrncasecmp(argv[i], "set",
296 						 MAX(command_len, 3))) {
297 			continue;
298 		} else if (!end
299 			   || !xstrncasecmp(argv[i], "Names",
300 					    MAX(command_len, 1))
301 			   || !xstrncasecmp(argv[i], "Resources",
302 					    MAX(command_len, 1))) {
303 			if (name_list)
304 				slurm_addto_char_list(name_list, argv[i]+end);
305 		} else if (!xstrncasecmp(argv[i], "Clusters",
306 					 MAX(command_len, 1))) {
307 			if (cluster_list) {
308 				slurm_addto_char_list(cluster_list,
309 						      argv[i]+end);
310 				if (sacctmgr_validate_cluster_list(
311 					    cluster_list) != SLURM_SUCCESS) {
312 					exit_code=1;
313 					fprintf(stderr,
314 						" Need a valid cluster name to "
315 						"add a cluster resource.\n");
316 				}
317 			} else {
318 				exit_code=1;
319 				fprintf(stderr,
320 					" Can't modify the cluster "
321 					"of an resource\n");
322 			}
323 		} else if (!xstrncasecmp(argv[i], "Count",
324 					 MAX(command_len, 3))) {
325 			if (get_uint(argv[i]+end, &res->count,
326 				     "count") == SLURM_SUCCESS) {
327 				set = 1;
328 			}
329 		} else if (!xstrncasecmp(argv[i], "Description",
330 					 MAX(command_len, 1))) {
331 			if (!res->description)
332 				res->description =
333 					strip_quotes(argv[i]+end, NULL, 1);
334 			set = 1;
335 		} else if (!xstrncasecmp(argv[i], "Flags",
336 					 MAX(command_len, 2))) {
337 			res->flags = str_2_res_flags(argv[i]+end, option);
338 			if (res->flags == SLURMDB_RES_FLAG_NOTSET) {
339 				char *tmp_char = slurmdb_res_flags_str(
340 					SLURMDB_RES_FLAG_BASE);
341 				printf(" Unknown Server Resource flag used "
342 				       "in:\n  '%s'\n"
343 				       " Valid Server Resource flags are\n"
344 				       " '%s'\n", argv[i]+end, tmp_char);
345 				xfree(tmp_char);
346 				exit_code = 1;
347 			} else
348 				set = 1;
349 
350 		} else if (!xstrncasecmp(argv[i], "Server",
351 					MAX(command_len, 1))) {
352 			if (!res->server) {
353 				res->server=
354 					strip_quotes(argv[i]+end, NULL, 1);
355 			}
356 			set = 1;
357 		} else if (!xstrncasecmp(argv[i], "ServerType",
358 					 MAX(command_len, 1))) {
359 			if (!res->manager)
360 				res->manager =
361 					strip_quotes(argv[i]+end, NULL, 1);
362 			set = 1;
363 		} else if (!xstrncasecmp(argv[i], "PercentAllowed",
364 					 MAX(command_len, 1))) {
365 			/* overload percent_used here */
366 			if (get_uint16(argv[i]+end, &res->percent_used,
367 				       "PercentAllowed") == SLURM_SUCCESS) {
368 				set = 1;
369 			}
370 		} else if (!xstrncasecmp(argv[i], "Type",
371 					 MAX(command_len, 1))) {
372 			char *temp = strip_quotes(argv[i]+end, NULL, 1);
373 
374 			if (!xstrncasecmp("License", temp,
375 					  MAX(strlen(temp), 1))) {
376 				res->type = SLURMDB_RESOURCE_LICENSE;
377 			} else {
378 				exit_code = 1;
379 				fprintf(stderr,
380 					" Unknown resource type: '%s'  "
381 					"Valid resources is License.\n",
382 					temp);
383 			}
384 			xfree(temp);
385 		} else {
386 			exit_code = 1;
387 			printf(" Unknown option: %s\n"
388 			       " Use keyword 'where' to modify condition\n",
389 			       argv[i]);
390 		}
391 	}
392 
393 	(*start) = i;
394 
395 	return set;
396 }
397 
_print_res_format(slurmdb_res_rec_t * res,slurmdb_clus_res_rec_t * clus_res,ListIterator itr,int field_count)398 static void _print_res_format(slurmdb_res_rec_t *res,
399 			      slurmdb_clus_res_rec_t *clus_res,
400 			      ListIterator itr,
401 			      int field_count)
402 {
403 	int curr_inx = 1;
404 	char *tmp_char;
405 	print_field_t *field = NULL;
406 	uint32_t count;
407 
408 	xassert(itr);
409 	xassert(res);
410 
411 	while ((field = list_next(itr))) {
412 		switch(field->type) {
413 		case PRINT_ALLOWED:
414 			field->print_routine(
415 				field, clus_res ? clus_res->percent_allowed : 0,
416 				(curr_inx == field_count));
417 			break;
418 		case PRINT_CLUSTER:
419 			field->print_routine(
420 				field, clus_res ? clus_res->cluster : NULL,
421 				(curr_inx == field_count));
422 			break;
423 		case PRINT_CALLOWED:
424 			if (clus_res)
425 				count = (res->count *
426 					 clus_res->percent_allowed) / 100;
427 			else
428 				count = 0;
429 			field->print_routine(field, count,
430 					     (curr_inx == field_count));
431 			break;
432 		case PRINT_COUNT:
433 			field->print_routine(field,
434 					     res->count,
435 					     (curr_inx == field_count));
436 			break;
437 		case PRINT_DESC:
438 			field->print_routine(
439 				field, res->description,
440 				(curr_inx == field_count));
441 			break;
442 		case PRINT_ID:
443 			field->print_routine(
444 				field, res->id,
445 				(curr_inx == field_count));
446 			break;
447 		case PRINT_FLAGS:
448 			tmp_char = slurmdb_res_flags_str(res->flags);
449 			field->print_routine(
450 				field,
451 				tmp_char,
452 				(curr_inx == field_count));
453 			xfree(tmp_char);
454 			break;
455 		case PRINT_SERVERTYPE:
456 			field->print_routine(field,
457 					     res->manager,
458 					     (curr_inx == field_count));
459 			break;
460 		case PRINT_NAME:
461 			field->print_routine(
462 				field, res->name,
463 				(curr_inx == field_count));
464 			break;
465 		case PRINT_SERVER:
466 			field->print_routine(field,
467 					     res->server,
468 					     (curr_inx == field_count));
469 			break;
470 		case PRINT_TYPE:
471 			field->print_routine(field,
472 					     slurmdb_res_type_str(
473 						     res->type),
474 					     (curr_inx == field_count));
475 			break;
476 		case PRINT_ALLOCATED:
477 			field->print_routine(
478 				field, res->percent_used,
479 				(curr_inx == field_count));
480 			break;
481 		default:
482 			field->print_routine(
483 				field, NULL,
484 				(curr_inx == field_count));
485 			break;
486 		}
487 		curr_inx++;
488 	}
489 	list_iterator_reset(itr);
490 	printf("\n");
491 }
492 
sacctmgr_add_res(int argc,char ** argv)493 extern int sacctmgr_add_res(int argc, char **argv)
494 
495 {
496 	int rc = SLURM_SUCCESS;
497 	int i = 0, limit_set = 0;
498 	ListIterator itr = NULL;
499 	ListIterator clus_itr = NULL;
500 	slurmdb_res_rec_t *res = NULL;
501 	slurmdb_res_rec_t *found_res = NULL;
502 	slurmdb_res_rec_t *start_res = xmalloc(sizeof(slurmdb_res_rec_t));
503 	List cluster_list = list_create(xfree_ptr);
504 	List name_list = list_create(xfree_ptr);
505 	char *name = NULL;
506 	List res_list = NULL;
507 	char *res_str = NULL;
508 
509 	slurmdb_init_res_rec(start_res, 0);
510 
511 	for (i = 0; i < argc; i++) {
512 		int command_len = strlen(argv[i]);
513 		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))
514 		    || !xstrncasecmp(argv[i], "Set", MAX(command_len, 3)))
515 			i++;
516 
517 		limit_set += _set_res_rec(&i, argc, argv, name_list,
518 					  cluster_list, start_res);
519 	}
520 
521 	if (exit_code) {
522 		FREE_NULL_LIST(name_list);
523 		FREE_NULL_LIST(cluster_list);
524 		slurmdb_destroy_res_rec(start_res);
525 		return SLURM_ERROR;
526 	} else if (!list_count(name_list)) {
527 		FREE_NULL_LIST(name_list);
528 		FREE_NULL_LIST(cluster_list);
529 		slurmdb_destroy_res_rec(start_res);
530 		exit_code = 1;
531 		fprintf(stderr, " Need name of resource to add.\n");
532 		return SLURM_SUCCESS;
533 	}
534 
535 	if (!start_res->server) {
536 		/* assign some server name */
537 		start_res->server = xstrdup("slurmdb");
538 	}
539 
540 	if (!g_res_list) {
541 		slurmdb_res_cond_t res_cond;
542 		slurmdb_init_res_cond(&res_cond, 0);
543 		/* 2 means return all resources even if they don't
544 		   have clusters attached to them.
545 		*/
546 		res_cond.with_clusters = 2;
547 		g_res_list = slurmdb_res_get(db_conn, &res_cond);
548 		if (!g_res_list) {
549 			exit_code=1;
550 			fprintf(stderr, " Problem getting system resources "
551 				"from database.  "
552 				"Contact your admin.\n");
553 			FREE_NULL_LIST(name_list);
554 			FREE_NULL_LIST(cluster_list);
555 			slurmdb_destroy_res_rec(start_res);
556 			return SLURM_ERROR;
557 		}
558 	}
559 
560 	res_list = list_create(slurmdb_destroy_res_rec);
561 
562 	itr = list_iterator_create(name_list);
563 	if (cluster_list)
564 		clus_itr = list_iterator_create(cluster_list);
565 	while ((name = list_next(itr))) {
566 		bool added = false;
567 		found_res = sacctmgr_find_res_from_list(
568 			g_res_list, NO_VAL, name, start_res->server);
569 		if (!found_res) {
570 			if (start_res->type == SLURMDB_RESOURCE_NOTSET) {
571 				exit_code=1;
572 				fprintf(stderr,
573 					" Need to designate a resource "
574 					"type to initially add '%s'.\n", name);
575 				break;
576 
577 			} else if (start_res->count == NO_VAL) {
578 				exit_code=1;
579 				fprintf(stderr,
580 					" Need to designate a resource "
581 					"count to initially add '%s'.\n", name);
582 				break;
583 			}
584 			res = xmalloc(sizeof(slurmdb_res_rec_t));
585 			slurmdb_init_res_rec(res, 0);
586 			res->name = xstrdup(name);
587 			res->description =
588 				xstrdup(start_res->description ?
589 					start_res->description : name);
590 			res->manager = xstrdup(start_res->manager);
591 			res->server = xstrdup(start_res->server);
592 			res->count = start_res->count;
593 			res->flags = start_res->flags;
594 			res->type = start_res->type;
595 			res->percent_used = 0;
596 
597 			xstrfmtcat(res_str, "  %s@%s\n",
598 				   res->name, res->server);
599 			list_append(res_list, res);
600 			added = true;
601 		}
602 
603 		if (cluster_list && list_count(cluster_list)) {
604 			ListIterator found_itr = NULL;
605 			slurmdb_clus_res_rec_t *clus_res;
606 			char *cluster;
607 			uint16_t start_used = 0;
608 
609 			if (found_res) {
610 				if (found_res->clus_res_list)
611 					found_itr = list_iterator_create(
612 						found_res->clus_res_list);
613 				res = xmalloc(sizeof(slurmdb_res_rec_t));
614 				slurmdb_init_res_rec(res, 0);
615 				res->id = found_res->id;
616 				res->type = found_res->type;
617 				res->server = xstrdup(found_res->server);
618 				start_used = res->percent_used =
619 					found_res->percent_used;
620 			}
621 
622 			res->clus_res_list = list_create(
623 				slurmdb_destroy_clus_res_rec);
624 
625 			while ((cluster = list_next(clus_itr))) {
626 				clus_res = NULL;
627 				if (found_itr) {
628 					while ((clus_res =
629 						list_next(found_itr))) {
630 						if (!xstrcmp(clus_res->cluster,
631 							     cluster))
632 							break;
633 					}
634 					list_iterator_reset(found_itr);
635 				}
636 
637 				if (!clus_res) {
638 					if (!added) {
639 						xstrfmtcat(res_str,
640 							   "  %s@%s\n", name,
641 							   res->server);
642 						list_append(res_list, res);
643 						added = true;
644 					}
645 					/* make sure we don't overcommit */
646 					res->percent_used +=
647 						start_res->percent_used;
648 					if (res->percent_used > 100) {
649 						exit_code = 1;
650 						fprintf(stderr,
651 							" Adding this %d "
652 							"clusters to resource "
653 							"%s@%s at %u%% each "
654 							", with %u%% already "
655 							"used,  would go over "
656 							"100%%.  Please redo "
657 							"your math and "
658 							"resubmit.\n",
659 							list_count(
660 								cluster_list),
661 							res->name, res->server,
662 							start_res->percent_used,
663 							start_used);
664 						break;
665 					}
666 					clus_res = xmalloc(
667 						sizeof(slurmdb_clus_res_rec_t));
668 					list_append(res->clus_res_list,
669 						    clus_res);
670 					clus_res->cluster = xstrdup(cluster);
671 					clus_res->percent_allowed =
672 						start_res->percent_used;
673 					xstrfmtcat(res_str,
674 						   "   Cluster - %s\t%u%%\n",
675 						   cluster,
676 						   clus_res->percent_allowed);
677 					/* FIXME: make sure we don't
678 					   overcommit */
679 				}
680 			}
681 
682 			if (!added)
683 				slurmdb_destroy_res_rec(res);
684 
685 			if (found_itr)
686 				list_iterator_destroy(found_itr);
687 
688 			if (added && (res->percent_used > 100))
689 				break;
690 
691 			list_iterator_reset(clus_itr);
692 		}
693 	}
694 
695 	if (cluster_list)
696 		list_iterator_destroy(clus_itr);
697 
698 	list_iterator_destroy(itr);
699 
700 	FREE_NULL_LIST(name_list);
701 	FREE_NULL_LIST(cluster_list);
702 
703 	if (exit_code) {
704 		rc = SLURM_ERROR;
705 		goto end_it;
706 	}
707 
708 	if (!list_count(res_list)) {
709 		printf(" Nothing new added.\n");
710 		rc = SLURM_ERROR;
711 		goto end_it;
712 	}
713 
714 	if (res_str) {
715 		char *tmp_str;
716 		switch (res->type) {
717 		case SLURMDB_RESOURCE_LICENSE:
718 			tmp_str = "License";
719 			break;
720 		default:
721 			tmp_str = "Unknown";
722 		}
723 		printf(" Adding Resource(s)\n%s", res_str);
724 		printf(" Settings\n");
725 		if (res->name)
726 			printf("  Name           = %s\n", res->name);
727 		if (res->server)
728 			printf("  Server         = %s\n", res->server);
729 		if (res->description)
730 			printf("  Description    = %s\n", res->description);
731 		if (res->manager)
732 			printf("  ServerType     = %s\n", res->manager);
733 		if (res->count != NO_VAL)
734 			printf("  Count          = %u\n", res->count);
735 		printf("  Type           = %s\n", tmp_str);
736 
737 		xfree(res_str);
738 	}
739 
740 	if (list_count(res_list)) {
741 		notice_thread_init();
742 		rc = slurmdb_res_add(db_conn, res_list);
743 		notice_thread_fini();
744 	} else
745 		goto end_it;
746 	if (rc == SLURM_SUCCESS) {
747 		if (commit_check("Would you like to commit changes?")) {
748 			slurmdb_connection_commit(db_conn, 1);
749 		} else {
750 			printf(" Changes Discarded\n");
751 			slurmdb_connection_commit(db_conn, 0);
752 		}
753 	} else {
754 		exit_code = 1;
755 		fprintf(stderr, " Problem adding system resource: %s\n",
756 			slurm_strerror(rc));
757 		rc = SLURM_ERROR;
758 	}
759 
760 end_it:
761 	FREE_NULL_LIST(res_list);
762 	slurmdb_destroy_res_rec(start_res);
763 	return rc;
764 }
765 
sacctmgr_list_res(int argc,char ** argv)766 extern int sacctmgr_list_res(int argc, char **argv)
767 
768 {
769 	int rc = SLURM_SUCCESS;
770 	slurmdb_res_cond_t *res_cond = xmalloc(sizeof(slurmdb_res_cond_t));
771  	int i=0;
772 	ListIterator itr = NULL;
773 	ListIterator itr2 = NULL;
774 	slurmdb_res_rec_t *res = NULL;
775 	slurmdb_clus_res_rec_t *clus_res = NULL;
776 	List res_list = NULL;
777 	int field_count = 0;
778 	List format_list = list_create(xfree_ptr);
779 	List print_fields_list; /* types are of print_field_t */
780 
781 	slurmdb_init_res_cond(res_cond, 0);
782 
783 	for (i=0; i<argc; i++) {
784 		int command_len = strlen(argv[i]);
785 		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))
786 		    || !xstrncasecmp(argv[i], "Set", MAX(command_len, 3)))
787 			i++;
788 		_set_res_cond(&i, argc, argv, res_cond, format_list);
789 	}
790 
791 	if (exit_code) {
792 		slurmdb_destroy_res_cond(res_cond);
793 		FREE_NULL_LIST(format_list);
794 		return SLURM_ERROR;
795 	} else if (!list_count(format_list)) {
796 		slurm_addto_char_list(
797 			format_list,
798 			"Name,Server,Type,Count,Allocated,ServerType");
799 		if (res_cond->with_clusters)
800 			slurm_addto_char_list(
801 				format_list, "Cluster,Allowed");
802 	}
803 
804 	print_fields_list = sacctmgr_process_format_list(format_list);
805 	FREE_NULL_LIST(format_list);
806 
807 	if (exit_code) {
808 		rc = SLURM_ERROR;
809 		goto end_it;
810 	}
811 	res_list = slurmdb_res_get(db_conn, res_cond);
812 
813 	if (!res_list) {
814 		exit_code=1;
815 		fprintf(stderr, " Problem with query.\n");
816 		rc = SLURM_ERROR;
817 		goto end_it;
818 	}
819 	itr = list_iterator_create(res_list);
820 	itr2 = list_iterator_create(print_fields_list);
821 	print_fields_header(print_fields_list);
822 
823 	field_count = list_count(print_fields_list);
824 	while ((res = list_next(itr))) {
825 		if (res_cond->with_clusters && res->clus_res_list
826 		    && list_count(res->clus_res_list)) {
827 			ListIterator clus_itr = list_iterator_create(
828 				res->clus_res_list);
829 			while ((clus_res = list_next(clus_itr))) {
830 				_print_res_format(res, clus_res,
831 						  itr2, field_count);
832 			}
833 			list_iterator_destroy(clus_itr);
834 		} else
835 			_print_res_format(res, NULL, itr2, field_count);
836 
837 	}
838 	list_iterator_destroy(itr2);
839 	list_iterator_destroy(itr);
840 	FREE_NULL_LIST(res_list);
841 end_it:
842 	FREE_NULL_LIST(print_fields_list);
843 	slurmdb_destroy_res_cond(res_cond);
844 	return rc;
845 }
846 
sacctmgr_modify_res(int argc,char ** argv)847 extern int sacctmgr_modify_res(int argc, char **argv)
848 
849 {
850 	int rc = SLURM_SUCCESS;
851 	slurmdb_res_cond_t *res_cond =
852 		xmalloc(sizeof(slurmdb_res_cond_t));
853 	slurmdb_res_rec_t *res =
854 		xmalloc(sizeof(slurmdb_res_rec_t));
855 	int i=0;
856 	int cond_set = 0, rec_set = 0, set = 0;
857 	List ret_list = NULL;
858 
859 	slurmdb_init_res_cond(res_cond, 0);
860 	slurmdb_init_res_rec(res, 0);
861 
862 	for (i=0; i<argc; i++) {
863 		int command_len = strlen(argv[i]);
864 		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))) {
865 			i++;
866 			cond_set += _set_res_cond(&i, argc, argv,
867 						  res_cond, NULL);
868 
869 		} else if (!xstrncasecmp(argv[i], "Set", MAX(command_len, 3))) {
870 			i++;
871 			rec_set += _set_res_rec(&i, argc, argv,
872 						NULL, NULL, res);
873 		} else {
874 			cond_set += _set_res_cond(&i, argc, argv,
875 						  res_cond, NULL);
876 		}
877 	}
878 
879 	if (exit_code) {
880 		slurmdb_destroy_res_cond(res_cond);
881 		slurmdb_destroy_res_rec(res);
882 		return SLURM_ERROR;
883 	} else if (!rec_set) {
884 		exit_code=1;
885 		fprintf(stderr, " You didn't give me anything to set\n");
886 		slurmdb_destroy_res_cond(res_cond);
887 		slurmdb_destroy_res_rec(res);
888 		return SLURM_ERROR;
889 	} else if (!cond_set) {
890 		if (!commit_check("You didn't set any conditions with "
891 				  "'WHERE'.\n"
892 				  "Are you sure you want to continue?")) {
893 			printf("Aborted\n");
894 			slurmdb_destroy_res_cond(res_cond);
895 			slurmdb_destroy_res_rec(res);
896 			return SLURM_SUCCESS;
897 		}
898 	}
899 
900 	if (res->count != NO_VAL && res_cond->cluster_list &&
901 			list_count(res_cond->cluster_list)) {
902 		fprintf(stderr, "Can't change \"count\" on a cluster-based "
903 			"resource. Remove cluster selection.\n");
904 		return SLURM_ERROR;
905 	} else if (res->percent_used != NO_VAL16 &&
906 			!res_cond->cluster_list) {
907 		fprintf(stderr, "Can't change \"percentallowed\" without "
908 			"specifying a cluster.\n");
909 		return SLURM_ERROR;
910 	}
911 
912 	notice_thread_init();
913 	ret_list = slurmdb_res_modify(db_conn, res_cond, res);
914 	notice_thread_fini();
915 	if (ret_list && list_count(ret_list)) {
916 		char *object = NULL;
917 		ListIterator itr = list_iterator_create(ret_list);
918 		printf(" Modified server resource ...\n");
919 		while ((object = list_next(itr))) {
920 			printf("  %s\n", object);
921 		}
922 		list_iterator_destroy(itr);
923 		set = 1;
924 	} else if (ret_list) {
925 		printf(" Nothing modified\n");
926 		rc = SLURM_ERROR;
927 	} else if (errno == ESLURM_OVER_ALLOCATE) {
928 		exit_code=1;
929 		rc = SLURM_ERROR;
930 		fprintf(stderr,
931 			" If change was accepted it would look like this...\n");
932 		_print_overcommit(res, res_cond);
933 
934 	} else {
935 		exit_code=1;
936 		fprintf(stderr, " Error with request: %s\n",
937 			slurm_strerror(errno));
938 		rc = SLURM_ERROR;
939 	}
940 
941 	if (set) {
942 		if (commit_check("Would you like to commit changes?")){
943 			slurmdb_connection_commit(db_conn, 1);
944 		} else {
945 			printf(" Changes Discarded\n");
946 			slurmdb_connection_commit(db_conn, 0);
947 		}
948 	}
949 
950 	FREE_NULL_LIST(ret_list);
951 
952 	slurmdb_destroy_res_cond(res_cond);
953 	slurmdb_destroy_res_rec(res);
954 	return rc;
955 }
956 
sacctmgr_delete_res(int argc,char ** argv)957 extern int sacctmgr_delete_res(int argc, char **argv)
958 
959 {
960 	int rc = SLURM_SUCCESS;
961 	slurmdb_res_cond_t *res_cond = xmalloc(sizeof(slurmdb_res_cond_t));
962 	int i=0;
963 	List ret_list = NULL;
964 	ListIterator itr = NULL;
965 	int set = 0;
966 	char *name = NULL;
967 
968 	slurmdb_init_res_cond(res_cond, 0);
969 
970 
971 	for (i=0; i<argc; i++) {
972 		int command_len = strlen(argv[i]);
973 		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))
974 		    || !xstrncasecmp(argv[i], "Set", MAX(command_len, 3)))
975 			i++;
976 		set += _set_res_cond(&i, argc, argv, res_cond, NULL);
977 	}
978 
979 	if (!set) {
980 		exit_code=1;
981 		fprintf(stderr,
982 			" No conditions given to remove, not executing.\n");
983 		slurmdb_destroy_res_cond(res_cond);
984 		return SLURM_ERROR;
985 	} else if (set == -1) {
986 		slurmdb_destroy_res_cond(res_cond);
987 		return SLURM_ERROR;
988 	}
989 
990 	notice_thread_init();
991 	ret_list = slurmdb_res_remove(db_conn, res_cond);
992 	notice_thread_fini();
993 	slurmdb_destroy_res_cond(res_cond);
994 
995 	if (ret_list && list_count(ret_list)) {
996 		itr = list_iterator_create(ret_list);
997 		printf(" Deleting resource(s)...\n");
998 
999 		while ((name = list_next(itr))) {
1000 			printf("  %s\n", name);
1001 		}
1002 		list_iterator_destroy(itr);
1003 		if (commit_check("Would you like to commit changes?")) {
1004 			slurmdb_connection_commit(db_conn, 1);
1005 		} else {
1006 			printf(" Changes Discarded\n");
1007 			slurmdb_connection_commit(db_conn, 0);
1008 		}
1009 	} else if (ret_list) {
1010 		printf(" Nothing deleted\n");
1011 		rc = SLURM_ERROR;
1012 	} else {
1013 		exit_code=1;
1014 		fprintf(stderr, " Error with request: %s\n",
1015 			slurm_strerror(errno));
1016 		rc = SLURM_ERROR;
1017 	}
1018 
1019 	FREE_NULL_LIST(ret_list);
1020 
1021 	xfree(name);
1022 	return rc;
1023 }
1024