PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sreport/sreport.c

https://github.com/cfenoy/slurm
C | 828 lines | 693 code | 51 blank | 84 comment | 183 complexity | 5f06251cd33affb6ad331eb5a0d31d9a MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * sreport.c - report generating tool for slurm accounting.
  3. *****************************************************************************
  4. * Copyright (C) 2008 Lawrence Livermore National Security.
  5. * Copyright (C) 2002-2007 The Regents of the University of California.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by Danny Auble <da@llnl.gov>
  8. * CODE-OCEC-09-009. All rights reserved.
  9. *
  10. * This file is part of SLURM, a resource management program.
  11. * For details, see <http://www.schedmd.com/slurmdocs/>.
  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. #include "src/sreport/sreport.h"
  40. #include "src/sreport/assoc_reports.h"
  41. #include "src/sreport/cluster_reports.h"
  42. #include "src/sreport/job_reports.h"
  43. #include "src/sreport/resv_reports.h"
  44. #include "src/sreport/user_reports.h"
  45. #include "src/common/xsignal.h"
  46. #include "src/common/proc_args.h"
  47. #define OPT_LONG_HIDE 0x102
  48. #define BUFFER_SIZE 4096
  49. char *command_name;
  50. int exit_code; /* sreport's exit code, =1 on any error at any time */
  51. int exit_flag; /* program to terminate if =1 */
  52. int input_words; /* number of words of input permitted */
  53. int quiet_flag; /* quiet=1, verbose=-1, normal=0 */
  54. int all_clusters_flag = 0;
  55. slurmdb_report_time_format_t time_format = SLURMDB_REPORT_TIME_MINS;
  56. char *time_format_string = "Minutes";
  57. void *db_conn = NULL;
  58. uint32_t my_uid = 0;
  59. slurmdb_report_sort_t sort_flag = SLURMDB_REPORT_SORT_TIME;
  60. static void _job_rep (int argc, char *argv[]);
  61. static void _user_rep (int argc, char *argv[]);
  62. static void _resv_rep (int argc, char *argv[]);
  63. static void _cluster_rep (int argc, char *argv[]);
  64. static void _assoc_rep (int argc, char *argv[]);
  65. static int _get_command (int *argc, char *argv[]);
  66. static void _print_version( void );
  67. static int _process_command (int argc, char *argv[]);
  68. static int _set_time_format(char *format);
  69. static int _set_sort(char *format);
  70. static void _usage ();
  71. int
  72. main (int argc, char *argv[])
  73. {
  74. int error_code = SLURM_SUCCESS, i, opt_char, input_field_count;
  75. char **input_fields;
  76. log_options_t opts = LOG_OPTS_STDERR_ONLY ;
  77. char *temp = NULL;
  78. int option_index;
  79. static struct option long_options[] = {
  80. {"all_clusters", 0, 0, 'a'},
  81. {"help", 0, 0, 'h'},
  82. {"immediate",0, 0, 'i'},
  83. {"noheader", 0, 0, 'n'},
  84. {"parsable", 0, 0, 'p'},
  85. {"parsable2",0, 0, 'P'},
  86. {"quiet", 0, 0, 'Q'},
  87. {"sort", 0, 0, 's'},
  88. {"usage", 0, 0, 'h'},
  89. {"verbose", 0, 0, 'v'},
  90. {"version", 0, 0, 'V'},
  91. {NULL, 0, 0, 0}
  92. };
  93. command_name = argv[0];
  94. exit_code = 0;
  95. exit_flag = 0;
  96. input_field_count = 0;
  97. quiet_flag = 0;
  98. log_init("sreport", opts, SYSLOG_FACILITY_DAEMON, NULL);
  99. /* Check to see if we are running a supported accounting plugin */
  100. temp = slurm_get_accounting_storage_type();
  101. if(strcasecmp(temp, "accounting_storage/slurmdbd")
  102. && strcasecmp(temp, "accounting_storage/mysql")) {
  103. fprintf (stderr, "You are not running a supported "
  104. "accounting_storage plugin\n(%s).\n"
  105. "Only 'accounting_storage/slurmdbd' "
  106. "and 'accounting_storage/mysql' are supported.\n",
  107. temp);
  108. xfree(temp);
  109. exit(1);
  110. }
  111. xfree(temp);
  112. while((opt_char = getopt_long(argc, argv, "ahnpPQs:t:vV",
  113. long_options, &option_index)) != -1) {
  114. switch (opt_char) {
  115. case (int)'?':
  116. fprintf(stderr, "Try \"sreport --help\" "
  117. "for more information\n");
  118. exit(1);
  119. break;
  120. case (int)'h':
  121. _usage ();
  122. exit(exit_code);
  123. break;
  124. case (int)'a':
  125. all_clusters_flag = 1;
  126. break;
  127. case (int)'n':
  128. print_fields_have_header = 0;
  129. break;
  130. case (int)'p':
  131. print_fields_parsable_print =
  132. PRINT_FIELDS_PARSABLE_ENDING;
  133. break;
  134. case (int)'P':
  135. print_fields_parsable_print =
  136. PRINT_FIELDS_PARSABLE_NO_ENDING;
  137. break;
  138. case (int)'Q':
  139. quiet_flag = 1;
  140. break;
  141. case (int)'s':
  142. _set_sort(optarg);
  143. break;
  144. case (int)'t':
  145. _set_time_format(optarg);
  146. break;
  147. case (int)'v':
  148. quiet_flag = -1;
  149. break;
  150. case (int)'V':
  151. _print_version();
  152. exit(exit_code);
  153. break;
  154. default:
  155. exit_code = 1;
  156. fprintf(stderr, "getopt error, returned %c\n",
  157. opt_char);
  158. exit(exit_code);
  159. }
  160. }
  161. if (argc > MAX_INPUT_FIELDS) /* bogus input, but continue anyway */
  162. input_words = argc;
  163. else
  164. input_words = 128;
  165. input_fields = (char **) xmalloc (sizeof (char *) * input_words);
  166. if (optind < argc) {
  167. for (i = optind; i < argc; i++) {
  168. input_fields[input_field_count++] = argv[i];
  169. }
  170. }
  171. db_conn = slurmdb_connection_get();
  172. if(errno) {
  173. error("Problem talking to the database: %m");
  174. exit(1);
  175. }
  176. my_uid = getuid();
  177. if (input_field_count)
  178. exit_flag = 1;
  179. else
  180. error_code = _get_command (&input_field_count, input_fields);
  181. while (error_code == SLURM_SUCCESS) {
  182. error_code = _process_command (input_field_count,
  183. input_fields);
  184. if (error_code || exit_flag)
  185. break;
  186. error_code = _get_command (&input_field_count, input_fields);
  187. }
  188. slurmdb_connection_close(&db_conn);
  189. slurm_acct_storage_fini();
  190. exit(exit_code);
  191. }
  192. #if !HAVE_READLINE
  193. /*
  194. * Alternative to readline if readline is not available
  195. */
  196. static char *_getline(const char *prompt)
  197. {
  198. char buf[4096];
  199. char *line;
  200. int len;
  201. printf("%s", prompt);
  202. /* we only set this here to avoid a warning. We throw it away
  203. later. */
  204. line = fgets(buf, 4096, stdin);
  205. len = strlen(buf);
  206. if ((len > 0) && (buf[len-1] == '\n'))
  207. buf[len-1] = '\0';
  208. else
  209. len++;
  210. line = malloc (len * sizeof(char));
  211. return strncpy(line, buf, len);
  212. }
  213. #endif
  214. /*
  215. * _job_rep - Reports having to do with jobs
  216. * IN argc - count of arguments
  217. * IN argv - list of arguments
  218. */
  219. static void _job_rep (int argc, char *argv[])
  220. {
  221. int error_code = SLURM_SUCCESS;
  222. int command_len = strlen(argv[0]);
  223. /* For backwards compatibility we just look at the 1st char
  224. * by default since Sizes was the original name */
  225. if (!strncasecmp (argv[0], "SizesByAccount", MAX(command_len, 1))) {
  226. error_code = job_sizes_grouped_by_top_acct(
  227. (argc - 1), &argv[1]);
  228. } else if (!strncasecmp (argv[0],
  229. "SizesByWcKey", MAX(command_len, 8))) {
  230. error_code = job_sizes_grouped_by_wckey(
  231. (argc - 1), &argv[1]);
  232. } else if (!strncasecmp (argv[0],
  233. "SizesByAccountAndWcKey",
  234. MAX(command_len, 15))) {
  235. error_code = job_sizes_grouped_by_top_acct_and_wckey(
  236. (argc - 1), &argv[1]);
  237. } else {
  238. exit_code = 1;
  239. fprintf(stderr, "Not valid report %s\n", argv[0]);
  240. fprintf(stderr, "Valid job reports are, ");
  241. fprintf(stderr, "\"SizesByAccount, SizesByAccountAndWcKey, ");
  242. fprintf(stderr, "and SizesByWckey\"\n");
  243. }
  244. if (error_code) {
  245. exit_code = 1;
  246. }
  247. }
  248. /*
  249. * _user_rep - Reports having to do with users
  250. * IN argc - count of arguments
  251. * IN argv - list of arguments
  252. */
  253. static void _user_rep (int argc, char *argv[])
  254. {
  255. int error_code = SLURM_SUCCESS;
  256. if (strncasecmp (argv[0], "Top", 1) == 0) {
  257. error_code = user_top((argc - 1), &argv[1]);
  258. } else {
  259. exit_code = 1;
  260. fprintf(stderr, "Not valid report %s\n", argv[0]);
  261. fprintf(stderr, "Valid user reports are, ");
  262. fprintf(stderr, "\"Top\"\n");
  263. }
  264. if (error_code) {
  265. exit_code = 1;
  266. }
  267. }
  268. /*
  269. * _resv_rep - Reports having to do with reservations
  270. * IN argc - count of arguments
  271. * IN argv - list of arguments
  272. */
  273. static void _resv_rep (int argc, char *argv[])
  274. {
  275. int error_code = SLURM_SUCCESS;
  276. if (strncasecmp (argv[0], "Utilization", 1) == 0) {
  277. error_code = resv_utilization((argc - 1), &argv[1]);
  278. } else {
  279. exit_code = 1;
  280. fprintf(stderr, "Not valid report %s\n", argv[0]);
  281. fprintf(stderr, "Valid reservation reports are, ");
  282. fprintf(stderr, "\"Utilization\"\n");
  283. }
  284. if (error_code) {
  285. exit_code = 1;
  286. }
  287. }
  288. /*
  289. * _cluster_rep - Reports having to do with clusters
  290. * IN argc - count of arguments
  291. * IN argv - list of arguments
  292. */
  293. static void _cluster_rep (int argc, char *argv[])
  294. {
  295. int error_code = SLURM_SUCCESS;
  296. if (strncasecmp (argv[0], "AccountUtilizationByUser", 1) == 0) {
  297. error_code = cluster_account_by_user((argc - 1), &argv[1]);
  298. } else if ((strncasecmp (argv[0], "UserUtilizationByAccount", 18) == 0)
  299. || (strncasecmp (argv[0], "UA", 2) == 0)) {
  300. error_code = cluster_user_by_account((argc - 1), &argv[1]);
  301. } else if ((strncasecmp (argv[0], "UserUtilizationByWckey", 18) == 0)
  302. || (strncasecmp (argv[0], "UW", 2) == 0)) {
  303. error_code = cluster_user_by_wckey((argc - 1), &argv[1]);
  304. } else if (strncasecmp (argv[0], "Utilization", 2) == 0) {
  305. error_code = cluster_utilization((argc - 1), &argv[1]);
  306. } else if (strncasecmp (argv[0], "WCKeyUtilizationByUser", 1) == 0) {
  307. error_code = cluster_wckey_by_user((argc - 1), &argv[1]);
  308. } else {
  309. exit_code = 1;
  310. fprintf(stderr, "Not valid report %s\n", argv[0]);
  311. fprintf(stderr, "Valid cluster reports are, ");
  312. fprintf(stderr, "\"AccountUtilizationByUser\", "
  313. "\"UserUtilizationByAccount\", "
  314. "\"UserUtilizationByWckey\", \"Utilization\", "
  315. "and \"WCKeyUtilizationByUser\"\n");
  316. }
  317. if (error_code) {
  318. exit_code = 1;
  319. }
  320. }
  321. /*
  322. * _assoc_rep - Reports having to do with jobs
  323. * IN argc - count of arguments
  324. * IN argv - list of arguments
  325. */
  326. static void _assoc_rep (int argc, char *argv[])
  327. {
  328. int error_code = SLURM_SUCCESS;
  329. if (error_code) {
  330. exit_code = 1;
  331. }
  332. }
  333. /*
  334. * _get_command - get a command from the user
  335. * OUT argc - location to store count of arguments
  336. * OUT argv - location to store the argument list
  337. */
  338. static int
  339. _get_command (int *argc, char **argv)
  340. {
  341. char *in_line;
  342. static char *last_in_line = NULL;
  343. int i, in_line_size;
  344. static int last_in_line_size = 0;
  345. *argc = 0;
  346. #if HAVE_READLINE
  347. in_line = readline ("sreport: ");
  348. #else
  349. in_line = _getline("sreport: ");
  350. #endif
  351. if (in_line == NULL)
  352. return 0;
  353. else if (strncmp (in_line, "#", 1) == 0) {
  354. free (in_line);
  355. return 0;
  356. } else if (strcmp (in_line, "!!") == 0) {
  357. free (in_line);
  358. in_line = last_in_line;
  359. in_line_size = last_in_line_size;
  360. } else {
  361. if (last_in_line)
  362. free (last_in_line);
  363. last_in_line = in_line;
  364. last_in_line_size = in_line_size = strlen (in_line);
  365. }
  366. #if HAVE_READLINE
  367. add_history(in_line);
  368. #endif
  369. /* break in_line into tokens */
  370. for (i = 0; i < in_line_size; i++) {
  371. bool double_quote = false, single_quote = false;
  372. if (in_line[i] == '\0')
  373. break;
  374. if (isspace ((int) in_line[i]))
  375. continue;
  376. if (((*argc) + 1) > MAX_INPUT_FIELDS) { /* bogus input line */
  377. exit_code = 1;
  378. fprintf (stderr,
  379. "%s: can not process over %d words\n",
  380. command_name, input_words);
  381. return E2BIG;
  382. }
  383. argv[(*argc)++] = &in_line[i];
  384. for (i++; i < in_line_size; i++) {
  385. if (in_line[i] == '\042') {
  386. double_quote = !double_quote;
  387. continue;
  388. }
  389. if (in_line[i] == '\047') {
  390. single_quote = !single_quote;
  391. continue;
  392. }
  393. if (in_line[i] == '\0')
  394. break;
  395. if (double_quote || single_quote)
  396. continue;
  397. if (isspace ((int) in_line[i])) {
  398. in_line[i] = '\0';
  399. break;
  400. }
  401. }
  402. }
  403. return 0;
  404. }
  405. static void _print_version(void)
  406. {
  407. print_slurm_version ();
  408. if (quiet_flag == -1) {
  409. long version = slurm_api_version();
  410. printf("slurm_api_version: %ld, %ld.%ld.%ld\n", version,
  411. SLURM_VERSION_MAJOR(version),
  412. SLURM_VERSION_MINOR(version),
  413. SLURM_VERSION_MICRO(version));
  414. }
  415. }
  416. /*
  417. * _process_command - process the user's command
  418. * IN argc - count of arguments
  419. * IN argv - the arguments
  420. * RET 0 or errno (only for errors fatal to sreport)
  421. */
  422. static int
  423. _process_command (int argc, char *argv[])
  424. {
  425. int command_len = 0;
  426. if (argc < 1) {
  427. exit_code = 1;
  428. if (quiet_flag == -1)
  429. fprintf(stderr, "no input");
  430. return 0;
  431. }
  432. command_len = strlen(argv[0]);
  433. if ((strncasecmp (argv[0], "association", MAX(command_len, 1)) == 0)) {
  434. if (argc < 2) {
  435. exit_code = 1;
  436. if (quiet_flag != 1)
  437. fprintf(stderr,
  438. "too few arguments for keyword:%s\n",
  439. argv[0]);
  440. } else
  441. _assoc_rep((argc - 1), &argv[1]);
  442. } else if ((strncasecmp (argv[0], "cluster",
  443. MAX(command_len, 2)) == 0)) {
  444. if (argc < 2) {
  445. exit_code = 1;
  446. if (quiet_flag != 1)
  447. fprintf(stderr,
  448. "too few arguments for keyword:%s\n",
  449. argv[0]);
  450. } else
  451. _cluster_rep((argc - 1), &argv[1]);
  452. } else if (strncasecmp (argv[0], "help", MAX(command_len, 2)) == 0) {
  453. if (argc > 1) {
  454. exit_code = 1;
  455. fprintf (stderr,
  456. "too many arguments for keyword:%s\n",
  457. argv[0]);
  458. }
  459. _usage ();
  460. } else if ((strncasecmp (argv[0], "job", MAX(command_len, 1)) == 0)) {
  461. if (argc < 2) {
  462. exit_code = 1;
  463. if (quiet_flag != 1)
  464. fprintf(stderr,
  465. "too few arguments for keyword:%s\n",
  466. argv[0]);
  467. } else
  468. _job_rep((argc - 1), &argv[1]);
  469. } else if (strncasecmp (argv[0], "quiet", MAX(command_len, 4)) == 0) {
  470. if (argc > 1) {
  471. exit_code = 1;
  472. fprintf (stderr, "too many arguments for keyword:%s\n",
  473. argv[0]);
  474. }
  475. quiet_flag = 1;
  476. } else if ((strncasecmp (argv[0], "exit", MAX(command_len, 1)) == 0) ||
  477. (strncasecmp (argv[0], "\\q", MAX(command_len, 2)) == 0) ||
  478. (strncasecmp (argv[0], "quit", MAX(command_len, 4)) == 0)) {
  479. if (argc > 1) {
  480. exit_code = 1;
  481. fprintf (stderr,
  482. "too many arguments for keyword:%s\n",
  483. argv[0]);
  484. }
  485. exit_flag = 1;
  486. } else if (strncasecmp (argv[0], "nonparsable",
  487. MAX(command_len, 4)) == 0) {
  488. if (argc > 1) {
  489. exit_code = 1;
  490. fprintf (stderr, "too many arguments for keyword:%s\n",
  491. argv[0]);
  492. }
  493. print_fields_parsable_print = 0;
  494. } else if (strncasecmp (argv[0], "parsable",
  495. MAX(command_len, 8)) == 0) {
  496. if (argc > 1) {
  497. exit_code = 1;
  498. fprintf (stderr, "too many arguments for keyword:%s\n",
  499. argv[0]);
  500. }
  501. print_fields_parsable_print = PRINT_FIELDS_PARSABLE_ENDING;
  502. } else if (strncasecmp (argv[0], "parsable2",
  503. MAX(command_len, 9)) == 0) {
  504. if (argc > 1) {
  505. exit_code = 1;
  506. fprintf (stderr, "too many arguments for keyword:%s\n",
  507. argv[0]);
  508. }
  509. print_fields_parsable_print = PRINT_FIELDS_PARSABLE_NO_ENDING;
  510. } else if ((strncasecmp (argv[0], "reservation",
  511. MAX(command_len, 2)) == 0)
  512. || (strncasecmp (argv[0], "resv",
  513. MAX(command_len, 2)) == 0)) {
  514. if (argc < 2) {
  515. exit_code = 1;
  516. if (quiet_flag != 1)
  517. fprintf(stderr,
  518. "too few arguments for keyword:%s\n",
  519. argv[0]);
  520. } else
  521. _resv_rep((argc - 1), &argv[1]);
  522. } else if (strncasecmp (argv[0], "sort", MAX(command_len, 1)) == 0) {
  523. if (argc < 2) {
  524. exit_code = 1;
  525. fprintf (stderr,
  526. "too few arguments for keyword:%s\n",
  527. argv[0]);
  528. } else
  529. _set_sort(argv[1]);
  530. } else if (strncasecmp (argv[0], "time", MAX(command_len, 1)) == 0) {
  531. if (argc < 2) {
  532. exit_code = 1;
  533. fprintf (stderr,
  534. "too few arguments for keyword:%s\n",
  535. argv[0]);
  536. } else
  537. _set_time_format(argv[1]);
  538. } else if (strncasecmp (argv[0], "verbose", MAX(command_len, 4)) == 0) {
  539. if (argc > 1) {
  540. exit_code = 1;
  541. fprintf (stderr,
  542. "too many arguments for %s keyword\n",
  543. argv[0]);
  544. }
  545. quiet_flag = -1;
  546. } else if (strncasecmp (argv[0], "version", MAX(command_len, 4)) == 0) {
  547. if (argc > 1) {
  548. exit_code = 1;
  549. fprintf (stderr,
  550. "too many arguments for %s keyword\n",
  551. argv[0]);
  552. }
  553. _print_version();
  554. } else if ((strncasecmp (argv[0], "user", MAX(command_len, 1)) == 0)) {
  555. if (argc < 2) {
  556. exit_code = 1;
  557. if (quiet_flag != 1)
  558. fprintf(stderr,
  559. "too few arguments for keyword:%s\n",
  560. argv[0]);
  561. } else
  562. _user_rep((argc - 1), &argv[1]);
  563. } else {
  564. exit_code = 1;
  565. fprintf (stderr, "invalid keyword: %s\n", argv[0]);
  566. }
  567. return 0;
  568. }
  569. static int _set_time_format(char *format)
  570. {
  571. int command_len = strlen(format);
  572. if (strncasecmp (format, "SecPer", MAX(command_len, 6)) == 0) {
  573. time_format = SLURMDB_REPORT_TIME_SECS_PER;
  574. time_format_string = "Seconds/Percentage of Total";
  575. } else if (strncasecmp (format, "MinPer", MAX(command_len, 6)) == 0) {
  576. time_format = SLURMDB_REPORT_TIME_MINS_PER;
  577. time_format_string = "Minutes/Percentage of Total";
  578. } else if (strncasecmp (format, "HourPer", MAX(command_len, 6)) == 0) {
  579. time_format = SLURMDB_REPORT_TIME_HOURS_PER;
  580. time_format_string = "Hours/Percentage of Total";
  581. } else if (strncasecmp (format, "Seconds", MAX(command_len, 1)) == 0) {
  582. time_format = SLURMDB_REPORT_TIME_SECS;
  583. time_format_string = "Seconds";
  584. } else if (strncasecmp (format, "Minutes", MAX(command_len, 1)) == 0) {
  585. time_format = SLURMDB_REPORT_TIME_MINS;
  586. time_format_string = "Minutes";
  587. } else if (strncasecmp (format, "Hours", MAX(command_len, 1)) == 0) {
  588. time_format = SLURMDB_REPORT_TIME_HOURS;
  589. time_format_string = "Hours";
  590. } else if (strncasecmp (format, "Percent", MAX(command_len, 1)) == 0) {
  591. time_format = SLURMDB_REPORT_TIME_PERCENT;
  592. time_format_string = "Percentage of Total";
  593. } else {
  594. fprintf (stderr, "unknown time format %s", format);
  595. return SLURM_ERROR;
  596. }
  597. return SLURM_SUCCESS;
  598. }
  599. static int _set_sort(char *format)
  600. {
  601. int command_len = strlen(format);
  602. if (strncasecmp (format, "Name", MAX(command_len, 1)) == 0) {
  603. sort_flag = SLURMDB_REPORT_SORT_NAME;
  604. } else if (strncasecmp (format, "Time", MAX(command_len, 6)) == 0) {
  605. sort_flag = SLURMDB_REPORT_SORT_TIME;
  606. } else {
  607. fprintf (stderr, "unknown timesort format %s", format);
  608. return SLURM_ERROR;
  609. }
  610. return SLURM_SUCCESS;
  611. }
  612. /* _usage - show the valid sreport commands */
  613. void _usage () {
  614. printf ("\
  615. sreport [<OPTION>] [<COMMAND>] \n\
  616. Valid <OPTION> values are: \n\
  617. -a or --all_clusters: Use all clusters instead of current \n\
  618. -h or --help: equivalent to \"help\" command \n\
  619. -n or --noheader: equivalent to \"noheader\" command \n\
  620. -p or --parsable: output will be '|' delimited with a '|' at the end \n\
  621. -P or --parsable2: output will be '|' delimited without a '|' at the end\n\
  622. -Q or --quiet: equivalent to \"quiet\" command \n\
  623. -t <time_format>: Second, Minute, Hour, Percent, SecPer, MinPer, HourPer\n\
  624. -v or --verbose: equivalent to \"verbose\" command \n\
  625. -V or --version: equivalent to \"version\" command \n\
  626. \n\
  627. <keyword> may be omitted from the execute line and sreport will execute \n\
  628. in interactive mode. It will process commands as entered until explicitly\n\
  629. terminated. \n\
  630. \n\
  631. Valid <COMMAND> values are: \n\
  632. exit Terminate sreport \n\
  633. help Print this description of use. \n\
  634. nonparsable Return output to normal \n\
  635. parsable Output will be | delimited with an ending '|' \n\
  636. parsable2 Output will be | delimited without an ending '|' \n\
  637. quiet Print no messages other than error messages. \n\
  638. quit Terminate this command. \n\
  639. time <time_format> Second, Minute, Hour, Percent, SecPer, MinPer, HourPer\n\
  640. verbose Enable detailed logging. \n\
  641. version Display tool version number. \n\
  642. !! Repeat the last command entered. \n\
  643. \n\
  644. Valid report types are: \n\
  645. cluster <REPORT> <OPTIONS> \n\
  646. job <REPORT> <OPTIONS> \n\
  647. user <REPORT> <OPTIONS> \n\
  648. \n\
  649. <REPORT> is different for each report type. \n\
  650. cluster - AccountUtilizationByUser, UserUtilizationByAccount, \n\
  651. UserUtilizationByWckey, Utilization, WCKeyUtilizationByUser \n\
  652. job - SizesByAccount, SizesByAccountAndWckey, SizesByWckey \n\
  653. reservation \n\
  654. - Utilization \n\
  655. user - TopUsage \n\
  656. \n\
  657. <OPTIONS> are different for each report type. \n\
  658. \n\
  659. COMMON FOR ALL TYPES \n\
  660. - All_Clusters - Use all monitored clusters default is \n\
  661. local cluster. \n\
  662. - Clusters=<OPT> - List of clusters to include in report \n\
  663. Default is local cluster. \n\
  664. - End=<OPT> - Period ending for report. \n\
  665. Default is 23:59:59 of previous day. \n\
  666. - Format=<OPT> - Comma separated list of fields to display\n\
  667. in report. \n\
  668. - Start=<OPT> - Period start for report. \n\
  669. Default is 00:00:00 of previous day. \n\
  670. \n\
  671. cluster - Accounts=<OPT> - When used with the UserUtilizationByAccount,\n\
  672. or AccountUtilizationByUser, List of accounts\n\
  673. to include in report. Default is all. \n\
  674. - Tree - When used with the AccountUtilizationByUser\n\
  675. report will span the accounts as they \n\
  676. in the hierarchy. \n\
  677. - Users=<OPT> - When used with any report other than \n\
  678. Utilization, List of users to include in \n\
  679. report. Default is all. \n\
  680. - Wckeys=<OPT> - When used with the UserUtilizationByWckey\n\
  681. or WCKeyUtilizationByUser, List of wckeys\n\
  682. to include in report. Default is all. \n\
  683. \n\
  684. job - Accounts=<OPT> - List of accounts to use for the report \n\
  685. Default is all. The SizesbyAccount(*) \n\
  686. report only displays 1 hierarchical level.\n\
  687. If accounts are specified the next layer \n\
  688. of accounts under those specified will be\n\
  689. displayed, not the accounts specified. \n\
  690. In the SizesByAccount(*) reports the \n\
  691. default for accounts is root. This \n\
  692. explanation does not apply when ran with \n\
  693. the FlatView option. \n\
  694. - FlatView - When used with the SizesbyAccount(*) \n\
  695. will not group accounts in a \n\
  696. hierarchical level, but print each \n\
  697. account where jobs ran on a separate \n\
  698. line without any hierarchy. \n\
  699. - GID=<OPT> - List of group ids to include in report. \n\
  700. Default is all. \n\
  701. - Grouping=<OPT> - Comma separated list of size groupings. \n\
  702. (i.e. 50,100,150 would group job cpu count\n\
  703. 1-49, 50-99, 100-149, > 150). \n\
  704. grouping=individual will result in a \n\
  705. single column for each job size found. \n\
  706. - Jobs=<OPT> - List of jobs/steps to include in report. \n\
  707. Default is all. \n\
  708. - Nodes=<OPT> - Only show jobs that ran on these nodes. \n\
  709. Default is all. \n\
  710. - Partitions=<OPT> - List of partitions jobs ran on to include\n\
  711. in report. Default is all. \n\
  712. - PrintJobCount - When used with the any Sizes report \n\
  713. will print number of jobs ran instead of \n\
  714. time used. \n\
  715. - Users=<OPT> - List of users jobs to include in report. \n\
  716. Default is all. \n\
  717. - Wckeys=<OPT> - List of wckeys to use for the report. \n\
  718. Default is all. The SizesbyWckey \n\
  719. report all users summed together. If \n\
  720. you want only certain users specify them \n\
  721. them with the Users= option. \n\
  722. \n\
  723. reservation \n\
  724. - Names=<OPT> - List of reservations to use for the report\n\
  725. Default is all. \n\
  726. - Nodes=<OPT> - Only show reservations that used these \n\
  727. nodes. Default is all. \n\
  728. \n\
  729. user - Accounts=<OPT> - List of accounts to use for the report \n\
  730. Default is all. \n\
  731. - Group - Group all accounts together for each user.\n\
  732. Default is a separate entry for each user\n\
  733. and account reference. \n\
  734. - TopCount=<OPT> - Used in the TopUsage report. Change the \n\
  735. number of users displayed. Default is 10.\n\
  736. - Users=<OPT> - List of users jobs to include in report. \n\
  737. Default is all. \n\
  738. \n\
  739. Below are the format options for each report. \n\
  740. \n\
  741. One can get an number of characters by following the field option with \n\
  742. a %%NUMBER option. i.e. format=name%%30 will print 30 chars of field name.\n\
  743. \n\
  744. Cluster \n\
  745. - AccountUtilizationByUser \n\
  746. - UserUtilizationByAccount \n\
  747. - Accounts, Cluster, CPUCount, Login, Proper, Used \n\
  748. - UserUtilizationByWckey \n\
  749. - WCKeyUtilizationByUser \n\
  750. - Cluster, CPUCount, Login, Proper, Used, Wckey \n\
  751. - Utilization \n\
  752. - Allocated, Cluster, CPUCount, Down, Idle, Overcommited, \n\
  753. PlannedDown, Reported, Reserved \n\
  754. \n\
  755. Job \n\
  756. - Sizes \n\
  757. - Account, Cluster \n\
  758. \n\
  759. Reservation \n\
  760. - Utilization \n\
  761. - Allocated, Associations, Cluster, CPUCount, CPUTime, \n\
  762. End, Idle, Name, Nodes, Start, TotalTime \n\
  763. \n\
  764. User \n\
  765. - TopUsage \n\
  766. - Account, Cluster, Login, Proper, Used \n\
  767. \n\
  768. \n\
  769. Note, valid start/end time formats are... \n\
  770. HH:MM[:SS] [AM|PM] \n\
  771. MMDD[YY] or MM/DD[/YY] or MM.DD[.YY] \n\
  772. MM/DD[/YY]-HH:MM[:SS] \n\
  773. YYYY-MM-DD[THH:MM[:SS]] \n\
  774. \n\
  775. \n\
  776. All commands and options are case-insensitive. \n\n");
  777. }