1 /*****************************************************************************\
2 * slurm_protocol_api.c - high-level slurm communication functions
3 *****************************************************************************
4 * Copyright (C) 2002-2007 The Regents of the University of California.
5 * Copyright (C) 2008-2010 Lawrence Livermore National Security.
6 * Copyright (C) 2010-2015 SchedMD LLC.
7 * Copyright (C) 2013 Intel, Inc.
8 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
9 * Written by Kevin Tew <tew1@llnl.gov>, et. al.
10 * CODE-OCEC-09-009. All rights reserved.
11 *
12 * This file is part of Slurm, a resource management program.
13 * For details, see <https://slurm.schedmd.com/>.
14 * Please also read the included file: DISCLAIMER.
15 *
16 * Slurm is free software; you can redistribute it and/or modify it under
17 * the terms of the GNU General Public License as published by the Free
18 * Software Foundation; either version 2 of the License, or (at your option)
19 * any later version.
20 *
21 * In addition, as a special exception, the copyright holders give permission
22 * to link the code of portions of this program with the OpenSSL library under
23 * certain conditions as described in each individual source file, and
24 * distribute linked combinations including the two. You must obey the GNU
25 * General Public License in all respects for all of the code used other than
26 * OpenSSL. If you modify file(s) with this exception, you may extend this
27 * exception to your version of the file(s), but you are not obligated to do
28 * so. If you do not wish to do so, delete this exception statement from your
29 * version. If you delete this exception statement from all source files in
30 * the program, then also delete it here.
31 *
32 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
33 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
35 * details.
36 *
37 * You should have received a copy of the GNU General Public License along
38 * with Slurm; if not, write to the Free Software Foundation, Inc.,
39 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 \*****************************************************************************/
41
42 #include "config.h"
43
44 /* GLOBAL INCLUDES */
45
46 #include <ctype.h>
47 #include <errno.h>
48 #include <poll.h>
49 #include <pthread.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sys/stat.h>
54 #include <sys/types.h>
55 #include <time.h>
56 #include <unistd.h>
57
58 /* PROJECT INCLUDES */
59 #include "src/common/assoc_mgr.h"
60 #include "src/common/fd.h"
61 #include "src/common/forward.h"
62 #include "src/common/log.h"
63 #include "src/common/macros.h"
64 #include "src/common/msg_aggr.h"
65 #include "src/common/pack.h"
66 #include "src/common/read_config.h"
67 #include "src/common/slurm_accounting_storage.h"
68 #include "src/common/slurm_auth.h"
69 #include "src/common/slurm_protocol_interface.h"
70 #include "src/common/slurm_protocol_api.h"
71 #include "src/common/slurm_protocol_common.h"
72 #include "src/common/slurm_protocol_pack.h"
73 #include "src/common/slurm_route.h"
74 #include "src/common/strlcpy.h"
75 #include "src/common/xmalloc.h"
76 #include "src/common/xstring.h"
77 #include "src/slurmdbd/read_config.h"
78
79 strong_alias(convert_num_unit2, slurm_convert_num_unit2);
80 strong_alias(convert_num_unit, slurm_convert_num_unit);
81 strong_alias(revert_num_unit, slurm_revert_num_unit);
82 strong_alias(get_convert_unit_val, slurm_get_convert_unit_val);
83 strong_alias(get_unit_type, slurm_get_unit_type);
84
85 /* EXTERNAL VARIABLES */
86
87 /* #DEFINES */
88 #define _DEBUG 0
89
90 /* STATIC VARIABLES */
91 static int message_timeout = -1;
92
93 /* STATIC FUNCTIONS */
94 static char *_global_auth_key(void);
95 static void _remap_slurmctld_errno(void);
96 static int _unpack_msg_uid(Buf buffer, uint16_t protocol_version);
97 static bool _is_port_ok(int, uint16_t, bool);
98
99 #if _DEBUG
100 static void _print_data(char *data, int len);
101 #endif
102
103 /* define slurmdbd_conf here so we can treat its existence as a flag */
104 slurmdbd_conf_t *slurmdbd_conf = NULL;
105
106 /**********************************************************************\
107 * protocol configuration functions
108 \**********************************************************************/
109
110 /* Free memory space returned by _slurm_api_get_comm_config() */
_slurm_api_free_comm_config(slurm_protocol_config_t * proto_conf)111 static void _slurm_api_free_comm_config(slurm_protocol_config_t *proto_conf)
112 {
113 if (proto_conf) {
114 xfree(proto_conf->controller_addr);
115 xfree(proto_conf);
116 }
117 }
118
119 /*
120 * Get communication data structure based upon configuration file
121 * RET communication information structure, call _slurm_api_free_comm_config
122 * to release allocated memory
123 */
_slurm_api_get_comm_config(void)124 static slurm_protocol_config_t *_slurm_api_get_comm_config(void)
125 {
126 slurm_protocol_config_t *proto_conf = NULL;
127 slurm_addr_t controller_addr;
128 slurm_ctl_conf_t *conf;
129 int i;
130
131 conf = slurm_conf_lock();
132
133 if (!conf->control_cnt ||
134 !conf->control_addr || !conf->control_addr[0]) {
135 error("Unable to establish controller machine");
136 goto cleanup;
137 }
138 if (conf->slurmctld_port == 0) {
139 error("Unable to establish controller port");
140 goto cleanup;
141 }
142 if (conf->control_cnt == 0) {
143 error("No slurmctld servers configured");
144 goto cleanup;
145 }
146
147 memset(&controller_addr, 0, sizeof(slurm_addr_t));
148 slurm_set_addr(&controller_addr, conf->slurmctld_port,
149 conf->control_addr[0]);
150 if (controller_addr.sin_port == 0) {
151 error("Unable to establish control machine address");
152 goto cleanup;
153 }
154
155 proto_conf = xmalloc(sizeof(slurm_protocol_config_t));
156 proto_conf->controller_addr = xcalloc(conf->control_cnt,
157 sizeof(slurm_addr_t));
158 proto_conf->control_cnt = conf->control_cnt;
159 memcpy(&proto_conf->controller_addr[0], &controller_addr,
160 sizeof(slurm_addr_t));
161
162 for (i = 1; i < proto_conf->control_cnt; i++) {
163 if (conf->control_addr[i]) {
164 slurm_set_addr(&proto_conf->controller_addr[i],
165 conf->slurmctld_port,
166 conf->control_addr[i]);
167 }
168 }
169
170 if (conf->slurmctld_addr) {
171 proto_conf->vip_addr_set = true;
172 slurm_set_addr(&proto_conf->vip_addr, conf->slurmctld_port,
173 conf->slurmctld_addr);
174 }
175
176 cleanup:
177 slurm_conf_unlock();
178 return proto_conf;
179 }
180
181 /* slurm_api_clear_config
182 * execute this only at program termination to free all memory */
slurm_api_clear_config(void)183 void slurm_api_clear_config(void)
184 {
185 slurm_conf_destroy();
186 }
187
188 /* slurm_get_complete_wait
189 * RET CompleteWait value from slurm.conf
190 */
slurm_get_complete_wait(void)191 uint16_t slurm_get_complete_wait(void)
192 {
193 uint16_t complete_wait = 0;
194 slurm_ctl_conf_t *conf;
195
196 if (slurmdbd_conf) {
197 } else {
198 conf = slurm_conf_lock();
199 complete_wait = conf->complete_wait;
200 slurm_conf_unlock();
201 }
202 return complete_wait;
203 }
204
205 /* slurm_get_cpu_freq_def
206 * RET CpuFreqDef value from slurm.conf
207 */
slurm_get_cpu_freq_def(void)208 uint32_t slurm_get_cpu_freq_def(void)
209 {
210 uint32_t cpu_freq_def = 0;
211 slurm_ctl_conf_t *conf;
212
213 if (slurmdbd_conf) {
214 } else {
215 conf = slurm_conf_lock();
216 cpu_freq_def = conf->cpu_freq_def;
217 slurm_conf_unlock();
218 }
219 return cpu_freq_def;
220 }
221
222 /* slurm_get_cpu_freq_govs
223 * RET CpuFreqGovernors value from slurm.conf
224 */
slurm_get_cpu_freq_govs(void)225 uint32_t slurm_get_cpu_freq_govs(void)
226 {
227 uint32_t cpu_freq_govs = 0;
228 slurm_ctl_conf_t *conf;
229
230 if (slurmdbd_conf) {
231 } else {
232 conf = slurm_conf_lock();
233 cpu_freq_govs = conf->cpu_freq_govs;
234 slurm_conf_unlock();
235 }
236 return cpu_freq_govs;
237 }
238
239 /* slurm_get_batch_start_timeout
240 * RET BatchStartTimeout value from slurm.conf
241 */
slurm_get_batch_start_timeout(void)242 uint16_t slurm_get_batch_start_timeout(void)
243 {
244 uint16_t batch_start_timeout = 0;
245 slurm_ctl_conf_t *conf;
246
247 if (slurmdbd_conf) {
248 } else {
249 conf = slurm_conf_lock();
250 batch_start_timeout = conf->batch_start_timeout;
251 slurm_conf_unlock();
252 }
253 return batch_start_timeout;
254 }
255
256 /*
257 * slurm_get_control_cnt
258 * RET Count of SlurmctldHost records from slurm.conf
259 * (slurmctld server count, primary plus backups)
260 */
slurm_get_control_cnt(void)261 uint32_t slurm_get_control_cnt(void)
262 {
263 uint32_t control_cnt = 0;
264 slurm_ctl_conf_t *conf;
265
266 if (slurmdbd_conf) {
267 } else {
268 conf = slurm_conf_lock();
269 control_cnt = conf->control_cnt;
270 slurm_conf_unlock();
271 }
272 return control_cnt;
273 }
274
275 /* slurm_get_suspend_timeout
276 * RET SuspendTimeout value from slurm.conf
277 */
slurm_get_suspend_timeout(void)278 uint16_t slurm_get_suspend_timeout(void)
279 {
280 uint16_t suspend_timeout = 0;
281 slurm_ctl_conf_t *conf;
282
283 if (slurmdbd_conf) {
284 } else {
285 conf = slurm_conf_lock();
286 suspend_timeout = conf->suspend_timeout;
287 slurm_conf_unlock();
288 }
289 return suspend_timeout;
290 }
291
292 /* slurm_get_resume_timeout
293 * RET ResumeTimeout value from slurm.conf
294 */
slurm_get_resume_timeout(void)295 uint16_t slurm_get_resume_timeout(void)
296 {
297 uint16_t resume_timeout = 0;
298 slurm_ctl_conf_t *conf;
299
300 if (slurmdbd_conf) {
301 } else {
302 conf = slurm_conf_lock();
303 resume_timeout = conf->resume_timeout;
304 slurm_conf_unlock();
305 }
306 return resume_timeout;
307 }
308
309 /* slurm_get_suspend_time
310 * RET SuspendTime value from slurm.conf
311 */
slurm_get_suspend_time(void)312 uint32_t slurm_get_suspend_time(void)
313 {
314 uint32_t suspend_time = 0;
315 slurm_ctl_conf_t *conf;
316
317 if (slurmdbd_conf) {
318 } else {
319 conf = slurm_conf_lock();
320 suspend_time = conf->suspend_time;
321 slurm_conf_unlock();
322 }
323 return suspend_time;
324 }
325
326 /* slurm_get_def_mem_per_cpu
327 * RET DefMemPerCPU/Node value from slurm.conf
328 */
slurm_get_def_mem_per_cpu(void)329 uint64_t slurm_get_def_mem_per_cpu(void)
330 {
331 uint64_t mem_per_cpu = 0;
332 slurm_ctl_conf_t *conf;
333
334 if (slurmdbd_conf) {
335 } else {
336 conf = slurm_conf_lock();
337 mem_per_cpu = conf->def_mem_per_cpu;
338 slurm_conf_unlock();
339 }
340 return mem_per_cpu;
341 }
342
343 /* slurm_get_kill_on_bad_exit
344 * RET KillOnBadExit value from slurm.conf
345 */
slurm_get_kill_on_bad_exit(void)346 uint16_t slurm_get_kill_on_bad_exit(void)
347 {
348 uint16_t kill_on_bad_exit = 0;
349 slurm_ctl_conf_t *conf;
350
351 if (slurmdbd_conf) {
352 } else {
353 conf = slurm_conf_lock();
354 kill_on_bad_exit = conf->kill_on_bad_exit;
355 slurm_conf_unlock();
356 }
357 return kill_on_bad_exit;
358 }
359
360 /* slurm_get_prolog_flags
361 * RET PrologFlags value from slurm.conf
362 */
slurm_get_prolog_flags(void)363 uint32_t slurm_get_prolog_flags(void)
364 {
365 uint32_t prolog_flags = 0;
366 slurm_ctl_conf_t *conf;
367
368 if (slurmdbd_conf) {
369 } else {
370 conf = slurm_conf_lock();
371 prolog_flags = conf->prolog_flags;
372 slurm_conf_unlock();
373 }
374 return prolog_flags;
375 }
376
377 /* slurm_get_debug_flags
378 * RET DebugFlags value from slurm.conf
379 */
slurm_get_debug_flags(void)380 uint64_t slurm_get_debug_flags(void)
381 {
382 uint64_t debug_flags = 0;
383 slurm_ctl_conf_t *conf;
384
385 if (slurmdbd_conf) {
386 debug_flags = slurmdbd_conf->debug_flags;
387 } else {
388 conf = slurm_conf_lock();
389 debug_flags = conf->debug_flags;
390 slurm_conf_unlock();
391 }
392 return debug_flags;
393 }
394
395 /* slurm_set_debug_flags
396 */
slurm_set_debug_flags(uint64_t debug_flags)397 void slurm_set_debug_flags(uint64_t debug_flags)
398 {
399 slurm_ctl_conf_t *conf;
400
401 if (slurmdbd_conf) {
402 } else {
403 conf = slurm_conf_lock();
404 conf->debug_flags = debug_flags;
405 slurm_conf_unlock();
406 }
407 }
408
409 /* slurm_get_max_mem_per_cpu
410 * RET MaxMemPerCPU/Node value from slurm.conf
411 */
slurm_get_max_mem_per_cpu(void)412 uint64_t slurm_get_max_mem_per_cpu(void)
413 {
414 uint64_t mem_per_cpu = 0;
415 slurm_ctl_conf_t *conf;
416
417 if (slurmdbd_conf) {
418 } else {
419 conf = slurm_conf_lock();
420 mem_per_cpu = conf->max_mem_per_cpu;
421 slurm_conf_unlock();
422 }
423 return mem_per_cpu;
424 }
425
426 /* slurm_get_epilog_msg_time
427 * RET EpilogMsgTime value from slurm.conf
428 */
slurm_get_epilog_msg_time(void)429 uint32_t slurm_get_epilog_msg_time(void)
430 {
431 uint32_t epilog_msg_time = 0;
432 slurm_ctl_conf_t *conf;
433
434 if (slurmdbd_conf) {
435 } else {
436 conf = slurm_conf_lock();
437 epilog_msg_time = conf->epilog_msg_time;
438 slurm_conf_unlock();
439 }
440 return epilog_msg_time;
441 }
442
443 /* slurm_get_env_timeout
444 * return default timeout for srun/sbatch --get-user-env option
445 */
slurm_get_env_timeout(void)446 extern int slurm_get_env_timeout(void)
447 {
448 int timeout = 0;
449 slurm_ctl_conf_t *conf;
450
451 if (slurmdbd_conf) {
452 } else {
453 conf = slurm_conf_lock();
454 timeout = conf->get_env_timeout;
455 slurm_conf_unlock();
456 }
457 return timeout;
458 }
459
460 /* slurm_get_max_array_size
461 * return MaxArraySize configuration parameter
462 */
slurm_get_max_array_size(void)463 extern uint32_t slurm_get_max_array_size(void)
464 {
465 int max_array_size = 0;
466 slurm_ctl_conf_t *conf;
467
468 if (slurmdbd_conf) {
469 } else {
470 conf = slurm_conf_lock();
471 max_array_size = conf->max_array_sz;
472 slurm_conf_unlock();
473 }
474 return max_array_size;
475 }
476
477
478 /* slurm_get_mpi_default
479 * get default mpi value from slurmctld_conf object
480 * RET char * - mpi default value from slurm.conf, MUST be xfreed by caller
481 */
slurm_get_mpi_default(void)482 char *slurm_get_mpi_default(void)
483 {
484 char *mpi_default = NULL;
485 slurm_ctl_conf_t *conf;
486
487 if (slurmdbd_conf) {
488 } else {
489 conf = slurm_conf_lock();
490 mpi_default = xstrdup(conf->mpi_default);
491 slurm_conf_unlock();
492 }
493 return mpi_default;
494 }
495
496 /* slurm_get_mpi_params
497 * get mpi parameters value from slurmctld_conf object
498 * RET char * - mpi default value from slurm.conf, MUST be xfreed by caller
499 */
slurm_get_mpi_params(void)500 char *slurm_get_mpi_params(void)
501 {
502 char *mpi_params = NULL;
503 slurm_ctl_conf_t *conf;
504
505 if (slurmdbd_conf) {
506 } else {
507 conf = slurm_conf_lock();
508 mpi_params = xstrdup(conf->mpi_params);
509 slurm_conf_unlock();
510 }
511 return mpi_params;
512 }
513
514 /* slurm_get_msg_aggr_params
515 * get message aggregation parameters value from slurmctld_conf object
516 * RET char * - message aggregation value from slurm.conf,
517 * MUST be xfreed by caller
518 */
slurm_get_msg_aggr_params(void)519 char *slurm_get_msg_aggr_params(void)
520 {
521 char *msg_aggr_params = NULL;
522 slurm_ctl_conf_t *conf;
523
524 if (slurmdbd_conf) {
525 } else {
526 conf = slurm_conf_lock();
527 msg_aggr_params = xstrdup(conf->msg_aggr_params);
528 slurm_conf_unlock();
529 }
530 return msg_aggr_params;
531 }
532
533 /* slurm_get_reboot_program
534 * RET char * - RebootProgram from slurm.conf, MUST be xfreed by caller
535 */
slurm_get_reboot_program(void)536 extern char *slurm_get_reboot_program(void)
537 {
538 char *reboot_program = NULL;
539 slurm_ctl_conf_t *conf;
540
541 if (slurmdbd_conf) {
542 } else {
543 conf = slurm_conf_lock();
544 reboot_program = xstrdup(conf->reboot_program);
545 slurm_conf_unlock();
546 }
547 return reboot_program;
548 }
549
550 /* slurm_get_tcp_timeout
551 * get default tcp timeout value from slurmctld_conf object
552 */
slurm_get_tcp_timeout(void)553 uint16_t slurm_get_tcp_timeout(void)
554 {
555 uint16_t tcp_timeout = 0;
556 slurm_ctl_conf_t *conf;
557
558 if (slurmdbd_conf) {
559 tcp_timeout = slurmdbd_conf->tcp_timeout;
560 } else {
561 conf = slurm_conf_lock();
562 tcp_timeout = conf->tcp_timeout;
563 slurm_conf_unlock();
564 }
565 return tcp_timeout;
566 }
567
568 /* slurm_get_msg_timeout
569 * get default message timeout value from slurmctld_conf object
570 */
slurm_get_msg_timeout(void)571 uint16_t slurm_get_msg_timeout(void)
572 {
573 uint16_t msg_timeout = 0;
574 slurm_ctl_conf_t *conf;
575
576 if (slurmdbd_conf) {
577 msg_timeout = slurmdbd_conf->msg_timeout;
578 } else {
579 conf = slurm_conf_lock();
580 msg_timeout = conf->msg_timeout;
581 slurm_conf_unlock();
582 #ifdef MEMORY_LEAK_DEBUG
583 msg_timeout *= 4;
584 #endif
585 }
586 return msg_timeout;
587 }
588
589 /* slurm_get_plugin_dir
590 * get plugin directory from slurmctld_conf object
591 * RET char * - plugin directory, MUST be xfreed by caller
592 */
slurm_get_plugin_dir(void)593 char *slurm_get_plugin_dir(void)
594 {
595 char *plugin_dir = NULL;
596 slurm_ctl_conf_t *conf;
597
598 if (slurmdbd_conf) {
599 plugin_dir = xstrdup(slurmdbd_conf->plugindir);
600 } else {
601 conf = slurm_conf_lock();
602 plugin_dir = xstrdup(conf->plugindir);
603 slurm_conf_unlock();
604 }
605 return plugin_dir;
606 }
607
608 /* slurm_get_priority_decay_hl
609 * returns the priority decay half life in seconds from slurmctld_conf object
610 * RET uint32_t - decay_hl in secs.
611 */
slurm_get_priority_decay_hl(void)612 uint32_t slurm_get_priority_decay_hl(void)
613 {
614 uint32_t priority_hl = NO_VAL;
615 slurm_ctl_conf_t *conf;
616
617 if (slurmdbd_conf) {
618 } else {
619 conf = slurm_conf_lock();
620 priority_hl = conf->priority_decay_hl;
621 slurm_conf_unlock();
622 }
623
624 return priority_hl;
625 }
626
627 /* slurm_get_priority_calc_period
628 * returns the seconds between priority decay calculation from slurmctld_conf
629 * RET uint32_t - calc_period in secs.
630 */
slurm_get_priority_calc_period(void)631 uint32_t slurm_get_priority_calc_period(void)
632 {
633 uint32_t calc_period = NO_VAL;
634 slurm_ctl_conf_t *conf;
635
636 if (slurmdbd_conf) {
637 } else {
638 conf = slurm_conf_lock();
639 calc_period = conf->priority_calc_period;
640 slurm_conf_unlock();
641 }
642
643 return calc_period;
644 }
645
646 /* slurm_get_priority_favor_small
647 * returns weither or not we are favoring small jobs from slurmctld_conf object
648 * RET bool - true if favor small, false else.
649 */
slurm_get_priority_favor_small(void)650 bool slurm_get_priority_favor_small(void)
651 {
652 bool factor = 0;
653 slurm_ctl_conf_t *conf;
654
655 if (slurmdbd_conf) {
656 } else {
657 conf = slurm_conf_lock();
658 factor = conf->priority_favor_small;
659 slurm_conf_unlock();
660 }
661
662 return factor;
663 }
664
665 /* slurm_get_priority_flags
666 * returns the priority flags bitmap from slurmctld_conf object
667 * RET uint16_t - priority flags
668 */
slurm_get_priority_flags(void)669 uint16_t slurm_get_priority_flags(void)
670 {
671 uint16_t flags = 0;
672 slurm_ctl_conf_t *conf;
673
674 if (slurmdbd_conf) {
675 } else {
676 conf = slurm_conf_lock();
677 flags = conf->priority_flags;
678 slurm_conf_unlock();
679 }
680
681 return flags;
682 }
683
684 /* slurm_get_priority_max_age
685 * returns the priority age max in seconds from slurmctld_conf object
686 * RET uint32_t - age_max in secs.
687 */
slurm_get_priority_max_age(void)688 uint32_t slurm_get_priority_max_age(void)
689 {
690 uint32_t age = NO_VAL;
691 slurm_ctl_conf_t *conf;
692
693 if (slurmdbd_conf) {
694 } else {
695 conf = slurm_conf_lock();
696 age = conf->priority_max_age;
697 slurm_conf_unlock();
698 }
699
700 return age;
701 }
702
703 /* slurm_get_priority_params
704 * RET char * - Value of PriorityParameters, MUST be xfreed by caller */
slurm_get_priority_params(void)705 char *slurm_get_priority_params(void)
706 {
707 char *params = 0;
708 slurm_ctl_conf_t *conf;
709
710 if (slurmdbd_conf) {
711 } else {
712 conf = slurm_conf_lock();
713 params = xstrdup(conf->priority_params);
714 slurm_conf_unlock();
715 }
716 return params;
717 }
718
719 /* slurm_get_priority_reset_period
720 * returns the priority usage reset period from slurmctld_conf object
721 * RET uint16_t - flag, see PRIORITY_RESET_* in slurm/slurm.h.
722 */
slurm_get_priority_reset_period(void)723 uint16_t slurm_get_priority_reset_period(void)
724 {
725 uint16_t reset_period = (uint16_t) 0;
726 slurm_ctl_conf_t *conf;
727
728 if (slurmdbd_conf) {
729 } else {
730 conf = slurm_conf_lock();
731 reset_period = conf->priority_reset_period;
732 slurm_conf_unlock();
733 }
734
735 return reset_period;
736 }
737
738 /* slurm_get_priority_site_factor_params
739 * returns the site_factor_params value from slurmctld_conf object
740 * RET char * - site_factor_params, MUST be xfreed by caller
741 */
slurm_get_priority_site_factor_params(void)742 char *slurm_get_priority_site_factor_params(void)
743 {
744 char *params = NULL;
745 slurm_ctl_conf_t *conf;
746
747 if (slurmdbd_conf) {
748 } else {
749 conf = slurm_conf_lock();
750 params = xstrdup(conf->site_factor_params);
751 slurm_conf_unlock();
752 }
753
754 return params;
755 }
756
757 /* slurm_get_priority_site_factor_plugin
758 * returns the site_factor_plugin value from slurmctld_conf object
759 * RET char * - site_factor_plugin, MUST be xfreed by caller
760 */
slurm_get_priority_site_factor_plugin(void)761 char *slurm_get_priority_site_factor_plugin(void)
762 {
763 char *plugin = NULL;
764 slurm_ctl_conf_t *conf;
765
766 if (slurmdbd_conf) {
767 } else {
768 conf = slurm_conf_lock();
769 plugin = xstrdup(conf->site_factor_plugin);
770 slurm_conf_unlock();
771 }
772
773 return plugin;
774 }
775
776 /* slurm_get_priority_type
777 * returns the priority type from slurmctld_conf object
778 * RET char * - priority type, MUST be xfreed by caller
779 */
slurm_get_priority_type(void)780 char *slurm_get_priority_type(void)
781 {
782 char *priority_type = NULL;
783 slurm_ctl_conf_t *conf;
784
785 if (slurmdbd_conf) {
786 } else {
787 conf = slurm_conf_lock();
788 priority_type = xstrdup(conf->priority_type);
789 slurm_conf_unlock();
790 }
791
792 return priority_type;
793 }
794
795 /* slurm_get_priority_weight_age
796 * returns the priority weight for age from slurmctld_conf object
797 * RET uint32_t - factor weight.
798 */
slurm_get_priority_weight_age(void)799 uint32_t slurm_get_priority_weight_age(void)
800 {
801 uint32_t factor = NO_VAL;
802 slurm_ctl_conf_t *conf;
803
804 if (slurmdbd_conf) {
805 } else {
806 conf = slurm_conf_lock();
807 factor = conf->priority_weight_age;
808 slurm_conf_unlock();
809 }
810
811 return factor;
812 }
813
814
815 /* slurm_get_priority_weight_assoc
816 * returns the priority weight for association from slurmctld_conf object
817 * RET uint32_t - factor weight.
818 */
slurm_get_priority_weight_assoc(void)819 uint32_t slurm_get_priority_weight_assoc(void)
820 {
821 uint32_t factor = NO_VAL;
822 slurm_ctl_conf_t *conf;
823
824 if (slurmdbd_conf) {
825 } else {
826 conf = slurm_conf_lock();
827 factor = conf->priority_weight_assoc;
828 slurm_conf_unlock();
829 }
830
831 return factor;
832 }
833
834
835 /* slurm_get_priority_weight_fairshare
836 * returns the priority weight for fairshare from slurmctld_conf object
837 * RET uint32_t - factor weight.
838 */
slurm_get_priority_weight_fairshare(void)839 uint32_t slurm_get_priority_weight_fairshare(void)
840 {
841 uint32_t factor = NO_VAL;
842 slurm_ctl_conf_t *conf;
843
844 if (slurmdbd_conf) {
845 } else {
846 conf = slurm_conf_lock();
847 factor = conf->priority_weight_fs;
848 slurm_conf_unlock();
849 }
850
851 return factor;
852 }
853
854 /* slurm_get_fs_dampening_factor
855 * returns the dampening factor for fairshare from slurmctld_conf object
856 * RET uint32_t - factor.
857 */
slurm_get_fs_dampening_factor(void)858 uint16_t slurm_get_fs_dampening_factor(void)
859 {
860 uint16_t factor = 1;
861 slurm_ctl_conf_t *conf;
862
863 if (slurmdbd_conf) {
864 } else {
865 conf = slurm_conf_lock();
866 factor = conf->fs_dampening_factor;
867 slurm_conf_unlock();
868 }
869
870 return factor;
871 }
872
873 /* slurm_set_fs_dampening_factor
874 * set the dampening factor for fairshare from slurmctld_conf object
875 */
slurm_set_fs_dampening_factor(uint16_t factor)876 void slurm_set_fs_dampening_factor(uint16_t factor)
877 {
878 slurm_ctl_conf_t *conf;
879
880 if (slurmdbd_conf) {
881 } else {
882 conf = slurm_conf_lock();
883 conf->fs_dampening_factor = factor;
884 slurm_conf_unlock();
885 }
886 }
887 /* slurm_get_priority_weight_job_size
888 * returns the priority weight for job size from slurmctld_conf object
889 * RET uint32_t - factor weight.
890 */
slurm_get_priority_weight_job_size(void)891 uint32_t slurm_get_priority_weight_job_size(void)
892 {
893 uint32_t factor = NO_VAL;
894 slurm_ctl_conf_t *conf;
895
896 if (slurmdbd_conf) {
897 } else {
898 conf = slurm_conf_lock();
899 factor = conf->priority_weight_js;
900 slurm_conf_unlock();
901 }
902
903 return factor;
904 }
905
906 /* slurm_get_priority_weight_partition
907 * returns the priority weight for partitions from slurmctld_conf object
908 * RET uint32_t - factor weight.
909 */
slurm_get_priority_weight_partition(void)910 uint32_t slurm_get_priority_weight_partition(void)
911 {
912 uint32_t factor = NO_VAL;
913 slurm_ctl_conf_t *conf;
914
915 if (slurmdbd_conf) {
916 } else {
917 conf = slurm_conf_lock();
918 factor = conf->priority_weight_part;
919 slurm_conf_unlock();
920 }
921
922 return factor;
923 }
924
925
926 /* slurm_get_priority_weight_qos
927 * returns the priority weight for QOS from slurmctld_conf object
928 * RET uint32_t - factor weight.
929 */
slurm_get_priority_weight_qos(void)930 uint32_t slurm_get_priority_weight_qos(void)
931 {
932 uint32_t factor = NO_VAL;
933 slurm_ctl_conf_t *conf;
934
935 if (slurmdbd_conf) {
936 } else {
937 conf = slurm_conf_lock();
938 factor = conf->priority_weight_qos;
939 slurm_conf_unlock();
940 }
941
942 return factor;
943 }
944
945 /* slurm_get_priority_weight_tres
946 * returns the priority weights for TRES' from slurmctld_conf object
947 * RET char * string of configured tres weights. MUST be xfreed by caller
948 */
slurm_get_priority_weight_tres(void)949 char *slurm_get_priority_weight_tres(void)
950 {
951 char *weights = NULL;
952 slurm_ctl_conf_t *conf;
953
954 if (slurmdbd_conf) {
955 } else {
956 conf = slurm_conf_lock();
957 weights = xstrdup(conf->priority_weight_tres);
958 slurm_conf_unlock();
959 }
960
961 return weights;
962 }
963
964 /* slurm_get_prep_plugins
965 * returns the PrEpPlugins from slurmctld_conf object
966 * RET char * - PrEpPlugins, MUST be xfreed by caller
967 */
slurm_get_prep_plugins(void)968 char *slurm_get_prep_plugins(void)
969 {
970 char *plugins = NULL;
971 slurm_ctl_conf_t *conf;
972
973 if (slurmdbd_conf) {
974 } else {
975 conf = slurm_conf_lock();
976 plugins = xstrdup(conf->prep_plugins);
977 slurm_conf_unlock();
978 }
979
980 return plugins;
981 }
982
_get_tres_id(char * type,char * name)983 static int _get_tres_id(char *type, char *name)
984 {
985 slurmdb_tres_rec_t tres_rec;
986 memset(&tres_rec, 0, sizeof(slurmdb_tres_rec_t));
987 tres_rec.type = type;
988 tres_rec.name = name;
989
990 return assoc_mgr_find_tres_pos(&tres_rec, false);
991 }
992
_tres_weight_item(double * weights,char * item_str)993 static int _tres_weight_item(double *weights, char *item_str)
994 {
995 char *type = NULL, *value_str = NULL, *val_unit = NULL, *name = NULL;
996 int tres_id;
997 double weight_value = 0;
998
999 if (!item_str) {
1000 error("TRES weight item is null");
1001 return SLURM_ERROR;
1002 }
1003
1004 type = strtok_r(item_str, "=", &value_str);
1005 if (type == NULL) {
1006 error("\"%s\" is an invalid TRES weight entry", item_str);
1007 return SLURM_ERROR;
1008 }
1009 if (strchr(type, '/'))
1010 type = strtok_r(type, "/", &name);
1011
1012 if (!value_str || !*value_str) {
1013 error("\"%s\" is an invalid TRES weight entry", item_str);
1014 return SLURM_ERROR;
1015 }
1016
1017 if ((tres_id = _get_tres_id(type, name)) == -1) {
1018 error("TRES weight '%s%s%s' is not a configured TRES type.",
1019 type, (name) ? ":" : "", (name) ? name : "");
1020 return SLURM_ERROR;
1021 }
1022
1023 errno = 0;
1024 weight_value = strtod(value_str, &val_unit);
1025 if (errno) {
1026 error("Unable to convert %s value to double in %s",
1027 __func__, value_str);
1028 return SLURM_ERROR;
1029 }
1030
1031 if (val_unit && *val_unit) {
1032 int base_unit = slurmdb_get_tres_base_unit(type);
1033 int convert_val = get_convert_unit_val(base_unit, *val_unit);
1034 if (convert_val == SLURM_ERROR)
1035 return SLURM_ERROR;
1036 if (convert_val > 0) {
1037 weight_value /= convert_val;
1038 }
1039 }
1040
1041 weights[tres_id] = weight_value;
1042
1043 return SLURM_SUCCESS;
1044 }
1045
1046 /* slurm_get_tres_weight_array
1047 * IN weights_str - string of tres and weights to be parsed.
1048 * IN tres_cnt - count of how many tres' are on the system (e.g.
1049 * slurmctld_tres_cnt).
1050 * IN fail - whether to fatal or not if there are parsing errors.
1051 * RET double* of tres weights.
1052 */
slurm_get_tres_weight_array(char * weights_str,int tres_cnt,bool fail)1053 double *slurm_get_tres_weight_array(char *weights_str, int tres_cnt, bool fail)
1054 {
1055 double *weights;
1056 char *tmp_str;
1057 char *token, *last = NULL;
1058
1059 if (!weights_str || !*weights_str || !tres_cnt)
1060 return NULL;
1061
1062 tmp_str = xstrdup(weights_str);
1063 weights = xcalloc(tres_cnt, sizeof(double));
1064
1065 token = strtok_r(tmp_str, ",", &last);
1066 while (token) {
1067 if (_tres_weight_item(weights, token)) {
1068 xfree(weights);
1069 xfree(tmp_str);
1070 if (fail)
1071 fatal("failed to parse tres weights str '%s'",
1072 weights_str);
1073 else
1074 error("failed to parse tres weights str '%s'",
1075 weights_str);
1076 return NULL;
1077 }
1078 token = strtok_r(NULL, ",", &last);
1079 }
1080 xfree(tmp_str);
1081 return weights;
1082 }
1083
1084 /* slurm_get_private_data
1085 * get private data from slurmctld_conf object
1086 */
slurm_get_private_data(void)1087 uint16_t slurm_get_private_data(void)
1088 {
1089 uint16_t private_data = 0;
1090 slurm_ctl_conf_t *conf;
1091
1092 if (slurmdbd_conf) {
1093 private_data = slurmdbd_conf->private_data;
1094 } else {
1095 conf = slurm_conf_lock();
1096 private_data = conf->private_data;
1097 slurm_conf_unlock();
1098 }
1099 return private_data;
1100 }
1101
1102 /* slurm_get_resume_fail_program
1103 * returns the ResumeFailProgram from slurmctld_conf object
1104 * RET char * - ResumeFailProgram, MUST be xfreed by caller
1105 */
slurm_get_resume_fail_program(void)1106 char *slurm_get_resume_fail_program(void)
1107 {
1108 char *resume_fail_program = NULL;
1109 slurm_ctl_conf_t *conf;
1110
1111 if (slurmdbd_conf) {
1112 } else {
1113 conf = slurm_conf_lock();
1114 resume_fail_program = xstrdup(conf->resume_fail_program);
1115 slurm_conf_unlock();
1116 }
1117 return resume_fail_program;
1118 }
1119
1120 /* slurm_get_resume_program
1121 * returns the ResumeProgram from slurmctld_conf object
1122 * RET char * - ResumeProgram, MUST be xfreed by caller
1123 */
slurm_get_resume_program(void)1124 char *slurm_get_resume_program(void)
1125 {
1126 char *resume_program = NULL;
1127 slurm_ctl_conf_t *conf;
1128
1129 if (slurmdbd_conf) {
1130 } else {
1131 conf = slurm_conf_lock();
1132 resume_program = xstrdup(conf->resume_program);
1133 slurm_conf_unlock();
1134 }
1135 return resume_program;
1136 }
1137
1138 /* slurm_get_state_save_location
1139 * get state_save_location from slurmctld_conf object from slurmctld_conf object
1140 * RET char * - state_save_location directory, MUST be xfreed by caller
1141 */
slurm_get_state_save_location(void)1142 char *slurm_get_state_save_location(void)
1143 {
1144 char *state_save_loc = NULL;
1145 slurm_ctl_conf_t *conf;
1146
1147 if (slurmdbd_conf) {
1148 } else {
1149 conf = slurm_conf_lock();
1150 state_save_loc = xstrdup(conf->state_save_location);
1151 slurm_conf_unlock();
1152 }
1153 return state_save_loc;
1154 }
1155
1156 /* slurm_get_stepd_loc
1157 * get path to the slurmstepd
1158 * 1. configure --sbindir concatenated with slurmstepd.
1159 * 2. configure --prefix concatenated with /sbin/slurmstepd.
1160 * RET char * - absolute path to the slurmstepd, MUST be xfreed by caller
1161 */
slurm_get_stepd_loc(void)1162 extern char *slurm_get_stepd_loc(void)
1163 {
1164 #ifdef SBINDIR
1165 return xstrdup_printf("%s/slurmstepd", SBINDIR);
1166 #elif defined SLURM_PREFIX
1167 return xstrdup_printf("%s/sbin/slurmstepd", SLURM_PREFIX);
1168 #endif
1169 }
1170
1171 /* slurm_get_tmp_fs
1172 * returns the TmpFS configuration parameter from slurmctld_conf object
1173 * RET char * - tmp_fs, MUST be xfreed by caller
1174 */
slurm_get_tmp_fs(char * node_name)1175 extern char *slurm_get_tmp_fs(char *node_name)
1176 {
1177 char *tmp_fs = NULL;
1178 slurm_ctl_conf_t *conf = NULL;
1179
1180 if (slurmdbd_conf) {
1181 } else {
1182 conf = slurm_conf_lock();
1183 if (!node_name)
1184 tmp_fs = xstrdup(conf->tmp_fs);
1185 else
1186 tmp_fs = slurm_conf_expand_slurmd_path(
1187 conf->tmp_fs, node_name);
1188 slurm_conf_unlock();
1189 }
1190 return tmp_fs;
1191 }
1192
1193 /* slurm_get_auth_alt_types
1194 * returns the alternate authentication types from slurmctld_conf object
1195 * RET char * - auth alternate types, MUST be xfreed by caller
1196 */
slurm_get_auth_alt_types(void)1197 char *slurm_get_auth_alt_types(void)
1198 {
1199 char *auth_alt_types = NULL;
1200 slurm_ctl_conf_t *conf = NULL;
1201
1202 if (slurmdbd_conf) {
1203 auth_alt_types = xstrdup(slurmdbd_conf->auth_alt_types);
1204 } else {
1205 conf = slurm_conf_lock();
1206 auth_alt_types = xstrdup(conf->authalttypes);
1207 slurm_conf_unlock();
1208 }
1209 return auth_alt_types;
1210 }
1211
1212 /* slurm_get_auth_type
1213 * returns the authentication type from slurmctld_conf object
1214 * RET char * - auth type, MUST be xfreed by caller
1215 */
slurm_get_auth_type(void)1216 char *slurm_get_auth_type(void)
1217 {
1218 char *auth_type = NULL;
1219 slurm_ctl_conf_t *conf = NULL;
1220
1221 if (slurmdbd_conf) {
1222 auth_type = xstrdup(slurmdbd_conf->auth_type);
1223 } else {
1224 conf = slurm_conf_lock();
1225 auth_type = xstrdup(conf->authtype);
1226 slurm_conf_unlock();
1227 }
1228 return auth_type;
1229 }
1230
1231 /* slurm_get_bb_type
1232 * returns the BurstBufferType (bb_type) from slurmctld_conf object
1233 * RET char * - BurstBufferType, MUST be xfreed by caller
1234 */
slurm_get_bb_type(void)1235 extern char *slurm_get_bb_type(void)
1236 {
1237 char *bb_type = NULL;
1238 slurm_ctl_conf_t *conf = NULL;
1239
1240 if (slurmdbd_conf) {
1241 } else {
1242 conf = slurm_conf_lock();
1243 bb_type = xstrdup(conf->bb_type);
1244 slurm_conf_unlock();
1245 }
1246 return bb_type;
1247 }
1248
1249 /* slurm_get_cluster_name
1250 * returns the cluster name from slurmctld_conf object
1251 * RET char * - cluster name, MUST be xfreed by caller
1252 */
slurm_get_cluster_name(void)1253 char *slurm_get_cluster_name(void)
1254 {
1255 char *name = NULL;
1256 slurm_ctl_conf_t *conf;
1257
1258 if (slurmdbd_conf) {
1259 } else {
1260 conf = slurm_conf_lock();
1261 name = xstrdup(conf->cluster_name);
1262 slurm_conf_unlock();
1263 }
1264 return name;
1265 }
1266
1267 /* slurm_get_comm_parameters
1268 * returns the value of comm_param in slurmctld_conf object
1269 * RET char * - comm parameters, MUST be xfreed by caller
1270 */
slurm_get_comm_parameters(void)1271 extern char *slurm_get_comm_parameters(void)
1272 {
1273 char *comm_params = NULL;
1274 slurm_ctl_conf_t *conf;
1275
1276 if (slurmdbd_conf) {
1277 } else {
1278 conf = slurm_conf_lock();
1279 comm_params = xstrdup(conf->comm_params);
1280 slurm_conf_unlock();
1281 }
1282 return comm_params;
1283 }
1284
1285
1286 /* slurm_get_cred_type
1287 * returns the cred_type from slurmctld_conf object
1288 * RET char * - cred type, MUST be xfreed by caller
1289 */
slurm_get_cred_type(void)1290 extern char *slurm_get_cred_type(void)
1291 {
1292 char *cred_type = NULL;
1293 slurm_ctl_conf_t *conf;
1294
1295 if (slurmdbd_conf) {
1296 } else {
1297 conf = slurm_conf_lock();
1298 cred_type = xstrdup(conf->cred_type);
1299 slurm_conf_unlock();
1300 }
1301 return cred_type;
1302 }
1303
1304 /* slurm_get_power_parameters
1305 * returns the PowerParameters from slurmctld_conf object
1306 * RET char * - PowerParameters, MUST be xfreed by caller
1307 */
slurm_get_power_parameters(void)1308 extern char *slurm_get_power_parameters(void)
1309 {
1310 char *power_parameters = NULL;
1311 slurm_ctl_conf_t *conf;
1312
1313 if (slurmdbd_conf) {
1314 } else {
1315 conf = slurm_conf_lock();
1316 power_parameters = xstrdup(conf->power_parameters);
1317 slurm_conf_unlock();
1318 }
1319 return power_parameters;
1320 }
1321
1322 /* slurm_set_power_parameters
1323 * reset the PowerParameters object
1324 */
slurm_set_power_parameters(char * power_parameters)1325 extern void slurm_set_power_parameters(char *power_parameters)
1326 {
1327 slurm_ctl_conf_t *conf;
1328
1329 if (slurmdbd_conf) {
1330 } else {
1331 conf = slurm_conf_lock();
1332 xfree(conf->power_parameters);
1333 conf->power_parameters = xstrdup(power_parameters);
1334 slurm_conf_unlock();
1335 }
1336 }
1337
1338 /* slurm_get_power_plugin
1339 * returns the PowerPlugin from slurmctld_conf object
1340 * RET char * - PowerPlugin, MUST be xfreed by caller
1341 */
slurm_get_power_plugin(void)1342 extern char *slurm_get_power_plugin(void)
1343 {
1344 char *power_plugin = NULL;
1345 slurm_ctl_conf_t *conf;
1346
1347 if (slurmdbd_conf) {
1348 } else {
1349 conf = slurm_conf_lock();
1350 power_plugin = xstrdup(conf->power_plugin);
1351 slurm_conf_unlock();
1352 }
1353 return power_plugin;
1354 }
1355
1356 /* slurm_get_topology_param
1357 * returns the value of topology_param in slurmctld_conf object
1358 * RET char * - topology parameters, MUST be xfreed by caller
1359 */
slurm_get_topology_param(void)1360 extern char * slurm_get_topology_param(void)
1361 {
1362 char *topology_param = NULL;
1363 slurm_ctl_conf_t *conf;
1364
1365 if (slurmdbd_conf) {
1366 } else {
1367 conf = slurm_conf_lock();
1368 topology_param = xstrdup(conf->topology_param);
1369 slurm_conf_unlock();
1370 }
1371 return topology_param;
1372 }
1373
1374 /* slurm_get_topology_plugin
1375 * returns the value of topology_plugin in slurmctld_conf object
1376 * RET char * - topology type, MUST be xfreed by caller
1377 */
slurm_get_topology_plugin(void)1378 extern char * slurm_get_topology_plugin(void)
1379 {
1380 char *topology_plugin = NULL;
1381 slurm_ctl_conf_t *conf;
1382
1383 if (slurmdbd_conf) {
1384 } else {
1385 conf = slurm_conf_lock();
1386 topology_plugin = xstrdup(conf->topology_plugin);
1387 slurm_conf_unlock();
1388 }
1389 return topology_plugin;
1390 }
1391
1392 /* slurm_get_propagate_prio_process
1393 * return the PropagatePrioProcess flag from slurmctld_conf object
1394 */
slurm_get_propagate_prio_process(void)1395 extern uint16_t slurm_get_propagate_prio_process(void)
1396 {
1397 uint16_t propagate_prio = 0;
1398 slurm_ctl_conf_t *conf;
1399
1400 if (slurmdbd_conf) {
1401 } else {
1402 conf = slurm_conf_lock();
1403 propagate_prio = conf->propagate_prio_process;
1404 slurm_conf_unlock();
1405 }
1406 return propagate_prio;
1407 }
1408
1409 /* slurm_get_route_plugin
1410 * returns the value of route_plugin in slurmctld_conf object
1411 * RET char * - route type, MUST be xfreed by caller
1412 */
slurm_get_route_plugin(void)1413 extern char * slurm_get_route_plugin(void)
1414 {
1415 char *route_plugin = NULL;
1416 slurm_ctl_conf_t *conf;
1417
1418 if (slurmdbd_conf) {
1419 } else {
1420 conf = slurm_conf_lock();
1421
1422 route_plugin = xstrdup(conf->route_plugin);
1423 slurm_conf_unlock();
1424 }
1425 return route_plugin;
1426 }
1427
1428 /* slurm_get_track_wckey
1429 * returns the value of track_wckey in slurmctld_conf object
1430 */
slurm_get_track_wckey(void)1431 extern uint16_t slurm_get_track_wckey(void)
1432 {
1433 uint16_t track_wckey = 0;
1434 slurm_ctl_conf_t *conf;
1435
1436 if (slurmdbd_conf) {
1437 track_wckey = slurmdbd_conf->track_wckey;
1438 } else {
1439 conf = slurm_conf_lock();
1440 track_wckey = conf->conf_flags & CTL_CONF_WCKEY ? 1 : 0;
1441 slurm_conf_unlock();
1442 }
1443 return track_wckey;
1444 }
1445
1446 /* slurm_set_tree_width
1447 * sets the value of tree_width in slurmctld_conf object
1448 * RET 0 or error code
1449 */
slurm_set_tree_width(uint16_t tree_width)1450 extern int slurm_set_tree_width(uint16_t tree_width)
1451 {
1452 slurm_ctl_conf_t *conf;
1453
1454 if (slurmdbd_conf) {
1455 } else {
1456 conf = slurm_conf_lock();
1457 if (tree_width == 0) {
1458 error("can't have span count of 0");
1459 return SLURM_ERROR;
1460 }
1461 conf->tree_width = tree_width;
1462 slurm_conf_unlock();
1463 }
1464 return 0;
1465 }
1466 /* slurm_get_tree_width
1467 * returns the value of tree_width in slurmctld_conf object
1468 */
slurm_get_tree_width(void)1469 extern uint16_t slurm_get_tree_width(void)
1470 {
1471 /* initialize to 1 to silence later warnings
1472 * about potential division by zero */
1473 uint16_t tree_width = 1;
1474 slurm_ctl_conf_t *conf;
1475
1476 if (slurmdbd_conf) {
1477 } else {
1478 conf = slurm_conf_lock();
1479 tree_width = conf->tree_width;
1480 slurm_conf_unlock();
1481 }
1482 return tree_width;
1483 }
1484
1485 /* slurm_get_vsize_factor
1486 * returns the value of vsize_factor in slurmctld_conf object
1487 */
slurm_get_vsize_factor(void)1488 extern uint16_t slurm_get_vsize_factor(void)
1489 {
1490 uint16_t vsize_factor = 0;
1491 slurm_ctl_conf_t *conf;
1492
1493 if (slurmdbd_conf) {
1494 } else {
1495 conf = slurm_conf_lock();
1496 vsize_factor = conf->vsize_factor;
1497 slurm_conf_unlock();
1498 }
1499 return vsize_factor;
1500 }
1501
1502 /* slurm_set_auth_type
1503 * set the authentication type in slurmctld_conf object
1504 * used for security testing purposes
1505 * RET 0 or error code
1506 */
slurm_set_auth_type(char * auth_type)1507 extern int slurm_set_auth_type(char *auth_type)
1508 {
1509 slurm_ctl_conf_t *conf;
1510
1511 if (slurmdbd_conf) {
1512 xfree(slurmdbd_conf->auth_type);
1513 slurmdbd_conf->auth_type = xstrdup(auth_type);
1514 } else {
1515 conf = slurm_conf_lock();
1516 xfree(conf->authtype);
1517 conf->authtype = xstrdup(auth_type);
1518 slurm_conf_unlock();
1519 }
1520 return 0;
1521 }
1522
1523 /* slurm_get_hash_val
1524 * get hash val of the slurm.conf from slurmctld_conf object from
1525 * slurmctld_conf object
1526 * RET uint32_t - hash_val
1527 */
slurm_get_hash_val(void)1528 uint32_t slurm_get_hash_val(void)
1529 {
1530 uint32_t hash_val;
1531 slurm_ctl_conf_t *conf;
1532
1533 if (slurmdbd_conf) {
1534 hash_val = NO_VAL;
1535 } else {
1536 conf = slurm_conf_lock();
1537 hash_val = conf->hash_val;
1538 slurm_conf_unlock();
1539 }
1540 return hash_val;
1541 }
1542
1543 /* slurm_get_health_check_program
1544 * get health_check_program from slurmctld_conf object from
1545 * slurmctld_conf object
1546 * RET char * - health_check_program, MUST be xfreed by caller
1547 */
slurm_get_health_check_program(void)1548 char *slurm_get_health_check_program(void)
1549 {
1550 char *health_check_program = NULL;
1551 slurm_ctl_conf_t *conf;
1552
1553 if (slurmdbd_conf) {
1554 } else {
1555 conf = slurm_conf_lock();
1556 health_check_program = xstrdup(conf->health_check_program);
1557 slurm_conf_unlock();
1558 }
1559 return health_check_program;
1560 }
1561
1562 /* slurm_get_gres_plugins
1563 * get gres_plugins from slurmctld_conf object from
1564 * slurmctld_conf object
1565 * RET char * - gres_plugins, MUST be xfreed by caller
1566 */
slurm_get_gres_plugins(void)1567 char *slurm_get_gres_plugins(void)
1568 {
1569 char *gres_plugins = NULL;
1570 slurm_ctl_conf_t *conf;
1571
1572 if (slurmdbd_conf) {
1573 } else {
1574 conf = slurm_conf_lock();
1575 gres_plugins = xstrdup(conf->gres_plugins);
1576 slurm_conf_unlock();
1577 }
1578 return gres_plugins;
1579 }
1580
1581 /* slurm_get_job_submit_plugins
1582 * get job_submit_plugins from slurmctld_conf object from
1583 * slurmctld_conf object
1584 * RET char * - job_submit_plugins, MUST be xfreed by caller
1585 */
slurm_get_job_submit_plugins(void)1586 char *slurm_get_job_submit_plugins(void)
1587 {
1588 char *job_submit_plugins = NULL;
1589 slurm_ctl_conf_t *conf;
1590
1591 if (slurmdbd_conf) {
1592 } else {
1593 conf = slurm_conf_lock();
1594 job_submit_plugins = xstrdup(conf->job_submit_plugins);
1595 slurm_conf_unlock();
1596 }
1597 return job_submit_plugins;
1598 }
1599
1600 /* slurm_get_cli_filter_plugins
1601 * get cli_filter_plugins from slurmctld_conf object from
1602 * slurmctld_conf object
1603 * RET char * - cli_filter_plugins, MUST be xfreed by caller
1604 */
slurm_get_cli_filter_plugins(void)1605 char *slurm_get_cli_filter_plugins(void)
1606 {
1607 char *cli_filter_plugins = NULL;
1608 slurm_ctl_conf_t *conf;
1609
1610 if (slurmdbd_conf) {
1611 } else {
1612 conf = slurm_conf_lock();
1613 cli_filter_plugins = xstrdup(conf->cli_filter_plugins);
1614 slurm_conf_unlock();
1615 }
1616 return cli_filter_plugins;
1617 }
1618
1619 /* slurm_get_slurmctld_logfile
1620 * get slurmctld_logfile from slurmctld_conf object from slurmctld_conf object
1621 * RET char * - slurmctld_logfile, MUST be xfreed by caller
1622 */
slurm_get_job_slurmctld_logfile(void)1623 char *slurm_get_job_slurmctld_logfile(void)
1624 {
1625 char *slurmctld_logfile = NULL;
1626 slurm_ctl_conf_t *conf;
1627
1628 if (slurmdbd_conf) {
1629 } else {
1630 conf = slurm_conf_lock();
1631 slurmctld_logfile = xstrdup(conf->slurmctld_logfile);
1632 slurm_conf_unlock();
1633 }
1634 return slurmctld_logfile;
1635 }
1636
1637 /* slurm_get_node_features_plugins
1638 * get node_features_plugins from slurmctld_conf object
1639 * RET char * - knl_plugins, MUST be xfreed by caller
1640 */
slurm_get_node_features_plugins(void)1641 char *slurm_get_node_features_plugins(void)
1642 {
1643 char *knl_plugins = NULL;
1644 slurm_ctl_conf_t *conf;
1645
1646 if (slurmdbd_conf) {
1647 } else {
1648 conf = slurm_conf_lock();
1649 knl_plugins = xstrdup(conf->node_features_plugins);
1650 slurm_conf_unlock();
1651 }
1652 return knl_plugins;
1653 }
1654
1655 /* slurm_get_slurmctld_plugstack
1656 * get slurmctld_plugstack from slurmctld_conf object from
1657 * slurmctld_conf object
1658 * RET char * - slurmctld_plugstack, MUST be xfreed by caller
1659 */
slurm_get_slurmctld_plugstack(void)1660 char *slurm_get_slurmctld_plugstack(void)
1661 {
1662 char *slurmctld_plugstack = NULL;
1663 slurm_ctl_conf_t *conf;
1664
1665 if (slurmdbd_conf) {
1666 } else {
1667 conf = slurm_conf_lock();
1668 slurmctld_plugstack = xstrdup(conf->slurmctld_plugstack);
1669 slurm_conf_unlock();
1670 }
1671 return slurmctld_plugstack;
1672 }
1673
1674 /* slurm_get_slurmctld_timeout
1675 * get slurmctld_timeout from slurmctld_conf object from
1676 * slurmctld_conf object
1677 * RET uint16_t - slurmctld timeout in seconds
1678 */
slurm_get_slurmctld_timeout(void)1679 uint16_t slurm_get_slurmctld_timeout(void)
1680 {
1681 uint16_t slurmctld_timeout = 0;
1682 slurm_ctl_conf_t *conf;
1683
1684 if (slurmdbd_conf) {
1685 } else {
1686 conf = slurm_conf_lock();
1687 slurmctld_timeout = conf->slurmctld_timeout;
1688 slurm_conf_unlock();
1689 }
1690 return slurmctld_timeout;
1691 }
1692
1693 /* slurm_get_accounting_storage_type
1694 * returns the accounting storage type from slurmctld_conf object
1695 * RET char * - accounting storage type, MUST be xfreed by caller
1696 */
slurm_get_accounting_storage_type(void)1697 char *slurm_get_accounting_storage_type(void)
1698 {
1699 char *accounting_type;
1700 slurm_ctl_conf_t *conf;
1701
1702 if (slurmdbd_conf) {
1703 accounting_type = xstrdup(slurmdbd_conf->storage_type);
1704 } else {
1705 conf = slurm_conf_lock();
1706 accounting_type = xstrdup(conf->accounting_storage_type);
1707 slurm_conf_unlock();
1708 }
1709 return accounting_type;
1710
1711 }
1712
1713 /* slurm_get_accounting_storage_tres
1714 * returns the accounting storage tres from slurmctld_conf object
1715 * RET char * - accounting storage tres, MUST be xfreed by caller
1716 */
slurm_get_accounting_storage_tres(void)1717 char *slurm_get_accounting_storage_tres(void)
1718 {
1719 char *accounting_tres;
1720 slurm_ctl_conf_t *conf;
1721
1722 if (slurmdbd_conf) {
1723 accounting_tres = NULL;
1724 } else {
1725 conf = slurm_conf_lock();
1726 accounting_tres = xstrdup(conf->accounting_storage_tres);
1727 slurm_conf_unlock();
1728 }
1729 return accounting_tres;
1730
1731 }
1732
1733 /* slurm_set_accounting_storage_tres
1734 * sets the value of accounting_storage_tres in slurmctld_conf object
1735 * RET 0 or error_code
1736 */
slurm_set_accounting_storage_tres(char * tres)1737 extern int slurm_set_accounting_storage_tres(char *tres)
1738 {
1739 slurm_ctl_conf_t *conf;
1740
1741 if (slurmdbd_conf) {
1742 } else {
1743 conf = slurm_conf_lock();
1744 xfree(conf->accounting_storage_tres);
1745 conf->accounting_storage_tres = xstrdup(tres);
1746 slurm_conf_unlock();
1747 }
1748 return 0;
1749
1750 }
1751
1752 /* slurm_get_accounting_storage_user
1753 * returns the storage user from slurmctld_conf object
1754 * RET char * - storage user, MUST be xfreed by caller
1755 */
slurm_get_accounting_storage_user(void)1756 char *slurm_get_accounting_storage_user(void)
1757 {
1758 char *storage_user;
1759 slurm_ctl_conf_t *conf;
1760
1761 if (slurmdbd_conf) {
1762 storage_user = xstrdup(slurmdbd_conf->storage_user);
1763 } else {
1764 conf = slurm_conf_lock();
1765 storage_user = xstrdup(conf->accounting_storage_user);
1766 slurm_conf_unlock();
1767 }
1768 return storage_user;
1769 }
1770
1771 /* slurm_set_accounting_storage_user
1772 * IN: char *user (name of file or database)
1773 * RET 0 or error code
1774 */
slurm_set_accounting_storage_user(char * user)1775 int slurm_set_accounting_storage_user(char *user)
1776 {
1777 slurm_ctl_conf_t *conf;
1778
1779 if (slurmdbd_conf) {
1780 xfree(slurmdbd_conf->storage_user);
1781 slurmdbd_conf->storage_user = xstrdup(user);
1782 } else {
1783 conf = slurm_conf_lock();
1784 xfree(conf->accounting_storage_user);
1785 conf->accounting_storage_user = xstrdup(user);
1786 slurm_conf_unlock();
1787 }
1788 return 0;
1789 }
1790
1791 /* slurm_get_accounting_storage_backup_host
1792 * returns the storage backup host from slurmctld_conf object
1793 * RET char * - storage backup host, MUST be xfreed by caller
1794 */
slurm_get_accounting_storage_backup_host(void)1795 char *slurm_get_accounting_storage_backup_host(void)
1796 {
1797 char *storage_host;
1798 slurm_ctl_conf_t *conf;
1799
1800 if (slurmdbd_conf) {
1801 storage_host = xstrdup(slurmdbd_conf->storage_backup_host);
1802 } else {
1803 conf = slurm_conf_lock();
1804 storage_host = xstrdup(conf->accounting_storage_backup_host);
1805 slurm_conf_unlock();
1806 }
1807 return storage_host;
1808 }
1809
slurm_get_accounting_storage_ext_host(void)1810 char *slurm_get_accounting_storage_ext_host(void)
1811 {
1812 char *ext_host = NULL;
1813 slurm_ctl_conf_t *conf;
1814
1815 if (slurmdbd_conf) {
1816 } else {
1817 conf = slurm_conf_lock();
1818 ext_host = xstrdup(conf->accounting_storage_ext_host);
1819 slurm_conf_unlock();
1820 }
1821 return ext_host;
1822 }
1823
1824 /* slurm_get_accounting_storage_host
1825 * returns the storage host from slurmctld_conf object
1826 * RET char * - storage host, MUST be xfreed by caller
1827 */
slurm_get_accounting_storage_host(void)1828 char *slurm_get_accounting_storage_host(void)
1829 {
1830 char *storage_host;
1831 slurm_ctl_conf_t *conf;
1832
1833 if (slurmdbd_conf) {
1834 storage_host = xstrdup(slurmdbd_conf->storage_host);
1835 } else {
1836 conf = slurm_conf_lock();
1837 storage_host = xstrdup(conf->accounting_storage_host);
1838 slurm_conf_unlock();
1839 }
1840 return storage_host;
1841 }
1842
1843 /* slurm_set_accounting_storage_host
1844 * IN: char *host (name of file or database)
1845 * RET 0 or error code
1846 */
slurm_set_accounting_storage_host(char * host)1847 int slurm_set_accounting_storage_host(char *host)
1848 {
1849 slurm_ctl_conf_t *conf;
1850
1851 if (slurmdbd_conf) {
1852 xfree(slurmdbd_conf->storage_host);
1853 slurmdbd_conf->storage_host = xstrdup(host);
1854 } else {
1855 conf = slurm_conf_lock();
1856 xfree(conf->accounting_storage_host);
1857 conf->accounting_storage_host = xstrdup(host);
1858 slurm_conf_unlock();
1859 }
1860 return 0;
1861 }
1862
1863 /* slurm_get_accounting_storage_loc
1864 * returns the storage location from slurmctld_conf object
1865 * RET char * - storage location, MUST be xfreed by caller
1866 */
slurm_get_accounting_storage_loc(void)1867 char *slurm_get_accounting_storage_loc(void)
1868 {
1869 char *storage_loc;
1870 slurm_ctl_conf_t *conf;
1871
1872 if (slurmdbd_conf) {
1873 storage_loc = xstrdup(slurmdbd_conf->storage_loc);
1874 } else {
1875 conf = slurm_conf_lock();
1876 storage_loc = xstrdup(conf->accounting_storage_loc);
1877 slurm_conf_unlock();
1878 }
1879 return storage_loc;
1880 }
1881
1882 /* slurm_set_accounting_storage_loc
1883 * IN: char *loc (name of file or database)
1884 * RET 0 or error code
1885 */
slurm_set_accounting_storage_loc(char * loc)1886 int slurm_set_accounting_storage_loc(char *loc)
1887 {
1888 slurm_ctl_conf_t *conf;
1889
1890 if (slurmdbd_conf) {
1891 xfree(slurmdbd_conf->storage_loc);
1892 slurmdbd_conf->storage_loc = xstrdup(loc);
1893 } else {
1894 conf = slurm_conf_lock();
1895 xfree(conf->accounting_storage_loc);
1896 conf->accounting_storage_loc = xstrdup(loc);
1897 slurm_conf_unlock();
1898 }
1899 return 0;
1900 }
1901
1902 /* slurm_get_accounting_storage_enforce
1903 * returns what level to enforce associations at
1904 */
slurm_get_accounting_storage_enforce(void)1905 uint16_t slurm_get_accounting_storage_enforce(void)
1906 {
1907 uint16_t enforce = 0;
1908 slurm_ctl_conf_t *conf;
1909
1910 if (slurmdbd_conf) {
1911 } else {
1912 conf = slurm_conf_lock();
1913 enforce = conf->accounting_storage_enforce;
1914 slurm_conf_unlock();
1915 }
1916 return enforce;
1917
1918 }
1919
1920 /* slurm_get_is_association_based_accounting
1921 * returns if we are doing accounting by associations
1922 */
slurm_get_is_association_based_accounting(void)1923 int slurm_get_is_association_based_accounting(void)
1924 {
1925 int enforce = 0;
1926 slurm_ctl_conf_t *conf;
1927
1928 if (slurmdbd_conf) {
1929 return 1;
1930 } else {
1931 conf = slurm_conf_lock();
1932 if (!xstrcasecmp(conf->accounting_storage_type,
1933 "accounting_storage/slurmdbd") ||
1934 !xstrcasecmp(conf->accounting_storage_type,
1935 "accounting_storage/mysql"))
1936 enforce = 1;
1937 slurm_conf_unlock();
1938 }
1939 return enforce;
1940
1941 }
1942
1943 /* slurm_get_accounting_storage_pass
1944 * returns the storage password from slurmctld_conf object
1945 * RET char * - storage password, MUST be xfreed by caller
1946 */
slurm_get_accounting_storage_pass(void)1947 char *slurm_get_accounting_storage_pass(void)
1948 {
1949 char *storage_pass;
1950 slurm_ctl_conf_t *conf;
1951
1952 if (slurmdbd_conf) {
1953 storage_pass = xstrdup(slurmdbd_conf->storage_pass);
1954 } else {
1955 conf = slurm_conf_lock();
1956 storage_pass = xstrdup(conf->accounting_storage_pass);
1957 slurm_conf_unlock();
1958 }
1959 return storage_pass;
1960 }
1961
1962 /* slurm_get_auth_info
1963 * returns the auth_info from slurmctld_conf object (AuthInfo parameter)
1964 * RET char * - AuthInfo value, MUST be xfreed by caller
1965 */
slurm_get_auth_info(void)1966 extern char *slurm_get_auth_info(void)
1967 {
1968 char *auth_info;
1969 slurm_ctl_conf_t *conf;
1970
1971 if (slurmdbd_conf) {
1972 auth_info = xstrdup(slurmdbd_conf->auth_info);
1973 } else {
1974 conf = slurm_conf_lock();
1975 auth_info = xstrdup(conf->authinfo);
1976 slurm_conf_unlock();
1977 }
1978
1979 return auth_info;
1980 }
1981
1982 /*
1983 * Convert AuthInfo to a socket path. Accepts two input formats:
1984 * 1) <path> (Old format)
1985 * 2) socket=<path>[,] (New format)
1986 * NOTE: Caller must xfree return value
1987 */
slurm_auth_opts_to_socket(char * opts)1988 extern char *slurm_auth_opts_to_socket(char *opts)
1989 {
1990 char *socket = NULL, *sep, *tmp;
1991
1992 if (!opts)
1993 return NULL;
1994
1995 tmp = strstr(opts, "socket=");
1996 if (tmp) {
1997 /* New format */
1998 socket = xstrdup(tmp + 7);
1999 sep = strchr(socket, ',');
2000 if (sep)
2001 sep[0] = '\0';
2002 } else if (strchr(opts, '=')) {
2003 /* New format, but socket not specified */
2004 ;
2005 } else {
2006 /* Old format */
2007 socket = xstrdup(opts);
2008 }
2009
2010 return socket;
2011 }
2012
2013 /* slurm_get_sbcast_parameters
2014 * RET char * - SbcastParameters from slurm.conf, MUST be xfreed by caller
2015 */
slurm_get_sbcast_parameters(void)2016 char *slurm_get_sbcast_parameters(void)
2017 {
2018 char *sbcast_parameters = NULL;
2019 slurm_ctl_conf_t *conf;
2020
2021 if (!slurmdbd_conf) {
2022 conf = slurm_conf_lock();
2023 sbcast_parameters = xstrdup(conf->sbcast_parameters);
2024 slurm_conf_unlock();
2025 }
2026
2027 return sbcast_parameters;
2028 }
2029
2030 /* slurm_get_auth_ttl
2031 * returns the credential Time To Live option from the AuthInfo parameter
2032 * cache value in local buffer for best performance
2033 * RET int - Time To Live in seconds or 0 if not specified
2034 */
slurm_get_auth_ttl(void)2035 extern int slurm_get_auth_ttl(void)
2036 {
2037 static int ttl = -1;
2038 char *auth_info, *tmp;
2039
2040 if (ttl >= 0)
2041 return ttl;
2042
2043 auth_info = slurm_get_auth_info();
2044 if (!auth_info)
2045 return 0;
2046
2047 tmp = strstr(auth_info, "ttl=");
2048 if (tmp) {
2049 ttl = atoi(tmp + 4);
2050 if (ttl < 0)
2051 ttl = 0;
2052 } else {
2053 ttl = 0;
2054 }
2055 xfree(auth_info);
2056
2057 return ttl;
2058 }
2059
2060 /* _global_auth_key
2061 * returns the storage password from slurmctld_conf or slurmdbd_conf object
2062 * cache value in local buffer for best performance
2063 * RET char * - storage password
2064 */
_global_auth_key(void)2065 static char *_global_auth_key(void)
2066 {
2067 static bool loaded_storage_pass = false;
2068 static char storage_pass[512] = "\0";
2069 static char *storage_pass_ptr = NULL;
2070
2071 if (loaded_storage_pass)
2072 return storage_pass_ptr;
2073
2074 if (slurmdbd_conf) {
2075 if (slurmdbd_conf->auth_info) {
2076 if (strlcpy(storage_pass, slurmdbd_conf->auth_info,
2077 sizeof(storage_pass))
2078 >= sizeof(storage_pass))
2079 fatal("AuthInfo is too long");
2080 storage_pass_ptr = storage_pass;
2081 }
2082 } else {
2083 slurm_ctl_conf_t *conf = slurm_conf_lock();
2084 if (conf->accounting_storage_pass) {
2085 if (strlcpy(storage_pass, conf->accounting_storage_pass,
2086 sizeof(storage_pass))
2087 >= sizeof(storage_pass))
2088 fatal("AccountingStoragePass is too long");
2089 storage_pass_ptr = storage_pass;
2090 }
2091 slurm_conf_unlock();
2092 }
2093
2094 loaded_storage_pass = true;
2095 return storage_pass_ptr;
2096 }
2097
2098 /* slurm_get_accounting_storage_port
2099 * returns the storage port from slurmctld_conf object
2100 * RET uint32_t - storage port
2101 */
slurm_get_accounting_storage_port(void)2102 uint32_t slurm_get_accounting_storage_port(void)
2103 {
2104 uint32_t storage_port;
2105 slurm_ctl_conf_t *conf;
2106
2107 if (slurmdbd_conf) {
2108 storage_port = slurmdbd_conf->storage_port;
2109 } else {
2110 conf = slurm_conf_lock();
2111 storage_port = conf->accounting_storage_port;
2112 slurm_conf_unlock();
2113 }
2114 return storage_port;
2115
2116 }
2117
2118 /* slurm_set_accounting_storage_port
2119 * sets the storage port in slurmctld_conf object
2120 * RET 0 or error code
2121 */
slurm_set_accounting_storage_port(uint32_t storage_port)2122 int slurm_set_accounting_storage_port(uint32_t storage_port)
2123 {
2124 slurm_ctl_conf_t *conf;
2125
2126 if (slurmdbd_conf) {
2127 slurmdbd_conf->storage_port = storage_port;
2128 } else {
2129 conf = slurm_conf_lock();
2130 if (storage_port == 0) {
2131 error("can't have storage port of 0");
2132 return SLURM_ERROR;
2133 }
2134
2135 conf->accounting_storage_port = storage_port;
2136 slurm_conf_unlock();
2137 }
2138 return 0;
2139 }
2140
2141 /*
2142 * slurm_get_dependency_params
2143 * RET dependency_params must be xfreed by caller
2144 */
slurm_get_dependency_params(void)2145 char *slurm_get_dependency_params(void)
2146 {
2147 char *dependency_params = NULL;
2148 slurm_ctl_conf_t *conf;
2149
2150 if (slurmdbd_conf) {
2151 } else {
2152 conf = slurm_conf_lock();
2153 dependency_params = xstrdup(conf->dependency_params);
2154 slurm_conf_unlock();
2155 }
2156 return dependency_params;
2157 }
2158
2159 /* slurm_get_preempt_mode
2160 * returns the PreemptMode value from slurmctld_conf object
2161 * RET uint16_t - PreemptMode value (See PREEMPT_MODE_* in slurm.h)
2162 */
slurm_get_preempt_mode(void)2163 uint16_t slurm_get_preempt_mode(void)
2164 {
2165 uint16_t preempt_mode = 0;
2166 slurm_ctl_conf_t *conf;
2167
2168 if (slurmdbd_conf) {
2169 } else {
2170 conf = slurm_conf_lock();
2171 preempt_mode = conf->preempt_mode;
2172 slurm_conf_unlock();
2173 }
2174 return preempt_mode;
2175 }
2176
2177 /* slurm_get_jobacct_gather_type
2178 * returns the job accounting type from the slurmctld_conf object
2179 * RET char * - job accounting type, MUST be xfreed by caller
2180 */
slurm_get_jobacct_gather_type(void)2181 char *slurm_get_jobacct_gather_type(void)
2182 {
2183 char *jobacct_type = NULL;
2184 slurm_ctl_conf_t *conf;
2185
2186 if (slurmdbd_conf) {
2187 } else {
2188 conf = slurm_conf_lock();
2189 jobacct_type = xstrdup(conf->job_acct_gather_type);
2190 slurm_conf_unlock();
2191 }
2192 return jobacct_type;
2193 }
2194
2195 /* slurm_get_jobacct_gather_params
2196 * returns the job accounting params from the slurmctld_conf object
2197 * RET char * - job accounting params, MUST be xfreed by caller
2198 */
slurm_get_jobacct_gather_params(void)2199 char *slurm_get_jobacct_gather_params(void)
2200 {
2201 char *jobacct_params = NULL;
2202 slurm_ctl_conf_t *conf;
2203
2204 if (slurmdbd_conf) {
2205 } else {
2206 conf = slurm_conf_lock();
2207 jobacct_params = xstrdup(conf->job_acct_gather_params);
2208 slurm_conf_unlock();
2209 }
2210 return jobacct_params;
2211 }
2212
2213 /* slurm_get_job_acct_oom_kill
2214 * returns the job_acct_oom_kill setting from the slurmctld_conf object
2215 * which represents the value of the OverMemoryKill flag.
2216 * RET bool * - job_acct_oom_kill parameter
2217 */
slurm_get_job_acct_oom_kill(void)2218 bool slurm_get_job_acct_oom_kill(void)
2219 {
2220 uint16_t enabled = 0;
2221 slurm_ctl_conf_t *conf;
2222
2223 if (slurmdbd_conf) {
2224 } else {
2225 conf = slurm_conf_lock();
2226 enabled = conf->job_acct_oom_kill;
2227 slurm_conf_unlock();
2228 }
2229 return enabled;
2230 }
2231
2232 /* slurm_get_jobacct_freq
2233 * returns the job accounting poll frequency from the slurmctld_conf object
2234 * RET int - job accounting frequency
2235 */
slurm_get_jobacct_gather_freq(void)2236 char *slurm_get_jobacct_gather_freq(void)
2237 {
2238 char *freq = NULL;
2239 slurm_ctl_conf_t *conf;
2240
2241 if (slurmdbd_conf) {
2242 } else {
2243 conf = slurm_conf_lock();
2244 freq = xstrdup(conf->job_acct_gather_freq);
2245 slurm_conf_unlock();
2246 }
2247 return freq;
2248 }
2249
2250 /* slurm_get_energy_accounting_type
2251 * get EnergyAccountingType from slurmctld_conf object
2252 * RET char * - energy_accounting type, MUST be xfreed by caller
2253 */
slurm_get_acct_gather_energy_type(void)2254 char *slurm_get_acct_gather_energy_type(void)
2255 {
2256 char *acct_gather_energy_type = NULL;
2257 slurm_ctl_conf_t *conf;
2258
2259 if (slurmdbd_conf) {
2260 } else {
2261 conf = slurm_conf_lock();
2262 acct_gather_energy_type =
2263 xstrdup(conf->acct_gather_energy_type);
2264 slurm_conf_unlock();
2265 }
2266 return acct_gather_energy_type;
2267 }
2268
2269 /* slurm_get_profile_accounting_type
2270 * get ProfileAccountingType from slurmctld_conf object
2271 * RET char * - profile_accounting type, MUST be xfreed by caller
2272 */
slurm_get_acct_gather_profile_type(void)2273 char *slurm_get_acct_gather_profile_type(void)
2274 {
2275 char *acct_gather_profile_type = NULL;
2276 slurm_ctl_conf_t *conf;
2277
2278 if (slurmdbd_conf) {
2279 } else {
2280 conf = slurm_conf_lock();
2281 acct_gather_profile_type =
2282 xstrdup(conf->acct_gather_profile_type);
2283 slurm_conf_unlock();
2284 }
2285 return acct_gather_profile_type;
2286 }
2287
2288 /* slurm_get_interconnect_accounting_type
2289 * get InterconnectAccountingType from slurmctld_conf object
2290 * RET char * - interconnect_accounting type, MUST be xfreed by caller
2291 */
slurm_get_acct_gather_interconnect_type(void)2292 char *slurm_get_acct_gather_interconnect_type(void)
2293 {
2294 char *acct_gather_interconnect_type = NULL;
2295 slurm_ctl_conf_t *conf;
2296
2297 if (slurmdbd_conf) {
2298 } else {
2299 conf = slurm_conf_lock();
2300 acct_gather_interconnect_type =
2301 xstrdup(conf->acct_gather_interconnect_type);
2302 slurm_conf_unlock();
2303 }
2304 return acct_gather_interconnect_type;
2305 }
2306
2307 /* slurm_get_filesystem_accounting_type
2308 * get FilesystemAccountingType from slurmctld_conf object
2309 * RET char * - filesystem_accounting type, MUST be xfreed by caller
2310 */
slurm_get_acct_gather_filesystem_type(void)2311 char *slurm_get_acct_gather_filesystem_type(void)
2312 {
2313 char *acct_gather_filesystem_type = NULL;
2314 slurm_ctl_conf_t *conf;
2315
2316 if (slurmdbd_conf) {
2317 } else {
2318 conf = slurm_conf_lock();
2319 acct_gather_filesystem_type =
2320 xstrdup(conf->acct_gather_filesystem_type);
2321 slurm_conf_unlock();
2322 }
2323 return acct_gather_filesystem_type;
2324 }
2325
2326
slurm_get_acct_gather_node_freq(void)2327 extern uint16_t slurm_get_acct_gather_node_freq(void)
2328 {
2329 uint16_t freq = 0;
2330 slurm_ctl_conf_t *conf;
2331
2332 if (slurmdbd_conf) {
2333 } else {
2334 conf = slurm_conf_lock();
2335 freq = conf->acct_gather_node_freq;
2336 slurm_conf_unlock();
2337 }
2338 return freq;
2339 }
2340
2341 /* slurm_get_ext_sensors_type
2342 * get ExtSensorsType from slurmctld_conf object
2343 * RET char * - ext_sensors type, MUST be xfreed by caller
2344 */
slurm_get_ext_sensors_type(void)2345 char *slurm_get_ext_sensors_type(void)
2346 {
2347 char *ext_sensors_type = NULL;
2348 slurm_ctl_conf_t *conf;
2349
2350 if (slurmdbd_conf) {
2351 } else {
2352 conf = slurm_conf_lock();
2353 ext_sensors_type =
2354 xstrdup(conf->ext_sensors_type);
2355 slurm_conf_unlock();
2356 }
2357 return ext_sensors_type;
2358 }
2359
slurm_get_ext_sensors_freq(void)2360 extern uint16_t slurm_get_ext_sensors_freq(void)
2361 {
2362 uint16_t freq = 0;
2363 slurm_ctl_conf_t *conf;
2364
2365 if (slurmdbd_conf) {
2366 } else {
2367 conf = slurm_conf_lock();
2368 freq = conf->ext_sensors_freq;
2369 slurm_conf_unlock();
2370 }
2371 return freq;
2372 }
2373
2374 /*
2375 * returns the configured GpuFreqDef value
2376 * RET char * - GpuFreqDef value, MUST be xfreed by caller
2377 */
slurm_get_gpu_freq_def(void)2378 char *slurm_get_gpu_freq_def(void)
2379 {
2380 char *gpu_freq_def = NULL;
2381 slurm_ctl_conf_t *conf;
2382
2383 if (slurmdbd_conf) {
2384 } else {
2385 conf = slurm_conf_lock();
2386 gpu_freq_def = xstrdup(conf->gpu_freq_def);
2387 slurm_conf_unlock();
2388 }
2389 return gpu_freq_def;
2390 }
2391
2392 /*
2393 * slurm_get_jobcomp_type
2394 * returns the job completion logger type from slurmctld_conf object
2395 * RET char * - job completion type, MUST be xfreed by caller
2396 */
slurm_get_jobcomp_type(void)2397 char *slurm_get_jobcomp_type(void)
2398 {
2399 char *jobcomp_type = NULL;
2400 slurm_ctl_conf_t *conf;
2401
2402 if (slurmdbd_conf) {
2403 } else {
2404 conf = slurm_conf_lock();
2405 jobcomp_type = xstrdup(conf->job_comp_type);
2406 slurm_conf_unlock();
2407 }
2408 return jobcomp_type;
2409 }
2410
2411 /* slurm_get_jobcomp_loc
2412 * returns the job completion loc from slurmctld_conf object
2413 * RET char * - job completion location, MUST be xfreed by caller
2414 */
slurm_get_jobcomp_loc(void)2415 char *slurm_get_jobcomp_loc(void)
2416 {
2417 char *jobcomp_loc = 0;
2418 slurm_ctl_conf_t *conf;
2419
2420 if (slurmdbd_conf) {
2421 } else {
2422 conf = slurm_conf_lock();
2423 jobcomp_loc = xstrdup(conf->job_comp_loc);
2424 slurm_conf_unlock();
2425 }
2426 return jobcomp_loc;
2427 }
2428
2429 /* slurm_get_jobcomp_user
2430 * returns the storage user from slurmctld_conf object
2431 * RET char * - storage user, MUST be xfreed by caller
2432 */
slurm_get_jobcomp_user(void)2433 char *slurm_get_jobcomp_user(void)
2434 {
2435 char *storage_user = NULL;
2436 slurm_ctl_conf_t *conf;
2437
2438 if (slurmdbd_conf) {
2439 } else {
2440 conf = slurm_conf_lock();
2441 storage_user = xstrdup(conf->job_comp_user);
2442 slurm_conf_unlock();
2443 }
2444 return storage_user;
2445 }
2446
2447 /* slurm_get_jobcomp_host
2448 * returns the storage host from slurmctld_conf object
2449 * RET char * - storage host, MUST be xfreed by caller
2450 */
slurm_get_jobcomp_host(void)2451 char *slurm_get_jobcomp_host(void)
2452 {
2453 char *storage_host = NULL;
2454 slurm_ctl_conf_t *conf;
2455
2456 if (slurmdbd_conf) {
2457 } else {
2458 conf = slurm_conf_lock();
2459 storage_host = xstrdup(conf->job_comp_host);
2460 slurm_conf_unlock();
2461 }
2462 return storage_host;
2463 }
2464
slurm_get_jobcomp_params(void)2465 char *slurm_get_jobcomp_params(void)
2466 {
2467 char *param = NULL;
2468 slurm_ctl_conf_t *conf;
2469
2470 if (slurmdbd_conf) {
2471 } else {
2472 conf = slurm_conf_lock();
2473 param = xstrdup(conf->job_comp_params);
2474 slurm_conf_unlock();
2475 }
2476 return param;
2477 }
2478
2479 /* slurm_get_jobcomp_pass
2480 * returns the storage password from slurmctld_conf object
2481 * RET char * - storage password, MUST be xfreed by caller
2482 */
slurm_get_jobcomp_pass(void)2483 char *slurm_get_jobcomp_pass(void)
2484 {
2485 char *storage_pass = NULL;
2486 slurm_ctl_conf_t *conf;
2487
2488 if (slurmdbd_conf) {
2489 } else {
2490 conf = slurm_conf_lock();
2491 storage_pass = xstrdup(conf->job_comp_pass);
2492 slurm_conf_unlock();
2493 }
2494 return storage_pass;
2495 }
2496
2497 /* slurm_get_jobcomp_port
2498 * returns the storage port from slurmctld_conf object
2499 * RET uint32_t - storage port
2500 */
slurm_get_jobcomp_port(void)2501 uint32_t slurm_get_jobcomp_port(void)
2502 {
2503 uint32_t storage_port = 0;
2504 slurm_ctl_conf_t *conf;
2505
2506 if (slurmdbd_conf) {
2507 } else {
2508 conf = slurm_conf_lock();
2509 storage_port = conf->job_comp_port;
2510 slurm_conf_unlock();
2511 }
2512 return storage_port;
2513
2514 }
2515
2516 /* slurm_set_jobcomp_port
2517 * sets the jobcomp port in slurmctld_conf object
2518 * RET 0 or error code
2519 */
slurm_set_jobcomp_port(uint32_t port)2520 int slurm_set_jobcomp_port(uint32_t port)
2521 {
2522 slurm_ctl_conf_t *conf;
2523
2524 if (slurmdbd_conf) {
2525 } else {
2526 conf = slurm_conf_lock();
2527 if (port == 0) {
2528 error("can't have jobcomp port of 0");
2529 return SLURM_ERROR;
2530 }
2531
2532 conf->job_comp_port = port;
2533 slurm_conf_unlock();
2534 }
2535 return 0;
2536 }
2537
2538 /* slurm_get_keep_alive_time
2539 * returns keep_alive_time slurmctld_conf object
2540 * RET uint16_t - keep_alive_time
2541 */
slurm_get_keep_alive_time(void)2542 uint16_t slurm_get_keep_alive_time(void)
2543 {
2544 uint16_t keep_alive_time = NO_VAL16;
2545 slurm_ctl_conf_t *conf;
2546
2547 if (slurmdbd_conf) {
2548 } else {
2549 conf = slurm_conf_lock();
2550 keep_alive_time = conf->keep_alive_time;
2551 slurm_conf_unlock();
2552 }
2553 return keep_alive_time;
2554 }
2555
2556
2557 /* slurm_get_kill_wait
2558 * returns kill_wait from slurmctld_conf object
2559 * RET uint16_t - kill_wait
2560 */
slurm_get_kill_wait(void)2561 uint16_t slurm_get_kill_wait(void)
2562 {
2563 uint16_t kill_wait = 0;
2564 slurm_ctl_conf_t *conf;
2565
2566 if (slurmdbd_conf) {
2567 } else {
2568 conf = slurm_conf_lock();
2569 kill_wait = conf->kill_wait;
2570 slurm_conf_unlock();
2571 }
2572 return kill_wait;
2573 }
2574
2575 /* slurm_get_launch_params
2576 * get launch_params from slurmctld_conf object
2577 * RET char * - launch_params, MUST be xfreed by caller
2578 */
slurm_get_launch_params(void)2579 char *slurm_get_launch_params(void)
2580 {
2581 char *launch_params = NULL;
2582 slurm_ctl_conf_t *conf;
2583
2584 if (slurmdbd_conf) {
2585 } else {
2586 conf = slurm_conf_lock();
2587 launch_params = xstrdup(conf->launch_params);
2588 slurm_conf_unlock();
2589 }
2590 return launch_params;
2591 }
2592
2593 /* slurm_get_launch_type
2594 * get launch_type from slurmctld_conf object
2595 * RET char * - launch_type, MUST be xfreed by caller
2596 */
slurm_get_launch_type(void)2597 char *slurm_get_launch_type(void)
2598 {
2599 char *launch_type = NULL;
2600 slurm_ctl_conf_t *conf;
2601
2602 if (slurmdbd_conf) {
2603 } else {
2604 conf = slurm_conf_lock();
2605 launch_type = xstrdup(conf->launch_type);
2606 slurm_conf_unlock();
2607 }
2608 return launch_type;
2609 }
2610
2611 /* slurm_set_launch_type
2612 * set launch_type in slurmctld_conf object
2613 * RET 0 or error code
2614 */
slurm_set_launch_type(char * launch_type)2615 int slurm_set_launch_type(char *launch_type)
2616 {
2617 slurm_ctl_conf_t *conf;
2618
2619 if (slurmdbd_conf) {
2620 } else {
2621 conf = slurm_conf_lock();
2622 xfree(conf->launch_type);
2623 conf->launch_type = xstrdup(launch_type);
2624 slurm_conf_unlock();
2625 }
2626 return 0;
2627 }
2628
2629 /* slurm_get_mcs_plugin
2630 * RET mcs_plugin name, must be xfreed by caller */
slurm_get_mcs_plugin(void)2631 char *slurm_get_mcs_plugin(void)
2632 {
2633 char *mcs_plugin = NULL;
2634 slurm_ctl_conf_t *conf;
2635
2636 if (slurmdbd_conf) {
2637 } else {
2638 conf = slurm_conf_lock();
2639 mcs_plugin = xstrdup(conf->mcs_plugin);
2640 slurm_conf_unlock();
2641 }
2642 return mcs_plugin;
2643 }
2644
2645 /* slurm_get_mcs_plugin_params
2646 * RET mcs_plugin_params name, must be xfreed by caller */
slurm_get_mcs_plugin_params(void)2647 char *slurm_get_mcs_plugin_params(void)
2648 {
2649 char *mcs_plugin_params = NULL;
2650 slurm_ctl_conf_t *conf;
2651
2652 if (slurmdbd_conf) {
2653 } else {
2654 conf = slurm_conf_lock();
2655 mcs_plugin_params = xstrdup(conf->mcs_plugin_params);
2656 slurm_conf_unlock();
2657 }
2658 return mcs_plugin_params;
2659 }
2660
2661 /* slurm_get_preempt_type
2662 * get PreemptType from slurmctld_conf object
2663 * RET char * - preempt type, MUST be xfreed by caller
2664 */
slurm_get_preempt_type(void)2665 char *slurm_get_preempt_type(void)
2666 {
2667 char *preempt_type = NULL;
2668 slurm_ctl_conf_t *conf;
2669
2670 if (slurmdbd_conf) {
2671 } else {
2672 conf = slurm_conf_lock();
2673 preempt_type = xstrdup(conf->preempt_type);
2674 slurm_conf_unlock();
2675 }
2676 return preempt_type;
2677 }
2678
2679 /* slurm_get_proctrack_type
2680 * get ProctrackType from slurmctld_conf object
2681 * RET char * - proctrack type, MUST be xfreed by caller
2682 */
slurm_get_proctrack_type(void)2683 char *slurm_get_proctrack_type(void)
2684 {
2685 char *proctrack_type = NULL;
2686 slurm_ctl_conf_t *conf;
2687
2688 if (slurmdbd_conf) {
2689 } else {
2690 conf = slurm_conf_lock();
2691 proctrack_type = xstrdup(conf->proctrack_type);
2692 slurm_conf_unlock();
2693 }
2694 return proctrack_type;
2695 }
2696
2697 /* slurm_get_slurmd_port
2698 * returns slurmd port from slurmctld_conf object
2699 * RET uint16_t - slurmd port
2700 */
slurm_get_slurmd_port(void)2701 uint16_t slurm_get_slurmd_port(void)
2702 {
2703 uint16_t slurmd_port = 0;
2704 slurm_ctl_conf_t *conf;
2705
2706 if (slurmdbd_conf) {
2707 } else {
2708 conf = slurm_conf_lock();
2709 slurmd_port = conf->slurmd_port;
2710 slurm_conf_unlock();
2711 }
2712 return slurmd_port;
2713 }
2714
2715 /* slurm_get_slurm_user_id
2716 * returns slurm uid from slurmctld_conf object
2717 * RET uint32_t - slurm user id
2718 */
slurm_get_slurm_user_id(void)2719 uint32_t slurm_get_slurm_user_id(void)
2720 {
2721 uint32_t slurm_uid = 0;
2722 slurm_ctl_conf_t *conf;
2723
2724 if (slurmdbd_conf) {
2725 slurm_uid = slurmdbd_conf->slurm_user_id;
2726 } else {
2727 conf = slurm_conf_lock();
2728 slurm_uid = conf->slurm_user_id;
2729 slurm_conf_unlock();
2730 }
2731 return slurm_uid;
2732 }
2733
2734 /* slurm_get_slurmd_user_id
2735 * returns slurmd uid from slurmctld_conf object
2736 * RET uint32_t - slurmd user id
2737 */
slurm_get_slurmd_user_id(void)2738 uint32_t slurm_get_slurmd_user_id(void)
2739 {
2740 uint32_t slurmd_uid = 0;
2741 slurm_ctl_conf_t *conf;
2742
2743 if (slurmdbd_conf) {
2744 } else {
2745 conf = slurm_conf_lock();
2746 slurmd_uid = conf->slurmd_user_id;
2747 slurm_conf_unlock();
2748 }
2749 return slurmd_uid;
2750 }
2751
2752 /*
2753 * slurm_get_slurmd_params
2754 * RET slurmd_params must be xfreed by caller
2755 */
slurm_get_slurmd_params(void)2756 char *slurm_get_slurmd_params(void)
2757 {
2758 char *slurmd_params = NULL;
2759 slurm_ctl_conf_t *conf;
2760
2761 if (slurmdbd_conf) {
2762 } else {
2763 conf = slurm_conf_lock();
2764 slurmd_params = xstrdup(conf->slurmd_params);
2765 slurm_conf_unlock();
2766 }
2767 return slurmd_params;
2768 }
2769
2770 /*
2771 * slurm_get_slurmctld_params
2772 * RET slurmctld_params must be xfreed by caller
2773 */
slurm_get_slurmctld_params(void)2774 char *slurm_get_slurmctld_params(void)
2775 {
2776 char *slurmctld_params = NULL;
2777 slurm_ctl_conf_t *conf;
2778
2779 if (slurmdbd_conf) {
2780 } else {
2781 conf = slurm_conf_lock();
2782 slurmctld_params = xstrdup(conf->slurmctld_params);
2783 slurm_conf_unlock();
2784 }
2785 return slurmctld_params;
2786 }
2787
2788 /* slurm_get_sched_params
2789 * RET char * - Value of SchedulerParameters, MUST be xfreed by caller */
slurm_get_sched_params(void)2790 extern char *slurm_get_sched_params(void)
2791 {
2792 char *params = 0;
2793 slurm_ctl_conf_t *conf;
2794
2795 if (slurmdbd_conf) {
2796 } else {
2797 conf = slurm_conf_lock();
2798 params = xstrdup(conf->sched_params);
2799 slurm_conf_unlock();
2800 }
2801 return params;
2802 }
2803
2804 /* slurm_get_sched_type
2805 * get sched type from slurmctld_conf object
2806 * RET char * - sched type, MUST be xfreed by caller
2807 */
slurm_get_sched_type(void)2808 char *slurm_get_sched_type(void)
2809 {
2810 char *sched_type = NULL;
2811 slurm_ctl_conf_t *conf;
2812
2813 if (slurmdbd_conf) {
2814 } else {
2815 conf = slurm_conf_lock();
2816 sched_type = xstrdup(conf->schedtype);
2817 slurm_conf_unlock();
2818 }
2819 return sched_type;
2820 }
2821
2822 /* slurm_get_select_type
2823 * get select_type from slurmctld_conf object
2824 * RET char * - select_type, MUST be xfreed by caller
2825 */
slurm_get_select_type(void)2826 char *slurm_get_select_type(void)
2827 {
2828 char *select_type = NULL;
2829 slurm_ctl_conf_t *conf;
2830
2831 if (slurmdbd_conf) {
2832 } else {
2833 conf = slurm_conf_lock();
2834 select_type = xstrdup(conf->select_type);
2835 slurm_conf_unlock();
2836 }
2837 return select_type;
2838 }
2839
2840 /* slurm_get_select_type_param
2841 * get select_type_param from slurmctld_conf object
2842 * RET uint16_t - select_type_param
2843 */
slurm_get_select_type_param(void)2844 uint16_t slurm_get_select_type_param(void)
2845 {
2846 uint16_t select_type_param = 0;
2847 slurm_ctl_conf_t *conf;
2848
2849 if (slurmdbd_conf) {
2850 } else {
2851 conf = slurm_conf_lock();
2852 select_type_param = conf->select_type_param;
2853 slurm_conf_unlock();
2854 }
2855 return select_type_param;
2856 }
2857
2858 /* slurm_set_select_type_param
2859 * set select_type_param for slurmctld_conf object
2860 * IN uint16_t - select_type_param
2861 */
slurm_set_select_type_param(uint16_t select_type_param)2862 void slurm_set_select_type_param(uint16_t select_type_param)
2863 {
2864 slurm_ctl_conf_t *conf;
2865
2866 if (slurmdbd_conf) {
2867 } else {
2868 conf = slurm_conf_lock();
2869 conf->select_type_param = select_type_param;
2870 slurm_conf_unlock();
2871 }
2872 }
2873
2874 /** Return true if (remote) system runs Cray Aries */
is_cray_select_type(void)2875 bool is_cray_select_type(void)
2876 {
2877 bool result = false;
2878
2879 if (slurmdbd_conf) {
2880 } else {
2881 slurm_ctl_conf_t *conf = slurm_conf_lock();
2882 result = !xstrcasecmp(conf->select_type, "select/cray_aries");
2883 slurm_conf_unlock();
2884 }
2885 return result;
2886 }
2887
2888 /* slurm_get_switch_type
2889 * get switch type from slurmctld_conf object
2890 * RET char * - switch type, MUST be xfreed by caller
2891 */
slurm_get_switch_type(void)2892 char *slurm_get_switch_type(void)
2893 {
2894 char *switch_type = NULL;
2895 slurm_ctl_conf_t *conf;
2896
2897 conf = slurm_conf_lock();
2898 switch_type = xstrdup(conf->switch_type);
2899 slurm_conf_unlock();
2900 return switch_type;
2901 }
2902
2903 /* slurm_get_wait_time
2904 * returns wait_time from slurmctld_conf object
2905 * RET uint16_t - wait_time
2906 */
slurm_get_wait_time(void)2907 uint16_t slurm_get_wait_time(void)
2908 {
2909 uint16_t wait_time = 0;
2910 slurm_ctl_conf_t *conf;
2911
2912 if (slurmdbd_conf) {
2913 } else {
2914 conf = slurm_conf_lock();
2915 wait_time = conf->wait_time;
2916 slurm_conf_unlock();
2917 }
2918 return wait_time;
2919 }
2920
2921 /* slurm_get_srun_prolog
2922 * return the name of the srun prolog program
2923 * RET char * - name of prolog program, must be xfreed by caller
2924 */
slurm_get_srun_prolog(void)2925 char *slurm_get_srun_prolog(void)
2926 {
2927 char *prolog = NULL;
2928 slurm_ctl_conf_t *conf;
2929
2930 if (slurmdbd_conf) {
2931 } else {
2932 conf = slurm_conf_lock();
2933 prolog = xstrdup(conf->srun_prolog);
2934 slurm_conf_unlock();
2935 }
2936 return prolog;
2937 }
2938
2939 /* slurm_get_srun_epilog
2940 * return the name of the srun epilog program
2941 * RET char * - name of epilog program, must be xfreed by caller
2942 */
slurm_get_srun_epilog(void)2943 char *slurm_get_srun_epilog(void)
2944 {
2945 char *epilog = NULL;
2946 slurm_ctl_conf_t *conf;
2947
2948 if (slurmdbd_conf) {
2949 } else {
2950 conf = slurm_conf_lock();
2951 epilog = xstrdup(conf->srun_epilog);
2952 slurm_conf_unlock();
2953 }
2954 return epilog;
2955 }
2956
2957 /* slurm_get_task_epilog
2958 * RET task_epilog name, must be xfreed by caller */
slurm_get_task_epilog(void)2959 char *slurm_get_task_epilog(void)
2960 {
2961 char *task_epilog = NULL;
2962 slurm_ctl_conf_t *conf;
2963
2964 if (slurmdbd_conf) {
2965 } else {
2966 conf = slurm_conf_lock();
2967 task_epilog = xstrdup(conf->task_epilog);
2968 slurm_conf_unlock();
2969 }
2970 return task_epilog;
2971 }
2972
2973 /* slurm_get_task_prolog
2974 * RET task_prolog name, must be xfreed by caller */
slurm_get_task_prolog(void)2975 char *slurm_get_task_prolog(void)
2976 {
2977 char *task_prolog = NULL;
2978 slurm_ctl_conf_t *conf;
2979
2980 if (slurmdbd_conf) {
2981 } else {
2982 conf = slurm_conf_lock();
2983 task_prolog = xstrdup(conf->task_prolog);
2984 slurm_conf_unlock();
2985 }
2986 return task_prolog;
2987 }
2988
2989 /* slurm_get_srun_port_range()
2990 */
2991 uint16_t *
slurm_get_srun_port_range(void)2992 slurm_get_srun_port_range(void)
2993 {
2994 uint16_t *ports = NULL;
2995 slurm_ctl_conf_t *conf;
2996
2997 if (slurmdbd_conf) {
2998 } else {
2999 conf = slurm_conf_lock();
3000 ports = conf->srun_port_range;
3001 slurm_conf_unlock();
3002 }
3003 return ports; /* CLANG false positive */
3004 }
3005
3006 /* slurm_get_task_plugin
3007 * RET task_plugin name, must be xfreed by caller */
slurm_get_task_plugin(void)3008 char *slurm_get_task_plugin(void)
3009 {
3010 char *task_plugin = NULL;
3011 slurm_ctl_conf_t *conf;
3012
3013 conf = slurm_conf_lock();
3014 task_plugin = xstrdup(conf->task_plugin);
3015 slurm_conf_unlock();
3016 return task_plugin;
3017 }
3018
3019 /* slurm_get_task_plugin_param */
slurm_get_task_plugin_param(void)3020 uint32_t slurm_get_task_plugin_param(void)
3021 {
3022 uint32_t task_plugin_param = 0;
3023 slurm_ctl_conf_t *conf;
3024
3025 if (slurmdbd_conf) {
3026 } else {
3027 conf = slurm_conf_lock();
3028 task_plugin_param = conf->task_plugin_param;
3029 slurm_conf_unlock();
3030 }
3031 return task_plugin_param;
3032 }
3033
3034 /* Get SchedulerTimeSlice (secs) */
slurm_get_time_slice(void)3035 uint16_t slurm_get_time_slice(void)
3036 {
3037 uint16_t sched_time_slice = 0;
3038 slurm_ctl_conf_t *conf;
3039
3040 if (slurmdbd_conf) {
3041 } else {
3042 conf = slurm_conf_lock();
3043 sched_time_slice = conf->sched_time_slice;
3044 slurm_conf_unlock();
3045 }
3046 return sched_time_slice;
3047 }
3048
3049 /* slurm_get_core_spec_plugin
3050 * RET core_spec plugin name, must be xfreed by caller */
slurm_get_core_spec_plugin(void)3051 char *slurm_get_core_spec_plugin(void)
3052 {
3053 char *core_spec_plugin = NULL;
3054 slurm_ctl_conf_t *conf;
3055
3056 conf = slurm_conf_lock();
3057 core_spec_plugin = xstrdup(conf->core_spec_plugin);
3058 slurm_conf_unlock();
3059 return core_spec_plugin;
3060 }
3061
3062 /* slurm_get_job_container_plugin
3063 * RET job_container plugin name, must be xfreed by caller */
slurm_get_job_container_plugin(void)3064 char *slurm_get_job_container_plugin(void)
3065 {
3066 char *job_container_plugin = NULL;
3067 slurm_ctl_conf_t *conf;
3068
3069 conf = slurm_conf_lock();
3070 job_container_plugin = xstrdup(conf->job_container_plugin);
3071 slurm_conf_unlock();
3072 return job_container_plugin;
3073 }
3074
3075 /* slurm_get_slurmd_spooldir
3076 * RET slurmd_spooldir name, must be xfreed by caller */
slurm_get_slurmd_spooldir(char * node_name)3077 char *slurm_get_slurmd_spooldir(char *node_name)
3078 {
3079 char *slurmd_spooldir = NULL;
3080 slurm_ctl_conf_t *conf;
3081
3082 if (slurmdbd_conf) {
3083 } else {
3084 conf = slurm_conf_lock();
3085 if (!node_name)
3086 slurmd_spooldir = xstrdup(conf->slurmd_spooldir);
3087 else
3088 slurmd_spooldir = slurm_conf_expand_slurmd_path(
3089 conf->slurmd_spooldir, node_name);
3090 slurm_conf_unlock();
3091 }
3092 return slurmd_spooldir;
3093 }
3094
3095 /* slurm_get_layouts
3096 * RET comma seperated list of layouts in a string, must be xfreed by caller */
slurm_get_layouts(void)3097 char *slurm_get_layouts(void)
3098 {
3099 char* layouts = NULL;
3100 slurm_ctl_conf_t *conf;
3101
3102 if (slurmdbd_conf) {
3103 layouts = xstrdup("");
3104 } else {
3105 conf = slurm_conf_lock();
3106 layouts = xstrdup(conf->layouts);
3107 slurm_conf_unlock();
3108 }
3109 return layouts;
3110 }
3111
3112 /* slurm_get_srun_eio_timeout()
3113 */
3114 int16_t
slurm_get_srun_eio_timeout(void)3115 slurm_get_srun_eio_timeout(void)
3116 {
3117 int16_t eio_timeout = 0;
3118 slurm_ctl_conf_t *conf;
3119
3120 if (slurmdbd_conf) {
3121 } else {
3122 conf = slurm_conf_lock();
3123 eio_timeout = conf->eio_timeout;
3124 slurm_conf_unlock();
3125 }
3126 return eio_timeout;
3127 }
3128
3129 /* Change general slurm communication errors to slurmctld specific errors */
_remap_slurmctld_errno(void)3130 static void _remap_slurmctld_errno(void)
3131 {
3132 int err = slurm_get_errno();
3133
3134 if (err == SLURM_COMMUNICATIONS_CONNECTION_ERROR)
3135 slurm_seterrno(SLURMCTLD_COMMUNICATIONS_CONNECTION_ERROR);
3136 else if (err == SLURM_COMMUNICATIONS_SEND_ERROR)
3137 slurm_seterrno(SLURMCTLD_COMMUNICATIONS_SEND_ERROR);
3138 else if (err == SLURM_COMMUNICATIONS_RECEIVE_ERROR)
3139 slurm_seterrno(SLURMCTLD_COMMUNICATIONS_RECEIVE_ERROR);
3140 else if (err == SLURM_COMMUNICATIONS_SHUTDOWN_ERROR)
3141 slurm_seterrno(SLURMCTLD_COMMUNICATIONS_SHUTDOWN_ERROR);
3142 }
3143
3144 /**********************************************************************\
3145 * general message management functions used by slurmctld, slurmd
3146 \**********************************************************************/
3147
3148 /* In the socket implementation it creates a socket, binds to it, and
3149 * listens for connections. Retry if bind() or listen() fail
3150 * even if asked for an ephemeral port.
3151 *
3152 * IN port - port to bind the msg server to
3153 * RET int - file descriptor of the connection created
3154 */
slurm_init_msg_engine_port(uint16_t port)3155 int slurm_init_msg_engine_port(uint16_t port)
3156 {
3157 int cc;
3158 slurm_addr_t addr;
3159 int i;
3160
3161 slurm_setup_sockaddr(&addr, port);
3162 cc = slurm_init_msg_engine(&addr);
3163 if ((cc < 0) && (port == 0) && (errno == EADDRINUSE)) {
3164 /* All ephemeral ports are in use, test other ports */
3165 for (i = 10001; i < 65536; i++) {
3166 slurm_setup_sockaddr(&addr, i);
3167 cc = slurm_init_msg_engine(&addr);
3168 if (cc >= 0)
3169 break;
3170 }
3171 }
3172 return cc;
3173 }
3174
3175 /* slurm_init_msg_engine_ports()
3176 */
slurm_init_msg_engine_ports(uint16_t * ports)3177 int slurm_init_msg_engine_ports(uint16_t *ports)
3178 {
3179 int cc;
3180 int val;
3181 int s;
3182 int port;
3183
3184 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
3185 if (s < 0)
3186 return -1;
3187
3188 val = 1;
3189 cc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int));
3190 if (cc < 0) {
3191 close(s);
3192 return -1;
3193 }
3194
3195 port = sock_bind_range(s, ports, false);
3196 if (port < 0) {
3197 close(s);
3198 return -1;
3199 }
3200
3201 cc = listen(s, SLURM_DEFAULT_LISTEN_BACKLOG);
3202 if (cc < 0) {
3203 close(s);
3204 return -1;
3205 }
3206
3207 return s;
3208 }
3209
3210 /**********************************************************************\
3211 * msg connection establishment functions used by msg clients
3212 \**********************************************************************/
3213
3214 /* In the bsd socket implementation it creates a SOCK_STREAM socket
3215 * and calls connect on it a SOCK_DGRAM socket called with connect
3216 * is defined to only receive messages from the address/port pair
3217 * argument of the connect call slurm_address - for now it is
3218 * really just a sockaddr_in
3219 * IN slurm_address - slurm_addr_t of the connection destination
3220 * RET slurm_fd - file descriptor of the connection created
3221 */
slurm_open_msg_conn(slurm_addr_t * slurm_address)3222 int slurm_open_msg_conn(slurm_addr_t * slurm_address)
3223 {
3224 int fd = slurm_open_stream(slurm_address, false);
3225 if (fd >= 0)
3226 fd_set_close_on_exec(fd);
3227 return fd;
3228 }
3229
3230 /*
3231 * Calls connect to make a connection-less datagram connection
3232 * primary or secondary slurmctld message engine
3233 * IN/OUT addr - address of controller contacted
3234 * IN/OUT use_backup - IN: whether to try the backup first or not
3235 * OUT: set to true if connection established with backup
3236 * IN comm_cluster_rec - Communication record (host/port/version)/
3237 * RET slurm_fd - file descriptor of the connection created
3238 */
slurm_open_controller_conn(slurm_addr_t * addr,bool * use_backup,slurmdb_cluster_rec_t * comm_cluster_rec)3239 extern int slurm_open_controller_conn(slurm_addr_t *addr, bool *use_backup,
3240 slurmdb_cluster_rec_t *comm_cluster_rec)
3241 {
3242 int fd = -1;
3243 slurm_protocol_config_t *proto_conf = NULL;
3244 int i, retry, max_retry_period;
3245
3246 if (!comm_cluster_rec) {
3247 /* This means the addr wasn't set up already */
3248 if (!(proto_conf = _slurm_api_get_comm_config()))
3249 return SLURM_ERROR;
3250
3251 for (i = 0; i < proto_conf->control_cnt; i++) {
3252 proto_conf->controller_addr[i].sin_port =
3253 htons(slurmctld_conf.slurmctld_port +
3254 (((time(NULL) + getpid()) %
3255 slurmctld_conf.slurmctld_port_count)));
3256 }
3257
3258 if (proto_conf->vip_addr_set) {
3259 proto_conf->vip_addr.sin_port =
3260 htons(slurmctld_conf.slurmctld_port +
3261 (((time(NULL) + getpid()) %
3262 slurmctld_conf.slurmctld_port_count)));
3263 }
3264 }
3265
3266 #ifdef HAVE_NATIVE_CRAY
3267 max_retry_period = 180;
3268 #else
3269 max_retry_period = slurm_get_msg_timeout();
3270 #endif
3271 for (retry = 0; retry < max_retry_period; retry++) {
3272 if (retry)
3273 sleep(1);
3274 if (comm_cluster_rec) {
3275 if (comm_cluster_rec->control_addr.sin_port == 0) {
3276 slurm_set_addr(
3277 &comm_cluster_rec->control_addr,
3278 comm_cluster_rec->control_port,
3279 comm_cluster_rec->control_host);
3280 }
3281 addr = &comm_cluster_rec->control_addr;
3282
3283 fd = slurm_open_msg_conn(addr);
3284 if (fd >= 0)
3285 goto end_it;
3286 debug("Failed to contact controller: %m");
3287 } else if (proto_conf->vip_addr_set) {
3288 fd = slurm_open_msg_conn(&proto_conf->vip_addr);
3289 if (fd >= 0)
3290 goto end_it;
3291 debug("Failed to contact controller: %m");
3292 } else {
3293 if (!*use_backup) {
3294 fd = slurm_open_msg_conn(
3295 &proto_conf->controller_addr[0]);
3296 if (fd >= 0) {
3297 *use_backup = false;
3298 goto end_it;
3299 }
3300 debug("Failed to contact primary controller: %m");
3301 }
3302 if ((proto_conf->control_cnt > 1) || *use_backup) {
3303 for (i = 1; i < proto_conf->control_cnt; i++) {
3304 fd = slurm_open_msg_conn(
3305 &proto_conf->controller_addr[i]);
3306 if (fd >= 0) {
3307 debug("Contacted backup controller %d",
3308 (i - 1));
3309 *use_backup = true;
3310 goto end_it;
3311 }
3312 }
3313 *use_backup = false;
3314 debug("Failed to contact backup controller: %m");
3315 }
3316 }
3317 }
3318 addr = NULL;
3319 _slurm_api_free_comm_config(proto_conf);
3320 slurm_seterrno_ret(SLURMCTLD_COMMUNICATIONS_CONNECTION_ERROR);
3321
3322 end_it:
3323 _slurm_api_free_comm_config(proto_conf);
3324 return fd;
3325 }
3326
3327 /*
3328 * Calls connect to make a connection-less datagram connection to a specific
3329 * primary or backup slurmctld message engine
3330 * IN dest - controller to contact (0=primary, 1=backup, 2=backup2, etc.)
3331 * IN comm_cluster_rec - Communication record (host/port/version)/
3332 * RET int - file descriptor of the connection created
3333 */
slurm_open_controller_conn_spec(int dest,slurmdb_cluster_rec_t * comm_cluster_rec)3334 extern int slurm_open_controller_conn_spec(int dest,
3335 slurmdb_cluster_rec_t *comm_cluster_rec)
3336 {
3337 slurm_protocol_config_t *proto_conf = NULL;
3338 slurm_addr_t *addr;
3339 int rc;
3340
3341 if (comm_cluster_rec) {
3342 if (comm_cluster_rec->control_addr.sin_port == 0) {
3343 slurm_set_addr(
3344 &comm_cluster_rec->control_addr,
3345 comm_cluster_rec->control_port,
3346 comm_cluster_rec->control_host);
3347 }
3348 addr = &comm_cluster_rec->control_addr;
3349 } else { /* Some backup slurmctld */
3350 if (!(proto_conf = _slurm_api_get_comm_config())) {
3351 debug3("Error: Unable to set default config");
3352 return SLURM_ERROR;
3353 }
3354 addr = NULL;
3355 if ((dest >= 0) && (dest <= proto_conf->control_cnt))
3356 addr = &proto_conf->controller_addr[dest];
3357 if (!addr) {
3358 rc = SLURM_ERROR;
3359 goto fini;
3360 }
3361 }
3362
3363 rc = slurm_open_msg_conn(addr);
3364 if (rc == -1)
3365 _remap_slurmctld_errno();
3366 fini: _slurm_api_free_comm_config(proto_conf);
3367 return rc;
3368 }
3369
slurm_unpack_received_msg(slurm_msg_t * msg,int fd,Buf buffer)3370 extern int slurm_unpack_received_msg(slurm_msg_t *msg, int fd, Buf buffer)
3371 {
3372 header_t header;
3373 int rc;
3374 void *auth_cred = NULL;
3375
3376 if (unpack_header(&header, buffer) == SLURM_ERROR) {
3377 rc = SLURM_COMMUNICATIONS_RECEIVE_ERROR;
3378 goto total_return;
3379 }
3380
3381 if (check_header_version(&header) < 0) {
3382 slurm_addr_t resp_addr;
3383 char addr_str[32];
3384 int uid = _unpack_msg_uid(buffer, header.version);
3385
3386 if (!slurm_get_peer_addr(fd, &resp_addr)) {
3387 slurm_print_slurm_addr(
3388 &resp_addr, addr_str, sizeof(addr_str));
3389 error("%s: Invalid Protocol Version %u from uid=%d at %s",
3390 __func__, header.version, uid, addr_str);
3391 } else {
3392 error("%s: Invalid Protocol Version %u from uid=%d from "
3393 "problem connection: %m", __func__,
3394 header.version, uid);
3395 }
3396
3397 rc = SLURM_PROTOCOL_VERSION_ERROR;
3398 goto total_return;
3399 }
3400 //info("ret_cnt = %d",header.ret_cnt);
3401 if (header.ret_cnt > 0) {
3402 error("%s: we received more than one message back use "
3403 "slurm_receive_msgs instead", __func__);
3404 header.ret_cnt = 0;
3405 FREE_NULL_LIST(header.ret_list);
3406 header.ret_list = NULL;
3407 }
3408
3409 /* Forward message to other nodes */
3410 if (header.forward.cnt > 0) {
3411 error("%s: We need to forward this to other nodes use "
3412 "slurm_receive_msg_and_forward instead", __func__);
3413 }
3414
3415 if ((auth_cred = g_slurm_auth_unpack(buffer, header.version)) == NULL) {
3416 error("%s: authentication: %m", __func__);
3417 rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3418 goto total_return;
3419 }
3420 msg->auth_index = slurm_auth_index(auth_cred);
3421 if (header.flags & SLURM_GLOBAL_AUTH_KEY) {
3422 rc = g_slurm_auth_verify(auth_cred, _global_auth_key());
3423 } else {
3424 char *auth_info = slurm_get_auth_info();
3425 rc = g_slurm_auth_verify(auth_cred, auth_info);
3426 xfree(auth_info);
3427 }
3428
3429 if (rc != SLURM_SUCCESS) {
3430 error("%s: %s has authentication error: %s",
3431 __func__, rpc_num2string(header.msg_type),
3432 slurm_strerror(rc));
3433 (void) g_slurm_auth_destroy(auth_cred);
3434 rc = SLURM_PROTOCOL_AUTHENTICATION_ERROR;
3435 goto total_return;
3436 }
3437
3438 /*
3439 * Unpack message body
3440 */
3441 msg->protocol_version = header.version;
3442 msg->msg_type = header.msg_type;
3443 msg->flags = header.flags;
3444
3445 msg->body_offset = get_buf_offset(buffer);
3446
3447 if ((header.body_length > remaining_buf(buffer)) ||
3448 (unpack_msg(msg, buffer) != SLURM_SUCCESS)) {
3449 rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3450 (void) g_slurm_auth_destroy(auth_cred);
3451 goto total_return;
3452 }
3453
3454 msg->auth_cred = (void *)auth_cred;
3455
3456 rc = SLURM_SUCCESS;
3457
3458 total_return:
3459 destroy_forward(&header.forward);
3460
3461 slurm_seterrno(rc);
3462 if (rc != SLURM_SUCCESS) {
3463 msg->auth_cred = (void *) NULL;
3464 error("%s: %s", __func__, slurm_strerror(rc));
3465 rc = -1;
3466 usleep(10000); /* Discourage brute force attack */
3467 } else {
3468 rc = 0;
3469 }
3470 return rc;
3471 }
3472
3473 /**********************************************************************\
3474 * receive message functions
3475 \**********************************************************************/
3476
3477 /*
3478 * NOTE: memory is allocated for the returned msg must be freed at
3479 * some point using the slurm_free_functions.
3480 * IN fd - file descriptor to receive msg on
3481 * OUT msg - a slurm_msg struct to be filled in by the function
3482 * IN timeout - how long to wait in milliseconds
3483 * RET int - returns 0 on success, -1 on failure and sets errno
3484 */
slurm_receive_msg(int fd,slurm_msg_t * msg,int timeout)3485 int slurm_receive_msg(int fd, slurm_msg_t *msg, int timeout)
3486 {
3487 char *buf = NULL;
3488 size_t buflen = 0;
3489 int rc;
3490 Buf buffer;
3491 bool keep_buffer = false;
3492
3493 if (msg->flags & SLURM_MSG_KEEP_BUFFER)
3494 keep_buffer = true;
3495
3496 if (msg->conn) {
3497 persist_msg_t persist_msg;
3498
3499 buffer = slurm_persist_recv_msg(msg->conn);
3500 if (!buffer) {
3501 error("%s: No response to persist_init", __func__);
3502 slurm_persist_conn_close(msg->conn);
3503 return SLURM_ERROR;
3504 }
3505 memset(&persist_msg, 0, sizeof(persist_msg_t));
3506 rc = slurm_persist_msg_unpack(msg->conn, &persist_msg, buffer);
3507
3508 if (keep_buffer)
3509 msg->buffer = buffer;
3510 else
3511 free_buf(buffer);
3512
3513 if (rc) {
3514 error("%s: Failed to unpack persist msg", __func__);
3515 slurm_persist_conn_close(msg->conn);
3516 return SLURM_ERROR;
3517 }
3518
3519 msg->msg_type = persist_msg.msg_type;
3520 msg->data = persist_msg.data;
3521
3522 return SLURM_SUCCESS;
3523 }
3524
3525 xassert(fd >= 0);
3526
3527 msg->conn_fd = fd;
3528
3529 if (timeout <= 0)
3530 /* convert secs to msec */
3531 timeout = slurm_get_msg_timeout() * MSEC_IN_SEC;
3532
3533 else if (timeout > (slurm_get_msg_timeout() * MSEC_IN_SEC * 10)) {
3534 /* consider 10x the timeout to be very long */
3535 debug("%s: You are receiving a message with very long "
3536 "timeout of %d seconds", __func__,
3537 (timeout / MSEC_IN_SEC));
3538 } else if (timeout < MSEC_IN_SEC) {
3539 /* consider a less than 1 second to be very short */
3540 error("%s: You are receiving a message with a very short "
3541 "timeout of %d msecs", __func__, timeout);
3542 }
3543
3544 /*
3545 * Receive a msg. slurm_msg_recvfrom() will read the message
3546 * length and allocate space on the heap for a buffer containing
3547 * the message.
3548 */
3549 if (slurm_msg_recvfrom_timeout(fd, &buf, &buflen, 0, timeout) < 0) {
3550 rc = errno;
3551 goto endit;
3552 }
3553
3554 #if _DEBUG
3555 _print_data (buf, buflen);
3556 #endif
3557 buffer = create_buf(buf, buflen);
3558
3559 rc = slurm_unpack_received_msg(msg, fd, buffer);
3560
3561 if (keep_buffer)
3562 msg->buffer = buffer;
3563 else
3564 free_buf(buffer);
3565
3566 endit:
3567 slurm_seterrno(rc);
3568
3569 return rc;
3570 }
3571
3572 /*
3573 * NOTE: memory is allocated for the returned list
3574 * and must be freed at some point using the list_destroy function.
3575 * IN open_fd - file descriptor to receive msg on
3576 * IN steps - how many steps down the tree we have to wait for
3577 * IN timeout - how long to wait in milliseconds
3578 * RET List - List containing the responses of the children (if any) we
3579 * forwarded the message to. List containing type
3580 * (ret_data_info_t).
3581 */
slurm_receive_msgs(int fd,int steps,int timeout)3582 List slurm_receive_msgs(int fd, int steps, int timeout)
3583 {
3584 char *buf = NULL;
3585 size_t buflen = 0;
3586 header_t header;
3587 int rc;
3588 void *auth_cred = NULL;
3589 slurm_msg_t msg;
3590 Buf buffer;
3591 ret_data_info_t *ret_data_info = NULL;
3592 List ret_list = NULL;
3593 int orig_timeout = timeout;
3594
3595 xassert(fd >= 0);
3596
3597 slurm_msg_t_init(&msg);
3598 msg.conn_fd = fd;
3599
3600 if (timeout <= 0) {
3601 /* convert secs to msec */
3602 timeout = slurm_get_msg_timeout() * 1000;
3603 orig_timeout = timeout;
3604 }
3605 if (steps) {
3606 if (message_timeout < 0)
3607 message_timeout = slurm_get_msg_timeout() * 1000;
3608 orig_timeout = (timeout -
3609 (message_timeout*(steps-1)))/steps;
3610 steps--;
3611 }
3612
3613 debug4("orig_timeout was %d we have %d steps and a timeout of %d",
3614 orig_timeout, steps, timeout);
3615 /* we compare to the orig_timeout here because that is really
3616 * what we are going to wait for each step
3617 */
3618 if (orig_timeout >= (slurm_get_msg_timeout() * 10000)) {
3619 debug("slurm_receive_msgs: "
3620 "You are sending a message with timeout's greater "
3621 "than %d seconds, your's is %d seconds",
3622 (slurm_get_msg_timeout() * 10),
3623 (timeout/1000));
3624 } else if (orig_timeout < 1000) {
3625 debug("slurm_receive_msgs: "
3626 "You are sending a message with a very short timeout of "
3627 "%d milliseconds each step in the tree has %d "
3628 "milliseconds", timeout, orig_timeout);
3629 }
3630
3631
3632 /*
3633 * Receive a msg. slurm_msg_recvfrom() will read the message
3634 * length and allocate space on the heap for a buffer containing
3635 * the message.
3636 */
3637 if (slurm_msg_recvfrom_timeout(fd, &buf, &buflen, 0, timeout) < 0) {
3638 forward_init(&header.forward);
3639 rc = errno;
3640 goto total_return;
3641 }
3642
3643 #if _DEBUG
3644 _print_data (buf, buflen);
3645 #endif
3646 buffer = create_buf(buf, buflen);
3647
3648 if (unpack_header(&header, buffer) == SLURM_ERROR) {
3649 free_buf(buffer);
3650 rc = SLURM_COMMUNICATIONS_RECEIVE_ERROR;
3651 goto total_return;
3652 }
3653
3654 if (check_header_version(&header) < 0) {
3655 slurm_addr_t resp_addr;
3656 char addr_str[32];
3657 int uid = _unpack_msg_uid(buffer, header.version);
3658 if (!slurm_get_peer_addr(fd, &resp_addr)) {
3659 slurm_print_slurm_addr(
3660 &resp_addr, addr_str, sizeof(addr_str));
3661 error("Invalid Protocol Version %u from uid=%d at %s",
3662 header.version, uid, addr_str);
3663 } else {
3664 error("Invalid Protocol Version %u from uid=%d from "
3665 "problem connection: %m",
3666 header.version, uid);
3667 }
3668
3669 free_buf(buffer);
3670 rc = SLURM_PROTOCOL_VERSION_ERROR;
3671 goto total_return;
3672 }
3673 //info("ret_cnt = %d",header.ret_cnt);
3674 if (header.ret_cnt > 0) {
3675 if (header.ret_list)
3676 ret_list = header.ret_list;
3677 else
3678 ret_list = list_create(destroy_data_info);
3679 header.ret_cnt = 0;
3680 header.ret_list = NULL;
3681 }
3682
3683 /* Forward message to other nodes */
3684 if (header.forward.cnt > 0) {
3685 error("We need to forward this to other nodes use "
3686 "slurm_receive_msg_and_forward instead");
3687 }
3688
3689 if ((auth_cred = g_slurm_auth_unpack(buffer, header.version)) == NULL) {
3690 error("%s: authentication: %m", __func__);
3691 free_buf(buffer);
3692 rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3693 goto total_return;
3694 }
3695 msg.auth_index = slurm_auth_index(auth_cred);
3696 if (header.flags & SLURM_GLOBAL_AUTH_KEY) {
3697 rc = g_slurm_auth_verify(auth_cred, _global_auth_key());
3698 } else {
3699 char *auth_info = slurm_get_auth_info();
3700 rc = g_slurm_auth_verify(auth_cred, auth_info);
3701 xfree(auth_info);
3702 }
3703
3704 if (rc != SLURM_SUCCESS) {
3705 error("%s: %s has authentication error: %m",
3706 __func__, rpc_num2string(header.msg_type));
3707 (void) g_slurm_auth_destroy(auth_cred);
3708 free_buf(buffer);
3709 rc = SLURM_PROTOCOL_AUTHENTICATION_ERROR;
3710 goto total_return;
3711 }
3712
3713 /*
3714 * Unpack message body
3715 */
3716 msg.protocol_version = header.version;
3717 msg.msg_type = header.msg_type;
3718 msg.flags = header.flags;
3719
3720 if ((header.body_length > remaining_buf(buffer)) ||
3721 (unpack_msg(&msg, buffer) != SLURM_SUCCESS)) {
3722 (void) g_slurm_auth_destroy(auth_cred);
3723 free_buf(buffer);
3724 rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3725 goto total_return;
3726 }
3727 g_slurm_auth_destroy(auth_cred);
3728
3729 free_buf(buffer);
3730 rc = SLURM_SUCCESS;
3731
3732 total_return:
3733 destroy_forward(&header.forward);
3734
3735 if (rc != SLURM_SUCCESS) {
3736 if (ret_list) {
3737 ret_data_info = xmalloc(sizeof(ret_data_info_t));
3738 ret_data_info->err = rc;
3739 ret_data_info->type = RESPONSE_FORWARD_FAILED;
3740 ret_data_info->data = NULL;
3741 list_push(ret_list, ret_data_info);
3742 }
3743 error("slurm_receive_msgs: %s", slurm_strerror(rc));
3744 usleep(10000); /* Discourage brute force attack */
3745 } else {
3746 if (!ret_list)
3747 ret_list = list_create(destroy_data_info);
3748 ret_data_info = xmalloc(sizeof(ret_data_info_t));
3749 ret_data_info->err = rc;
3750 ret_data_info->node_name = NULL;
3751 ret_data_info->type = msg.msg_type;
3752 ret_data_info->data = msg.data;
3753 list_push(ret_list, ret_data_info);
3754 }
3755
3756
3757 errno = rc;
3758 return ret_list;
3759
3760 }
3761
3762 /* try to determine the UID associated with a message with different
3763 * message header version, return -1 if we can't tell */
_unpack_msg_uid(Buf buffer,uint16_t protocol_version)3764 static int _unpack_msg_uid(Buf buffer, uint16_t protocol_version)
3765 {
3766 int uid = -1;
3767 void *auth_cred = NULL, *auth_info;
3768
3769 if ((auth_cred = g_slurm_auth_unpack(buffer, protocol_version)) == NULL)
3770 return uid;
3771 auth_info = slurm_get_auth_info();
3772 if (g_slurm_auth_verify(auth_cred, auth_info)) {
3773 xfree(auth_info);
3774 return uid;
3775 }
3776 xfree(auth_info);
3777 uid = (int) g_slurm_auth_get_uid(auth_cred);
3778 g_slurm_auth_destroy(auth_cred);
3779
3780 return uid;
3781 }
3782
3783 /*
3784 * NOTE: memory is allocated for the returned msg and the returned list
3785 * both must be freed at some point using the slurm_free_functions
3786 * and list_destroy function.
3787 * IN open_fd - file descriptor to receive msg on
3788 * IN/OUT msg - a slurm_msg struct to be filled in by the function
3789 * we use the orig_addr from this var for forwarding.
3790 * IN timeout - how long to wait in milliseconds
3791 * RET int - returns 0 on success, -1 on failure and sets errno
3792 */
slurm_receive_msg_and_forward(int fd,slurm_addr_t * orig_addr,slurm_msg_t * msg,int timeout)3793 int slurm_receive_msg_and_forward(int fd, slurm_addr_t *orig_addr,
3794 slurm_msg_t *msg, int timeout)
3795 {
3796 char *buf = NULL;
3797 size_t buflen = 0;
3798 header_t header;
3799 int rc;
3800 void *auth_cred = NULL;
3801 Buf buffer;
3802
3803 xassert(fd >= 0);
3804
3805 if (msg->forward.init != FORWARD_INIT)
3806 slurm_msg_t_init(msg);
3807 /* set msg connection fd to accepted fd. This allows
3808 * possibility for slurmd_req () to close accepted connection
3809 */
3810 msg->conn_fd = fd;
3811 /* this always is the connection */
3812 memcpy(&msg->address, orig_addr, sizeof(slurm_addr_t));
3813
3814 /* where the connection originated from, this
3815 * might change based on the header we receive */
3816 memcpy(&msg->orig_addr, orig_addr, sizeof(slurm_addr_t));
3817
3818 msg->ret_list = list_create(destroy_data_info);
3819
3820 if (timeout <= 0) {
3821 /* convert secs to msec */
3822 timeout = slurm_get_msg_timeout() * 1000;
3823 } else if (timeout < 1000) {
3824 debug("%s: You are sending a message with a very short timeout of %d milliseconds",
3825 __func__, timeout);
3826 } else if (timeout >= (slurm_get_msg_timeout() * 10000)) {
3827 debug("slurm_receive_msg_and_forward: "
3828 "You are sending a message with timeout's greater "
3829 "than %d seconds, your's is %d seconds",
3830 (slurm_get_msg_timeout() * 10),
3831 (timeout/1000));
3832 }
3833
3834 /*
3835 * Receive a msg. slurm_msg_recvfrom() will read the message
3836 * length and allocate space on the heap for a buffer containing
3837 * the message.
3838 */
3839 if (slurm_msg_recvfrom_timeout(fd, &buf, &buflen, 0, timeout) < 0) {
3840 forward_init(&header.forward);
3841 rc = errno;
3842 goto total_return;
3843 }
3844
3845 #if _DEBUG
3846 _print_data (buf, buflen);
3847 #endif
3848 buffer = create_buf(buf, buflen);
3849
3850 if (unpack_header(&header, buffer) == SLURM_ERROR) {
3851 free_buf(buffer);
3852 rc = SLURM_COMMUNICATIONS_RECEIVE_ERROR;
3853 goto total_return;
3854 }
3855
3856 if (check_header_version(&header) < 0) {
3857 slurm_addr_t resp_addr;
3858 char addr_str[32];
3859 int uid = _unpack_msg_uid(buffer, header.version);
3860
3861 if (!slurm_get_peer_addr(fd, &resp_addr)) {
3862 slurm_print_slurm_addr(
3863 &resp_addr, addr_str, sizeof(addr_str));
3864 error("Invalid Protocol Version %u from uid=%d at %s",
3865 header.version, uid, addr_str);
3866 } else {
3867 error("Invalid Protocol Version %u from uid=%d from "
3868 "problem connection: %m",
3869 header.version, uid);
3870 }
3871
3872 free_buf(buffer);
3873 rc = SLURM_PROTOCOL_VERSION_ERROR;
3874 goto total_return;
3875 }
3876 if (header.ret_cnt > 0) {
3877 error("we received more than one message back use "
3878 "slurm_receive_msgs instead");
3879 header.ret_cnt = 0;
3880 FREE_NULL_LIST(header.ret_list);
3881 header.ret_list = NULL;
3882 }
3883
3884 /*
3885 * header.orig_addr will be set to where the first message
3886 * came from if this is a forward else we set the
3887 * header.orig_addr to our addr just in case we need to send it off.
3888 */
3889 if (header.orig_addr.sin_addr.s_addr != 0) {
3890 memcpy(&msg->orig_addr, &header.orig_addr, sizeof(slurm_addr_t));
3891 } else {
3892 memcpy(&header.orig_addr, orig_addr, sizeof(slurm_addr_t));
3893 }
3894
3895 /* Forward message to other nodes */
3896 if (header.forward.cnt > 0) {
3897 debug2("forwarding to %u", header.forward.cnt);
3898 msg->forward_struct = xmalloc(sizeof(forward_struct_t));
3899 slurm_mutex_init(&msg->forward_struct->forward_mutex);
3900 slurm_cond_init(&msg->forward_struct->notify, NULL);
3901
3902 msg->forward_struct->buf_len = remaining_buf(buffer);
3903 msg->forward_struct->buf =
3904 xmalloc(msg->forward_struct->buf_len);
3905 memcpy(msg->forward_struct->buf,
3906 &buffer->head[buffer->processed],
3907 msg->forward_struct->buf_len);
3908
3909 msg->forward_struct->ret_list = msg->ret_list;
3910 /* take out the amount of timeout from this hop */
3911 msg->forward_struct->timeout = header.forward.timeout;
3912 if (!msg->forward_struct->timeout)
3913 msg->forward_struct->timeout = message_timeout;
3914 msg->forward_struct->fwd_cnt = header.forward.cnt;
3915
3916 debug3("forwarding messages to %u nodes with timeout of %d",
3917 msg->forward_struct->fwd_cnt,
3918 msg->forward_struct->timeout);
3919
3920 if (forward_msg(msg->forward_struct, &header) == SLURM_ERROR) {
3921 error("problem with forward msg");
3922 }
3923 }
3924
3925 if ((auth_cred = g_slurm_auth_unpack(buffer, header.version)) == NULL) {
3926 error("%s: authentication: %m", __func__);
3927 free_buf(buffer);
3928 rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3929 goto total_return;
3930 }
3931 msg->auth_index = slurm_auth_index(auth_cred);
3932 if (header.flags & SLURM_GLOBAL_AUTH_KEY) {
3933 rc = g_slurm_auth_verify(auth_cred, _global_auth_key());
3934 } else {
3935 char *auth_info = slurm_get_auth_info();
3936 rc = g_slurm_auth_verify(auth_cred, auth_info);
3937 xfree(auth_info);
3938 }
3939
3940 if (rc != SLURM_SUCCESS) {
3941 error("%s: %s has authentication error: %m",
3942 __func__, rpc_num2string(header.msg_type));
3943 (void) g_slurm_auth_destroy(auth_cred);
3944 free_buf(buffer);
3945 rc = SLURM_PROTOCOL_AUTHENTICATION_ERROR;
3946 goto total_return;
3947 }
3948
3949 /*
3950 * Unpack message body
3951 */
3952 msg->protocol_version = header.version;
3953 msg->msg_type = header.msg_type;
3954 msg->flags = header.flags;
3955
3956 if (header.msg_type == MESSAGE_COMPOSITE) {
3957 slurm_send_rc_msg(msg, SLURM_SUCCESS);
3958 msg_aggr_add_comp(buffer, auth_cred, &header);
3959 goto total_return;
3960 }
3961
3962 if ( (header.body_length > remaining_buf(buffer)) ||
3963 (unpack_msg(msg, buffer) != SLURM_SUCCESS) ) {
3964 (void) g_slurm_auth_destroy(auth_cred);
3965 free_buf(buffer);
3966 rc = ESLURM_PROTOCOL_INCOMPLETE_PACKET;
3967 goto total_return;
3968 }
3969 msg->auth_cred = (void *) auth_cred;
3970
3971 free_buf(buffer);
3972 rc = SLURM_SUCCESS;
3973
3974 total_return:
3975 destroy_forward(&header.forward);
3976
3977 slurm_seterrno(rc);
3978 if (rc != SLURM_SUCCESS) {
3979 msg->msg_type = RESPONSE_FORWARD_FAILED;
3980 msg->auth_cred = (void *) NULL;
3981 msg->data = NULL;
3982 error("slurm_receive_msg_and_forward: %s",
3983 slurm_strerror(rc));
3984 usleep(10000); /* Discourage brute force attack */
3985 } else {
3986 rc = 0;
3987 }
3988 return rc;
3989
3990 }
3991
3992 /**********************************************************************\
3993 * send message functions
3994 \**********************************************************************/
3995
3996 /*
3997 * Do the wonderful stuff that needs be done to pack msg
3998 * and hdr into buffer
3999 */
4000 static void
_pack_msg(slurm_msg_t * msg,header_t * hdr,Buf buffer)4001 _pack_msg(slurm_msg_t *msg, header_t *hdr, Buf buffer)
4002 {
4003 unsigned int tmplen, msglen;
4004
4005 tmplen = get_buf_offset(buffer);
4006 pack_msg(msg, buffer);
4007 msglen = get_buf_offset(buffer) - tmplen;
4008
4009 /* update header with correct cred and msg lengths */
4010 update_header(hdr, msglen);
4011
4012 /* repack updated header */
4013 tmplen = get_buf_offset(buffer);
4014 set_buf_offset(buffer, 0);
4015 pack_header(hdr, buffer);
4016 set_buf_offset(buffer, tmplen);
4017 }
4018
4019 /*
4020 * Send a slurm message over an open file descriptor `fd'
4021 * Returns the size of the message sent in bytes, or -1 on failure.
4022 */
slurm_send_node_msg(int fd,slurm_msg_t * msg)4023 int slurm_send_node_msg(int fd, slurm_msg_t * msg)
4024 {
4025 header_t header;
4026 Buf buffer;
4027 int rc;
4028 void * auth_cred;
4029 time_t start_time = time(NULL);
4030
4031 if (msg->conn) {
4032 persist_msg_t persist_msg;
4033
4034 memset(&persist_msg, 0, sizeof(persist_msg_t));
4035 persist_msg.msg_type = msg->msg_type;
4036 persist_msg.data = msg->data;
4037 persist_msg.data_size = msg->data_size;
4038
4039 buffer = slurm_persist_msg_pack(msg->conn, &persist_msg);
4040 if (!buffer) /* pack error */
4041 return SLURM_ERROR;
4042
4043 rc = slurm_persist_send_msg(msg->conn, buffer);
4044 free_buf(buffer);
4045
4046 if ((rc < 0) && (errno == ENOTCONN)) {
4047 debug3("slurm_persist_send_msg: persistent connection has disappeared for msg_type=%u",
4048 msg->msg_type);
4049 } else if (rc < 0) {
4050 slurm_addr_t peer_addr;
4051 char addr_str[32];
4052 if (!slurm_get_peer_addr(msg->conn->fd, &peer_addr)) {
4053 slurm_print_slurm_addr(
4054 &peer_addr, addr_str, sizeof(addr_str));
4055 error("slurm_persist_send_msg: address:port=%s msg_type=%u: %m",
4056 addr_str, msg->msg_type);
4057 } else
4058 error("slurm_persist_send_msg: msg_type=%u: %m",
4059 msg->msg_type);
4060 }
4061
4062 return rc;
4063 }
4064
4065 /*
4066 * Initialize header with Auth credential and message type.
4067 * We get the credential now rather than later so the work can
4068 * can be done in parallel with waiting for message to forward,
4069 * but we may need to generate the credential again later if we
4070 * wait too long for the incoming message.
4071 */
4072 if (msg->flags & SLURM_GLOBAL_AUTH_KEY) {
4073 auth_cred = g_slurm_auth_create(msg->auth_index,
4074 _global_auth_key());
4075 } else {
4076 char *auth_info = slurm_get_auth_info();
4077 auth_cred = g_slurm_auth_create(msg->auth_index, auth_info);
4078 xfree(auth_info);
4079 }
4080
4081 if (msg->forward.init != FORWARD_INIT) {
4082 forward_init(&msg->forward);
4083 msg->ret_list = NULL;
4084 }
4085
4086 if (!msg->forward.tree_width)
4087 msg->forward.tree_width = slurm_get_tree_width();
4088
4089 forward_wait(msg);
4090
4091 if (difftime(time(NULL), start_time) >= 60) {
4092 (void) g_slurm_auth_destroy(auth_cred);
4093 if (msg->flags & SLURM_GLOBAL_AUTH_KEY) {
4094 auth_cred = g_slurm_auth_create(msg->auth_index,
4095 _global_auth_key());
4096 } else {
4097 char *auth_info = slurm_get_auth_info();
4098 auth_cred = g_slurm_auth_create(msg->auth_index,
4099 auth_info);
4100 xfree(auth_info);
4101 }
4102 }
4103 if (auth_cred == NULL) {
4104 error("%s: authentication: %m", __func__);
4105 slurm_seterrno_ret(SLURM_PROTOCOL_AUTHENTICATION_ERROR);
4106 }
4107
4108 init_header(&header, msg, msg->flags);
4109
4110 /*
4111 * Pack header into buffer for transmission
4112 */
4113 buffer = init_buf(BUF_SIZE);
4114 pack_header(&header, buffer);
4115
4116 /*
4117 * Pack auth credential
4118 */
4119 rc = g_slurm_auth_pack(auth_cred, buffer, header.version);
4120 (void) g_slurm_auth_destroy(auth_cred);
4121 if (rc) {
4122 error("%s: authentication: %m", __func__);
4123 free_buf(buffer);
4124 slurm_seterrno_ret(SLURM_PROTOCOL_AUTHENTICATION_ERROR);
4125 }
4126
4127 /*
4128 * Pack message into buffer
4129 */
4130 _pack_msg(msg, &header, buffer);
4131
4132 #if _DEBUG
4133 _print_data (get_buf_data(buffer),get_buf_offset(buffer));
4134 #endif
4135 /*
4136 * Send message
4137 */
4138 rc = slurm_msg_sendto(fd, get_buf_data(buffer),
4139 get_buf_offset(buffer));
4140
4141 if ((rc < 0) && (errno == ENOTCONN)) {
4142 debug3("slurm_msg_sendto: peer has disappeared for msg_type=%u",
4143 msg->msg_type);
4144 } else if (rc < 0) {
4145 slurm_addr_t peer_addr;
4146 char addr_str[32];
4147 if (!slurm_get_peer_addr(fd, &peer_addr)) {
4148 slurm_print_slurm_addr(
4149 &peer_addr, addr_str, sizeof(addr_str));
4150 error("slurm_msg_sendto: address:port=%s "
4151 "msg_type=%u: %m",
4152 addr_str, msg->msg_type);
4153 } else if (errno == ENOTCONN)
4154 debug3("slurm_msg_sendto: peer has disappeared "
4155 "for msg_type=%u",
4156 msg->msg_type);
4157 else
4158 error("slurm_msg_sendto: msg_type=%u: %m",
4159 msg->msg_type);
4160 }
4161
4162 free_buf(buffer);
4163 return rc;
4164 }
4165
4166 /**********************************************************************\
4167 * stream functions
4168 \**********************************************************************/
4169
4170 /* slurm_write_stream
4171 * writes a buffer out a stream file descriptor
4172 * IN open_fd - file descriptor to write on
4173 * IN buffer - buffer to send
4174 * IN size - size of buffer send
4175 * IN timeout - how long to wait in milliseconds
4176 * RET size_t - bytes sent , or -1 on errror
4177 */
slurm_write_stream(int open_fd,char * buffer,size_t size)4178 size_t slurm_write_stream(int open_fd, char *buffer, size_t size)
4179 {
4180 return slurm_send_timeout(open_fd, buffer, size,
4181 SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4182 (slurm_get_msg_timeout() * 1000));
4183 }
slurm_write_stream_timeout(int open_fd,char * buffer,size_t size,int timeout)4184 size_t slurm_write_stream_timeout(int open_fd, char *buffer,
4185 size_t size, int timeout)
4186 {
4187 return slurm_send_timeout(open_fd, buffer, size,
4188 SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4189 timeout);
4190 }
4191
4192 /* slurm_read_stream
4193 * read into buffer grom a stream file descriptor
4194 * IN open_fd - file descriptor to read from
4195 * OUT buffer - buffer to receive into
4196 * IN size - size of buffer
4197 * IN timeout - how long to wait in milliseconds
4198 * RET size_t - bytes read , or -1 on errror
4199 */
slurm_read_stream(int open_fd,char * buffer,size_t size)4200 size_t slurm_read_stream(int open_fd, char *buffer, size_t size)
4201 {
4202 return slurm_recv_timeout(open_fd, buffer, size,
4203 SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4204 (slurm_get_msg_timeout() * 1000));
4205 }
slurm_read_stream_timeout(int open_fd,char * buffer,size_t size,int timeout)4206 size_t slurm_read_stream_timeout(int open_fd, char *buffer,
4207 size_t size, int timeout)
4208 {
4209 return slurm_recv_timeout(open_fd, buffer, size,
4210 SLURM_PROTOCOL_NO_SEND_RECV_FLAGS,
4211 timeout);
4212 }
4213
4214 /**********************************************************************\
4215 * address conversion and management functions
4216 \**********************************************************************/
4217
4218 /* slurm_set_addr
4219 * initializes the slurm_address with the supplied port and host name
4220 * OUT slurm_address - slurm_addr_t to be filled in
4221 * IN port - port in host order
4222 * IN host - hostname or dns name
4223 */
slurm_set_addr(slurm_addr_t * slurm_address,uint16_t port,char * host)4224 void slurm_set_addr(slurm_addr_t * slurm_address, uint16_t port, char *host)
4225 {
4226 slurm_set_addr_char(slurm_address, port, host);
4227 }
4228
4229 /* slurm_get_ip_str
4230 * given a slurm_address it returns its port and ip address string
4231 * IN slurm_address - slurm_addr_t to be queried
4232 * OUT port - port number
4233 * OUT ip - ip address in dotted-quad string form
4234 * IN buf_len - length of ip buffer
4235 */
slurm_get_ip_str(slurm_addr_t * slurm_address,uint16_t * port,char * ip,unsigned int buf_len)4236 void slurm_get_ip_str(slurm_addr_t * slurm_address, uint16_t * port,
4237 char *ip, unsigned int buf_len)
4238 {
4239 unsigned char *uc = (unsigned char *)&slurm_address->sin_addr.s_addr;
4240 *port = slurm_address->sin_port;
4241 snprintf(ip, buf_len, "%u.%u.%u.%u", uc[0], uc[1], uc[2], uc[3]);
4242 }
4243
4244 /* slurm_get_peer_addr
4245 * get the slurm address of the peer connection, similar to getpeeraddr
4246 * IN fd - an open connection
4247 * OUT slurm_address - place to park the peer's slurm_addr
4248 */
slurm_get_peer_addr(int fd,slurm_addr_t * slurm_address)4249 int slurm_get_peer_addr(int fd, slurm_addr_t * slurm_address)
4250 {
4251 struct sockaddr name;
4252 socklen_t namelen = (socklen_t) sizeof(struct sockaddr);
4253 int rc;
4254
4255 if ((rc = getpeername((int) fd, &name, &namelen)))
4256 return rc;
4257 memcpy(slurm_address, &name, sizeof(slurm_addr_t));
4258 return 0;
4259 }
4260
4261 /**********************************************************************\
4262 * slurm_addr_t pack routines
4263 \**********************************************************************/
4264
4265 /* slurm_pack_slurm_addr_array
4266 * packs an array of slurm_addrs into a buffer
4267 * OUT slurm_address - slurm_addr_t to pack
4268 * IN size_val - how many to pack
4269 * IN/OUT buffer - buffer to pack the slurm_addr_t from
4270 * returns - Slurm error code
4271 */
slurm_pack_slurm_addr_array(slurm_addr_t * slurm_address,uint32_t size_val,Buf buffer)4272 void slurm_pack_slurm_addr_array(slurm_addr_t * slurm_address,
4273 uint32_t size_val, Buf buffer)
4274 {
4275 int i = 0;
4276 uint32_t nl = htonl(size_val);
4277 pack32(nl, buffer);
4278
4279 for (i = 0; i < size_val; i++) {
4280 slurm_pack_slurm_addr(slurm_address + i, buffer);
4281 }
4282
4283 }
4284
4285 /* slurm_unpack_slurm_addr_array
4286 * unpacks an array of slurm_addrs from a buffer
4287 * OUT slurm_address - slurm_addr_t to unpack to
4288 * IN size_val - how many to unpack
4289 * IN/OUT buffer - buffer to upack the slurm_addr_t from
4290 * returns - Slurm error code
4291 */
slurm_unpack_slurm_addr_array(slurm_addr_t ** slurm_address,uint32_t * size_val,Buf buffer)4292 int slurm_unpack_slurm_addr_array(slurm_addr_t ** slurm_address,
4293 uint32_t * size_val, Buf buffer)
4294 {
4295 int i = 0;
4296 uint32_t nl;
4297
4298 *slurm_address = NULL;
4299 safe_unpack32(&nl, buffer);
4300 if (nl > NO_VAL)
4301 goto unpack_error;
4302 *size_val = ntohl(nl);
4303 *slurm_address = xcalloc(*size_val, sizeof(slurm_addr_t));
4304
4305 for (i = 0; i < *size_val; i++) {
4306 if (slurm_unpack_slurm_addr_no_alloc((*slurm_address) + i,
4307 buffer))
4308 goto unpack_error;
4309
4310 }
4311 return SLURM_SUCCESS;
4312
4313 unpack_error:
4314 xfree(*slurm_address);
4315 *slurm_address = NULL;
4316 return SLURM_ERROR;
4317 }
4318
_resp_msg_setup(slurm_msg_t * msg,slurm_msg_t * resp_msg,uint16_t msg_type,void * data)4319 static void _resp_msg_setup(slurm_msg_t *msg, slurm_msg_t *resp_msg,
4320 uint16_t msg_type, void *data)
4321 {
4322 slurm_msg_t_init(resp_msg);
4323 resp_msg->address = msg->address;
4324 resp_msg->auth_index = msg->auth_index;
4325 resp_msg->conn = msg->conn;
4326 resp_msg->data = data;
4327 resp_msg->flags = msg->flags;
4328 resp_msg->forward = msg->forward;
4329 resp_msg->forward_struct = msg->forward_struct;
4330 resp_msg->msg_type = msg_type;
4331 resp_msg->protocol_version = msg->protocol_version;
4332 resp_msg->ret_list = msg->ret_list;
4333 resp_msg->orig_addr = msg->orig_addr;
4334 }
4335
_rc_msg_setup(slurm_msg_t * msg,slurm_msg_t * resp_msg,return_code_msg_t * rc_msg,int rc)4336 static void _rc_msg_setup(slurm_msg_t *msg, slurm_msg_t *resp_msg,
4337 return_code_msg_t *rc_msg, int rc)
4338 {
4339 memset(rc_msg, 0, sizeof(return_code_msg_t));
4340 rc_msg->return_code = rc;
4341
4342 _resp_msg_setup(msg, resp_msg, RESPONSE_SLURM_RC, rc_msg);
4343 }
4344
4345
4346 /**********************************************************************\
4347 * simplified communication routines
4348 * They open a connection do work then close the connection all within
4349 * the function
4350 \**********************************************************************/
4351
4352 /* slurm_send_msg
4353 * given the original request message this function sends a
4354 * arbitrary message back to the client that made the request
4355 * IN request_msg - slurm_msg the request msg
4356 * IN msg_type - message type being returned
4357 * IN resp_msg - the message being returned to the client
4358 */
slurm_send_msg(slurm_msg_t * msg,uint16_t msg_type,void * resp)4359 int slurm_send_msg(slurm_msg_t *msg, uint16_t msg_type, void *resp)
4360 {
4361 if (msg->msg_index && msg->ret_list) {
4362 slurm_msg_t *resp_msg = xmalloc_nz(sizeof(slurm_msg_t));
4363
4364 _resp_msg_setup(msg, resp_msg, msg_type, resp);
4365
4366 resp_msg->msg_index = msg->msg_index;
4367 resp_msg->ret_list = NULL;
4368 /*
4369 * The return list here is the list we are sending to
4370 * the node, so after we attach this message to it set
4371 * it to NULL to remove it.
4372 */
4373 list_append(msg->ret_list, resp_msg);
4374 return SLURM_SUCCESS;
4375 } else {
4376 slurm_msg_t resp_msg;
4377
4378 if (msg->conn_fd < 0) {
4379 slurm_seterrno(ENOTCONN);
4380 return SLURM_ERROR;
4381 }
4382 _resp_msg_setup(msg, &resp_msg, msg_type, resp);
4383
4384 /* send message */
4385 return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4386 }
4387 }
4388
4389 /* slurm_send_rc_msg
4390 * given the original request message this function sends a
4391 * slurm_return_code message back to the client that made the request
4392 * IN request_msg - slurm_msg the request msg
4393 * IN rc - the return_code to send back to the client
4394 */
slurm_send_rc_msg(slurm_msg_t * msg,int rc)4395 int slurm_send_rc_msg(slurm_msg_t *msg, int rc)
4396 {
4397 if (msg->msg_index && msg->ret_list) {
4398 slurm_msg_t *resp_msg = xmalloc_nz(sizeof(slurm_msg_t));
4399 return_code_msg_t *rc_msg =
4400 xmalloc_nz(sizeof(return_code_msg_t));
4401
4402 _rc_msg_setup(msg, resp_msg, rc_msg, rc);
4403
4404 resp_msg->msg_index = msg->msg_index;
4405 resp_msg->ret_list = NULL;
4406 /* The return list here is the list we are sending to
4407 the node, so after we attach this message to it set
4408 it to NULL to remove it.
4409 */
4410 list_append(msg->ret_list, resp_msg);
4411 return SLURM_SUCCESS;
4412 } else {
4413 slurm_msg_t resp_msg;
4414 return_code_msg_t rc_msg;
4415
4416 if (msg->conn_fd < 0) {
4417 slurm_seterrno(ENOTCONN);
4418 return SLURM_ERROR;
4419 }
4420 _rc_msg_setup(msg, &resp_msg, &rc_msg, rc);
4421
4422 /* send message */
4423 return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4424 }
4425 }
4426
4427 /* slurm_send_rc_err_msg
4428 * given the original request message this function sends a
4429 * slurm_return_code message back to the client that made the request
4430 * IN request_msg - slurm_msg the request msg
4431 * IN rc - the return_code to send back to the client
4432 * IN err_msg - message for user
4433 */
slurm_send_rc_err_msg(slurm_msg_t * msg,int rc,char * err_msg)4434 int slurm_send_rc_err_msg(slurm_msg_t *msg, int rc, char *err_msg)
4435 {
4436 slurm_msg_t resp_msg;
4437 return_code2_msg_t rc_msg;
4438
4439 if (msg->conn_fd < 0) {
4440 slurm_seterrno(ENOTCONN);
4441 return SLURM_ERROR;
4442 }
4443 rc_msg.return_code = rc;
4444 rc_msg.err_msg = err_msg;
4445
4446 _resp_msg_setup(msg, &resp_msg, RESPONSE_SLURM_RC_MSG, &rc_msg);
4447
4448 /* send message */
4449 return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4450 }
4451
4452 /*
4453 * Sends back reroute_msg_t which directs the client to make the request to
4454 * another cluster.
4455 *
4456 * IN msg - msg to respond to.
4457 * IN cluster_rec - cluster to direct msg to.
4458 */
slurm_send_reroute_msg(slurm_msg_t * msg,slurmdb_cluster_rec_t * cluster_rec)4459 int slurm_send_reroute_msg(slurm_msg_t *msg, slurmdb_cluster_rec_t *cluster_rec)
4460 {
4461 slurm_msg_t resp_msg;
4462 reroute_msg_t reroute_msg = {0};
4463
4464 if (msg->conn_fd < 0) {
4465 slurm_seterrno(ENOTCONN);
4466 return SLURM_ERROR;
4467 }
4468
4469 /* Don't free the cluster_rec, it's pointing to the actual object. */
4470 reroute_msg.working_cluster_rec = cluster_rec;
4471
4472 _resp_msg_setup(msg, &resp_msg, RESPONSE_SLURM_REROUTE_MSG,
4473 &reroute_msg);
4474
4475 /* send message */
4476 return slurm_send_node_msg(msg->conn_fd, &resp_msg);
4477 }
4478
4479 /*
4480 * Send and recv a slurm request and response on the open slurm descriptor
4481 * Doesn't close the connection.
4482 * IN fd - file descriptor to receive msg on
4483 * IN req - a slurm_msg struct to be sent by the function
4484 * OUT resp - a slurm_msg struct to be filled in by the function
4485 * IN timeout - how long to wait in milliseconds
4486 * RET int - returns 0 on success, -1 on failure and sets errno
4487 */
slurm_send_recv_msg(int fd,slurm_msg_t * req,slurm_msg_t * resp,int timeout)4488 extern int slurm_send_recv_msg(int fd, slurm_msg_t *req,
4489 slurm_msg_t *resp, int timeout)
4490 {
4491 int rc = -1;
4492 slurm_msg_t_init(resp);
4493
4494 /* If we are using a persistent connection make sure it is the one we
4495 * actually want. This should be the correct one already, but just make
4496 * sure.
4497 */
4498 if (req->conn) {
4499 fd = req->conn->fd;
4500 resp->conn = req->conn;
4501 }
4502
4503 if (slurm_send_node_msg(fd, req) >= 0) {
4504 /* no need to adjust and timeouts here since we are not
4505 forwarding or expecting anything other than 1 message
4506 and the regular timeout will be altered in
4507 slurm_receive_msg if it is 0 */
4508 rc = slurm_receive_msg(fd, resp, timeout);
4509 }
4510
4511 return rc;
4512 }
4513
4514 /*
4515 * Send and recv a slurm request and response on the open slurm descriptor
4516 * Closes the connection.
4517 * IN fd - file descriptor to receive msg on
4518 * IN req - a slurm_msg struct to be sent by the function
4519 * OUT resp - a slurm_msg struct to be filled in by the function
4520 * IN timeout - how long to wait in milliseconds
4521 * RET int - returns 0 on success, -1 on failure and sets errno
4522 */
4523 static int
_send_and_recv_msg(int fd,slurm_msg_t * req,slurm_msg_t * resp,int timeout)4524 _send_and_recv_msg(int fd, slurm_msg_t *req,
4525 slurm_msg_t *resp, int timeout)
4526 {
4527 int rc = slurm_send_recv_msg(fd, req, resp, timeout);
4528 (void) close(fd);
4529 return rc;
4530 }
4531
4532 /*
4533 * Send and recv a slurm request and response on the open slurm descriptor
4534 * with a list containing the responses of the children (if any) we
4535 * forwarded the message to. List containing type (ret_data_info_t).
4536 * IN fd - file descriptor to receive msg on
4537 * IN req - a slurm_msg struct to be sent by the function
4538 * IN timeout - how long to wait in milliseconds
4539 * RET List - List containing the responses of the children (if any) we
4540 * forwarded the message to. List containing type
4541 * (ret_data_info_t).
4542 */
4543 static List
_send_and_recv_msgs(int fd,slurm_msg_t * req,int timeout)4544 _send_and_recv_msgs(int fd, slurm_msg_t *req, int timeout)
4545 {
4546 List ret_list = NULL;
4547 int steps = 0;
4548
4549 if (!req->forward.timeout) {
4550 if (!timeout)
4551 timeout = slurm_get_msg_timeout() * 1000;
4552 req->forward.timeout = timeout;
4553 }
4554 if (slurm_send_node_msg(fd, req) >= 0) {
4555 if (req->forward.cnt > 0) {
4556 /* figure out where we are in the tree and set
4557 * the timeout for to wait for our children
4558 * correctly
4559 * (timeout+message_timeout sec per step)
4560 * to let the child timeout */
4561 if (message_timeout < 0)
4562 message_timeout =
4563 slurm_get_msg_timeout() * 1000;
4564 steps = req->forward.cnt + 1;
4565 if (!req->forward.tree_width)
4566 req->forward.tree_width =
4567 slurm_get_tree_width();
4568 if (req->forward.tree_width)
4569 steps /= req->forward.tree_width;
4570 timeout = (message_timeout * steps);
4571 steps++;
4572
4573 timeout += (req->forward.timeout*steps);
4574 }
4575 ret_list = slurm_receive_msgs(fd, steps, timeout);
4576 }
4577
4578 (void) close(fd);
4579
4580 return ret_list;
4581 }
4582
4583 /*
4584 * slurm_send_recv_controller_msg
4585 * opens a connection to the controller, sends the controller a message,
4586 * listens for the response, then closes the connection
4587 * IN request_msg - slurm_msg request
4588 * OUT response_msg - slurm_msg response
4589 * IN comm_cluster_rec - Communication record (host/port/version)/
4590 * RET int - returns 0 on success, -1 on failure and sets errno
4591 */
slurm_send_recv_controller_msg(slurm_msg_t * request_msg,slurm_msg_t * response_msg,slurmdb_cluster_rec_t * comm_cluster_rec)4592 extern int slurm_send_recv_controller_msg(slurm_msg_t * request_msg,
4593 slurm_msg_t * response_msg,
4594 slurmdb_cluster_rec_t *comm_cluster_rec)
4595 {
4596 int fd = -1;
4597 int rc = 0;
4598 time_t start_time = time(NULL);
4599 int retry = 1;
4600 slurm_ctl_conf_t *conf;
4601 bool have_backup;
4602 uint16_t slurmctld_timeout;
4603 slurm_addr_t ctrl_addr;
4604 static bool use_backup = false;
4605 slurmdb_cluster_rec_t *save_comm_cluster_rec = comm_cluster_rec;
4606
4607 /*
4608 * Just in case the caller didn't initialize his slurm_msg_t, and
4609 * since we KNOW that we are only sending to one node (the controller),
4610 * we initialize some forwarding variables to disable forwarding.
4611 */
4612 forward_init(&request_msg->forward);
4613 request_msg->ret_list = NULL;
4614 request_msg->forward_struct = NULL;
4615
4616 tryagain:
4617 retry = 1;
4618 if (comm_cluster_rec)
4619 request_msg->flags |= SLURM_GLOBAL_AUTH_KEY;
4620
4621 if ((fd = slurm_open_controller_conn(&ctrl_addr, &use_backup,
4622 comm_cluster_rec)) < 0) {
4623 rc = -1;
4624 goto cleanup;
4625 }
4626
4627 conf = slurm_conf_lock();
4628 have_backup = conf->control_cnt > 1;
4629 slurmctld_timeout = conf->slurmctld_timeout;
4630 slurm_conf_unlock();
4631
4632 while (retry) {
4633 /*
4634 * If the backup controller is in the process of assuming
4635 * control, we sleep and retry later
4636 */
4637 retry = 0;
4638 rc = _send_and_recv_msg(fd, request_msg, response_msg, 0);
4639 if (response_msg->auth_cred)
4640 g_slurm_auth_destroy(response_msg->auth_cred);
4641 else
4642 rc = -1;
4643
4644 if ((rc == 0) && (!comm_cluster_rec)
4645 && (response_msg->msg_type == RESPONSE_SLURM_RC)
4646 && ((((return_code_msg_t *)response_msg->data)->return_code)
4647 == ESLURM_IN_STANDBY_MODE)
4648 && (have_backup)
4649 && (difftime(time(NULL), start_time)
4650 < (slurmctld_timeout + (slurmctld_timeout / 2)))) {
4651
4652 debug("Primary not responding, backup not in control. "
4653 "sleep and retry");
4654 slurm_free_return_code_msg(response_msg->data);
4655 sleep(slurmctld_timeout / 2);
4656 use_backup = false;
4657 if ((fd = slurm_open_controller_conn(&ctrl_addr,
4658 &use_backup,
4659 comm_cluster_rec))
4660 < 0) {
4661 rc = -1;
4662 } else {
4663 retry = 1;
4664 }
4665 }
4666
4667 if (rc == -1)
4668 break;
4669 }
4670
4671 if (!rc && (response_msg->msg_type == RESPONSE_SLURM_REROUTE_MSG)) {
4672 reroute_msg_t *rr_msg = (reroute_msg_t *)response_msg->data;
4673
4674 /*
4675 * Don't expect mutliple hops but in the case it does
4676 * happen, free the previous rr cluster_rec.
4677 */
4678 if (comm_cluster_rec &&
4679 (comm_cluster_rec != save_comm_cluster_rec))
4680 slurmdb_destroy_cluster_rec(comm_cluster_rec);
4681
4682 comm_cluster_rec = rr_msg->working_cluster_rec;
4683 slurmdb_setup_cluster_rec(comm_cluster_rec);
4684 rr_msg->working_cluster_rec = NULL;
4685 goto tryagain;
4686 }
4687
4688 if (comm_cluster_rec != save_comm_cluster_rec)
4689 slurmdb_destroy_cluster_rec(comm_cluster_rec);
4690
4691 cleanup:
4692 if (rc != 0)
4693 _remap_slurmctld_errno();
4694
4695 return rc;
4696 }
4697
4698 /* slurm_send_recv_node_msg
4699 * opens a connection to node, sends the node a message, listens
4700 * for the response, then closes the connection
4701 * IN request_msg - slurm_msg request
4702 * OUT response_msg - slurm_msg response
4703 * IN timeout - how long to wait in milliseconds
4704 * RET int - returns 0 on success, -1 on failure and sets errno
4705 */
slurm_send_recv_node_msg(slurm_msg_t * req,slurm_msg_t * resp,int timeout)4706 int slurm_send_recv_node_msg(slurm_msg_t *req, slurm_msg_t *resp, int timeout)
4707 {
4708 int fd = -1;
4709
4710 resp->auth_cred = NULL;
4711 if ((fd = slurm_open_msg_conn(&req->address)) < 0)
4712 return -1;
4713
4714 return _send_and_recv_msg(fd, req, resp, timeout);
4715
4716 }
4717
4718 /* slurm_send_only_controller_msg
4719 * opens a connection to the controller, sends the controller a
4720 * message then, closes the connection
4721 * IN request_msg - slurm_msg request
4722 * IN comm_cluster_rec - Communication record (host/port/version)
4723 * RET int - return code
4724 * NOTE: NOT INTENDED TO BE CROSS-CLUSTER
4725 */
slurm_send_only_controller_msg(slurm_msg_t * req,slurmdb_cluster_rec_t * comm_cluster_rec)4726 extern int slurm_send_only_controller_msg(slurm_msg_t *req,
4727 slurmdb_cluster_rec_t *comm_cluster_rec)
4728 {
4729 int rc = SLURM_SUCCESS;
4730 int fd = -1;
4731 slurm_addr_t ctrl_addr;
4732 bool use_backup = false;
4733
4734 /*
4735 * Open connection to Slurm controller:
4736 */
4737 if ((fd = slurm_open_controller_conn(&ctrl_addr, &use_backup,
4738 comm_cluster_rec)) < 0) {
4739 rc = SLURM_ERROR;
4740 goto cleanup;
4741 }
4742
4743 if ((rc = slurm_send_node_msg(fd, req)) < 0) {
4744 rc = SLURM_ERROR;
4745 } else {
4746 debug3("slurm_send_only_controller_msg: sent %d", rc);
4747 rc = SLURM_SUCCESS;
4748 }
4749
4750 (void) close(fd);
4751
4752 cleanup:
4753 if (rc != SLURM_SUCCESS)
4754 _remap_slurmctld_errno();
4755 return rc;
4756 }
4757
4758 /*
4759 * Open a connection to the "address" specified in the slurm msg `req'
4760 * Then, immediately close the connection w/out waiting for a reply.
4761 *
4762 * Returns SLURM_SUCCESS on success SLURM_ERROR (< 0) for failure.
4763 *
4764 * DO NOT USE THIS IN NEW CODE
4765 * Use slurm_send_recv_rc_msg_only_one() or something similar instead.
4766 *
4767 * By not waiting for a response message, the message to be transmitted
4768 * may never be received by the remote end. The remote TCP stack may
4769 * acknowledge the data while the application itself has not had a chance
4770 * to receive it. The only way to tell that the application has processed
4771 * a given packet is for it to send back a message across the socket itself.
4772 *
4773 * The receive side looks like: poll() && read(), close(). If the poll() times
4774 * out, the kernel may still ACK the data while the application has jumped to
4775 * closing the connection. The send side cannot then distinguish between the
4776 * close happening as a result of the timeout vs. as a normal message shutdown.
4777 *
4778 * This is only one example of the many races inherent in this approach.
4779 *
4780 * See "UNIX Network Programming" Volume 1 (Third Edition) Section 7.5 on
4781 * SO_LINGER for a description of the subtle hazards inherent in abusing
4782 * TCP as a unidirectional pipe.
4783 */
slurm_send_only_node_msg(slurm_msg_t * req)4784 int slurm_send_only_node_msg(slurm_msg_t *req)
4785 {
4786 int rc = SLURM_SUCCESS;
4787 int fd = -1;
4788 struct pollfd pfd;
4789 int value = -1;
4790 int pollrc;
4791
4792 if ((fd = slurm_open_msg_conn(&req->address)) < 0) {
4793 return SLURM_ERROR;
4794 }
4795
4796 if ((rc = slurm_send_node_msg(fd, req)) < 0) {
4797 rc = SLURM_ERROR;
4798 } else {
4799 debug3("%s: sent %d", __func__, rc);
4800 rc = SLURM_SUCCESS;
4801 }
4802
4803 /*
4804 * Make sure message was received by remote, and that there isn't
4805 * and outstanding write() or that the connection has been reset.
4806 *
4807 * The shutdown() call intentionally falls through to the next block,
4808 * the poll() should hit POLLERR which gives the TICOUTQ count as an
4809 * additional diagnostic element.
4810 *
4811 * The steps below may result in a false-positive on occassion, in
4812 * which case the code path above may opt to retransmit an already
4813 * received message. If this is a concern, you should not be using
4814 * this function.
4815 */
4816 if (shutdown(fd, SHUT_WR))
4817 debug("%s: shutdown call failed: %m", __func__);
4818
4819 again:
4820 pfd.fd = fd;
4821 pfd.events = POLLIN;
4822 /*
4823 * Wait for 1000 ms for shutdown to respond. We found this is long
4824 * enough to get a response, but any longer would start to produce a
4825 * delay that could be compounded if many of these started stacking up.
4826 * We were easily able to create this kind of scenario when restarting
4827 * the slurmds over and over with message aggregation turned on.
4828 */
4829 pollrc = poll(&pfd, 1, 1000);
4830 if (pollrc == -1) {
4831 if (errno == EINTR)
4832 goto again;
4833 debug("%s: poll error: %m", __func__);
4834 (void) close(fd);
4835 return SLURM_ERROR;
4836 }
4837
4838 if (pollrc == 0) {
4839 if (ioctl(fd, TIOCOUTQ, &value))
4840 debug("%s: TIOCOUTQ ioctl failed", __func__);
4841 debug("%s: poll timed out with %d outstanding: %m", __func__, value);
4842 (void) close(fd);
4843 return SLURM_ERROR;
4844 }
4845
4846 if (pfd.revents & POLLERR) {
4847 int err;
4848 socklen_t errlen = sizeof(err);
4849 int value = -1;
4850
4851 if (ioctl(fd, TIOCOUTQ, &value))
4852 debug("%s: TIOCOUTQ ioctl failed", __func__);
4853 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen))
4854 debug("%s: getsockopt error with %d outstanding: %m",
4855 __func__, value);
4856 else
4857 debug("%s: poll error with %d outstanding: %s",
4858 __func__, value, strerror(err));
4859 (void) close(fd);
4860 return SLURM_ERROR;
4861 }
4862
4863 (void) close(fd);
4864
4865 return rc;
4866 }
4867
4868 /*
4869 * Open a connection to the "address" specified in the slurm msg `req'
4870 * Then, immediately close the connection w/out waiting for a reply.
4871 * Ignore any errors. This should only be used when you do not care if
4872 * the message is ever received.
4873 */
slurm_send_msg_maybe(slurm_msg_t * req)4874 void slurm_send_msg_maybe(slurm_msg_t *req)
4875 {
4876 int fd = -1;
4877
4878 if ((fd = slurm_open_msg_conn(&req->address)) < 0) {
4879 return;
4880 }
4881
4882 (void) slurm_send_node_msg(fd, req);
4883
4884 (void) close(fd);
4885 }
4886
4887 /*
4888 * Send a message to the nodelist specificed using fanout
4889 * Then return List containing type (ret_data_info_t).
4890 * IN nodelist - list of nodes to send to.
4891 * IN msg - a slurm_msg struct to be sent by the function
4892 * IN timeout - how long to wait in milliseconds
4893 * RET List - List containing the responses of the children
4894 * (if any) we forwarded the message to. List
4895 * containing type (ret_data_info_t).
4896 */
slurm_send_recv_msgs(const char * nodelist,slurm_msg_t * msg,int timeout)4897 List slurm_send_recv_msgs(const char *nodelist, slurm_msg_t *msg, int timeout)
4898 {
4899 List ret_list = NULL;
4900 hostlist_t hl = NULL;
4901
4902 if (!nodelist || !strlen(nodelist)) {
4903 error("slurm_send_recv_msgs: no nodelist given");
4904 return NULL;
4905 }
4906
4907 hl = hostlist_create(nodelist);
4908 if (!hl) {
4909 error("slurm_send_recv_msgs: problem creating hostlist");
4910 return NULL;
4911 }
4912
4913 ret_list = start_msg_tree(hl, msg, timeout);
4914 hostlist_destroy(hl);
4915
4916 return ret_list;
4917 }
4918
4919 /*
4920 * Send a message to msg->address
4921 * Then return List containing type (ret_data_info_t).
4922 * IN msg - a slurm_msg struct to be sent by the function
4923 * IN timeout - how long to wait in milliseconds
4924 * RET List - List containing the responses of the children
4925 * (if any) we forwarded the message to. List
4926 * containing type (ret_types_t).
4927 */
slurm_send_addr_recv_msgs(slurm_msg_t * msg,char * name,int timeout)4928 List slurm_send_addr_recv_msgs(slurm_msg_t *msg, char *name, int timeout)
4929 {
4930 static pthread_mutex_t conn_lock = PTHREAD_MUTEX_INITIALIZER;
4931 static uint16_t conn_timeout = NO_VAL16, tcp_timeout = 2;
4932 char addrbuf[32];
4933 List ret_list = NULL;
4934 int fd = -1;
4935 ret_data_info_t *ret_data_info = NULL;
4936 ListIterator itr;
4937 int i;
4938
4939 slurm_mutex_lock(&conn_lock);
4940 if (conn_timeout == NO_VAL16) {
4941 conn_timeout = MAX(5, slurm_get_msg_timeout() / 2);
4942 tcp_timeout = MAX(0, slurm_get_tcp_timeout() - 1);
4943 }
4944 slurm_mutex_unlock(&conn_lock);
4945 slurm_print_slurm_addr(&msg->address, addrbuf, sizeof(addrbuf));
4946
4947 /* This connect retry logic permits Slurm hierarchical communications
4948 * to better survive slurmd restarts */
4949 for (i = 0; i <= conn_timeout; i++) {
4950 fd = slurm_open_msg_conn(&msg->address);
4951 if ((fd >= 0) || (errno != ECONNREFUSED && errno != ETIMEDOUT))
4952 break;
4953
4954 if (errno == ETIMEDOUT) {
4955 if (i == 0)
4956 debug3("Timed out connecting to %s, retrying...",
4957 addrbuf);
4958 i += tcp_timeout;
4959 } else {
4960 if (i == 0)
4961 debug3("Connection refused by %s, retrying...",
4962 addrbuf);
4963 sleep(1);
4964 }
4965 }
4966 if (fd < 0) {
4967 debug2("Failed to connect to %s, %m", addrbuf);
4968 mark_as_failed_forward(&ret_list, name,
4969 SLURM_COMMUNICATIONS_CONNECTION_ERROR);
4970 errno = SLURM_COMMUNICATIONS_CONNECTION_ERROR;
4971 return ret_list;
4972 }
4973
4974 msg->ret_list = NULL;
4975 msg->forward_struct = NULL;
4976 if (!(ret_list = _send_and_recv_msgs(fd, msg, timeout))) {
4977 mark_as_failed_forward(&ret_list, name, errno);
4978 errno = SLURM_COMMUNICATIONS_CONNECTION_ERROR;
4979 return ret_list;
4980 } else {
4981 itr = list_iterator_create(ret_list);
4982 while ((ret_data_info = list_next(itr)))
4983 if (!ret_data_info->node_name) {
4984 ret_data_info->node_name = xstrdup(name);
4985 }
4986 list_iterator_destroy(itr);
4987 }
4988 return ret_list;
4989 }
4990
4991 /*
4992 * Open a connection to the "address" specified in the slurm msg "req".
4993 * Then read back an "rc" message returning the "return_code" specified
4994 * in the response in the "rc" parameter.
4995 * IN req - a slurm_msg struct to be sent by the function
4996 * OUT rc - return code from the sent message
4997 * IN timeout - how long to wait in milliseconds
4998 * RET int either 0 for success or -1 for failure.
4999 */
slurm_send_recv_rc_msg_only_one(slurm_msg_t * req,int * rc,int timeout)5000 int slurm_send_recv_rc_msg_only_one(slurm_msg_t *req, int *rc, int timeout)
5001 {
5002 int fd = -1;
5003 int ret_c = 0;
5004 slurm_msg_t resp;
5005
5006 slurm_msg_t_init(&resp);
5007
5008 /* Just in case the caller didn't initialize his slurm_msg_t, and
5009 * since we KNOW that we are only sending to one node,
5010 * we initialize some forwarding variables to disable forwarding.
5011 */
5012 forward_init(&req->forward);
5013 req->ret_list = NULL;
5014 req->forward_struct = NULL;
5015
5016 if ((fd = slurm_open_msg_conn(&req->address)) < 0)
5017 return -1;
5018 if (!_send_and_recv_msg(fd, req, &resp, timeout)) {
5019 if (resp.auth_cred)
5020 g_slurm_auth_destroy(resp.auth_cred);
5021 *rc = slurm_get_return_code(resp.msg_type, resp.data);
5022 slurm_free_msg_data(resp.msg_type, resp.data);
5023 ret_c = 0;
5024 } else
5025 ret_c = -1;
5026 return ret_c;
5027 }
5028
5029 /*
5030 * Send message to controller and get return code.
5031 * Make use of slurm_send_recv_controller_msg(), which handles
5032 * support for backup controller and retry during transistion.
5033 * IN req - request to send
5034 * OUT rc - return code
5035 * IN comm_cluster_rec - Communication record (host/port/version)/
5036 * RET - 0 on success, -1 on failure
5037 */
slurm_send_recv_controller_rc_msg(slurm_msg_t * req,int * rc,slurmdb_cluster_rec_t * comm_cluster_rec)5038 extern int slurm_send_recv_controller_rc_msg(slurm_msg_t *req, int *rc,
5039 slurmdb_cluster_rec_t *comm_cluster_rec)
5040 {
5041 int ret_c;
5042 slurm_msg_t resp;
5043
5044 if (!slurm_send_recv_controller_msg(req, &resp, comm_cluster_rec)) {
5045 *rc = slurm_get_return_code(resp.msg_type, resp.data);
5046 slurm_free_msg_data(resp.msg_type, resp.data);
5047 ret_c = 0;
5048 } else {
5049 ret_c = -1;
5050 }
5051
5052 return ret_c;
5053 }
5054
5055 /* this is used to set how many nodes are going to be on each branch
5056 * of the tree.
5057 * IN total - total number of nodes to send to
5058 * IN tree_width - how wide the tree should be on each hop
5059 * RET int * - int array tree_width in length each space
5060 * containing the number of nodes to send to each hop
5061 * on the span.
5062 */
set_span(int total,uint16_t tree_width)5063 extern int *set_span(int total, uint16_t tree_width)
5064 {
5065 int *span = NULL;
5066 int left = total;
5067 int i = 0;
5068
5069 if (tree_width == 0)
5070 tree_width = slurm_get_tree_width();
5071
5072 span = xcalloc(tree_width, sizeof(int));
5073 //info("span count = %d", tree_width);
5074 if (total <= tree_width) {
5075 return span;
5076 }
5077
5078 while (left > 0) {
5079 for (i = 0; i < tree_width; i++) {
5080 if ((tree_width-i) >= left) {
5081 if (span[i] == 0) {
5082 left = 0;
5083 break;
5084 } else {
5085 span[i] += left;
5086 left = 0;
5087 break;
5088 }
5089 } else if (left <= tree_width) {
5090 if (span[i] == 0)
5091 left--;
5092
5093 span[i] += left;
5094 left = 0;
5095 break;
5096 }
5097
5098 if (span[i] == 0)
5099 left--;
5100
5101 span[i] += tree_width;
5102 left -= tree_width;
5103 }
5104 }
5105
5106 return span;
5107 }
5108
5109 /*
5110 * Free a slurm message's memebers but not the message itself
5111 */
slurm_free_msg_members(slurm_msg_t * msg)5112 extern void slurm_free_msg_members(slurm_msg_t *msg)
5113 {
5114 if (msg) {
5115 if (msg->auth_cred)
5116 (void) g_slurm_auth_destroy(msg->auth_cred);
5117 free_buf(msg->buffer);
5118 slurm_free_msg_data(msg->msg_type, msg->data);
5119 FREE_NULL_LIST(msg->ret_list);
5120 }
5121 }
5122
5123 /*
5124 * Free a slurm message
5125 */
slurm_free_msg(slurm_msg_t * msg)5126 extern void slurm_free_msg(slurm_msg_t *msg)
5127 {
5128 if (msg) {
5129 slurm_free_msg_members(msg);
5130 xfree(msg);
5131 }
5132 }
5133
nodelist_nth_host(const char * nodelist,int inx)5134 extern char *nodelist_nth_host(const char *nodelist, int inx)
5135 {
5136 hostlist_t hl = hostlist_create(nodelist);
5137 char *name = hostlist_nth(hl, inx);
5138 hostlist_destroy(hl);
5139 return name;
5140 }
5141
nodelist_find(const char * nodelist,const char * name)5142 extern int nodelist_find(const char *nodelist, const char *name)
5143 {
5144 hostlist_t hl = hostlist_create(nodelist);
5145 int id = hostlist_find(hl, name);
5146 hostlist_destroy(hl);
5147 return id;
5148 }
5149
5150 /*
5151 * Convert number from one unit to another.
5152 * By default, Will convert num to largest divisible unit.
5153 * Appends unit type suffix -- if applicable.
5154 *
5155 * IN num: number to convert.
5156 * OUT buf: buffer to copy converted number into.
5157 * IN buf_size: size of buffer.
5158 * IN orig_type: The original type of num.
5159 * IN spec_type: Type to convert num to. If specified, num will be converted up
5160 * or down to this unit type.
5161 * IN divisor: size of type
5162 * IN flags: flags to control whether to convert exactly or not at all.
5163 */
convert_num_unit2(double num,char * buf,int buf_size,int orig_type,int spec_type,int divisor,uint32_t flags)5164 extern void convert_num_unit2(double num, char *buf, int buf_size,
5165 int orig_type, int spec_type, int divisor,
5166 uint32_t flags)
5167 {
5168 char *unit = "\0KMGTP?";
5169 uint64_t i;
5170
5171 if ((int64_t)num == 0) {
5172 snprintf(buf, buf_size, "0");
5173 return;
5174 }
5175
5176 if (spec_type != NO_VAL) {
5177 /* spec_type overrides all flags */
5178 if (spec_type < orig_type) {
5179 while (spec_type < orig_type) {
5180 num *= divisor;
5181 orig_type--;
5182 }
5183 } else if (spec_type > orig_type) {
5184 while (spec_type > orig_type) {
5185 num /= divisor;
5186 orig_type++;
5187 }
5188 }
5189 } else if (flags & CONVERT_NUM_UNIT_RAW) {
5190 orig_type = UNIT_NONE;
5191 } else if (flags & CONVERT_NUM_UNIT_NO) {
5192 /* no op */
5193 } else if (flags & CONVERT_NUM_UNIT_EXACT) {
5194 /* convert until we would loose precision */
5195 /* half values (e.g., 2.5G) are still considered precise */
5196
5197 while (num >= divisor
5198 && ((uint64_t)num % (divisor / 2) == 0)) {
5199 num /= divisor;
5200 orig_type++;
5201 }
5202 } else {
5203 /* aggressively convert values */
5204 while (num >= divisor) {
5205 num /= divisor;
5206 orig_type++;
5207 }
5208 }
5209
5210 if (orig_type < UNIT_NONE || orig_type > UNIT_PETA)
5211 orig_type = UNIT_UNKNOWN;
5212 i = (uint64_t)num;
5213 /* Here we are checking to see if these numbers are the same,
5214 * meaning the float has not floating point. If we do have
5215 * floating point print as a float.
5216 */
5217 if ((double)i == num)
5218 snprintf(buf, buf_size, "%"PRIu64"%c", i, unit[orig_type]);
5219 else
5220 snprintf(buf, buf_size, "%.2f%c", num, unit[orig_type]);
5221 }
5222
convert_num_unit(double num,char * buf,int buf_size,int orig_type,int spec_type,uint32_t flags)5223 extern void convert_num_unit(double num, char *buf, int buf_size,
5224 int orig_type, int spec_type, uint32_t flags)
5225 {
5226 convert_num_unit2(num, buf, buf_size, orig_type, spec_type, 1024,
5227 flags);
5228 }
5229
revert_num_unit(const char * buf)5230 extern int revert_num_unit(const char *buf)
5231 {
5232 char *unit = "\0KMGTP\0";
5233 int i = 1, j = 0, number = 0;
5234
5235 if (!buf)
5236 return -1;
5237 j = strlen(buf) - 1;
5238 while (unit[i]) {
5239 if (toupper((int)buf[j]) == unit[i])
5240 break;
5241 i++;
5242 }
5243
5244 number = atoi(buf);
5245 if (unit[i])
5246 number *= (i*1024);
5247
5248 return number;
5249 }
5250
get_convert_unit_val(int base_unit,char convert_to)5251 extern int get_convert_unit_val(int base_unit, char convert_to)
5252 {
5253 int conv_unit = 0, conv_value = 0;
5254
5255 if ((conv_unit = get_unit_type(convert_to)) == SLURM_ERROR)
5256 return SLURM_ERROR;
5257
5258 while (base_unit++ < conv_unit) {
5259 if (!conv_value)
5260 conv_value = 1024;
5261 else
5262 conv_value *= 1024;
5263 }
5264
5265 return conv_value;
5266 }
5267
get_unit_type(char unit)5268 extern int get_unit_type(char unit)
5269 {
5270 char *units = "\0KMGTP";
5271 char *tmp_char = NULL;
5272
5273 if (unit == '\0') {
5274 error("Invalid unit type '%c'. Possible options are '%s'",
5275 unit, units + 1);
5276 return SLURM_ERROR;
5277 }
5278
5279 tmp_char = strchr(units + 1, toupper(unit));
5280 if (!tmp_char) {
5281 error("Invalid unit type '%c'. Possible options are '%s'",
5282 unit, units + 1);
5283 return SLURM_ERROR;
5284 }
5285 return tmp_char - units;
5286 }
5287
5288 #if _DEBUG
5289
_print_data(char * data,int len)5290 static void _print_data(char *data, int len)
5291 {
5292 int i;
5293 for (i = 0; i < len; i++) {
5294 if ((i % 10 == 0) && (i != 0))
5295 printf("\n");
5296 printf("%2.2x ", ((int) data[i] & 0xff));
5297 if (i >= 200)
5298 break;
5299 }
5300 printf("\n\n");
5301 }
5302
5303 #endif
5304
5305 /*
5306 * slurm_forward_data - forward arbitrary data to unix domain sockets on nodes
5307 * IN/OUT nodelist: Nodes to forward data to (if failure this list is changed to
5308 * reflect the failed nodes).
5309 * IN address: address of unix domain socket
5310 * IN len: length of data
5311 * IN data: real data
5312 * RET: error code
5313 */
slurm_forward_data(char ** nodelist,char * address,uint32_t len,const char * data)5314 extern int slurm_forward_data(
5315 char **nodelist, char *address, uint32_t len, const char *data)
5316 {
5317 List ret_list = NULL;
5318 int temp_rc = 0, rc = 0;
5319 ret_data_info_t *ret_data_info = NULL;
5320 slurm_msg_t msg;
5321 forward_data_msg_t req;
5322 hostlist_t hl = NULL;
5323 bool redo_nodelist = false;
5324 slurm_msg_t_init(&msg);
5325
5326 debug2("slurm_forward_data: nodelist=%s, address=%s, len=%u",
5327 *nodelist, address, len);
5328 req.address = address;
5329 req.len = len;
5330 req.data = (char *)data;
5331
5332 msg.msg_type = REQUEST_FORWARD_DATA;
5333 msg.data = &req;
5334
5335 if ((ret_list = slurm_send_recv_msgs(*nodelist, &msg, 0))) {
5336 if (list_count(ret_list) > 1)
5337 redo_nodelist = true;
5338
5339 while ((ret_data_info = list_pop(ret_list))) {
5340 temp_rc = slurm_get_return_code(ret_data_info->type,
5341 ret_data_info->data);
5342 if (temp_rc != SLURM_SUCCESS) {
5343 rc = temp_rc;
5344 if (redo_nodelist) {
5345 if (!hl)
5346 hl = hostlist_create(
5347 ret_data_info->
5348 node_name);
5349 else
5350 hostlist_push_host(
5351 hl, ret_data_info->
5352 node_name);
5353 }
5354 }
5355 destroy_data_info(ret_data_info);
5356 }
5357 } else {
5358 error("slurm_forward_data: no list was returned");
5359 rc = SLURM_ERROR;
5360 }
5361
5362 if (hl) {
5363 xfree(*nodelist);
5364 hostlist_sort(hl);
5365 *nodelist = hostlist_ranged_string_xmalloc(hl);
5366 hostlist_destroy(hl);
5367 }
5368
5369 FREE_NULL_LIST(ret_list);
5370
5371 return rc;
5372 }
5373
slurm_setup_sockaddr(struct sockaddr_in * sin,uint16_t port)5374 extern void slurm_setup_sockaddr(struct sockaddr_in *sin, uint16_t port)
5375 {
5376 static uint32_t s_addr = NO_VAL;
5377
5378 memset(sin, 0, sizeof(struct sockaddr_in));
5379 sin->sin_family = AF_INET;
5380 sin->sin_port = htons(port);
5381
5382 if (s_addr == NO_VAL) {
5383 /* On systems with multiple interfaces we might not
5384 * want to get just any address. This is the case on
5385 * a Cray system with RSIP.
5386 */
5387 char *comm_params = slurm_get_comm_parameters();
5388 char *var;
5389
5390 if (running_in_slurmctld())
5391 var = "NoCtldInAddrAny";
5392 else
5393 var = "NoInAddrAny";
5394
5395 if (xstrcasestr(comm_params, var)) {
5396 char host[MAXHOSTNAMELEN];
5397
5398 if (!gethostname(host, MAXHOSTNAMELEN)) {
5399 slurm_set_addr_char(sin, port, host);
5400 s_addr = sin->sin_addr.s_addr;
5401 } else
5402 fatal("slurm_setup_sockaddr: "
5403 "Can't get hostname or addr: %m");
5404 } else
5405 s_addr = htonl(INADDR_ANY);
5406
5407 xfree(comm_params);
5408 }
5409
5410 sin->sin_addr.s_addr = s_addr;
5411 }
5412
5413 /*
5414 * Check if we can bind() the socket s to port port.
5415 *
5416 * IN: s - socket
5417 * IN: port - port number to attempt to bind
5418 * IN: local - only bind to localhost if true
5419 * OUT: true/false if port was bound successfully
5420 */
sock_bind_range(int s,uint16_t * range,bool local)5421 int sock_bind_range(int s, uint16_t *range, bool local)
5422 {
5423 uint32_t count;
5424 uint32_t min;
5425 uint32_t max;
5426 uint32_t port;
5427 uint32_t num;
5428
5429 min = range[0];
5430 max = range[1];
5431
5432 srand(getpid());
5433 num = max - min + 1;
5434 port = min + (random() % num);
5435 count = num;
5436
5437 do {
5438 if (_is_port_ok(s, port, local))
5439 return port;
5440
5441 if (port == max)
5442 port = min;
5443 else
5444 ++port;
5445 --count;
5446 } while (count > 0);
5447
5448 error("%s: all ports in range (%u, %u) exhausted, cannot establish listening port",
5449 __func__, min, max);
5450
5451 return -1;
5452 }
5453
5454 /*
5455 * Check if we can bind() the socket s to port port.
5456 *
5457 * IN: s - socket
5458 * IN: port - port number to attempt to bind
5459 * IN: local - only bind to localhost if true
5460 * OUT: true/false if port was bound successfully
5461 */
_is_port_ok(int s,uint16_t port,bool local)5462 static bool _is_port_ok(int s, uint16_t port, bool local)
5463 {
5464 struct sockaddr_in sin;
5465
5466 slurm_setup_sockaddr(&sin, port);
5467
5468 if (local)
5469 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
5470
5471 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
5472 debug("%s: bind() failed port %d sock %d %m",
5473 __func__, port, s);
5474 return false;
5475 }
5476
5477 return true;
5478 }
5479
5480 /* slurm_get_prolog_timeout
5481 * Get prolog/epilog timeout
5482 */
slurm_get_prolog_timeout(void)5483 uint16_t slurm_get_prolog_timeout(void)
5484 {
5485 uint16_t timeout = 0;
5486 slurm_ctl_conf_t *conf;
5487
5488 if (slurmdbd_conf) {
5489 } else {
5490 conf = slurm_conf_lock();
5491 timeout = conf->prolog_epilog_timeout;
5492 slurm_conf_unlock();
5493 }
5494
5495 return timeout;
5496 }
5497
slurm_hex_to_char(int v)5498 extern int slurm_hex_to_char(int v)
5499 {
5500 if (v >= 0 && v < 10)
5501 return '0' + v;
5502 else if (v >= 10 && v < 16)
5503 return ('a' - 10) + v;
5504 else
5505 return -1;
5506 }
5507
slurm_char_to_hex(int c)5508 extern int slurm_char_to_hex(int c)
5509 {
5510 int cl;
5511
5512 cl = tolower(c);
5513 if (c >= '0' && c <= '9')
5514 return c - '0';
5515 else if (cl >= 'a' && cl <= 'f')
5516 return cl + (10 - 'a');
5517 else
5518 return -1;
5519 }
5520