PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sacctmgr/archive_functions.c

https://github.com/cfenoy/slurm
C | 555 lines | 472 code | 41 blank | 42 comment | 167 complexity | b40604a9f0e309a42511353fceda126e MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * archive_functions.c - functions dealing with archive in the
  3. * accounting system.
  4. *****************************************************************************
  5. * Copyright (C) 2008 Lawrence Livermore National Security.
  6. * Copyright (C) 2002-2007 The Regents of the University of California.
  7. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  8. * Written by Danny Auble <da@llnl.gov>
  9. * CODE-OCEC-09-009. All rights reserved.
  10. *
  11. * This file is part of SLURM, a resource management program.
  12. * For details, see <http://www.schedmd.com/slurmdocs/>.
  13. * Please also read the included file: DISCLAIMER.
  14. *
  15. * SLURM is free software; you can redistribute it and/or modify it under
  16. * the terms of the GNU General Public License as published by the Free
  17. * Software Foundation; either version 2 of the License, or (at your option)
  18. * any later version.
  19. *
  20. * In addition, as a special exception, the copyright holders give permission
  21. * to link the code of portions of this program with the OpenSSL library under
  22. * certain conditions as described in each individual source file, and
  23. * distribute linked combinations including the two. You must obey the GNU
  24. * General Public License in all respects for all of the code used other than
  25. * OpenSSL. If you modify file(s) with this exception, you may extend this
  26. * exception to your version of the file(s), but you are not obligated to do
  27. * so. If you do not wish to do so, delete this exception statement from your
  28. * version. If you delete this exception statement from all source files in
  29. * the program, then also delete it here.
  30. *
  31. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  32. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  33. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  34. * details.
  35. *
  36. * You should have received a copy of the GNU General Public License along
  37. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  38. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  39. \*****************************************************************************/
  40. #include <sys/stat.h>
  41. #include "src/sacctmgr/sacctmgr.h"
  42. #include <sys/param.h> /* MAXPATHLEN */
  43. #include "src/common/proc_args.h"
  44. #include "src/common/uid.h"
  45. static char *_string_to_uid( char *name )
  46. {
  47. uid_t uid;
  48. if ( uid_from_string( name, &uid ) != 0 ) {
  49. fprintf(stderr, "Invalid user id: %s\n", name);
  50. exit(1);
  51. }
  52. xfree(name);
  53. return xstrdup_printf( "%d", (int) uid );
  54. }
  55. /* returns number of objects added to list */
  56. extern int _addto_uid_char_list(List char_list, char *names)
  57. {
  58. int i=0, start=0;
  59. char *name = NULL, *tmp_char = NULL;
  60. ListIterator itr = NULL;
  61. char quote_c = '\0';
  62. int quote = 0;
  63. int count = 0;
  64. if(!char_list) {
  65. error("No list was given to fill in");
  66. return 0;
  67. }
  68. itr = list_iterator_create(char_list);
  69. if(names) {
  70. if (names[i] == '\"' || names[i] == '\'') {
  71. quote_c = names[i];
  72. quote = 1;
  73. i++;
  74. }
  75. start = i;
  76. while(names[i]) {
  77. //info("got %d - %d = %d", i, start, i-start);
  78. if(quote && names[i] == quote_c)
  79. break;
  80. else if (names[i] == '\"' || names[i] == '\'')
  81. names[i] = '`';
  82. else if(names[i] == ',') {
  83. if((i-start) > 0) {
  84. name = xmalloc((i-start+1));
  85. memcpy(name, names+start, (i-start));
  86. //info("got %s %d", name, i-start);
  87. name = _string_to_uid( name );
  88. while((tmp_char = list_next(itr))) {
  89. if(!strcasecmp(tmp_char, name))
  90. break;
  91. }
  92. if(!tmp_char) {
  93. list_append(char_list, name);
  94. count++;
  95. } else
  96. xfree(name);
  97. list_iterator_reset(itr);
  98. }
  99. i++;
  100. start = i;
  101. if(!names[i]) {
  102. info("There is a problem with "
  103. "your request. It appears you "
  104. "have spaces inside your list.");
  105. break;
  106. }
  107. }
  108. i++;
  109. }
  110. if((i-start) > 0) {
  111. name = xmalloc((i-start)+1);
  112. memcpy(name, names+start, (i-start));
  113. name = _string_to_uid( name );
  114. while((tmp_char = list_next(itr))) {
  115. if(!strcasecmp(tmp_char, name))
  116. break;
  117. }
  118. if(!tmp_char) {
  119. list_append(char_list, name);
  120. count++;
  121. } else
  122. xfree(name);
  123. }
  124. }
  125. list_iterator_destroy(itr);
  126. return count;
  127. }
  128. static int _set_cond(int *start, int argc, char *argv[],
  129. slurmdb_archive_cond_t *arch_cond)
  130. {
  131. int i;
  132. int set = 0;
  133. int end = 0;
  134. int command_len = 0;
  135. uint32_t tmp;
  136. slurmdb_job_cond_t *job_cond = NULL;
  137. if(!arch_cond) {
  138. error("No arch_cond given");
  139. return -1;
  140. }
  141. if(!arch_cond->job_cond)
  142. arch_cond->job_cond = xmalloc(sizeof(slurmdb_job_cond_t));
  143. job_cond = arch_cond->job_cond;
  144. for (i=(*start); i<argc; i++) {
  145. end = parse_option_end(argv[i]);
  146. if(!end)
  147. command_len=strlen(argv[i]);
  148. else {
  149. command_len=end-1;
  150. if (argv[i][end] == '=') {
  151. end++;
  152. }
  153. }
  154. if(!end && !strncasecmp(argv[i], "where",
  155. MAX(command_len, 5))) {
  156. continue;
  157. } else if(!end && !strncasecmp(argv[i], "events",
  158. MAX(command_len, 1))) {
  159. arch_cond->purge_event |= SLURMDB_PURGE_ARCHIVE;
  160. set = 1;
  161. } else if(!end && !strncasecmp(argv[i], "jobs",
  162. MAX(command_len, 1))) {
  163. arch_cond->purge_job |= SLURMDB_PURGE_ARCHIVE;
  164. set = 1;
  165. } else if(!end && !strncasecmp(argv[i], "steps",
  166. MAX(command_len, 1))) {
  167. arch_cond->purge_step |= SLURMDB_PURGE_ARCHIVE;
  168. set = 1;
  169. } else if(!end && !strncasecmp(argv[i], "suspend",
  170. MAX(command_len, 1))) {
  171. arch_cond->purge_suspend |= SLURMDB_PURGE_ARCHIVE;
  172. set = 1;
  173. } else if(!end
  174. || !strncasecmp(argv[i], "Clusters",
  175. MAX(command_len, 1))) {
  176. if(!job_cond->cluster_list)
  177. job_cond->cluster_list =
  178. list_create(slurm_destroy_char);
  179. slurm_addto_char_list(job_cond->cluster_list,
  180. argv[i]+end);
  181. set = 1;
  182. } else if (!strncasecmp (argv[i], "Accounts",
  183. MAX(command_len, 2))) {
  184. if(!job_cond->acct_list)
  185. job_cond->acct_list =
  186. list_create(slurm_destroy_char);
  187. slurm_addto_char_list(job_cond->acct_list,
  188. argv[i]+end);
  189. set = 1;
  190. } else if (!strncasecmp (argv[i], "Associations",
  191. MAX(command_len, 2))) {
  192. if(!job_cond->associd_list)
  193. job_cond->associd_list =
  194. list_create(slurm_destroy_char);
  195. slurm_addto_char_list(job_cond->associd_list,
  196. argv[i]+end);
  197. set = 1;
  198. } else if (!strncasecmp (argv[i], "Directory",
  199. MAX(command_len, 2))) {
  200. arch_cond->archive_dir =
  201. strip_quotes(argv[i]+end, NULL, 0);
  202. set = 1;
  203. } else if (!strncasecmp (argv[i], "End", MAX(command_len, 1))) {
  204. job_cond->usage_end = parse_time(argv[i]+end, 1);
  205. set = 1;
  206. } else if (!strncasecmp (argv[i], "Gid", MAX(command_len, 2))) {
  207. if(!job_cond->groupid_list)
  208. job_cond->groupid_list =
  209. list_create(slurm_destroy_char);
  210. slurm_addto_char_list(job_cond->groupid_list,
  211. argv[i]+end);
  212. set = 1;
  213. } else if (!strncasecmp (argv[i], "Jobs",
  214. MAX(command_len, 1))) {
  215. char *end_char = NULL, *start_char = argv[i]+end;
  216. slurmdb_selected_step_t *selected_step = NULL;
  217. char *dot = NULL;
  218. if(!job_cond->step_list)
  219. job_cond->step_list =
  220. list_create(slurm_destroy_char);
  221. while ((end_char = strstr(start_char, ","))
  222. && start_char) {
  223. *end_char = 0;
  224. while (isspace(*start_char))
  225. start_char++; /* discard whitespace */
  226. if(!(int)*start_char)
  227. continue;
  228. selected_step = xmalloc(
  229. sizeof(slurmdb_selected_step_t));
  230. list_append(job_cond->step_list, selected_step);
  231. dot = strstr(start_char, ".");
  232. if (dot == NULL) {
  233. debug2("No jobstep requested");
  234. selected_step->stepid = NO_VAL;
  235. } else {
  236. *dot++ = 0;
  237. selected_step->stepid = atoi(dot);
  238. }
  239. selected_step->jobid = atoi(start_char);
  240. start_char = end_char + 1;
  241. }
  242. set = 1;
  243. } else if (!strncasecmp (argv[i], "Partitions",
  244. MAX(command_len, 2))) {
  245. if(!job_cond->partition_list)
  246. job_cond->partition_list =
  247. list_create(slurm_destroy_char);
  248. slurm_addto_char_list(job_cond->partition_list,
  249. argv[i]+end);
  250. set = 1;
  251. } else if (!strncasecmp (argv[i], "PurgeEventAfter",
  252. MAX(command_len, 10))) {
  253. if ((tmp = slurmdb_parse_purge(argv[i]+end))
  254. == NO_VAL) {
  255. exit_code = 1;
  256. } else {
  257. arch_cond->purge_event |= tmp;
  258. set = 1;
  259. }
  260. } else if (!strncasecmp (argv[i], "PurgeJobAfter",
  261. MAX(command_len, 10))) {
  262. if ((tmp = slurmdb_parse_purge(argv[i]+end))
  263. == NO_VAL) {
  264. exit_code = 1;
  265. } else {
  266. arch_cond->purge_job |= tmp;
  267. set = 1;
  268. }
  269. } else if (!strncasecmp (argv[i], "PurgeStepAfter",
  270. MAX(command_len, 10))) {
  271. if ((tmp = slurmdb_parse_purge(argv[i]+end))
  272. == NO_VAL) {
  273. exit_code = 1;
  274. } else {
  275. arch_cond->purge_step |= tmp;
  276. set = 1;
  277. }
  278. } else if (!strncasecmp (argv[i], "PurgeSuspendAfter",
  279. MAX(command_len, 10))) {
  280. if ((tmp = slurmdb_parse_purge(argv[i]+end))
  281. == NO_VAL) {
  282. exit_code = 1;
  283. } else {
  284. arch_cond->purge_suspend |= tmp;
  285. set = 1;
  286. }
  287. } else if (!strncasecmp (argv[i], "PurgeEventMonths",
  288. MAX(command_len, 6))) {
  289. if (get_uint(argv[i]+end, &tmp, "PurgeEventMonths")
  290. != SLURM_SUCCESS) {
  291. exit_code = 1;
  292. } else {
  293. arch_cond->purge_event |= tmp;
  294. arch_cond->purge_event |= SLURMDB_PURGE_MONTHS;
  295. set = 1;
  296. }
  297. } else if (!strncasecmp (argv[i], "PurgeJobMonths",
  298. MAX(command_len, 6))) {
  299. if (get_uint(argv[i]+end, &tmp, "PurgeJobMonths")
  300. != SLURM_SUCCESS) {
  301. exit_code = 1;
  302. } else {
  303. arch_cond->purge_job |= tmp;
  304. arch_cond->purge_job |= SLURMDB_PURGE_MONTHS;
  305. set = 1;
  306. }
  307. } else if (!strncasecmp (argv[i], "PurgeStepMonths",
  308. MAX(command_len, 7))) {
  309. if (get_uint(argv[i]+end, &tmp, "PurgeStepMonths")
  310. != SLURM_SUCCESS) {
  311. exit_code = 1;
  312. } else {
  313. arch_cond->purge_step |= tmp;
  314. arch_cond->purge_step |= SLURMDB_PURGE_MONTHS;
  315. set = 1;
  316. }
  317. } else if (!strncasecmp (argv[i], "PurgeSuspendMonths",
  318. MAX(command_len, 7))) {
  319. if (get_uint(argv[i]+end, &tmp, "PurgeSuspendMonths")
  320. != SLURM_SUCCESS) {
  321. exit_code = 1;
  322. } else {
  323. arch_cond->purge_suspend |= tmp;
  324. arch_cond->purge_suspend
  325. |= SLURMDB_PURGE_MONTHS;
  326. set = 1;
  327. }
  328. } else if (!strncasecmp (argv[i], "Start",
  329. MAX(command_len, 2))) {
  330. job_cond->usage_start = parse_time(argv[i]+end, 1);
  331. set = 1;
  332. } else if (!strncasecmp (argv[i], "Script",
  333. MAX(command_len, 2))) {
  334. arch_cond->archive_script =
  335. strip_quotes(argv[i]+end, NULL, 0);
  336. set = 1;
  337. } else if (!strncasecmp (argv[i], "Users",
  338. MAX(command_len, 1))) {
  339. if(!job_cond->userid_list)
  340. job_cond->userid_list =
  341. list_create(slurm_destroy_char);
  342. _addto_uid_char_list(job_cond->userid_list,
  343. argv[i]+end);
  344. set = 1;
  345. } else {
  346. exit_code=1;
  347. fprintf(stderr, " Unknown condition: %s\n", argv[i]);
  348. }
  349. }
  350. (*start) = i;
  351. return set;
  352. }
  353. extern int sacctmgr_archive_dump(int argc, char *argv[])
  354. {
  355. int rc = SLURM_SUCCESS;
  356. slurmdb_archive_cond_t *arch_cond =
  357. xmalloc(sizeof(slurmdb_archive_cond_t));
  358. int i=0;
  359. struct stat st;
  360. for (i=0; i<argc; i++) {
  361. int command_len = strlen(argv[i]);
  362. if (!strncasecmp (argv[i], "Where", MAX(command_len, 5))
  363. || !strncasecmp (argv[i], "Set", MAX(command_len, 3)))
  364. i++;
  365. _set_cond(&i, argc, argv, arch_cond);
  366. }
  367. if(!arch_cond->purge_event)
  368. arch_cond->purge_event = NO_VAL;
  369. if(!arch_cond->purge_job)
  370. arch_cond->purge_job = NO_VAL;
  371. if(!arch_cond->purge_step)
  372. arch_cond->purge_step = NO_VAL;
  373. if(!arch_cond->purge_suspend)
  374. arch_cond->purge_suspend = NO_VAL;
  375. if(exit_code) {
  376. slurmdb_destroy_archive_cond(arch_cond);
  377. return SLURM_ERROR;
  378. }
  379. if (arch_cond->archive_dir) {
  380. if(stat(arch_cond->archive_dir, &st) < 0) {
  381. exit_code = errno;
  382. fprintf(stderr, " dump: Failed to stat %s: %m\n "
  383. "Note: For archive dump, "
  384. "the directory must be on "
  385. "the calling host.\n",
  386. arch_cond->archive_dir);
  387. return SLURM_ERROR;
  388. }
  389. if (!(st.st_mode & S_IFDIR)) {
  390. errno = EACCES;
  391. fprintf(stderr, " dump: "
  392. "archive dir %s isn't a directory\n",
  393. arch_cond->archive_dir);
  394. return SLURM_ERROR;
  395. }
  396. if (access(arch_cond->archive_dir, W_OK) < 0) {
  397. errno = EACCES;
  398. fprintf(stderr, " dump: "
  399. "archive dir %s is not writable\n",
  400. arch_cond->archive_dir);
  401. return SLURM_ERROR;
  402. }
  403. }
  404. if (arch_cond->archive_script) {
  405. if(stat(arch_cond->archive_script, &st) < 0) {
  406. exit_code = errno;
  407. fprintf(stderr, " dump: Failed to stat %s: %m\n "
  408. "Note: For archive dump, the script must be on "
  409. "the calling host.\n",
  410. arch_cond->archive_script);
  411. return SLURM_ERROR;
  412. }
  413. if (!(st.st_mode & S_IFREG)) {
  414. errno = EACCES;
  415. fprintf(stderr, " dump: "
  416. "archive script %s isn't a regular file\n",
  417. arch_cond->archive_script);
  418. return SLURM_ERROR;
  419. }
  420. if (access(arch_cond->archive_script, X_OK) < 0) {
  421. errno = EACCES;
  422. fprintf(stderr, " dump: "
  423. "archive script %s is not executable\n",
  424. arch_cond->archive_script);
  425. return SLURM_ERROR;
  426. }
  427. }
  428. rc = jobacct_storage_g_archive(db_conn, arch_cond);
  429. if(rc == SLURM_SUCCESS) {
  430. if(commit_check("Would you like to commit changes?")) {
  431. acct_storage_g_commit(db_conn, 1);
  432. } else {
  433. printf(" Changes Discarded\n");
  434. acct_storage_g_commit(db_conn, 0);
  435. }
  436. } else {
  437. exit_code=1;
  438. fprintf(stderr, " Problem dumping archive: %s\n",
  439. slurm_strerror(rc));
  440. rc = SLURM_ERROR;
  441. }
  442. slurmdb_destroy_archive_cond(arch_cond);
  443. return rc;
  444. }
  445. extern int sacctmgr_archive_load(int argc, char *argv[])
  446. {
  447. int rc = SLURM_SUCCESS;
  448. slurmdb_archive_rec_t *arch_rec =
  449. xmalloc(sizeof(slurmdb_archive_rec_t));
  450. int i=0, command_len = 0;
  451. struct stat st;
  452. for (i=0; i<argc; i++) {
  453. int end = parse_option_end(argv[i]);
  454. if(!end)
  455. command_len=strlen(argv[i]);
  456. else {
  457. command_len=end-1;
  458. if (argv[i][end] == '=') {
  459. end++;
  460. }
  461. }
  462. if(!end
  463. || !strncasecmp (argv[i], "File", MAX(command_len, 1))) {
  464. arch_rec->archive_file =
  465. strip_quotes(argv[i]+end, NULL, 0);
  466. } else if (!strncasecmp (argv[i], "Insert",
  467. MAX(command_len, 2))) {
  468. arch_rec->insert = strip_quotes(argv[i]+end, NULL, 1);
  469. } else {
  470. exit_code=1;
  471. fprintf(stderr, " Unknown option: %s\n", argv[i]);
  472. }
  473. }
  474. if(exit_code) {
  475. slurmdb_destroy_archive_rec(arch_rec);
  476. return SLURM_ERROR;
  477. }
  478. if (arch_rec->archive_file) {
  479. char *fullpath;
  480. char cwd[MAXPATHLEN + 1];
  481. int mode = R_OK;
  482. if ((getcwd(cwd, MAXPATHLEN)) == NULL)
  483. fatal("getcwd failed: %m");
  484. if ((fullpath = search_path(cwd, arch_rec->archive_file,
  485. true, mode))) {
  486. xfree(arch_rec->archive_file);
  487. arch_rec->archive_file = fullpath;
  488. }
  489. if(stat(arch_rec->archive_file, &st) < 0) {
  490. exit_code = errno;
  491. fprintf(stderr, " load: Failed to stat %s: %m\n "
  492. "Note: For archive load, the file must be on "
  493. "the calling host.\n",
  494. arch_rec->archive_file);
  495. return SLURM_ERROR;
  496. }
  497. }
  498. rc = jobacct_storage_g_archive_load(db_conn, arch_rec);
  499. if(rc == SLURM_SUCCESS) {
  500. if(commit_check("Would you like to commit changes?")) {
  501. acct_storage_g_commit(db_conn, 1);
  502. } else {
  503. printf(" Changes Discarded\n");
  504. acct_storage_g_commit(db_conn, 0);
  505. }
  506. } else {
  507. exit_code=1;
  508. fprintf(stderr, " Problem loading archive file: %s\n",
  509. slurm_strerror(rc));
  510. rc = SLURM_ERROR;
  511. }
  512. slurmdb_destroy_archive_rec(arch_rec);
  513. return rc;
  514. }