PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/plugins/sched/wiki/msg.c

https://github.com/cfenoy/slurm
C | 739 lines | 561 code | 74 blank | 104 comment | 127 complexity | cc188aa67a4a9fa90905d837a3ef3a45 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * msg.c - Message/communcation manager for Wiki plugin
  3. *****************************************************************************
  4. * Copyright (C) 2006-2007 The Regents of the University of California.
  5. * Copyright (C) 2008-2009 Lawrence Livermore National Security.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by 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. #include "slurm/slurm.h"
  40. #include "src/common/uid.h"
  41. #include "src/slurmctld/locks.h"
  42. #include "src/plugins/sched/wiki/crypto.h"
  43. #include "src/plugins/sched/wiki/msg.h"
  44. #define _DEBUG 0
  45. static bool thread_running = false;
  46. static bool thread_shutdown = false;
  47. static pthread_mutex_t thread_flag_mutex = PTHREAD_MUTEX_INITIALIZER;
  48. static pthread_t msg_thread_id;
  49. static char *err_msg;
  50. static int err_code;
  51. static uint16_t sched_port;
  52. /* Global configuration parameters */
  53. char auth_key[KEY_SIZE] = "";
  54. char e_host[E_HOST_SIZE] = "";
  55. char e_host_bu[E_HOST_SIZE] = "";
  56. uint16_t e_port = 0;
  57. struct part_record *exclude_part_ptr[EXC_PART_CNT];
  58. struct part_record *hide_part_ptr[HIDE_PART_CNT];
  59. struct part_record *hide_part_nodes_ptr[HIDE_PART_CNT];
  60. uint16_t job_aggregation_time = 10; /* Default value is 10 seconds */
  61. uint16_t host_format;
  62. int init_prio_mode = PRIO_HOLD;
  63. uint16_t kill_wait;
  64. uint16_t use_host_exp = 0;
  65. static char * _get_wiki_conf_path(void);
  66. static void * _msg_thread(void *no_data);
  67. static int _parse_msg(char *msg, char **req);
  68. static void _proc_msg(slurm_fd_t new_fd, char *msg);
  69. static size_t _read_bytes(int fd, char *buf, const size_t size);
  70. static char * _recv_msg(slurm_fd_t new_fd);
  71. static size_t _send_msg(slurm_fd_t new_fd, char *buf, size_t size);
  72. static void _send_reply(slurm_fd_t new_fd, char *response);
  73. static size_t _write_bytes(int fd, char *buf, const size_t size);
  74. /*****************************************************************************\
  75. * spawn message hander thread
  76. \*****************************************************************************/
  77. extern int spawn_msg_thread(void)
  78. {
  79. pthread_attr_t thread_attr_msg;
  80. pthread_mutex_lock( &thread_flag_mutex );
  81. if (thread_running) {
  82. error("Wiki thread already running, not starting another");
  83. pthread_mutex_unlock(&thread_flag_mutex);
  84. return SLURM_ERROR;
  85. }
  86. parse_wiki_config();
  87. slurm_attr_init(&thread_attr_msg);
  88. if (pthread_create(&msg_thread_id, &thread_attr_msg,
  89. _msg_thread, NULL))
  90. fatal("pthread_create %m");
  91. slurm_attr_destroy(&thread_attr_msg);
  92. thread_running = true;
  93. pthread_mutex_unlock(&thread_flag_mutex);
  94. return SLURM_SUCCESS;
  95. }
  96. /*****************************************************************************\
  97. * terminate message hander thread
  98. \*****************************************************************************/
  99. extern void term_msg_thread(void)
  100. {
  101. pthread_mutex_lock(&thread_flag_mutex);
  102. if (thread_running) {
  103. int fd;
  104. slurm_addr_t addr;
  105. thread_shutdown = true;
  106. /* Open and close a connection to the wiki listening port.
  107. * Allows slurm_accept_msg_conn() to return in
  108. * _msg_thread() so that it can check the thread_shutdown
  109. * flag.
  110. */
  111. slurm_set_addr(&addr, sched_port, "localhost");
  112. fd = slurm_open_stream(&addr);
  113. if (fd != -1) {
  114. /* we don't care if the open failed */
  115. slurm_close_stream(fd);
  116. }
  117. debug2("waiting for sched/wiki thread to exit");
  118. pthread_join(msg_thread_id, NULL);
  119. msg_thread_id = 0;
  120. thread_shutdown = false;
  121. thread_running = false;
  122. debug2("join of sched/wiki thread was successful");
  123. }
  124. pthread_mutex_unlock(&thread_flag_mutex);
  125. }
  126. /*****************************************************************************\
  127. * message hander thread
  128. \*****************************************************************************/
  129. static void *_msg_thread(void *no_data)
  130. {
  131. slurm_fd_t sock_fd = -1, new_fd;
  132. slurm_addr_t cli_addr;
  133. char *msg;
  134. slurm_ctl_conf_t *conf;
  135. int i;
  136. /* Locks: Write configuration, job, node, and partition */
  137. slurmctld_lock_t config_write_lock = {
  138. WRITE_LOCK, WRITE_LOCK, WRITE_LOCK, WRITE_LOCK };
  139. conf = slurm_conf_lock();
  140. sched_port = conf->schedport;
  141. slurm_conf_unlock();
  142. /* Wait until configuration is completely loaded */
  143. lock_slurmctld(config_write_lock);
  144. unlock_slurmctld(config_write_lock);
  145. /* If SchedulerPort is already taken, keep trying to open it
  146. * once per minute. Slurmctld will continue to function
  147. * during this interval even if nothing can be scheduled. */
  148. for (i=0; (!thread_shutdown); i++) {
  149. if (i > 0)
  150. sleep(60);
  151. sock_fd = slurm_init_msg_engine_port(sched_port);
  152. if (sock_fd != SLURM_SOCKET_ERROR)
  153. break;
  154. error("wiki: slurm_init_msg_engine_port %u %m",
  155. sched_port);
  156. error("wiki: Unable to communicate with Moab");
  157. }
  158. /* Process incoming RPCs until told to shutdown */
  159. while (!thread_shutdown) {
  160. if ((new_fd = slurm_accept_msg_conn(sock_fd, &cli_addr))
  161. == SLURM_SOCKET_ERROR) {
  162. if (errno != EINTR)
  163. error("wiki: slurm_accept_msg_conn %m");
  164. continue;
  165. }
  166. if (thread_shutdown) {
  167. close(new_fd);
  168. break;
  169. }
  170. /* It would be nice to create a pthread for each new
  171. * RPC, but that leaks memory on some systems when
  172. * done from a plugin.
  173. * FIXME: Maintain a pool of and reuse them. */
  174. err_code = 0;
  175. err_msg = "";
  176. msg = _recv_msg(new_fd);
  177. if (msg) {
  178. _proc_msg(new_fd, msg);
  179. xfree(msg);
  180. }
  181. slurm_close_accepted_conn(new_fd);
  182. }
  183. if (sock_fd > 0)
  184. (void) slurm_shutdown_msg_engine(sock_fd);
  185. pthread_exit((void *) 0);
  186. return NULL;
  187. }
  188. /*****************************************************************************\
  189. * _get_wiki_conf_path - return the pathname of the wiki.conf file
  190. * return value must be xfreed
  191. \*****************************************************************************/
  192. static char * _get_wiki_conf_path(void)
  193. {
  194. char *val = getenv("SLURM_CONF");
  195. char *path = NULL;
  196. int i;
  197. if (!val)
  198. val = default_slurm_config_file;
  199. /* Replace file name on end of path */
  200. i = strlen(val) + 10;
  201. path = xmalloc(i);
  202. strcpy(path, val);
  203. val = strrchr(path, (int)'/');
  204. if (val) /* absolute path */
  205. val++;
  206. else /* not absolute path */
  207. val = path;
  208. strcpy(val, "wiki.conf");
  209. return path;
  210. }
  211. /*****************************************************************************\
  212. * parse_wiki_config - Results go into global variables
  213. * RET SLURM_SUCESS or error code
  214. *
  215. * wiki_conf options
  216. * JobPriority=hold|run
  217. * AuthKey=number
  218. \*****************************************************************************/
  219. extern int parse_wiki_config(void)
  220. {
  221. s_p_options_t options[] = {
  222. {"AuthKey", S_P_STRING},
  223. {"EHost", S_P_STRING},
  224. {"EHostBackup", S_P_STRING},
  225. {"EPort", S_P_UINT16},
  226. {"ExcludePartitions", S_P_STRING},
  227. {"HidePartitionJobs", S_P_STRING},
  228. {"HidePartitionNodes", S_P_STRING},
  229. {"HostFormat", S_P_UINT16},
  230. {"JobAggregationTime", S_P_UINT16},
  231. {"JobPriority", S_P_STRING},
  232. {NULL} };
  233. s_p_hashtbl_t *tbl;
  234. char *exclude_partitions, *hide_partitions, *hide_part_nodes;
  235. char *key = NULL, *priority_mode = NULL, *wiki_conf;
  236. struct stat buf;
  237. slurm_ctl_conf_t *conf;
  238. int i;
  239. /* Set default values */
  240. for (i=0; i<EXC_PART_CNT; i++)
  241. exclude_part_ptr[i] = NULL;
  242. for (i=0; i<HIDE_PART_CNT; i++)
  243. hide_part_ptr[i] = NULL;
  244. for (i=0; i<HIDE_PART_CNT; i++)
  245. hide_part_nodes_ptr[i] = NULL;
  246. conf = slurm_conf_lock();
  247. strncpy(e_host, conf->control_addr, sizeof(e_host));
  248. if (conf->backup_addr) {
  249. strncpy(e_host_bu, conf->backup_addr,
  250. sizeof(e_host));
  251. }
  252. kill_wait = conf->kill_wait;
  253. slurm_conf_unlock();
  254. wiki_conf = _get_wiki_conf_path();
  255. if ((wiki_conf == NULL) || (stat(wiki_conf, &buf) == -1)) {
  256. debug("No wiki.conf file (%s)", wiki_conf);
  257. xfree(wiki_conf);
  258. return SLURM_SUCCESS;
  259. }
  260. debug("Reading wiki.conf file (%s)",wiki_conf);
  261. tbl = s_p_hashtbl_create(options);
  262. if (s_p_parse_file(tbl, NULL, wiki_conf, false) == SLURM_ERROR)
  263. fatal("something wrong with opening/reading wiki.conf file");
  264. if (! s_p_get_string(&key, "AuthKey", tbl))
  265. debug("Warning: No wiki_conf AuthKey specified");
  266. else {
  267. strncpy(auth_key, key, sizeof(auth_key));
  268. xfree(key);
  269. }
  270. if ( s_p_get_string(&key, "EHost", tbl)) {
  271. strncpy(e_host, key, sizeof(e_host));
  272. xfree(key);
  273. } else
  274. debug("wiki: Using ControlAddr for EHost value");
  275. if ( s_p_get_string(&key, "EHostBackup", tbl)) {
  276. strncpy(e_host_bu, key, sizeof(e_host_bu));
  277. xfree(key);
  278. }
  279. s_p_get_uint16(&e_port, "EPort", tbl);
  280. if (s_p_get_uint16(&job_aggregation_time, "JobAggregationTime", tbl))
  281. error("JobAggregationTime not used by sched/wiki");
  282. if (s_p_get_uint16(&host_format, "HostFormat", tbl))
  283. error("HostFormat not used by sched/wiki");
  284. if (s_p_get_string(&exclude_partitions, "ExcludePartitions", tbl)) {
  285. char *tok = NULL, *tok_p = NULL;
  286. tok = strtok_r(exclude_partitions, ",", &tok_p);
  287. i = 0;
  288. while (tok) {
  289. if (i >= EXC_PART_CNT) {
  290. error("ExcludePartitions has too many entries "
  291. "skipping %s and later entries", tok);
  292. break;
  293. }
  294. exclude_part_ptr[i] = find_part_record(tok);
  295. if (exclude_part_ptr[i])
  296. i++;
  297. else
  298. error("ExcludePartitions %s not found", tok);
  299. tok = strtok_r(NULL, ",", &tok_p);
  300. }
  301. }
  302. if (s_p_get_string(&hide_partitions, "HidePartitionJobs", tbl)) {
  303. char *tok = NULL, *tok_p = NULL;
  304. tok = strtok_r(hide_partitions, ",", &tok_p);
  305. i = 0;
  306. while (tok) {
  307. if (i >= HIDE_PART_CNT) {
  308. error("HidePartitionJobs has too many entries "
  309. "skipping %s and later entries", tok);
  310. break;
  311. }
  312. hide_part_ptr[i] = find_part_record(tok);
  313. if (hide_part_ptr[i])
  314. i++;
  315. else
  316. error("HidePartitionJobs %s not found", tok);
  317. tok = strtok_r(NULL, ",", &tok_p);
  318. }
  319. }
  320. if (s_p_get_string(&hide_part_nodes, "HidePartitionNodes", tbl)) {
  321. char *tok = NULL, *tok_p = NULL;
  322. tok = strtok_r(hide_part_nodes, ",", &tok_p);
  323. i = 0;
  324. while (tok) {
  325. if (i >= HIDE_PART_CNT) {
  326. error("HidePartitionNodes has too many entries "
  327. "skipping %s and later entries", tok);
  328. break;
  329. }
  330. hide_part_nodes_ptr[i] = find_part_record(tok);
  331. if (hide_part_nodes_ptr[i])
  332. i++;
  333. else
  334. error("HidePartitionNodes %s not found", tok);
  335. tok = strtok_r(NULL, ",", &tok_p);
  336. }
  337. }
  338. if (s_p_get_string(&priority_mode, "JobPriority", tbl)) {
  339. if (strcasecmp(priority_mode, "hold") == 0)
  340. init_prio_mode = PRIO_HOLD;
  341. else if (strcasecmp(priority_mode, "run") == 0)
  342. init_prio_mode = PRIO_DECREMENT;
  343. else
  344. error("Invalid value for JobPriority in wiki.conf");
  345. xfree(priority_mode);
  346. }
  347. s_p_hashtbl_destroy(tbl);
  348. xfree(wiki_conf);
  349. #if _DEBUG
  350. info("AuthKey = %s", auth_key);
  351. info("EHost = %s", e_host);
  352. info("EHostBackup = %s", e_host_bu);
  353. info("EPort = %u", e_port);
  354. info("JobAggregationTime = %u sec", job_aggregation_time);
  355. info("JobPriority = %s", init_prio_mode ? "run" : "hold");
  356. info("KillWait = %u sec", kill_wait);
  357. for (i=0; i<EXC_PART_CNT; i++) {
  358. if (!exclude_part_ptr[i])
  359. continue;
  360. info("ExcludePartitions = %s", exclude_part_ptr[i]->name);
  361. }
  362. for (i=0; i<HIDE_PART_CNT; i++) {
  363. if (!hide_part_ptr[i])
  364. continue;
  365. info("HidePartitionJobs = %s", hide_part_ptr[i]->name);
  366. }
  367. for (i=0; i<HIDE_PART_CNT; i++) {
  368. if (!hide_part_nodes_ptr[i])
  369. continue;
  370. info("HidePartitionNodes = %s", hide_part_nodes_ptr[i]->name);
  371. }
  372. #endif
  373. return SLURM_SUCCESS;
  374. }
  375. extern char * get_wiki_conf(void)
  376. {
  377. int i, first;
  378. char buf[32], *conf = NULL;
  379. snprintf(buf, sizeof(buf), "HostFormat=%u", use_host_exp);
  380. xstrcat(conf, buf);
  381. snprintf(buf, sizeof(buf), ";JobAggregationTime=%u",
  382. job_aggregation_time);
  383. xstrcat(conf, buf);
  384. first = 1;
  385. for (i=0; i<EXC_PART_CNT; i++) {
  386. if (!exclude_part_ptr[i])
  387. continue;
  388. if (first) {
  389. xstrcat(conf, ";ExcludePartitions=");
  390. first = 0;
  391. } else
  392. xstrcat(conf, ",");
  393. xstrcat(conf, exclude_part_ptr[i]->name);
  394. }
  395. first = 1;
  396. for (i=0; i<HIDE_PART_CNT; i++) {
  397. if (!hide_part_ptr[i])
  398. continue;
  399. if (first) {
  400. xstrcat(conf, ";HidePartitionJobs=");
  401. first = 0;
  402. } else
  403. xstrcat(conf, ",");
  404. xstrcat(conf, hide_part_ptr[i]->name);
  405. }
  406. first = 1;
  407. for (i=0; i<HIDE_PART_CNT; i++) {
  408. if (!hide_part_nodes_ptr[i])
  409. continue;
  410. if (first) {
  411. xstrcat(conf, ";HidePartitionNodes=");
  412. first = 0;
  413. } else
  414. xstrcat(conf, ",");
  415. xstrcat(conf, hide_part_nodes_ptr[i]->name);
  416. }
  417. return conf;
  418. }
  419. static size_t _read_bytes(int fd, char *buf, const size_t size)
  420. {
  421. size_t bytes_remaining, bytes_read;
  422. char *ptr;
  423. bytes_remaining = size;
  424. ptr = buf;
  425. while (bytes_remaining > 0) {
  426. bytes_read = read(fd, ptr, bytes_remaining);
  427. if (bytes_read <= 0)
  428. return 0;
  429. bytes_remaining -= bytes_read;
  430. ptr += bytes_read;
  431. }
  432. return size;
  433. }
  434. static size_t _write_bytes(int fd, char *buf, const size_t size)
  435. {
  436. size_t bytes_remaining, bytes_written;
  437. char *ptr;
  438. bytes_remaining = size;
  439. ptr = buf;
  440. while (bytes_remaining > 0) {
  441. bytes_written = write(fd, ptr, bytes_remaining);
  442. if (bytes_written <= 0)
  443. return (size - bytes_remaining);
  444. bytes_remaining -= bytes_written;
  445. ptr += bytes_written;
  446. }
  447. return size;
  448. }
  449. /*****************************************************************************\
  450. * Read a message (request) from specified file descriptor
  451. *
  452. * RET - The message which must be xfreed or
  453. * NULL on error
  454. \*****************************************************************************/
  455. static char * _recv_msg(slurm_fd_t new_fd)
  456. {
  457. char header[10];
  458. unsigned long size;
  459. char *buf;
  460. if (_read_bytes((int) new_fd, header, 9) != 9) {
  461. err_code = -240;
  462. err_msg = "failed to read message header";
  463. error("wiki: failed to read message header %m");
  464. return NULL;
  465. }
  466. if (sscanf(header, "%lu", &size) != 1) {
  467. err_code = -244;
  468. err_msg = "malformed message header";
  469. error("wiki: malformed message header (%s)", header);
  470. return NULL;
  471. }
  472. buf = xmalloc(size + 1); /* need '\0' on end to print */
  473. if (_read_bytes((int) new_fd, buf, size) != size) {
  474. err_code = -246;
  475. err_msg = "unable to read all message data";
  476. error("wiki: unable to read data message");
  477. xfree(buf);
  478. return NULL;
  479. }
  480. if (slurm_get_debug_flags() & DEBUG_FLAG_WIKI)
  481. info("wiki msg recv:%s", buf);
  482. return buf;
  483. }
  484. /*****************************************************************************\
  485. * Send a message (response) to specified file descriptor
  486. *
  487. * RET - Number of data bytes written (excludes header)
  488. \*****************************************************************************/
  489. static size_t _send_msg(slurm_fd_t new_fd, char *buf, size_t size)
  490. {
  491. char header[10];
  492. size_t data_sent;
  493. if (slurm_get_debug_flags() & DEBUG_FLAG_WIKI)
  494. info("wiki msg send:%s", buf);
  495. (void) sprintf(header, "%08lu\n", (unsigned long) size);
  496. if (_write_bytes((int) new_fd, header, 9) != 9) {
  497. error("wiki: failed to write message header %m");
  498. return 0;
  499. }
  500. data_sent = _write_bytes((int) new_fd, buf, size);
  501. if (data_sent != size) {
  502. error("wiki: unable to write data message (%lu of %lu) %m",
  503. (long unsigned) data_sent, (long unsigned) size);
  504. }
  505. return data_sent;
  506. }
  507. /*****************************************************************************\
  508. * Parse and checksum a wiki request
  509. * msg IN - message to parse
  510. * req OUT - pointer the request portion of the message
  511. * RET 0 on success, -1 on error
  512. \*****************************************************************************/
  513. static int _parse_msg(char *msg, char **req)
  514. {
  515. char *auth_ptr = strstr(msg, "AUTH=");
  516. char *dt_ptr = strstr(msg, "DT=");
  517. char *ts_ptr = strstr(msg, "TS=");
  518. char *cmd_ptr = strstr(msg, "CMD=");
  519. time_t ts, now = time(NULL);
  520. uint32_t delta_t;
  521. if ((auth_key[0] == '\0') && cmd_ptr) {
  522. /* No authentication required */
  523. *req = cmd_ptr;
  524. return 0;
  525. }
  526. if (!auth_ptr) {
  527. err_code = -300;
  528. err_msg = "request lacks AUTH";
  529. error("wiki: request lacks AUTH=");
  530. return -1;
  531. }
  532. if (!dt_ptr) {
  533. err_code = -300;
  534. err_msg = "request lacks DT";
  535. error("wiki: request lacks DT=");
  536. return -1;
  537. }
  538. if (!ts_ptr) {
  539. err_code = -300;
  540. err_msg = "request lacks TS";
  541. error("wiki: request lacks TS=");
  542. return -1;
  543. }
  544. ts = strtoul((ts_ptr+3), NULL, 10);
  545. if (ts < now)
  546. delta_t = (uint32_t) difftime(now, ts);
  547. else
  548. delta_t = (uint32_t) difftime(ts, now);
  549. if (delta_t > 300) {
  550. err_code = -350;
  551. err_msg = "TS value too far from NOW";
  552. error("wiki: TimeStamp too far from NOW (%u secs)",
  553. delta_t);
  554. return -1;
  555. }
  556. #if 0
  557. /* Old wiki interface does not require checksum
  558. * (actually a cryptographic signature) on incoming
  559. * messages. NOTE: This is not secure! */
  560. if (auth_key[0] != '\0') {
  561. char sum[20]; /* format is "CK=%08x08x" */
  562. checksum(sum, auth_key, ts_ptr);
  563. if (strncmp(sum, msg, 19) != 0) {
  564. err_code = -422;
  565. err_msg = "bad checksum";
  566. error("wiki: message checksum error, "
  567. "check AuthKey in wiki.conf");
  568. return -1;
  569. }
  570. }
  571. #endif
  572. *req = dt_ptr + 3;
  573. return 0;
  574. }
  575. /*****************************************************************************\
  576. * Parse, process and respond to a request
  577. \*****************************************************************************/
  578. static void _proc_msg(slurm_fd_t new_fd, char *msg)
  579. {
  580. DEF_TIMERS;
  581. char *req, *cmd_ptr, *msg_type = NULL;
  582. char response[128];
  583. if (new_fd < 0)
  584. return;
  585. START_TIMER;
  586. if (!msg) {
  587. err_code = -300;
  588. err_msg = "NULL request message";
  589. error("wiki: NULL request message");
  590. goto resp_msg;
  591. }
  592. if (_parse_msg(msg, &req) != 0)
  593. goto resp_msg;
  594. cmd_ptr = strstr(req, "CMD=");
  595. if (cmd_ptr == NULL) {
  596. err_code = -300;
  597. err_msg = "request lacks CMD";
  598. error("wiki: request lacks CMD");
  599. goto resp_msg;
  600. }
  601. cmd_ptr +=4;
  602. err_code = 0;
  603. if (strncmp(cmd_ptr, "GETJOBS", 7) == 0) {
  604. msg_type = "wiki:GETJOBS";
  605. if (!get_jobs(cmd_ptr, &err_code, &err_msg))
  606. goto free_resp_msg;
  607. } else if (strncmp(cmd_ptr, "GETNODES", 8) == 0) {
  608. msg_type = "wiki:GETNODES";
  609. if (!get_nodes(cmd_ptr, &err_code, &err_msg))
  610. goto free_resp_msg;
  611. } else if (strncmp(cmd_ptr, "STARTJOB", 8) == 0) {
  612. msg_type = "wiki:STARTJOB";
  613. start_job(cmd_ptr, &err_code, &err_msg);
  614. } else if (strncmp(cmd_ptr, "CANCELJOB", 9) == 0) {
  615. msg_type = "wiki:CANCELJOB";
  616. cancel_job(cmd_ptr, &err_code, &err_msg);
  617. } else if (strncmp(cmd_ptr, "SUSPENDJOB", 10) == 0) {
  618. msg_type = "wiki:SUSPENDJOB";
  619. suspend_job(cmd_ptr, &err_code, &err_msg);
  620. } else if (strncmp(cmd_ptr, "RESUMEJOB", 9) == 0) {
  621. msg_type = "wiki:RESUMEJOB";
  622. resume_job(cmd_ptr, &err_code, &err_msg);
  623. } else if (strncmp(cmd_ptr, "MODIFYJOB", 9) == 0) {
  624. msg_type = "wiki:MODIFYJOB";
  625. job_modify_wiki(cmd_ptr, &err_code, &err_msg);
  626. } else {
  627. err_code = -300;
  628. err_msg = "unsupported request type";
  629. error("wiki: unrecognized request type: %s", req);
  630. }
  631. END_TIMER2(msg_type);
  632. resp_msg:
  633. snprintf(response, sizeof(response),
  634. "SC=%d RESPONSE=%s", err_code, err_msg);
  635. _send_reply(new_fd, response);
  636. return;
  637. free_resp_msg:
  638. /* Message is pre-formatted by get_jobs and get_nodes
  639. * ONLY if no error. Send message and xfree the buffer. */
  640. _send_reply(new_fd, err_msg);
  641. xfree(err_msg);
  642. return;
  643. }
  644. static void _send_reply(slurm_fd_t new_fd, char *response)
  645. {
  646. size_t i;
  647. char *buf, sum[20], *tmp;
  648. static char uname[64] = "";
  649. i = strlen(response);
  650. i += 100; /* leave room for header */
  651. buf = xmalloc(i);
  652. if (uname[0] == '\0') {
  653. tmp = uid_to_string(getuid());
  654. strncpy(uname, tmp, sizeof(uname));
  655. uname[sizeof(uname) - 1] = '\0';
  656. xfree(tmp);
  657. }
  658. snprintf(buf, i, "CK=dummy67890123456 TS=%u AUTH=%s DT=%s",
  659. (uint32_t) time(NULL), uname, response);
  660. checksum(sum, auth_key, (buf+20)); /* overwrite "CK=dummy..." above */
  661. memcpy(buf, sum, 19);
  662. i = strlen(buf) + 1;
  663. (void) _send_msg(new_fd, buf, i);
  664. xfree(buf);
  665. }