/* * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2021 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006-2017 Los Alamos National Security, LLC. * All rights reserved. * Copyright (c) 2009-2022 Cisco Systems, Inc. All rights reserved * Copyright (c) 2011-2017 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2017 UT-Battelle, LLC. All rights reserved. * Copyright (c) 2013-2020 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2018-2022 IBM Corporation. All rights reserved. * Copyright (c) 2021-2024 Nanook Consulting All rights reserved. * Copyright (c) 2022-2024 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ * */ #include "prte_config.h" #include "types.h" #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_SYS_UTSNAME_H # include #endif #include "src/util/pmix_argv.h" #include "src/util/name_fns.h" #include "src/util/pmix_os_dirpath.h" #include "src/util/pmix_os_path.h" #include "src/util/pmix_path.h" #include "src/util/pmix_environ.h" #include "src/util/proc_info.h" #include "src/util/prte_cmd_line.h" #include "src/runtime/pmix_init_util.h" #include "src/util/session_dir.h" #include "src/util/pmix_show_help.h" #include "src/mca/base/pmix_mca_base_vari.h" #include "src/mca/errmgr/errmgr.h" #include "src/mca/ess/base/base.h" #include "src/mca/rmaps/base/base.h" #include "src/mca/state/base/base.h" #include "src/runtime/prte_globals.h" #include "schizo_ompi.h" #include "src/mca/schizo/base/base.h" static int parse_cli(char **argv, pmix_cli_result_t *results, bool silent); static int detect_proxy(char *argv); static int parse_env(char **srcenv, char ***dstenv, pmix_cli_result_t *cli); static void allow_run_as_root(pmix_cli_result_t *results); static int set_default_ranking(prte_job_t *jdata, prte_rmaps_options_t *options); static void job_info(pmix_cli_result_t *results, void *jobinfo); static int setup_app(prte_pmix_app_t *app); static int set_default_rto(prte_job_t *jdata, prte_rmaps_options_t *options); prte_schizo_base_module_t prte_schizo_ompi_module = { .name = "ompi", .parse_cli = parse_cli, .parse_env = parse_env, .setup_fork = prte_schizo_base_setup_fork, .setup_app = setup_app, .detect_proxy = detect_proxy, .allow_run_as_root = allow_run_as_root, .set_default_ranking = set_default_ranking, .job_info = job_info, .set_default_rto = set_default_rto, .check_sanity = prte_schizo_base_sanity }; static struct option ompioptions[] = { /* basic options */ PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PMIX_ARG_OPTIONAL, 'h'), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PMIX_ARG_NONE, 'V'), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PMIX_ARG_NONE, 'v'), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_PARSEABLE, PMIX_ARG_NONE, 'p'), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_PARSABLE, PMIX_ARG_NONE, 'p'), // synonym for parseable PMIX_OPTION_DEFINE(PRTE_CLI_REPORT_PID, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_REPORT_URI, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_PERSONALITY, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_DVM, PMIX_ARG_REQD), // MCA parameters PMIX_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PMIX_ARG_REQD), PMIX_OPTION_DEFINE("omca", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("gomca", PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_TUNE, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_LAUNCH_AGENT, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_MAX_VM_SIZE, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS_FILE, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_LEAVE_SESSION_ATTACHED, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_TMPDIR, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_PREFIX, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_NOPREFIX, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_FWD_SIGNALS, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_RUN_AS_ROOT, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_REPORT_CHILD_SEP, PMIX_ARG_NONE), /* debug options */ PMIX_OPTION_DEFINE(PRTE_CLI_XTERM, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_STOP_ON_EXEC, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_STOP_IN_INIT, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_STOP_IN_APP, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_TIMEOUT, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_REPORT_STATE, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_STACK_TRACES, PMIX_ARG_NONE), #ifdef PMIX_SPAWN_TIMEOUT PMIX_OPTION_DEFINE(PRTE_CLI_SPAWN_TIMEOUT, PMIX_ARG_REQD), #endif #ifdef PMIX_LOG_AGG PMIX_OPTION_DEFINE(PRTE_CLI_DO_NOT_AGG_HELP, PMIX_ARG_NONE), #endif /* Conventional options - for historical compatibility, support * both single and multi dash versions */ /* Number of processes; -c, -n, --n, -np, and --np are all synonyms */ PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PMIX_ARG_REQD, 'n'), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PMIX_ARG_REQD, 'c'), PMIX_OPTION_DEFINE("n", PMIX_ARG_REQD), // will be converted to "np" after parsing PMIX_OPTION_SHORT_DEFINE("N", PMIX_ARG_REQD, 'N'), PMIX_OPTION_DEFINE(PRTE_CLI_APPFILE, PMIX_ARG_REQD), /* output options */ PMIX_OPTION_DEFINE(PRTE_CLI_OUTPUT, PMIX_ARG_REQD), /* input options */ PMIX_OPTION_DEFINE(PRTE_CLI_STDIN, PMIX_ARG_REQD), /* launch options */ PMIX_OPTION_DEFINE(PRTE_CLI_PRELOAD_FILES, PMIX_ARG_REQD), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_PRELOAD_BIN, PMIX_ARG_NONE, 's'), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_FWD_ENVAR, PMIX_ARG_REQD, 'x'), PMIX_OPTION_DEFINE(PRTE_CLI_WDIR, PMIX_ARG_REQD), PMIX_OPTION_DEFINE("wd", PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_PATH, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_PSET, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_HOSTFILE, PMIX_ARG_REQD), PMIX_OPTION_DEFINE("machinefile", PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_DEFAULT_HOSTFILE, PMIX_ARG_REQD), PMIX_OPTION_SHORT_DEFINE(PRTE_CLI_HOST, PMIX_ARG_REQD, 'H'), PMIX_OPTION_DEFINE(PRTE_CLI_FWD_ENVIRON, PMIX_ARG_OPTIONAL), /* placement options */ /* Mapping options */ PMIX_OPTION_DEFINE(PRTE_CLI_MAPBY, PMIX_ARG_REQD), /* Ranking options */ PMIX_OPTION_DEFINE(PRTE_CLI_RANKBY, PMIX_ARG_REQD), /* Binding options */ PMIX_OPTION_DEFINE(PRTE_CLI_BINDTO, PMIX_ARG_REQD), /* display options */ PMIX_OPTION_DEFINE(PRTE_CLI_DISPLAY, PMIX_ARG_REQD), /* developer options */ PMIX_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PMIX_ARG_NONE), // Runtime options PMIX_OPTION_DEFINE(PRTE_CLI_RTOS, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_ENABLE_RECOVERY, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_MAX_RESTARTS, PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_DISABLE_RECOVERY, PMIX_ARG_NONE), PMIX_OPTION_DEFINE(PRTE_CLI_CONTINUOUS, PMIX_ARG_NONE), PMIX_OPTION_DEFINE("with-ft", PMIX_ARG_REQD), /* mpiexec mandated form launch key parameters - MPI 4.0 */ PMIX_OPTION_DEFINE("initial-errhandler", PMIX_ARG_REQD), /* mpiexec mandated form launch key parameters - MPI 4.1*/ PMIX_OPTION_DEFINE("memory-alloc-kinds", PMIX_ARG_REQD), /* Display Commumication Protocol : MPI_Init */ PMIX_OPTION_DEFINE("display-comm", PMIX_ARG_NONE), /* Display Commumication Protocol : MPI_Finalize */ PMIX_OPTION_DEFINE("display-comm-finalize", PMIX_ARG_NONE), // unsupported, but mandated options PMIX_OPTION_DEFINE("soft", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("arch", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("file", PMIX_ARG_REQD), // deprecated options PMIX_OPTION_DEFINE("mca", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("gmca", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("xml", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("tag-output", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("timestamp-output", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("output-directory", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("output-filename", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("merge-stderr-to-stdout", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("display-devel-map", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("display-topo", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("report-bindings", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("display-map", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("display-allocation", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("nolocal", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("oversubscribe", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("nooversubscribe", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("use-hwthread-cpus", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("cpu-set", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("cpu-list", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("bind-to-core", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("bynode", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("bycore", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("byslot", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("cpus-per-proc", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("cpus-per-rank", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("npernode", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("pernode", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("npersocket", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("ppr", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("amca", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("am", PMIX_ARG_REQD), PMIX_OPTION_DEFINE("rankfile", PMIX_ARG_REQD), PMIX_OPTION_DEFINE(PRTE_CLI_OUTPUT_PROCTABLE, PMIX_ARG_OPTIONAL), PMIX_OPTION_DEFINE("debug", PMIX_ARG_NONE), PMIX_OPTION_DEFINE("stream-buffering", PMIX_ARG_REQD), PMIX_OPTION_END }; static char *ompishorts = "h::vVpn:c:N:sH:x:"; static char *ompi_install_dirs_libdir = NULL; static int convert_deprecated_cli(pmix_cli_result_t *results, bool silent); static void set_classpath_jar_file(prte_pmix_app_t *app, int index, char *jarfile) { if (NULL == strstr(app->app.argv[index], jarfile)) { /* nope - need to add it */ char *fmt = ':' == app->app.argv[index][strlen(app->app.argv[index]-1)] ? "%s%s/%s" : "%s:%s/%s"; char *str; asprintf(&str, fmt, app->app.argv[index], ompi_install_dirs_libdir, jarfile); free(app->app.argv[index]); app->app.argv[index] = str; } } /* * OMPI schizo setup_app is the place we prep for Java apps */ static int setup_app(prte_pmix_app_t *app) { bool found; int i,rc; char *value; /* if this is a Java application, we have a bit more work to do. Such * applications actually need to be run under the Java virtual machine * and the "java" command will start the "executable". So we need to ensure * that all the proper java-specific paths are provided */ if (0 != strcmp(app->app.argv[0], "java")) { return PRTE_SUCCESS; } ompi_install_dirs_libdir = getenv("OMPI_LIBDIR_LOC"); if (NULL == ompi_install_dirs_libdir) { pmix_show_help("help-schizo-ompi.txt", "openmpi-install-path-not-found",1); return PRTE_ERR_NOT_AVAILABLE; } /* see if we were given a library path */ found = false; for (i=1; NULL != app->app.argv[i]; i++) { if (NULL != strstr(app->app.argv[i], "java.library.path")) { char *dptr; /* find the '=' that delineates the option from the path */ if (NULL == (dptr = strchr(app->app.argv[i], '='))) { /* that's just wrong */ rc = PRTE_ERR_BAD_PARAM; goto cleanup; } /* step over the '=' */ ++dptr; /* yep - but does it include the path to the mpi libs? */ found = true; if (NULL == strstr(app->app.argv[i], ompi_install_dirs_libdir)) { /* doesn't appear to - add it to be safe */ if (':' == app->app.argv[i][strlen(app->app.argv[i]-1)]) { asprintf(&value, "-Djava.library.path=%s%s", dptr, ompi_install_dirs_libdir); } else { asprintf(&value, "-Djava.library.path=%s:%s", dptr, ompi_install_dirs_libdir); } free(app->app.argv[i]); app->app.argv[i] = value; } break; } } if (!found) { /* need to add it right after the java command */ asprintf(&value, "-Djava.library.path=%s", ompi_install_dirs_libdir); pmix_argv_insert_element(&app->app.argv, 1, value); free(value); } /* see if we were given a class path * See https://docs.oracle.com/javase/8/docs/technotes/tools/findingclasses.html * for more info about rules for the ways to set the class path */ found = false; for (i=1; NULL != app->app.argv[i]; i++) { if (NULL != strstr(app->app.argv[i], "cp") || NULL != strstr(app->app.argv[i], "classpath")) { /* yep - but does it include the path to the mpi libs? */ found = true; /* check if mpi.jar exists - if so, add it */ value = pmix_os_path(false, ompi_install_dirs_libdir, "mpi.jar", NULL); if (access(value, F_OK ) != -1) { set_classpath_jar_file(app, i+1, "mpi.jar"); } free(value); /* always add the local directory */ asprintf(&value, "%s:%s", app->app.cwd, app->app.argv[i+1]); free(app->app.argv[i+1]); app->app.argv[i+1] = value; break; } } if (!found) { /* check to see if CLASSPATH is in the environment */ found = false; // just to be pedantic for (i=0; NULL != environ[i]; i++) { if (0 == strncmp(environ[i], "CLASSPATH", strlen("CLASSPATH"))) { value = strchr(environ[i], '='); ++value; /* step over the = */ pmix_argv_insert_element(&app->app.argv, 1, value); /* check for mpi.jar */ value = pmix_os_path(false, ompi_install_dirs_libdir, "mpi.jar", NULL); if (access(value, F_OK ) != -1) { set_classpath_jar_file(app, 1, "mpi.jar"); } free(value); /* always add the local directory */ (void)asprintf(&value, "%s:%s", app->app.cwd, app->app.argv[1]); free(app->app.argv[1]); app->app.argv[1] = value; pmix_argv_insert_element(&app->app.argv, 1, "-cp"); found = true; break; } } if (!found) { /* need to add it right after the java command - have * to include the working directory and trust that * the user set cwd if necessary */ char *str, *str2; /* always start with the working directory */ str = strdup(app->app.cwd); /* check for mpi.jar */ value = pmix_os_path(false, ompi_install_dirs_libdir, "mpi.jar", NULL); if (access(value, F_OK ) != -1) { (void)asprintf(&str2, "%s:%s", str, value); free(str); str = str2; } free(value); pmix_argv_insert_element(&app->app.argv, 1, str); free(str); pmix_argv_insert_element(&app->app.argv, 1, "-cp"); } } return PRTE_SUCCESS; cleanup: return rc; } static bool mcaoption(char *s) { size_t len = strlen(s); if (3 > len) { return false; } if ('a' == s[len-1] && 'c' == s[len-2] && 'm' == s[len-3]) { return true; } return false; } static int parse_cli(char **argv, pmix_cli_result_t *results, bool silent) { int rc, n; pmix_cli_item_t *opt; char *p1, *p2; char **pargv; /* backup the argv */ pargv = PMIX_ARGV_COPY_COMPAT(argv); char **caught_single_dashes = NULL; int *caught_positions = NULL; int cur_caught_pos = 0; bool warn; if (silent) { warn = false; } else { warn = prte_mca_schizo_ompi_component.warn_deprecations; } if(warn) { int argc = 0; for(n=1; NULL != pargv[n]; n++) argc++; caught_single_dashes = calloc(argc + 1, sizeof(char *)); caught_positions = calloc(argc + 1, sizeof(int)); } /* Convert single dashes to multi-dashes. */ for (n=1; NULL != pargv[n]; n++) { if (0 == strcmp("--", pargv[n])) { // quit processing break; } /* check for option */ if ('-' != pargv[n][0]) { continue; } // if this is an mca spec, then skip it if (mcaoption(pargv[n])) { if ('-' != pargv[n][1]) { // make it a "--" option p2 = strdup(pargv[n]); free(pargv[n]); pmix_asprintf(&pargv[n], "-%s", p2); free(p2); } // now skip the next two positions n += 2; continue; } /* check for single-dash errors */ if ('-' != pargv[n][1] && 2 < strlen(pargv[n])) { /* we know this is incorrect */ p2 = pargv[n]; pmix_asprintf(&pargv[n], "-%s", p2); if(warn) { caught_single_dashes[cur_caught_pos] = strdup(p2); caught_positions[cur_caught_pos++] = n; } free(p2); } } const char *tool_version = getenv("OMPI_VERSION"); const char *tool_name = getenv("OMPI_TOOL_NAME"); // If the user is using prterun --personality ompi, these // won't be set, and thus this is not mpirun/mpiexec. if(tool_version && tool_name) { pmix_tool_version = tool_version; pmix_tool_basename = tool_name; pmix_tool_org = "Open MPI"; pmix_tool_msg = "Report bugs to https://www.open-mpi.org/community/help/"; } rc = pmix_cmd_line_parse(pargv, ompishorts, ompioptions, NULL, results, "help-schizo-ompi.txt"); if (PMIX_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(pargv); if (PMIX_OPERATION_SUCCEEDED == rc) { /* pmix cmd line interpreter output result * successfully - usually means version or * some other stock output was generated */ return PRTE_OPERATION_SUCCEEDED; } if(warn) { for(n = 0; n < cur_caught_pos; n++) { free(caught_single_dashes[n]); } free(caught_single_dashes); free(caught_positions); } return prte_pmix_convert_status(rc); } /* * If warning is enabled, list all offending * single dash params are before the last found * argument by the parser (results -> tail). * * The only case where tail should be NULL is * if the user didn't specify an executable on * the command line, and that should have been caught * earlier. Put a bozo check anyway. */ if(warn && cur_caught_pos > 0 && results->tail) { char *orig_args = NULL; char *corrected_args = NULL; int tail_pos = 0; // Find the position of the tail. for(n = 0; NULL != pargv[n]; n++) { if(0 == strcmp(results->tail[0], pargv[n])) break; } tail_pos = n; for(n = 0; n < cur_caught_pos; n++) { // Add all offending arguments before the user executable (tail). if(caught_positions[n] < tail_pos) { // Multiple offending single dashes case. Append and free. if(orig_args && corrected_args) { char *tmp = orig_args; pmix_asprintf(&orig_args, "%s, %s", tmp, caught_single_dashes[n]); free(tmp); tmp = corrected_args; pmix_asprintf(&corrected_args, "%s, -%s", tmp, caught_single_dashes[n]); free(tmp); } else { // First case. pmix_asprintf(&orig_args, "%s", caught_single_dashes[n]); pmix_asprintf(&corrected_args, "-%s", caught_single_dashes[n]); } } else { break; } } if(orig_args && corrected_args) { pmix_show_help("help-schizo-base.txt", "single-dash-error", true, orig_args, corrected_args); free(orig_args); free(corrected_args); } for(n = 0; n < cur_caught_pos; n++) { free(caught_single_dashes[n]); } free(caught_single_dashes); free(caught_positions); } PMIX_ARGV_FREE_COMPAT(pargv); /* check for deprecated options - warn and convert them */ rc = convert_deprecated_cli(results, silent); if (PRTE_SUCCESS != rc) { return rc; } // handle relevant MCA params PMIX_LIST_FOREACH(opt, &results->instances, pmix_cli_item_t) { if (0 == strcmp(opt->key, PRTE_CLI_PRTEMCA)) { for (n=0; NULL != opt->values[n]; n++) { p1 = opt->values[n]; prte_schizo_base_expose(p1, "PRTE_MCA_"); } } else if (0 == strcmp(opt->key, PRTE_CLI_PMIXMCA)) { for (n=0; NULL != opt->values[n]; n++) { p1 = opt->values[n]; prte_schizo_base_expose(p1, "PMIX_MCA_"); } } else if(0 == strcmp(opt->key, "mca") || 0 == strcmp(opt->key, "omca")) { for (n=0; NULL != opt->values[n]; n++) { p1 = opt->values[n]; prte_schizo_base_expose(p1, "OMPI_MCA_"); } } } if (NULL != results->tail) { /* search for the leader of the tail */ for (n=0; NULL != argv[n]; n++) { if (0 == strcmp(results->tail[0], argv[n])) { /* this starts the tail - replace the rest of the * tail with the original argv */ PMIX_ARGV_FREE_COMPAT(results->tail); results->tail = PMIX_ARGV_COPY_COMPAT(&argv[n]); break; } } } return PRTE_SUCCESS; } static int convert_deprecated_cli(pmix_cli_result_t *results, bool silent) { char *option, *p1, *p2, *tmp, *tmp2, *output; int rc = PRTE_SUCCESS; pmix_cli_item_t *opt, *nxt; bool warn; if (silent) { warn = false; } else { warn = prte_mca_schizo_ompi_component.warn_deprecations; } PMIX_LIST_FOREACH_SAFE(opt, nxt, &results->instances, pmix_cli_item_t) { option = opt->key; if (0 == strcmp(option, "n")) { /* if they passed a "--n" option, we need to convert it * back to the "--np" one without a deprecation warning */ rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_NP, opt->values[0], false); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --nolocal -> --map-by :nolocal */ else if (0 == strcmp(option, "nolocal")) { rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, PRTE_CLI_NOLOCAL, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --oversubscribe -> --map-by :OVERSUBSCRIBE */ else if (0 == strcmp(option, "oversubscribe")) { rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, PRTE_CLI_OVERSUB, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --nooversubscribe -> --map-by :NOOVERSUBSCRIBE */ else if (0 == strcmp(option, "nooversubscribe")) { rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, PRTE_CLI_NOOVER, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --use-hwthread-cpus -> --map-by hwtcpus */ else if (0 == strcmp(option, "use-hwthread-cpus")) { rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, PRTE_CLI_HWTCPUS, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); if (NULL != prte_set_slots) { free(prte_set_slots); } prte_set_slots = strdup("hwthreads"); } /* --do-not-launch -> --runtime-options do-not-launch */ else if(0 == strcmp(option, "do-not-launch")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_RTOS, PRTE_CLI_NOLAUNCH, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --show-progress -> --runtime-options show-progress */ else if(0 == strcmp(option, PRTE_CLI_SHOW_PROGRESS)) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_RTOS, PRTE_CLI_SHOW_PROGRESS, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --cpu-set and --cpu-list -> --map-by pe-list:X */ else if (0 == strcmp(option, "cpu-set") || 0 == strcmp(option, "cpu-list")) { pmix_asprintf(&p2, "%s%s", PRTE_CLI_PELIST, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --bind-to-core and --bind-to-socket -> --bind-to X */ else if (0 == strcmp(option, "bind-to-core")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, PRTE_CLI_CORE, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "bind-to-socket")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, PRTE_CLI_PACKAGE, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --bynode -> "--map-by X --rank-by X" */ else if (0 == strcmp(option, "bynode")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, PRTE_CLI_NODE, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --bycore -> "--map-by X --rank-by X" */ else if (0 == strcmp(option, "bycore")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, PRTE_CLI_CORE, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --byslot -> "--map-by X --rank-by X" */ else if (0 == strcmp(option, "byslot")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, PRTE_CLI_SLOT, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --cpus-per-proc/rank X -> --map-by :pe=X */ else if (0 == strcmp(option, "cpus-per-proc") || 0 == strcmp(option, "cpus-per-rank")) { pmix_asprintf(&p2, "%s%s", PRTE_CLI_PE, opt->values[0]); rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* -N -> map-by ppr:N:node */ else if (0 == strcmp(option, "N")) { pmix_asprintf(&p2, "ppr:%s:node", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --npernode X and --npersocket X -> --map-by ppr:X:node/socket */ else if (0 == strcmp(option, "npernode")) { pmix_asprintf(&p2, "ppr:%s:node", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "pernode")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, "ppr:1:node", warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "npersocket")) { pmix_asprintf(&p2, "ppr:%s:package", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --ppr X -> --map-by ppr:X */ else if (0 == strcmp(option, "ppr")) { /* if they didn't specify a complete pattern, then this is an error */ if (NULL == strchr(opt->values[0], ':')) { pmix_show_help("help-schizo-base.txt", "bad-ppr", true, opt->values[0], true); return PRTE_ERR_SILENT; } pmix_asprintf(&p2, "ppr:%s", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --am[ca] X -> --tune X */ else if (0 == strcmp(option, "amca") || 0 == strcmp(option, "am")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_TUNE, opt->values[0], warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --rankfile X -> map-by rankfile:file=X */ else if (0 == strcmp(option, "rankfile")) { pmix_asprintf(&p2, "%s:%s%s", PRTE_CLI_RANKFILE, PRTE_CLI_QFILE, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --tag-output -> "--output tag */ else if (0 == strcmp(option, "tag-output")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_TAG, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --timestamp-output -> --output timestamp */ else if (0 == strcmp(option, "timestamp-output")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_TIMESTAMP, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-directory DIR -> --output dir=DIR */ else if (0 == strcmp(option, "output-directory")) { pmix_asprintf(&p2, "%s%s", PRTE_CLI_QDIR, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-filename DIR -> --output file=file */ else if (0 == strcmp(option, "output-filename")) { pmix_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* merge-stderr-to-stdout -> --output merge-stderr-to-stdout */ else if (0 == strcmp(option, "merge-stderr-to-stdout")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_MERGE_ERROUT, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --xml -> --output xml */ else if (0 == strcmp(option, "xml")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_XML, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-devel-map -> --display allocation-devel */ else if (0 == strcmp(option, "display-devel-map")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-proctable -> --runtime-options output-proctable */ else if (0 == strcmp(option, PRTE_CLI_OUTPUT_PROCTABLE)) { if (NULL != opt->values && NULL != opt->values[0]) { pmix_asprintf(&p2, "%s=%s", PRTE_CLI_OUTPUT_PROCTABLE, opt->values[0]); } else { p2 = strdup(PRTE_CLI_OUTPUT_PROCTABLE); } rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_RTOS, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-map -> --display map */ else if (0 == strcmp(option, "display-map")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_MAP, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-topo -> --display topo */ else if (0 == strcmp(option, "display-topo")) { pmix_asprintf(&p2, "%s=%s", "topo", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, p2, warn); free(p2); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --report-bindings -> --display bind */ else if (0 == strcmp(option, "report-bindings")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_BIND, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-allocation -> --display allocation */ else if (0 == strcmp(option, "display-allocation")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_ALLOC, warn); PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --debug will be deprecated starting with open mpi v5 */ else if (0 == strcmp(option, "debug")) { if (warn) { pmix_show_help("help-schizo-base.txt", "deprecated-inform", true, option, "This CLI option will be deprecated starting in Open MPI v5"); } PMIX_CLI_REMOVE_DEPRECATED(results, opt); } /* --map-by socket -> --map-by package */ else if (0 == strcmp(option, PRTE_CLI_MAPBY)) { /* check the value of the option for "socket" */ if (0 == strncasecmp(opt->values[0], "socket", strlen("socket"))) { p1 = strdup(opt->values[0]); // save the original option /* replace "socket" with "package" */ if (NULL == (p2 = strchr(opt->values[0], ':'))) { /* no modifiers */ tmp = strdup(PRTE_CLI_PACKAGE); } else { *p2 = '\0'; ++p2; pmix_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); } if (warn) { pmix_asprintf(&p2, "%s %s", option, p1); pmix_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ output = pmix_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, tmp2); fprintf(stderr, "%s\n", output); free(output); free(tmp2); free(p2); } free(p1); free(opt->values[0]); opt->values[0] = tmp; } } /* --rank-by socket -> --rank-by package */ else if (0 == strcmp(option, PRTE_CLI_RANKBY)) { /* check the value of the option for "socket" */ if (0 == strncasecmp(opt->values[0], "socket", strlen("socket"))) { p1 = strdup(opt->values[0]); // save the original option /* replace "socket" with "package" */ if (NULL == (p2 = strchr(opt->values[0], ':'))) { /* no modifiers */ tmp = strdup("package"); } else { *p2 = '\0'; ++p2; pmix_asprintf(&tmp, "package:%s", p2); } if (warn) { pmix_asprintf(&p2, "%s %s", option, p1); pmix_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ output = pmix_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, tmp2); fprintf(stderr, "%s\n", output); free(output); free(tmp2); free(p2); } free(p1); free(opt->values[0]); opt->values[0] = tmp; } } /* --bind-to socket -> --bind-to package */ else if (0 == strcmp(option, PRTE_CLI_BINDTO)) { /* check the value of the option for "socket" */ if (0 == strncasecmp(opt->values[0], "socket", strlen("socket"))) { p1 = strdup(opt->values[0]); // save the original option /* replace "socket" with "package" */ if (NULL == (p2 = strchr(opt->values[0], ':'))) { /* no modifiers */ tmp = strdup(PRTE_CLI_PACKAGE); } else { *p2 = '\0'; ++p2; pmix_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); } if (warn) { pmix_asprintf(&p2, "%s %s", option, p1); pmix_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ output = pmix_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, tmp2); fprintf(stderr, "%s\n", output); free(output); free(tmp2); free(p2); } free(p1); free(opt->values[0]); opt->values[0] = tmp; } } else if (0 == strcmp(option, "with-ft")) { p1 = opt->values[0]; if (0 != strcmp("no", p1) && 0 != strcmp("false", p1) && 0 != strcmp("0", p1)) { if (0 == strcmp("yes", p1) || 0 == strcmp("true", p1) || 0 == strcmp("1", p1) || 0 == strcmp("ulfm", p1) || 0 == strcmp("mpi", p1)) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_RTOS, PRTE_CLI_RECOVERABLE, warn); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_RTOS, PRTE_CLI_NOTIFY_ERRORS, warn); tmp = strdup("mpi_ft_enable=1"); pmix_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:ompi:parse_cli pushing OMPI_MCA_mpi_ft_enable into environment", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); prte_schizo_base_expose(tmp, "OMPI_MCA_"); free(tmp); } else { pmix_show_help("help-schizo-ompi.txt", "with-ft-bad-option", true, p1); return PRTE_ERR_SILENT; } } PMIX_CLI_REMOVE_DEPRECATED(results, opt); } } return rc; } static int check_cache_noadd(char ***c1, char ***c2, char *p1, char *p2) { char **cache; char **cachevals; int k; if (NULL == c1 || NULL == c2) { return PRTE_SUCCESS; } cache = *c1; cachevals = *c2; if (NULL != cache) { /* see if we already have these */ for (k = 0; NULL != cache[k]; k++) { if (0 == strcmp(cache[k], p1)) { /* we do have it - check for same value */ if (0 != strcmp(cachevals[k], p2)) { /* this is an error */ pmix_show_help("help-schizo-base.txt", "duplicate-mca-value", true, p1, p2, cachevals[k]); return PRTE_ERR_BAD_PARAM; } } } } return PRTE_SUCCESS; } static int check_cache(char ***c1, char ***c2, char *p1, char *p2) { int rc; rc = check_cache_noadd(c1, c2, p1, p2); if (PRTE_SUCCESS == rc) { /* add them to the cache */ PMIX_ARGV_APPEND_NOSIZE_COMPAT(c1, p1); PMIX_ARGV_APPEND_NOSIZE_COMPAT(c2, p2); } return rc; } static int process_envar(const char *p, char ***cache, char ***cachevals) { char *value, **tmp; char *p1, *p2; size_t len; int k, rc = PRTE_SUCCESS; bool found; p1 = strdup(p); if (NULL != (value = strchr(p1, '='))) { /* terminate the name of the param */ *value = '\0'; /* step over the equals */ value++; rc = check_cache(cache, cachevals, p1, value); } else { /* check for a '*' wildcard at the end of the value */ if ('*' == p1[strlen(p1) - 1]) { /* search the local environment for all params * that start with the string up to the '*' */ p1[strlen(p1) - 1] = '\0'; len = strlen(p1); for (k = 0; NULL != environ[k]; k++) { if (0 == strncmp(environ[k], p1, len)) { value = strdup(environ[k]); /* find the '=' sign */ p2 = strchr(value, '='); if (NULL == p2) { free(p1); free(value); return PRTE_ERR_BAD_PARAM; } *p2 = '\0'; ++p2; rc = check_cache(cache, cachevals, value, p2); free(value); } } } else { value = getenv(p1); if (NULL != value) { rc = check_cache(cache, cachevals, p1, value); } else { found = false; if (NULL != cache) { /* see if it is already in the cache */ tmp = *cache; for (k = 0; NULL != tmp[k]; k++) { if (0 == strncmp(p1, tmp[k], strlen(p1))) { found = true; break; } } } if (!found) { pmix_show_help("help-schizo-base.txt", "env-not-found", true, p1); rc = PRTE_ERR_NOT_FOUND; } } } } free(p1); return rc; } /* process params from an env_list - add them to the cache */ static int process_token(char *token, char ***cache, char ***cachevals) { char *ptr, *value; int rc; if (NULL == (ptr = strchr(token, '='))) { value = getenv(token); if (NULL == value) { return PRTE_ERR_NOT_FOUND; } /* duplicate the value to silence tainted string coverity issue */ value = strdup(value); if (NULL == value) { /* out of memory */ return PRTE_ERR_OUT_OF_RESOURCE; } if (NULL != (ptr = strchr(value, '='))) { *ptr = '\0'; rc = check_cache(cache, cachevals, value, ptr + 1); } else { rc = check_cache(cache, cachevals, token, value); } free(value); } else { *ptr = '\0'; rc = check_cache(cache, cachevals, token, ptr + 1); /* NTH: don't bother resetting ptr to = since the string will not be used again */ } return rc; } static int process_env_list(const char *env_list, char ***xparams, char ***xvals, char sep) { char **tokens; int rc = PRTE_SUCCESS; tokens = PMIX_ARGV_SPLIT_COMPAT(env_list, (int) sep); if (NULL == tokens) { return PRTE_SUCCESS; } for (int i = 0; NULL != tokens[i]; ++i) { rc = process_token(tokens[i], xparams, xvals); if (PRTE_SUCCESS != rc) { if (PRTE_ERR_NOT_FOUND == rc) { pmix_show_help("help-schizo-base.txt", "incorrect-env-list-param", true, tokens[i], env_list); } break; } } PMIX_ARGV_FREE_COMPAT(tokens); return rc; } static int process_tune_files(char *filename, char ***dstenv, char sep) { FILE *fp; char **tmp, **opts, *line, *param, *p1, *p2; int i, n, rc = PRTE_SUCCESS; char **cache = NULL, **cachevals = NULL; char **xparams = NULL, **xvals = NULL; tmp = PMIX_ARGV_SPLIT_COMPAT(filename, sep); if (NULL == tmp) { return PRTE_SUCCESS; } /* Iterate through all the files passed in -- it is an ERROR if * a given param appears more than once with different values */ for (i = 0; NULL != tmp[i]; i++) { fp = fopen(tmp[i], "r"); if (NULL == fp) { /* if the file given wasn't absolute, check in the default location */ if (!pmix_path_is_absolute(tmp[i])) { p1 = pmix_os_path(false, DEFAULT_PARAM_FILE_PATH, tmp[i], NULL); fp = fopen(p1, "r"); if (NULL == fp) { pmix_show_help("help-schizo-base.txt", "missing-param-file-def", true, tmp[i], p1);; PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); free(p1); return PRTE_ERR_NOT_FOUND; } free(p1); } else { pmix_show_help("help-schizo-base.txt", "missing-param-file", true, tmp[i]);; PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); return PRTE_ERR_NOT_FOUND; } } while (NULL != (line = prte_schizo_base_getline(fp))) { if ('\0' == line[0]) { continue; /* skip empty lines */ } opts = PMIX_ARGV_SPLIT_WITH_EMPTY_COMPAT(line, ' '); if (NULL == opts) { pmix_show_help("help-schizo-base.txt", "bad-param-line", true, tmp[i], line); free(line); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); fclose(fp); return PRTE_ERR_BAD_PARAM; } for (n = 0; NULL != opts[n]; n++) { if ('\0' == opts[n][0] || '#' == opts[n][0]) { /* the line is only spaces, or a comment, ignore */ break; } if (0 == strcmp(opts[n], "-x")) { /* the next value must be the envar */ if (NULL == opts[n + 1]) { pmix_show_help("help-schizo-base.txt", "bad-param-line", true, tmp[i], line); free(line); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); fclose(fp); return PRTE_ERR_BAD_PARAM; } p1 = prte_schizo_base_strip_quotes(opts[n + 1]); /* some idiot decided to allow spaces around an "=" sign, which is * a violation of the Posix cmd line syntax. Rather than fighting * the battle to correct their error, try to accommodate it here */ if (NULL != opts[n + 2] && 0 == strcmp(opts[n + 2], "=")) { if (NULL == opts[n + 3]) { pmix_show_help("help-schizo-base.txt", "bad-param-line", true, tmp[i], line); free(line); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); fclose(fp); return PRTE_ERR_BAD_PARAM; } p2 = prte_schizo_base_strip_quotes(opts[n + 3]); pmix_asprintf(¶m, "%s=%s", p1, p2); free(p1); free(p2); p1 = param; ++n; // need an extra step } rc = process_envar(p1, &xparams, &xvals); free(p1); if (PRTE_SUCCESS != rc) { fclose(fp); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); free(line); return rc; } ++n; // skip over the envar option } else if (0 == strcmp(opts[n], "--mca")) { if (NULL == opts[n + 1] || NULL == opts[n + 2]) { pmix_show_help("help-schizo-base.txt", "bad-param-line", true, tmp[i], line); free(line); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); fclose(fp); return PRTE_ERR_BAD_PARAM; } p1 = prte_schizo_base_strip_quotes(opts[n + 1]); p2 = prte_schizo_base_strip_quotes(opts[n + 2]); if (0 == strcmp(p1, "mca_base_env_list")) { /* next option must be the list of envars */ rc = process_env_list(p2, &xparams, &xvals, ';'); } else { /* treat it as an arbitrary MCA param */ rc = check_cache(&cache, &cachevals, p1, p2); } free(p1); free(p2); if (PRTE_SUCCESS != rc) { fclose(fp); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); free(line); return rc; } n += 2; // skip over the MCA option } else if (0 == strncmp(opts[n], "mca_base_env_list", strlen("mca_base_env_list"))) { /* find the equal sign */ p1 = strchr(opts[n], '='); if (NULL == p1) { pmix_show_help("help-schizo-base.txt", "bad-param-line", true, tmp[i], line); free(line); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); fclose(fp); return PRTE_ERR_BAD_PARAM; } ++p1; rc = process_env_list(p1, &xparams, &xvals, ';'); if (PRTE_SUCCESS != rc) { fclose(fp); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); free(line); return rc; } } else { rc = process_token(opts[n], &cache, &cachevals); if (PRTE_SUCCESS != rc) { pmix_show_help("help-schizo-base.txt", "bad-param-line", true, tmp[i], line); fclose(fp); PMIX_ARGV_FREE_COMPAT(tmp); PMIX_ARGV_FREE_COMPAT(opts); PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); free(line); return rc; } } } free(line); } fclose(fp); } PMIX_ARGV_FREE_COMPAT(tmp); if (NULL != cache) { /* add the results into dstenv */ for (i = 0; NULL != cache[i]; i++) { if (0 != strncmp(cache[i], "OMPI_MCA_", strlen("OMPI_MCA_"))) { pmix_asprintf(&p1, "OMPI_MCA_%s", cache[i]); PMIX_SETENV_COMPAT(p1, cachevals[i], true, dstenv); free(p1); } else { PMIX_SETENV_COMPAT(cache[i], cachevals[i], true, dstenv); } } PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); } /* add the -x values */ if (NULL != xparams) { for (i = 0; NULL != xparams[i]; i++) { PMIX_SETENV_COMPAT(xparams[i], xvals[i], true, dstenv); } PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); } return PRTE_SUCCESS; } // These frameworks are current as of 16 Sep, 2022, and are the list // of frameworks that are planned to be in Open MPI v5.0.0. static char *ompi_frameworks_static_5_0_0[] = { // Generic prefixes used by OMPI "mca", "opal", "ompi", /* OPAL frameworks */ "allocator", "backtrace", "btl", "dl", "hwloc", "if", "installdirs", "memchecker", "memcpy", "memory", "mpool", "patcher", "pmix", "rcache", "reachable", "shmem", "smsc", "threads", "timer", /* OMPI frameworks */ "mpi", /* global options set in runtime/ompi_mpi_params.c */ "bml", "coll", "fbtl", "fcoll", "fs", "hook", "io", "mtl", "op", "osc", "part", "pml", "sharedfp", "topo", "vprotocol", /* OSHMEM frameworks */ "memheap", "scoll", "spml", "sshmem", NULL, }; static char **ompi_frameworks = ompi_frameworks_static_5_0_0; static bool ompi_frameworks_setup = false; static void setup_ompi_frameworks(void) { if (ompi_frameworks_setup) { return; } ompi_frameworks_setup = true; char *env = getenv("OMPI_MCA_PREFIXES"); if (NULL == env) { return; } // If we found the env variable, it will be a comma-delimited list // of values. Split it into an argv-style array. char **tmp = PMIX_ARGV_SPLIT_COMPAT(env, ','); if (NULL != tmp) { ompi_frameworks = tmp; } } static bool check_generic(char *p1) { setup_ompi_frameworks(); /* See if the parameter we were passed belongs to one of the OMPI frameworks or prefixes */ for (int j = 0; NULL != ompi_frameworks[j]; j++) { if (0 == strncmp(p1, ompi_frameworks[j], strlen(ompi_frameworks[j]))) { return true; } } return false; } static int parse_env(char **srcenv, char ***dstenv, pmix_cli_result_t *results) { char *p1, *p2, *p3; char *env_set_flag; char **cache = NULL, **cachevals = NULL; char **xparams = NULL, **xvals = NULL; char **envlist = NULL, **envtgt = NULL; pmix_cli_item_t *opt; int i, j, rc; PRTE_HIDE_UNUSED_PARAMS(srcenv); pmix_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:ompi: parse_env", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); /* protect against bozo input */ if (NULL == results) { return PRTE_SUCCESS; } /* Begin by examining the environment as the cmd line trumps all */ env_set_flag = getenv("OMPI_MCA_mca_base_env_list"); if (NULL != env_set_flag) { rc = process_env_list(env_set_flag, &xparams, &xvals, ';'); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); return rc; } } /* process the resulting cache into the dstenv */ if (NULL != xparams) { for (i = 0; NULL != xparams[i]; i++) { PMIX_SETENV_COMPAT(xparams[i], xvals[i], true, dstenv); } PMIX_ARGV_FREE_COMPAT(xparams); xparams = NULL; PMIX_ARGV_FREE_COMPAT(xvals); xvals = NULL; } /* now process any tune file specification - the tune file processor * will police itself for duplicate values */ if (NULL != (opt = pmix_cmd_line_get_param(results, "tune"))) { p1 = PMIX_ARGV_JOIN_COMPAT(opt->values, ','); rc = process_tune_files(p1, dstenv, ','); free(p1); if (PRTE_SUCCESS != rc) { return rc; } } if (NULL != (opt = pmix_cmd_line_get_param(results, "initial-errhandler"))) { rc = check_cache(&cache, &cachevals, "mpi_initial_errhandler", opt->values[0]); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); return rc; } } if (NULL != (opt = pmix_cmd_line_get_param(results, "memory-alloc-kinds"))) { rc = check_cache(&cache, &cachevals, "mpi_memory_alloc_kinds", opt->values[0]); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); return rc; } } if (pmix_cmd_line_is_taken(results, "display-comm") && pmix_cmd_line_is_taken(results, "display-comm-finalize")) { PMIX_SETENV_COMPAT("OMPI_MCA_ompi_display_comm", "mpi_init,mpi_finalize", true, dstenv); } else if (pmix_cmd_line_is_taken(results, "display-comm")) { PMIX_SETENV_COMPAT("OMPI_MCA_ompi_display_comm", "mpi_init", true, dstenv); } else if (pmix_cmd_line_is_taken(results, "display-comm-finalize")) { PMIX_SETENV_COMPAT("OMPI_MCA_ompi_display_comm", "mpi_finalize", true, dstenv); } /* --stream-buffering will be deprecated starting with Open MPI v5 */ if (NULL != (opt = pmix_cmd_line_get_param(results, "stream-buffering"))) { uint16_t u16; if (prte_mca_schizo_ompi_component.warn_deprecations) { pmix_show_help("help-schizo-base.txt", "deprecated-inform", true, "stream-buffering", "This CLI option will be deprecated starting in Open MPI v5. " "If you need this functionality use the Open MPI MCA option: ompi_stream_buffering"); } u16 = strtol(opt->values[0], NULL, 10); if (0 != u16 && 1 != u16 && 2 != u16) { /* bad value */ pmix_show_help("help-schizo-base.txt", "bad-stream-buffering-value", true, u16); } PMIX_SETENV_COMPAT("OMPI_MCA_ompi_stream_buffering", opt->values[0], true, dstenv); } /* now look for any "--mca" options - note that it is an error * for the same MCA param to be given more than once if the * values differ */ if (NULL != (opt = pmix_cmd_line_get_param(results, "omca"))) { for (i = 0; NULL != opt->values[i]; ++i) { /* the value is provided in "param=value" format, so * we need to split it here - it is okay to change * the value as we won't be using it again */ p3 = strchr(opt->values[i], '='); *p3 = '\0'; ++p3; p1 = opt->values[i]; /* treat mca_base_env_list as a special case */ if (0 == strcmp(p1, "mca_base_env_list")) { PMIX_ARGV_APPEND_NOSIZE_COMPAT(&envlist, p3); continue; } rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); return rc; } } } if (NULL != (opt = pmix_cmd_line_get_param(results, "gomca"))) { for (i = 0; NULL != opt->values[i]; ++i) { /* the value is provided in "param=value" format, so * we need to split it here - it is okay to change * the value as we won't be using it again */ p3 = strchr(opt->values[i], '='); *p3 = '\0'; ++p3; p1 = opt->values[i]; /* treat mca_base_env_list as a special case */ if (0 == strcmp(p1, "mca_base_env_list")) { PMIX_ARGV_APPEND_NOSIZE_COMPAT(&envlist, p3); continue; } rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); return rc; } } } if (NULL != (opt = pmix_cmd_line_get_param(results, "mca"))) { for (i = 0; NULL != opt->values[i]; ++i) { /* the value is provided in "param=value" format, so * we need to split it here - it is okay to change * the value as we won't be using it again */ p3 = strchr(opt->values[i], '='); *p3 = '\0'; ++p3; p1 = opt->values[i]; /* check if this is one of ours */ if (check_generic(p1)) { /* treat mca_base_env_list as a special case */ if (0 == strcmp(p1, "mca_base_env_list")) { PMIX_ARGV_APPEND_NOSIZE_COMPAT(&envlist, p3); continue; } rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(envlist); return rc; } } } } if (NULL != (opt = pmix_cmd_line_get_param(results, "gmca"))) { for (i = 0; NULL != opt->values[i]; ++i) { /* the value is provided in "param=value" format, so * we need to split it here - it is okay to change * the value as we won't be using it again */ p3 = strchr(opt->values[i], '='); *p3 = '\0'; ++p3; p1 = opt->values[i]; /* check if this is one of ours */ if (check_generic(p1)) { /* treat mca_base_env_list as a special case */ if (0 == strcmp(p1, "mca_base_env_list")) { PMIX_ARGV_APPEND_NOSIZE_COMPAT(&envlist, p3); continue; } rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(envlist); return rc; } } } } /* if we got any env lists, process them here */ if (NULL != envlist) { for (i = 0; NULL != envlist[i]; i++) { envtgt = PMIX_ARGV_SPLIT_COMPAT(envlist[i], ';'); for (j = 0; NULL != envtgt[j]; j++) { if (NULL == (p2 = strchr(envtgt[j], '='))) { p1 = getenv(envtgt[j]); if (NULL == p1) { continue; } p1 = strdup(p1); if (NULL != (p2 = strchr(p1, '='))) { *p2 = '\0'; rc = check_cache(&xparams, &xvals, p1, p2 + 1); } else { rc = check_cache(&xparams, &xvals, envtgt[j], p1); } free(p1); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(envtgt); PMIX_ARGV_FREE_COMPAT(envlist); return rc; } } else { *p2 = '\0'; rc = check_cache(&xparams, &xvals, envtgt[j], p2 + 1); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(envtgt); PMIX_ARGV_FREE_COMPAT(envlist); return rc; } } } PMIX_ARGV_FREE_COMPAT(envtgt); } } PMIX_ARGV_FREE_COMPAT(envlist); /* now look for -x options - not allowed to conflict with a -mca option */ if (NULL != (opt = pmix_cmd_line_get_param(results, "x"))) { for (i = 0; NULL != opt->values[i]; ++i) { /* the value is the envar */ p1 = opt->values[i]; /* if there is an '=' in it, then they are setting a value */ if (NULL != (p2 = strchr(p1, '='))) { *p2 = '\0'; ++p2; } else { p2 = getenv(p1); if (NULL == p2) { continue; } } /* not allowed to duplicate anything from an MCA param on the cmd line */ rc = check_cache_noadd(&cache, &cachevals, p1, p2); if (PRTE_SUCCESS != rc) { PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); return rc; } /* cache this for later inclusion */ PMIX_ARGV_APPEND_NOSIZE_COMPAT(&xparams, p1); PMIX_ARGV_APPEND_NOSIZE_COMPAT(&xvals, p2); } } /* process the resulting cache into the dstenv */ if (NULL != cache) { for (i = 0; NULL != cache[i]; i++) { if (0 != strncmp(cache[i], "OMPI_MCA_", strlen("OMPI_MCA_"))) { pmix_asprintf(&p1, "OMPI_MCA_%s", cache[i]); PMIX_SETENV_COMPAT(p1, cachevals[i], true, dstenv); free(p1); } else { PMIX_SETENV_COMPAT(cache[i], cachevals[i], true, dstenv); } } } PMIX_ARGV_FREE_COMPAT(cache); PMIX_ARGV_FREE_COMPAT(cachevals); /* add the -x values */ if (NULL != xparams) { for (i = 0; NULL != xparams[i]; i++) { PMIX_SETENV_COMPAT(xparams[i], xvals[i], true, dstenv); } PMIX_ARGV_FREE_COMPAT(xparams); PMIX_ARGV_FREE_COMPAT(xvals); } #if PMIX_NUMERIC_VERSION != 0x00040208 /* add a flag indicating that we did indeed check the tmpdir * for a shared file system */ if (prte_process_info.shared_fs) { p1 = "TRUE"; } else { p1 = "FALSE"; } PMIX_SETENV_COMPAT("PRTE_SHARED_FS", p1, true, dstenv); #endif return PRTE_SUCCESS; } static bool check_prte_overlap(char *var, char *value) { char *tmp; if (0 == strncmp(var, "dl_", 3)) { pmix_asprintf(&tmp, "PRTE_MCA_prtedl_%s", &var[3]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "oob_", 4)) { pmix_asprintf(&tmp, "PRTE_MCA_%s", var); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "hwloc_", 6)) { pmix_asprintf(&tmp, "PRTE_MCA_%s", var); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "if_", 3)) { // need to convert if to prteif pmix_asprintf(&tmp, "PRTE_MCA_prteif_%s", &var[3]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "reachable_", strlen("reachable_"))) { // need to convert reachable to prtereachable pmix_asprintf(&tmp, "PRTE_MCA_prtereachable_%s", &var[strlen("reachable_")]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "plm_rsh_", strlen("plm_rsh_"))) { // need to convert rsh to ssh pmix_asprintf(&tmp, "PRTE_MCA_plm_ssh_%s", &var[strlen("plm_rsh_")]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "orte_", strlen("orte_"))) { // need to convert "orte" to "prte" pmix_asprintf(&tmp, "PRTE_MCA_prte_%s", &var[strlen("orte_")]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } return false; } static bool check_pmix_overlap(char *var, char *value) { char *tmp; if (0 == strncmp(var, "dl_", 3)) { pmix_asprintf(&tmp, "PMIX_MCA_pdl_%s", &var[3]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "oob_", 4)) { pmix_asprintf(&tmp, "PMIX_MCA_ptl_%s", &var[4]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "hwloc_", 6)) { pmix_asprintf(&tmp, "PMIX_MCA_%s", var); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } else if (0 == strncmp(var, "if_", 3)) { // need to convert if to pif pmix_asprintf(&tmp, "PMIX_MCA_pif_%s", &var[3]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, value, false); free(tmp); return true; } return false; } // NOTE: This code is fundamentally the same (module PMIX <-> OPAL) // as the translate_params() routine in the OMPI repo's // opal/mca/pmix/base/pmix_base_fns.c file. If there are // changes here, there are likely to be changes there. static int translate_params(void) { char *evar, *tmp, *e2; char *file; const char *home; pmix_list_t params; pmix_mca_base_var_file_value_t *fv; uid_t uid; int n, len; /* since we are the proxy, we need to check the OMPI default * MCA params to see if there is something relating to PRRTE * in them - this would be "old" references to things from * ORTE, as well as a few OPAL references that also impact us * * NOTE: we do this in the following precedence order. Note * that we do not overwrite at any step - this is so that we * don't overwrite something previously set by the user. So * the order to execution is the opposite of the intended * precedence order. * * 1. check the environmental paramaters for OMPI_MCA values * that need to be translated * * 2. the user's home directory file as it should * overwrite the system default file, but not the * envars * * 3. the system default parameter file */ len = strlen("OMPI_MCA_"); for (n=0; NULL != environ[n]; n++) { if (0 == strncmp(environ[n], "OMPI_MCA_", len)) { e2 = strdup(environ[n]); evar = strrchr(e2, '='); *evar = '\0'; ++evar; if (check_prte_overlap(&e2[len], evar)) { // check for pmix overlap check_pmix_overlap(&e2[len], evar); } else if (prte_schizo_base_check_prte_param(&e2[len])) { pmix_asprintf(&tmp, "PRTE_MCA_%s", &e2[len]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, evar, false); free(tmp); // check for pmix overlap check_pmix_overlap(&e2[len], evar); } else if (prte_schizo_base_check_pmix_param(&e2[len])) { pmix_asprintf(&tmp, "PMIX_MCA_%s", &e2[len]); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, evar, false); free(tmp); } free(e2); } } /* see if the user has a default MCA param file */ uid = geteuid(); /* try to get their home directory */ home = pmix_home_directory(uid); if (NULL != home) { file = pmix_os_path(false, home, ".openmpi", "mca-params.conf", NULL); PMIX_CONSTRUCT(¶ms, pmix_list_t); pmix_mca_base_parse_paramfile(file, ¶ms); free(file); PMIX_LIST_FOREACH (fv, ¶ms, pmix_mca_base_var_file_value_t) { // see if this param relates to PRRTE if (check_prte_overlap(fv->mbvfv_var, fv->mbvfv_value)) { check_pmix_overlap(fv->mbvfv_var, fv->mbvfv_value); } else if (prte_schizo_base_check_prte_param(fv->mbvfv_var)) { pmix_asprintf(&tmp, "PRTE_MCA_%s", fv->mbvfv_var); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, fv->mbvfv_value, false); free(tmp); // if this relates to the DL, OOB, HWLOC, IF, or // REACHABLE frameworks, then we also need to set // the equivalent PMIx value check_pmix_overlap(fv->mbvfv_var, fv->mbvfv_value); } else if (prte_schizo_base_check_pmix_param(fv->mbvfv_var)) { pmix_asprintf(&tmp, "PMIX_MCA_%s", fv->mbvfv_var); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, fv->mbvfv_value, false); free(tmp); } } PMIX_LIST_DESTRUCT(¶ms); } /* check if the user has set OMPIHOME in their environment */ if (NULL != (evar = getenv("OMPIHOME"))) { /* look for the default MCA param file */ file = pmix_os_path(false, evar, "etc", "openmpi-mca-params.conf", NULL); PMIX_CONSTRUCT(¶ms, pmix_list_t); pmix_mca_base_parse_paramfile(file, ¶ms); free(file); PMIX_LIST_FOREACH (fv, ¶ms, pmix_mca_base_var_file_value_t) { // see if this param relates to PRRTE if (check_prte_overlap(fv->mbvfv_var, fv->mbvfv_value)) { check_pmix_overlap(fv->mbvfv_var, fv->mbvfv_value); } else if (prte_schizo_base_check_prte_param(fv->mbvfv_var)) { pmix_asprintf(&tmp, "PRTE_MCA_%s", fv->mbvfv_var); // set it, but don't overwrite if they already // have a value in our environment setenv(tmp, fv->mbvfv_value, false); free(tmp); // if this relates to the DL, OOB, HWLOC, IF, or // REACHABLE frameworks, then we also need to set // the equivalent PMIx value check_pmix_overlap(fv->mbvfv_var, fv->mbvfv_value); } } PMIX_LIST_DESTRUCT(¶ms); } return 100; } static int detect_proxy(char *personalities) { char *evar; pmix_output_verbose(2, prte_schizo_base_framework.framework_output, "%s[%s]: detect proxy with %s (%s)", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), __FILE__, (NULL == personalities) ? "NULL" : personalities, prte_tool_basename); /* COMMAND-LINE OVERRIDES ALL */ if (NULL != personalities) { /* this is a list of personalities we need to check - * if it contains "ompi", then we are available */ if (NULL != strstr(personalities, "ompi")) { return translate_params(); } return 0; } /* if we were told the proxy, then use it */ if (NULL != (evar = getenv("PRTE_MCA_schizo_proxy"))) { if (0 == strcmp(evar, "ompi")) { return translate_params(); } else { return 0; } } /* if neither of those were true, then it cannot be us */ return 0; } static void allow_run_as_root(pmix_cli_result_t *results) { /* we always run last */ char *r1, *r2; if (pmix_cmd_line_is_taken(results, "allow-run-as-root")) { prte_allow_run_as_root = true; return; } if (NULL != (r1 = getenv("OMPI_ALLOW_RUN_AS_ROOT")) && NULL != (r2 = getenv("OMPI_ALLOW_RUN_AS_ROOT_CONFIRM"))) { if (0 == strcmp(r1, "1") && 0 == strcmp(r2, "1")) { prte_allow_run_as_root = true; return; } } prte_schizo_base_root_error_msg(); } static int set_default_ranking(prte_job_t *jdata, prte_rmaps_options_t *options) { int rc; prte_mapping_policy_t map; /* use the base system and then we will correct it */ rc = prte_rmaps_base_set_default_ranking(jdata, options); if (PRTE_SUCCESS != rc) { // it will have output the error message return rc; } // correct how we handle PPR if (PRTE_MAPPING_GIVEN & PRTE_GET_MAPPING_DIRECTIVE(jdata->map->mapping)) { map = PRTE_GET_MAPPING_POLICY(jdata->map->mapping); // set for dense packing - but don't override any user setting if (PRTE_MAPPING_PPR == map && !PRTE_RANKING_POLICY_IS_SET(jdata->map->ranking)) { PRTE_SET_RANKING_POLICY(jdata->map->ranking, PRTE_RANK_BY_SLOT); } } return PRTE_SUCCESS; } static void job_info(pmix_cli_result_t *results, void *jobinfo) { PRTE_HIDE_UNUSED_PARAMS(results, jobinfo); return; } static int set_default_rto(prte_job_t *jdata, prte_rmaps_options_t *options) { PRTE_HIDE_UNUSED_PARAMS(options); return prte_state_base_set_runtime_options(jdata, NULL); }