PageRenderTime 47ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/squeue/opts.c

https://github.com/cfenoy/slurm
C | 1192 lines | 1003 code | 83 blank | 106 comment | 292 complexity | 798fbb3aeb5762fa39782b0785a5ea25 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /****************************************************************************\
  2. * opts.c - squeue command line option parsing
  3. *****************************************************************************
  4. * Copyright (C) 2002-2007 The Regents of the University of California.
  5. * Copyright (C) 2008-2010 Lawrence Livermore National Security.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by Joey Ekstrom <ekstrom1@llnl.gov>, Morris Jette <jette1@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. #ifndef _GNU_SOURCE
  40. # define _GNU_SOURCE
  41. #endif
  42. #ifdef HAVE_CONFIG_H
  43. # include "config.h"
  44. #endif
  45. #if HAVE_GETOPT_H
  46. # include <getopt.h>
  47. #else
  48. # include "src/common/getopt.h"
  49. #endif
  50. #include <pwd.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <sys/types.h>
  54. #include <unistd.h>
  55. #include "src/common/read_config.h"
  56. #include "src/common/xstring.h"
  57. #include "src/common/proc_args.h"
  58. #include "src/common/uid.h"
  59. #include "src/squeue/squeue.h"
  60. /* getopt_long options, integers but not characters */
  61. #define OPT_LONG_HELP 0x100
  62. #define OPT_LONG_USAGE 0x101
  63. #define OPT_LONG_HIDE 0x102
  64. #define OPT_LONG_START 0x103
  65. /* FUNCTIONS */
  66. static List _build_job_list( char* str );
  67. static List _build_str_list( char* str );
  68. static List _build_state_list( char* str );
  69. static List _build_all_states_list( void );
  70. static List _build_step_list( char* str );
  71. static List _build_user_list( char* str );
  72. static char *_get_prefix(char *token);
  73. static void _help( void );
  74. static int _max_cpus_per_node(void);
  75. static int _parse_state( char* str, uint16_t* states );
  76. static void _parse_token( char *token, char *field, int *field_size,
  77. bool *right_justify, char **suffix);
  78. static void _print_options( void );
  79. static void _usage( void );
  80. /*
  81. * parse_command_line
  82. */
  83. extern void
  84. parse_command_line( int argc, char* argv[] )
  85. {
  86. char *env_val = NULL;
  87. bool override_format_env = false;
  88. int opt_char;
  89. int option_index;
  90. static struct option long_options[] = {
  91. {"accounts", required_argument, 0, 'A'},
  92. {"all", no_argument, 0, 'a'},
  93. {"format", required_argument, 0, 'o'},
  94. {"help", no_argument, 0, OPT_LONG_HELP},
  95. {"hide", no_argument, 0, OPT_LONG_HIDE},
  96. {"iterate", required_argument, 0, 'i'},
  97. {"jobs", optional_argument, 0, 'j'},
  98. {"long", no_argument, 0, 'l'},
  99. {"cluster", required_argument, 0, 'M'},
  100. {"clusters", required_argument, 0, 'M'},
  101. {"name", required_argument, 0, 'n'},
  102. {"node", required_argument, 0, 'w'},
  103. {"nodes", required_argument, 0, 'w'},
  104. {"nodelist", required_argument, 0, 'w'},
  105. {"noheader", no_argument, 0, 'h'},
  106. {"partitions", required_argument, 0, 'p'},
  107. {"qos", required_argument, 0, 'q'},
  108. {"reservation",required_argument, 0, 'R'},
  109. {"sort", required_argument, 0, 'S'},
  110. {"start", no_argument, 0, OPT_LONG_START},
  111. {"steps", optional_argument, 0, 's'},
  112. {"states", required_argument, 0, 't'},
  113. {"usage", no_argument, 0, OPT_LONG_USAGE},
  114. {"user", required_argument, 0, 'u'},
  115. {"users", required_argument, 0, 'u'},
  116. {"verbose", no_argument, 0, 'v'},
  117. {"version", no_argument, 0, 'V'},
  118. {NULL, 0, 0, 0}
  119. };
  120. if (getenv("SQUEUE_ALL"))
  121. params.all_flag = true;
  122. if ( ( env_val = getenv("SQUEUE_SORT") ) )
  123. params.sort = xstrdup(env_val);
  124. if ( ( env_val = getenv("SLURM_CLUSTERS") ) ) {
  125. if (!(params.clusters = slurmdb_get_info_cluster(env_val))) {
  126. error("'%s' can't be reached now, "
  127. "or it is an invalid entry for "
  128. "SLURM_CLUSTERS. Use 'sacctmgr --list "
  129. "cluster' to see available clusters.",
  130. env_val);
  131. exit(1);
  132. }
  133. working_cluster_rec = list_peek(params.clusters);
  134. }
  135. while ((opt_char = getopt_long(argc, argv,
  136. "A:ahi:j::ln:M:o:p:q:R:s::S:t:u:U:vVw:",
  137. long_options, &option_index)) != -1) {
  138. switch (opt_char) {
  139. case (int)'?':
  140. fprintf(stderr, "Try \"squeue --help\" "
  141. "for more information\n");
  142. exit(1);
  143. case (int) 'A':
  144. case (int) 'U': /* backwards compatibility */
  145. xfree(params.accounts);
  146. params.accounts = xstrdup(optarg);
  147. params.account_list =
  148. _build_str_list( params.accounts );
  149. break;
  150. case (int)'a':
  151. params.all_flag = true;
  152. break;
  153. case (int)'h':
  154. params.no_header = true;
  155. break;
  156. case (int) 'i':
  157. params.iterate= atoi(optarg);
  158. if (params.iterate <= 0) {
  159. error ("--iterate=%s\n", optarg);
  160. exit(1);
  161. }
  162. break;
  163. case (int) 'j':
  164. if (optarg) {
  165. params.jobs = xstrdup(optarg);
  166. params.job_list =
  167. _build_job_list(params.jobs);
  168. }
  169. params.job_flag = true;
  170. break;
  171. case (int) 'l':
  172. params.long_list = true;
  173. override_format_env = true;
  174. break;
  175. case (int) 'M':
  176. if (params.clusters)
  177. list_destroy(params.clusters);
  178. if (!(params.clusters =
  179. slurmdb_get_info_cluster(optarg))) {
  180. error("'%s' can't be reached now, "
  181. "or it is an invalid entry for "
  182. "--cluster. Use 'sacctmgr --list "
  183. "cluster' to see available clusters.",
  184. optarg);
  185. exit(1);
  186. }
  187. working_cluster_rec = list_peek(params.clusters);
  188. break;
  189. case (int) 'n':
  190. xfree(params.names);
  191. params.names = xstrdup(optarg);
  192. params.name_list = _build_str_list( params.names );
  193. break;
  194. case (int) 'o':
  195. xfree(params.format);
  196. params.format = xstrdup(optarg);
  197. override_format_env = true;
  198. break;
  199. case (int) 'p':
  200. xfree(params.partitions);
  201. params.partitions = xstrdup(optarg);
  202. params.part_list =
  203. _build_str_list( params.partitions );
  204. params.all_flag = true;
  205. break;
  206. case (int) 'q':
  207. xfree(params.qoss);
  208. params.qoss = xstrdup(optarg);
  209. params.qos_list =
  210. _build_str_list( params.qoss );
  211. break;
  212. case (int) 'R':
  213. xfree(params.reservation);
  214. params.reservation = xstrdup(optarg);
  215. break;
  216. case (int) 's':
  217. if (optarg) {
  218. params.steps = xstrdup(optarg);
  219. params.step_list =
  220. _build_step_list(params.steps);
  221. }
  222. params.step_flag = true;
  223. override_format_env = true;
  224. break;
  225. case (int) 'S':
  226. xfree(params.sort);
  227. params.sort = xstrdup(optarg);
  228. break;
  229. case (int) 't':
  230. xfree(params.states);
  231. params.states = xstrdup(optarg);
  232. params.state_list =
  233. _build_state_list( params.states );
  234. break;
  235. case (int) 'u':
  236. xfree(params.users);
  237. params.users = xstrdup(optarg);
  238. params.user_list =
  239. _build_user_list( params.users );
  240. break;
  241. case (int) 'v':
  242. params.verbose++;
  243. break;
  244. case (int) 'V':
  245. print_slurm_version();
  246. exit(0);
  247. case (int) 'w':
  248. if (params.nodes)
  249. hostset_destroy(params.nodes);
  250. params.nodes = hostset_create(optarg);
  251. if (params.nodes == NULL) {
  252. error("'%s' invalid entry for --nodelist",
  253. optarg);
  254. exit(1);
  255. }
  256. break;
  257. case OPT_LONG_HELP:
  258. _help();
  259. exit(0);
  260. case OPT_LONG_HIDE:
  261. params.all_flag = false;
  262. break;
  263. case OPT_LONG_START:
  264. params.start_flag = true;
  265. break;
  266. case OPT_LONG_USAGE:
  267. _usage();
  268. exit(0);
  269. }
  270. }
  271. if ( override_format_env == false ) {
  272. if ( ( env_val = getenv("SQUEUE_FORMAT") ) )
  273. params.format = xstrdup(env_val);
  274. }
  275. params.cluster_flags = slurmdb_setup_cluster_flags();
  276. if (optind < argc) {
  277. if (params.job_flag) {
  278. params.jobs = xstrdup(argv[optind++]);
  279. params.job_list = _build_job_list(params.jobs);
  280. } else if (params.step_flag) {
  281. params.steps = xstrdup(argv[optind++]);
  282. params.step_list = _build_step_list(params.steps);
  283. }
  284. if (optind < argc) {
  285. error("Unrecognized option: %s",argv[optind]);
  286. _usage();
  287. exit(1);
  288. }
  289. }
  290. if ( params.job_flag && params.step_flag) {
  291. if (params.job_list) {
  292. verbose("Printing job steps with job filter");
  293. params.job_flag = false;
  294. } else {
  295. error("Incompatible options --jobs and --steps");
  296. exit(1);
  297. }
  298. }
  299. if ( params.nodes ) {
  300. char *name1 = NULL;
  301. char *name2 = NULL;
  302. hostset_t nodenames = hostset_create(NULL);
  303. if (nodenames == NULL)
  304. fatal("malloc failure");
  305. while ( hostset_count(params.nodes) > 0 ) {
  306. name1 = hostset_pop(params.nodes);
  307. /* localhost = use current host name */
  308. if ( strcasecmp("localhost", name1) == 0 ) {
  309. name2 = xmalloc(128);
  310. gethostname_short(name2, 128);
  311. } else {
  312. /* translate NodeHostName to NodeName */
  313. name2 = slurm_conf_get_nodename(name1);
  314. /* use NodeName if translation failed */
  315. if ( name2 == NULL )
  316. name2 = xstrdup(name1);
  317. }
  318. hostset_insert(nodenames, name2);
  319. free(name1);
  320. xfree(name2);
  321. }
  322. /* Replace params.nodename with the new one */
  323. hostset_destroy(params.nodes);
  324. params.nodes = nodenames;
  325. }
  326. if ( ( params.accounts == NULL ) &&
  327. ( env_val = getenv("SQUEUE_ACCOUNT") ) ) {
  328. params.accounts = xstrdup(env_val);
  329. params.account_list = _build_str_list( params.accounts );
  330. }
  331. if ( ( params.names == NULL ) &&
  332. ( env_val = getenv("SQUEUE_NAMES") ) ) {
  333. params.names = xstrdup(env_val);
  334. params.name_list = _build_str_list( params.names );
  335. }
  336. if ( ( params.partitions == NULL ) &&
  337. ( env_val = getenv("SQUEUE_PARTITION") ) ) {
  338. params.partitions = xstrdup(env_val);
  339. params.part_list = _build_str_list( params.partitions );
  340. params.all_flag = true;
  341. }
  342. if ( ( params.qoss == NULL ) &&
  343. ( env_val = getenv("SQUEUE_QOS") ) ) {
  344. params.qoss = xstrdup(env_val);
  345. params.qos_list = _build_str_list( params.qoss );
  346. }
  347. if ( ( params.states == NULL ) &&
  348. ( env_val = getenv("SQUEUE_STATES") ) ) {
  349. params.states = xstrdup(env_val);
  350. params.state_list = _build_state_list( params.states );
  351. }
  352. if ( ( params.users == NULL ) &&
  353. ( env_val = getenv("SQUEUE_USERS") ) ) {
  354. params.users = xstrdup(env_val);
  355. params.user_list = _build_user_list( params.users );
  356. }
  357. if ( params.start_flag && !params.step_flag ) {
  358. /* Set more defaults */
  359. if (params.format == NULL)
  360. params.format = xstrdup("%.7i %.9P %.8j %.8u %.2t %.19S %.6D %R");
  361. if (params.sort == NULL)
  362. params.sort = xstrdup("S");
  363. if (params.states == NULL) {
  364. params.states = xstrdup("PD");
  365. params.state_list = _build_state_list( params.states );
  366. }
  367. }
  368. params.max_cpus = _max_cpus_per_node();
  369. if ( params.verbose )
  370. _print_options();
  371. }
  372. /* Return the maximum number of processors for any node in the cluster */
  373. static int _max_cpus_per_node(void)
  374. {
  375. int error_code, max_cpus = 1;
  376. node_info_msg_t *node_info_ptr = NULL;
  377. error_code = slurm_load_node ((time_t) NULL, &node_info_ptr,
  378. params.all_flag);
  379. if (error_code == SLURM_SUCCESS) {
  380. int i;
  381. node_info_t *node_ptr = node_info_ptr->node_array;
  382. for (i=0; i<node_info_ptr->record_count; i++) {
  383. max_cpus = MAX(max_cpus, node_ptr[i].cpus);
  384. }
  385. slurm_free_node_info_msg (node_info_ptr);
  386. }
  387. return max_cpus;
  388. }
  389. /*
  390. * _parse_state - convert job state name string to numeric value
  391. * IN str - state name
  392. * OUT states - enum job_states value corresponding to str
  393. * RET 0 or error code
  394. */
  395. static int
  396. _parse_state( char* str, uint16_t* states )
  397. {
  398. int i;
  399. char *state_names;
  400. if ((i = job_state_num(str)) >= 0) {
  401. *states = (uint16_t) i;
  402. return SLURM_SUCCESS;
  403. }
  404. error ("Invalid job state specified: %s", str);
  405. state_names = xstrdup(job_state_string(0));
  406. for (i=1; i<JOB_END; i++) {
  407. xstrcat(state_names, ",");
  408. xstrcat(state_names, job_state_string(i));
  409. }
  410. xstrcat(state_names, ",");
  411. xstrcat(state_names, job_state_string(JOB_COMPLETING));
  412. xstrcat(state_names, ",");
  413. xstrcat(state_names, job_state_string(JOB_CONFIGURING));
  414. error ("Valid job states include: %s\n", state_names);
  415. xfree (state_names);
  416. return SLURM_ERROR;
  417. }
  418. /*
  419. * parse_format - Take the user's format specification and use it to build
  420. * build the format specifications (internalize it to print.c data
  421. * structures)
  422. * IN format - user's format specification
  423. * RET zero or error code
  424. */
  425. extern int parse_format( char* format )
  426. {
  427. int field_size;
  428. bool right_justify;
  429. char *prefix = NULL, *suffix = NULL, *token = NULL;
  430. char *tmp_char = NULL, *tmp_format = NULL;
  431. char field[1];
  432. if (format == NULL) {
  433. error ("Format option lacks specification.");
  434. exit( 1 );
  435. }
  436. params.format_list = list_create( NULL );
  437. if ((prefix = _get_prefix(format))) {
  438. if (params.step_flag)
  439. step_format_add_prefix( params.format_list, 0, 0,
  440. prefix);
  441. else
  442. job_format_add_prefix( params.format_list, 0, 0,
  443. prefix);
  444. }
  445. field_size = strlen( format );
  446. tmp_format = xmalloc( field_size + 1 );
  447. strcpy( tmp_format, format );
  448. token = strtok_r( tmp_format, "%", &tmp_char);
  449. if (token && (format[0] != '%')) /* toss header */
  450. token = strtok_r( NULL, "%", &tmp_char );
  451. while (token) {
  452. _parse_token( token, field, &field_size, &right_justify,
  453. &suffix);
  454. if (params.step_flag) {
  455. if (field[0] == 'A')
  456. step_format_add_num_tasks( params.format_list,
  457. field_size,
  458. right_justify,
  459. suffix );
  460. else if (field[0] == 'b')
  461. step_format_add_gres( params.format_list,
  462. field_size,
  463. right_justify, suffix );
  464. else if (field[0] == 'i')
  465. step_format_add_id( params.format_list,
  466. field_size,
  467. right_justify, suffix );
  468. else if (field[0] == 'j')
  469. step_format_add_name( params.format_list,
  470. field_size,
  471. right_justify,
  472. suffix );
  473. else if (field[0] == 'l')
  474. step_format_add_time_limit( params.format_list,
  475. field_size,
  476. right_justify,
  477. suffix );
  478. else if (field[0] == 'M')
  479. step_format_add_time_used( params.format_list,
  480. field_size,
  481. right_justify,
  482. suffix );
  483. else if (field[0] == 'N')
  484. step_format_add_nodes( params.format_list,
  485. field_size,
  486. right_justify, suffix );
  487. else if (field[0] == 'P')
  488. step_format_add_partition( params.format_list,
  489. field_size,
  490. right_justify,
  491. suffix );
  492. else if (field[0] == 'S')
  493. step_format_add_time_start( params.format_list,
  494. field_size,
  495. right_justify,
  496. suffix );
  497. else if (field[0] == 'U')
  498. step_format_add_user_id( params.format_list,
  499. field_size,
  500. right_justify,
  501. suffix );
  502. else if (field[0] == 'u')
  503. step_format_add_user_name( params.format_list,
  504. field_size,
  505. right_justify,
  506. suffix );
  507. else {
  508. prefix = xstrdup("%");
  509. xstrcat(prefix, token);
  510. xfree(suffix);
  511. suffix = prefix;
  512. step_format_add_invalid( params.format_list,
  513. field_size,
  514. right_justify,
  515. suffix );
  516. error ( "Invalid job step format "
  517. "specification: %c",
  518. field[0] );
  519. }
  520. } else {
  521. if (field[0] == 'a')
  522. job_format_add_account( params.format_list,
  523. field_size,
  524. right_justify,
  525. suffix );
  526. else if (field[0] == 'b')
  527. job_format_add_gres( params.format_list,
  528. field_size, right_justify,
  529. suffix );
  530. else if (field[0] == 'B')
  531. job_format_add_batch_host( params.format_list,
  532. field_size,
  533. right_justify,
  534. suffix );
  535. else if (field[0] == 'c')
  536. job_format_add_min_cpus( params.format_list,
  537. field_size,
  538. right_justify,
  539. suffix );
  540. else if (field[0] == 'C')
  541. job_format_add_num_cpus( params.format_list,
  542. field_size,
  543. right_justify,
  544. suffix );
  545. else if (field[0] == 'd')
  546. job_format_add_min_tmp_disk(
  547. params.format_list,
  548. field_size,
  549. right_justify,
  550. suffix );
  551. else if (field[0] == 'D')
  552. job_format_add_num_nodes( params.format_list,
  553. field_size,
  554. right_justify,
  555. suffix );
  556. else if (field[0] == 'e')
  557. job_format_add_time_end( params.format_list,
  558. field_size,
  559. right_justify,
  560. suffix );
  561. else if (field[0] == 'E')
  562. job_format_add_dependency( params.format_list,
  563. field_size,
  564. right_justify,
  565. suffix );
  566. else if (field[0] == 'f')
  567. job_format_add_features( params.format_list,
  568. field_size,
  569. right_justify,
  570. suffix );
  571. else if (field[0] == 'g')
  572. job_format_add_group_name( params.format_list,
  573. field_size,
  574. right_justify,
  575. suffix );
  576. else if (field[0] == 'G')
  577. job_format_add_group_id( params.format_list,
  578. field_size,
  579. right_justify,
  580. suffix );
  581. else if (field[0] == 'h')
  582. job_format_add_shared( params.format_list,
  583. field_size,
  584. right_justify,
  585. suffix );
  586. else if (field[0] == 'H')
  587. job_format_add_sockets( params.format_list,
  588. field_size,
  589. right_justify,
  590. suffix );
  591. else if (field[0] == 'i')
  592. job_format_add_job_id( params.format_list,
  593. field_size,
  594. right_justify,
  595. suffix );
  596. else if (field[0] == 'I')
  597. job_format_add_cores( params.format_list,
  598. field_size,
  599. right_justify, suffix );
  600. else if (field[0] == 'j')
  601. job_format_add_name( params.format_list,
  602. field_size,
  603. right_justify, suffix );
  604. else if (field[0] == 'J')
  605. job_format_add_threads( params.format_list,
  606. field_size,
  607. right_justify,
  608. suffix );
  609. else if (field[0] == 'k')
  610. job_format_add_comment( params.format_list,
  611. field_size,
  612. right_justify,
  613. suffix );
  614. else if (field[0] == 'l')
  615. job_format_add_time_limit( params.format_list,
  616. field_size,
  617. right_justify,
  618. suffix );
  619. else if (field[0] == 'L')
  620. job_format_add_time_left( params.format_list,
  621. field_size,
  622. right_justify,
  623. suffix );
  624. else if (field[0] == 'm')
  625. job_format_add_min_memory( params.format_list,
  626. field_size,
  627. right_justify,
  628. suffix );
  629. else if (field[0] == 'M')
  630. job_format_add_time_used( params.format_list,
  631. field_size,
  632. right_justify,
  633. suffix );
  634. else if (field[0] == 'n')
  635. job_format_add_req_nodes( params.format_list,
  636. field_size,
  637. right_justify,
  638. suffix );
  639. else if (field[0] == 'N')
  640. job_format_add_nodes( params.format_list,
  641. field_size,
  642. right_justify, suffix );
  643. else if (field[0] == 'O')
  644. job_format_add_contiguous( params.format_list,
  645. field_size,
  646. right_justify,
  647. suffix );
  648. else if (field[0] == 'p')
  649. job_format_add_priority( params.format_list,
  650. field_size,
  651. right_justify,
  652. suffix );
  653. else if (field[0] == 'P')
  654. job_format_add_partition( params.format_list,
  655. field_size,
  656. right_justify,
  657. suffix );
  658. else if (field[0] == 'q')
  659. job_format_add_qos( params.format_list,
  660. field_size,
  661. right_justify,
  662. suffix );
  663. else if (field[0] == 'Q')
  664. job_format_add_priority_long(
  665. params.format_list,
  666. field_size,
  667. right_justify,
  668. suffix );
  669. else if (field[0] == 'r')
  670. job_format_add_reason( params.format_list,
  671. field_size,
  672. right_justify,
  673. suffix );
  674. else if (field[0] == 'R')
  675. job_format_add_reason_list( params.format_list,
  676. field_size,
  677. right_justify,
  678. suffix );
  679. else if (field[0] == 's')
  680. job_format_add_select_jobinfo(
  681. params.format_list,
  682. field_size,
  683. right_justify,
  684. suffix );
  685. else if (field[0] == 'S')
  686. job_format_add_time_start( params.format_list,
  687. field_size,
  688. right_justify,
  689. suffix );
  690. else if (field[0] == 't')
  691. job_format_add_job_state_compact(
  692. params.format_list,
  693. field_size,
  694. right_justify,
  695. suffix );
  696. else if (field[0] == 'T')
  697. job_format_add_job_state( params.format_list,
  698. field_size,
  699. right_justify,
  700. suffix );
  701. else if (field[0] == 'U')
  702. job_format_add_user_id( params.format_list,
  703. field_size,
  704. right_justify,
  705. suffix );
  706. else if (field[0] == 'u')
  707. job_format_add_user_name( params.format_list,
  708. field_size,
  709. right_justify,
  710. suffix );
  711. else if (field[0] == 'v')
  712. job_format_add_reservation( params.format_list,
  713. field_size,
  714. right_justify,
  715. suffix );
  716. else if (field[0] == 'w')
  717. job_format_add_wckey( params.format_list,
  718. field_size,
  719. right_justify,
  720. suffix );
  721. else if (field[0] == 'W')
  722. job_format_add_licenses( params.format_list,
  723. field_size,
  724. right_justify, suffix );
  725. else if (field[0] == 'x')
  726. job_format_add_exc_nodes( params.format_list,
  727. field_size,
  728. right_justify,
  729. suffix );
  730. else if (field[0] == 'z')
  731. job_format_add_num_sct( params.format_list,
  732. field_size,
  733. right_justify,
  734. suffix );
  735. else {
  736. prefix = xstrdup("%");
  737. xstrcat(prefix, token);
  738. xfree(suffix);
  739. suffix = prefix;
  740. job_format_add_invalid( params.format_list,
  741. field_size,
  742. right_justify,
  743. suffix );
  744. error( "Invalid job format specification: %c",
  745. field[0] );
  746. }
  747. }
  748. token = strtok_r( NULL, "%", &tmp_char);
  749. }
  750. xfree( tmp_format );
  751. return SLURM_SUCCESS;
  752. }
  753. /* Take a format specification and copy out it's prefix
  754. * IN/OUT token - input specification, everything before "%" is removed
  755. * RET - everything before "%" in the token
  756. */
  757. static char *
  758. _get_prefix( char *token )
  759. {
  760. char *pos, *prefix;
  761. if (token == NULL)
  762. return NULL;
  763. pos = strchr(token, (int) '%');
  764. if (pos == NULL) /* everything is prefix */
  765. return xstrdup(token);
  766. if (pos == token) /* no prefix */
  767. return NULL;
  768. pos[0] = '\0'; /* some prefix */
  769. prefix = xstrdup(token);
  770. pos[0] = '%';
  771. memmove(token, pos, (strlen(pos)+1));
  772. return prefix;
  773. }
  774. /* Take a format specification and break it into its components
  775. * IN token - input specification without leading "%", eg. ".5u"
  776. * OUT field - the letter code for the data type
  777. * OUT field_size - byte count
  778. * OUT right_justify - true of field to be right justified
  779. * OUT suffix - string containing everthing after the field specification
  780. */
  781. static void
  782. _parse_token( char *token, char *field, int *field_size, bool *right_justify,
  783. char **suffix)
  784. {
  785. int i = 0;
  786. assert (token != NULL);
  787. if (token[i] == '.') {
  788. *right_justify = true;
  789. i++;
  790. } else
  791. *right_justify = false;
  792. *field_size = 0;
  793. while ((token[i] >= '0') && (token[i] <= '9'))
  794. *field_size = (*field_size * 10) + (token[i++] - '0');
  795. field[0] = token[i++];
  796. *suffix = xstrdup(&token[i]);
  797. }
  798. /* print the parameters specified */
  799. static void
  800. _print_options(void)
  801. {
  802. ListIterator iterator;
  803. int i;
  804. char *part, *name;
  805. uint32_t *user;
  806. enum job_states *state_id;
  807. squeue_job_step_t *job_step_id;
  808. uint32_t *job_id;
  809. char hostlist[8192];
  810. if (params.nodes) {
  811. hostset_ranged_string(params.nodes, sizeof(hostlist)-1,
  812. hostlist);
  813. } else
  814. hostlist[0] = '\0';
  815. printf( "-----------------------------\n" );
  816. printf( "all = %s\n", params.all_flag ? "true" : "false");
  817. printf( "format = %s\n", params.format );
  818. printf( "iterate = %d\n", params.iterate );
  819. printf( "job_flag = %d\n", params.job_flag );
  820. printf( "jobs = %s\n", params.jobs );
  821. printf( "max_cpus = %d\n", params.max_cpus ) ;
  822. printf( "names = %s\n", params.names );
  823. printf( "nodes = %s\n", hostlist ) ;
  824. printf( "partitions = %s\n", params.partitions ) ;
  825. printf( "reservation = %s\n", params.reservation ) ;
  826. printf( "sort = %s\n", params.sort ) ;
  827. printf( "start_flag = %d\n", params.start_flag );
  828. printf( "states = %s\n", params.states ) ;
  829. printf( "step_flag = %d\n", params.step_flag );
  830. printf( "steps = %s\n", params.steps );
  831. printf( "users = %s\n", params.users );
  832. printf( "verbose = %d\n", params.verbose );
  833. if ((params.verbose > 1) && params.job_list) {
  834. i = 0;
  835. iterator = list_iterator_create( params.job_list );
  836. while ( (job_id = list_next( iterator )) ) {
  837. printf( "job_list[%d] = %u\n", i++, *job_id);
  838. }
  839. list_iterator_destroy( iterator );
  840. }
  841. if ((params.verbose > 1) && params.name_list) {
  842. i = 0;
  843. iterator = list_iterator_create( params.name_list );
  844. while ( (name = list_next( iterator )) ) {
  845. printf( "name_list[%d] = %u\n", i++, *name);
  846. }
  847. list_iterator_destroy( iterator );
  848. }
  849. if ((params.verbose > 1) && params.part_list) {
  850. i = 0;
  851. iterator = list_iterator_create( params.part_list );
  852. while ( (part = list_next( iterator )) ) {
  853. printf( "part_list[%d] = %s\n", i++, part);
  854. }
  855. list_iterator_destroy( iterator );
  856. }
  857. if ((params.verbose > 1) && params.state_list) {
  858. i = 0;
  859. iterator = list_iterator_create( params.state_list );
  860. while ( (state_id = list_next( iterator )) ) {
  861. printf( "state_list[%d] = %s\n",
  862. i++, job_state_string( *state_id ));
  863. }
  864. list_iterator_destroy( iterator );
  865. }
  866. if ((params.verbose > 1) && params.step_list) {
  867. i = 0;
  868. iterator = list_iterator_create( params.step_list );
  869. while ( (job_step_id = list_next( iterator )) ) {
  870. printf( "step_list[%d] = %u.%u\n", i++,
  871. job_step_id->job_id, job_step_id->step_id );
  872. }
  873. list_iterator_destroy( iterator );
  874. }
  875. if ((params.verbose > 1) && params.user_list) {
  876. i = 0;
  877. iterator = list_iterator_create( params.user_list );
  878. while ( (user = list_next( iterator )) ) {
  879. printf( "user_list[%d] = %u\n", i++, *user);
  880. }
  881. list_iterator_destroy( iterator );
  882. }
  883. printf( "-----------------------------\n\n\n" );
  884. } ;
  885. /*
  886. * _build_job_list- build a list of job_ids
  887. * IN str - comma separated list of job_ids
  888. * RET List of job_ids (uint32_t)
  889. */
  890. static List
  891. _build_job_list( char* str )
  892. {
  893. List my_list;
  894. char *job = NULL, *tmp_char = NULL, *my_job_list = NULL;
  895. int i;
  896. uint32_t *job_id = NULL;
  897. if ( str == NULL )
  898. return NULL;
  899. my_list = list_create( NULL );
  900. my_job_list = xstrdup( str );
  901. job = strtok_r( my_job_list, ",", &tmp_char );
  902. while (job) {
  903. i = strtol( job, (char **) NULL, 10 );
  904. if (i <= 0) {
  905. error( "Invalid job id: %s", job );
  906. exit( 1 );
  907. }
  908. job_id = xmalloc( sizeof( uint32_t ) );
  909. *job_id = (uint32_t) i;
  910. list_append( my_list, job_id );
  911. job = strtok_r (NULL, ",", &tmp_char);
  912. }
  913. return my_list;
  914. }
  915. /*
  916. * _build_str_list - convert a string of comma-separated elements
  917. * into a list of strings
  918. * IN str - comma separated list of strings
  919. * RET List of strings
  920. */
  921. static List
  922. _build_str_list( char* str )
  923. {
  924. List my_list;
  925. char *part = NULL, *tmp_char = NULL, *my_part_list = NULL;
  926. if ( str == NULL)
  927. return NULL;
  928. my_list = list_create( NULL );
  929. my_part_list = xstrdup( str );
  930. part = strtok_r( my_part_list, ",", &tmp_char );
  931. while (part) {
  932. list_append( my_list, part );
  933. part = strtok_r( NULL, ",", &tmp_char );
  934. }
  935. /* NOTE: Do NOT xfree my_part_list or the elements just added to the
  936. * list will also be freed. */
  937. return my_list;
  938. }
  939. /*
  940. * _build_state_list - build a list of job states
  941. * IN str - comma separated list of job states
  942. * RET List of enum job_states values
  943. */
  944. static List
  945. _build_state_list( char* str )
  946. {
  947. List my_list;
  948. char *state = NULL, *tmp_char = NULL, *my_state_list = NULL;
  949. uint16_t *state_id = NULL;
  950. if ( str == NULL)
  951. return NULL;
  952. if ( strcasecmp( str, "all" ) == 0 )
  953. return _build_all_states_list ();
  954. my_list = list_create( NULL );
  955. my_state_list = xstrdup( str );
  956. state = strtok_r( my_state_list, ",", &tmp_char );
  957. while (state)
  958. {
  959. state_id = xmalloc( sizeof( uint16_t ) );
  960. if ( _parse_state( state, state_id ) != SLURM_SUCCESS )
  961. exit( 1 );
  962. list_append( my_list, state_id );
  963. state = strtok_r( NULL, ",", &tmp_char );
  964. }
  965. return my_list;
  966. }
  967. /*
  968. * _build_all_states_list - build a list containing all possible job states
  969. * RET List of uint16_t values
  970. */
  971. static List
  972. _build_all_states_list( void )
  973. {
  974. List my_list;
  975. int i;
  976. uint16_t * state_id;
  977. my_list = list_create( NULL );
  978. for (i = 0; i<JOB_END; i++) {
  979. state_id = xmalloc( sizeof(uint16_t) );
  980. *state_id = (uint16_t) i;
  981. list_append( my_list, state_id );
  982. }
  983. state_id = xmalloc( sizeof(uint16_t) );
  984. *state_id = (uint16_t) JOB_COMPLETING;
  985. list_append( my_list, state_id );
  986. state_id = xmalloc( sizeof(uint16_t) );
  987. *state_id = (uint16_t) JOB_CONFIGURING;
  988. list_append( my_list, state_id );
  989. return my_list;
  990. }
  991. /*
  992. * _build_step_list- build a list of job/step_ids
  993. * IN str - comma separated list of job_id.step_ids
  994. * RET List of job/step_ids (structure of uint32_t's)
  995. */
  996. static List
  997. _build_step_list( char* str )
  998. {
  999. List my_list;
  1000. char *step = NULL, *tmp_char = NULL, *tmps_char = NULL;
  1001. char *job_name = NULL, *step_name = NULL, *my_step_list = NULL;
  1002. int i, j;
  1003. squeue_job_step_t *job_step_id = NULL;
  1004. if ( str == NULL)
  1005. return NULL;
  1006. my_list = list_create( NULL );
  1007. my_step_list = xstrdup( str );
  1008. step = strtok_r( my_step_list, ",", &tmp_char );
  1009. while (step)
  1010. {
  1011. job_name = strtok_r( step, ".", &tmps_char );
  1012. step_name = strtok_r( NULL, ".", &tmps_char );
  1013. i = strtol( job_name, (char **) NULL, 10 );
  1014. if (step_name == NULL) {
  1015. error ( "Invalid job_step id: %s.??",
  1016. job_name );
  1017. exit( 1 );
  1018. }
  1019. j = strtol( step_name, (char **) NULL, 10 );
  1020. if ((i <= 0) || (j < 0)) {
  1021. error( "Invalid job_step id: %s.%s",
  1022. job_name, step_name );
  1023. exit( 1 );
  1024. }
  1025. job_step_id = xmalloc( sizeof( squeue_job_step_t ) );
  1026. job_step_id->job_id = (uint32_t) i;
  1027. job_step_id->step_id = (uint32_t) j;
  1028. list_append( my_list, job_step_id );
  1029. step = strtok_r( NULL, ",", &tmp_char);
  1030. }
  1031. return my_list;
  1032. }
  1033. /*
  1034. * _build_user_list- build a list of UIDs
  1035. * IN str - comma separated list of user names
  1036. * RET List of UIDs (uint32_t)
  1037. */
  1038. static List
  1039. _build_user_list( char* str )
  1040. {
  1041. List my_list;
  1042. char *user = NULL;
  1043. char *tmp_char = NULL, *my_user_list = NULL;
  1044. if ( str == NULL )
  1045. return NULL;
  1046. my_list = list_create( NULL );
  1047. my_user_list = xstrdup( str );
  1048. user = strtok_r( my_user_list, ",", &tmp_char );
  1049. while (user) {
  1050. uid_t some_uid;
  1051. if ( uid_from_string( user, &some_uid ) == 0 ) {
  1052. uint32_t *user_id = NULL;
  1053. user_id = xmalloc( sizeof( uint32_t ));
  1054. *user_id = (uint32_t) some_uid;
  1055. list_append( my_list, user_id );
  1056. } else {
  1057. error( "Invalid user: %s\n", user);
  1058. }
  1059. user = strtok_r (NULL, ",", &tmp_char);
  1060. }
  1061. return my_list;
  1062. }
  1063. static void _usage(void)
  1064. {
  1065. printf("\
  1066. Usage: squeue [-i seconds] [-n name] [-o format] [-p partitions]\n\
  1067. [-R reservation] [-S fields] [--start] [-t states]\n\
  1068. [-u user_name] [--usage] [-w nodes] [-ahjlsv]\n");
  1069. }
  1070. static void _help(void)
  1071. {
  1072. printf("\
  1073. Usage: squeue [OPTIONS]\n\
  1074. -A, --account=account(s) comma separated list of accounts\n\
  1075. to view, default is all accounts\n\
  1076. -a, --all display jobs in hidden partitions\n\
  1077. -h, --noheader no headers on output\n\
  1078. --hide do not display jobs in hidden partitions\n\
  1079. -i, --iterate=seconds specify an interation period\n\
  1080. -j, --job=job(s) comma separated list of jobs IDs\n\
  1081. to view, default is all\n\
  1082. -l, --long long report\n\
  1083. -M, --clusters=cluster_name cluster to issue commands to. Default is\n\
  1084. current cluster. cluster with no name will\n\
  1085. reset to default.\n\
  1086. -n, --name=job_name(s) comma separated list of job names to view\n\
  1087. -o, --format=format format specification\n\
  1088. -p, --partition=partition(s) comma separated list of partitions\n\
  1089. to view, default is all partitions\n\
  1090. -q, --qos=qos(s) comma separated list of qos's\n\
  1091. to view, default is all qos's\n\
  1092. -R, --reservation=name reservation to view, default is all\n\
  1093. -s, --step=step(s) comma separated list of job steps\n\
  1094. to view, default is all\n\
  1095. -S, --sort=fields comma separated list of fields to sort on\n\
  1096. --start print expected start times of pending jobs\n\
  1097. -t, --states=states comma separated list of states to view,\n\
  1098. default is pending and running,\n\
  1099. '--states=all' reports all states\n\
  1100. -u, --user=user_name(s) comma separated list of users to view\n\
  1101. --name=job_name(s) comma separated list of job names to view\n\
  1102. -v, --verbose verbosity level\n\
  1103. -V, --version output version information and exit\n\
  1104. -w, --nodelist=hostlist list of nodes to view, default is \n\
  1105. all nodes\n\
  1106. \nHelp options:\n\
  1107. --help show this help message\n\
  1108. --usage display a brief summary of squeue options\n");
  1109. }