| /*****************************************************************************\ |
| ** pmix_info.c - PMIx various environment information |
| ***************************************************************************** |
| * Copyright (C) 2014-2015 Artem Polyakov. All rights reserved. |
| * Copyright (C) 2015-2020 Mellanox Technologies. All rights reserved. |
| * Written by Artem Polyakov <artpol84@gmail.com, artemp@mellanox.com>, |
| * Boris Karasev <karasev.b@gmail.com, boriska@mellanox.com>. |
| * Copyright (C) 2020 Siberian State University of Telecommunications |
| * and Information Sciences (SibSUTIS). |
| * All rights reserved. |
| * Written by Boris Bochkarev <boris-bochkaryov@yandex.ru>. |
| * |
| * This file is part of Slurm, a resource management program. |
| * For details, see <https://slurm.schedmd.com/>. |
| * Please also read the included file: DISCLAIMER. |
| * |
| * Slurm is free software; you can redistribute it and/or modify it under |
| * the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| * |
| * In addition, as a special exception, the copyright holders give permission |
| * to link the code of portions of this program with the OpenSSL library under |
| * certain conditions as described in each individual source file, and |
| * distribute linked combinations including the two. You must obey the GNU |
| * General Public License in all respects for all of the code used other than |
| * OpenSSL. If you modify file(s) with this exception, you may extend this |
| * exception to your version of the file(s), but you are not obligated to do |
| * so. If you do not wish to do so, delete this exception statement from your |
| * version. If you delete this exception statement from all source files in |
| * the program, then also delete it here. |
| * |
| * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| * details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with Slurm; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| \*****************************************************************************/ |
| |
| #include <string.h> |
| #include "pmixp_common.h" |
| #include "pmixp_debug.h" |
| #include "pmixp_info.h" |
| #include "pmixp_coll.h" |
| |
| /* Server communication */ |
| static char *_srv_usock_path = NULL; |
| static int _srv_usock_fd = -1; |
| static bool _srv_use_direct_conn = true; |
| static bool _srv_use_direct_conn_early = false; |
| static bool _srv_same_arch = true; |
| #ifdef HAVE_UCX |
| static bool _srv_use_direct_conn_ucx = true; |
| #endif |
| static int _srv_fence_coll_type = PMIXP_COLL_TYPE_FENCE_MAX; |
| static bool _srv_fence_coll_barrier = false; |
| |
| pmix_jobinfo_t _pmixp_job_info; |
| |
| static int _resources_set(char ***env); |
| static int _env_set(const stepd_step_rec_t *step, char ***env); |
| |
| /* stepd global UNIX socket contact information */ |
| extern void pmixp_info_srv_usock_set(char *path, int fd) |
| { |
| _srv_usock_path = _pmixp_job_info.server_addr_unfmt; |
| _srv_usock_fd = fd; |
| } |
| |
| extern const char *pmixp_info_srv_usock_path(void) |
| { |
| /* Check that Server address was initialized */ |
| xassert(_srv_usock_path); |
| return _srv_usock_path; |
| } |
| |
| extern int pmixp_info_srv_usock_fd(void) |
| { |
| /* Check that Server fd was created */ |
| xassert(0 <= _srv_usock_fd); |
| return _srv_usock_fd; |
| } |
| |
| extern bool pmixp_info_same_arch(void) |
| { |
| return _srv_same_arch; |
| } |
| |
| extern bool pmixp_info_srv_direct_conn(void) |
| { |
| return _srv_use_direct_conn; |
| } |
| |
| extern bool pmixp_info_srv_direct_conn_early(void) |
| { |
| return _srv_use_direct_conn_early && _srv_use_direct_conn; |
| } |
| #ifdef HAVE_UCX |
| extern bool pmixp_info_srv_direct_conn_ucx(void) |
| { |
| return _srv_use_direct_conn_ucx && _srv_use_direct_conn; |
| } |
| #endif |
| |
| extern int pmixp_info_srv_fence_coll_type(void) |
| { |
| if (!_srv_use_direct_conn) { |
| static bool printed = false; |
| if (!printed && PMIXP_COLL_CPERF_RING == _srv_fence_coll_type) { |
| PMIXP_ERROR("Ring collective algorithm cannot be used " |
| "with Slurm RPC's communication subsystem. " |
| "Tree-based collective will be used instead."); |
| printed = true; |
| } |
| return PMIXP_COLL_CPERF_TREE; |
| } |
| return _srv_fence_coll_type; |
| } |
| |
| extern bool pmixp_info_srv_fence_coll_barrier(void) |
| { |
| return _srv_fence_coll_barrier; |
| } |
| |
| static char *_argv_to_string(int argc, char **argv) |
| { |
| char *res = NULL, *tmp = NULL; |
| |
| if (!*argv || !argc) |
| return NULL; |
| |
| xstrcat(res, argv[0]); |
| for (int i = 1; i < argc; i++) { |
| xstrfmtcat(tmp, "%s %s", res, argv[i]); |
| xfree(res); |
| res = tmp; |
| tmp = NULL; |
| } |
| |
| return res; |
| } |
| |
| /* Job information */ |
| extern int pmixp_info_set(const stepd_step_rec_t *step, char ***env) |
| { |
| int i, rc; |
| size_t msize; |
| memset(&_pmixp_job_info, 0, sizeof(_pmixp_job_info)); |
| #ifndef NDEBUG |
| _pmixp_job_info.magic = PMIXP_INFO_MAGIC; |
| #endif |
| /* security info */ |
| _pmixp_job_info.uid = step->uid; |
| _pmixp_job_info.gid = step->gid; |
| |
| memcpy(&_pmixp_job_info.step_id, &step->step_id, |
| sizeof(_pmixp_job_info.step_id)); |
| |
| if (step->het_job_id && (step->het_job_id != NO_VAL)) |
| _pmixp_job_info.step_id.job_id = step->het_job_id; |
| |
| if ((step->het_job_offset != NO_VAL) && |
| (step->het_job_step_task_cnts)) { |
| for (i = 0; i < step->het_job_offset; i++) { |
| _pmixp_job_info.app_ldr += |
| step->het_job_step_task_cnts[i]; |
| } |
| } |
| |
| if (step->het_job_offset < NO_VAL) { |
| _pmixp_job_info.node_id = step->nodeid + |
| step->het_job_node_offset; |
| _pmixp_job_info.node_tasks = step->node_tasks; |
| _pmixp_job_info.ntasks = step->het_job_ntasks; |
| _pmixp_job_info.nnodes = step->het_job_nnodes; |
| msize = _pmixp_job_info.nnodes * sizeof(uint32_t); |
| _pmixp_job_info.task_cnts = xmalloc(msize); |
| for (i = 0; i < _pmixp_job_info.nnodes; i++) |
| _pmixp_job_info.task_cnts[i] = |
| step->het_job_task_cnts[i]; |
| |
| msize = _pmixp_job_info.node_tasks * sizeof(uint32_t); |
| _pmixp_job_info.gtids = xmalloc(msize); |
| for (i = 0; i < step->node_tasks; i++) { |
| _pmixp_job_info.gtids[i] = step->task[i]->gtid + |
| step->het_job_task_offset; |
| } |
| |
| /* Create an array that contains the step id per each task */ |
| msize = _pmixp_job_info.ntasks * sizeof(uint32_t); |
| _pmixp_job_info.het_job_offset = xmalloc(msize); |
| int t = 0; |
| for (int s = 0; s < step->het_job_step_cnt; s++) { |
| for (i = 0; i < step->het_job_step_task_cnts[s]; |
| i++, t++) { |
| _pmixp_job_info.het_job_offset[t] = s; |
| } |
| } |
| } else { |
| _pmixp_job_info.node_id = step->nodeid; |
| _pmixp_job_info.node_tasks = step->node_tasks; |
| _pmixp_job_info.ntasks = step->ntasks; |
| _pmixp_job_info.nnodes = step->nnodes; |
| msize = _pmixp_job_info.nnodes * sizeof(uint32_t); |
| _pmixp_job_info.task_cnts = xmalloc(msize); |
| for (i = 0; i < _pmixp_job_info.nnodes; i++) |
| _pmixp_job_info.task_cnts[i] = step->task_cnts[i]; |
| |
| msize = _pmixp_job_info.node_tasks * sizeof(uint32_t); |
| _pmixp_job_info.gtids = xmalloc(msize); |
| for (i = 0; i < step->node_tasks; i++) |
| _pmixp_job_info.gtids[i] = step->task[i]->gtid; |
| |
| _pmixp_job_info.het_job_offset = NULL; |
| } |
| |
| if (_pmixp_job_info.ntasks > 0) |
| _pmixp_job_info.cmd = _argv_to_string(step->task[0]->argc, |
| step->task[0]->argv); |
| |
| _pmixp_job_info.task_dist = |
| slurm_step_layout_type_name(step->task_dist); |
| |
| #if 0 |
| if ((step->het_job_id != 0) && (step->het_job_id != NO_VAL)) |
| info("HET_JOB_ID:%u", _pmixp_job_info.step_id.job_id); |
| info("%ps", &_pmixp_job_info.step_id); |
| info("NODEID:%u", _pmixp_job_info.node_id); |
| info("NODE_TASKS:%u", _pmixp_job_info.node_tasks); |
| info("NTASKS:%u", _pmixp_job_info.ntasks); |
| info("NNODES:%u", _pmixp_job_info.nnodes); |
| for (i = 0; i < _pmixp_job_info.nnodes; i++) |
| info("TASK_CNT[%d]:%u", i,_pmixp_job_info.task_cnts[i]); |
| for (i = 0; i < step->node_tasks; i++) |
| info("GTIDS[%d]:%u", i, _pmixp_job_info.gtids[i]); |
| #endif |
| |
| _pmixp_job_info.hostname = xstrdup(step->node_name); |
| |
| /* Setup job-wide info */ |
| if ((rc = _resources_set(env))) { |
| return rc; |
| } |
| |
| if ((rc = _env_set(step, env))) { |
| return rc; |
| } |
| |
| snprintf(_pmixp_job_info.nspace, sizeof(_pmixp_job_info.nspace), |
| "slurm.pmix.%d.%d", |
| pmixp_info_jobid(), pmixp_info_stepid()); |
| |
| return SLURM_SUCCESS; |
| } |
| |
| extern int pmixp_info_free(void) |
| { |
| if (_pmixp_job_info.task_cnts) { |
| xfree(_pmixp_job_info.task_cnts); |
| } |
| if (_pmixp_job_info.gtids) { |
| xfree(_pmixp_job_info.gtids); |
| } |
| |
| if (_pmixp_job_info.task_map_packed) { |
| xfree(_pmixp_job_info.task_map_packed); |
| } |
| |
| xfree(_pmixp_job_info.srun_ip); |
| xfree(_pmixp_job_info.cmd); |
| xfree(_pmixp_job_info.task_dist); |
| xfree(_pmixp_job_info.het_job_offset); |
| |
| hostlist_destroy(_pmixp_job_info.job_hl); |
| hostlist_destroy(_pmixp_job_info.step_hl); |
| if (_pmixp_job_info.hostname) { |
| xfree(_pmixp_job_info.hostname); |
| } |
| return SLURM_SUCCESS; |
| } |
| |
| static eio_handle_t *_io_handle = NULL; |
| |
| extern void pmixp_info_io_set(eio_handle_t *h) |
| { |
| _io_handle = h; |
| } |
| |
| extern eio_handle_t *pmixp_info_io(void) |
| { |
| xassert(_io_handle); |
| return _io_handle; |
| } |
| |
| static int _resources_set(char ***env) |
| { |
| char *p = NULL; |
| |
| /* Initialize abort thread info */ |
| p = getenvp(*env, PMIXP_SLURM_ABORT_AGENT_IP); |
| |
| xfree(_pmixp_job_info.srun_ip); |
| _pmixp_job_info.srun_ip = xstrdup(p); |
| |
| p = getenvp(*env, PMIXP_SLURM_ABORT_AGENT_PORT); |
| if (p) |
| _pmixp_job_info.abort_agent_port = slurm_atoul(p); |
| else |
| _pmixp_job_info.abort_agent_port = -1; |
| |
| /* |
| * Initialize all memory pointers |
| * So in case of error exit we will know what to xfree |
| */ |
| _pmixp_job_info.job_hl = hostlist_create(""); |
| _pmixp_job_info.step_hl = hostlist_create(""); |
| |
| /* Save step host list */ |
| p = getenvp(*env, PMIXP_STEP_NODES_ENV); |
| if (!p) { |
| PMIXP_ERROR_NO(ENOENT, "Environment variable %s not found", |
| PMIXP_STEP_NODES_ENV); |
| goto err_exit; |
| } |
| hostlist_push(_pmixp_job_info.step_hl, p); |
| |
| /* Determine job-wide node id and job-wide node count */ |
| p = getenvp(*env, PMIXP_JOB_NODES_ENV); |
| if (!p) { |
| p = getenvp(*env, PMIXP_JOB_NODES_ENV_DEP); |
| if (!p) { |
| /* shouldn't happen if we are under Slurm! */ |
| PMIXP_ERROR_NO(ENOENT, |
| "Neither of nodelist environment variables: %s OR %s was found!", |
| PMIXP_JOB_NODES_ENV, |
| PMIXP_JOB_NODES_ENV_DEP); |
| goto err_exit; |
| } |
| } |
| hostlist_push(_pmixp_job_info.job_hl, p); |
| _pmixp_job_info.nnodes_job = hostlist_count(_pmixp_job_info.job_hl); |
| _pmixp_job_info.node_id_job = hostlist_find(_pmixp_job_info.job_hl, |
| _pmixp_job_info.hostname); |
| |
| _pmixp_job_info.ntasks_job = _pmixp_job_info.ntasks; |
| _pmixp_job_info.ncpus_job = _pmixp_job_info.ntasks; |
| |
| /* Save task-to-node mapping */ |
| p = getenvp(*env, PMIXP_SLURM_MAPPING_ENV); |
| if (!p) { |
| /* Direct modex won't work */ |
| PMIXP_ERROR_NO(ENOENT, "No %s environment variable found!", |
| PMIXP_SLURM_MAPPING_ENV); |
| goto err_exit; |
| } |
| |
| _pmixp_job_info.task_map_packed = xstrdup(p); |
| |
| return SLURM_SUCCESS; |
| err_exit: |
| hostlist_destroy(_pmixp_job_info.job_hl); |
| hostlist_destroy(_pmixp_job_info.step_hl); |
| if (_pmixp_job_info.hostname) { |
| xfree(_pmixp_job_info.hostname); |
| } |
| |
| xfree(_pmixp_job_info.srun_ip); |
| return SLURM_ERROR; |
| } |
| |
| static void _parse_pmix_conf_env(char ***env, char *pmix_conf_env) |
| { |
| char *tmp, *tok, *sep, *save_ptr = NULL; |
| |
| if (!pmix_conf_env || !pmix_conf_env[0]) |
| return; |
| |
| tmp = xstrdup(pmix_conf_env); |
| tok = strtok_r(tmp, ";", &save_ptr); |
| while (tok) { |
| sep = strchr(tok, '='); |
| if (sep) { |
| sep[0] = '\0'; |
| sep++; |
| /* Only set PMIX and UCX related env. vars. */ |
| if (!xstrncasecmp("PMIX", tok, 4) && |
| !xstrncasecmp("UCX", tok, 4)) |
| continue; |
| |
| /* Overwrite current user's environment */ |
| setenvf(env, tok, "%s", sep); |
| |
| debug2("Setting env. from mpi.conf - %s=%s", tok, sep); |
| setenv(tok, sep, 1); |
| } |
| tok = strtok_r(NULL, ";", &save_ptr); |
| } |
| xfree(tmp); |
| } |
| |
| static int _env_set(const stepd_step_rec_t *step, char ***env) |
| { |
| char *p = NULL; |
| |
| xassert(_pmixp_job_info.hostname); |
| |
| /* |
| * Set first the random environment vars specified in mpi.conf. |
| * They will take precedence and overwrite any user environment variable |
| * already set and any discrete setting in pmix.conf. |
| */ |
| _parse_pmix_conf_env(env, slurm_pmix_conf.env); |
| |
| if (step->container) { |
| /* |
| * In this case PMIx tmp files/dirs are created under: |
| * ContainerPath/oci-<jobid>-<stepid>/ |
| * |
| * ContainerPath could be considered trusted, but oci subdir has |
| * user permissions and contents can be modified. oci subdir is |
| * created by stepd and is not a symlink, so we don't need that |
| * flexibility anyway, thus let's be conservative. |
| * |
| * See: src/slurmd/slurmstepd/container.[ch] |
| */ |
| _pmixp_job_info.server_addr_unfmt = |
| xstrdup(step->container->spool_dir); |
| _pmixp_job_info.client_lib_tmpdir = |
| xstrdup(step->container->mount_spool_dir); |
| } else { |
| _pmixp_job_info.server_addr_unfmt = |
| xstrdup(slurm_conf.slurmd_spooldir); |
| _pmixp_job_info.flags |= PMIXP_FLAG_TRUSTED_LIB_TMPDIR; |
| } |
| |
| debug2("set _pmixp_job_info.server_addr_unfmt = %s", |
| _pmixp_job_info.server_addr_unfmt); |
| |
| if (!_pmixp_job_info.lib_tmpdir) |
| _pmixp_job_info.lib_tmpdir = slurm_conf_expand_slurmd_path( |
| _pmixp_job_info.server_addr_unfmt, |
| _pmixp_job_info.hostname, NULL); |
| |
| xstrfmtcat(_pmixp_job_info.server_addr_unfmt, |
| "/stepd.slurm.pmix.%d.%d", |
| pmixp_info_jobid(), pmixp_info_stepid()); |
| |
| _pmixp_job_info.spool_dir = xstrdup(_pmixp_job_info.lib_tmpdir); |
| |
| /* ----------- Temp directories settings ------------- */ |
| xstrfmtcat(_pmixp_job_info.lib_tmpdir, "/pmix.%d.%d/", |
| pmixp_info_jobid(), pmixp_info_stepid()); |
| |
| /* save client temp directory if requested |
| * TODO: We want to get TmpFS value as well if exists. |
| * Need to sync with Slurm developers. |
| */ |
| p = getenvp(*env, PMIXP_TMPDIR_CLI); |
| |
| if (p){ |
| _pmixp_job_info.cli_tmpdir_base = xstrdup(p); |
| } else if (step->container) { |
| _pmixp_job_info.cli_tmpdir_base = xstrdup( |
| step->container->spool_dir); |
| } else if (slurm_pmix_conf.cli_tmpdir_base) { |
| _pmixp_job_info.cli_tmpdir_base = |
| xstrdup(slurm_pmix_conf.cli_tmpdir_base); |
| _pmixp_job_info.flags |= PMIXP_FLAG_TRUSTED_CLI_TMPDIR; |
| } else { |
| _pmixp_job_info.cli_tmpdir_base = slurm_get_tmp_fs( |
| _pmixp_job_info.hostname); |
| _pmixp_job_info.flags |= PMIXP_FLAG_TRUSTED_CLI_TMPDIR; |
| } |
| |
| _pmixp_job_info.cli_tmpdir = |
| xstrdup_printf("%s/spmix_appdir_%u_%d.%d", |
| _pmixp_job_info.cli_tmpdir_base, |
| pmixp_info_jobuid(), |
| pmixp_info_jobid(), |
| pmixp_info_stepid()); |
| |
| /* ----------- Timeout setting ------------- */ |
| /* TODO: also would be nice to have a cluster-wide setting in Slurm */ |
| p = getenvp(*env, PMIXP_TIMEOUT); |
| if (p) { |
| int tmp; |
| tmp = atoi(p); |
| if (tmp > 0) { |
| _pmixp_job_info.timeout = tmp; |
| } |
| } else |
| _pmixp_job_info.timeout = slurm_pmix_conf.timeout; |
| |
| /* ----------- Forward PMIX settings ------------- */ |
| /* FIXME: this may be intrusive as well as PMIx library will create |
| * lots of output files in /tmp by default. |
| * somebody can use this or annoyance */ |
| p = getenvp(*env, PMIXP_PMIXLIB_DEBUG); |
| if (p) { |
| setenv(PMIXP_PMIXLIB_DEBUG, p, 1); |
| /* output into the file since we are in slurmstepd |
| * and stdout is muted. |
| * One needs to check TMPDIR for the results */ |
| setenv(PMIXP_PMIXLIB_DEBUG_REDIR, "file", 1); |
| } else if (slurm_pmix_conf.debug) { |
| char *tmp; |
| tmp = xstrdup_printf("%d", slurm_pmix_conf.debug); |
| setenv(PMIXP_PMIXLIB_DEBUG, tmp, 1); |
| setenv(PMIXP_PMIXLIB_DEBUG_REDIR, "file", 1); |
| xfree(tmp); |
| } |
| |
| /*------------- Flag controlling heterogeneous support ----------*/ |
| /* NOTE: Heterogen support is not tested */ |
| p = getenvp(*env, PMIXP_DIRECT_SAMEARCH); |
| if (p) { |
| if (!xstrcmp("1",p) || !xstrcasecmp("true", p) || |
| !xstrcasecmp("yes", p)) { |
| _srv_same_arch = true; |
| } else if (!xstrcmp("0",p) || !xstrcasecmp("false", p) || |
| !xstrcasecmp("no", p)) { |
| _srv_same_arch = false; |
| } |
| } else |
| _srv_same_arch = slurm_pmix_conf.direct_samearch; |
| |
| /*------------- Direct connection setting ----------*/ |
| p = getenvp(*env, PMIXP_DIRECT_CONN); |
| if (p) { |
| if (!xstrcmp("1",p) || !xstrcasecmp("true", p) || |
| !xstrcasecmp("yes", p)) { |
| _srv_use_direct_conn = true; |
| } else if (!xstrcmp("0",p) || !xstrcasecmp("false", p) || |
| !xstrcasecmp("no", p)) { |
| _srv_use_direct_conn = false; |
| } |
| } else |
| _srv_use_direct_conn = slurm_pmix_conf.direct_conn; |
| |
| p = getenvp(*env, PMIXP_DIRECT_CONN_EARLY); |
| if (p) { |
| if (!xstrcmp("1", p) || !xstrcasecmp("true", p) || |
| !xstrcasecmp("yes", p)) { |
| _srv_use_direct_conn_early = true; |
| } else if (!xstrcmp("0", p) || !xstrcasecmp("false", p) || |
| !xstrcasecmp("no", p)) { |
| _srv_use_direct_conn_early = false; |
| } |
| } else |
| _srv_use_direct_conn_early = slurm_pmix_conf.direct_conn_early; |
| |
| /*------------- Fence coll type setting ----------*/ |
| p = getenvp(*env, PMIXP_COLL_FENCE); |
| if (!p) |
| p = slurm_pmix_conf.coll_fence; |
| if (p) { |
| if (!xstrcmp("mixed", p)) { |
| _srv_fence_coll_type = PMIXP_COLL_CPERF_MIXED; |
| } else if (!xstrcmp("tree", p)) { |
| _srv_fence_coll_type = PMIXP_COLL_CPERF_TREE; |
| } else if (!xstrcmp("ring", p)) { |
| _srv_fence_coll_type = PMIXP_COLL_CPERF_RING; |
| } |
| } |
| |
| p = getenvp(*env, SLURM_PMIXP_FENCE_BARRIER); |
| if (p) { |
| if (!xstrcmp("1",p) || !xstrcasecmp("true", p) || |
| !xstrcasecmp("yes", p)) { |
| _srv_fence_coll_barrier = true; |
| } else if (!xstrcmp("0",p) || !xstrcasecmp("false", p) || |
| !xstrcasecmp("no", p)) { |
| _srv_fence_coll_barrier = false; |
| } |
| } else |
| _srv_fence_coll_barrier = slurm_pmix_conf.fence_barrier; |
| |
| /* |
| * Setup transport keys in case the MPI layer needs them. |
| * |
| * We use the jobid and stepid to form the unique keys in this node. |
| * |
| * According to Intel the format is 16 digit hexadecimal characters |
| * separated by a dash. For example: 13241234acffedeb-abcdefabcdef1233 |
| * |
| * This key is used by the PSM2 library to uniquely identify each |
| * different job end point used on the fabric. If two MPI jobs are |
| * running on the same node sharing the same HFI and using PSM2, each |
| * one should have a different key. |
| */ |
| if (!getenvp(*env, "OMPI_MCA_orte_precondition_transports")) { |
| char *string_key = xstrdup_printf("%08x%08x-%08x%08x", |
| step->step_id.job_id, |
| step->step_id.step_id, |
| step->step_id.job_id, |
| step->step_id.step_id); |
| env_array_overwrite(env, |
| "OMPI_MCA_orte_precondition_transports", |
| string_key); |
| log_flag(MPI, |
| "Setting OMPI_MCA_orte_precondition_transports=%s", |
| string_key); |
| xfree(string_key); |
| } |
| |
| #ifdef HAVE_UCX |
| p = getenvp(*env, PMIXP_DIRECT_CONN_UCX); |
| if (p) { |
| if (!xstrcmp("1",p) || !xstrcasecmp("true", p) || |
| !xstrcasecmp("yes", p)) { |
| _srv_use_direct_conn_ucx = true; |
| } else if (!xstrcmp("0",p) || !xstrcasecmp("false", p) || |
| !xstrcasecmp("no", p)) { |
| _srv_use_direct_conn_ucx = false; |
| } |
| } else |
| _srv_use_direct_conn_ucx = slurm_pmix_conf.direct_conn_ucx; |
| |
| /* Propagate UCX env */ |
| p = getenvp(*env, "UCX_NET_DEVICES"); |
| if (p) |
| setenv("UCX_NET_DEVICES", p, 1); |
| else if (slurm_pmix_conf.ucx_netdevices) { |
| setenv("UCX_NET_DEVICES", slurm_pmix_conf.ucx_netdevices, 1); |
| env_array_overwrite(env, "UCX_NET_DEVICES", |
| slurm_pmix_conf.ucx_netdevices); |
| } |
| |
| p = getenvp(*env, "UCX_TLS"); |
| if (p) |
| setenv("UCX_TLS", p, 1); |
| else if (slurm_pmix_conf.ucx_tls) { |
| setenv("UCX_TLS", slurm_pmix_conf.ucx_tls, 1); |
| env_array_overwrite(env, "UCX_TLS", slurm_pmix_conf.ucx_tls); |
| } |
| |
| #endif |
| |
| return SLURM_SUCCESS; |
| } |
| |
| extern int pmixp_info_timeout() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.timeout; |
| } |
| |
| /* My hostname */ |
| extern char *pmixp_info_hostname() |
| { |
| return _pmixp_job_info.hostname; |
| } |
| |
| /* Cli tempdir */ |
| extern char *pmixp_info_tmpdir_cli() |
| { |
| return _pmixp_job_info.cli_tmpdir; |
| } |
| |
| extern char *pmixp_info_tmpdir_cli_base() |
| { |
| return _pmixp_job_info.cli_tmpdir_base; |
| } |
| |
| /* Lib tempdir */ |
| extern char *pmixp_info_tmpdir_lib() |
| { |
| return _pmixp_job_info.lib_tmpdir; |
| } |
| |
| /* client Lib tempdir */ |
| extern char *_pmixp_info_client_tmpdir_lib() |
| { |
| if (_pmixp_job_info.client_lib_tmpdir) |
| return _pmixp_job_info.client_lib_tmpdir; |
| else |
| return pmixp_info_tmpdir_lib(); |
| } |
| |
| extern char *pmixp_info_cmd() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.cmd; |
| } |
| |
| extern uint32_t pmixp_info_jobuid() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.uid; |
| } |
| |
| extern uint32_t pmixp_info_jobgid() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.gid; |
| } |
| |
| extern uint32_t pmixp_info_jobid() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.step_id.job_id; |
| } |
| |
| extern uint32_t pmixp_info_job_offset(int rank) |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| if (!_pmixp_job_info.het_job_offset) |
| return 0; |
| return _pmixp_job_info.het_job_offset[rank]; |
| } |
| |
| extern char *pmixp_info_srun_ip() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.srun_ip; |
| } |
| |
| extern int pmixp_info_abort_agent_port() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.abort_agent_port; |
| } |
| |
| extern uint32_t pmixp_info_stepid() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.step_id.step_id; |
| } |
| |
| extern char *pmixp_info_namespace() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.nspace; |
| } |
| |
| extern uint32_t pmixp_info_nodeid() |
| { |
| /* This routine is called from PMIX_DEBUG/ERROR and |
| * this CAN happen before initialization. Relax demand to have |
| * _pmix_job_info.magic == PMIX_INFO_MAGIC |
| * ! xassert(_pmix_job_info.magic == PMIX_INFO_MAGIC); |
| */ |
| return _pmixp_job_info.node_id; |
| } |
| |
| extern uint32_t pmixp_info_nodeid_job() |
| { |
| /* This routine is called from PMIX_DEBUG/ERROR and |
| * this CAN happen before initialization. Relax demand to have |
| * _pmix_job_info.magic == PMIX_INFO_MAGIC |
| * ! xassert(_pmix_job_info.magic == PMIX_INFO_MAGIC); |
| */ |
| return _pmixp_job_info.node_id_job; |
| } |
| |
| extern uint32_t pmixp_info_nodes() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.nnodes; |
| } |
| |
| extern uint32_t pmixp_info_nodes_uni() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.nnodes_job; |
| } |
| |
| extern uint32_t pmixp_info_tasks() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.ntasks; |
| } |
| |
| extern uint32_t pmixp_info_tasks_node(uint32_t nodeid) |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| xassert(nodeid < _pmixp_job_info.nnodes); |
| return _pmixp_job_info.task_cnts[nodeid]; |
| } |
| |
| extern uint32_t *pmixp_info_tasks_cnts() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.task_cnts; |
| } |
| |
| extern uint32_t pmixp_info_tasks_loc() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.node_tasks; |
| } |
| |
| extern uint32_t pmixp_info_tasks_uni() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.ntasks_job; |
| } |
| |
| extern uint32_t pmixp_info_cpus() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.ncpus_job; |
| } |
| |
| extern uint32_t pmixp_info_taskid(uint32_t localid) |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| xassert(localid < _pmixp_job_info.node_tasks); |
| return _pmixp_job_info.gtids[localid]; |
| } |
| |
| /* |
| * Since tasks array in Slurm job structure is uint16_t |
| * task local id can't be grater than 2^16. So we can |
| * safely return int here. We need (-1) for the not-found case |
| */ |
| extern int pmixp_info_taskid2localid(uint32_t taskid) |
| { |
| int i; |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| xassert(taskid < _pmixp_job_info.ntasks); |
| |
| for (i = 0; i < _pmixp_job_info.node_tasks; i++) { |
| if (_pmixp_job_info.gtids[i] == taskid) |
| return i; |
| } |
| return -1; |
| } |
| |
| extern char *pmixp_info_task_dist() |
| { |
| return _pmixp_job_info.task_dist; |
| } |
| |
| extern char *pmixp_info_task_map() |
| { |
| return _pmixp_job_info.task_map_packed; |
| } |
| |
| extern hostlist_t *pmixp_info_step_hostlist() |
| { |
| return _pmixp_job_info.step_hl; |
| } |
| |
| extern char *pmixp_info_step_host(int nodeid) |
| { |
| xassert(nodeid < _pmixp_job_info.nnodes); |
| char *p = hostlist_nth(_pmixp_job_info.step_hl, nodeid); |
| char *ret = xstrdup(p); |
| free(p); |
| return ret; |
| } |
| |
| extern int pmixp_info_step_hostid(char *hostname) |
| { |
| return hostlist_find(_pmixp_job_info.step_hl, hostname); |
| } |
| |
| extern char *pmixp_info_job_host(int nodeid) |
| { |
| xassert(nodeid < _pmixp_job_info.nnodes_job); |
| if (nodeid >= _pmixp_job_info.nnodes_job) { |
| return NULL; |
| } |
| char *p = hostlist_nth(_pmixp_job_info.job_hl, nodeid); |
| char *ret = xstrdup(p); |
| free(p); |
| return ret; |
| } |
| |
| extern int pmixp_info_job_hostid(char *hostname) |
| { |
| return hostlist_find(_pmixp_job_info.job_hl, hostname); |
| } |
| |
| /* namespaces list operations */ |
| extern char *pmixp_info_nspace_usock(const char *nspace) |
| { |
| char *spool; |
| debug("setup sockets"); |
| spool = xstrdup_printf("%s/stepd.%s", |
| _pmixp_job_info.spool_dir, nspace); |
| return spool; |
| } |
| |
| extern uint32_t pmixp_info_appldr() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.app_ldr; |
| } |
| |
| extern uint32_t pmixp_info_flags() |
| { |
| xassert(_pmixp_job_info.magic == PMIXP_INFO_MAGIC); |
| return _pmixp_job_info.flags; |
| } |