From 138abd5ab0656eedb6475696bc684346a798929d Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Tue, 19 Oct 2021 08:55:34 -0700 Subject: [PATCH 1/7] Redesign the command line system to provide isolation As the number of organizations using PRRTE grows, we are beginning to see conflicts surrounding the command line interface. This is the primary interaction point to the user, so it is natural that organizations want to customize it - i.e., to "rebrand" PRRTE to match their needs. The original code utilized a custom command line parser that was rigidly tied to the needs of OpenMPI. Modifying this to create the desired independence would be challenging. Instead, we chose to replace that code with use of the standard "getopt_long" function. This reduced the amount of custom code, though it still requires one to properly deal with the input/output to/from that parser. This represents an initial working prototype of the revised system. Note that it does change the schizo interface. Some minor configuration changes have also crept into this PR and will be separated out prior to commit. Main purpose of this PR is to provide the community an opportunity to look over the changes and provide feedback. Updates to the code will continue. In particular, we need to seperate out the map/rank/bind policy assignments so that the individual organizations can each choose their own defaults. Signed-off-by: Ralph Castain --- src/mca/odls/base/odls_base_default_fns.c | 46 +- src/mca/plm/alps/configure.m4 | 1 + src/mca/plm/lsf/configure.m4 | 1 + src/mca/plm/slurm/configure.m4 | 1 + src/mca/plm/ssh/plm_ssh_module.c | 15 +- src/mca/plm/tm/configure.m4 | 1 + src/mca/ras/base/ras_base_allocate.c | 32 +- src/mca/routed/routed.h | 3 +- src/mca/schizo/base/base.h | 36 +- src/mca/schizo/base/help-schizo-base.txt | 31 +- src/mca/schizo/base/schizo_base_frame.c | 578 +++---- src/mca/schizo/base/schizo_base_stubs.c | 348 ++--- src/mca/schizo/hydra/.prte_ignore | 0 src/mca/schizo/hydra/configure.m4 | 41 + src/mca/schizo/hydra/owner.txt | 7 + src/mca/schizo/ompi/Makefile.am | 5 +- src/mca/schizo/ompi/configure.m4 | 41 + src/mca/schizo/ompi/help-schizo-ompi.txt | 588 ++++++++ src/mca/schizo/ompi/owner.txt | 2 +- src/mca/schizo/ompi/schizo_ompi.c | 1505 +++++++++---------- src/mca/schizo/prte/Makefile.am | 9 + src/mca/schizo/prte/configure.m4 | 35 + src/mca/schizo/prte/help-schizo-pinfo.txt | 71 + src/mca/schizo/prte/help-schizo-prte.txt | 248 +++ src/mca/schizo/prte/help-schizo-prted.txt | 449 ++++++ src/mca/schizo/prte/help-schizo-prterun.txt | 568 +++++++ src/mca/schizo/prte/help-schizo-prun.txt | 363 +++++ src/mca/schizo/prte/help-schizo-pterm.txt | 449 ++++++ src/mca/schizo/prte/owner.txt | 2 +- src/mca/schizo/prte/schizo_prte.c | 1263 ++++++++-------- src/mca/schizo/prte/schizo_prte.h | 4 +- src/mca/schizo/prte/schizo_prte_component.c | 2 +- src/mca/schizo/schizo.h | 68 +- src/prted/Makefile.am | 5 +- src/prted/prte_app_parse.c | 263 +--- src/prted/prted.h | 7 +- src/runtime/prte_finalize.c | 6 +- src/runtime/prte_globals.c | 8 +- src/runtime/prte_globals.h | 11 +- src/tools/prte/Makefile.am | 4 +- src/tools/prte/main.c | 35 - src/{prted => tools/prte}/prte.c | 565 +++---- src/tools/prte_info/help-prte-info.txt | 42 +- src/tools/prte_info/param.c | 171 +-- src/tools/prte_info/pinfo.h | 8 +- src/tools/prte_info/prte_info.c | 157 +- src/tools/prte_info/version.c | 58 +- src/tools/prted/prted.c | 219 ++- src/tools/prun/prun.c | 468 +++--- src/tools/pterm/help-pterm.txt | 20 +- src/tools/pterm/pterm.c | 169 +-- src/util/Makefile.am | 9 +- src/util/argv.c | 122 +- src/util/argv.h | 5 +- src/util/cmd_line.c | 1340 ++++------------- src/util/cmd_line.h | 844 ++++------- src/util/help-cli.txt | 86 ++ src/util/help-prte-util.txt | 103 -- 58 files changed, 6403 insertions(+), 5135 deletions(-) create mode 100644 src/mca/schizo/hydra/.prte_ignore create mode 100644 src/mca/schizo/hydra/configure.m4 create mode 100644 src/mca/schizo/hydra/owner.txt create mode 100644 src/mca/schizo/ompi/configure.m4 create mode 100644 src/mca/schizo/ompi/help-schizo-ompi.txt create mode 100644 src/mca/schizo/prte/configure.m4 create mode 100644 src/mca/schizo/prte/help-schizo-pinfo.txt create mode 100644 src/mca/schizo/prte/help-schizo-prte.txt create mode 100644 src/mca/schizo/prte/help-schizo-prted.txt create mode 100644 src/mca/schizo/prte/help-schizo-prterun.txt create mode 100644 src/mca/schizo/prte/help-schizo-prun.txt create mode 100644 src/mca/schizo/prte/help-schizo-pterm.txt delete mode 100644 src/tools/prte/main.c rename src/{prted => tools/prte}/prte.c (69%) create mode 100644 src/util/help-cli.txt diff --git a/src/mca/odls/base/odls_base_default_fns.c b/src/mca/odls/base/odls_base_default_fns.c index 53a6fd761f..8fbdea4943 100644 --- a/src/mca/odls/base/odls_base_default_fns.c +++ b/src/mca/odls/base/odls_base_default_fns.c @@ -19,7 +19,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2017 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2017-2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -71,7 +71,7 @@ #include "src/mca/rml/rml.h" #include "src/mca/routed/routed.h" #include "src/mca/rtc/rtc.h" -#include "src/mca/schizo/schizo.h" +#include "src/mca/schizo/base/base.h" #include "src/mca/state/state.h" #include "src/prted/pmix/pmix_server.h" @@ -425,6 +425,7 @@ int prte_odls_base_default_construct_child_list(pmix_data_buffer_t *buffer, pmix pmix_byte_object_t bo, pbo; size_t m; pmix_envar_t envt; + char *tmp; PRTE_OUTPUT_VERBOSE((5, prte_odls_base_framework.framework_output, "%s odls:constructing child list", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME))); @@ -581,6 +582,24 @@ int prte_odls_base_default_construct_child_list(pmix_data_buffer_t *buffer, pmix jdata->map = PRTE_NEW(prte_job_map_t); } } + /* get the associated schizo module */ + if (NULL != jdata->personality) { + tmp = prte_argv_join(jdata->personality, ','); + } else { + tmp = NULL; + } + jdata->schizo = (struct prte_schizo_base_module_t*)prte_schizo_base_detect_proxy(tmp); + if (NULL == jdata->schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, + prte_tool_basename, (NULL == tmp) ? "NULL" : tmp); + if (NULL != tmp) { + free(tmp); + } + return 1; + } + if (NULL != tmp) { + free(tmp); + } /* if the job is fully described, then mpirun will have computed * and sent us the complete array of procs in the prte_job_t, so we @@ -952,6 +971,7 @@ void prte_odls_base_spawn_proc(int fd, short sd, void *cbdata) pmix_proc_t pproc; pmix_status_t ret; char *ptr; + PRTE_HIDE_UNUSED_PARAMS(fd, sd); PRTE_ACQUIRE_OBJECT(cd); @@ -967,7 +987,7 @@ void prte_odls_base_spawn_proc(int fd, short sd, void *cbdata) char *tmp = strdup(app->env[i]); ptr = strchr(tmp, '='); if (NULL == ptr) { - PMIX_ERROR_LOG(PRTE_ERR_BAD_PARAM); + PRTE_ERROR_LOG(PRTE_ERR_BAD_PARAM); rc = PRTE_ERR_BAD_PARAM; state = PRTE_PROC_STATE_FAILED_TO_LAUNCH; free(tmp); @@ -1009,15 +1029,6 @@ void prte_odls_base_spawn_proc(int fd, short sd, void *cbdata) child->rml_uri = NULL; } - /* setup the rest of the environment with the proc-specific items - these - * will be overwritten for each child - */ - if (PRTE_SUCCESS != (rc = prte_schizo.setup_child(jobdat, child, app, &cd->env))) { - PRTE_ERROR_LOG(rc); - state = PRTE_PROC_STATE_FAILED_TO_LAUNCH; - goto errorout; - } - /* did the user request we display output in xterms? */ if (NULL != prte_xterm) { prte_list_item_t *nmitem; @@ -1130,6 +1141,8 @@ void prte_odls_base_default_launch_local(int fd, short sd, void *cbdata) char **argvptr; char *pathenv = NULL, *mpiexec_pathenv = NULL; char *full_search; + prte_schizo_base_module_t *schizo; + PRTE_HIDE_UNUSED_PARAMS(fd, sd); PRTE_ACQUIRE_OBJECT(caddy); @@ -1154,6 +1167,7 @@ void prte_odls_base_default_launch_local(int fd, short sd, void *cbdata) * and was removed. This isn't an error so just move along */ goto ERROR_OUT; } + schizo = (prte_schizo_base_module_t*)jobdat->schizo; /* do we have any local procs to launch? */ if (0 == jobdat->num_local_procs) { @@ -1269,7 +1283,7 @@ void prte_odls_base_default_launch_local(int fd, short sd, void *cbdata) } /* setup the environment for this app */ - if (PRTE_SUCCESS != (rc = prte_schizo.setup_fork(jobdat, app))) { + if (PRTE_SUCCESS != (rc = schizo->setup_fork(jobdat, app))) { PRTE_OUTPUT_VERBOSE((10, prte_odls_base_framework.framework_output, "%s odls:launch:setup_fork failed with error %s", @@ -2078,12 +2092,6 @@ int prte_odls_base_default_restart_proc(prte_proc_t *child, } app = (prte_app_context_t *) prte_pointer_array_get_item(jobdat->apps, child->app_idx); - /* reset envars to match this child */ - if (PRTE_SUCCESS != (rc = prte_schizo.setup_child(jobdat, child, app, &app->env))) { - PRTE_ERROR_LOG(rc); - goto CLEANUP; - } - /* setup the path */ if (PRTE_SUCCESS != (rc = setup_path(app, &wdir))) { PRTE_ERROR_LOG(rc); diff --git a/src/mca/plm/alps/configure.m4 b/src/mca/plm/alps/configure.m4 index 565eda55f0..88dc035f8a 100644 --- a/src/mca/plm/alps/configure.m4 +++ b/src/mca/plm/alps/configure.m4 @@ -14,6 +14,7 @@ # Copyright (c) 2011-2016 Los Alamos National Security, LLC. # All rights reserved. # Copyright (c) 2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow diff --git a/src/mca/plm/lsf/configure.m4 b/src/mca/plm/lsf/configure.m4 index aa67654929..d6690f3b06 100644 --- a/src/mca/plm/lsf/configure.m4 +++ b/src/mca/plm/lsf/configure.m4 @@ -14,6 +14,7 @@ # Copyright (c) 2011-2013 Los Alamos National Security, LLC. # All rights reserved. # Copyright (c) 2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow diff --git a/src/mca/plm/slurm/configure.m4 b/src/mca/plm/slurm/configure.m4 index 9f29b47040..11b7f18ea5 100644 --- a/src/mca/plm/slurm/configure.m4 +++ b/src/mca/plm/slurm/configure.m4 @@ -14,6 +14,7 @@ # Copyright (c) 2011-2016 Los Alamos National Security, LLC. # All rights reserved. # Copyright (c) 2017-2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow diff --git a/src/mca/plm/ssh/plm_ssh_module.c b/src/mca/plm/ssh/plm_ssh_module.c index 527032dfbb..7610236cba 100644 --- a/src/mca/plm/ssh/plm_ssh_module.c +++ b/src/mca/plm/ssh/plm_ssh_module.c @@ -17,7 +17,7 @@ * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -93,7 +93,6 @@ #include "src/mca/rml/rml.h" #include "src/mca/rml/rml_types.h" #include "src/mca/routed/routed.h" -#include "src/mca/schizo/schizo.h" #include "src/mca/state/state.h" #include "src/mca/plm/base/base.h" @@ -628,18 +627,6 @@ static int setup_launch(int *argcptr, char ***argvptr, char *nodename, int *node free(param); } - /* unless told otherwise... */ - if (prte_plm_ssh_component.pass_environ_mca_params) { - /* now check our local environment for MCA params - add them - * only if they aren't already present - */ - if (PRTE_SUCCESS != (rc = prte_schizo.parse_env(NULL, environ, &argv, true))) { - prte_argv_free(argv); - return rc; - } - argc = prte_argv_count(argv); - } - /* protect the params */ prte_plm_base_wrap_args(argv); diff --git a/src/mca/plm/tm/configure.m4 b/src/mca/plm/tm/configure.m4 index 85e956ae18..8cb03acb09 100644 --- a/src/mca/plm/tm/configure.m4 +++ b/src/mca/plm/tm/configure.m4 @@ -14,6 +14,7 @@ # All rights reserved. # Copyright (c) 2009-2020 Cisco Systems, Inc. All rights reserved # Copyright (c) 2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow diff --git a/src/mca/ras/base/ras_base_allocate.c b/src/mca/ras/base/ras_base_allocate.c index 71633ea3f2..c9ff04901c 100644 --- a/src/mca/ras/base/ras_base_allocate.c +++ b/src/mca/ras/base/ras_base_allocate.c @@ -15,7 +15,7 @@ * Copyright (c) 2018 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -181,10 +181,10 @@ void prte_ras_base_allocate(int fd, short args, void *cbdata) prte_job_t *jdata; prte_list_t nodes; prte_node_t *node; - int32_t i; + int32_t i, j; prte_app_context_t *app; prte_state_caddy_t *caddy = (prte_state_caddy_t *) cbdata; - char *hosts = NULL; + char *hosts = NULL, **hostlist; char *ptr; pmix_status_t ret; PRTE_HIDE_UNUSED_PARAMS(fd, args); @@ -373,8 +373,7 @@ void prte_ras_base_allocate(int fd, short args, void *cbdata) if (NULL == (app = (prte_app_context_t *) prte_pointer_array_get_item(jdata->apps, i))) { continue; } - if (prte_get_attribute(&app->attributes, PRTE_APP_DASH_HOST, (void **) &hosts, - PMIX_STRING)) { + if (prte_get_attribute(&app->attributes, PRTE_APP_DASH_HOST, (void **) &hosts, PMIX_STRING)) { PRTE_OUTPUT_VERBOSE((5, prte_ras_base_framework.framework_output, "%s ras:base:allocate adding dash_hosts", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME))); @@ -426,22 +425,25 @@ void prte_ras_base_allocate(int fd, short args, void *cbdata) if (NULL == (app = (prte_app_context_t *) prte_pointer_array_get_item(jdata->apps, i))) { continue; } - if (prte_get_attribute(&app->attributes, PRTE_APP_HOSTFILE, (void **) &hosts, - PMIX_STRING)) { + if (prte_get_attribute(&app->attributes, PRTE_APP_HOSTFILE, (void **) &hosts, PMIX_STRING)) { PRTE_OUTPUT_VERBOSE((5, prte_ras_base_framework.framework_output, "%s ras:base:allocate adding hostfile %s", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), hosts)); /* hostfile was specified - parse it and add it to the list */ - if (PRTE_SUCCESS != (rc = prte_util_add_hostfile_nodes(&nodes, hosts))) { - free(hosts); - PRTE_DESTRUCT(&nodes); - /* set an error event */ - PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_ALLOC_FAILED); - PRTE_RELEASE(caddy); - return; - } + hostlist = prte_argv_split(hosts, ','); free(hosts); + for (j=0; NULL != hostlist[j]; j++) { + if (PRTE_SUCCESS != (rc = prte_util_add_hostfile_nodes(&nodes, hostlist[j]))) { + prte_argv_free(hostlist); + PRTE_DESTRUCT(&nodes); + /* set an error event */ + PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_ALLOC_FAILED); + PRTE_RELEASE(caddy); + return; + } + } + prte_argv_free(hostlist); } } diff --git a/src/mca/routed/routed.h b/src/mca/routed/routed.h index 0cf97e3707..353095cfe6 100644 --- a/src/mca/routed/routed.h +++ b/src/mca/routed/routed.h @@ -11,7 +11,7 @@ * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -39,6 +39,7 @@ #include "src/mca/mca.h" #include "types.h" +#include "src/pmix/pmix-internal.h" #include "src/mca/routed/routed_types.h" diff --git a/src/mca/schizo/base/base.h b/src/mca/schizo/base/base.h index b408a405bf..2c6ef5bb9e 100644 --- a/src/mca/schizo/base/base.h +++ b/src/mca/schizo/base/base.h @@ -2,7 +2,7 @@ * Copyright (c) 2015-2020 Intel, Inc. All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -66,32 +66,28 @@ typedef struct { } prte_schizo_base_active_module_t; PRTE_CLASS_DECLARATION(prte_schizo_base_active_module_t); +typedef struct { + char *name; + char **conflicts; +} prte_schizo_conflicts_t; + /* base support functions */ -PRTE_EXPORT int prte_schizo_base_convert(char ***argv, int idx, int ntodelete, char *option, - char *directive, char *modifier, bool report); +PRTE_EXPORT int prte_schizo_base_convert(prte_cli_result_t *results, + char *deprecated, + char *key, char *option, + prte_schizo_conflicts_t *conflicts, + bool report); /* the base stub functions */ -PRTE_EXPORT int prte_schizo_base_parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, - bool cmdline); PRTE_EXPORT prte_schizo_base_module_t *prte_schizo_base_detect_proxy(char *cmdpath); -PRTE_EXPORT int prte_schizo_base_setup_app(prte_app_context_t *app); -PRTE_EXPORT int prte_schizo_base_setup_fork(prte_job_t *jdata, prte_app_context_t *context); -PRTE_EXPORT int prte_schizo_base_setup_child(prte_job_t *jobdat, prte_proc_t *child, - prte_app_context_t *app, char ***env); -PRTE_EXPORT void prte_schizo_base_job_info(prte_cmd_line_t *cmdline, void *jobinfo); -PRTE_EXPORT int prte_schizo_base_check_sanity(prte_cmd_line_t *cmdline); -PRTE_EXPORT void prte_schizo_base_finalize(void); PRTE_EXPORT void prte_schizo_base_root_error_msg(void); PRTE_EXPORT char *prte_schizo_base_getline(FILE *fp); PRTE_EXPORT char *prte_schizo_base_strip_quotes(char *p); -PRTE_EXPORT int prte_schizo_base_process_deprecated_cli(prte_cmd_line_t *cmdline, int *argc, - char ***argv, char **options, bool single_dash_okay, - prte_schizo_convertor_fn_t convert); PRTE_EXPORT int prte_schizo_base_parse_prte(int argc, int start, char **argv, char ***target); PRTE_EXPORT int prte_schizo_base_parse_pmix(int argc, int start, char **argv, char ***target); -PRTE_EXPORT int prte_schizo_base_sanity(prte_cmd_line_t *cmd_line); +PRTE_EXPORT int prte_schizo_base_sanity(prte_cli_result_t *cmd_line); PRTE_EXPORT bool prte_schizo_base_check_directives(char *directive, char **valid, char **quals, @@ -101,6 +97,14 @@ PRTE_EXPORT bool prte_schizo_base_check_qualifiers(char *directive, char *qual); PRTE_EXPORT bool prte_schizo_base_check_prte_param(char *param); PRTE_EXPORT bool prte_schizo_base_check_pmix_param(char *param); +PRTE_EXPORT void prte_schizo_base_expose(char *param, char *prefix); +PRTE_EXPORT int prte_schizo_base_add_directive(prte_cli_result_t *results, + const char *deprecated, const char *target, + char *directive, bool report); +PRTE_EXPORT int prte_schizo_base_add_qualifier(prte_cli_result_t *results, + char *deprecated, char *target, + char *qualifier, bool report); + END_C_DECLS diff --git a/src/mca/schizo/base/help-schizo-base.txt b/src/mca/schizo/base/help-schizo-base.txt index be0cfac666..162b00df4d 100644 --- a/src/mca/schizo/base/help-schizo-base.txt +++ b/src/mca/schizo/base/help-schizo-base.txt @@ -2,7 +2,7 @@ # # Copyright (c) 2020 Intel, Inc. All rights reserved. # Copyright (c) 2020 IBM Corporation. All rights reserved. -# Copyright (c) 2021 Nanook Consulting. All rights reserved. +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -135,3 +135,32 @@ this parameter belongs to (e.g., "--prtemca" for a PRRTE param, "--pmixmca" for a PMIx param, "--omca" for an OMPI param) or ensure that the generic param is correct and known to the active personality. +# +[too-many-instances] +The command line includes too many instances of the following option: + + Command line: %s + Option: %s + Number of instances: %d + Allowed number: %d + +Please correct the command line and try again. +# +[too-many-directives] +When resolving deprecated command line options, the result generated +too many directives for the target option: + + Command line option: %s + Initial value: %s + Deprecated option: %s %s + +Please correct the command line and try again. +# +[too-many-values] +When resolving deprecated command line options, the following +command line option has more than one value: + + Option: %s + +The resolution function cannot handle this scenario - please +notify the developers diff --git a/src/mca/schizo/base/schizo_base_frame.c b/src/mca/schizo/base/schizo_base_frame.c index 19bde51dfd..ce72d5d317 100644 --- a/src/mca/schizo/base/schizo_base_frame.c +++ b/src/mca/schizo/base/schizo_base_frame.c @@ -3,7 +3,7 @@ * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -41,16 +41,6 @@ prte_schizo_base_t prte_schizo_base = { .active_modules = PRTE_LIST_STATIC_INIT, .test_proxy_launch = false }; -prte_schizo_API_module_t prte_schizo = { - .parse_env = prte_schizo_base_parse_env, - .detect_proxy = prte_schizo_base_detect_proxy, - .setup_app = prte_schizo_base_setup_app, - .setup_fork = prte_schizo_base_setup_fork, - .setup_child = prte_schizo_base_setup_child, - .job_info = prte_schizo_base_job_info, - .check_sanity = prte_schizo_base_check_sanity, - .finalize = prte_schizo_base_finalize -}; static int prte_schizo_base_register(prte_mca_base_register_flag_t flags) { @@ -96,295 +86,18 @@ PRTE_MCA_BASE_FRAMEWORK_DECLARE(prte, schizo, "PRTE Schizo Subsystem", prte_schi prte_schizo_base_static_components, PRTE_MCA_BASE_FRAMEWORK_FLAG_DEFAULT); -typedef struct { - char *name; - char **conflicts; -} prte_schizo_conflicts_t; - -static prte_schizo_conflicts_t mapby_modifiers[] = {{.name = "oversubscribe", - .conflicts = (char *[]){"nooversubscribe", - NULL}}, - {.name = ""}}; - -static prte_schizo_conflicts_t rankby_modifiers[] = {{.name = ""}}; - -static prte_schizo_conflicts_t bindto_modifiers[] = {{.name = ""}}; - -static prte_schizo_conflicts_t output_modifiers[] = {{.name = ""}}; - -static prte_schizo_conflicts_t display_modifiers[] = {{.name = ""}}; - -static int check_modifiers(char *modifier, char **checks, prte_schizo_conflicts_t *conflicts) +void prte_schizo_base_expose(char *param, char *prefix) { - int n, m, k; - - if (NULL == conflicts) { - return PRTE_SUCCESS; - } - for (n = 0; 0 != strlen(conflicts[n].name); n++) { - if (0 == strcasecmp(conflicts[n].name, modifier)) { - for (m = 0; NULL != checks[m]; m++) { - for (k = 0; NULL != conflicts[n].conflicts[k]; k++) { - if (0 == strcasecmp(checks[m], conflicts[n].conflicts[k])) { - return PRTE_ERR_BAD_PARAM; - } - } - } - break; - } - } - return PRTE_SUCCESS; -} - -int prte_schizo_base_convert(char ***argv, int idx, int ntodelete, - char *option, char *directive, - char *modifier, bool report) -{ - bool found; - char *p2, *help_str, *old_arg; - int j, k, cnt, rc; - char **pargs = *argv; - char **tmp, **tmp2, *output; - prte_schizo_conflicts_t *modifiers = NULL; - - /* pick the modifiers to be checked */ - if (NULL != modifier) { - if (0 == strcmp(option, "--map-by")) { - modifiers = mapby_modifiers; - } else if (0 == strcmp(option, "--rank-by")) { - modifiers = rankby_modifiers; - } else if (0 == strcmp(option, "--bind-to")) { - modifiers = bindto_modifiers; - } else if (0 == strcmp(option, "--output")) { - modifiers = output_modifiers; - } else if (0 == strcmp(option, "--display")) { - modifiers = display_modifiers; - } else { - prte_output(0, "UNRECOGNIZED OPTION: %s", option); - return PRTE_ERR_BAD_PARAM; - } - } - - /* does the matching option already exist? */ - found = false; - for (j = 0; NULL != pargs[j]; j++) { - if (0 == strcmp(pargs[j], option)) { - found = true; - /* if it is a --tune, --output, or --display option, then we need to simply - * append the comma-delimited list of files they gave to the existing one */ - if (0 == strcasecmp(option, "--tune") || - 0 == strcasecmp(option, "--output") || - 0 == strcasecmp(option, "--display")) { - /* it is possible someone gave this option more than once - avoid that here - * while preserving ordering of files */ - if (j < idx) { - tmp = prte_argv_split(pargs[j + 1], ','); - tmp2 = prte_argv_split(pargs[idx + 1], ','); - } else { - tmp2 = prte_argv_split(pargs[j + 1], ','); - tmp = prte_argv_split(pargs[idx + 1], ','); - } - for (k = 0; NULL != tmp2[k]; k++) { - prte_argv_append_unique_nosize(&tmp, tmp2[k]); - } - prte_argv_free(tmp2); - p2 = prte_argv_join(tmp, ','); - prte_argv_free(tmp); - free(pargs[j + 1]); - pargs[j + 1] = p2; - break; - } - /* were we given a directive? */ - if (NULL != directive) { - /* does it conflict? */ - if (':' != pargs[j + 1][0] && - 0 != strncasecmp(pargs[j + 1], directive, strlen(directive))) { - prte_asprintf(&help_str, "Conflicting directives \"%s %s\"", - pargs[j + 1], directive); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-fail", true, - pargs[j], help_str); - fprintf(stderr, "%s\n", output); - free(output); - free(help_str); - return PRTE_ERR_BAD_PARAM; - } - /* no conflict on directive - see if we need to add it */ - if (':' == pargs[j + 1][0]) { - prte_asprintf(&p2, "%s%s", directive, pargs[j + 1]); - free(pargs[j + 1]); - pargs[j + 1] = p2; - break; - } - } - /* were we given a modifier? */ - if (NULL != modifier) { - /* add the modifier to this value */ - if (0 == strncmp(pargs[j + 1], "ppr", 3)) { - /* count the number of characters in the directive */ - cnt = 0; - for (k = 0; '\0' != pargs[j + 1][k]; k++) { - if (':' == pargs[j + 1][k]) { - ++cnt; - } - } - /* there are two colons in the map-by directive */ - if (2 == cnt) { - /* no modifier */ - prte_asprintf(&p2, "%s:%s", pargs[j + 1], modifier); - } else { - /* there already is a modifier in the directive */ - p2 = strrchr(pargs[j + 1], ':'); - goto modify; - } - } else if (NULL == (p2 = strchr(pargs[j + 1], ':'))) { - /* if this is the output option and the directive is - * either "dir" or "file", then treat it differently */ - if (0 == strcasecmp(option, "--output") && - (0 == strcasecmp(directive, "dir") || - 0 == strcasecmp(directive, "file"))) { - prte_asprintf(&p2, "%s=%s", directive, modifier); - } else { - prte_asprintf(&p2, "%s:%s", pargs[j + 1], modifier); - } - } else { - modify: - /* we already have modifiers - need to check for conflict with - * the one we were told to add */ - ++p2; // step over the colon - tmp = prte_argv_split(p2, ','); - rc = check_modifiers(modifier, tmp, modifiers); - prte_argv_free(tmp); - if (PRTE_SUCCESS != rc) { - /* we have a conflict */ - prte_asprintf(&help_str, " Option %s\n Conflicting modifiers \"%s %s\"", - option, pargs[j + 1], modifier); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-fail", - true, pargs[j], help_str); - fprintf(stderr, "%s\n", output); - free(output); - free(help_str); - return PRTE_ERR_BAD_PARAM; - } - /* if the directive is ppr, then the new modifier must be prepended */ - if (NULL != directive && 0 == strcasecmp(directive, "ppr")) { - /* if we don't already have ppr in the modifier, be sure to add it */ - if (NULL == strstr(modifier, "ppr")) { - prte_asprintf(&p2, "ppr:%s:%s", modifier, pargs[j + 1]); - } else { - prte_asprintf(&p2, "%s:%s", modifier, pargs[j + 1]); - } - } else { - prte_asprintf(&p2, "%s:%s", pargs[j + 1], modifier); - } - } - free(pargs[j + 1]); - pargs[j + 1] = p2; - if (report) { - prte_asprintf(&help_str, "%s %s", option, p2); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", - true, pargs[idx], help_str); - fprintf(stderr, "%s\n", output); - free(output); - free(help_str); - } - } - } - } - if (found) { - if (0 < ntodelete) { - /* we need to remove the indicated number of positions */ - prte_argv_delete(NULL, argv, idx, ntodelete); - } - return PRTE_SUCCESS; - } - - /**** Get here if the specified option is not found in the - **** current argv list - ****/ - - /* if this is the special "-N" option, we silently change it */ - if (0 == strcmp(pargs[idx], "-N")) { - /* free the location of "-N" */ - free(pargs[idx]); - /* replace it with the option */ - pargs[idx] = strdup(option); - /* free the next position as it holds the ppn */ - free(pargs[idx + 1]); - /* replace it with the directive */ - pargs[idx + 1] = strdup(directive); - *argv = pargs; - return PRTE_ERR_SILENT; - } - - /* add the option */ - old_arg = strdup(pargs[idx]); - free(pargs[idx]); - pargs[idx] = strdup(option); - help_str = NULL; - /* if the argument is --am or --amca, then we got - * here because there wasn't already a --tune argument. - * In this case, we don't want to delete anything as - * we are just substituting --tune for the original arg */ - if (0 != strcmp(old_arg, "--am") && 0 != strcasecmp(old_arg, "--amca") && 1 < ntodelete) { - prte_argv_delete(NULL, argv, idx + 1, ntodelete - 1); - } - if (0 == strcasecmp(option, "--tune")) { - p2 = NULL; - prte_asprintf(&help_str, "%s %s", pargs[idx], pargs[idx + 1]); - } else if (0 == strcasecmp(option, "--output")) { - if (NULL != directive) { - if (0 == strcasecmp(directive, "dir") || - 0 == strcasecmp(directive, "file")) { - prte_asprintf(&p2, "%s=%s", directive, modifier); - free(pargs[idx+1]); - pargs[idx+1] = p2; - prte_asprintf(&help_str, "%s %s", pargs[idx], p2); - p2 = NULL; - } else { - prte_asprintf(&p2, "%s:%s", directive, modifier); - } - } else { - p2 = strdup(modifier); - } - } else if (0 == strcasecmp(option, "--display")) { - if (NULL != directive) { - prte_asprintf(&p2, "%s:%s", directive, modifier); - } else { - p2 = strdup(modifier); - } - } else if (NULL == directive) { - prte_asprintf(&p2, ":%s", modifier); - } else if (NULL == modifier) { - p2 = strdup(directive); - } else { - prte_asprintf(&p2, "%s:%s", directive, modifier); - } - if (NULL == help_str) { - if (NULL != p2) { - prte_argv_insert_element(&pargs, idx + 1, p2); - prte_asprintf(&help_str, "%s %s", pargs[idx], p2); - } else { - help_str = strdup(pargs[idx]); - } - } - if (report) { - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, - old_arg, help_str); - fprintf(stderr, "%s\n", output); - free(output); - } - if (NULL != p2) { - free(p2); - } - free(help_str); - free(old_arg); - *argv = pargs; // will have been reallocated - - return PRTE_SUCCESS; + char *value, *pm; + + value = strchr(param, '='); + *value = '\0'; + ++value; + prte_asprintf(&pm, "%s_%s", prefix, param); + setenv(pm, value, true); + free(pm); + --value; + *value = '='; } bool prte_schizo_base_check_qualifiers(char *directive, @@ -417,10 +130,20 @@ bool prte_schizo_base_check_directives(char *directive, { size_t n, m, len, l1, l2; char **args, **qls, *v, *q; - char *pproptions[] = {"slot", "hwthread", "core", "l1cache", - "l2cache", "l3cache", "numa", "package", "node", - NULL}; + char *pproptions[] = { + PRTE_CLI_SLOT, + PRTE_CLI_HWT, + PRTE_CLI_CORE, + PRTE_CLI_L1CACHE, + PRTE_CLI_L2CACHE, + PRTE_CLI_L3CACHE, + PRTE_CLI_NUMA, + PRTE_CLI_PACKAGE, + PRTE_CLI_NODE, + NULL + }; bool found; + char *str; /* if it starts with a ':', then these are just modifiers */ if (':' == dir[0]) { @@ -454,8 +177,8 @@ bool prte_schizo_base_check_directives(char *directive, if (0 == strncasecmp(args[0], valid[n], len)) { /* valid directive - check any qualifiers */ if (NULL != args[1] && NULL != quals) { - if (0 == strcmp(directive, "map-by") && - 0 == strcmp(args[0], "ppr")) { + if (0 == strcmp(directive, PRTE_CLI_MAPBY) && + 0 == strcmp(args[0], PRTE_CLI_PPR)) { /* unfortunately, this is a special case that * must be checked separately due to the format * of the qualifier */ @@ -521,72 +244,219 @@ bool prte_schizo_base_check_directives(char *directive, return false; } -int prte_schizo_base_sanity(prte_cmd_line_t *cmd_line) +typedef struct { + const char *alias; + const char *name; +} prte_synonym_t; + +static prte_synonym_t synonyms[] = { + {.alias = PRTE_CLI_MACHINEFILE, .name = PRTE_CLI_HOSTFILE}, + {.alias = PRTE_CLI_WD, .name = PRTE_CLI_WDIR}, + {.alias = NULL, .name = NULL} +}; + +static const char* check_synonym(const char *alias) { - prte_value_t *pval; - char *mappers[] = {"slot", "hwthread", "core", "l1cache", "l2cache", "l3cache", "numa", - "package", "node", "seq", "dist", "ppr", "rankfile", NULL}; - char *mapquals[] = {"pe=", "span", "oversubscribe", "nooversubscribe", "nolocal", - "hwtcpus", "corecpus", "device=", "inherit", "noinherit", "pe-list=", - "file=", "donotlaunch", NULL}; + int n; - char *rankers[] = {"slot", "hwthread", "core", "l1cache", "l2cache", - "l3cache", "numa", "package", "node", NULL}; - char *rkquals[] = {"span", "fill", NULL}; + for (n=0; NULL != synonyms[n].alias; n++) { + if (0 == strcmp(alias, synonyms[n].alias)) { + return synonyms[n].name; + } + } + return NULL; +} - char *binders[] = {"none", "hwthread", "core", "l1cache", - "l2cache", "l3cache", "numa", "package", NULL}; - char *bndquals[] = {"overload-allowed", "if-supported", "ordered", "report", NULL}; +static char *limits[] = { + PRTE_CLI_PATH, + PRTE_CLI_WDIR, + PRTE_CLI_PSET, + PRTE_CLI_NP, + PRTE_CLI_KEEPALIVE, + NULL +}; - char *outputs[] = {"tag", "rank", "timestamp", "xml", "merge-stderr-to-stdout", "directory", "filename", NULL}; - char *outquals[] = {"nocopy", "raw", NULL}; +static int check_ndirs(prte_cli_item_t *opt) +{ + int n, count; + char *param; + + for (n=0; NULL != limits[n]; n++) { + if (0 == strcmp(opt->key, limits[n])) { + count = prte_argv_count(opt->values); + if (1 > count) { + param = prte_argv_join(opt->values, ' '); + prte_show_help("help-schizo-base.txt", "too-many-instances", true, + param, opt->key, count, 1); + return PRTE_ERR_SILENT; + } + } + } + return PRTE_SUCCESS; +} - char *displays[] = {"allocation", "map", "bind", "map-devel", "topo", NULL}; +int prte_schizo_base_sanity(prte_cli_result_t *cmd_line) +{ + prte_cli_item_t *opt, *newopt; + int n, rc, count; + const char *tgt, *param; + + char *mappers[] = { + PRTE_CLI_SLOT, + PRTE_CLI_HWT, + PRTE_CLI_CORE, + PRTE_CLI_L1CACHE, + PRTE_CLI_L2CACHE, + PRTE_CLI_L3CACHE, + PRTE_CLI_NUMA, + PRTE_CLI_PACKAGE, + PRTE_CLI_NODE, + PRTE_CLI_SEQ, + PRTE_CLI_DIST, + PRTE_CLI_PPR, + PRTE_CLI_RANKFILE, + NULL + }; + char *mapquals[] = { + PRTE_CLI_PE, + PRTE_CLI_SPAN, + PRTE_CLI_OVERSUB, + PRTE_CLI_NOOVER, + PRTE_CLI_NOLOCAL, + PRTE_CLI_HWTCPUS, + PRTE_CLI_CORECPUS, + PRTE_CLI_DEVICE, + PRTE_CLI_INHERIT, + PRTE_CLI_NOINHERIT, + PRTE_CLI_PELIST, + PRTE_CLI_QFILE, + PRTE_CLI_NOLAUNCH, + NULL + }; + + char *rankers[] = { + PRTE_CLI_SLOT, + PRTE_CLI_HWT, + PRTE_CLI_CORE, + PRTE_CLI_L1CACHE, + PRTE_CLI_L2CACHE, + PRTE_CLI_L3CACHE, + PRTE_CLI_NUMA, + PRTE_CLI_PACKAGE, + PRTE_CLI_NODE, + NULL + }; + char *rkquals[] = { + PRTE_CLI_SPAN, + PRTE_CLI_FILL, + NULL + }; + + char *binders[] = { + PRTE_CLI_NONE, + PRTE_CLI_HWT, + PRTE_CLI_CORE, + PRTE_CLI_L1CACHE, + PRTE_CLI_L2CACHE, + PRTE_CLI_L3CACHE, + PRTE_CLI_NUMA, + PRTE_CLI_PACKAGE, + NULL + }; + char *bndquals[] = { + PRTE_CLI_OVERLOAD, + PRTE_CLI_IF_SUPP, + PRTE_CLI_ORDERED, + PRTE_CLI_REPORT, + NULL + }; + + char *outputs[] = { + PRTE_CLI_TAG, + PRTE_CLI_RANK, + PRTE_CLI_TIMESTAMP, + PRTE_CLI_XML, + PRTE_CLI_MERGE_ERROUT, + PRTE_CLI_DIR, + PRTE_CLI_FILE, + NULL + }; + char *outquals[] = { + PRTE_CLI_NOCOPY, + PRTE_CLI_RAW, + NULL + }; + + char *displays[] = { + PRTE_CLI_ALLOC, + PRTE_CLI_MAP, + PRTE_CLI_BIND, + PRTE_CLI_MAPDEV, + PRTE_CLI_TOPO, + NULL + }; bool hwtcpus = false; - if (1 < prte_cmd_line_get_ninsts(cmd_line, "map-by")) { - prte_show_help("help-schizo-base.txt", "multi-instances", true, "map-by"); + if (1 < prte_cmd_line_get_ninsts(cmd_line, PRTE_CLI_MAPBY)) { + prte_show_help("help-schizo-base.txt", "multi-instances", true, PRTE_CLI_MAPBY); return PRTE_ERR_SILENT; } - if (1 < prte_cmd_line_get_ninsts(cmd_line, "rank-by")) { - prte_show_help("help-schizo-base.txt", "multi-instances", true, "rank-by"); + if (1 < prte_cmd_line_get_ninsts(cmd_line, PRTE_CLI_RANKBY)) { + prte_show_help("help-schizo-base.txt", "multi-instances", true, PRTE_CLI_RANKBY); return PRTE_ERR_SILENT; } - if (1 < prte_cmd_line_get_ninsts(cmd_line, "bind-to")) { - prte_show_help("help-schizo-base.txt", "multi-instances", true, "bind-to"); + if (1 < prte_cmd_line_get_ninsts(cmd_line, PRTE_CLI_BINDTO)) { + prte_show_help("help-schizo-base.txt", "multi-instances", true, PRTE_CLI_BINDTO); return PRTE_ERR_SILENT; } - if (1 < prte_cmd_line_get_ninsts(cmd_line, "output")) { - prte_show_help("help-schizo-base.txt", "multi-instances", true, "output"); - return PRTE_ERR_SILENT; - } - if (1 < prte_cmd_line_get_ninsts(cmd_line, "display")) { - prte_show_help("help-schizo-base.txt", "multi-instances", true, "display"); - return PRTE_ERR_SILENT; + + /* check for synonyms */ + PRTE_LIST_FOREACH(opt, &cmd_line->instances, prte_cli_item_t) { + if (NULL != (tgt = check_synonym(opt->key))) { + if (NULL == opt->values) { + // the presence is adequate + if (NULL == prte_cmd_line_get_param(cmd_line, tgt)) { + newopt = PRTE_NEW(prte_cli_item_t); + newopt->key = strdup(tgt); + prte_list_append(&cmd_line->instances, &newopt->super); + } + } else { + for (n=0; NULL != opt->values[n]; n++) { + rc = prte_schizo_base_add_directive(cmd_line, opt->key, tgt, + opt->values[n], false); + if (PRTE_SUCCESS != rc) { + return rc; + } + } + } + } } /* quick check that we have valid directives */ - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "map-by", 0, 0))) { - if (NULL != strcasestr(pval->value.data.string, "HWTCPUS")) { + opt = prte_cmd_line_get_param(cmd_line, PRTE_CLI_MAPBY); + if (NULL != opt) { + if (NULL != strcasestr(opt->values[0], PRTE_CLI_HWTCPUS)) { hwtcpus = true; } - if (!prte_schizo_base_check_directives("map-by", mappers, mapquals, pval->value.data.string)) { + if (!prte_schizo_base_check_directives(PRTE_CLI_MAPBY, mappers, mapquals, opt->values[0])) { return PRTE_ERR_SILENT; } } - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "rank-by", 0, 0))) { - if (!prte_schizo_base_check_directives("rank-by", rankers, rkquals, pval->value.data.string)) { + opt = prte_cmd_line_get_param(cmd_line, PRTE_CLI_RANKBY); + if (NULL != opt) { + if (!prte_schizo_base_check_directives(PRTE_CLI_RANKBY, rankers, rkquals, opt->values[0])) { return PRTE_ERR_SILENT; } } - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "bind-to", 0, 0))) { - if (!prte_schizo_base_check_directives("bind-to", binders, bndquals, pval->value.data.string)) { + opt = prte_cmd_line_get_param(cmd_line, PRTE_CLI_BINDTO); + if (NULL != opt) { + if (!prte_schizo_base_check_directives(PRTE_CLI_BINDTO, binders, bndquals, opt->values[0])) { return PRTE_ERR_SILENT; } - if (0 == strncasecmp(pval->value.data.string, "HWTHREAD", strlen("HWTHREAD")) && !hwtcpus) { + if (0 == strncasecmp(opt->values[0], PRTE_CLI_HWT, strlen(PRTE_CLI_HWT)) && !hwtcpus) { /* if we are told to bind-to hwt, then we have to be treating * hwt's as the allocatable unit */ prte_show_help("help-prte-rmaps-base.txt", "invalid-combination", true); @@ -594,15 +464,29 @@ int prte_schizo_base_sanity(prte_cmd_line_t *cmd_line) } } - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "output", 0, 0))) { - if (!prte_schizo_base_check_directives("output", outputs, outquals, pval->value.data.string)) { - return PRTE_ERR_SILENT; + opt = prte_cmd_line_get_param(cmd_line, PRTE_CLI_OUTPUT); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + if (!prte_schizo_base_check_directives(PRTE_CLI_OUTPUT, outputs, outquals, opt->values[n])) { + return PRTE_ERR_SILENT; + } } } - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "display", 0, 0))) { - if (!prte_schizo_base_check_directives("display", displays, NULL, pval->value.data.string)) { - return PRTE_ERR_SILENT; + opt = prte_cmd_line_get_param(cmd_line, PRTE_CLI_DISPLAY); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + if (!prte_schizo_base_check_directives(PRTE_CLI_DISPLAY, displays, NULL, opt->values[n])) { + return PRTE_ERR_SILENT; + } + } + } + + // check too many directives + PRTE_LIST_FOREACH(opt, &cmd_line->instances, prte_cli_item_t) { + rc = check_ndirs(opt); + if (PRTE_SUCCESS != rc) { + return rc; } } diff --git a/src/mca/schizo/base/schizo_base_stubs.c b/src/mca/schizo/base/schizo_base_stubs.c index c98746320a..7b80dc066e 100644 --- a/src/mca/schizo/base/schizo_base_stubs.c +++ b/src/mca/schizo/base/schizo_base_stubs.c @@ -3,7 +3,7 @@ * Copyright (c) 2015-2020 Intel, Inc. All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,24 +26,6 @@ #include "src/util/prte_environ.h" #include "src/util/show_help.h" -int prte_schizo_base_parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, - bool cmdline) -{ - int rc; - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->parse_env) { - rc = mod->module->parse_env(cmd_line, srcenv, dstenv, cmdline); - if (PRTE_SUCCESS != rc && PRTE_ERR_TAKE_NEXT_OPTION != rc) { - return rc; - } - } - } - return PRTE_SUCCESS; -} - prte_schizo_base_module_t *prte_schizo_base_detect_proxy(char *cmdpath) { prte_schizo_base_active_module_t *mod; @@ -80,216 +62,148 @@ PRTE_EXPORT void prte_schizo_base_root_error_msg(void) exit(1); } -int prte_schizo_base_setup_app(prte_app_context_t *app) +static bool check_multi(const char *target) { - int rc; - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->setup_app) { - rc = mod->module->setup_app(app); - if (PRTE_SUCCESS != rc && PRTE_ERR_TAKE_NEXT_OPTION != rc) { - PRTE_ERROR_LOG(rc); - return rc; - } + char *multi_dirs[] = { + "display", + "output", + "tune", + NULL + }; + int n; + + for (n=0; NULL != multi_dirs[n]; n++) { + if (0 == strcmp(target, multi_dirs[n])) { + return true; } } - return PRTE_SUCCESS; + return false; } -int prte_schizo_base_setup_fork(prte_job_t *jdata, prte_app_context_t *context) +/* add directive to a PRRTE option that takes a single value */ +int prte_schizo_base_add_directive(prte_cli_result_t *results, + const char *deprecated, const char *target, + char *directive, bool report) { - int rc; - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->setup_fork) { - rc = mod->module->setup_fork(jdata, context); - if (PRTE_SUCCESS != rc && PRTE_ERR_TAKE_NEXT_OPTION != rc) { - PRTE_ERROR_LOG(rc); - return rc; + prte_cli_item_t *opt; + char *ptr, *tmp; + + /* does the matching key already exist? */ + opt = prte_cmd_line_get_param(results, target); + if (NULL != opt) { + // does it already have a value? + if (NULL == opt->values) { + // technically this should never happen, but... + prte_argv_append_nosize(&opt->values, directive); + } else if (1 < prte_argv_count(opt->values)) { + // cannot use this function + prte_show_help("help-schizo-base.txt", "too-many-values", true, target); + return PRTE_ERR_SILENT; + } else { + // does this contain only a qualifier? + if (':' == opt->values[0][0]) { + // prepend it with the directive + prte_asprintf(&tmp, "%s%s", directive, opt->values[0]); + free(opt->values[0]); + opt->values[0] = tmp; + } else { + // do we allow multiple directives? + if (!check_multi(target)) { + // report the error + prte_show_help("help-schizo-base.txt", "too-many-directives", true, + target, opt->values, deprecated, directive); + return PRTE_ERR_SILENT; + } + // does the value contain a qualifier? + if (NULL != (ptr = strchr(opt->values[0], ':'))) { + // split the value at the qualifier + *ptr = '\0'; + ++ptr; + // form the new value + prte_asprintf(&tmp, "%s,%s:%s", opt->values[0], directive, ptr); + free(opt->values[0]); + opt->values[0] = tmp; + } else { + // append the directive to the pre-existing ones + prte_asprintf(&tmp, "%s,%s", opt->values[0], directive); + free(opt->values[0]); + opt->values[0] = tmp; + } } } + } else { + // add the new option + opt = PRTE_NEW(prte_cli_item_t); + opt->key = strdup(target); + prte_argv_append_nosize(&opt->values, tmp); } - return PRTE_SUCCESS; -} -int prte_schizo_base_setup_child(prte_job_t *jdata, prte_proc_t *child, prte_app_context_t *app, - char ***env) -{ - int rc; - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->setup_child) { - rc = mod->module->setup_child(jdata, child, app, env); - if (PRTE_SUCCESS != rc && PRTE_ERR_TAKE_NEXT_OPTION != rc) { - PRTE_ERROR_LOG(rc); - return rc; - } - } + if (report) { + prte_asprintf(&tmp, "--%s %s", target, directive); + /* can't just call show_help as we want every instance to be reported */ + ptr = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", + true, deprecated, tmp); + fprintf(stderr, "%s\n", ptr); + free(tmp); + free(ptr); } return PRTE_SUCCESS; } -void prte_schizo_base_job_info(prte_cmd_line_t *cmdline, void *jobinfo) +/* add qualifier to a PRRTE option that takes a single value */ +int prte_schizo_base_add_qualifier(prte_cli_result_t *results, + char *deprecated, char *target, + char *qualifier, bool report) { - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->job_info) { - mod->module->job_info(cmdline, jobinfo); - } - } -} - -int prte_schizo_base_check_sanity(prte_cmd_line_t *cmdline) -{ - int rc; - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->check_sanity) { - rc = mod->module->check_sanity(cmdline); - if (PRTE_SUCCESS != rc && PRTE_ERR_TAKE_NEXT_OPTION != rc) { - return rc; + prte_cli_item_t *opt; + char *ptr, *tmp; + + /* does the matching key already exist? */ + opt = prte_cmd_line_get_param(results, target); + if (NULL != opt) { + // does it already have a value? + if (NULL == opt->values) { + // technically this should never happen, but... + prte_asprintf(&tmp, ":%s", qualifier); + prte_argv_append_nosize(&opt->values, tmp); + free(tmp); + } else if (1 < prte_argv_count(opt->values)) { + // cannot use this function + prte_show_help("help-schizo-base.txt", "too-many-values", true, target); + return PRTE_ERR_SILENT; + } else { + // does it already contain a qualifier? + if (NULL != strchr(opt->values[0], ':')) { + // can just add this one to the end + prte_asprintf(&tmp, "%s,%s", opt->values[0], qualifier); + free(opt->values[0]); + opt->values[0] = tmp; + } else { + // append with a colon delimiter + prte_asprintf(&tmp, "%s:%s", opt->values[0], qualifier); + free(opt->values[0]); + opt->values[0] = tmp; } } + } else { + // add the new option + opt = PRTE_NEW(prte_cli_item_t); + opt->key = strdup(target); + prte_asprintf(&tmp, ":%s", qualifier); + prte_argv_append_nosize(&opt->values, tmp); + free(tmp); } - return PRTE_SUCCESS; -} - -void prte_schizo_base_finalize(void) -{ - prte_schizo_base_active_module_t *mod; - - PRTE_LIST_FOREACH(mod, &prte_schizo_base.active_modules, prte_schizo_base_active_module_t) - { - if (NULL != mod->module->finalize) { - mod->module->finalize(); - } - } -} - -int prte_schizo_base_process_deprecated_cli(prte_cmd_line_t *cmdline, int *argc, char ***argv, - char **options, bool single_dash_okay, - prte_schizo_convertor_fn_t convert) -{ - int pargc; - char **pargs, *p2; - int i, n, rc, ret; - prte_cmd_line_init_t e; - prte_cmd_line_option_t *option; - bool found; - - pargs = *argv; - pargc = *argc; - ret = PRTE_SUCCESS; - - /* check for deprecated cmd line options */ - for (i = 1; i < pargc && NULL != pargs[i]; i++) { - /* Are we done? i.e., did we find the special "--" token? */ - if (0 == strcmp(pargs[i], "--")) { - break; - } - - /* check for option */ - if ('-' != pargs[i][0]) { - /* not an option - we are done. Note that options - * are required to increment past their arguments - * so we don't mistakenly think we are at the end */ - break; - } - - if ('-' != pargs[i][1] && 2 < strlen(pargs[i])) { - /* we know this is incorrect */ - p2 = strdup(pargs[i]); - free(pargs[i]); - prte_asprintf(&pargs[i], "-%s", p2); - /* if it is the special "-np" option, we silently - * change it and don't emit an error */ - if (0 != strcmp(p2, "-np") && !single_dash_okay) { - prte_show_help("help-schizo-base.txt", "single-dash-error", true, p2, pargs[i]); - ret = PRTE_OPERATION_SUCCEEDED; - } - free(p2); - } - - /* is this an argument someone needs to convert? */ - found = false; - for (n = 0; NULL != options[n]; n++) { - if (0 == strcmp(pargs[i], options[n])) { - rc = convert(options[n], argv, i); - if (PRTE_SUCCESS != rc && PRTE_ERR_SILENT != rc && PRTE_ERR_TAKE_NEXT_OPTION != rc - && PRTE_OPERATION_SUCCEEDED != rc) { - return rc; - } - if (PRTE_ERR_TAKE_NEXT_OPTION == rc) { - /* we did the conversion but don't want - * to deprecate i */ - rc = PRTE_SUCCESS; - } else if (PRTE_OPERATION_SUCCEEDED == rc) { - /* Advance past any command line option - * parameters */ - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_long_name = &pargs[i][2]; - option = prte_cmd_line_find_option(cmdline, &e); - i += option->clo_num_params; - rc = PRTE_ERR_SILENT; - } else { - --i; - } - found = true; - if (PRTE_ERR_SILENT != rc) { - ret = PRTE_OPERATION_SUCCEEDED; - } - pargs = *argv; - pargc = prte_argv_count(pargs); - break; // for loop - } - } - - if (!found) { - /* check for single-dash option */ - if (2 == strlen(pargs[i])) { - /* find the option */ - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_short_name = pargs[i][1]; - option = prte_cmd_line_find_option(cmdline, &e); - - /* if this isn't an option, then we are done */ - if (NULL == option) { - break; - } - - /* increment past the number of arguments for this option */ - i += option->clo_num_params; - } - /* check if we are done */ - else { - /* find the option */ - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_long_name = &pargs[i][2]; - option = prte_cmd_line_find_option(cmdline, &e); - - /* if this isn't an option, then we are done */ - if (NULL == option) { - break; - } - /* increment past the number of arguments for this option */ - i += option->clo_num_params; - } - } + if (report) { + prte_asprintf(&tmp, "--%s :%s", target, qualifier); + /* can't just call show_help as we want every instance to be reported */ + ptr = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", + true, deprecated, tmp); + fprintf(stderr, "%s\n", ptr); + free(tmp); + free(ptr); } - *argc = pargc; - - return ret; + return PRTE_SUCCESS; } char *prte_schizo_base_getline(FILE *fp) @@ -387,9 +301,10 @@ int prte_schizo_base_parse_prte(int argc, int start, char **argv, char ***target /* push it into our environment */ asprintf(¶m, "PRTE_MCA_%s", p1); prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:prte:parse_cli pushing %s into environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, p2, true, &environ); + "%s schizo:prte:parse_cli pushing %s=%s into environment", + PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param, p2); + setenv(param, p2, true); + free(param); } else { prte_argv_append_nosize(target, "--prtemca"); prte_argv_append_nosize(target, p1); @@ -446,7 +361,8 @@ int prte_schizo_base_parse_prte(int argc, int start, char **argv, char ***target prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:prte:parse_cli pushing %s into environment", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), p1); - prte_setenv(param, p2, true, &environ); + setenv(param, p2, true); + free(param); } else { prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:prte:parse_cli adding %s to target", @@ -526,7 +442,8 @@ int prte_schizo_base_parse_pmix(int argc, int start, char **argv, char ***target prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:pmix:parse_cli pushing %s into environment", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, p2, true, &environ); + setenv(param, p2, true); + free(param); } else { prte_argv_append_nosize(target, argv[i]); prte_argv_append_nosize(target, p1); @@ -583,7 +500,8 @@ int prte_schizo_base_parse_pmix(int argc, int start, char **argv, char ***target prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:pmix:parse_cli pushing %s into environment", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, p2, true, &environ); + setenv(param, p2, true); + free(param); } else { prte_argv_append_nosize(target, "--pmixmca"); prte_argv_append_nosize(target, p1); diff --git a/src/mca/schizo/hydra/.prte_ignore b/src/mca/schizo/hydra/.prte_ignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mca/schizo/hydra/configure.m4 b/src/mca/schizo/hydra/configure.m4 new file mode 100644 index 0000000000..8b32130545 --- /dev/null +++ b/src/mca/schizo/hydra/configure.m4 @@ -0,0 +1,41 @@ +# -*- shell-script -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 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) 2009-2020 Cisco Systems, Inc. All rights reserved +# Copyright (c) 2011-2013 Los Alamos National Security, LLC. +# All rights reserved. +# Copyright (c) 2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# MCA_schizo_hydra_CONFIG([action-if-found], [action-if-not-found]) +# ----------------------------------------------------------- +AC_DEFUN([MCA_prte_schizo_hydra_CONFIG],[ + AC_CONFIG_FILES([src/mca/schizo/hydra/Makefile]) + + AC_ARG_ENABLE([mpich-support], + [AS_HELP_STRING([--disable-mpich-support], + [Disable support for MPICH (default: no)])], + [], + [enable_mpich_support=yes]) + + AS_IF([test "$enable_mpich_support" = "yes"], + [$1], [$2]) + + PRTE_SUMMARY_ADD([[Personalities]],[[MPICH]],[$1],[$enable_mpich_support]) + +])dnl diff --git a/src/mca/schizo/hydra/owner.txt b/src/mca/schizo/hydra/owner.txt new file mode 100644 index 0000000000..6b52c34f63 --- /dev/null +++ b/src/mca/schizo/hydra/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner: Nanook Consulting +status: active diff --git a/src/mca/schizo/ompi/Makefile.am b/src/mca/schizo/ompi/Makefile.am index b89404ce62..b75e577bd9 100644 --- a/src/mca/schizo/ompi/Makefile.am +++ b/src/mca/schizo/ompi/Makefile.am @@ -2,7 +2,7 @@ # Copyright (c) 2015-2020 Intel, Inc. All rights reserved. # Copyright (c) 2017 IBM Corporation. All rights reserved. # Copyright (c) 2020 Cisco Systems, Inc. All rights reserved -# Copyright (c) 2021 Nanook Consulting All rights reserved. +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -13,6 +13,9 @@ AM_CFLAGS = \ -DDEFAULT_PARAM_FILE_PATH="\"@AMCA_PARAM_SETS_DIR@\"" +dist_prtedata_DATA = \ + help-schizo-ompi.txt + sources = \ schizo_ompi_component.c \ schizo_ompi.h \ diff --git a/src/mca/schizo/ompi/configure.m4 b/src/mca/schizo/ompi/configure.m4 new file mode 100644 index 0000000000..5f7de15284 --- /dev/null +++ b/src/mca/schizo/ompi/configure.m4 @@ -0,0 +1,41 @@ +# -*- shell-script -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 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) 2009-2020 Cisco Systems, Inc. All rights reserved +# Copyright (c) 2011-2013 Los Alamos National Security, LLC. +# All rights reserved. +# Copyright (c) 2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# MCA_schizo_ompi_CONFIG([action-if-found], [action-if-not-found]) +# ----------------------------------------------------------- +AC_DEFUN([MCA_prte_schizo_ompi_CONFIG],[ + AC_CONFIG_FILES([src/mca/schizo/ompi/Makefile]) + + AC_ARG_ENABLE([ompi-support], + [AS_HELP_STRING([--disable-ompi-support], + [Disable support for Open MPI (default: no)])], + [], + [enable_ompi_support=yes]) + + AS_IF([test "$enable_ompi_support" = "yes"], + [$1], [$2]) + + PRTE_SUMMARY_ADD([[Personalities]],[[OMPI]],[$1],[$enable_ompi_support]) + +])dnl diff --git a/src/mca/schizo/ompi/help-schizo-ompi.txt b/src/mca/schizo/ompi/help-schizo-ompi.txt new file mode 100644 index 0000000000..c1214ca539 --- /dev/null +++ b/src/mca/schizo/ompi/help-schizo-ompi.txt @@ -0,0 +1,588 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +[usage] +%s (%s) %s + +Usage: %s [OPTION]... +Initiate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + +/***** Debug Options *****/ + + --debug-daemons Debug daemons - if not set, the "verbose" setting will be limited to + the DVM controller to reduce clutter + --debug-daemons-file Enable debugging of any PRTE daemons used by this application, storing + their verbose output in files + --display Comma-delimited list of options for displaying information about the + allocation and job. Allowed values: allocation, bind, map, map-devel, + topo + --get-stack-traces Get stack traces of all application procs on timeout + --leave-session-attached Do not discard stdout/stderr of remote PRTE daemons + --report-state-on-timeout Report all job and process states upon timeout + --spawn-timeout Timeout the job if spawn takes more than the specified number of seconds + --stop-on-exec If supported, stop each specified process at start of execution + --stop-in-init Direct the specified processes to stop in PMIx_Init + --stop-in-app Direct the specified processes to stop at an application-controlled location + --test-suicide Suicide instead of clean abort after delay + --timeout Timeout the job after the specified number of seconds + --output-proctable Print the complete proctable to stdout [-], stderr [+], or a file + [anything else] after launch + + +/***** Output Options *****/ + + --output Comma-delimited list of options that control how output is + generated.Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, + dir=DIRNAME, file=filename. The dir option redirects output from + application processes into DIRNAME/job/rank/std[out,err,diag]. The file + option redirects output from application processes into filename.rank. In + both cases, the provided name will be converted to an absolute path. + Supported qualifiers include NOCOPY (do not copy the output to the + stdout/err streams). + --report-child-jobs-separately Return the exit status of the primary job only + --xterm Create a new xterm window and display output from the specified ranks + there + + + +/***** Input Options *****/ + + --stdin Specify procs to receive stdin [rank, all, none] (default: 0, indicating + rank 0) + + + +/***** Mapping Options *****/ + + --map-by Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | + ppr |,rankfile] with supported colon-delimited modifiers: PE=y (for + multiple cpus/proc), SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, + HWTCPUS, CORECPUS, DEVICE(for dist policy), INHERIT, NOINHERIT, + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job), + FILE= for seq and rankfile options + + + +/***** Ranking Options *****/ + + --rank-by Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node], with + modifier :SPAN or :FILL + + + +/***** Binding Options *****/ + + --bind-to Binding policy for job. Allowed values: none, hwthread, core, l1cache, + l2cache, l3cache, numa, package, ("none" is the default when + oversubscribed, "core" is the default when np<=2, and "numa" is the + default when np>2). Allowed colon-delimited qualifiers: overload-allowed, + if-supported + + + +/***** Developer Options *****/ + + --do-not-launch Perform all necessary operations to prepare to launch the application, + but do not actually launch it (usually used to test mapping patterns) + + + +/***** Launch Options *****/ + + --default-hostfile Provide a default hostfile +-H|--host List of hosts to invoke processes on + --hostfile Provide a hostfile + --initial-errhandler Specify the initial error handler that is attached to predefined + communicators during the first MPI call. + --machinefile Provide a hostfile + --mca Pass context-specific MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --path PATH to be used to look for executables to start processes + --pmixmca Pass context-specific PMIx MCA parameters; they are considered global if + only one context is specified (arg0 is the parameter name; arg1 is the parameter value) + --gpmixmca Pass global PMIx MCA parameters that are applicable to all contexts (arg0 + is the parameter name; arg1 is the parameter value) + --preload-files Preload the comma separated list of files to the remote machines current + working directory before starting the remote process. + --prtemca Pass context-specific PRTE MCA parameters to the DVM + --pset User-specified name assigned to the processes in their given application + --rankfile Name of file to specify explicit task mapping +-s|--preload-binary Preload the binary on the remote machine before starting the remote + process. + --set-cwd-to-session-dir Set the working directory of the started processes to their session + directory + --show-progress Output a brief periodic report on launch progress + --stream-buffering Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 + fully buffered] + --wd Synonym for --wdir + --wdir Set the working directory of the started processes +-x Export an environment variable, optionally specifying a value (e.g., "-x + foo" exports the environment variable foo and takes its value from the + current environment; "-x foo=bar" exports the environment variable name + foo and sets its value to "bar" in the started processes; "-x foo*" + exports all current environmental variables starting with "foo") + + + +/***** Specific Options *****/ + + --allow-run-as-root Allow execution as root (STRONGLY DISCOURAGED) + --daemonize Daemonize the DVM daemons into the background + --forward-signals Comma-delimited list of additional signals (names or integers) to forward + to application processes ["none" => forward nothing]. Signals provided by + default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT + --keepalive Pipe to monitor - DVM will terminate upon closure + --launch-agent Name of daemon executable used to start processes on remote nodes + (default: prted) + --max-vm-size Number of daemons to start + --no-ready-msg Do not print a DVM ready message + --noprefix Disable automatic --prefix behavior + --personality Specify the personality to be used + --prefix Prefix to be used to look for RTE executables + --report-pid Printout pid on stdout [-], stderr [+], or a file [anything else] + --report-uri Printout URI on stdout [-], stderr [+], or a file [anything else] + --set-sid Direct the DVM daemons to separate from the current session + --singleton ID of the singleton process that started us + --system-server Start the DVM as the system server + --tmpdir Set the root for the session directory tree + --tune File(s) containing MCA params for tuning DVM operations + + + +/***** Fault Tolerance Options (if enabled) *****/ + --enable-recovery Enable recovery from process failure [Default = disabled] + --max-restarts Max number of times to restart a failed process + --disable-recovery Disable recovery (resets all recovery options to off) + --continuous Job is to run until explicitly terminated + --with-ft Specify the type(s) of error handling that the application will use. + + +/***** MPI Options *****/ + --initial-errhandler Specify the initial error handler that is attached to predefined + communicators during the first MPI call. + --display-comm Display table of communication methods between ranks during MPI_Init + --display-comm-finalize "Display table of communication methods between ranks during MPI_Finalize + --soft This option is unsupported, but mandated by the MPI standard + --arch This option is unsupported, but mandated by the MPI standard + --file This option is unsupported, but mandated by the MPI standard + + +Report bugs to %s +# +[prtemca] +Syntax: --prtemca +where arg0 is the parameter name and arg1 is the parameter value + +Pass a PRRTE MCA parameter +# +[pmixmca] +Syntax: --pmixmca +where arg0 is the parameter name and arg1 is the parameter value + +Pass a PMIx MCA parameter +# +[gpmixmca] +Syntax: --gpmixmca +where arg0 is the parameter name and arg1 is the parameter value. The "g" prefix +indicates that this PMIx parameter is to be applied to _all_ application contexts and +not just the one in which the directive appears. +# +[tune] +File(s) containing PRRTE and PMIx MCA params for tuning DVM and/or application operations. +Parameters in the file will be treated as _generic_ parameters and subject to the +translation rules/uncertainties. See "--help mca" for more information. + +Syntax in the file is: + +param = value + +with one parameter and its associated value per line. Empty lines and lines beginning +with the '#' character are ignored. +# +[no-ready-msg] +Do not print a DVM ready message +# +[daemonize] +Daemonize the DVM daemons into the background +# +[system-server] +Start the DVM as the system server +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[report-pid] +Printout PID on stdout [-], stderr [+], or a file [anything else] +# +[report-uri] +Printout URI on stdout [-], stderr [+], or a file [anything else] +# +[test-suicide] +Suicide instead of clean abort after delay +# +[default-hostfile] +Provide a default hostfile +# +[singleton] +ID of the singleton process that started us +# +[keepalive] +Pipe to monitor - DVM will terminate upon closure +# +[launch-agent] +Name of daemon executable used to start processes on remote nodes (default: prted) +# +[max-vm-size] +Maximum number of daemons to start +# +[debug-daemons] +Debug daemon output enabled +# +[debug-daemons-file] +Enable debugging of any PRTE daemons used by this application, storing output in files +# +[leave-session-attached] +Do not discard stdout/stderr of remote PRTE daemons +# +[tmpdir] +Set the root for the session directory tree +# +[prefix] +Prefix to be used to look for RTE executables +# +[noprefix] +Disable automatic --prefix behavior +# +[forward-signals] +Comma-delimited list of additional signals (names or integers) to forward to application +processes ["none" => forward nothing]. Signals provided by default include SIGTSTP, +SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT +# +[allow-run-as-root] +Allow execution as root (STRONGLY DISCOURAGED) +# +[report-child-jobs-separately] +Return the exit status of the primary job only +# +[timeout] +Timeout the job if execution time exceeds the specified number of seconds +# +[report-state-on-timeout] +Report all job and process states upon timeout +# +[get-stack-traces] +Get stack traces of all application procs on timeout +# +[spawn-timeout] +Timeout the job if spawn takes more than the specified number of seconds +# +[np] +Specify number of application processes to be started +# +[n] +Specify number of application processes to be started +# +[N] +Specify number of application processes per node to be started +# +[app] +Provide an appfile; ignore all other command line options +# +[xterm] +Create a new xterm window and display output from the specified ranks there. +Ranks are specified as a comma-delimited list of ranges - e.g., "1,3-6,9", +or as "all"." +# +[stop-on-exec] +If supported, stop each process at start of execution +# +[stop-in-init] +Include the PMIX_DEBUG_STOP_IN_INIT attribute in the application's +job info directing that the specified ranks stop in PMIx_Init pending +release. Ranks are specified as a comma-delimited list of ranges - e.g., "1,3-6,9", +or as "all". +# +[stop-in-app] +Include the PMIX_DEBUG_STOP_IN_APP attribute in the application's +job info directing that the specified ranks stop at an application-determined +point pending release. Ranks are specified as a comma-delimited list of +ranges - e.g., "1,3-6,9", or as "all". +# +[x] +Export an environment variable, optionally specifying a value (e.g., "-x foo" exports the +environment variable foo and takes its value from the current environment; "-x foo=bar" +exports the environment variable name foo and sets its value to "bar" in the started +processes; "-x foo*" exports all current environmental variables starting with "foo") +# +[wdir] +Set the working directory of the started processes +# +[wd] +Synonym for --wdir +# +[set-cwd-to-session-dir] +Set the working directory of the started processes to their session directory +# +[path] +PATH to be used to look for executables to start processes +# +[show-progress] +Output a brief periodic report on launch progress +# +[pset] +User-specified name assigned to the processes in their given application +# +[hostfile] +Provide a hostfile +# +[machinefile] +Provide a hostfile (synonym for "hostfile") +# +[host] +Comma-separated list of hosts to invoke processes on +# +[personality] +Specify the personality to be used +# +[preload-files] +Syntax: --preload-files + +Preload the comma separated list of files to the remote machines current +working directory before starting the remote process. +# +[preload-binary] +Syntax: --preload-binary + +Preload the binary on the remote machine before starting the +remote process. +# +[output] +Comma-delimited list of options that control how output is generated. +Allowed values: + tag Mark each output line with the [job,rank] of the + process that generated it + timestamp Prefix each output line with a datetime stamp. Note + that the timestamp will be the time when the line + is output by the DVM - not the time when the source + output it + xml Format all output in XML + merge[-stderr-to-stdout] Merge stderr into stdout + dir=DIRNAME Redirect output from application processes into files of + the form DIRNAME/job/rank/std[out,err,diag]. + file=filename Redirect output from application processes into files of + the form filename.rank. + +In both the "dir" and "file" cases, the provided name will be converted to an absolute path. +Supported qualifiers include NOCOPY (i.e., output shall go only into the files - do not copy +the output to the stdout/err streams). +# +[stream-buffering] +Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 fully buffered] +# +[stdin] +Specify procs to receive stdin [rank, "all", "none"] (default: 0, indicating rank 0) +# +[map-by] +Mapping Policy for job: + slot + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node + seq + dist + ppr + rankfile +with supported colon-delimited qualifiers: + PE=y (for multiple cpus/proc) + SPAN + OVERSUBSCRIBE + NOOVERSUBSCRIBE + NOLOCAL + HWTCPUS + CORECPUS + DEVICE(for dist policy) + INHERIT + NOINHERIT + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job) + FILE= for seq and rankfile options +# +[rank-by] +Ranking Policy for job: + slot (default: np <= 2) + hwthread + core + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node +with supported colon-delimited qualifiers: + SPAN + FILL +# +[bind-to] +Binding Policy for job: + none (default: oversubscribed) + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package +with supported colon-delimited qualifiers: + overload-allowed + if-supported +# +[rankfile] +Name of file to specify explicit task mapping +# +[display] +Comma-delimited list of options for displaying information about the allocation and job. +Allowed values: + allocation + bind + map + map-devel + topo +# +[do-not-launch] +Perform all necessary operations to prepare to launch the application, but do not actually +launch it (usually used to test mapping patterns) +# +[enable-recovery] +Enable recovery from process failure [Default = disabled] +# +[max-restarts] +Max number of times to restart a failed process +# +[disable-recovery] +Disable recovery (resets all recovery options to off) +# +[continuous] +Job is to run until explicitly terminated +# +# +# DEPRECATED OPTIONS +# +[mca] +Syntax: --mca +where arg0 is the parameter name and arg1 is the parameter value + +Pass generic MCA parameters - i.e., parameters whose project affiliation +must be determined by PRRTE based on matching the name of the parameter with defined values +from various projects that PRRTE knows about. + +DEPRECATED: This translation can be incomplete (e.g., if known project adds or changes +parameters) - thus, it is strongly recommended that users use project-specific parameters +such as "prtemca" or "pmixmca". +# +[gmca] +Syntax: --gmca +where arg0 is the parameter name and arg1 is the parameter value. The "g" prefix +indicates that this parameter is to be applied to _all_ application contexts and +not just the one in which the directive appears. + +Pass generic MCA parameters - i.e., parameters whose project affiliation +must be determined by PRRTE based on matching the name of the parameter with defined values +from various projects that PRRTE knows about. This translation can be incomplete (e.g., if +a known project adds or changes parameters) - thus, it is strongly recommended that users +use project-specific parameters such as "prtemca" or "pmixmca". + +DEPRECATED: This translation can be incomplete (e.g., if known project adds or changes +parameters) - thus, it is strongly recommended that users use project-specific parameters +such as "gprtemca" or "gpmixmca". +# +[xml] +Provide all output in XML format + +DEPRECATED: please see "--help output" for details +# +[tag-output] +Tag all output with [job,rank] + +DEPRECATED: please see "--help output" for details +# +[timestamp-output] +Timestamp all application process output + +DEPRECATED: please see "--help output" for details +# +[output-directory] +Redirect output from application processes into filename/job/rank/std[out,err,diag]. A +relative path value will be converted to an absolute path. The directory name may include a +colon followed by a comma-delimited list of optional case-insensitive directives. Supported +directives currently include NOJOBID (do not include a job-id directory level) and NOCOPY +(do not copy the output to the stdout/err streams) + +DEPRECATED: please see "--help output" for details +# +[output-filename] +Redirect output from application processes into filename.rank. A relative path value will be +converted to an absolute path. The directory name may include a colon followed by a +comma-delimited list of optional case-insensitive directives. Supported directives currently +include NOCOPY (do not copy the output to the stdout/err streams) + +DEPRECATED: please see "--help output" for details +# +[merge-stderr-to-stdout] +Merge stderr to stdout for each process + +DEPRECATED: please see "--help output" for details +# +[display-devel-map] +Display a detailed process map (mostly intended for developers) +just before launch + +DEPRECATED: please see "--help display" for details +# +[display-topo] +Display the topology as part of the process map (mostly intended +for developers) just before launch + +DEPRECATED: please see "--help display" for details +# +[report-bindings] +Display process bindings to stderr + +DEPRECATED: please see "--help display" for details +# +[display-devel-allocation] +Display a detailed list (mostly intended for developers) of the +allocation being used by this job + +DEPRECATED: please see "--help display" for details +# +[display-map] +Display the process map just before launch + +DEPRECATED: please see "--help display" for details +# +[display-allocation] +Display the allocation being used by this job + +DEPRECATED: please see "--help display" for details diff --git a/src/mca/schizo/ompi/owner.txt b/src/mca/schizo/ompi/owner.txt index 85b4416d20..6b52c34f63 100644 --- a/src/mca/schizo/ompi/owner.txt +++ b/src/mca/schizo/ompi/owner.txt @@ -3,5 +3,5 @@ # owner: institution that is responsible for this package # status: e.g. active, maintenance, unmaintained # -owner: INTEL +owner: Nanook Consulting status: active diff --git a/src/mca/schizo/ompi/schizo_ompi.c b/src/mca/schizo/ompi/schizo_ompi.c index 215d561329..470a0759a4 100644 --- a/src/mca/schizo/ompi/schizo_ompi.c +++ b/src/mca/schizo/ompi/schizo_ompi.c @@ -18,7 +18,7 @@ * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2018-2021 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -59,672 +59,521 @@ #include "schizo_ompi.h" #include "src/mca/schizo/base/base.h" -static int define_cli(prte_cmd_line_t *cli); -static int check_help(prte_cmd_line_t *cli, char **argv); -static int parse_cli(int argc, int start, char **argv, char ***target); -static int parse_deprecated_cli(prte_cmd_line_t *cmdline, int *argc, char ***argv); -static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, bool cmdline); +static int parse_cli(char **argv, prte_cli_result_t *results); static int detect_proxy(char *argv); -static void allow_run_as_root(prte_cmd_line_t *cmd_line); -static void job_info(prte_cmd_line_t *cmdline, void *jobinfo); +static int parse_env(char **srcenv, char ***dstenv, prte_cli_result_t *cli); +static void allow_run_as_root(prte_cli_result_t *results); +static int setup_fork(prte_job_t *jdata, prte_app_context_t *context); +static void job_info(prte_cli_result_t *results, + void *jobinfo); prte_schizo_base_module_t prte_schizo_ompi_module = { .name = "ompi", - .define_cli = define_cli, - .check_help = check_help, .parse_cli = parse_cli, - .parse_deprecated_cli = parse_deprecated_cli, .parse_env = parse_env, + .setup_fork = setup_fork, .detect_proxy = detect_proxy, .allow_run_as_root = allow_run_as_root, - .job_info = job_info, - .check_sanity = prte_schizo_base_sanity + .job_info = job_info }; -static prte_cmd_line_init_t ompi_cmd_line_init[] = { +static struct option ompioptions[] = { /* basic options */ - {'h', "help", 0, PRTE_CMD_LINE_TYPE_BOOL, "This help message", PRTE_CMD_LINE_OTYPE_GENERAL}, - {'V', "version", 0, PRTE_CMD_LINE_TYPE_BOOL, "Print version and exit", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'v', "verbose", 0, PRTE_CMD_LINE_TYPE_BOOL, "Be verbose", PRTE_CMD_LINE_OTYPE_GENERAL}, - {'q', "quiet", 0, PRTE_CMD_LINE_TYPE_BOOL, "Suppress helpful messages", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "parsable", 0, PRTE_CMD_LINE_TYPE_BOOL, - "When used in conjunction with other parameters, the output is displayed in a " - "machine-parsable format", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "parseable", 0, PRTE_CMD_LINE_TYPE_BOOL, "Synonym for --parsable", - PRTE_CMD_LINE_OTYPE_GENERAL}, - - /* mpirun options */ - /* Specify the launch agent to be used */ - {'\0', "launch-agent", 1, PRTE_CMD_LINE_TYPE_STRING, - "Name of daemon executable used to start processes on remote nodes (default: prted)", - PRTE_CMD_LINE_OTYPE_DVM}, - /* maximum size of VM - typically used to subdivide an allocation */ - {'\0', "max-vm-size", 1, PRTE_CMD_LINE_TYPE_INT, "Number of daemons to start", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "debug-daemons", 0, PRTE_CMD_LINE_TYPE_BOOL, "Debug daemons", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-daemons-file", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Enable debugging of any PRTE daemons used by this application, storing output in files", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "leave-session-attached", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Do not discard stdout/stderr of remote PRTE daemons", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "tmpdir", 1, PRTE_CMD_LINE_TYPE_STRING, "Set the root for the session directory tree", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "prefix", 1, PRTE_CMD_LINE_TYPE_STRING, "Prefix to be used to look for RTE executables", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "noprefix", 0, PRTE_CMD_LINE_TYPE_BOOL, "Disable automatic --prefix behavior", - PRTE_CMD_LINE_OTYPE_DVM}, - - /* setup MCA parameters */ - {'\0', "omca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific OMPI MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "gomca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass global OMPI MCA parameters that are applicable to all contexts (arg0 is the parameter " - "name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "mca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific MCA parameters; they are considered global if --gmca is not used and " - "only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* setup MCA parameters */ - {'\0', "prtemca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific PRTE MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "pmixmca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific PMIx MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "gpmixmca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass global PMIx MCA parameters that are applicable to all contexts (arg0 is the parameter " - "name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "tune", 1, PRTE_CMD_LINE_TYPE_STRING, - "File(s) containing MCA params for tuning DVM operations", PRTE_CMD_LINE_OTYPE_DVM}, - - /* forward signals */ - {'\0', "forward-signals", 1, PRTE_CMD_LINE_TYPE_STRING, - "Comma-delimited list of additional signals (names or integers) to forward to " - "application processes [\"none\" => forward nothing]. Signals provided by " - "default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT", - PRTE_CMD_LINE_OTYPE_DVM}, - - {'\0', "debug", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Top-level PRTE debug switch (default: false) " - "This CLI option will be deprecated starting in Open MPI v5", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-verbose", 1, PRTE_CMD_LINE_TYPE_INT, - "Verbosity level for PRTE debug messages (default: 1)", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'d', "debug-devel", 0, PRTE_CMD_LINE_TYPE_BOOL, "Enable debugging of PRTE", - PRTE_CMD_LINE_OTYPE_DEBUG}, - - {'\0', "timeout", 1, PRTE_CMD_LINE_TYPE_INT, - "Timeout the job after the specified number of seconds", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "report-state-on-timeout", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Report all job and process states upon timeout", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "get-stack-traces", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Get stack traces of all application procs on timeout", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PRTE_ARG_NONE, 'v'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSEABLE, PRTE_ARG_NONE, 'p'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSABLE, PRTE_ARG_NONE, 'p'), // synonym for parseable + PRTE_OPTION_DEFINE(PRTE_CLI_PERSONALITY, PRTE_ARG_REQD), + + // MCA parameters + PRTE_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("omca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("gomca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TUNE, PRTE_ARG_REQD), + + PRTE_OPTION_DEFINE(PRTE_CLI_LAUNCH_AGENT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_MAX_VM_SIZE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS_FILE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_LEAVE_SESSION_ATTACHED, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_TMPDIR, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PREFIX, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NOPREFIX, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_FWD_SIGNALS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_RUN_AS_ROOT, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_CHILD_SEP, PRTE_ARG_NONE), + + /* debug options */ + PRTE_OPTION_DEFINE(PRTE_CLI_XTERM, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_ON_EXEC, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_IN_INIT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_IN_APP, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TIMEOUT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_STATE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_STACK_TRACES, PRTE_ARG_NONE), #ifdef PMIX_SPAWN_TIMEOUT - {'\0', "spawn-timeout", 1, PRTE_CMD_LINE_TYPE_INT, - "Timeout the job if spawn takes more than the specified number of seconds", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_SPAWN_TIMEOUT, PRTE_ARG_REQD), #endif - {'\0', "allow-run-as-root", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Allow execution as root (STRONGLY DISCOURAGED)", PRTE_CMD_LINE_OTYPE_DVM}, /* End of list */ - /* fwd mpirun port */ - {'\0', "fwd-mpirun-port", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Forward mpirun port to compute node daemons so all will use it", PRTE_CMD_LINE_OTYPE_DVM}, - /* Conventional options - for historical compatibility, support * both single and multi dash versions */ /* Number of processes; -c, -n, --n, -np, and --np are all synonyms */ - {'c', "np", 1, PRTE_CMD_LINE_TYPE_INT, "Number of processes to run", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'n', "n", 1, PRTE_CMD_LINE_TYPE_INT, "Number of processes to run", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'N', NULL, 1, PRTE_CMD_LINE_TYPE_INT, "Number of processes to run per node", - PRTE_CMD_LINE_OTYPE_GENERAL}, - /* Use an appfile */ - {'\0', "app", 1, PRTE_CMD_LINE_TYPE_STRING, - "Provide an appfile; ignore all other command line options", PRTE_CMD_LINE_OTYPE_GENERAL}, + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'n'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'c'), + PRTE_OPTION_DEFINE("n", PRTE_ARG_REQD), // will be converted to "np" after parsing + PRTE_OPTION_SHORT_DEFINE("N", PRTE_ARG_REQD, 'N'), + PRTE_OPTION_DEFINE("app", PRTE_ARG_REQD), /* output options */ - {'\0', "output", 1, PRTE_CMD_LINE_TYPE_STRING, - "Comma-delimited list of options that control how output is generated." - "Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, dir=DIRNAME, file=filename." - " The dir option redirects output from application processes into DIRNAME/job/rank/std[out,err,diag]." - " The file option redirects output from application processes into filename.rank. In both cases, " - "the provided name will be converted to an absolute path. Supported qualifiers include NOCOPY" - " (do not copy the output to the stdout/err streams).", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - /* exit status reporting */ - {'\0', "report-child-jobs-separately", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Return the exit status of the primary job only", PRTE_CMD_LINE_OTYPE_OUTPUT}, - /* select XML output */ - {'\0', "xml", 0, PRTE_CMD_LINE_TYPE_BOOL, "Provide all output in XML format", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - /* tag output */ - {'\0', "tag-output", 0, PRTE_CMD_LINE_TYPE_BOOL, "Tag all output with [job,rank]", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "timestamp-output", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Timestamp all application process output", PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "output-directory", 1, PRTE_CMD_LINE_TYPE_STRING, - "Redirect output from application processes into filename/job/rank/std[out,err,diag]. A " - "relative path value will be converted to an absolute path. The directory name may include a " - "colon followed by a comma-delimited list of optional case-insensitive directives. Supported " - "directives currently include NOJOBID (do not include a job-id directory level) and NOCOPY " - "(do not copy the output to the stdout/err streams)", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "output-filename", 1, PRTE_CMD_LINE_TYPE_STRING, - "Redirect output from application processes into filename.rank. A relative path value will be " - "converted to an absolute path. The directory name may include a colon followed by a " - "comma-delimited list of optional case-insensitive directives. Supported directives currently " - "include NOCOPY (do not copy the output to the stdout/err streams)", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "merge-stderr-to-stdout", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Merge stderr to stdout for each process", PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "xterm", 1, PRTE_CMD_LINE_TYPE_STRING, - "Create a new xterm window and display output from the specified ranks there", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "stream-buffering", 1, PRTE_CMD_LINE_TYPE_STRING, - "Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 fully buffered]", - PRTE_CMD_LINE_OTYPE_LAUNCH}, + PRTE_OPTION_DEFINE(PRTE_CLI_OUTPUT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STREAM_BUF, PRTE_ARG_REQD), /* input options */ - /* select stdin option */ - {'\0', "stdin", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify procs to receive stdin [rank, all, none] (default: 0, indicating rank 0)", - PRTE_CMD_LINE_OTYPE_INPUT}, - - /* debugger options */ - {'\0', "output-proctable", 1, PRTE_CMD_LINE_TYPE_STRING, - "Print the complete proctable to stdout [-], stderr [+], or a file [anything else] after " - "launch", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "stop-on-exec", 0, PRTE_CMD_LINE_TYPE_BOOL, - "If supported, stop each process at start of execution", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_STDIN, PRTE_ARG_REQD), + /* launch options */ - /* Preload the binary on the remote machine */ - {'s', "preload-binary", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Preload the binary on the remote machine before starting the remote process.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* Preload files on the remote machine */ - {'\0', "preload-files", 1, PRTE_CMD_LINE_TYPE_STRING, - "Preload the comma separated list of files to the remote machines current working directory " - "before starting the remote process.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* Export environment variables; potentially used multiple times, - so it does not make sense to set into a variable */ - {'x', NULL, 1, PRTE_CMD_LINE_TYPE_STRING, - "Export an environment variable, optionally specifying a value (e.g., \"-x foo\" exports the " - "environment variable foo and takes its value from the current environment; \"-x foo=bar\" " - "exports the environment variable name foo and sets its value to \"bar\" in the started " - "processes; \"-x foo*\" exports all current environmental variables starting with \"foo\")", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "wdir", 1, PRTE_CMD_LINE_TYPE_STRING, - "Set the working directory of the started processes", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "wd", 1, PRTE_CMD_LINE_TYPE_STRING, "Synonym for --wdir", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "set-cwd-to-session-dir", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Set the working directory of the started processes to their session directory", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "path", 1, PRTE_CMD_LINE_TYPE_STRING, - "PATH to be used to look for executables to start processes", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "show-progress", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Output a brief periodic report on launch progress", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "pset", 1, PRTE_CMD_LINE_TYPE_STRING, - "User-specified name assigned to the processes in their given application", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* Set a hostfile */ - {'\0', "hostfile", 1, PRTE_CMD_LINE_TYPE_STRING, "Provide a hostfile", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "machinefile", 1, PRTE_CMD_LINE_TYPE_STRING, "Provide a hostfile", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "default-hostfile", 1, PRTE_CMD_LINE_TYPE_STRING, "Provide a default hostfile", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'H', "host", 1, PRTE_CMD_LINE_TYPE_STRING, "List of hosts to invoke processes on", - PRTE_CMD_LINE_OTYPE_LAUNCH}, + PRTE_OPTION_DEFINE(PRTE_CLI_PRELOAD_FILES, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PRELOAD_BIN, PRTE_ARG_NONE, 's'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_FWD_ENVAR, PRTE_ARG_REQD, 'x'), + PRTE_OPTION_DEFINE(PRTE_CLI_WDIR, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("wd", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PATH, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PSET, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("machinefile", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DEFAULT_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HOST, PRTE_ARG_REQD, 'H'), /* placement options */ /* Mapping options */ - {'\0', "map-by", 1, PRTE_CMD_LINE_TYPE_STRING, - "Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache | " - "l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | ppr |," - "rankfile]" - " with supported colon-delimited modifiers: PE=y (for multiple cpus/proc), " - "SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, HWTCPUS, CORECPUS, " - "DEVICE(for dist policy), INHERIT, NOINHERIT, PE-LIST=a,b (comma-delimited " - "ranges of cpus to use for this job), FILE= for seq and rankfile options", - PRTE_CMD_LINE_OTYPE_MAPPING}, + PRTE_OPTION_DEFINE(PRTE_CLI_MAPBY, PRTE_ARG_REQD), /* Ranking options */ - {'\0', "rank-by", 1, PRTE_CMD_LINE_TYPE_STRING, - "Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache " - "| l2cache | l3cache | numa (default:np>2) | package | node], with modifier :SPAN or :FILL", - PRTE_CMD_LINE_OTYPE_RANKING}, + PRTE_OPTION_DEFINE(PRTE_CLI_RANKBY, PRTE_ARG_REQD), /* Binding options */ - {'\0', "bind-to", 1, PRTE_CMD_LINE_TYPE_STRING, - "Binding policy for job. Allowed values: none, hwthread, core, l1cache, l2cache, " - "l3cache, numa, package, (\"none\" is the default when oversubscribed, \"core\" is " - "the default when np<=2, and \"numa\" is the default when np>2). Allowed colon-delimited " - "qualifiers: " - "overload-allowed, if-supported", - PRTE_CMD_LINE_OTYPE_BINDING}, - - /* rankfile */ - {'\0', "rankfile", 1, PRTE_CMD_LINE_TYPE_STRING, - "Name of file to specify explicit task mapping", PRTE_CMD_LINE_OTYPE_LAUNCH}, + PRTE_OPTION_DEFINE(PRTE_CLI_BINDTO, PRTE_ARG_REQD), /* display options */ - {'\0', "display", 1, PRTE_CMD_LINE_TYPE_STRING, - "Comma-delimited list of options for displaying information about the allocation and job." - "Allowed values: allocation, bind, map, map-devel, topo", - PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_DISPLAY, PRTE_ARG_REQD), + /* developer options */ - {'\0', "do-not-launch", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Perform all necessary operations to prepare to launch the application, but do not actually " - "launch it (usually used to test mapping patterns)", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-devel-map", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display a detailed process map (mostly intended for developers) just before launch", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-topo", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display the topology as part of the process map (mostly intended for developers) just before " - "launch", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "report-bindings", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Whether to report process bindings to stderr", PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-devel-allocation", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display a detailed list (mostly intended for developers) of the allocation being used by " - "this job", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-map", 0, PRTE_CMD_LINE_TYPE_BOOL, "Display the process map just before launch", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "display-allocation", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display the allocation being used by this job", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PRTE_ARG_REQD), + #if PRTE_ENABLE_FT - {'\0', "enable-recovery", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Enable recovery from process failure [Default = disabled]", PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "max-restarts", 1, PRTE_CMD_LINE_TYPE_INT, - "Max number of times to restart a failed process", PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "disable-recovery", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Disable recovery (resets all recovery options to off)", PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "continuous", 0, PRTE_CMD_LINE_TYPE_BOOL, "Job is to run until explicitly terminated", - PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "with-ft", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify the type(s) of error handling that the application will use.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, + PRTE_OPTION_DEFINE("enable-recovery", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("max-restarts", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("disable-recovery", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("continuous", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("with-ft", PRTE_ARG_REQD), #endif /* mpiexec mandated form launch key parameters */ - {'\0', "initial-errhandler", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify the initial error handler that is attached to predefined communicators during the " - "first MPI call.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, + PRTE_OPTION_DEFINE("initial-errhandler", PRTE_ARG_REQD), /* Display Commumication Protocol : MPI_Init */ - {'\0', "display-comm", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display table of communication methods between ranks during MPI_Init", - PRTE_CMD_LINE_OTYPE_GENERAL}, + PRTE_OPTION_DEFINE("display-comm", PRTE_ARG_NONE), /* Display Commumication Protocol : MPI_Finalize */ - {'\0', "display-comm-finalize", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display table of communication methods between ranks during MPI_Finalize", - PRTE_CMD_LINE_OTYPE_GENERAL}, + PRTE_OPTION_DEFINE("display-comm-finalize", PRTE_ARG_NONE), + + // unsupported, but mandated options + PRTE_OPTION_DEFINE("soft", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("arch", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("file", PRTE_ARG_REQD), + + // deprecated options + PRTE_OPTION_DEFINE("mca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("gmca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("xml", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("tag-output", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("timestamp-output", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("output-directory", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("output-filename", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("merge-stderr-to-stdout", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-topo", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("report-bindings", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("nolocal", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("oversubscribe", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("nooversubscribe", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("use-hwthread-cpus", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("cpu-set", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("cpu-list", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("--bind-to-core", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("bynode", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("bycore", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("byslot", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("cpus-per-proc", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("cpus-per-rank", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("npernode", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("pernode", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("npersocket", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("ppr", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("amca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("am", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("rankfile", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("output-proctable", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("debug", PRTE_ARG_NONE), + + PRTE_OPTION_END +}; +static char *ompishorts = "h::vVpn:c:sHx:"; - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; +static int convert_deprecated_cli(prte_cli_result_t *results); -static int define_cli(prte_cmd_line_t *cli) +static int parse_cli(char **argv, prte_cli_result_t *results) { - int rc; - - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:ompi: define_cli", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); + int rc, n; + prte_cli_item_t *opt; + char *p1; + + /* handle the non-compliant options - i.e., the single-dash + * multi-character options mandated by the MPI standard */ + for (n=0; NULL != argv[n]; n++) { + if (0 == strcmp(argv[n], "-soft")) { + free(argv[n]); + argv[n] = strdup("--soft"); + } else if (0 == strcmp(argv[n], "-host")) { + free(argv[n]); + argv[n] = strdup("--host"); + } else if (0 == strcmp(argv[n], "-arch")) { + free(argv[n]); + argv[n] = strdup("--arch"); + } else if (0 == strcmp(argv[n], "-wdir")) { + free(argv[n]); + argv[n] = strdup("--wdir"); + } else if (0 == strcmp(argv[n], "-path")) { + free(argv[n]); + argv[n] = strdup("--path"); + } else if (0 == strcmp(argv[n], "-file")) { + free(argv[n]); + argv[n] = strdup("--file"); + } else if (0 == strcmp(argv[n], "-initial-errhandler")) { + free(argv[n]); + argv[n] = strdup("--initial-errhandler"); + } else if (0 == strcmp(argv[n], "-np")) { + free(argv[n]); + argv[n] = strdup("--np"); + } +#if PRTE_ENABLE_FT + else if (0 == strcmp(argv[n], "-with-ft")) { + free(argv[n]); + argv[n] = strdup("--with-ft"); + } +#endif + } - /* protect against bozo error */ - if (NULL == cli) { - return PRTE_ERR_BAD_PARAM; + rc = prte_cmd_line_parse(argv, ompishorts, ompioptions, NULL, + results, "help-schizo-ompi.txt"); + if (PRTE_SUCCESS != rc) { + return rc; } - rc = prte_cmd_line_add(cli, ompi_cmd_line_init); - return rc; -} + /* check for deprecated options - warn and convert them */ + rc = convert_deprecated_cli(results); + if (PRTE_SUCCESS != rc) { + return rc; + } -static int check_help(prte_cmd_line_t *cli, char **argv) -{ - if (prte_cmd_line_is_taken(cli, "help")) { - char *str, *args = NULL; - args = prte_cmd_line_get_usage_msg(cli, false); - str = prte_show_help_string("help-prun.txt", "prun:usage", false, prte_tool_basename, - "PRTE", PRTE_VERSION, prte_tool_basename, args, - PACKAGE_BUGREPORT); - if (NULL != str) { - printf("%s", str); - free(str); - } - free(args); - - /* If someone asks for help, that should be all we do */ - return PRTE_ERR_SILENT; + // handle relevant MCA params + PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { + if (0 == strcmp(opt->key, "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, "pmixmca")) { + for (n=0; NULL != opt->values[n]; n++) { + p1 = opt->values[n]; + prte_schizo_base_expose(p1, "PMIX_MCA_"); + } +#if PRTE_ENABLE_FT + } else if (0 == strcmp(opt->key, "with-ft")) { + if (NULL == opt->values || NULL == opt->values[0]) { + /* this is an error */ + return PRTE_ERR_FATAL; + } + 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)) { + /* push it into our environment */ + prte_schizo_base_expose("prte_enable_ft=1", "PRTE_MCA_"); + prte_output_verbose(1, prte_schizo_base_framework.framework_output, + "%s schizo:ompi:parse_cli pushing PRTE_MCA_prte_enable_ft=1 into environment", + PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); + prte_enable_recovery = true; + prte_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), param); + prte_schizo_base_expose("mpi_ft_enable=1", "OMPI_MCA_"); + } + } + else { + prte_output(0, "UNRECOGNIZED OPTION: --with-ft %s", p1); + return PRTE_ERR_FATAL; + } + } +#endif + } } return PRTE_SUCCESS; -} +}; -static int convert_deprecated_cli(char *option, char ***argv, int i) +static int convert_deprecated_cli(prte_cli_result_t *results) { - char **pargs, *p1, *p2, *tmp, *tmp2, *output, *modifier; + char *option, *p1, *p2, *tmp, *tmp2, *output, *modifier; int rc = PRTE_SUCCESS; - - pargs = *argv; - - /* --nolocal -> --map-by :nolocal */ - if (0 == strcmp(option, "--nolocal")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", NULL, "NOLOCAL", true); - } - /* --oversubscribe -> --map-by :OVERSUBSCRIBE - * --nooversubscribe -> --map-by :NOOVERSUBSCRIBE - */ - else if (0 == strcmp(option, "--oversubscribe") || 0 == strcmp(option, "--nooversubscribe")) { - if (0 == strcmp(option, "--nooversubscribe")) { - prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, - "This is the default behavior so does not need to be specified"); - modifier = "NOOVERSUBSCRIBE"; - } else { - modifier = "OVERSUBSCRIBE"; + prte_cli_item_t *opt; + prte_value_t *pval, val; + + PRTE_LIST_FOREACH(opt, &results->instances, prte_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, "np", opt->values[0], false); } - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", NULL, modifier, true); - } - /* --use-hwthread-cpus -> --bind-to hwthread */ - else if (0 == strcmp(option, "--use-hwthread-cpus")) { - rc = prte_schizo_base_convert(argv, i, 1, "--bind-to", "hwthread", NULL, true); - } - /* --cpu-set and --cpu-list -> --map-by pe-list:X - */ - else if (0 == strcmp(option, "--cpu-set") || 0 == strcmp(option, "--cpu-list")) { - prte_asprintf(&p2, "PE-LIST=%s", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", NULL, p2, true); - free(p2); - } - /* --bind-to-core and --bind-to-socket -> --bind-to X */ - else if (0 == strcmp(option, "--bind-to-core")) { - rc = prte_schizo_base_convert(argv, i, 1, "--bind-to", "core", NULL, true); - } else if (0 == strcmp(option, "--bind-to-socket")) { - rc = prte_schizo_base_convert(argv, i, 1, "--bind-to", "socket", NULL, true); - } - /* --bynode -> "--map-by X --rank-by X" */ - else if (0 == strcmp(option, "--bynode")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", "node", NULL, true); - if (PRTE_SUCCESS != rc) { - return rc; + /* --nolocal -> --map-by :nolocal */ + else if (0 == strcmp(option, "nolocal")) { + rc = prte_schizo_base_add_qualifier(results, option, "map-by", "NOLOCAL", true); } - } - /* --bycore -> "--map-by X --rank-by X" */ - else if (0 == strcmp(option, "--bycore")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", "core", NULL, true); - if (PRTE_SUCCESS != rc) { - return rc; + /* --oversubscribe -> --map-by :OVERSUBSCRIBE */ + else if (0 == strcmp(option, "oversubscribe")) { + rc = prte_schizo_base_add_qualifier(results, option, "map-by", "OVERSUBSCRIBE", true); } - } - /* --byslot -> "--map-by X --rank-by X" */ - else if (0 == strcmp(option, "--byslot")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", "slot", NULL, true); - if (PRTE_SUCCESS != rc) { - return rc; + /* --nooversubscribe -> --map-by :NOOVERSUBSCRIBE */ + else if (0 == strcmp(option, "nooversubscribe")) { + rc = prte_schizo_base_add_qualifier(results, option, "map-by", "NOOVERSUBSCRIBE", true); } - } - /* --cpus-per-proc/rank X -> --map-by :pe=X */ - else if (0 == strcmp(option, "--cpus-per-proc") || 0 == strcmp(option, "--cpus-per-rank")) { - prte_asprintf(&p2, "pe=%s", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", NULL, p2, true); - free(p2); - } - /* -N -> map-by ppr:N:node */ - else if (0 == strcmp(option, "-N")) { - prte_asprintf(&p2, "ppr:%s:node", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", p2, NULL, true); - free(p2); - } - /* --npernode X and --npersocket X -> --map-by ppr:X:node/socket */ - else if (0 == strcmp(option, "--npernode")) { - prte_asprintf(&p2, "ppr:%s:node", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", p2, NULL, true); - free(p2); - } else if (0 == strcmp(option, "--pernode")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", "ppr:1:node", NULL, true); - } else if (0 == strcmp(option, "--npersocket")) { - prte_asprintf(&p2, "ppr:%s:socket", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", p2, NULL, true); - free(p2); - } - /* --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(pargs[i + 1], ':')) { - prte_show_help("help-schizo-base.txt", "bad-ppr", true, pargs[i + 1], true); - return PRTE_ERR_BAD_PARAM; - } - prte_asprintf(&p2, "ppr:%s", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", p2, NULL, true); - free(p2); - } - /* --am[ca] X -> --tune X */ - else if (0 == strcmp(option, "--amca") || 0 == strcmp(option, "--am")) { - rc = prte_schizo_base_convert(argv, i, 2, "--tune", NULL, NULL, true); - } - /* --tune X -> aggregate */ - else if (0 == strcmp(option, "--tune")) { - rc = prte_schizo_base_convert(argv, i, 2, "--tune", NULL, NULL, true); - } - /* --rankfile X -> map-by rankfile:file=X */ - else if (0 == strcmp(option, "--rankfile")) { - prte_asprintf(&p2, "file=%s", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", "rankfile", p2, false); - free(p2); - rc = PRTE_ERR_SILENT; - } - /* --tag-output -> "--output tag */ - else if (0 == strcmp(option, "--tag-output")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", NULL, "tag", true); - } - /* --timestamp-output -> --output timestamp */ - else if (0 == strcmp(option, "--timestamp-output")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", NULL, "timestamp", true); - } - /* --output-directory DIR -> --output dir=DIR */ - else if (0 == strcmp(option, "--output-directory")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", "dir", pargs[i + 1], true); - } - /* --output-filename DIR -> --output file=file */ - else if (0 == strcmp(option, "--output-filename")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", "file", pargs[i + 1], true); - } - /* --xml -> --output xml */ - else if (0 == strcmp(option, "--xml")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", NULL, "xml", true); - } - /* --display-devel-map -> --display allocation-devel */ - else if (0 == strcmp(option, "--display-devel-map")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "map-devel", true); - } - /* --output-proctable -> --display map-devel */ - else if (0 == strcmp(option, "--output-proctable")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "map-devel", true); - } - /* --display-map -> --display map */ - else if (0 == strcmp(option, "--display-map")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "map", true); - } - /* --display-topo -> --display topo */ - else if (0 == strcmp(option, "--display-topo")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "topo", true); - } - /* --report-bindings -> --display bind */ - else if (0 == strcmp(option, "--report-bindings")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "bind", true); - } - /* --display-allocation -> --display allocation */ - else if (0 == strcmp(option, "--display-allocation")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "allocation", true); - } - /* --debug will be deprecated starting with open mpi v5 - */ - else if (0 == strcmp(option, "--debug")) { - prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, - "This CLI option will be deprecated starting in Open MPI v5"); - rc = PRTE_ERR_TAKE_NEXT_OPTION; - } - /* --map-by socket -> --map-by package */ - else if (0 == strcmp(option, "--map-by")) { - /* check the value of the option for "socket" */ - if (0 == strncasecmp(pargs[i + 1], "socket", strlen("socket"))) { - p1 = strdup(pargs[i + 1]); // save the original option - /* replace "socket" with "package" */ - if (NULL == (p2 = strchr(pargs[i + 1], ':'))) { - /* no modifiers */ - tmp = strdup("package"); - } else { - *p2 = '\0'; - ++p2; - prte_asprintf(&tmp, "package:%s", p2); - } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); - free(p1); + /* --use-hwthread-cpus -> --bind-to hwthread */ + else if (0 == strcmp(option, "use-hwthread-cpus")) { + rc = prte_schizo_base_add_directive(results, option, "bind-to", "hwthread", true); + } + /* --cpu-set and --cpu-list -> --map-by pe-list:X + */ + else if (0 == strcmp(option, "cpu-set") || 0 == strcmp(option, "cpu-list")) { + prte_asprintf(&p2, "PE-LIST=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; } - rc = PRTE_OPERATION_SUCCEEDED; - } - /* --rank-by socket -> --rank-by package */ - else if (0 == strcmp(option, "--rank-by")) { - /* check the value of the option for "socket" */ - if (0 == strncasecmp(pargs[i + 1], "socket", strlen("socket"))) { - p1 = strdup(pargs[i + 1]); // save the original option - /* replace "socket" with "package" */ - if (NULL == (p2 = strchr(pargs[i + 1], ':'))) { - /* no modifiers */ - tmp = strdup("package"); - } else { - *p2 = '\0'; - ++p2; - prte_asprintf(&tmp, "package:%s", p2); - } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); - free(p1); + /* --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, "bind-to", "core", true); + } else if (0 == strcmp(option, "bind-to-socket")) { + rc = prte_schizo_base_add_directive(results, option, "bind-to", "socket", true); + } + /* --bynode -> "--map-by X --rank-by X" */ + else if (0 == strcmp(option, "bynode")) { + rc = prte_schizo_base_add_directive(results, option, "map-by", "node", true); + } + /* --bycore -> "--map-by X --rank-by X" */ + else if (0 == strcmp(option, "bycore")) { + rc = prte_schizo_base_add_directive(results, option, "map-by", "core", true); + } + /* --byslot -> "--map-by X --rank-by X" */ + else if (0 == strcmp(option, "byslot")) { + rc = prte_schizo_base_add_directive(results, option, "map-by", "slot", true); + } + /* --cpus-per-proc/rank X -> --map-by :pe=X */ + else if (0 == strcmp(option, "cpus-per-proc") || 0 == strcmp(option, "cpus-per-rank")) { + prte_asprintf(&p2, ":pe=%s", opt->values[0]); + rc = prte_schizo_base_add_qualifier(results, option, "map-by", p2, true); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; } - rc = PRTE_OPERATION_SUCCEEDED; - } - /* --bind-to socket -> --bind-to package */ - else if (0 == strcmp(option, "--bind-to")) { - /* check the value of the option for "socket" */ - if (0 == strncasecmp(pargs[i + 1], "socket", strlen("socket"))) { - p1 = strdup(pargs[i + 1]); // save the original option - /* replace "socket" with "package" */ - if (NULL == (p2 = strchr(pargs[i + 1], ':'))) { - /* no modifiers */ - tmp = strdup("package"); - } else { - *p2 = '\0'; - ++p2; - prte_asprintf(&tmp, "package:%s", p2); + /* -N -> map-by ppr:N:node */ + else if (0 == strcmp(option, "N")) { + prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + free(p2); + } + /* --npernode X and --npersocket X -> --map-by ppr:X:node/socket */ + else if (0 == strcmp(option, "npernode")) { + prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + free(p2); + } else if (0 == strcmp(option, "pernode")) { + rc = prte_schizo_base_add_directive(results, option, "map-by", "ppr:1:node", true); + } else if (0 == strcmp(option, "npersocket")) { + prte_asprintf(&p2, "ppr:%s:socket", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + free(p2); + } + /* --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], ':')) { + prte_show_help("help-schizo-base.txt", "bad-ppr", true, opt->values[0], true); + return PRTE_ERR_SILENT; } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); - free(p1); + prte_asprintf(&p2, "ppr:%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + free(p2); + } + /* --am[ca] X -> --tune X */ + else if (0 == strcmp(option, "amca") || 0 == strcmp(option, "am")) { + rc = prte_schizo_base_add_directive(results, option, "tune", opt->values[0], true); + } + /* --rankfile X -> map-by rankfile:file=X */ + else if (0 == strcmp(option, "rankfile")) { + prte_asprintf(&p2, "file=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; } - rc = PRTE_OPERATION_SUCCEEDED; + /* --tag-output -> "--output tag */ + else if (0 == strcmp(option, "tag-output")) { + rc = prte_schizo_base_add_directive(results, option, "output", "tag", true); + } + /* --timestamp-output -> --output timestamp */ + else if (0 == strcmp(option, "timestamp-output")) { + rc = prte_schizo_base_add_directive(results, option, "output", "timestamp", true); + } + /* --output-directory DIR -> --output dir=DIR */ + else if (0 == strcmp(option, "output-directory")) { + prte_asprintf(&p2, "dir=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "output", p2, true); + free(p2); + } + /* --output-filename DIR -> --output file=file */ + else if (0 == strcmp(option, "--output-filename")) { + prte_asprintf(&p2, "file=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, "output", p2, true); + free(p2); + } + /* --xml -> --output xml */ + else if (0 == strcmp(option, "xml")) { + rc = prte_schizo_base_add_directive(results, option, "output", "xml", true); + } + /* --display-devel-map -> --display allocation-devel */ + else if (0 == strcmp(option, "display-devel-map")) { + rc = prte_schizo_base_add_directive(results, option, "display", "map-devel", true); + } + /* --output-proctable -> --display map-devel */ + else if (0 == strcmp(option, "output-proctable")) { + rc = prte_schizo_base_add_directive(results, option, "display", "map-devel", true); + } + /* --display-map -> --display map */ + else if (0 == strcmp(option, "display-map")) { + rc = prte_schizo_base_add_directive(results, option, "display", "map", true); + } + /* --display-topo -> --display topo */ + else if (0 == strcmp(option, "display-topo")) { + rc = prte_schizo_base_add_directive(results, option, "display", "topo", true); + } + /* --report-bindings -> --display bind */ + else if (0 == strcmp(option, "report-bindings")) { + rc = prte_schizo_base_add_directive(results, option, "display", "bind", true); + } + /* --display-allocation -> --display allocation */ + else if (0 == strcmp(option, "display-allocation")) { + rc = prte_schizo_base_add_directive(results, option, "display", "allocation", true); + } + /* --debug will be deprecated starting with open mpi v5 + */ + else if (0 == strcmp(option, "debug")) { + prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, + "This CLI option will be deprecated starting in Open MPI v5"); + } + /* --map-by socket -> --map-by package */ + else if (0 == strcmp(option, "map-by")) { + /* 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; + prte_asprintf(&tmp, "package:%s", p2); + } + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p1); + free(p2); + free(tmp2); + free(opt->values[0]); + opt->values[0] = tmp; + } + } + /* --rank-by socket -> --rank-by package */ + else if (0 == strcmp(option, "--rank-by")) { + /* 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; + prte_asprintf(&tmp, "package:%s", p2); + } + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p1); + free(p2); + free(tmp2); + free(opt->values[0]); + opt->values[0] = tmp; + } + } + /* --bind-to socket -> --bind-to package */ + else if (0 == strcmp(option, "--bind-to")) { + /* 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; + prte_asprintf(&tmp, "package:%s", p2); + } + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p1); + free(p2); + free(tmp2); + free(opt->values[0]); + opt->values[0] = tmp; + } + } } return rc; } -static int parse_deprecated_cli(prte_cmd_line_t *cmdline, int *argc, char ***argv) -{ - pmix_status_t rc; - - char *options[] = {"--nolocal", - "--oversubscribe", - "--nooversubscribe", - "--use-hwthread-cpus", - "--cpu-set", - "--cpu-list", - "--bind-to-core", - "--bind-to-socket", - "--bynode", - "--bycore", - "--byslot", - "--cpus-per-proc", - "--cpus-per-rank", - "-N", - "--npernode", - "--pernode", - "--npersocket", - "--ppr", - "--amca", - "--am", - "--rankfile", - "--display-devel-map", - "--display-map", - "--display-topo", - "--display-diff", - "--report-bindings", - "--display-allocation", - "--tag-output", - "--timestamp-output", - "--xml", - "--output-proctable", - "--output-filename", - "--output-directory", - "--debug", - "--map-by", - "--rank-by", - "--bind-to", - NULL}; - - rc = prte_schizo_base_process_deprecated_cli(cmdline, argc, argv, options, - false, convert_deprecated_cli); - - return rc; -} - static int check_cache_noadd(char ***c1, char ***c2, char *p1, char *p2) { char **cache; @@ -1050,8 +899,7 @@ static int process_tune_files(char *filename, char ***dstenv, char sep) return rc; } n += 2; // skip over the MCA option - } else if (0 - == strncmp(opts[n], "mca_base_env_list", strlen("mca_base_env_list"))) { + } 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) { @@ -1202,156 +1050,26 @@ static bool check_generic(char *p1) return false; } -static int parse_cli(int argc, int start, char **argv, char ***target) -{ - char *p1, *p2; - int i; - bool takeus; - char *param = NULL; - - prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:ompi: parse_cli", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); - - for (i = 0; i < (argc - start); ++i) { - if (0 == strcmp("--omca", argv[i])) { - if (NULL == argv[i + 1] || NULL == argv[i + 2]) { - /* this is an error */ - return PRTE_ERR_FATAL; - } - p1 = prte_schizo_base_strip_quotes(argv[i + 1]); - p2 = prte_schizo_base_strip_quotes(argv[i + 2]); - if (NULL == target) { - /* push it into our environment */ - asprintf(¶m, "OMPI_MCA_%s", p1); - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:ompi:parse_cli pushing %s into environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, p2, true, &environ); - } else { - prte_argv_append_nosize(target, "--omca"); - prte_argv_append_nosize(target, p1); - prte_argv_append_nosize(target, p2); - } - free(p1); - free(p2); - i += 2; - continue; - } - if (0 == strcmp("--mca", argv[i])) { - if (NULL == argv[i + 1] || NULL == argv[i + 2]) { - /* this is an error */ - return PRTE_ERR_FATAL; - } - p1 = prte_schizo_base_strip_quotes(argv[i + 1]); - p2 = prte_schizo_base_strip_quotes(argv[i + 2]); - - /* this is a generic MCA designation, so see if the parameter it - * refers to belongs to one of our frameworks */ - takeus = check_generic(p1); - if (takeus) { - if (NULL == target) { - /* push it into our environment */ - prte_asprintf(¶m, "OMPI_MCA_%s", p1); - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:ompi:parse_cli pushing %s into environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, p2, true, &environ); - } else { - prte_argv_append_nosize(target, "--omca"); - prte_argv_append_nosize(target, p1); - prte_argv_append_nosize(target, p2); - } - } - free(p1); - free(p2); - i += 2; - continue; - } - if (0 == strcmp("--map-by", argv[i])) { - /* if they set "inherit", then make this the default for prte */ - if (NULL != strcasestr(argv[i + 1], "inherit") - && NULL == strcasestr(argv[i + 1], "noinherit")) { - if (NULL == target) { - /* push it into our environment */ - prte_setenv("PRTE_MCA_rmaps_default_inherit", "1", true, &environ); - prte_setenv("PRTE_MCA_rmaps_default_mapping_policy", argv[i + 1], true, - &environ); - } else { - prte_argv_append_nosize(target, "--prtemca"); - prte_argv_append_nosize(target, "rmaps_default_inherit"); - prte_argv_append_nosize(target, "1"); - prte_argv_append_nosize(target, "--prtemca"); - prte_argv_append_nosize(target, "rmaps_default_mapping_policy"); - prte_argv_append_nosize(target, argv[i + 1]); - } - } - } - -#if PRTE_ENABLE_FT - if (0 == strcmp("--with-ft", argv[i]) || 0 == strcmp("-with-ft", argv[i])) { - if (NULL == argv[i + 1]) { - /* this is an error */ - return PRTE_ERR_FATAL; - } - p1 = prte_schizo_base_strip_quotes(argv[i + 1]); - 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)) { - if (NULL == target) { - /* push it into our environment */ - prte_asprintf(¶m, "PRTE_MCA_prte_enable_ft"); - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:ompi:parse_cli pushing %s into environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, "true", true, &environ); - prte_enable_recovery = true; - prte_asprintf(¶m, "OMPI_MCA_mpi_ft_enable"); - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:ompi:parse_cli pushing %s into environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), param); - prte_setenv(param, "true", true, &environ); - } else { - prte_argv_append_nosize(target, "--prtemca"); - prte_argv_append_nosize(target, "prte_enable_ft"); - prte_argv_append_nosize(target, "true"); - prte_argv_append_nosize(target, "--enable-recovery"); - prte_argv_append_nosize(target, "--mca"); - prte_argv_append_nosize(target, "mpi_ft_enable"); - prte_argv_append_nosize(target, "true"); - } - } - else { - prte_output(0, "UNRECOGNIZED OPTION: --with-ft %s", p1); - free(p1); - return PRTE_ERR_FATAL; - } - } - free(p1); - } -#endif - } - - return PRTE_SUCCESS; -} - -static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, bool cmdline) +static int parse_env(char **srcenv, char ***dstenv, + prte_cli_result_t *results) { - char *p1, *p2; + char *p1, *p2, *p3; char *env_set_flag; char **cache = NULL, **cachevals = NULL; char **xparams = NULL, **xvals = NULL; char **envlist = NULL, **envtgt = NULL; - prte_value_t *pval; + prte_cli_item_t *opt; int i, j, rc; - prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:ompi: parse_env", + prte_output_verbose(1, prte_schizo_base_framework.framework_output, + "%s schizo:ompi: parse_env", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); - /* if they are filling out a cmd line, then we don't - * have anything to contribute */ - if (cmdline) { - return PRTE_ERR_TAKE_NEXT_OPTION; + /* 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) { @@ -1375,8 +1093,8 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b /* now process any tune file specification - the tune file processor * will police itself for duplicate values */ - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "tune", 0, 0))) { - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); + if (NULL != (opt = prte_cmd_line_get_param(results, "tune"))) { + p1 = prte_argv_join(opt->values, ','); rc = process_tune_files(p1, dstenv, ','); free(p1); if (PRTE_SUCCESS != rc) { @@ -1384,10 +1102,8 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b } } - if (NULL != (pval = prte_cmd_line_get_param(cmd_line, "initial-errhandler", 0, 0))) { - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); - rc = check_cache(&cache, &cachevals, "mpi_initial_errhandler", p1); - free(p1); + if (NULL != (opt = prte_cmd_line_get_param(results, "initial-errhandler"))) { + rc = check_cache(&cache, &cachevals, "mpi_initial_errhandler", opt->values[0]); if (PRTE_SUCCESS != rc) { prte_argv_free(cache); prte_argv_free(cachevals); @@ -1395,36 +1111,33 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b } } - if (prte_cmd_line_is_taken(cmd_line, "display-comm") - && prte_cmd_line_is_taken(cmd_line, "display-comm-finalize")) { + if (prte_cmd_line_is_taken(results, "display-comm") && + prte_cmd_line_is_taken(results, "display-comm-finalize")) { prte_setenv("OMPI_MCA_ompi_display_comm", "mpi_init,mpi_finalize", true, dstenv); - } else if (prte_cmd_line_is_taken(cmd_line, "display-comm")) { + } else if (prte_cmd_line_is_taken(results, "display-comm")) { prte_setenv("OMPI_MCA_ompi_display_comm", "mpi_init", true, dstenv); - } else if (prte_cmd_line_is_taken(cmd_line, "display-comm-finalize")) { + } else if (prte_cmd_line_is_taken(results, "display-comm-finalize")) { prte_setenv("OMPI_MCA_ompi_display_comm", "mpi_finalize", 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 (0 < (j = prte_cmd_line_get_ninsts(cmd_line, "omca"))) { - for (i = 0; i < j; ++i) { - /* the first value on the list is the name of the param */ - pval = prte_cmd_line_get_param(cmd_line, "omca", i, 0); - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); - /* next value on the list is the value */ - pval = prte_cmd_line_get_param(cmd_line, "omca", i, 1); - p2 = prte_schizo_base_strip_quotes(pval->value.data.string); + if (NULL != (opt = prte_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[0]; /* treat mca_base_env_list as a special case */ if (0 == strcmp(p1, "mca_base_env_list")) { - prte_argv_append_nosize(&envlist, p2); - free(p1); - free(p2); + prte_argv_append_nosize(&envlist, p3); continue; } - rc = check_cache(&cache, &cachevals, p1, p2); - free(p1); - free(p2); + rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { prte_argv_free(cache); prte_argv_free(cachevals); @@ -1432,24 +1145,21 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b } } } - if (0 < (j = prte_cmd_line_get_ninsts(cmd_line, "gomca"))) { - for (i = 0; i < j; ++i) { - /* the first value on the list is the name of the param */ - pval = prte_cmd_line_get_param(cmd_line, "gomca", i, 0); - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); - /* next value on the list is the value */ - pval = prte_cmd_line_get_param(cmd_line, "gomca", i, 1); - p2 = prte_schizo_base_strip_quotes(pval->value.data.string); + if (NULL != (opt = prte_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[0]; /* treat mca_base_env_list as a special case */ if (0 == strcmp(p1, "mca_base_env_list")) { - prte_argv_append_nosize(&envlist, p2); - free(p1); - free(p2); + prte_argv_append_nosize(&envlist, p3); continue; } - rc = check_cache(&cache, &cachevals, p1, p2); - free(p1); - free(p2); + rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { prte_argv_free(cache); prte_argv_free(cachevals); @@ -1457,26 +1167,23 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b } } } - if (0 < (j = prte_cmd_line_get_ninsts(cmd_line, "mca"))) { - for (i = 0; i < j; ++i) { - /* the first value on the list is the name of the param */ - pval = prte_cmd_line_get_param(cmd_line, "mca", i, 0); - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); - /* next value on the list is the value */ - pval = prte_cmd_line_get_param(cmd_line, "mca", i, 1); - p2 = prte_schizo_base_strip_quotes(pval->value.data.string); + if (NULL != (opt = prte_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[0]; /* 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")) { - prte_argv_append_nosize(&envlist, p2); - free(p1); - free(p2); + prte_argv_append_nosize(&envlist, p3); continue; } - rc = check_cache(&cache, &cachevals, p1, p2); - free(p1); - free(p2); + rc = check_cache(&cache, &cachevals, p1, p3); if (PRTE_SUCCESS != rc) { prte_argv_free(cache); prte_argv_free(cachevals); @@ -1486,34 +1193,29 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b } } } - if (0 < (j = prte_cmd_line_get_ninsts(cmd_line, "gmca"))) { - for (i = 0; i < j; ++i) { - /* the first value on the list is the name of the param */ - pval = prte_cmd_line_get_param(cmd_line, "gmca", i, 0); - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); + if (NULL != (opt = prte_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[0]; /* check if this is one of ours */ - if (!check_generic(p1)) { - free(p1); - continue; - } - /* next value on the list is the value */ - pval = prte_cmd_line_get_param(cmd_line, "gmca", i, 1); - p2 = prte_schizo_base_strip_quotes(pval->value.data.string); - /* treat mca_base_env_list as a special case */ - if (0 == strcmp(p1, "mca_base_env_list")) { - prte_argv_append_nosize(&envlist, p2); - free(p1); - free(p2); - continue; - } - rc = check_cache(&cache, &cachevals, p1, p2); - free(p1); - free(p2); - if (PRTE_SUCCESS != rc) { - prte_argv_free(cache); - prte_argv_free(cachevals); - prte_argv_free(envlist); - return rc; + if (check_generic(p1)) { + /* treat mca_base_env_list as a special case */ + if (0 == strcmp(p1, "mca_base_env_list")) { + prte_argv_append_nosize(&envlist, p3); + continue; + } + rc = check_cache(&cache, &cachevals, p1, p3); + if (PRTE_SUCCESS != rc) { + prte_argv_free(cache); + prte_argv_free(cachevals); + prte_argv_free(envlist); + return rc; + } } } } @@ -1561,11 +1263,10 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b prte_argv_free(envlist); /* now look for -x options - not allowed to conflict with a -mca option */ - if (0 < (j = prte_cmd_line_get_ninsts(cmd_line, "x"))) { - for (i = 0; i < j; ++i) { + if (NULL != (opt = prte_cmd_line_get_param(results, "x"))) { + for (i = 0; NULL != opt->values[i]; ++i) { /* the value is the envar */ - pval = prte_cmd_line_get_param(cmd_line, "x", i, 0); - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); + p1 = opt->values[i]; /* if there is an '=' in it, then they are setting a value */ if (NULL != (p2 = strchr(p1, '='))) { *p2 = '\0'; @@ -1573,7 +1274,6 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b } else { p2 = getenv(p1); if (NULL == p2) { - free(p1); continue; } } @@ -1582,7 +1282,6 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b if (PRTE_SUCCESS != rc) { prte_argv_free(cache); prte_argv_free(cachevals); - free(p1); prte_argv_free(xparams); prte_argv_free(xvals); return rc; @@ -1590,7 +1289,6 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b /* cache this for later inclusion */ prte_argv_append_nosize(&xparams, p1); prte_argv_append_nosize(&xvals, p2); - free(p1); } } @@ -1712,6 +1410,151 @@ static bool check_pmix_overlap(char *var, char *value) return false; } +static int setup_fork(prte_job_t *jdata, prte_app_context_t *app) +{ + prte_attribute_t *attr; + bool exists; + char *param, *p2, *saveptr; + int i; + + /* flag that we started this job */ + prte_setenv("PRTE_LAUNCHED", "1", true, &app->env); + + /* now process any envar attributes - we begin with the job-level + * ones as the app-specific ones can override them. We have to + * process them in the order they were given to ensure we wind + * up in the desired final state */ + PRTE_LIST_FOREACH(attr, &jdata->attributes, prte_attribute_t) + { + if (PRTE_JOB_SET_ENVAR == attr->key) { + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, true, &app->env); + } else if (PRTE_JOB_ADD_ENVAR == attr->key) { + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, false, &app->env); + } else if (PRTE_JOB_UNSET_ENVAR == attr->key) { + prte_unsetenv(attr->data.data.string, &app->env); + } else if (PRTE_JOB_PREPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i = 0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + prte_asprintf(&p2, "%s%c%s", attr->data.data.envar.value, + attr->data.data.envar.separator, param); + *saveptr = '='; // restore the current envar setting + prte_setenv(attr->data.data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, true, + &app->env); + } + } else if (PRTE_JOB_APPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i = 0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + prte_asprintf(&p2, "%s%c%s", param, attr->data.data.envar.separator, + attr->data.data.envar.value); + *saveptr = '='; // restore the current envar setting + prte_setenv(attr->data.data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, true, + &app->env); + } + } + } + + /* now do the same thing for any app-level attributes */ + PRTE_LIST_FOREACH(attr, &app->attributes, prte_attribute_t) + { + if (PRTE_APP_SET_ENVAR == attr->key) { + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, true, &app->env); + } else if (PRTE_APP_ADD_ENVAR == attr->key) { + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, false, &app->env); + } else if (PRTE_APP_UNSET_ENVAR == attr->key) { + prte_unsetenv(attr->data.data.string, &app->env); + } else if (PRTE_APP_PREPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i = 0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + prte_asprintf(&p2, "%s%c%s", attr->data.data.envar.value, + attr->data.data.envar.separator, param); + *saveptr = '='; // restore the current envar setting + prte_setenv(attr->data.data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, true, + &app->env); + } + } else if (PRTE_APP_APPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i = 0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + prte_asprintf(&p2, "%s%c%s", param, attr->data.data.envar.separator, + attr->data.data.envar.value); + *saveptr = '='; // restore the current envar setting + prte_setenv(attr->data.data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + prte_setenv(attr->data.data.envar.envar, attr->data.data.envar.value, true, + &app->env); + } + } + } + + return PRTE_SUCCESS; +} + + static int detect_proxy(char *personalities) { char *evar, *tmp, *e2; @@ -1864,12 +1707,12 @@ static int detect_proxy(char *personalities) return 100; } -static void allow_run_as_root(prte_cmd_line_t *cmd_line) +static void allow_run_as_root(prte_cli_result_t *results) { /* we always run last */ char *r1, *r2; - if (prte_cmd_line_is_taken(cmd_line, "allow-run-as-root")) { + if (prte_cmd_line_is_taken(results, "allow-run-as-root")) { return; } @@ -1883,18 +1726,18 @@ static void allow_run_as_root(prte_cmd_line_t *cmd_line) prte_schizo_base_root_error_msg(); } -static void job_info(prte_cmd_line_t *cmdline, void *jobinfo) +static void job_info(prte_cli_result_t *results, + void *jobinfo) { - prte_value_t *pval; + prte_cli_item_t *opt; uint16_t u16; pmix_status_t rc; - if (NULL != (pval = prte_cmd_line_get_param(cmdline, "stream-buffering", 0, 0))) { - u16 = pval->value.data.integer; + if (NULL != (opt = prte_cmd_line_get_param(results, "stream-buffering"))) { + u16 = strtol(opt->values[0], NULL, 10); if (0 != u16 && 1 != u16 && 2 != u16) { /* bad value */ - prte_show_help("help-schizo-base.txt", "bad-stream-buffering-value", true, - pval->value.data.integer); + prte_show_help("help-schizo-base.txt", "bad-stream-buffering-value", true, u16); return; } PMIX_INFO_LIST_ADD(rc, jobinfo, "OMPI_STREAM_BUFFERING", &u16, PMIX_UINT16); diff --git a/src/mca/schizo/prte/Makefile.am b/src/mca/schizo/prte/Makefile.am index c7edf31040..d4876ee59c 100644 --- a/src/mca/schizo/prte/Makefile.am +++ b/src/mca/schizo/prte/Makefile.am @@ -2,6 +2,7 @@ # Copyright (c) 2015-2020 Intel, Inc. All rights reserved. # Copyright (c) 2017 IBM Corporation. All rights reserved. # Copyright (c) 2020 Cisco Systems, Inc. All rights reserved +# Copyright (c) 2022 Nanook Consulting All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -9,6 +10,14 @@ # $HEADER$ # +dist_prtedata_DATA = \ + help-schizo-prte.txt \ + help-schizo-prted.txt \ + help-schizo-prun.txt \ + help-schizo-pterm.txt \ + help-schizo-pinfo.txt \ + help-schizo-prterun.txt + sources = \ schizo_prte_component.c \ schizo_prte.h \ diff --git a/src/mca/schizo/prte/configure.m4 b/src/mca/schizo/prte/configure.m4 new file mode 100644 index 0000000000..8eb0ee14f4 --- /dev/null +++ b/src/mca/schizo/prte/configure.m4 @@ -0,0 +1,35 @@ +# -*- shell-script -*- +# +# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright (c) 2004-2005 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) 2009-2020 Cisco Systems, Inc. All rights reserved +# Copyright (c) 2011-2013 Los Alamos National Security, LLC. +# All rights reserved. +# Copyright (c) 2019 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# MCA_schizo_prte_CONFIG([action-if-found], [action-if-not-found]) +# ----------------------------------------------------------- +AC_DEFUN([MCA_prte_schizo_prte_CONFIG],[ + AC_CONFIG_FILES([src/mca/schizo/prte/Makefile]) + + AS_IF([test "yes" = "yes"], + [$1], [$2]) + + PRTE_SUMMARY_ADD([[Personalities]],[[PRTE]],[$1],[yes]) + +])dnl diff --git a/src/mca/schizo/prte/help-schizo-pinfo.txt b/src/mca/schizo/prte/help-schizo-pinfo.txt new file mode 100644 index 0000000000..4a8fdc19af --- /dev/null +++ b/src/mca/schizo/prte/help-schizo-pinfo.txt @@ -0,0 +1,71 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +[usage] +%s (%s) %s + +Usage: %s [OPTION]... +Provide detailed information on your PRRTE installation. + +/***** General Options *****/ + +-a|--all Show all configuration options and MCA parameters + --arch Show architecture PRRTE was compiled on +-c|--config Show configuration options +-h|--help This help message + --hostname Show the hostname that PRRTE was configured and built on + --internal Show internal MCA parameters (not meant to be modified by users) + --param Show MCA parameters. The first parameter is the framework (or the + keyword "all"); the second parameter is the specific component name (or + the keyword "all"). + --path Show paths that PRRTE was configured with. Accepts the following + parameters: prefix, bindir, libdir, incdir, mandir, pkglibdir, + sysconfdir + --show-version Show version of PRRTE or a component. The first parameter can be the + keywords "prte" or "all", a framework name (indicating all components in + a framework), or a framework:component string (indicating a specific + component). The second parameter can be one of: full, major, minor, + release, greek, svn. +-V|--version Print version and exit + + +Report bugs to %s +# +[param] +Syntax: --param +Show MCA parameters. The first parameter is the framework (or the +keyword "all"); the second parameter is the specific component name (or +the keyword "all"). +# +[internal] +Syntax: --internal +Show internal MCA parameters (i.e., parameters not meant to be modified by users) +# +[path] +Syntax: --path +Show the paths with which PRRTE was configured. Accepts the following +parameters: prefix, bindir, libdir, incdir, mandir, pkglibdir, +sysconfdir +# +[arch] +Syntax: --arch +Show architecture PRRTE was compiled on +# +[config] +Syntax: -c or --config +Show configuration options used to configure PRRTE +# +[hostname] +Syntax: --hostname +Show the hostname upon which PRRTE was configured and built +# +[all] +Syntax: -a or --all +Show all configuration options and MCA parameters diff --git a/src/mca/schizo/prte/help-schizo-prte.txt b/src/mca/schizo/prte/help-schizo-prte.txt new file mode 100644 index 0000000000..0c2fa196bd --- /dev/null +++ b/src/mca/schizo/prte/help-schizo-prte.txt @@ -0,0 +1,248 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +[usage] +%s (%s) %s + +Usage: %s [OPTION]... +Initiate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + +/***** Debug Options *****/ + + --debug-daemons Debug daemons - if not set, the "verbose" setting will be limited to + the DVM controller to reduce clutter + --debug-daemons-file Enable debugging of any PRTE daemons used by this application, storing + their verbose output in files + --leave-session-attached Do not discard stdout/stderr of remote PRTE daemons + --test-suicide Suicide instead of clean abort after delay + --do-not-launch Do not actually launch the DVM + --display Comma-delimited list of options for displaying information + + +/***** Launch Options *****/ + + --default-hostfile Provide a default hostfile +-H|--host List of hosts to use for the DVM + --hostfile Provide a hostfile + --machinefile Provide a hostfile (synonym for "hostfile") + --mca Pass generic MCA parameters to the DVM + --pmixmca Pass PMIx MCA parameters + --prtemca Pass PRTE MCA parameters to the DVM + --show-progress Output a brief periodic report on launch progress + --stream-buffering Adjust buffering for stdout/stderr +-x Export an environment variable, optionally specifying a value (e.g., "-x + foo" exports the environment variable foo and takes its value from the + current environment; "-x foo=bar" exports the environment variable name + foo and sets its value to "bar" in the started processes; "-x foo*" + exports all current environmental variables starting with "foo") + --allow-run-as-root Allow execution as root (STRONGLY DISCOURAGED) + --daemonize Daemonize the DVM daemons into the background + --forward-signals Additional signals (names or integers) to forward + --keepalive Pipe to monitor - DVM will terminate upon closure + --launch-agent Name of daemon executable used to start processes on remote nodes + (default: prted) + --max-vm-size Max number of daemons to start + --no-ready-msg Do not print a DVM ready message + --noprefix Disable automatic --prefix behavior + --prefix Prefix to be used to look for RTE executables + --report-pid Printout pid on stdout [-], stderr [+], or a file [anything else] + --report-uri Printout URI on stdout [-], stderr [+], or a file [anything else] + --set-sid Direct the DVM daemons to separate from the current session + --singleton ID of the singleton process that started us + --system-server Start the DVM as the system server + --tmpdir Set the root for the session directory tree + --tune File(s) containing MCA params for tuning DVM operations + --timeout Timeout DVM startup if time exceeds the specified number of seconds + +Report bugs to %s +# +[prtemca] +Syntax: --prtemca +where arg0 is the parameter name and arg1 is the parameter value + +Pass a PRRTE MCA parameter +# +[pmixmca] +Syntax: --pmixmca +where arg0 is the parameter name and arg1 is the parameter value + +Pass a PMIx MCA parameter +# +[tune] +File(s) containing PRRTE and PMIx MCA params for tuning DVM and/or application operations. +Parameters in the file will be treated as _generic_ parameters and subject to the +translation rules/uncertainties. See "--help mca" for more information. + +Syntax in the file is: + +param = value + +with one parameter and its associated value per line. Empty lines and lines beginning +with the '#' character are ignored. +# +[no-ready-msg] +Do not print a DVM ready message +# +[daemonize] +Daemonize the DVM daemons and controller into the background +# +[system-server] +Start the DVM as the system server +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[report-pid] +Printout PID on stdout [-], stderr [+], or a file [anything else] +# +[report-uri] +Printout URI on stdout [-], stderr [+], or a file [anything else] +# +[test-suicide] +Suicide instead of clean abort after delay +# +[default-hostfile] +Provide a default hostfile +# +[singleton] +ID of the singleton process that started us +# +[keepalive] +Pipe to monitor - DVM will terminate upon closure +# +[launch-agent] +Name of daemon executable used to start processes on remote nodes (default: prted) +# +[max-vm-size] +Maximum number of daemons to start +# +[debug-daemons] +Debug daemon output enabled +# +[debug-daemons-file] +Enable debugging of any PRTE daemons used by this application, storing output in files +# +[leave-session-attached] +Do not discard stdout/stderr of remote PRTE daemons +# +[tmpdir] +Set the root for the session directory tree +# +[prefix] +Prefix to be used to look for RTE executables +# +[noprefix] +Disable automatic --prefix behavior +# +[forward-signals] +Comma-delimited list of additional signals (names or integers) to forward to application +processes ["none" => forward nothing]. Signals provided by default include SIGTSTP, +SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT +# +[allow-run-as-root] +Allow execution as root (STRONGLY DISCOURAGED) +# +[timeout] +Timeout DVM startup if time exceeds the specified number of seconds +# +[x] +Export an environment variable, optionally specifying a value (e.g., "-x foo" exports the +environment variable foo and takes its value from the current environment; "-x foo=bar" +exports the environment variable name foo and sets its value to "bar" in the started +processes; "-x foo*" exports all current environmental variables starting with "foo") +# +[show-progress] +Output a brief periodic report on launch progress +# +[hostfile] +Provide a hostfile +# +[machinefile] +Provide a hostfile (synonym for "hostfile") +# +[host] +Comma-separated list of hosts to use for the DVM +# +[stream-buffering] +Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 fully buffered] +# +[do-not-launch] +Perform all necessary operations to prepare to launch the DVM, but do not actually +launch it (usually used to test mapping patterns) +# +[display] +Comma-delimited list of options for displaying information about the allocation and DVM. +Allowed values: + allocation + bind + map + map-devel + topo +# +# +# DEPRECATED OPTIONS +# +[mca] +Syntax: --mca +where arg0 is the parameter name and arg1 is the parameter value + +Pass generic MCA parameters - i.e., parameters whose project affiliation +must be determined by PRRTE based on matching the name of the parameter with defined values +from various projects that PRRTE knows about. + +DEPRECATED: This translation can be incomplete (e.g., if known project adds or changes +parameters) - thus, it is strongly recommended that users use project-specific parameters +such as "prtemca" or "pmixmca". +# +[xml] +Provide all output in XML format + +DEPRECATED: please see "--help output" for details +# +[display-devel-map] +Display a detailed process map (mostly intended for developers) +just before launch + +DEPRECATED: please see "--help display" for details +# +[display-topo] +Display the topology as part of the process map (mostly intended +for developers) just before launch + +DEPRECATED: please see "--help display" for details +# +[report-bindings] +Display process bindings to stderr + +DEPRECATED: please see "--help display" for details +# +[display-devel-allocation] +Display a detailed list (mostly intended for developers) of the +allocation being used by this job + +DEPRECATED: please see "--help display" for details +# +[display-map] +Display the process map just before launch + +DEPRECATED: please see "--help display" for details +# +[display-allocation] +Display the allocation being used by this job + +DEPRECATED: please see "--help display" for details diff --git a/src/mca/schizo/prte/help-schizo-prted.txt b/src/mca/schizo/prte/help-schizo-prted.txt new file mode 100644 index 0000000000..d199e81ce7 --- /dev/null +++ b/src/mca/schizo/prte/help-schizo-prted.txt @@ -0,0 +1,449 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +[usage-prte] +%s (%s) %s + +Usage: %s [OPTION]... +Initiate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + +/***** Debug Options *****/ + +-d|--debug-devel Enable debugging of PRTE + --debug Top-level PRTE debug switch (default: false) This option will be + deprecated, use --debug-devel instead. + --debug-daemons Debug daemons + --debug-daemons-file Enable debugging of any PRTE daemons used by this application, storing + output in files + --debug-verbose Verbosity level for PRTE debug messages (default: 1) + --display Comma-delimited list of options for displaying information about the + allocation and job.Allowed values: allocation, bind, map, map-devel, + topo + --display-allocation Display the allocation being used by this job + --display-map Display the process map just before launch + --get-stack-traces Get stack traces of all application procs on timeout + --leave-session-attached Do not discard stdout/stderr of remote PRTE daemons + --output-proctable Print the complete proctable to stdout [-], stderr [+], or a file + [anything else] after launch + --report-state-on-timeout Report all job and process states upon timeout + --spawn-timeout Timeout the job if spawn takes more than the specified number of seconds + --stop-on-exec If supported, stop each process at start of execution + --test-suicide Suicide instead of clean abort after delay + --timeout Timeout the job after the specified number of seconds + + + +/***** Output Options *****/ + + --merge-stderr-to-stdout Merge stderr to stdout for each process + --output Comma-delimited list of options that control how output is + generated.Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, + dir=DIRNAME, file=filename. The dir option redirects output from + application processes into DIRNAME/job/rank/std[out,err,diag]. The file + option redirects output from application processes into filename.rank. In + both cases, the provided name will be converted to an absolute path. + Supported qualifiers include NOCOPY (do not copy the output to the + stdout/err streams). + --output-directory Redirect output from application processes into + filename/job/rank/std[out,err,diag]. A relative path value will be + converted to an absolute path. The directory name may include a colon + followed by a comma-delimited list of optional case-insensitive + directives. Supported directives currently include NOJOBID (do not + include a job-id directory level) and NOCOPY (do not copy the output to + the stdout/err streams) + --output-filename Redirect output from application processes into filename.rank. A relative + path value will be converted to an absolute path. The directory name may + include a colon followed by a comma-delimited list of optional + case-insensitive directives. Supported directives currently include + NOCOPY (do not copy the output to the stdout/err streams) + --report-child-jobs-separately Return the exit status of the primary job only + --tag-output Tag all output with [job,rank] + --timestamp-output Timestamp all application process output + --xml Provide all output in XML format + --xterm Create a new xterm window and display output from the specified ranks + there + + + +/***** Input Options *****/ + + --stdin Specify procs to receive stdin [rank, all, none] (default: 0, indicating + rank 0) + + + +/***** Mapping Options *****/ + + --map-by Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | + ppr |,rankfile] with supported colon-delimited modifiers: PE=y (for + multiple cpus/proc), SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, + HWTCPUS, CORECPUS, DEVICE(for dist policy), INHERIT, NOINHERIT, + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job), + FILE= for seq and rankfile options + + + +/***** Ranking Options *****/ + + --rank-by Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node], with + modifier :SPAN or :FILL + + + +/***** Binding Options *****/ + + --bind-to Binding policy for job. Allowed values: none, hwthread, core, l1cache, + l2cache, l3cache, numa, package, ("none" is the default when + oversubscribed, "core" is the default when np<=2, and "numa" is the + default when np>2). Allowed colon-delimited qualifiers: overload-allowed, + if-supported + + + +/***** Developer Options *****/ + + --display-devel-allocation Display a detailed list (mostly intended for developers) of the + allocation being used by this job + --display-devel-map Display a detailed process map (mostly intended for developers) just + before launch + --display-topo Display the topology as part of the process map (mostly intended for + developers) just before launch + --do-not-launch Perform all necessary operations to prepare to launch the application, + but do not actually launch it (usually used to test mapping patterns) + --report-bindings Whether to report process bindings to stderr + + + +/***** Launch Options *****/ + + --default-hostfile Provide a default hostfile + --gpmixmca Pass global PMIx MCA parameters that are applicable to all contexts (arg0 + is the parameter name; arg1 is the parameter value) +-H|--host List of hosts to invoke processes on + --hostfile Provide a hostfile + --initial-errhandler Specify the initial error handler that is attached to predefined + communicators during the first MPI call. + --machinefile Provide a hostfile + --mca Pass context-specific MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --path PATH to be used to look for executables to start processes + --pmixmca Pass context-specific PMIx MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --preload-files Preload the comma separated list of files to the remote machines current + working directory before starting the remote process. + --prtemca Pass context-specific PRTE MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --pset User-specified name assigned to the processes in their given application + --rankfile Name of file to specify explicit task mapping +-s|--preload-binary Preload the binary on the remote machine before starting the remote + process. + --set-cwd-to-session-dir Set the working directory of the started processes to their session + directory + --show-progress Output a brief periodic report on launch progress + --stream-buffering Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 + fully buffered] + --wd Synonym for --wdir + --wdir Set the working directory of the started processes +-x Export an environment variable, optionally specifying a value (e.g., "-x + foo" exports the environment variable foo and takes its value from the + current environment; "-x foo=bar" exports the environment variable name + foo and sets its value to "bar" in the started processes; "-x foo*" + exports all current environmental variables starting with "foo") + + + +/***** %s Specific Options *****/ + + --allow-run-as-root Allow execution as root (STRONGLY DISCOURAGED) + --daemonize Daemonize the DVM daemons into the background + --forward-signals Comma-delimited list of additional signals (names or integers) to forward + to application processes ["none" => forward nothing]. Signals provided by + default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT + --keepalive Pipe to monitor - DVM will terminate upon closure + --launch-agent Name of daemon executable used to start processes on remote nodes + (default: prted) + --max-vm-size Number of daemons to start + --no-ready-msg Do not print a DVM ready message + --noprefix Disable automatic --prefix behavior + --personality Specify the personality to be used + --prefix Prefix to be used to look for RTE executables + --report-pid Printout pid on stdout [-], stderr [+], or a file [anything else] + --report-uri Printout URI on stdout [-], stderr [+], or a file [anything else] + --set-sid Direct the DVM daemons to separate from the current session + --singleton ID of the singleton process that started us + --system-server Start the DVM as the system server + --tmpdir Set the root for the session directory tree + --tune File(s) containing MCA params for tuning DVM operations + + +Report bugs to %s +# +[usage-prted] +NEED FULL PAGE FOR PRTED +# +[usage-prun] +NEED FULL PAGE FOR PRUN +# +[usage-pterm] +%s (%s) %s + +Usage: %s [OPTION]... +Terminate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + + +/***** %s Specific Options *****/ + + --dvm-uri Specify the URI of the DVM master, or the name of the file (specified as + file:filename) that contains that info + --num-connect-retries Max number of times to try to connect (int) + --pid PID of the daemon to which we should connect (int => PID or file: + for file containing the PID + --namespace Namespace of the daemon we are to connect to (char*) + --system-server-first First look for a system server and connect to it if found + --system-server-only Connect only to a system-level server + --wait-to-connect Delay specified number of seconds before trying to connect + + +Report bugs to %s +# +[version] +%s (%s) %s + +Report bugs to %s +# +[dvm-uri] +Specify the URI of the DVM master, or the name of the file (specified as +file:filename) that contains that info +# +[num-connect-retries] +Max number of times to try to connect to the specified server (int) +# +[pid] +PID of the daemon to which we should connect (int => PID or file: +for file containing the PID +# +[namespace] +Namespace of the daemon we are to connect to (char*) +# +[system-server-first] +First look for a system server and connect to it if found +# +[system-server-only] +Connect only to a system-level server - abort if one is not found +# +[wait-to-connect] +Delay specified number of seconds before trying to connect +# +[parseable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[parsable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[np] +Specify number of application processes to be started +# +[no-ready-msg] +Do not print a DVM ready message +# +[daemonize] +Daemonize the DVM daemons into the background +# +[system-server] +Start the DVM as the system server +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[report-pid] +Printout PID on stdout [-], stderr [+], or a file [anything else] +# +[report-uri] +Printout URI on stdout [-], stderr [+], or a file [anything else] +# +[test-suicide] +Suicide instead of clean abort after delay +# +[default-hostfile] +Provide a default hostfile +# +[singleton] +ID of the singleton process that started us +# +[keepalive] +Pipe to monitor - DVM will terminate upon closure +# +[map-by] +Mapping Policy for job: + slot + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node + seq + dist + ppr + rankfile +with supported colon-delimited qualifiers: + PE=y (for multiple cpus/proc) + SPAN + OVERSUBSCRIBE + NOOVERSUBSCRIBE + NOLOCAL + HWTCPUS + CORECPUS + DEVICE(for dist policy) + INHERIT + NOINHERIT + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job) + FILE= for seq and rankfile options +# +[rank-by] +Ranking Policy for job: + slot (default: np <= 2) + hwthread + core + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node +with supported colon-delimited qualifiers: + SPAN + FILL +# +[bind-to] +Binding Policy for job: + none (default: oversubscribed) + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package +with supported colon-delimited qualifiers: + overload-allowed + if-supported +# +[display] +Comma-delimited list of options for displaying information +about the allocation and job. Allowed values: + allocation + bind + map + map-devel + topo +# +[rankfile] +Name of file to specify explicit task mapping +# +[do-not-launch] +Perform all necessary operations to prepare to launch the +application, but do not actually launch it (usually used +to test mapping patterns) +# +[display-devel-map] +Display a detailed process map (mostly intended for developers) +just before launch +# +[display-topo] +Display the topology as part of the process map (mostly intended +for developers) just before launch +# +[report-bindings] +"Display process bindings to stderr +# +[display-devel-allocation] +Display a detailed list (mostly intended for developers) of the +allocation being used by this job +# +[display-map] +Display the process map just before launch +# +[display-allocation] +Display the allocation being used by this job +# +[enable-recovery] +Enable recovery from process failure [Default = disabled] +# +[max-restarts] +Max number of times to restart a failed process +# +[disable-recovery] +Disable recovery (resets all recovery options to off) +# +[continuous] +Job is to run until explicitly terminated +# +[personality] +Specify the personality to be used +# +[prte-server] +Specify the URI of the publish/lookup server, or the name +of the file (specified as file:filename) that contains that info +# +[dvm-master-uri] +URI for the DVM master +# +[parent-uri] +URI for the parent if tree launch is enabled +# +[tree-spawn] +Tree-based spawn in progress +# +[daemonize] +Daemonize the DVM daemons into the background +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[prtemca] +Pass context-specific PRTE MCA parameters (arg0 is the +parameter name; arg1 is the parameter value) +# +[pmixmca] +Pass context-specific PMIx MCA parameters (arg0 is the +parameter name; arg1 is the parameter value) +# +[debug-daemons-file] +Enable debugging of any PRTE daemons used by this +application, storing output in files +# +[leave-session-attached] +Do not discard stdout/stderr of remote PRTE daemons diff --git a/src/mca/schizo/prte/help-schizo-prterun.txt b/src/mca/schizo/prte/help-schizo-prterun.txt new file mode 100644 index 0000000000..506d945f63 --- /dev/null +++ b/src/mca/schizo/prte/help-schizo-prterun.txt @@ -0,0 +1,568 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +[usage] +%s (%s) %s + +Usage: %s [OPTION]... +Initiate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + +/***** Debug Options *****/ + + --debug-daemons Debug daemons - if not set, the "verbose" setting will be limited to + the DVM controller to reduce clutter + --debug-daemons-file Enable debugging of any PRTE daemons used by this application, storing + their verbose output in files + --display Comma-delimited list of options for displaying information about the + allocation and job. Allowed values: allocation, bind, map, map-devel, + topo + --get-stack-traces Get stack traces of all application procs on timeout + --leave-session-attached Do not discard stdout/stderr of remote PRTE daemons + --report-state-on-timeout Report all job and process states upon timeout + --spawn-timeout Timeout the job if spawn takes more than the specified number of seconds + --stop-on-exec If supported, stop each specified process at start of execution + --stop-in-init Direct the specified processes to stop in PMIx_Init + --stop-in-app Direct the specified processes to stop at an application-controlled location + --test-suicide Suicide instead of clean abort after delay + --timeout Timeout the job after the specified number of seconds + + + +/***** Output Options *****/ + + --output Comma-delimited list of options that control how output is + generated.Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, + dir=DIRNAME, file=filename. The dir option redirects output from + application processes into DIRNAME/job/rank/std[out,err,diag]. The file + option redirects output from application processes into filename.rank. In + both cases, the provided name will be converted to an absolute path. + Supported qualifiers include NOCOPY (do not copy the output to the + stdout/err streams). + --report-child-jobs-separately Return the exit status of the primary job only + --xterm Create a new xterm window and display output from the specified ranks + there + + + +/***** Input Options *****/ + + --stdin Specify procs to receive stdin [rank, all, none] (default: 0, indicating + rank 0) + + + +/***** Mapping Options *****/ + + --map-by Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | + ppr |,rankfile] with supported colon-delimited modifiers: PE=y (for + multiple cpus/proc), SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, + HWTCPUS, CORECPUS, DEVICE(for dist policy), INHERIT, NOINHERIT, + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job), + FILE= for seq and rankfile options + + + +/***** Ranking Options *****/ + + --rank-by Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node], with + modifier :SPAN or :FILL + + + +/***** Binding Options *****/ + + --bind-to Binding policy for job. Allowed values: none, hwthread, core, l1cache, + l2cache, l3cache, numa, package, ("none" is the default when + oversubscribed, "core" is the default when np<=2, and "numa" is the + default when np>2). Allowed colon-delimited qualifiers: overload-allowed, + if-supported + + + +/***** Developer Options *****/ + + --do-not-launch Perform all necessary operations to prepare to launch the application, + but do not actually launch it (usually used to test mapping patterns) + + + +/***** Launch Options *****/ + + --default-hostfile Provide a default hostfile +-H|--host List of hosts to invoke processes on + --hostfile Provide a hostfile + --initial-errhandler Specify the initial error handler that is attached to predefined + communicators during the first MPI call. + --machinefile Provide a hostfile + --mca Pass context-specific MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --path PATH to be used to look for executables to start processes + --pmixmca Pass context-specific PMIx MCA parameters; they are considered global if + only one context is specified (arg0 is the parameter name; arg1 is the parameter value) + --gpmixmca Pass global PMIx MCA parameters that are applicable to all contexts (arg0 + is the parameter name; arg1 is the parameter value) + --preload-files Preload the comma separated list of files to the remote machines current + working directory before starting the remote process. + --prtemca Pass context-specific PRTE MCA parameters to the DVM + --pset User-specified name assigned to the processes in their given application + --rankfile Name of file to specify explicit task mapping +-s|--preload-binary Preload the binary on the remote machine before starting the remote + process. + --set-cwd-to-session-dir Set the working directory of the started processes to their session + directory + --show-progress Output a brief periodic report on launch progress + --stream-buffering Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 + fully buffered] + --wd Synonym for --wdir + --wdir Set the working directory of the started processes +-x Export an environment variable, optionally specifying a value (e.g., "-x + foo" exports the environment variable foo and takes its value from the + current environment; "-x foo=bar" exports the environment variable name + foo and sets its value to "bar" in the started processes; "-x foo*" + exports all current environmental variables starting with "foo") + + + +/***** Specific Options *****/ + + --allow-run-as-root Allow execution as root (STRONGLY DISCOURAGED) + --daemonize Daemonize the DVM daemons into the background + --forward-signals Comma-delimited list of additional signals (names or integers) to forward + to application processes ["none" => forward nothing]. Signals provided by + default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT + --keepalive Pipe to monitor - DVM will terminate upon closure + --launch-agent Name of daemon executable used to start processes on remote nodes + (default: prted) + --max-vm-size Number of daemons to start + --no-ready-msg Do not print a DVM ready message + --noprefix Disable automatic --prefix behavior + --personality Specify the personality to be used + --prefix Prefix to be used to look for RTE executables + --report-pid Printout pid on stdout [-], stderr [+], or a file [anything else] + --report-uri Printout URI on stdout [-], stderr [+], or a file [anything else] + --set-sid Direct the DVM daemons to separate from the current session + --singleton ID of the singleton process that started us + --system-server Start the DVM as the system server + --tmpdir Set the root for the session directory tree + --tune File(s) containing MCA params for tuning DVM operations + + +Report bugs to %s +# +[prtemca] +Syntax: --prtemca +where arg0 is the parameter name and arg1 is the parameter value + +Pass a PRRTE MCA parameter +# +[pmixmca] +Syntax: --pmixmca +where arg0 is the parameter name and arg1 is the parameter value + +Pass a PMIx MCA parameter +# +[gpmixmca] +Syntax: --gpmixmca +where arg0 is the parameter name and arg1 is the parameter value. The "g" prefix +indicates that this PMIx parameter is to be applied to _all_ application contexts and +not just the one in which the directive appears. +# +[tune] +File(s) containing PRRTE and PMIx MCA params for tuning DVM and/or application operations. +Parameters in the file will be treated as _generic_ parameters and subject to the +translation rules/uncertainties. See "--help mca" for more information. + +Syntax in the file is: + +param = value + +with one parameter and its associated value per line. Empty lines and lines beginning +with the '#' character are ignored. +# +[no-ready-msg] +Do not print a DVM ready message +# +[daemonize] +Daemonize the DVM daemons into the background +# +[system-server] +Start the DVM as the system server +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[report-pid] +Printout PID on stdout [-], stderr [+], or a file [anything else] +# +[report-uri] +Printout URI on stdout [-], stderr [+], or a file [anything else] +# +[test-suicide] +Suicide instead of clean abort after delay +# +[default-hostfile] +Provide a default hostfile +# +[singleton] +ID of the singleton process that started us +# +[keepalive] +Pipe to monitor - DVM will terminate upon closure +# +[launch-agent] +Name of daemon executable used to start processes on remote nodes (default: prted) +# +[max-vm-size] +Maximum number of daemons to start +# +[debug-daemons] +Debug daemon output enabled +# +[debug-daemons-file] +Enable debugging of any PRTE daemons used by this application, storing output in files +# +[leave-session-attached] +Do not discard stdout/stderr of remote PRTE daemons +# +[tmpdir] +Set the root for the session directory tree +# +[prefix] +Prefix to be used to look for RTE executables +# +[noprefix] +Disable automatic --prefix behavior +# +[forward-signals] +Comma-delimited list of additional signals (names or integers) to forward to application +processes ["none" => forward nothing]. Signals provided by default include SIGTSTP, +SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT +# +[allow-run-as-root] +Allow execution as root (STRONGLY DISCOURAGED) +# +[report-child-jobs-separately] +Return the exit status of the primary job only +# +[timeout] +Timeout the job if execution time exceeds the specified number of seconds +# +[report-state-on-timeout] +Report all job and process states upon timeout +# +[get-stack-traces] +Get stack traces of all application procs on timeout +# +[spawn-timeout] +Timeout the job if spawn takes more than the specified number of seconds +# +[np] +Specify number of application processes to be started +# +[n] +Specify number of application processes to be started +# +[N] +Specify number of application processes per node to be started +# +[app] +Provide an appfile; ignore all other command line options +# +[xterm] +Create a new xterm window and display output from the specified ranks there. +Ranks are specified as a comma-delimited list of ranges - e.g., "1,3-6,9", +or as "all"." +# +[stop-on-exec] +If supported, stop each process at start of execution +# +[stop-in-init] +Include the PMIX_DEBUG_STOP_IN_INIT attribute in the application's +job info directing that the specified ranks stop in PMIx_Init pending +release. Ranks are specified as a comma-delimited list of ranges - e.g., "1,3-6,9", +or as "all". +# +[stop-in-app] +Include the PMIX_DEBUG_STOP_IN_APP attribute in the application's +job info directing that the specified ranks stop at an application-determined +point pending release. Ranks are specified as a comma-delimited list of +ranges - e.g., "1,3-6,9", or as "all". +# +[x] +Export an environment variable, optionally specifying a value (e.g., "-x foo" exports the +environment variable foo and takes its value from the current environment; "-x foo=bar" +exports the environment variable name foo and sets its value to "bar" in the started +processes; "-x foo*" exports all current environmental variables starting with "foo") +# +[wdir] +Set the working directory of the started processes +# +[wd] +Synonym for --wdir +# +[set-cwd-to-session-dir] +Set the working directory of the started processes to their session directory +# +[path] +PATH to be used to look for executables to start processes +# +[show-progress] +Output a brief periodic report on launch progress +# +[pset] +User-specified name assigned to the processes in their given application +# +[hostfile] +Provide a hostfile +# +[machinefile] +Provide a hostfile (synonym for "hostfile") +# +[host] +Comma-separated list of hosts to invoke processes on +# +[personality] +Specify the personality to be used +# +[preload-files] +Syntax: --preload-files + +Preload the comma separated list of files to the remote machines current +working directory before starting the remote process. +# +[preload-binary] +Syntax: --preload-binary + +Preload the binary on the remote machine before starting the +remote process. +# +[output] +Comma-delimited list of options that control how output is generated. +Allowed values: + tag Mark each output line with the [job,rank] of the + process that generated it + timestamp Prefix each output line with a datetime stamp. Note + that the timestamp will be the time when the line + is output by the DVM - not the time when the source + output it + xml Format all output in XML + merge[-stderr-to-stdout] Merge stderr into stdout + dir=DIRNAME Redirect output from application processes into files of + the form DIRNAME/job/rank/std[out,err,diag]. + file=filename Redirect output from application processes into files of + the form filename.rank. + +In both the "dir" and "file" cases, the provided name will be converted to an absolute path. +Supported qualifiers include NOCOPY (i.e., output shall go only into the files - do not copy +the output to the stdout/err streams). +# +[stream-buffering] +Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 fully buffered] +# +[stdin] +Specify procs to receive stdin [rank, "all", "none"] (default: 0, indicating rank 0) +# +[map-by] +Mapping Policy for job: + slot + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node + seq + dist + ppr + rankfile +with supported colon-delimited qualifiers: + PE=y (for multiple cpus/proc) + SPAN + OVERSUBSCRIBE + NOOVERSUBSCRIBE + NOLOCAL + HWTCPUS + CORECPUS + DEVICE(for dist policy) + INHERIT + NOINHERIT + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job) + FILE= for seq and rankfile options +# +[rank-by] +Ranking Policy for job: + slot (default: np <= 2) + hwthread + core + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node +with supported colon-delimited qualifiers: + SPAN + FILL +# +[bind-to] +Binding Policy for job: + none (default: oversubscribed) + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package +with supported colon-delimited qualifiers: + overload-allowed + if-supported +# +[rankfile] +Name of file to specify explicit task mapping +# +[display] +Comma-delimited list of options for displaying information about the allocation and job. +Allowed values: + allocation + bind + map + map-devel + topo +# +[do-not-launch] +Perform all necessary operations to prepare to launch the application, but do not actually +launch it (usually used to test mapping patterns) +# +[enable-recovery] +Enable recovery from process failure [Default = disabled] +# +[max-restarts] +Max number of times to restart a failed process +# +[disable-recovery] +Disable recovery (resets all recovery options to off) +# +[continuous] +Job is to run until explicitly terminated +# +# +# DEPRECATED OPTIONS +# +[mca] +Syntax: --mca +where arg0 is the parameter name and arg1 is the parameter value + +Pass generic MCA parameters - i.e., parameters whose project affiliation +must be determined by PRRTE based on matching the name of the parameter with defined values +from various projects that PRRTE knows about. + +DEPRECATED: This translation can be incomplete (e.g., if known project adds or changes +parameters) - thus, it is strongly recommended that users use project-specific parameters +such as "prtemca" or "pmixmca". +# +[gmca] +Syntax: --gmca +where arg0 is the parameter name and arg1 is the parameter value. The "g" prefix +indicates that this parameter is to be applied to _all_ application contexts and +not just the one in which the directive appears. + +Pass generic MCA parameters - i.e., parameters whose project affiliation +must be determined by PRRTE based on matching the name of the parameter with defined values +from various projects that PRRTE knows about. This translation can be incomplete (e.g., if +a known project adds or changes parameters) - thus, it is strongly recommended that users +use project-specific parameters such as "prtemca" or "pmixmca". + +DEPRECATED: This translation can be incomplete (e.g., if known project adds or changes +parameters) - thus, it is strongly recommended that users use project-specific parameters +such as "gprtemca" or "gpmixmca". +# +[xml] +Provide all output in XML format + +DEPRECATED: please see "--help output" for details +# +[tag-output] +Tag all output with [job,rank] + +DEPRECATED: please see "--help output" for details +# +[timestamp-output] +Timestamp all application process output + +DEPRECATED: please see "--help output" for details +# +[output-directory] +Redirect output from application processes into filename/job/rank/std[out,err,diag]. A +relative path value will be converted to an absolute path. The directory name may include a +colon followed by a comma-delimited list of optional case-insensitive directives. Supported +directives currently include NOJOBID (do not include a job-id directory level) and NOCOPY +(do not copy the output to the stdout/err streams) + +DEPRECATED: please see "--help output" for details +# +[output-filename] +Redirect output from application processes into filename.rank. A relative path value will be +converted to an absolute path. The directory name may include a colon followed by a +comma-delimited list of optional case-insensitive directives. Supported directives currently +include NOCOPY (do not copy the output to the stdout/err streams) + +DEPRECATED: please see "--help output" for details +# +[merge-stderr-to-stdout] +Merge stderr to stdout for each process + +DEPRECATED: please see "--help output" for details +# +[display-devel-map] +Display a detailed process map (mostly intended for developers) +just before launch + +DEPRECATED: please see "--help display" for details +# +[display-topo] +Display the topology as part of the process map (mostly intended +for developers) just before launch + +DEPRECATED: please see "--help display" for details +# +[report-bindings] +Display process bindings to stderr + +DEPRECATED: please see "--help display" for details +# +[display-devel-allocation] +Display a detailed list (mostly intended for developers) of the +allocation being used by this job + +DEPRECATED: please see "--help display" for details +# +[display-map] +Display the process map just before launch + +DEPRECATED: please see "--help display" for details +# +[display-allocation] +Display the allocation being used by this job + +DEPRECATED: please see "--help display" for details diff --git a/src/mca/schizo/prte/help-schizo-prun.txt b/src/mca/schizo/prte/help-schizo-prun.txt new file mode 100644 index 0000000000..341cdce593 --- /dev/null +++ b/src/mca/schizo/prte/help-schizo-prun.txt @@ -0,0 +1,363 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +# +[usage] +%s (%s) %s + +Usage: %s [OPTION]... +Submit job to the PMIx Reference RTE + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + +/***** Debug Options *****/ + + --display Comma-delimited list of options for displaying information about the + allocation and job. Allowed values: allocation, bind, map, map-devel, + topo + --timeout Timeout the job after the specified number of seconds + --spawn-timeout Timeout the job if spawn takes more than the specified number of seconds + --get-stack-traces Get stack traces of all application procs on timeout + --report-state-on-timeout Report all job and process states upon timeout + --stop-on-exec If supported, stop each specified process at start of execution + --stop-in-init Direct the specified processes to stop in PMIx_Init + --stop-in-app Direct the specified processes to stop at an application-controlled location + + + +/***** Output Options *****/ + + --output Comma-delimited list of options that control how output is + generated.Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, + dir=DIRNAME, file=filename. The dir option redirects output from + application processes into DIRNAME/job/rank/std[out,err,diag]. The file + option redirects output from application processes into filename.rank. In + both cases, the provided name will be converted to an absolute path. + Supported qualifiers include NOCOPY (do not copy the output to the + stdout/err streams). + --report-child-jobs-separately Return the exit status of the primary job only + --xterm Create a new xterm window and display output from the specified ranks + there + + + +/***** Input Options *****/ + + --stdin Specify procs to receive stdin [rank, all, none] (default: 0, indicating + rank 0) + + + +/***** Mapping Options *****/ + + --map-by Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | + ppr |,rankfile] with supported colon-delimited modifiers: PE=y (for + multiple cpus/proc), SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, + HWTCPUS, CORECPUS, DEVICE(for dist policy), INHERIT, NOINHERIT, + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job), + FILE= for seq and rankfile options + + + +/***** Ranking Options *****/ + + --rank-by Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node], with + modifier :SPAN or :FILL + + + +/***** Binding Options *****/ + + --bind-to Binding policy for job. Allowed values: none, hwthread, core, l1cache, + l2cache, l3cache, numa, package, ("none" is the default when + oversubscribed, "core" is the default when np<=2, and "numa" is the + default when np>2). Allowed colon-delimited qualifiers: overload-allowed, + if-supported + + + +/***** Developer Options *****/ + + --do-not-launch Perform all necessary operations to prepare to launch the application, + but do not actually launch it (usually used to test mapping patterns) + + + +/***** Launch Options *****/ +-c|--np Number of processes to run +-n|--n Number of processes to run +-N Number of processes to run per node + --app Provide an appfile; ignore all other command line options +-H|--host List of hosts to invoke processes on + --hostfile Provide a hostfile + --machinefile Provide a hostfile + --path PATH to be used to look for executables to start processes + --pmixmca Pass context-specific PMIx MCA parameters; they are considered global if + only one context is specified (arg0 is the parameter name; arg1 is the parameter value) + --gpmixmca Pass global PMIx MCA parameters that are applicable to all contexts (arg0 + is the parameter name; arg1 is the parameter value) + --tune File(s) containing MCA params for tuning operations + --preload-files Preload the comma separated list of files to the remote machines current + working directory before starting the remote process. + --prtemca Pass context-specific PRTE MCA parameters to the DVM + --pset User-specified name assigned to the processes in their given application + --rankfile Name of file to specify explicit task mapping +-s|--preload-binary Preload the binary on the remote machine before starting the remote + process. + --set-cwd-to-session-dir Set the working directory of the started processes to their session + directory + --show-progress Output a brief periodic report on launch progress + --stream-buffering Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 + fully buffered] + --wd Synonym for --wdir + --wdir Set the working directory of the started processes +-x Export an environment variable, optionally specifying a value (e.g., "-x + foo" exports the environment variable foo and takes its value from the + current environment; "-x foo=bar" exports the environment variable name + foo and sets its value to "bar" in the started processes; "-x foo*" + exports all current environmental variables starting with "foo") + + + +/***** Specific Options *****/ + --do-not-connect Do not connect to a server + --dvm-uri Specify the URI of the DVM master, or the name of the file (specified as + file:filename) that contains that info + --namespace Namespace of the daemon to which we should connect + --pid PID of the daemon to which we should connect (int => PID or file: + for file containing the PID + --system-server-first First look for a system server and connect to it if found + --system-server-only Connect only to a system-level server + --tmpdir Set the root for the session directory tree + --wait-to-connect Delay specified number of seconds before trying to connect + --num-connect-retries Max number of times to try to connect + --personality Specify the personality to be used + --allow-run-as-root Allow execution as root (STRONGLY DISCOURAGED) + --forward-signals Comma-delimited list of additional signals (names or integers) to forward + to application processes ["none" => forward nothing]. Signals provided by + default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT + +Report bugs to %s +# +[dvm-uri] +Specify the URI of the DVM master, or the name of the file (specified as +file:filename) that contains that info +# +[num-connect-retries] +Max number of times to try to connect to the specified server (int) +# +[pid] +PID of the daemon to which we should connect (int => PID or file: +for file containing the PID +# +[namespace] +Namespace of the daemon we are to connect to (char*) +# +[system-server-first] +First look for a system server and connect to it if found +# +[system-server-only] +Connect only to a system-level server - abort if one is not found +# +[wait-to-connect] +Delay specified number of seconds before trying to connect +# +[parseable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[parsable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[np] +Specify number of application processes to be started +# +[no-ready-msg] +Do not print a DVM ready message +# +[daemonize] +Daemonize the DVM daemons into the background +# +[system-server] +Start the DVM as the system server +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[report-pid] +Printout PID on stdout [-], stderr [+], or a file [anything else] +# +[report-uri] +Printout URI on stdout [-], stderr [+], or a file [anything else] +# +[test-suicide] +Suicide instead of clean abort after delay +# +[default-hostfile] +Provide a default hostfile +# +[singleton] +ID of the singleton process that started us +# +[keepalive] +Pipe to monitor - DVM will terminate upon closure +# +[map-by] +Mapping Policy for job: + slot + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node + seq + dist + ppr + rankfile +with supported colon-delimited qualifiers: + PE=y (for multiple cpus/proc) + SPAN + OVERSUBSCRIBE + NOOVERSUBSCRIBE + NOLOCAL + HWTCPUS + CORECPUS + DEVICE(for dist policy) + INHERIT + NOINHERIT + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job) + FILE= for seq and rankfile options +# +[rank-by] +Ranking Policy for job: + slot (default: np <= 2) + hwthread + core + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node +with supported colon-delimited qualifiers: + SPAN + FILL +# +[bind-to] +Binding Policy for job: + none (default: oversubscribed) + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package +with supported colon-delimited qualifiers: + overload-allowed + if-supported +# +[display] +Comma-delimited list of options for displaying information +about the allocation and job. Allowed values: + allocation + bind + map + map-devel + topo +# +[rankfile] +Name of file to specify explicit task mapping +# +[do-not-launch] +Perform all necessary operations to prepare to launch the +application, but do not actually launch it (usually used +to test mapping patterns) +# +[display-devel-map] +Display a detailed process map (mostly intended for developers) +just before launch +# +[display-topo] +Display the topology as part of the process map (mostly intended +for developers) just before launch +# +[report-bindings] +"Display process bindings to stderr +# +[display-devel-allocation] +Display a detailed list (mostly intended for developers) of the +allocation being used by this job +# +[display-map] +Display the process map just before launch +# +[display-allocation] +Display the allocation being used by this job +# +[enable-recovery] +Enable recovery from process failure [Default = disabled] +# +[max-restarts] +Max number of times to restart a failed process +# +[disable-recovery] +Disable recovery (resets all recovery options to off) +# +[continuous] +Job is to run until explicitly terminated +# +[personality] +Specify the personality to be used +# +[prte-server] +Specify the URI of the publish/lookup server, or the name +of the file (specified as file:filename) that contains that info +# +[dvm-master-uri] +URI for the DVM master +# +[parent-uri] +URI for the parent if tree launch is enabled +# +[tree-spawn] +Tree-based spawn in progress +# +[daemonize] +Daemonize the DVM daemons into the background +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[prtemca] +Pass context-specific PRTE MCA parameters (arg0 is the +parameter name; arg1 is the parameter value) +# +[pmixmca] +Pass context-specific PMIx MCA parameters (arg0 is the +parameter name; arg1 is the parameter value) +# +[debug-daemons-file] +Enable debugging of any PRTE daemons used by this +application, storing output in files +# +[leave-session-attached] +Do not discard stdout/stderr of remote PRTE daemons diff --git a/src/mca/schizo/prte/help-schizo-pterm.txt b/src/mca/schizo/prte/help-schizo-pterm.txt new file mode 100644 index 0000000000..d199e81ce7 --- /dev/null +++ b/src/mca/schizo/prte/help-schizo-pterm.txt @@ -0,0 +1,449 @@ +# -*- text -*- +# +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# +[usage-prte] +%s (%s) %s + +Usage: %s [OPTION]... +Initiate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + +/***** Debug Options *****/ + +-d|--debug-devel Enable debugging of PRTE + --debug Top-level PRTE debug switch (default: false) This option will be + deprecated, use --debug-devel instead. + --debug-daemons Debug daemons + --debug-daemons-file Enable debugging of any PRTE daemons used by this application, storing + output in files + --debug-verbose Verbosity level for PRTE debug messages (default: 1) + --display Comma-delimited list of options for displaying information about the + allocation and job.Allowed values: allocation, bind, map, map-devel, + topo + --display-allocation Display the allocation being used by this job + --display-map Display the process map just before launch + --get-stack-traces Get stack traces of all application procs on timeout + --leave-session-attached Do not discard stdout/stderr of remote PRTE daemons + --output-proctable Print the complete proctable to stdout [-], stderr [+], or a file + [anything else] after launch + --report-state-on-timeout Report all job and process states upon timeout + --spawn-timeout Timeout the job if spawn takes more than the specified number of seconds + --stop-on-exec If supported, stop each process at start of execution + --test-suicide Suicide instead of clean abort after delay + --timeout Timeout the job after the specified number of seconds + + + +/***** Output Options *****/ + + --merge-stderr-to-stdout Merge stderr to stdout for each process + --output Comma-delimited list of options that control how output is + generated.Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, + dir=DIRNAME, file=filename. The dir option redirects output from + application processes into DIRNAME/job/rank/std[out,err,diag]. The file + option redirects output from application processes into filename.rank. In + both cases, the provided name will be converted to an absolute path. + Supported qualifiers include NOCOPY (do not copy the output to the + stdout/err streams). + --output-directory Redirect output from application processes into + filename/job/rank/std[out,err,diag]. A relative path value will be + converted to an absolute path. The directory name may include a colon + followed by a comma-delimited list of optional case-insensitive + directives. Supported directives currently include NOJOBID (do not + include a job-id directory level) and NOCOPY (do not copy the output to + the stdout/err streams) + --output-filename Redirect output from application processes into filename.rank. A relative + path value will be converted to an absolute path. The directory name may + include a colon followed by a comma-delimited list of optional + case-insensitive directives. Supported directives currently include + NOCOPY (do not copy the output to the stdout/err streams) + --report-child-jobs-separately Return the exit status of the primary job only + --tag-output Tag all output with [job,rank] + --timestamp-output Timestamp all application process output + --xml Provide all output in XML format + --xterm Create a new xterm window and display output from the specified ranks + there + + + +/***** Input Options *****/ + + --stdin Specify procs to receive stdin [rank, all, none] (default: 0, indicating + rank 0) + + + +/***** Mapping Options *****/ + + --map-by Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | + ppr |,rankfile] with supported colon-delimited modifiers: PE=y (for + multiple cpus/proc), SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, + HWTCPUS, CORECPUS, DEVICE(for dist policy), INHERIT, NOINHERIT, + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job), + FILE= for seq and rankfile options + + + +/***** Ranking Options *****/ + + --rank-by Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache + | l2cache | l3cache | numa (default:np>2) | package | node], with + modifier :SPAN or :FILL + + + +/***** Binding Options *****/ + + --bind-to Binding policy for job. Allowed values: none, hwthread, core, l1cache, + l2cache, l3cache, numa, package, ("none" is the default when + oversubscribed, "core" is the default when np<=2, and "numa" is the + default when np>2). Allowed colon-delimited qualifiers: overload-allowed, + if-supported + + + +/***** Developer Options *****/ + + --display-devel-allocation Display a detailed list (mostly intended for developers) of the + allocation being used by this job + --display-devel-map Display a detailed process map (mostly intended for developers) just + before launch + --display-topo Display the topology as part of the process map (mostly intended for + developers) just before launch + --do-not-launch Perform all necessary operations to prepare to launch the application, + but do not actually launch it (usually used to test mapping patterns) + --report-bindings Whether to report process bindings to stderr + + + +/***** Launch Options *****/ + + --default-hostfile Provide a default hostfile + --gpmixmca Pass global PMIx MCA parameters that are applicable to all contexts (arg0 + is the parameter name; arg1 is the parameter value) +-H|--host List of hosts to invoke processes on + --hostfile Provide a hostfile + --initial-errhandler Specify the initial error handler that is attached to predefined + communicators during the first MPI call. + --machinefile Provide a hostfile + --mca Pass context-specific MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --path PATH to be used to look for executables to start processes + --pmixmca Pass context-specific PMIx MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --preload-files Preload the comma separated list of files to the remote machines current + working directory before starting the remote process. + --prtemca Pass context-specific PRTE MCA parameters; they are considered global if + --gmca is not used and only one context is specified (arg0 is the + parameter name; arg1 is the parameter value) + --pset User-specified name assigned to the processes in their given application + --rankfile Name of file to specify explicit task mapping +-s|--preload-binary Preload the binary on the remote machine before starting the remote + process. + --set-cwd-to-session-dir Set the working directory of the started processes to their session + directory + --show-progress Output a brief periodic report on launch progress + --stream-buffering Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 + fully buffered] + --wd Synonym for --wdir + --wdir Set the working directory of the started processes +-x Export an environment variable, optionally specifying a value (e.g., "-x + foo" exports the environment variable foo and takes its value from the + current environment; "-x foo=bar" exports the environment variable name + foo and sets its value to "bar" in the started processes; "-x foo*" + exports all current environmental variables starting with "foo") + + + +/***** %s Specific Options *****/ + + --allow-run-as-root Allow execution as root (STRONGLY DISCOURAGED) + --daemonize Daemonize the DVM daemons into the background + --forward-signals Comma-delimited list of additional signals (names or integers) to forward + to application processes ["none" => forward nothing]. Signals provided by + default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT + --keepalive Pipe to monitor - DVM will terminate upon closure + --launch-agent Name of daemon executable used to start processes on remote nodes + (default: prted) + --max-vm-size Number of daemons to start + --no-ready-msg Do not print a DVM ready message + --noprefix Disable automatic --prefix behavior + --personality Specify the personality to be used + --prefix Prefix to be used to look for RTE executables + --report-pid Printout pid on stdout [-], stderr [+], or a file [anything else] + --report-uri Printout URI on stdout [-], stderr [+], or a file [anything else] + --set-sid Direct the DVM daemons to separate from the current session + --singleton ID of the singleton process that started us + --system-server Start the DVM as the system server + --tmpdir Set the root for the session directory tree + --tune File(s) containing MCA params for tuning DVM operations + + +Report bugs to %s +# +[usage-prted] +NEED FULL PAGE FOR PRTED +# +[usage-prun] +NEED FULL PAGE FOR PRUN +# +[usage-pterm] +%s (%s) %s + +Usage: %s [OPTION]... +Terminate an instance of the PMIx Reference RTE (PRRTE) DVM + +/***** General Options *****/ + +-h|--help This help message +-h|--help Help for the specified option +-v|--verbose Enable typical debug options +-V|--version Print version and exit + + + +/***** %s Specific Options *****/ + + --dvm-uri Specify the URI of the DVM master, or the name of the file (specified as + file:filename) that contains that info + --num-connect-retries Max number of times to try to connect (int) + --pid PID of the daemon to which we should connect (int => PID or file: + for file containing the PID + --namespace Namespace of the daemon we are to connect to (char*) + --system-server-first First look for a system server and connect to it if found + --system-server-only Connect only to a system-level server + --wait-to-connect Delay specified number of seconds before trying to connect + + +Report bugs to %s +# +[version] +%s (%s) %s + +Report bugs to %s +# +[dvm-uri] +Specify the URI of the DVM master, or the name of the file (specified as +file:filename) that contains that info +# +[num-connect-retries] +Max number of times to try to connect to the specified server (int) +# +[pid] +PID of the daemon to which we should connect (int => PID or file: +for file containing the PID +# +[namespace] +Namespace of the daemon we are to connect to (char*) +# +[system-server-first] +First look for a system server and connect to it if found +# +[system-server-only] +Connect only to a system-level server - abort if one is not found +# +[wait-to-connect] +Delay specified number of seconds before trying to connect +# +[parseable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[parsable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[np] +Specify number of application processes to be started +# +[no-ready-msg] +Do not print a DVM ready message +# +[daemonize] +Daemonize the DVM daemons into the background +# +[system-server] +Start the DVM as the system server +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[report-pid] +Printout PID on stdout [-], stderr [+], or a file [anything else] +# +[report-uri] +Printout URI on stdout [-], stderr [+], or a file [anything else] +# +[test-suicide] +Suicide instead of clean abort after delay +# +[default-hostfile] +Provide a default hostfile +# +[singleton] +ID of the singleton process that started us +# +[keepalive] +Pipe to monitor - DVM will terminate upon closure +# +[map-by] +Mapping Policy for job: + slot + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node + seq + dist + ppr + rankfile +with supported colon-delimited qualifiers: + PE=y (for multiple cpus/proc) + SPAN + OVERSUBSCRIBE + NOOVERSUBSCRIBE + NOLOCAL + HWTCPUS + CORECPUS + DEVICE(for dist policy) + INHERIT + NOINHERIT + PE-LIST=a,b (comma-delimited ranges of cpus to use for this job) + FILE= for seq and rankfile options +# +[rank-by] +Ranking Policy for job: + slot (default: np <= 2) + hwthread + core + l1cache + l2cache + l3cache + numa (default: np > 2) + package + node +with supported colon-delimited qualifiers: + SPAN + FILL +# +[bind-to] +Binding Policy for job: + none (default: oversubscribed) + hwthread + core (default: np <= 2) + l1cache + l2cache + l3cache + numa (default: np > 2) + package +with supported colon-delimited qualifiers: + overload-allowed + if-supported +# +[display] +Comma-delimited list of options for displaying information +about the allocation and job. Allowed values: + allocation + bind + map + map-devel + topo +# +[rankfile] +Name of file to specify explicit task mapping +# +[do-not-launch] +Perform all necessary operations to prepare to launch the +application, but do not actually launch it (usually used +to test mapping patterns) +# +[display-devel-map] +Display a detailed process map (mostly intended for developers) +just before launch +# +[display-topo] +Display the topology as part of the process map (mostly intended +for developers) just before launch +# +[report-bindings] +"Display process bindings to stderr +# +[display-devel-allocation] +Display a detailed list (mostly intended for developers) of the +allocation being used by this job +# +[display-map] +Display the process map just before launch +# +[display-allocation] +Display the allocation being used by this job +# +[enable-recovery] +Enable recovery from process failure [Default = disabled] +# +[max-restarts] +Max number of times to restart a failed process +# +[disable-recovery] +Disable recovery (resets all recovery options to off) +# +[continuous] +Job is to run until explicitly terminated +# +[personality] +Specify the personality to be used +# +[prte-server] +Specify the URI of the publish/lookup server, or the name +of the file (specified as file:filename) that contains that info +# +[dvm-master-uri] +URI for the DVM master +# +[parent-uri] +URI for the parent if tree launch is enabled +# +[tree-spawn] +Tree-based spawn in progress +# +[daemonize] +Daemonize the DVM daemons into the background +# +[set-sid] +Direct the DVM daemons to separate from the current session +# +[prtemca] +Pass context-specific PRTE MCA parameters (arg0 is the +parameter name; arg1 is the parameter value) +# +[pmixmca] +Pass context-specific PMIx MCA parameters (arg0 is the +parameter name; arg1 is the parameter value) +# +[debug-daemons-file] +Enable debugging of any PRTE daemons used by this +application, storing output in files +# +[leave-session-attached] +Do not discard stdout/stderr of remote PRTE daemons diff --git a/src/mca/schizo/prte/owner.txt b/src/mca/schizo/prte/owner.txt index 85b4416d20..6b52c34f63 100644 --- a/src/mca/schizo/prte/owner.txt +++ b/src/mca/schizo/prte/owner.txt @@ -3,5 +3,5 @@ # owner: institution that is responsible for this package # status: e.g. active, maintenance, unmaintained # -owner: INTEL +owner: Nanook Consulting status: active diff --git a/src/mca/schizo/prte/schizo_prte.c b/src/mca/schizo/prte/schizo_prte.c index 22bad1e516..8f37633362 100644 --- a/src/mca/schizo/prte/schizo_prte.c +++ b/src/mca/schizo/prte/schizo_prte.c @@ -18,7 +18,7 @@ * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2018-2021 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -34,6 +34,8 @@ # include #endif #include +#include + #include "src/util/argv.h" #include "src/util/basename.h" @@ -55,670 +57,677 @@ #include "schizo_prte.h" #include "src/mca/schizo/base/base.h" -static int define_cli(prte_cmd_line_t *cli); -static int check_help(prte_cmd_line_t *cli, char **argv); -static int parse_cli(int argc, int start, char **argv, char ***target); -static int parse_deprecated_cli(prte_cmd_line_t *cmdline, int *argc, char ***argv); -static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, bool cmdline); -static int setup_fork(prte_job_t *jdata, prte_app_context_t *context); +static int parse_cli(char **argv, prte_cli_result_t *results); static int detect_proxy(char *argv); -static void allow_run_as_root(prte_cmd_line_t *cmd_line); -static void job_info(prte_cmd_line_t *cmdline, void *jobinfo); +static int parse_env(char **srcenv, char ***dstenv, prte_cli_result_t *cli); +static void allow_run_as_root(prte_cli_result_t *results); +static int setup_fork(prte_job_t *jdata, prte_app_context_t *context); +static void job_info(prte_cli_result_t *results, + void *jobinfo); prte_schizo_base_module_t prte_schizo_prte_module = { .name = "prte", - .define_cli = define_cli, - .check_help = check_help, .parse_cli = parse_cli, - .parse_deprecated_cli = parse_deprecated_cli, .parse_env = parse_env, .setup_fork = setup_fork, .detect_proxy = detect_proxy, .allow_run_as_root = allow_run_as_root, - .check_sanity = prte_schizo_base_sanity, .job_info = job_info }; -static prte_cmd_line_init_t prte_cmd_line_init[] = { +static struct option prteoptions[] = { + /* basic options */ + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PRTE_ARG_NONE, 'v'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSEABLE, PRTE_ARG_NONE, 'p'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSABLE, PRTE_ARG_NONE, 'p'), // synonym for parseable + + // MCA parameters + PRTE_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TUNE, PRTE_ARG_REQD), + + // DVM options + PRTE_OPTION_DEFINE(PRTE_CLI_NO_READY_MSG, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DAEMONIZE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SYSTEM_SERVER, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SET_SID, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_PID, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_URI, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TEST_SUICIDE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DEFAULT_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SINGLETON, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_KEEPALIVE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_LAUNCH_AGENT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_MAX_VM_SIZE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS_FILE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_LEAVE_SESSION_ATTACHED, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_TMPDIR, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PREFIX, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NOPREFIX, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_FWD_SIGNALS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_RUN_AS_ROOT, PRTE_ARG_NONE), + + // Launch options + PRTE_OPTION_DEFINE(PRTE_CLI_TIMEOUT, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_FWD_ENVAR, PRTE_ARG_REQD, 'x'), + PRTE_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HOST, PRTE_ARG_REQD, 'H'), + + // output options + PRTE_OPTION_DEFINE(PRTE_CLI_STREAM_BUF, PRTE_ARG_REQD), + + /* developer options */ + PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DISPLAY, PRTE_ARG_REQD), + + // deprecated options + PRTE_OPTION_DEFINE("mca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("machinefile", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("xml", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-topo", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("report-bindings", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-allocation", PRTE_ARG_NONE), + + PRTE_OPTION_END +}; +static char *prteshorts = "h::vVpx:H:"; + +static struct option prterunoptions[] = { /* basic options */ - {'h', "help", 0, PRTE_CMD_LINE_TYPE_BOOL, "This help message", PRTE_CMD_LINE_OTYPE_GENERAL}, - {'V', "version", 0, PRTE_CMD_LINE_TYPE_BOOL, "Print version and exit", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'v', "verbose", 0, PRTE_CMD_LINE_TYPE_BOOL, "Be verbose", PRTE_CMD_LINE_OTYPE_GENERAL}, - {'q', "quiet", 0, PRTE_CMD_LINE_TYPE_BOOL, "Suppress helpful messages", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "parsable", 0, PRTE_CMD_LINE_TYPE_BOOL, - "When used in conjunction with other parameters, the output is displayed in a " - "machine-parsable format", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "parseable", 0, PRTE_CMD_LINE_TYPE_BOOL, "Synonym for --parsable", - PRTE_CMD_LINE_OTYPE_GENERAL}, - - /* prterun options */ - /* Specify the launch agent to be used */ - {'\0', "launch-agent", 1, PRTE_CMD_LINE_TYPE_STRING, - "Name of daemon executable used to start processes on remote nodes (default: prted)", - PRTE_CMD_LINE_OTYPE_DVM}, - /* maximum size of VM - typically used to subdivide an allocation */ - {'\0', "max-vm-size", 1, PRTE_CMD_LINE_TYPE_INT, "Number of daemons to start", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "debug-daemons", 0, PRTE_CMD_LINE_TYPE_BOOL, "Debug daemons", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-daemons-file", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Enable debugging of any PRTE daemons used by this application, storing output in files", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "leave-session-attached", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Do not discard stdout/stderr of remote PRTE daemons", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "tmpdir", 1, PRTE_CMD_LINE_TYPE_STRING, "Set the root for the session directory tree", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "prefix", 1, PRTE_CMD_LINE_TYPE_STRING, "Prefix to be used to look for RTE executables", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "noprefix", 0, PRTE_CMD_LINE_TYPE_BOOL, "Disable automatic --prefix behavior", - PRTE_CMD_LINE_OTYPE_DVM}, - - /* setup MCA parameters */ - {'\0', "mca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific MCA parameters; they are considered global if --gmca is not used and " - "only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* setup MCA parameters */ - {'\0', "prtemca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific PRTE MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "pmixmca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific PMIx MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "gpmixmca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass global PMIx MCA parameters that are applicable to all contexts (arg0 is the parameter " - "name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "tune", 1, PRTE_CMD_LINE_TYPE_STRING, - "File(s) containing MCA params for tuning DVM operations", PRTE_CMD_LINE_OTYPE_DVM}, - - /* forward signals */ - {'\0', "forward-signals", 1, PRTE_CMD_LINE_TYPE_STRING, - "Comma-delimited list of additional signals (names or integers) to forward to " - "application processes [\"none\" => forward nothing]. Signals provided by " - "default include SIGTSTP, SIGUSR1, SIGUSR2, SIGABRT, SIGALRM, and SIGCONT", - PRTE_CMD_LINE_OTYPE_DVM}, - - {'\0', "debug", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Top-level PRTE debug switch (default: false) " - "This option will be deprecated, use --debug-devel instead.", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-verbose", 1, PRTE_CMD_LINE_TYPE_INT, - "Verbosity level for PRTE debug messages (default: 1)", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'d', "debug-devel", 0, PRTE_CMD_LINE_TYPE_BOOL, "Enable debugging of PRTE", - PRTE_CMD_LINE_OTYPE_DEBUG}, - - {'\0', "timeout", 1, PRTE_CMD_LINE_TYPE_INT, - "Timeout the job after the specified number of seconds", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "report-state-on-timeout", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Report all job and process states upon timeout", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "get-stack-traces", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Get stack traces of all application procs on timeout", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PRTE_ARG_NONE, 'v'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSEABLE, PRTE_ARG_NONE, 'p'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSABLE, PRTE_ARG_NONE, 'p'), // synonym for parseable + + // MCA parameters + PRTE_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TUNE, PRTE_ARG_REQD), + + // DVM options + PRTE_OPTION_DEFINE(PRTE_CLI_DAEMONIZE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SYSTEM_SERVER, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SET_SID, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_PID, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_URI, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TEST_SUICIDE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DEFAULT_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SINGLETON, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_KEEPALIVE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_LAUNCH_AGENT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_MAX_VM_SIZE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS_FILE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_LEAVE_SESSION_ATTACHED, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_TMPDIR, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PREFIX, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NOPREFIX, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_FWD_SIGNALS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PERSONALITY, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_RUN_AS_ROOT, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_CHILD_SEP, PRTE_ARG_NONE), + + // Launch options + PRTE_OPTION_DEFINE(PRTE_CLI_TIMEOUT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_STATE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_STACK_TRACES, PRTE_ARG_NONE), #ifdef PMIX_SPAWN_TIMEOUT - {'\0', "spawn-timeout", 1, PRTE_CMD_LINE_TYPE_INT, - "Timeout the job if spawn takes more than the specified number of seconds", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_SPAWN_TIMEOUT, PRTE_ARG_REQD), #endif + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'n'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'c'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NPERNODE, PRTE_ARG_REQD, 'N'), + PRTE_OPTION_DEFINE(PRTE_CLI_APPFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_XTERM, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_ON_EXEC, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_IN_INIT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_IN_APP, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_FWD_ENVAR, PRTE_ARG_REQD, 'x'), + PRTE_OPTION_DEFINE(PRTE_CLI_WDIR, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("wd", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SET_CWD_SESSION, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_PATH, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PSET, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("machinefile", PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HOST, PRTE_ARG_REQD, 'H'), + PRTE_OPTION_DEFINE(PRTE_CLI_PRELOAD_FILES, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PRELOAD_BIN, PRTE_ARG_NONE, 's'), + + // output options + PRTE_OPTION_DEFINE(PRTE_CLI_OUTPUT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STREAM_BUF, PRTE_ARG_REQD), + + // input options + PRTE_OPTION_DEFINE(PRTE_CLI_STDIN, PRTE_ARG_REQD), - {'\0', "allow-run-as-root", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Allow execution as root (STRONGLY DISCOURAGED)", PRTE_CMD_LINE_OTYPE_DVM}, /* End of list */ - - /* Conventional options - for historical compatibility, support - * both single and multi dash versions */ - /* Number of processes; -c, -n, --n, -np, and --np are all - synonyms */ - {'c', "np", 1, PRTE_CMD_LINE_TYPE_INT, "Number of processes to run", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'n', "n", 1, PRTE_CMD_LINE_TYPE_INT, "Number of processes to run", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'N', NULL, 1, PRTE_CMD_LINE_TYPE_INT, "Number of processes to run per node", - PRTE_CMD_LINE_OTYPE_GENERAL}, - /* Use an appfile */ - {'\0', "app", 1, PRTE_CMD_LINE_TYPE_STRING, - "Provide an appfile; ignore all other command line options", PRTE_CMD_LINE_OTYPE_GENERAL}, - - /* output options */ - {'\0', "output", 1, PRTE_CMD_LINE_TYPE_STRING, - "Comma-delimited list of options that control how output is generated." - "Allowed values: tag, timestamp, xml, merge-stderr-to-stdout, dir=DIRNAME, file=filename." - " The dir option redirects output from application processes into DIRNAME/job/rank/std[out,err,diag]." - " The file option redirects output from application processes into filename.rank. In both cases, " - "the provided name will be converted to an absolute path. Supported qualifiers include NOCOPY" - " (do not copy the output to the stdout/err streams).", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - /* exit status reporting */ - {'\0', "report-child-jobs-separately", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Return the exit status of the primary job only", PRTE_CMD_LINE_OTYPE_OUTPUT}, - /* select XML output */ - {'\0', "xml", 0, PRTE_CMD_LINE_TYPE_BOOL, "Provide all output in XML format", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - /* tag output */ - {'\0', "tag-output", 0, PRTE_CMD_LINE_TYPE_BOOL, "Tag all output with [job,rank]", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "timestamp-output", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Timestamp all application process output", PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "output-directory", 1, PRTE_CMD_LINE_TYPE_STRING, - "Redirect output from application processes into filename/job/rank/std[out,err,diag]. A " - "relative path value will be converted to an absolute path. The directory name may include a " - "colon followed by a comma-delimited list of optional case-insensitive directives. Supported " - "directives currently include NOJOBID (do not include a job-id directory level) and NOCOPY " - "(do not copy the output to the stdout/err streams)", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "output-filename", 1, PRTE_CMD_LINE_TYPE_STRING, - "Redirect output from application processes into filename.rank. A relative path value will be " - "converted to an absolute path. The directory name may include a colon followed by a " - "comma-delimited list of optional case-insensitive directives. Supported directives currently " - "include NOCOPY (do not copy the output to the stdout/err streams)", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "merge-stderr-to-stdout", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Merge stderr to stdout for each process", PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "xterm", 1, PRTE_CMD_LINE_TYPE_STRING, - "Create a new xterm window and display output from the specified ranks there", - PRTE_CMD_LINE_OTYPE_OUTPUT}, - {'\0', "stream-buffering", 1, PRTE_CMD_LINE_TYPE_STRING, - "Adjust buffering for stdout/stderr [0 unbuffered] [1 line buffered] [2 fully buffered]", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - - /* input options */ - /* select stdin option */ - {'\0', "stdin", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify procs to receive stdin [rank, all, none] (default: 0, indicating rank 0)", - PRTE_CMD_LINE_OTYPE_INPUT}, - - /* debugger options */ - {'\0', "output-proctable", 1, PRTE_CMD_LINE_TYPE_STRING, - "Print the complete proctable to stdout [-], stderr [+], or a file [anything else] after " - "launch", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "stop-on-exec", 0, PRTE_CMD_LINE_TYPE_BOOL, - "If supported, stop each process at start of execution", PRTE_CMD_LINE_OTYPE_DEBUG}, - - /* launch options */ - /* Preload the binary on the remote machine */ - {'s', "preload-binary", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Preload the binary on the remote machine before starting the remote process.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* Preload files on the remote machine */ - {'\0', "preload-files", 1, PRTE_CMD_LINE_TYPE_STRING, - "Preload the comma separated list of files to the remote machines current working directory " - "before starting the remote process.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* Export environment variables; potentially used multiple times, - so it does not make sense to set into a variable */ - {'x', NULL, 1, PRTE_CMD_LINE_TYPE_STRING, - "Export an environment variable, optionally specifying a value (e.g., \"-x foo\" exports the " - "environment variable foo and takes its value from the current environment; \"-x foo=bar\" " - "exports the environment variable name foo and sets its value to \"bar\" in the started " - "processes; \"-x foo*\" exports all current environmental variables starting with \"foo\")", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "wdir", 1, PRTE_CMD_LINE_TYPE_STRING, - "Set the working directory of the started processes", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "wd", 1, PRTE_CMD_LINE_TYPE_STRING, "Synonym for --wdir", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "set-cwd-to-session-dir", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Set the working directory of the started processes to their session directory", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "path", 1, PRTE_CMD_LINE_TYPE_STRING, - "PATH to be used to look for executables to start processes", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "show-progress", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Output a brief periodic report on launch progress", PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "pset", 1, PRTE_CMD_LINE_TYPE_STRING, - "User-specified name assigned to the processes in their given application", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - /* Set a hostfile */ - {'\0', "hostfile", 1, PRTE_CMD_LINE_TYPE_STRING, "Provide a hostfile", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "machinefile", 1, PRTE_CMD_LINE_TYPE_STRING, "Provide a hostfile", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'H', "host", 1, PRTE_CMD_LINE_TYPE_STRING, "List of hosts to invoke processes on", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - - /* placement options */ /* Mapping options */ - {'\0', "map-by", 1, PRTE_CMD_LINE_TYPE_STRING, - "Mapping Policy for job [slot | hwthread | core (default:np<=2) | l1cache | " - "l2cache | l3cache | numa (default:np>2) | package | node | seq | dist | ppr |," - "rankfile]" - " with supported colon-delimited modifiers: PE=y (for multiple cpus/proc), " - "SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, HWTCPUS, CORECPUS, " - "DEVICE(for dist policy), INHERIT, NOINHERIT, PE-LIST=a,b (comma-delimited " - "ranges of cpus to use for this job), FILE= for seq and rankfile options", - PRTE_CMD_LINE_OTYPE_MAPPING}, + PRTE_OPTION_DEFINE(PRTE_CLI_MAPBY, PRTE_ARG_REQD), /* Ranking options */ - {'\0', "rank-by", 1, PRTE_CMD_LINE_TYPE_STRING, - "Ranking Policy for job [slot (default:np<=2) | hwthread | core | l1cache " - "| l2cache | l3cache | numa (default:np>2) | package | node], with modifier :SPAN or :FILL", - PRTE_CMD_LINE_OTYPE_RANKING}, + PRTE_OPTION_DEFINE(PRTE_CLI_RANKBY, PRTE_ARG_REQD), /* Binding options */ - {'\0', "bind-to", 1, PRTE_CMD_LINE_TYPE_STRING, - "Binding policy for job. Allowed values: none, hwthread, core, l1cache, l2cache, " - "l3cache, numa, package, (\"none\" is the default when oversubscribed, \"core\" is " - "the default when np<=2, and \"numa\" is the default when np>2). Allowed colon-delimited " - "qualifiers: " - "overload-allowed, if-supported", - PRTE_CMD_LINE_OTYPE_BINDING}, - - /* rankfile */ - {'\0', "rankfile", 1, PRTE_CMD_LINE_TYPE_STRING, - "Name of file to specify explicit task mapping", PRTE_CMD_LINE_OTYPE_LAUNCH}, + PRTE_OPTION_DEFINE(PRTE_CLI_BINDTO, PRTE_ARG_REQD), /* display options */ - {'\0', "display", 1, PRTE_CMD_LINE_TYPE_STRING, - "Comma-delimited list of options for displaying information about the allocation and job." - "Allowed values: allocation, bind, map, map-devel, topo", - PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_DISPLAY, PRTE_ARG_REQD), + /* developer options */ - {'\0', "do-not-launch", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Perform all necessary operations to prepare to launch the application, but do not actually " - "launch it (usually used to test mapping patterns)", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-devel-map", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display a detailed process map (mostly intended for developers) just before launch", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-topo", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display the topology as part of the process map (mostly intended for developers) just before " - "launch", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "report-bindings", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Whether to report process bindings to stderr", PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-devel-allocation", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display a detailed list (mostly intended for developers) of the allocation being used by " - "this job", - PRTE_CMD_LINE_OTYPE_DEVEL}, - {'\0', "display-map", 0, PRTE_CMD_LINE_TYPE_BOOL, "Display the process map just before launch", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "display-allocation", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display the allocation being used by this job", PRTE_CMD_LINE_OTYPE_DEBUG}, + PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PRTE_ARG_REQD), #if PRTE_ENABLE_FT - {'\0', "enable-recovery", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Enable recovery from process failure [Default = disabled]", PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "max-restarts", 1, PRTE_CMD_LINE_TYPE_INT, - "Max number of times to restart a failed process", PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "disable-recovery", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Disable recovery (resets all recovery options to off)", PRTE_CMD_LINE_OTYPE_FT}, - {'\0', "continuous", 0, PRTE_CMD_LINE_TYPE_BOOL, "Job is to run until explicitly terminated", - PRTE_CMD_LINE_OTYPE_FT}, + PRTE_OPTION_DEFINE(PRTE_CLI_ENABLE_RECOVERY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_MAX_RESTARTS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DISABLE_RECOVERY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_CONTINUOUS, PRTE_ARG_NONE), #endif - /* mpiexec mandated form launch key parameters */ - {'\0', "initial-errhandler", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify the initial error handler that is attached to predefined communicators during the " - "first MPI call.", - PRTE_CMD_LINE_OTYPE_LAUNCH}, + // deprecated options + PRTE_OPTION_DEFINE("mca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("xml", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("tag-output", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("timestamp-output", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("output-directory", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("output-filename", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("merge-stderr-to-stdout", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-topo", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("report-bindings", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("rankfile", PRTE_ARG_REQD), + + PRTE_OPTION_END +}; +static char *prterunshorts = "h::vVpn:c:N:sH:x:"; - /* Display Commumication Protocol : MPI_Init */ - {'\0', "display-comm", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display table of communication methods between ranks during MPI_Init", - PRTE_CMD_LINE_OTYPE_GENERAL}, +static struct option prunoptions[] = { + /* basic options */ + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PRTE_ARG_NONE, 'v'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSEABLE, PRTE_ARG_NONE, 'p'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PARSABLE, PRTE_ARG_NONE, 'p'), // synonym for parseable + + // MCA parameters + PRTE_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TUNE, PRTE_ARG_REQD), + // DVM options + PRTE_OPTION_DEFINE(PRTE_CLI_SYS_SERVER_FIRST, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SYS_SERVER_ONLY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_CONNECT, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_WAIT_TO_CONNECT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NUM_CONNECT_RETRIES, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PID, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NAMESPACE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DVM_URI, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PERSONALITY, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_RUN_AS_ROOT, PRTE_ARG_NONE), + + // Launch options + PRTE_OPTION_DEFINE(PRTE_CLI_TIMEOUT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_REPORT_STATE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_STACK_TRACES, PRTE_ARG_NONE), +#ifdef PMIX_SPAWN_TIMEOUT + PRTE_OPTION_DEFINE(PRTE_CLI_SPAWN_TIMEOUT, PRTE_ARG_REQD), +#endif + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'n'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'c'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NPERNODE, PRTE_ARG_REQD, 'N'), + PRTE_OPTION_DEFINE(PRTE_CLI_APPFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_APPFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_XTERM, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_ON_EXEC, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_IN_INIT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STOP_IN_APP, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_FWD_ENVAR, PRTE_ARG_REQD, 'x'), + PRTE_OPTION_DEFINE(PRTE_CLI_WDIR, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("wd", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SET_CWD_SESSION, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_PATH, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PSET, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_HOSTFILE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("machinefile", PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HOST, PRTE_ARG_REQD, 'H'), + PRTE_OPTION_DEFINE(PRTE_CLI_PRELOAD_FILES, PRTE_ARG_REQD), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_PRELOAD_BIN, PRTE_ARG_NONE, 's'), + + // output options + PRTE_OPTION_DEFINE(PRTE_CLI_OUTPUT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_STREAM_BUF, PRTE_ARG_REQD), + + // input options + PRTE_OPTION_DEFINE(PRTE_CLI_STDIN, PRTE_ARG_REQD), - /* Display Commumication Protocol : MPI_Finalize */ - {'\0', "display-comm-finalize", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Display table of communication methods between ranks during MPI_Finalize", - PRTE_CMD_LINE_OTYPE_GENERAL}, + /* Mapping options */ + PRTE_OPTION_DEFINE(PRTE_CLI_MAPBY, PRTE_ARG_REQD), - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; - -static prte_cmd_line_init_t prte_dvm_cmd_line_init[] = { - /* do not print a "ready" message */ - {'\0', "no-ready-msg", 0, PRTE_CMD_LINE_TYPE_BOOL, "Do not print a DVM ready message", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "daemonize", 0, PRTE_CMD_LINE_TYPE_BOOL, "Daemonize the DVM daemons into the background", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "system-server", 0, PRTE_CMD_LINE_TYPE_BOOL, "Start the DVM as the system server", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "set-sid", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Direct the DVM daemons to separate from the current session", PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "report-pid", 1, PRTE_CMD_LINE_TYPE_STRING, - "Printout pid on stdout [-], stderr [+], or a file [anything else]", PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "report-uri", 1, PRTE_CMD_LINE_TYPE_STRING, - "Printout URI on stdout [-], stderr [+], or a file [anything else]", PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "test-suicide", 1, PRTE_CMD_LINE_TYPE_BOOL, "Suicide instead of clean abort after delay", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "default-hostfile", 1, PRTE_CMD_LINE_TYPE_STRING, "Provide a default hostfile", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "singleton", 1, PRTE_CMD_LINE_TYPE_STRING, "ID of the singleton process that started us", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "keepalive", 1, PRTE_CMD_LINE_TYPE_INT, - "Pipe to monitor - DVM will terminate upon closure", PRTE_CMD_LINE_OTYPE_DVM}, + /* Ranking options */ + PRTE_OPTION_DEFINE(PRTE_CLI_RANKBY, PRTE_ARG_REQD), - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; + /* Binding options */ + PRTE_OPTION_DEFINE(PRTE_CLI_BINDTO, PRTE_ARG_REQD), -static int define_cli(prte_cmd_line_t *cli) -{ - int rc; + /* display options */ + PRTE_OPTION_DEFINE(PRTE_CLI_DISPLAY, PRTE_ARG_REQD), - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:prte: define_cli", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); + /* developer options */ + PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PRTE_ARG_REQD), - /* protect against bozo error */ - if (NULL == cli) { - return PRTE_ERR_BAD_PARAM; - } +#if PRTE_ENABLE_FT + PRTE_OPTION_DEFINE(PRTE_CLI_ENABLE_RECOVERY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_MAX_RESTARTS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DISABLE_RECOVERY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_CONTINUOUS, PRTE_ARG_NONE), +#endif - rc = prte_cmd_line_add(cli, prte_cmd_line_init); - if (PRTE_SUCCESS != rc) { - return rc; - } + // deprecated options + PRTE_OPTION_DEFINE("mca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("gmca", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("xml", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("tag-output", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("timestamp-output", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("output-directory", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("output-filename", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("merge-stderr-to-stdout", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-topo", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("report-bindings", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-devel-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-map", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("display-allocation", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("rankfile", PRTE_ARG_REQD), + + PRTE_OPTION_END +}; +static char *prunshorts = "h::vVpn:c:N:sH:x:"; - if (PRTE_PROC_IS_MASTER) { - rc = prte_cmd_line_add(cli, prte_dvm_cmd_line_init); - if (PRTE_SUCCESS != rc) { - return rc; - } - } +static struct option prtedoptions[] = { + /* basic options */ + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PRTE_ARG_NONE, 'v'), + + // MCA parameters + PRTE_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PRTE_ARG_REQD), + + // DVM options + PRTE_OPTION_DEFINE(PRTE_CLI_PUBSUB_SERVER, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_CONTROLLER_URI, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PARENT_URI, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_TREE_SPAWN, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DAEMONIZE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SYSTEM_SERVER, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SET_SID, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_DEBUG_DAEMONS_FILE, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_LEAVE_SESSION_ATTACHED, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_TEST_SUICIDE, PRTE_ARG_NONE), + + PRTE_OPTION_END +}; +static char *prtedshorts = "hvV"; - return PRTE_SUCCESS; -} +static struct option ptermoptions[] = { + /* basic options */ + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERBOSE, PRTE_ARG_NONE, 'v'), + + // MCA parameters + PRTE_OPTION_DEFINE(PRTE_CLI_PRTEMCA, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PMIXMCA, PRTE_ARG_REQD), + + // DVM options + PRTE_OPTION_DEFINE(PRTE_CLI_SYS_SERVER_FIRST, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_SYS_SERVER_ONLY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_WAIT_TO_CONNECT, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NUM_CONNECT_RETRIES, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_PID, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_NAMESPACE, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DVM_URI, PRTE_ARG_REQD), + + PRTE_OPTION_END +}; +static char *ptermshorts = "hvV"; -static int check_help(prte_cmd_line_t *cli, char **argv) -{ - if (prte_cmd_line_is_taken(cli, "help")) { - char *str, *args = NULL; - args = prte_cmd_line_get_usage_msg(cli, false); - str = prte_show_help_string("help-prun.txt", "prun:usage", false, prte_tool_basename, - "PRTE", PRTE_VERSION, prte_tool_basename, args, - PACKAGE_BUGREPORT); - if (NULL != str) { - printf("%s", str); - free(str); - } - free(args); +static struct option pinfooptions[] = { + /* basic options */ + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_HELP, PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_VERSION, PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE("all", PRTE_ARG_NONE, 'a'), + PRTE_OPTION_SHORT_DEFINE("config", PRTE_ARG_NONE, 'c'), - /* If someone asks for help, that should be all we do */ - return PRTE_ERR_SILENT; - } + PRTE_OPTION_DEFINE("param", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("internal", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("path", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("arch", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("hostname", PRTE_ARG_NONE), - return PRTE_SUCCESS; -} + /* End of list */ + PRTE_OPTION_END +}; +static char *pinfoshorts = "hVac"; + +static int convert_deprecated_cli(prte_cli_result_t *results); -static int parse_cli(int argc, int start, char **argv, char ***target) +static int parse_cli(char **argv, prte_cli_result_t *results) { - int i; - - prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:prte: parse_cli", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); + char *shorts, *helpfile; + struct option *myoptions; + int rc, n; + prte_cli_item_t *opt; + + if (0 == strcmp(prte_tool_actual, "prte")) { + myoptions = prteoptions; + shorts = prteshorts; + helpfile = "help-schizo-prte.txt"; + } else if (0 == strcmp(prte_tool_actual, "prterun")) { + myoptions = prterunoptions; + shorts = prterunshorts; + helpfile = "help-schizo-prterun.txt"; + } else if (0 == strcmp(prte_tool_actual, "prted")) { + myoptions = prtedoptions; + shorts = prtedshorts; + helpfile = "help-schizo-prted.txt"; + } else if (0 == strcmp(prte_tool_actual, "prun")) { + myoptions = prunoptions; + shorts = prunshorts; + helpfile = "help-schizo-prun.txt"; + } else if (0 == strcmp(prte_tool_actual, "pterm")) { + myoptions = ptermoptions; + shorts = ptermshorts; + helpfile = "help-schizo-pterm.txt"; + } else if (0 == strcmp(prte_tool_actual, "prte_info")) { + myoptions = pinfooptions; + shorts = pinfoshorts; + helpfile = "help-schizo-pinfo.txt"; + } + rc = prte_cmd_line_parse(argv, shorts, myoptions, NULL, + results, helpfile); + if (PRTE_SUCCESS != rc) { + return rc; + } - for (i = 0; i < (argc - start); ++i) { - if (0 == strcmp("--mca", argv[i])) { - /* this is an unrecognized generic param */ - prte_show_help("help-schizo-base.txt", "unrecog-generic-param", - true, argv[i+1], argv[i+2]); - return PRTE_ERR_SILENT; - } + /* check for deprecated options - warn and convert them */ + rc = convert_deprecated_cli(results); + if (PRTE_SUCCESS != rc) { + return rc; } + // handle relevant MCA params + PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { + if (0 == strcmp(opt->key, PRTE_CLI_PRTEMCA)) { + for (n=0; NULL != opt->values[n]; n++) { + prte_schizo_base_expose(opt->values[n], "PRTE_MCA_"); + } + } else if (0 == strcmp(opt->key, PRTE_CLI_PMIXMCA)) { + for (n=0; NULL != opt->values[n]; n++) { + prte_schizo_base_expose(opt->values[n], "PMIX_MCA_"); + } + } + } return PRTE_SUCCESS; -} +}; -static int convert_deprecated_cli(char *option, char ***argv, int i) +static int convert_deprecated_cli(prte_cli_result_t *results) { - int rc = PRTE_ERR_NOT_FOUND; - char **pargs = *argv; - char *p1, *p2, *tmp, *tmp2, *output; - - /* --display-devel-map -> --display allocation-devel */ - if (0 == strcmp(option, "--display-devel-map")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "map-devel", true); - } - /* --output-proctable -> --display map-devel */ - else if (0 == strcmp(option, "--output-proctable")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "map-devel", true); - } - /* --display-map -> --display map */ - else if (0 == strcmp(option, "--display-map")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "map", true); - } - /* --display-topo -> --display topo */ - else if (0 == strcmp(option, "--display-topo")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "topo", true); - } - /* --report-bindings -> --display bind */ - else if (0 == strcmp(option, "--report-bindings")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "bind", true); - } - /* --display-allocation -> --display allocation */ - else if (0 == strcmp(option, "--display-allocation")) { - rc = prte_schizo_base_convert(argv, i, 1, "--display", NULL, "allocation", true); - } - /* --do-not-launch -> --map-by :donotlaunch*/ - else if (0 == strcmp(option, "--do-not-launch")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", NULL, "DONOTLAUNCH", true); - } - /* --do-not-resolve -> --map-by :donotresolve*/ - else if (0 == strcmp(option, "--do-not-resolve")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", NULL, "DONOTRESOLVE", true); - } - /* --tag-output -> "--output tag */ - else if (0 == strcmp(option, "--tag-output")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", NULL, "tag", true); - } - /* --timestamp-output -> --output timestamp */ - else if (0 == strcmp(option, "--timestamp-output")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", NULL, "timestamp", true); - } - /* --output-directory DIR -> --output dir=DIR */ - else if (0 == strcmp(option, "--output-directory")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", "dir", pargs[i + 1], true); - } - /* --output-filename DIR -> --output file=file */ - else if (0 == strcmp(option, "--output-filename")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", "file", pargs[i + 1], true); - } - /* --xml -> --output xml */ - else if (0 == strcmp(option, "--xml")) { - rc = prte_schizo_base_convert(argv, i, 1, "--output", NULL, "xml", true); - } - /* -N -> map-by ppr:N:node */ - else if (0 == strcmp(option, "-N")) { - prte_asprintf(&p2, "ppr:%s:node", pargs[i + 1]); - rc = prte_schizo_base_convert(argv, i, 2, "--map-by", p2, NULL, true); - free(p2); - } - /* -N -> map-by ppr:N:node */ - else if (0 == strcmp(option, "--debug")) { - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, option, - "--debug-devel"); - fprintf(stderr, "%s\n", output); - pargs[i] = "--debug-devel"; - free(output); - rc = PRTE_ERR_TAKE_NEXT_OPTION; - } - /* --map-by socket -> --map-by package */ - else if (0 == strcmp(option, "--map-by")) { - /* check the value of the option for "socket" */ - if (0 == strncasecmp(pargs[i + 1], "socket", strlen("socket"))) { - p1 = strdup(pargs[i + 1]); // save the original option - /* replace "socket" with "package" */ - if (NULL == (p2 = strchr(pargs[i + 1], ':'))) { - /* no modifiers */ - tmp = strdup("package"); - } else { - *p2 = '\0'; - ++p2; - prte_asprintf(&tmp, "package:%s", p2); - } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); - free(p1); + char *option, *p1, *p2, *tmp, *tmp2, *output, *modifier; + int rc = PRTE_SUCCESS; + prte_cli_item_t *opt; + prte_value_t *pval, val; + + PRTE_LIST_FOREACH(opt, &results->instances, prte_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); + } + /* --nolocal -> --map-by :nolocal */ + else if (0 == strcmp(option, "nolocal")) { + rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, "NOLOCAL", true); + } + /* --oversubscribe -> --map-by :OVERSUBSCRIBE */ + else if (0 == strcmp(option, "oversubscribe")) { + rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, "OVERSUBSCRIBE", true); + } + /* --nooversubscribe -> --map-by :NOOVERSUBSCRIBE */ + else if (0 == strcmp(option, "nooversubscribe")) { + rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, "NOOVERSUBSCRIBE", true); + } + /* --use-hwthread-cpus -> --bind-to hwthread */ + else if (0 == strcmp(option, "use-hwthread-cpus")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, "hwthread", true); + } + /* --cpu-set and --cpu-list -> --map-by pe-list:X + */ + else if (0 == strcmp(option, "cpu-set") || 0 == strcmp(option, "cpu-list")) { + prte_asprintf(&p2, "PE-LIST=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; } - rc = PRTE_OPERATION_SUCCEEDED; - } - /* --rank-by socket -> --rank-by package */ - else if (0 == strcmp(option, "--rank-by")) { - /* check the value of the option for "socket" */ - if (0 == strncasecmp(pargs[i + 1], "socket", strlen("socket"))) { - p1 = strdup(pargs[i + 1]); // save the original option - /* replace "socket" with "package" */ - if (NULL == (p2 = strchr(pargs[i + 1], ':'))) { - /* no modifiers */ - tmp = strdup("package"); - } else { - *p2 = '\0'; - ++p2; - prte_asprintf(&tmp, "package:%s", p2); - } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); - free(p1); + /* --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, "core", true); + } else if (0 == strcmp(option, "bind-to-socket")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, "socket", true); + } + /* --bynode -> "--map-by X --rank-by X" */ + else if (0 == strcmp(option, "bynode")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, "node", true); + } + /* --bycore -> "--map-by X --rank-by X" */ + else if (0 == strcmp(option, "bycore")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, "core", true); + } + /* --byslot -> "--map-by X --rank-by X" */ + else if (0 == strcmp(option, "byslot")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, "slot", true); + } + /* --cpus-per-proc/rank X -> --map-by :pe=X */ + else if (0 == strcmp(option, "cpus-per-proc") || 0 == strcmp(option, "cpus-per-rank")) { + prte_asprintf(&p2, ":pe=%s", opt->values[0]); + rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, p2, true); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; } - rc = PRTE_OPERATION_SUCCEEDED; - } - /* --bind-to socket -> --bind-to package */ - else if (0 == strcmp(option, "--bind-to")) { - /* check the value of the option for "socket" */ - if (0 == strncasecmp(pargs[i + 1], "socket", strlen("socket"))) { - p1 = strdup(pargs[i + 1]); // save the original option - /* replace "socket" with "package" */ - if (NULL == (p2 = strchr(pargs[i + 1], ':'))) { - /* no modifiers */ - tmp = strdup("package"); - } else { - *p2 = '\0'; - ++p2; - prte_asprintf(&tmp, "package:%s", p2); - } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); - free(p1); + /* -N -> map-by ppr:N:node */ + else if (0 == strcmp(option, "N")) { + prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; } - rc = PRTE_OPERATION_SUCCEEDED; - } - - return rc; -} - -static int parse_deprecated_cli(prte_cmd_line_t *cmdline, int *argc, char ***argv) -{ - pmix_status_t rc; - - char *options[] = {"--display-devel-map", - "--display-map", - "--display-topo", - "--display-diff", - "--report-bindings", - "--display-allocation", - "--do-not-launch", - "--tag-output", - "--timestamp-output", - "--xml", - "-N", - "--map-by", - "--rank-by", - "--bind-to", - "--output-proctable", - "--output-filename", - "--output-directory", - "--debug", - NULL}; - - rc = prte_schizo_base_process_deprecated_cli(cmdline, argc, argv, options, - false, convert_deprecated_cli); - - return rc; -} - -static void doit(char *tgt, char *src, char **srcenv, char ***dstenv, bool cmdline) -{ - char *param, *p1, *value, *tmp; - char **env = *dstenv; - size_t n; - - param = strdup(src); - p1 = param + strlen(tgt); - value = strchr(param, '='); - *value = '\0'; - value++; - /* check for duplicate in app->env - this - * would have been placed there by the - * cmd line processor. By convention, we - * always let the cmd line override the - * environment - */ - if (cmdline) { - /* check if it is already present */ - for (n = 0; NULL != env[n]; n++) { - if (0 == strcmp(env[n], p1)) { - /* this param is already given */ - free(param); - return; + /* --npernode X and --npersocket X -> --map-by ppr:X:node/socket */ + else if (0 == strcmp(option, "npernode")) { + prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + free(p2); + } else if (0 == strcmp(option, "pernode")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, "ppr:1:node", true); + } else if (0 == strcmp(option, "npersocket")) { + prte_asprintf(&p2, "ppr:%s:socket", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + free(p2); + } + /* --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], ':')) { + prte_show_help("help-schizo-base.txt", "bad-ppr", true, opt->values[0], true); + return PRTE_ERR_SILENT; } + prte_asprintf(&p2, "ppr:%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + free(p2); } - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:prte:parse_env adding %s %s to cmd line", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), p1, value); - if (0 == strcmp(tgt, "PMIX_MCA_")) { - prte_argv_append_nosize(dstenv, "--pmixmca"); - } else { - prte_argv_append_nosize(dstenv, "--prtemca"); + /* --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], true); } - prte_argv_append_nosize(dstenv, p1); - prte_argv_append_nosize(dstenv, value); - } else { - /* push it into our environment with a PRTE_MCA_ prefix*/ - if (0 == strcmp(tgt, "PMIX_MCA_")) { - prte_asprintf(&tmp, "PMIX_MCA_%s", p1); - } else if (0 != strcmp(tgt, "PRTE_MCA_")) { - prte_asprintf(&tmp, "PRTE_MCA_%s", p1); - } else { - tmp = strdup(param); + /* --rankfile X -> map-by rankfile:file=X */ + else if (0 == strcmp(option, "rankfile")) { + prte_asprintf(&p2, "file=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + free(p2); + } + /* --tag-output -> "--output tag */ + else if (0 == strcmp(option, "tag-output")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, "tag", true); + } + /* --timestamp-output -> --output timestamp */ + else if (0 == strcmp(option, "timestamp-output")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, "timestamp", true); + } + /* --output-directory DIR -> --output dir=DIR */ + else if (0 == strcmp(option, "output-directory")) { + prte_asprintf(&p2, "dir=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, true); + free(p2); + } + /* --output-filename DIR -> --output file=file */ + else if (0 == strcmp(option, "--output-filename")) { + prte_asprintf(&p2, "file=%s", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, true); + free(p2); + } + /* --xml -> --output xml */ + else if (0 == strcmp(option, "xml")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, "xml", true); } - if (environ != srcenv) { - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:prte:parse_env pushing %s=%s into my environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), tmp, value); - prte_setenv(tmp, value, true, &environ); + /* --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, "map-devel", true); + } + /* --output-proctable -> --display map-devel */ + else if (0 == strcmp(option, "output-proctable")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "map-devel", true); + } + /* --display-map -> --display map */ + else if (0 == strcmp(option, "display-map")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "map", true); + } + /* --display-topo -> --display topo */ + else if (0 == strcmp(option, "display-topo")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "topo", true); + } + /* --report-bindings -> --display bind */ + else if (0 == strcmp(option, "report-bindings")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "bind", true); + } + /* --display-allocation -> --display allocation */ + else if (0 == strcmp(option, "display-allocation")) { + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "allocation", true); + } + /* --debug will be deprecated starting with open mpi v5 + */ + else if (0 == strcmp(option, "debug")) { + prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, + "This CLI option will be deprecated starting in Open MPI v5"); + } + /* --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("package"); + } else { + *p2 = '\0'; + ++p2; + prte_asprintf(&tmp, "package:%s", p2); + } + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p1); + free(p2); + free(tmp2); + 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; + prte_asprintf(&tmp, "package:%s", p2); + } + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p1); + free(p2); + free(tmp2); + 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("package"); + } else { + *p2 = '\0'; + ++p2; + prte_asprintf(&tmp, "package:%s", p2); + } + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p1); + free(p2); + free(tmp2); + free(opt->values[0]); + opt->values[0] = tmp; + } } - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:prte:parse_env pushing %s=%s into dest environment", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), tmp, value); - prte_setenv(tmp, value, true, dstenv); - free(tmp); } - free(param); -} -static char *orte_frameworks[] = {"errmgr", "ess", "filem", "grpcomm", "iof", "odls", - "oob", "plm", "ras", "rmaps", "rml", "routed", - "rtc", "schizo", "state", NULL}; + return rc; +} -static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, bool cmdline) +static int parse_env(char **srcenv, char ***dstenv, + prte_cli_result_t *cli) { int i, j, n; char *p1, *p2; @@ -726,40 +735,24 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b prte_value_t *pval; char **xparams = NULL, **xvals = NULL; char *param, *value; + prte_cli_item_t *opt; - prte_output_verbose(1, prte_schizo_base_framework.framework_output, "%s schizo:prte: parse_env", + prte_output_verbose(1, prte_schizo_base_framework.framework_output, + "%s schizo:prte: parse_env", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); - for (i = 0; NULL != srcenv[i]; ++i) { - if (0 == strncmp("PRTE_MCA_", srcenv[i], strlen("PRTE_MCA_"))) { - doit("PRTE_MCA_", srcenv[i], srcenv, dstenv, cmdline); - } else if (0 == strncmp("OMPI_MCA_", srcenv[i], strlen("OMPI_MCA_"))) { - /* if this references one of the old ORTE frameworks, then take it here */ - p1 = srcenv[i] + strlen("OMPI_MCA_"); - for (j = 0; NULL != orte_frameworks[j]; j++) { - if (0 == strncmp(p1, orte_frameworks[j], strlen(orte_frameworks[j]))) { - doit("PRTE_MCA_", srcenv[i], srcenv, dstenv, cmdline); - break; - } - } - } else if (0 == strncmp("PMIX_MCA_", srcenv[i], strlen("PMIX_MCA_"))) { - doit("PMIX_MCA_", srcenv[i], srcenv, dstenv, cmdline); - } - } - - if (cmdline) { - /* if we are looking at the cmd line, then we are done */ + if (NULL == cli) { return PRTE_SUCCESS; } env = *dstenv; - /* now look for -x options - not allowed to conflict with a -mca option */ - if (NULL != cmd_line && 0 < (j = prte_cmd_line_get_ninsts(cmd_line, "x"))) { - for (i = 0; i < j; ++i) { + /* look for -x options - not allowed to conflict with a -mca option */ + opt = prte_cmd_line_get_param(cli, PRTE_CLI_FWD_ENVAR); + if (NULL != opt) { + for (j=0; NULL != opt->values[j]; j++) { /* the value is the envar */ - pval = prte_cmd_line_get_param(cmd_line, "x", i, 0); - p1 = prte_schizo_base_strip_quotes(pval->value.data.string); + p1 = opt->values[j]; /* if there is an '=' in it, then they are setting a value */ if (NULL != (p2 = strchr(p1, '='))) { *p2 = '\0'; @@ -768,7 +761,6 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b p2 = getenv(p1); if (NULL == p2) { prte_show_help("help-schizo-base.txt", "missing-envar-param", true, p1); - free(p1); continue; } } @@ -787,6 +779,8 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b prte_show_help("help-schizo-base.txt", "duplicate-mca-value", true, p1, p2, value); free(param); + prte_argv_free(xparams); + prte_argv_free(xvals); return PRTE_ERR_BAD_PARAM; } } @@ -796,11 +790,12 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b /* check if we already processed a conflicting -x version with MCA prefix */ if (NULL != xparams) { for (i = 0; NULL != xparams[i]; i++) { - if (0 == strncmp("PRTE_MCA_", p1, strlen("PRTE_MCA_")) - || 0 == strncmp("OMPI_MCA_", p1, strlen("OMPI_MCA_"))) { + if (0 == strncmp("PRTE_MCA_", p1, strlen("PRTE_MCA_"))) { /* this is an error - different values */ prte_show_help("help-schizo-base.txt", "duplicate-mca-value", true, p1, p2, xvals[i]); + prte_argv_free(xparams); + prte_argv_free(xvals); return PRTE_ERR_BAD_PARAM; } } @@ -809,7 +804,6 @@ static int parse_env(prte_cmd_line_t *cmd_line, char **srcenv, char ***dstenv, b /* cache this for later inclusion - do not modify dstenv in this loop */ prte_argv_append_nosize(&xparams, p1); prte_argv_append_nosize(&xvals, p2); - free(p1); } } @@ -1005,11 +999,11 @@ static int detect_proxy(char *personalities) return prte_schizo_prte_component.priority; } -static void allow_run_as_root(prte_cmd_line_t *cmd_line) +static void allow_run_as_root(prte_cli_result_t *cli) { char *r1, *r2; - if (prte_cmd_line_is_taken(cmd_line, "allow-run-as-root")) { + if (prte_cmd_line_is_taken(cli, "allow-run-as-root")) { return; } @@ -1023,7 +1017,8 @@ static void allow_run_as_root(prte_cmd_line_t *cmd_line) prte_schizo_base_root_error_msg(); } -static void job_info(prte_cmd_line_t *cmdline, void *jobinfo) +static void job_info(prte_cli_result_t *results, + void *jobinfo) { return; } diff --git a/src/mca/schizo/prte/schizo_prte.h b/src/mca/schizo/prte/schizo_prte.h index 4209b2cbdc..d12f5e6074 100644 --- a/src/mca/schizo/prte/schizo_prte.h +++ b/src/mca/schizo/prte/schizo_prte.h @@ -3,7 +3,7 @@ * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -33,4 +33,4 @@ extern prte_schizo_base_module_t prte_schizo_prte_module; END_C_DECLS -#endif /* MCA_SCHIZO_OMPI_H_ */ +#endif /* MCA_SCHIZO_PRTE_H_ */ diff --git a/src/mca/schizo/prte/schizo_prte_component.c b/src/mca/schizo/prte/schizo_prte_component.c index f199109e68..afcd30d153 100644 --- a/src/mca/schizo/prte/schizo_prte_component.c +++ b/src/mca/schizo/prte/schizo_prte_component.c @@ -6,7 +6,7 @@ * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/src/mca/schizo/schizo.h b/src/mca/schizo/schizo.h index 053c483767..7cc940d7d5 100644 --- a/src/mca/schizo/schizo.h +++ b/src/mca/schizo/schizo.h @@ -5,7 +5,7 @@ * reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -51,31 +51,9 @@ typedef int (*prte_schizo_convertor_fn_t)(char *option, char ***argv, int idx); * things it requires */ typedef int (*prte_schizo_base_module_init_fn_t)(void); -/* provide an opportunity for components to add personality and/or - * environment-specific command line options. The PRTE cli tools - * will add provided options to the CLI definition, and so the - * resulting CLI array will include the _union_ of options provided - * by the various components. Where there is overlap (i.e., an option - * is added that was also defined earlier in the stack), then the - * first definition is used. This reflects the higher priority of - * the original definition - note that this only impacts the help - * message that will be displayed */ -typedef int (*prte_schizo_base_module_define_cli_fn_t)(prte_cmd_line_t *cli); - -/* allow the active schizo component to print its own help message - * in its own format */ -typedef int (*prte_schizo_base_module_check_help_fn_t)(prte_cmd_line_t *cli, char **argv); - -/* parse a tool command line - * starting from the given location according to the cmd line options - * known to this module's personality. First, of course, check that - * this module is included in the base array of personalities, or is - * automatically recognizable! */ -typedef int (*prte_schizo_base_module_parse_cli_fn_t)(int argc, int start, char **argv, - char ***target); - -typedef int (*prte_schizo_base_parse_deprecated_cli_fn_t)(prte_cmd_line_t *cmdline, int *argc, - char ***argv); +/* parse a tool command line */ +typedef int (*prte_schizo_base_module_parse_cli_fn_t)(char **argv, + prte_cli_result_t *results); /* detect if we are running as a proxy * Check the environment to determine what, if any, host we are running @@ -90,11 +68,12 @@ typedef int (*prte_schizo_base_detect_proxy_fn_t)(char *cmdpath); /* parse the environment of the * tool to extract any personality-specific envars that need to be * forward to the app's environment upon execution */ -typedef int (*prte_schizo_base_module_parse_env_fn_t)(prte_cmd_line_t *cmd_line, char **srcenv, - char ***dstenv, bool cmdline); +typedef int (*prte_schizo_base_module_parse_env_fn_t)(char **srcenv, + char ***dstenv, + prte_cli_result_t *cli); /* check if running as root is allowed in this environment */ -typedef void (*prte_schizo_base_module_allow_run_as_root_fn_t)(prte_cmd_line_t *cmd_line); +typedef void (*prte_schizo_base_module_allow_run_as_root_fn_t)(prte_cli_result_t *results); /* do whatever preparation work * is required to setup the app for execution. This is intended to be @@ -109,19 +88,12 @@ typedef int (*prte_schizo_base_module_setup_app_fn_t)(prte_app_context_t *app); typedef int (*prte_schizo_base_module_setup_fork_fn_t)(prte_job_t *jdata, prte_app_context_t *context); -/* add any personality-specific envars required for this specific local - * proc upon execution */ -typedef int (*prte_schizo_base_module_setup_child_fn_t)(prte_job_t *jdata, prte_proc_t *child, - prte_app_context_t *app, char ***env); - /* give the component a chance to cleanup */ typedef void (*prte_schizo_base_module_finalize_fn_t)(void); /* give the components a chance to add job info */ -typedef void (*prte_schizo_base_module_job_info_fn_t)(prte_cmd_line_t *cmdline, void *jobinfo); - -/* give the components a chance to check sanity */ -typedef int (*prte_schizo_base_module_check_sanity_fn_t)(prte_cmd_line_t *cmdline); +typedef void (*prte_schizo_base_module_job_info_fn_t)(prte_cli_result_t *results, + void *jobinfo); /* * schizo module version 1.3.0 @@ -129,36 +101,16 @@ typedef int (*prte_schizo_base_module_check_sanity_fn_t)(prte_cmd_line_t *cmdlin typedef struct { char *name; prte_schizo_base_module_init_fn_t init; - prte_schizo_base_module_define_cli_fn_t define_cli; - prte_schizo_base_module_check_help_fn_t check_help; prte_schizo_base_module_parse_cli_fn_t parse_cli; - prte_schizo_base_parse_deprecated_cli_fn_t parse_deprecated_cli; prte_schizo_base_module_parse_env_fn_t parse_env; prte_schizo_base_detect_proxy_fn_t detect_proxy; prte_schizo_base_module_allow_run_as_root_fn_t allow_run_as_root; prte_schizo_base_module_setup_app_fn_t setup_app; prte_schizo_base_module_setup_fork_fn_t setup_fork; - prte_schizo_base_module_setup_child_fn_t setup_child; prte_schizo_base_module_job_info_fn_t job_info; - prte_schizo_base_module_check_sanity_fn_t check_sanity; prte_schizo_base_module_finalize_fn_t finalize; } prte_schizo_base_module_t; -typedef prte_schizo_base_module_t *(*prte_schizo_API_detect_proxy_fn_t)(char *cmdpath); - -typedef struct { - prte_schizo_base_module_init_fn_t init; - prte_schizo_base_module_parse_env_fn_t parse_env; - prte_schizo_API_detect_proxy_fn_t detect_proxy; - prte_schizo_base_module_setup_app_fn_t setup_app; - prte_schizo_base_module_setup_fork_fn_t setup_fork; - prte_schizo_base_module_setup_child_fn_t setup_child; - prte_schizo_base_module_job_info_fn_t job_info; - prte_schizo_base_module_check_sanity_fn_t check_sanity; - prte_schizo_base_module_finalize_fn_t finalize; -} prte_schizo_API_module_t; - -PRTE_EXPORT extern prte_schizo_API_module_t prte_schizo; /* * schizo component */ diff --git a/src/prted/Makefile.am b/src/prted/Makefile.am index 7548d16f24..86495dc369 100644 --- a/src/prted/Makefile.am +++ b/src/prted/Makefile.am @@ -13,7 +13,7 @@ # Copyright (c) 2014-2020 Cisco Systems, Inc. All rights reserved # Copyright (c) 2015-2020 Intel, Inc. All rights reserved. # Copyright (c) 2018 IBM Corporation. All rights reserved. -# Copyright (c) 2021 Nanook Consulting. All rights reserved. +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -30,7 +30,6 @@ headers += \ libprrte_la_SOURCES += \ prted/prted_comm.c \ - prted/prte_app_parse.c \ - prted/prte.c + prted/prte_app_parse.c include prted/pmix/Makefile.am diff --git a/src/prted/prte_app_parse.c b/src/prted/prte_app_parse.c index 2fa5004709..288af1b705 100644 --- a/src/prted/prte_app_parse.c +++ b/src/prted/prte_app_parse.c @@ -18,7 +18,7 @@ * Copyright (c) 2016-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -37,6 +37,7 @@ #endif #include "src/mca/prteinstalldirs/prteinstalldirs.h" +#include "src/mca/schizo/base/base.h" #include "src/pmix/pmix-internal.h" #include "src/util/argv.h" #include "src/util/basename.h" @@ -76,9 +77,9 @@ static void set_classpath_jar_file(prte_pmix_app_t *app, int index, char *jarfil * with a NULL value for app_env, meaning that there is no "base" * environment that the app needs to be created from. */ -static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], prte_list_t *jdata, - prte_pmix_app_t **app_ptr, bool *made_app, char ***app_env, char ***hostfiles, - char ***hosts) +static int create_app(prte_schizo_base_module_t *schizo, char **argv, prte_list_t *jdata, + prte_pmix_app_t **app_ptr, bool *made_app, char ***app_env, + char ***hostfiles, char ***hosts) { char cwd[PRTE_PATH_MAX]; int i, j, count, rc; @@ -86,28 +87,40 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr prte_pmix_app_t *app = NULL; bool found = false; char *appname = NULL; + prte_cli_item_t *opt; prte_value_t *pvalue; + prte_cli_result_t results; + char *tval; *made_app = false; /* parse the cmd line - do this every time thru so we can * repopulate the globals */ - if (PRTE_SUCCESS != (rc = prte_cmd_line_parse(prte_cmd_line, true, false, argc, argv))) { + PRTE_CONSTRUCT(&results, prte_cli_result_t); + rc = schizo->parse_cli(argv, &results); + if (PRTE_SUCCESS != rc) { if (PRTE_ERR_SILENT != rc) { fprintf(stderr, "%s: command line error (%s)\n", argv[0], prte_strerror(rc)); } + PRTE_DESTRUCT(&results); + return rc; + } + // sanity check the results + rc = prte_schizo_base_sanity(&results); + if (PRTE_SUCCESS != rc) { + // sanity checker prints the reason + PRTE_DESTRUCT(&results); return rc; } - - /* Setup application context */ - app = PRTE_NEW(prte_pmix_app_t); - prte_cmd_line_get_tail(prte_cmd_line, &count, &app->app.argv); /* See if we have anything left */ - if (0 == count) { + if (NULL == results.tail) { rc = PRTE_ERR_NOT_FOUND; goto cleanup; } + /* Setup application context */ + app = PRTE_NEW(prte_pmix_app_t); + app->app.argv = prte_argv_copy(results.tail); app->app.cmd = strdup(app->app.argv[0]); /* get the cwd - we may need it in several places */ @@ -117,8 +130,9 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr } /* Did the user specify a path to the executable? */ - if (NULL != (pvalue = prte_cmd_line_get_param(prte_cmd_line, "path", 0, 0))) { - param = pvalue->value.data.string; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_PATH); + if (NULL != opt) { + param = opt->values[0]; /* if this is a relative path, convert it to an absolute path */ if (prte_path_is_absolute(param)) { value = strdup(param); @@ -134,8 +148,9 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr } /* Did the user request a specific wdir? */ - if (NULL != (pvalue = prte_cmd_line_get_param(prte_cmd_line, "wdir", 0, 0))) { - param = pvalue->value.data.string; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_WDIR); + if (NULL != opt) { + param = opt->values[0]; /* if this is a relative path, convert it to an absolute path */ if (prte_path_is_absolute(param)) { app->app.cwd = strdup(param); @@ -143,79 +158,60 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr /* construct the absolute path */ app->app.cwd = prte_os_path(false, cwd, param, NULL); } - } else if (prte_cmd_line_is_taken(prte_cmd_line, "set-cwd-to-session-dir")) { + } else if (prte_cmd_line_is_taken(&results, "set-cwd-to-session-dir")) { PMIX_INFO_LIST_ADD(rc, app->info, PMIX_SET_SESSION_CWD, NULL, PMIX_BOOL); } else { app->app.cwd = strdup(cwd); } /* if they specified a process set name, then pass it along */ - if (NULL != (pvalue = prte_cmd_line_get_param(prte_cmd_line, "pset", 0, 0))) { - PMIX_INFO_LIST_ADD(rc, app->info, PMIX_PSET_NAME, pvalue->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_PSET); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(rc, app->info, PMIX_PSET_NAME, + opt->values[0], PMIX_STRING); } - /* Did the user specify a hostfile. Need to check for both - * hostfile and machine file. - * We can only deal with one hostfile per app context, otherwise give an error. - */ - found = false; - if (0 < (j = prte_cmd_line_get_ninsts(prte_cmd_line, "hostfile"))) { - if (1 < j) { - prte_show_help("help-prun.txt", "prun:multiple-hostfiles", true, "prun", NULL); - return PRTE_ERR_FATAL; - } else { - pvalue = prte_cmd_line_get_param(prte_cmd_line, "hostfile", 0, 0); - PMIX_INFO_LIST_ADD(rc, app->info, PMIX_HOSTFILE, pvalue->value.data.string, - PMIX_STRING); - if (NULL != hostfiles) { - prte_argv_append_nosize(hostfiles, pvalue->value.data.string); - } - found = true; - } - } - if (0 < (j = prte_cmd_line_get_ninsts(prte_cmd_line, "machinefile"))) { - if (1 < j || found) { - prte_show_help("help-prun.txt", "prun:multiple-hostfiles", true, "prun", NULL); - return PRTE_ERR_FATAL; - } else { - pvalue = prte_cmd_line_get_param(prte_cmd_line, "machinefile", 0, 0); - PMIX_INFO_LIST_ADD(rc, app->info, PMIX_HOSTFILE, pvalue->value.data.string, - PMIX_STRING); - if (NULL != hostfiles) { - prte_argv_append_nosize(hostfiles, pvalue->value.data.string); + /* Did the user specify a hostfile? */ + opt = prte_cmd_line_get_param(&results, PRTE_CLI_HOSTFILE); + if (NULL != opt) { + tval = prte_argv_join(opt->values, ','); + PMIX_INFO_LIST_ADD(rc, app->info, PMIX_HOSTFILE, + tval, PMIX_STRING); + free(tval); + if (NULL != hostfiles) { + for (i=0; NULL != opt->values[i]; i++) { + prte_argv_append_nosize(hostfiles, opt->values[i]); } } } /* Did the user specify any hosts? */ - if (0 < (j = prte_cmd_line_get_ninsts(prte_cmd_line, "host"))) { - char **targ = NULL, *tval; - for (i = 0; i < j; ++i) { - pvalue = prte_cmd_line_get_param(prte_cmd_line, "host", i, 0); - prte_argv_append_nosize(&targ, pvalue->value.data.string); - if (NULL != hosts) { - prte_argv_append_nosize(hosts, pvalue->value.data.string); - } - } - tval = prte_argv_join(targ, ','); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_HOST); + if (NULL != opt) { + tval = prte_argv_join(opt->values, ','); PMIX_INFO_LIST_ADD(rc, app->info, PMIX_HOST, tval, PMIX_STRING); free(tval); + if (NULL != hosts) { + for (i=0; NULL != opt->values[i]; i++) { + prte_argv_append_nosize(hosts, opt->values[i]); + } + } } /* check for bozo error */ - if (NULL != (pvalue = prte_cmd_line_get_param(prte_cmd_line, "np", 0, 0)) - || NULL != (pvalue = prte_cmd_line_get_param(prte_cmd_line, "n", 0, 0))) { - if (0 > pvalue->value.data.integer) { - prte_show_help("help-prun.txt", "prun:negative-nprocs", true, "prun", app->app.argv[0], - pvalue->value.data.integer, NULL); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_NP); + if (NULL != opt) { + count = strtol(opt->values[0], NULL, 10); + if (0 > count) { + prte_show_help("help-prun.txt", "prun:negative-nprocs", true, + prte_tool_basename, + app->app.argv[0], count, NULL); return PRTE_ERR_FATAL; } - } - if (NULL != pvalue) { /* we don't require that the user provide --np or -n because * the cmd line might stipulate a mapping policy that computes * the number of procs - e.g., a map-by ppr option */ - app->app.maxprocs = pvalue->value.data.integer; + app->app.maxprocs = count; } /* see if we need to preload the binary to @@ -223,13 +219,16 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr * can't easily find the class on the cmd line. Java apps have to * preload their binary via the preload_files option */ - if (NULL == strstr(app->app.argv[0], "java")) { - if (prte_cmd_line_is_taken(prte_cmd_line, "preload-binary")) { + appname = prte_basename(app->app.cmd); + if (0 == strcmp(appname, "java")) { + opt = prte_cmd_line_get_param(&results, PRTE_CLI_PRELOAD_BIN); + if (NULL != opt) { PMIX_INFO_LIST_ADD(rc, app->info, PMIX_SET_SESSION_CWD, NULL, PMIX_BOOL); PMIX_INFO_LIST_ADD(rc, app->info, PMIX_PRELOAD_BIN, NULL, PMIX_BOOL); } } - if (prte_cmd_line_is_taken(prte_cmd_line, "preload-files")) { + opt = prte_cmd_line_get_param(&results, "preload-files"); + if (NULL != opt) { PMIX_INFO_LIST_ADD(rc, app->info, PMIX_PRELOAD_FILES, NULL, PMIX_BOOL); } @@ -251,7 +250,6 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr * and the "java" command will start the "executable". So we need to ensure * that all the proper java-specific paths are provided */ - appname = prte_basename(app->app.cmd); if (0 == strcmp(appname, "java")) { /* see if we were given a library path */ found = false; @@ -376,110 +374,11 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr } } -#if 0 - /* if this is a singularity app, a little more to do */ - if (0 == strcmp(app->argv[0],"singularity") || - NULL != strstr(app->argv[0], ".sif")) { - /* We do not assume that the location of the singularity binary is set at - * compile time as it can change between jobs (not during a job). If it does, - * then it will be in the application's environment */ - if (NULL != app->env) { - pth = prte_path_findv("singularity", X_OK, app->env, NULL); - } - if (NULL != pth) { - /* prte_path_findv returned the absolute path to the Singularity binary, - * we want the directory where the binary is. */ - pth = prte_dirname(pth); - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:singularity: Singularity found from env: %s\n", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), pth); - } else { - /* wasn't in the environment - see if it was found somewhere */ - if (0 < strlen(PRTE_SINGULARITY_PATH)) { - if (0 != strcmp(PRTE_SINGULARITY_PATH, "DEFAULT")) { - pth = PRTE_SINGULARITY_PATH; - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:singularity: using default Singularity from %s\n", - PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), pth); - /* Update (if possible) the PATH of the app so it can find singularity otherwise - it will likely not find it and create a failure. The default path to singularity - that is set at configuration time may not be in the environment that is passed in - by the user. */ - for (i = 0; NULL != app->env[i]; i++) { - if (0 == strncmp(app->env[i], "PATH", 4)) { - char *cur_path_val = &app->env[i][5]; - if (app->env[i] != NULL) { - free(app->env[i]); - } - prte_asprintf(&app->env[i], "PATH=%s:%s", pth, cur_path_val); - break; - } - } - } - } else { - return PRTE_ERR_TAKE_NEXT_OPTION; - } - } - if (NULL == pth) { - // at this point, if we do not have a valid path to Singularity, there is nothing we can do - return PRTE_ERR_TAKE_NEXT_OPTION; - } - - /* tell the odls component to prepend this to our PATH */ - envar.envar = "PATH"; - envar.value = pth; - envar.separator = ':'; - prte_add_attribute(&jdata->attributes, PRTE_JOB_PREPEND_ENVAR, - PRTE_ATTR_GLOBAL, &envar, PMIX_ENVAR); - - // the final command is now singularity - if (app->app) { - free(app->app); - } - asprintf(&app->app, "%s/singularity", pth); - - /* start building the final cmd */ - prte_argv_append_nosize(&cmd_args, "singularity"); - prte_argv_append_nosize(&cmd_args, "exec"); - - /* We need to parse the environment of the application because there is important - * information in it to be able to set everything up. For example, the arguments - * used to start a container, i.e., the 'singularity exec' flags are based to some - * extent on the configuration of Singularity and also on the image itself. Extra - * 'singularity exec' flags can be set using an environment variable (its name is - * defined by the value of singularity_exec_argc_env_var_name). */ - if (NULL != app->env) { - for (i=0; NULL != app->env[i]; i++) { - if (0 == strncmp(app->env[i], singularity_exec_argc_env_var_name, strlen(singularity_exec_argc_env_var_name))) { - exec_args = &app->env[i][strlen(singularity_exec_argc_env_var_name) + 1]; // We do not want the "=" - break; - } - } - if (NULL != exec_args) { - char **args = prte_argv_split(exec_args, ' '); - for (i=0; NULL != args[i]; i++) { - prte_argv_append_nosize(&cmd_args, args[i]); - } - } - } - /* now add in the rest of the args they provided */ - for(i=0; NULL != app->argv[i]; i++) { - prte_argv_append_nosize(&cmd_args, app->argv[i]); - } - - /* replace their argv with the new one */ - prte_argv_free(app->argv); - app->argv = cmd_args; - - /* set the singularity cache dir, unless asked not to do so */ - if (!prte_get_attribute(&app->attributes, PRTE_APP_NO_CACHEDIR, NULL, PMIX_BOOL)) { - /* Set the Singularity sessiondir to exist within the PRTE sessiondir */ - prte_setenv("SINGULARITY_SESSIONDIR", prte_process_info.job_session_dir, true, &app->env); - /* No need for Singularity to clean up after itself if PRTE will */ - prte_setenv("SINGULARITY_NOSESSIONCLEANUP", "1", true, &app->env); - } + // parse any environment-related cmd line options + rc = schizo->parse_env(prte_launch_environ, &app->app.env, &results); + if (PRTE_SUCCESS != rc) { + goto cleanup; } -#endif *app_ptr = app; app = NULL; @@ -494,29 +393,29 @@ static int create_app(prte_cmd_line_t *prte_cmd_line, int argc, char *argv[], pr if (NULL != appname) { free(appname); } + PRTE_DESTRUCT(&results); return rc; } -int prte_parse_locals(prte_cmd_line_t *prte_cmd_line, prte_list_t *jdata, int argc, char *argv[], +int prte_parse_locals(prte_schizo_base_module_t *schizo, + prte_list_t *jdata, char *argv[], char ***hostfiles, char ***hosts) { int i, rc; - int temp_argc; char **temp_argv, **env; prte_pmix_app_t *app; bool made_app; /* Make the apps */ - temp_argc = 0; temp_argv = NULL; - prte_argv_append(&temp_argc, &temp_argv, argv[0]); + prte_argv_append_nosize(&temp_argv, argv[0]); /* NOTE: This bogus env variable is necessary in the calls to create_app(), below. See comment immediately before the create_app() function for an explanation. */ env = NULL; - for (i = 1; i < argc; ++i) { + for (i = 1; NULL != argv[i]; ++i) { if (0 == strcmp(argv[i], ":")) { /* Make an app with this argv */ if (prte_argv_count(temp_argv) > 1) { @@ -525,11 +424,12 @@ int prte_parse_locals(prte_cmd_line_t *prte_cmd_line, prte_list_t *jdata, int ar env = NULL; } app = NULL; - rc = create_app(prte_cmd_line, temp_argc, temp_argv, jdata, &app, &made_app, &env, + rc = create_app(schizo, temp_argv, jdata, &app, &made_app, &env, hostfiles, hosts); if (PRTE_SUCCESS != rc) { /* Assume that the error message has already been printed; */ + prte_argv_free(temp_argv); return rc; } if (made_app) { @@ -537,19 +437,18 @@ int prte_parse_locals(prte_cmd_line_t *prte_cmd_line, prte_list_t *jdata, int ar } /* Reset the temps */ - - temp_argc = 0; + prte_argv_free(temp_argv); temp_argv = NULL; - prte_argv_append(&temp_argc, &temp_argv, argv[0]); + prte_argv_append_nosize(&temp_argv, argv[0]); } } else { - prte_argv_append(&temp_argc, &temp_argv, argv[i]); + prte_argv_append_nosize(&temp_argv, argv[i]); } } if (prte_argv_count(temp_argv) > 1) { app = NULL; - rc = create_app(prte_cmd_line, temp_argc, temp_argv, jdata, &app, &made_app, &env, + rc = create_app(schizo, temp_argv, jdata, &app, &made_app, &env, hostfiles, hosts); if (PRTE_SUCCESS != rc) { return rc; diff --git a/src/prted/prted.h b/src/prted/prted.h index 498c7a3e36..2bf894256e 100644 --- a/src/prted/prted.h +++ b/src/prted/prted.h @@ -11,7 +11,7 @@ * All rights reserved. * Copyright (c) 2019 Intel, Inc. All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -29,6 +29,7 @@ #include "src/class/prte_pointer_array.h" #include "src/mca/rml/rml_types.h" +#include "src/mca/schizo/schizo.h" BEGIN_C_DECLS @@ -44,8 +45,8 @@ PRTE_EXPORT void prte_daemon_cmd_processor(int fd, short event, void *data); PRTE_EXPORT int prte_daemon_process_commands(pmix_proc_t *sender, pmix_data_buffer_t *buffer, prte_rml_tag_t tag); -PRTE_EXPORT int prte_parse_locals(prte_cmd_line_t *prte_cmd_line, prte_list_t *jdata, int argc, - char *argv[], char ***hostfiles, char ***hosts); +PRTE_EXPORT int prte_parse_locals(prte_schizo_base_module_t *schizo, prte_list_t *jdata, + char **argv, char ***hostfiles, char ***hosts); END_C_DECLS diff --git a/src/runtime/prte_finalize.c b/src/runtime/prte_finalize.c index f7b825ad0f..572729ef50 100644 --- a/src/runtime/prte_finalize.c +++ b/src/runtime/prte_finalize.c @@ -16,7 +16,7 @@ * Copyright (c) 2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * Copyright (c) 2021 Amazon.com, Inc. or its affiliates. All Rights * reserved. * $COPYRIGHT$ @@ -38,7 +38,6 @@ #include "src/mca/base/prte_mca_base_alias.h" #include "src/mca/ess/base/base.h" #include "src/mca/ess/ess.h" -#include "src/mca/schizo/base/base.h" #include "src/runtime/prte_globals.h" #include "src/runtime/prte_locks.h" #include "src/runtime/runtime.h" @@ -159,9 +158,6 @@ int prte_finalize(void) return rc; } - /* finalize schizo */ - prte_schizo.finalize(); - /* Close the general debug stream */ prte_output_close(prte_debug_output); diff --git a/src/runtime/prte_globals.c b/src/runtime/prte_globals.c index 79804f7be0..7ec633a418 100644 --- a/src/runtime/prte_globals.c +++ b/src/runtime/prte_globals.c @@ -17,7 +17,7 @@ * Copyright (c) 2014-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2017-2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -68,6 +68,7 @@ prte_hash_table_t *prte_coprocessors = NULL; char *prte_topo_signature = NULL; char *prte_data_server_uri = NULL; char *prte_tool_basename = NULL; +char *prte_tool_actual = NULL; bool prte_dvm_ready = false; prte_pointer_array_t *prte_cache = NULL; bool prte_persistent = true; @@ -411,6 +412,7 @@ static void prte_app_context_construct(prte_app_context_t *app_context) app_context->cwd = NULL; app_context->flags = 0; PRTE_CONSTRUCT(&app_context->attributes, prte_list_t); + PRTE_CONSTRUCT(&app_context->cli, prte_cli_result_t); } static void prte_app_context_destructor(prte_app_context_t *app_context) @@ -447,6 +449,7 @@ static void prte_app_context_destructor(prte_app_context_t *app_context) } PRTE_LIST_DESTRUCT(&app_context->attributes); + PRTE_DESTRUCT(&app_context->cli); } PRTE_CLASS_INSTANCE(prte_app_context_t, prte_object_t, prte_app_context_construct, @@ -456,6 +459,7 @@ static void prte_job_construct(prte_job_t *job) { job->exit_code = 0; job->personality = NULL; + job->schizo = NULL; PMIX_LOAD_NSPACE(job->nspace, NULL); job->index = -1; job->offset = 0; @@ -492,6 +496,7 @@ static void prte_job_construct(prte_job_t *job) PMIX_LOAD_NSPACE(job->launcher, NULL); job->ntraces = 0; job->traces = NULL; + PRTE_CONSTRUCT(&job->cli, prte_cli_result_t); } static void prte_job_destruct(prte_job_t *job) @@ -578,6 +583,7 @@ static void prte_job_destruct(prte_job_t *job) if (NULL != job->traces) { prte_argv_free(job->traces); } + PRTE_DESTRUCT(&job->cli); } PRTE_CLASS_INSTANCE(prte_job_t, diff --git a/src/runtime/prte_globals.h b/src/runtime/prte_globals.h index 8b1feb57c9..2a4f6f369e 100644 --- a/src/runtime/prte_globals.h +++ b/src/runtime/prte_globals.h @@ -17,7 +17,7 @@ * Copyright (c) 2017-2020 IBM Corporation. All rights reserved. * Copyright (c) 2017-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -54,6 +54,7 @@ #include "src/mca/rml/rml_types.h" #include "src/runtime/runtime.h" #include "src/util/attr.h" +#include "src/util/cmd_line.h" #include "src/util/name_fns.h" #include "src/util/proc_info.h" @@ -70,6 +71,7 @@ PRTE_EXPORT extern bool prte_event_base_active; /* instantiated in src/runtim PRTE_EXPORT extern bool prte_proc_is_bound; /* instantiated in src/runtime/prte_init.c */ PRTE_EXPORT extern int prte_progress_thread_debug; /* instantiated in src/runtime/prte_init.c */ PRTE_EXPORT extern char *prte_tool_basename; // argv[0] of prun or one of its symlinks +PRTE_EXPORT extern char *prte_tool_actual; // actual tool executable /** * Global indicating where this process was bound to at launch (will @@ -199,6 +201,8 @@ typedef uint16_t prte_job_controls_t; */ struct prte_proc_t; struct prte_job_map_t; +struct prte_schizo_base_module_t; + /************/ /* define an object for storing node topologies */ @@ -245,6 +249,8 @@ typedef struct { * every time we want some new (rarely used) option */ prte_list_t attributes; + // store the result of parsing this app's cmd line + prte_cli_result_t cli; } prte_app_context_t; PRTE_EXPORT PRTE_CLASS_DECLARATION(prte_app_context_t); @@ -307,6 +313,7 @@ typedef struct { int exit_code; /* personality for this job */ char **personality; + struct prte_schizo_base_module_t *schizo; /* jobid for this job */ pmix_nspace_t nspace; int index; // index in the job array where this is stored @@ -367,6 +374,8 @@ typedef struct { /* track the number of stack traces recv'd */ uint32_t ntraces; char **traces; + // store the result of parsing this app's cmd line + prte_cli_result_t cli; } prte_job_t; PRTE_EXPORT PRTE_CLASS_DECLARATION(prte_job_t); diff --git a/src/tools/prte/Makefile.am b/src/tools/prte/Makefile.am index 90bbd0b15d..0546bab290 100644 --- a/src/tools/prte/Makefile.am +++ b/src/tools/prte/Makefile.am @@ -12,7 +12,7 @@ # Copyright (c) 2008-2020 Cisco Systems, Inc. All rights reserved # Copyright (c) 2008 Sun Microsystems, Inc. All rights reserved. # Copyright (c) 2015-2020 Intel, Inc. All rights reserved. -# Copyright (c) 2021 Nanook Consulting. All rights reserved. +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -40,7 +40,7 @@ AM_CFLAGS = \ bin_PROGRAMS = prte prte_SOURCES = \ - main.c + prte.c prte_LDADD = \ $(prte_libevent_LIBS) \ diff --git a/src/tools/prte/main.c b/src/tools/prte/main.c deleted file mode 100644 index 787c2ecd40..0000000000 --- a/src/tools/prte/main.c +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************** - * * - * PRTE: PMIx Reference RunTime Environment (PRTE) * - * * - * https://github.com/openpmix/prte * - * * - ***************************************************************************/ - -#include "include/prte.h" - -int main(int argc, char *argv[]) -{ - return prte(argc, argv); -} - -/* - * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 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) 2017-2020 Intel, Inc. All rights reserved. - * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ diff --git a/src/prted/prte.c b/src/tools/prte/prte.c similarity index 69% rename from src/prted/prte.c rename to src/tools/prte/prte.c index 3000017f5d..2196b530e5 100644 --- a/src/prted/prte.c +++ b/src/tools/prte/prte.c @@ -19,7 +19,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Geoffroy Vallee. All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * Copyright (c) 2021 Amazon.com, Inc. or its affiliates. All Rights * reserved. * $COPYRIGHT$ @@ -121,7 +121,6 @@ static prte_mutex_t prun_abort_inprogress_lock = PRTE_MUTEX_STATIC_INIT; static prte_event_t *forward_signals_events = NULL; static char *mypidfile = NULL; static bool verbose = false; -static prte_cmd_line_t *prte_cmd_line = NULL; static bool want_prefix_by_default = (bool) PRTE_WANT_PRTE_PREFIX_BY_DEFAULT; static void abort_signal_callback(int signal); static void clean_abort(int fd, short flags, void *arg); @@ -223,15 +222,7 @@ static void setup_sighandler(int signal, prte_event_t *ev, prte_event_cbfunc_t c prte_event_signal_add(ev, NULL); } -static prte_cmd_line_init_t cmd_line_init[] = { - /* override personality */ - {'\0', "personality", 1, PRTE_CMD_LINE_TYPE_STRING, "Specify the personality to be used", - PRTE_CMD_LINE_OTYPE_DVM}, - - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; - -int prte(int argc, char *argv[]) +int main(int argc, char *argv[]) { int rc = 1, i, j; char *param, *timeoutenv, *ptr, *tpath, *cptr; @@ -245,7 +236,6 @@ int prte(int argc, char *argv[]) pmix_app_t *papps; size_t napps; mylock_t mylock; - prte_value_t *pval; uint32_t ui32; char **pargv; int pargc; @@ -258,7 +248,6 @@ int prte(int argc, char *argv[]) pmix_data_array_t darray; char **hostfiles = NULL; char **hosts = NULL; - bool donotlaunch = false; prte_schizo_base_module_t *schizo; prte_ess_base_signal_t *sig; char **targv, **options; @@ -266,6 +255,8 @@ int prte(int argc, char *argv[]) char *outfile = NULL; pmix_status_t code; char *personality; + prte_cli_result_t results; + prte_cli_item_t *opt; /* init the globals */ PRTE_CONSTRUCT(&apps, prte_list_t); @@ -274,8 +265,14 @@ int prte(int argc, char *argv[]) } else { prte_tool_basename = strdup(param); } + if (0 == strcmp(prte_tool_basename, "prterun")) { + prte_tool_actual = "prterun"; + } else { + prte_tool_actual = "prte"; + } pargc = argc; - pargv = prte_argv_copy(argv); + pargv = prte_argv_copy_strip(argv); // strip any incoming quoted arguments + /* save a pristine copy of the environment for launch purposes. * This MUST be done so that we can pass it to any local procs we * spawn - otherwise, those local procs will get a bunch of @@ -303,7 +300,7 @@ int prte(int argc, char *argv[]) return rc; } - /* init the tiny part of PRTE we use */ + /* init the tiny part of PRTE we initially need */ prte_init_util(PRTE_PROC_MASTER); /** setup callbacks for abort signals - from this point @@ -373,7 +370,7 @@ int prte(int argc, char *argv[]) /* detect if we are running as a proxy and select the active * schizo module for this tool */ - schizo = prte_schizo.detect_proxy(personality); + schizo = prte_schizo_base_detect_proxy(personality); if (NULL == schizo) { prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, personality); return 1; @@ -393,34 +390,15 @@ int prte(int argc, char *argv[]) personality = schizo->name; } - /* setup the cmd line - this is specific to the proxy */ - prte_cmd_line = PRTE_NEW(prte_cmd_line_t); - if (PRTE_SUCCESS != (rc = schizo->define_cli(prte_cmd_line))) { - PRTE_ERROR_LOG(rc); - return rc; - } - /* add any prte-specific options */ - if (PRTE_SUCCESS != (rc = prte_cmd_line_add(prte_cmd_line, cmd_line_init))) { - PRTE_ERROR_LOG(rc); - return rc; - } - - /* handle deprecated options */ - if (PRTE_SUCCESS != (rc = schizo->parse_deprecated_cli(prte_cmd_line, &pargc, &pargv))) { - if (PRTE_OPERATION_SUCCEEDED == rc) { - /* the cmd line was restructured - show them the end result */ - param = prte_argv_join(pargv, ' '); - fprintf(stderr, "\n******* Corrected cmd line: %s\n\n\n", param); - free(param); - } else { - return rc; - } - } - - /* parse the result to get values - this will not include MCA params */ - if (PRTE_SUCCESS != (rc = prte_cmd_line_parse(prte_cmd_line, true, false, pargc, pargv))) { + /* parse the input argv to get values, including everyone's MCA params */ + PRTE_CONSTRUCT(&results, prte_cli_result_t); + rc = schizo->parse_cli(pargv, &results); + if (PRTE_SUCCESS != rc) { + PRTE_DESTRUCT(&results); if (PRTE_ERR_SILENT != rc) { fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); + } else { + rc = PRTE_SUCCESS; } return rc; } @@ -430,83 +408,19 @@ int prte(int argc, char *argv[]) * exit with a giant warning message */ if (0 == geteuid()) { - schizo->allow_run_as_root(prte_cmd_line); // will exit us if not allowed + schizo->allow_run_as_root(&results); // will exit us if not allowed } /* if we were given a keepalive pipe, set up to monitor it now */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "keepalive", 0, 0))) { - prte_asprintf(¶m, "%d", pval->value.data.integer); - prte_setenv("PMIX_KEEPALIVE_PIPE", param, true, &environ); - free(param); - } - - /* let the schizo components take a pass at it to get the MCA params */ - if (PRTE_SUCCESS != (rc = schizo->parse_cli(pargc, 0, pargv, NULL))) { - if (PRTE_ERR_SILENT != rc) { - fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); - } - return rc; - } - - /* check command line sanity - ensure there aren't multiple instances of - * options where there should be only one */ - rc = schizo->check_sanity(prte_cmd_line); - if (PRTE_SUCCESS != rc) { - if (PRTE_ERR_SILENT != rc) { - fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); - param = prte_argv_join(pargv, ' '); - fprintf(stderr, "\n******* Cmd line: %s\n\n\n", param); - free(param); - } - return rc; - } - - if (prte_cmd_line_is_taken(prte_cmd_line, "verbose")) { - verbose = true; - } - - /* see if print version is requested. Do this before - * check for help so that --version --help works as - * one might expect. */ - if (prte_cmd_line_is_taken(prte_cmd_line, "version")) { - if (proxyrun) { - fprintf(stdout, "%s (%s) %s\n\nReport bugs to %s\n", prte_tool_basename, - PRTE_PROXY_PACKAGE_NAME, PRTE_PROXY_VERSION_STRING, PRTE_PROXY_BUGREPORT); - } else { - fprintf(stdout, "%s (%s) %s\n\nReport bugs to %s\n", prte_tool_basename, - "PMIx Reference RunTime Environment", PRTE_VERSION, PACKAGE_BUGREPORT); - } - exit(0); - } - - /* Check for help request */ - rc = schizo->check_help(prte_cmd_line, pargv); - if (PRTE_ERR_SILENT == rc) { - /* help was printed */ - exit(0); - } - - /* set debug flags */ - prte_debug_flag = prte_cmd_line_is_taken(prte_cmd_line, "debug"); - prte_debug_daemons_flag = prte_cmd_line_is_taken(prte_cmd_line, "debug-daemons"); - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "debug-verbose", 0, 0))) { - prte_debug_verbosity = pval->value.data.integer; - } - prte_debug_daemons_file_flag = prte_cmd_line_is_taken(prte_cmd_line, "debug-daemons-file"); - if (prte_debug_daemons_file_flag) { - prte_debug_daemons_flag = true; - } - prte_leave_session_attached = prte_cmd_line_is_taken(prte_cmd_line, "leave-session-attached"); - /* if any debug level is set, ensure we output debug level dumps */ - if (prte_debug_flag || prte_debug_daemons_flag || prte_leave_session_attached) { - prte_devel_level_output = true; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_KEEPALIVE); + if (NULL != opt) { + prte_setenv("PMIX_KEEPALIVE_PIPE", opt->values[0], true, &environ); } /* detach from controlling terminal * otherwise, remain attached so output can get to us */ - if (!prte_debug_flag && !prte_debug_daemons_flag - && prte_cmd_line_is_taken(prte_cmd_line, "daemonize")) { + if (!prte_debug_flag && prte_cmd_line_is_taken(&results, PRTE_CLI_DAEMONIZE)) { pipe(wait_pipe); prte_state_base_parent_fd = wait_pipe[1]; prte_daemon_init_callback(NULL, wait_dvm); @@ -514,33 +428,35 @@ int prte(int argc, char *argv[]) } else { #if defined(HAVE_SETSID) /* see if we were directed to separate from current session */ - if (prte_cmd_line_is_taken(prte_cmd_line, "set-sid")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_SET_SID)) { setsid(); } #endif } - if (prte_cmd_line_is_taken(prte_cmd_line, "no-ready-msg")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_NO_READY_MSG)) { prte_state_base_ready_msg = false; } - if (prte_cmd_line_is_taken(prte_cmd_line, "system-server")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_SYSTEM_SERVER)) { /* we should act as system-level PMIx server */ prte_setenv("PRTE_MCA_pmix_system_server", "1", true, &environ); } /* always act as session-level PMIx server */ prte_setenv("PRTE_MCA_pmix_session_server", "1", true, &environ); /* if we were asked to report a uri, set the MCA param to do so */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "report-uri", 0, 0))) { - prte_pmix_server_globals.report_uri = strdup(pval->value.data.string); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_REPORT_URI); + if (NULL != opt) { + prte_pmix_server_globals.report_uri = strdup(opt->values[0]); } /* don't aggregate help messages as that will apply job-to-job */ prte_setenv("PRTE_MCA_prte_base_help_aggregate", "0", true, &environ); /* if we are supporting a singleton, push its ID into the environ * so it can get picked up and registered by server init */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "singleton", 0, 0))) { - prte_pmix_server_globals.singleton = strdup(pval->value.data.string); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_SINGLETON); + if (NULL != opt) { + prte_pmix_server_globals.singleton = strdup(opt->values[0]); } /* Setup MCA params */ @@ -550,11 +466,15 @@ int prte(int argc, char *argv[]) prte_persistent = true; /* if we are told to daemonize, then we cannot have apps */ - if (!prte_cmd_line_is_taken(prte_cmd_line, "daemonize")) { + if (!prte_cmd_line_is_taken(&results, PRTE_CLI_DAEMONIZE)) { /* see if they want to run an application - let's parse * the cmd line to get it */ - rc = prte_parse_locals(prte_cmd_line, &apps, pargc, pargv, &hostfiles, &hosts); - + rc = prte_parse_locals(schizo, &apps, pargv, &hostfiles, &hosts); + // not-found => no app given + if (PRTE_SUCCESS != rc && PRTE_ERR_NOT_FOUND != rc) { + PRTE_UPDATE_EXIT_STATUS(rc); + goto DONE; + } /* did they provide an app? */ if (PMIX_SUCCESS != rc || 0 == prte_list_get_size(&apps)) { if (proxyrun) { @@ -593,9 +513,10 @@ int prte(int argc, char *argv[]) memcpy(&myproc, val->data.proc, sizeof(pmix_proc_t)); PMIX_VALUE_RELEASE(val); - /** setup callbacks for signals we should forward */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "forward-signals", 0, 0))) { - param = pval->value.data.string; + /* setup callbacks for signals we should forward */ + opt = prte_cmd_line_get_param(&results, PRTE_CLI_FWD_SIGNALS); + if (NULL != opt) { + param = opt->values[0]; } else { param = NULL; } @@ -620,8 +541,8 @@ int prte(int argc, char *argv[]) signals_set = true; /* if we are supporting a singleton, add it to our jobs */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "singleton", 0, 0))) { - rc = prep_singleton(pval->value.data.string); + if (NULL != prte_pmix_server_globals.singleton) { + rc = prep_singleton(prte_pmix_server_globals.singleton); if (PRTE_SUCCESS != ret) { PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); goto DONE; @@ -668,19 +589,19 @@ int prte(int argc, char *argv[]) goto DONE; } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "map-by", 0, 0))) { - if (NULL != strcasestr(pval->value.data.string, "DONOTLAUNCH")) { - prte_set_attribute(&jdata->attributes, PRTE_JOB_DO_NOT_LAUNCH, PRTE_ATTR_GLOBAL, NULL, - PMIX_BOOL); - donotlaunch = true; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_MAPBY); + if (NULL != opt) { + if (NULL != strcasestr(opt->values[0], PRTE_CLI_NOLAUNCH)) { + prte_set_attribute(&jdata->attributes, PRTE_JOB_DO_NOT_LAUNCH, + PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } } /* Did the user specify a prefix, or want prefix by default? */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "prefix", 0, 0)) - || want_prefix_by_default) { - if (NULL != pval) { - param = strdup(pval->value.data.string); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_PREFIX); + if (NULL != opt || want_prefix_by_default) { + if (NULL != opt) { + param = strdup(opt->values[0]); } else { /* --enable-prun-prefix-default was given to prun */ param = strdup(prte_install_dirs.prefix); @@ -724,8 +645,8 @@ int prte(int argc, char *argv[]) } free(tmp_basename); } - prte_set_attribute(&dapp->attributes, PRTE_APP_PREFIX_DIR, PRTE_ATTR_GLOBAL, tpath, - PMIX_STRING); + prte_set_attribute(&dapp->attributes, PRTE_APP_PREFIX_DIR, PRTE_ATTR_GLOBAL, + tpath, PMIX_STRING); } } @@ -754,70 +675,42 @@ int prte(int argc, char *argv[]) /* add any hostfile directives to the daemon job */ if (prte_persistent) { - if (0 < (j = prte_cmd_line_get_ninsts(prte_cmd_line, "hostfile"))) { - if (1 < j) { - prte_show_help("help-prun.txt", "prun:multiple-hostfiles", true, prte_tool_basename, - NULL); - PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); - goto DONE; - } else { - pval = prte_cmd_line_get_param(prte_cmd_line, "hostfile", 0, 0); - prte_set_attribute(&dapp->attributes, PRTE_APP_HOSTFILE, PRTE_ATTR_GLOBAL, - pval->value.data.string, PMIX_STRING); - } - } - if (0 < (j = prte_cmd_line_get_ninsts(prte_cmd_line, "machinefile"))) { - if (1 < j - || prte_get_attribute(&dapp->attributes, PRTE_APP_HOSTFILE, NULL, PMIX_STRING)) { - prte_show_help("help-prun.txt", "prun:multiple-hostfiles", true, prte_tool_basename, - NULL); - PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); - goto DONE; - } else { - pval = prte_cmd_line_get_param(prte_cmd_line, "machinefile", 0, 0); - prte_set_attribute(&dapp->attributes, PRTE_APP_HOSTFILE, PRTE_ATTR_GLOBAL, - pval->value.data.string, PMIX_STRING); - } + opt = prte_cmd_line_get_param(&results, PRTE_CLI_HOSTFILE); + if (NULL != opt) { + tpath = prte_argv_join(opt->values, ','); + prte_set_attribute(&dapp->attributes, PRTE_APP_HOSTFILE, + PRTE_ATTR_GLOBAL, tpath, PMIX_STRING); + free(tpath); } /* Did the user specify any hosts? */ - if (0 < (j = prte_cmd_line_get_ninsts(prte_cmd_line, "host"))) { - char **targ = NULL, *tval; - for (i = 0; i < j; ++i) { - pval = prte_cmd_line_get_param(prte_cmd_line, "host", i, 0); - prte_argv_append_nosize(&targ, pval->value.data.string); - } - tval = prte_argv_join(targ, ','); - prte_set_attribute(&dapp->attributes, PRTE_APP_DASH_HOST, PRTE_ATTR_GLOBAL, tval, - PMIX_STRING); - prte_argv_free(targ); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_HOST); + if (NULL != opt) { + char *tval; + tval = prte_argv_join(opt->values, ','); + prte_set_attribute(&dapp->attributes, PRTE_APP_DASH_HOST, + PRTE_ATTR_GLOBAL, tval, PMIX_STRING); free(tval); } } else { - /* the directives will be in the app(s) */ + /* the directives might be in the app(s) */ if (NULL != hostfiles) { char *tval; tval = prte_argv_join(hostfiles, ','); - prte_set_attribute(&dapp->attributes, PRTE_APP_HOSTFILE, PRTE_ATTR_GLOBAL, tval, - PMIX_STRING); + prte_set_attribute(&dapp->attributes, PRTE_APP_HOSTFILE, + PRTE_ATTR_GLOBAL, tval, PMIX_STRING); free(tval); prte_argv_free(hostfiles); } if (NULL != hosts) { char *tval; tval = prte_argv_join(hosts, ','); - prte_set_attribute(&dapp->attributes, PRTE_APP_DASH_HOST, PRTE_ATTR_GLOBAL, tval, - PMIX_STRING); + prte_set_attribute(&dapp->attributes, PRTE_APP_DASH_HOST, + PRTE_ATTR_GLOBAL, tval, PMIX_STRING); free(tval); prte_argv_free(hosts); } } - /* pickup any relevant envars that need to go on the DVM cmd line */ - rc = prte_schizo.parse_env(prte_cmd_line, environ, &pargv, true); - if (PRTE_SUCCESS != rc) { - PRTE_UPDATE_EXIT_STATUS(rc); - goto DONE; - } /* spawn the DVM - we skip the initial steps as this * isn't a user-level application */ @@ -827,11 +720,12 @@ int prte(int argc, char *argv[]) while (prte_event_base_active && !prte_dvm_ready) { prte_event_loop(prte_event_base, PRTE_EVLOOP_ONCE); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "report-pid", 0, 0))) { + opt = prte_cmd_line_get_param(&results, PRTE_CLI_REPORT_PID); + if (NULL != opt) { /* if the string is a "-", then output to stdout */ - if (0 == strcmp(pval->value.data.string, "-")) { + if (0 == strcmp(opt->values[0], "-")) { fprintf(stdout, "%lu\n", (unsigned long) getpid()); - } else if (0 == strcmp(pval->value.data.string, "+")) { + } else if (0 == strcmp(opt->values[0], "+")) { /* output to stderr */ fprintf(stderr, "%lu\n", (unsigned long) getpid()); } else { @@ -839,7 +733,7 @@ int prte(int argc, char *argv[]) int outpipe; /* see if it is an integer pipe */ leftover = NULL; - outpipe = strtol(pval->value.data.string, &leftover, 10); + outpipe = strtol(opt->values[0], &leftover, 10); if (NULL == leftover || 0 == strlen(leftover)) { /* stitch together the var names and URI */ prte_asprintf(&leftover, "%lu", (unsigned long) getpid()); @@ -850,17 +744,16 @@ int prte(int argc, char *argv[]) } else { /* must be a file */ FILE *fp; - fp = fopen(pval->value.data.string, "w"); + fp = fopen(opt->values[0], "w"); if (NULL == fp) { - prte_output(0, "Impossible to open the file %s in write mode\n", - pval->value.data.string); + prte_output(0, "Impossible to open the file %s in write mode\n", opt->values[0]); PRTE_UPDATE_EXIT_STATUS(1); goto DONE; } /* output my PID */ fprintf(fp, "%lu\n", (unsigned long) getpid()); fclose(fp); - mypidfile = strdup(pval->value.data.string); + mypidfile = strdup(opt->values[0]); } } } @@ -888,129 +781,135 @@ int prte(int argc, char *argv[]) PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_PERSONALITY, personality, PMIX_STRING); /* get display options */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "display", 0, 0))) { - targv = prte_argv_split(pval->value.data.string, ','); - - for (int idx = 0; idx < prte_argv_count(targv); idx++) { - if (0 == strncasecmp(targv[idx], "allocation", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYALLOC", PMIX_STRING); - } - if (0 == strcasecmp(targv[idx], "map")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAY", PMIX_STRING); - } - if (0 == strncasecmp(targv[idx], "bind", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, ":REPORT", PMIX_STRING); - } - if (0 == strcasecmp(targv[idx], "map-devel")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYDEVEL", PMIX_STRING); - } - if (0 == strncasecmp(targv[idx], "topo", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYTOPO", PMIX_STRING); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_DISPLAY); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + targv = prte_argv_split(opt->values[n], ','); + + for (int idx = 0; idx < prte_argv_count(targv); idx++) { + if (0 == strncasecmp(targv[idx], PRTE_CLI_ALLOC, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":"PRTE_CLI_DISPALLOC, PMIX_STRING); + } + if (0 == strcasecmp(targv[idx], PRTE_CLI_MAP)) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":"PRTE_CLI_DISPLAY, PMIX_STRING); + } + if (0 == strncasecmp(targv[idx], PRTE_CLI_BIND, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, ":"PRTE_CLI_REPORT, PMIX_STRING); + } + if (0 == strcasecmp(targv[idx], PRTE_CLI_MAPDEV)) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":"PRTE_CLI_DISPDEV, PMIX_STRING); + } + if (0 == strncasecmp(targv[idx], PRTE_CLI_TOPO, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":"PRTE_CLI_DISPTOPO, PMIX_STRING); + } } + prte_argv_free(targv); } - prte_argv_free(targv); } /* cannot have both files and directory set for output */ outdir = NULL; outfile = NULL; - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "output", 0, 0))) { - targv = prte_argv_split(pval->value.data.string, ','); - for (int idx = 0; NULL != targv[idx]; idx++) { - /* check for qualifiers */ - cptr = strchr(targv[idx], ':'); - if (NULL != cptr) { - *cptr = '\0'; - ++cptr; - /* could be multiple qualifiers, so separate them */ - options = prte_argv_split(cptr, ','); - for (int m=0; NULL != options[m]; m++) { - if (0 == strcasecmp(options[m], "nocopy")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_ONLY, NULL, PMIX_BOOL); - } else if (0 == strcasecmp(options[m], "pattern")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_PATTERN, NULL, PMIX_BOOL); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_OUTPUT); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + targv = prte_argv_split(opt->values[0], ','); + for (int idx = 0; NULL != targv[idx]; idx++) { + /* check for qualifiers */ + cptr = strchr(targv[idx], ':'); + if (NULL != cptr) { + *cptr = '\0'; + ++cptr; + /* could be multiple qualifiers, so separate them */ + options = prte_argv_split(cptr, ','); + for (int m=0; NULL != options[m]; m++) { + if (0 == strcasecmp(options[m], PRTE_CLI_NOCOPY)) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_ONLY, NULL, PMIX_BOOL); + } else if (0 == strcasecmp(options[m], PRTE_CLI_PATTERN)) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_PATTERN, NULL, PMIX_BOOL); #ifdef PMIX_IOF_OUTPUT_RAW - } else if (0 == strcasecmp(options[m], "raw")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_RAW, NULL, PMIX_BOOL); + } else if (0 == strcasecmp(options[m], PRTE_CLI_RAW)) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_RAW, NULL, PMIX_BOOL); #endif + } } + prte_argv_free(options); } - prte_argv_free(options); - } - if (0 == strlen(targv[idx])) { - // only qualifiers were given - continue; - } - /* remove any '=' sign in the directive */ - if (NULL != (ptr = strchr(targv[idx], '='))) { - *ptr = '\0'; - ++ptr; // step over '=' sign - } - if (0 == strncasecmp(targv[idx], "tag", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TAG_OUTPUT, NULL, PMIX_BOOL); - } else if (0 == strncasecmp(targv[idx], "rank", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_RANK_OUTPUT, NULL, PMIX_BOOL); - } else if (0 == strncasecmp(targv[idx], "timestamp", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TIMESTAMP_OUTPUT, &flag, PMIX_BOOL); - } else if (0 == strncasecmp(targv[idx], "xml", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_XML_OUTPUT, NULL, PMIX_BOOL); - } else if (0 == strncasecmp(targv[idx], "merge-stderr-to-stdout", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_MERGE_STDERR_STDOUT, &flag, PMIX_BOOL); - } else if (0 == strncasecmp(targv[idx], "directory", strlen(targv[idx]))) { - if (NULL != outfile) { - prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); - return PRTE_ERR_FATAL; + if (0 == strlen(targv[idx])) { + // only qualifiers were given + continue; } - if (NULL == ptr) { - prte_show_help("help-prte-rmaps-base.txt", - "missing-qualifier", true, - "output", "directory", "directory"); - return PRTE_ERR_FATAL; + /* remove any '=' sign in the directive */ + if (NULL != (ptr = strchr(targv[idx], '='))) { + *ptr = '\0'; + ++ptr; // step over '=' sign } - /* If the given filename isn't an absolute path, then - * convert it to one so the name will be relative to - * the directory where prun was given as that is what - * the user will have seen */ - if (!prte_path_is_absolute(ptr)) { - char cwd[PRTE_PATH_MAX]; - if (NULL == getcwd(cwd, sizeof(cwd))) { - PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); - goto DONE; + if (0 == strncasecmp(targv[idx], PRTE_CLI_TAG, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TAG_OUTPUT, NULL, PMIX_BOOL); + } else if (0 == strncasecmp(targv[idx], PRTE_CLI_RANK, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_RANK_OUTPUT, NULL, PMIX_BOOL); + } else if (0 == strncasecmp(targv[idx], PRTE_CLI_TIMESTAMP, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TIMESTAMP_OUTPUT, &flag, PMIX_BOOL); + } else if (0 == strncasecmp(targv[idx], PRTE_CLI_XML, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_XML_OUTPUT, NULL, PMIX_BOOL); + } else if (0 == strncasecmp(targv[idx], PRTE_CLI_MERGE_ERROUT, strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_MERGE_STDERR_STDOUT, &flag, PMIX_BOOL); + } else if (0 == strncasecmp(targv[idx], PRTE_CLI_DIR, strlen(targv[idx]))) { + if (NULL != outfile) { + prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); + return PRTE_ERR_FATAL; } - outdir = prte_os_path(false, cwd, ptr, NULL); - } else { - outdir = strdup(ptr); - } - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_DIRECTORY, outdir, PMIX_STRING); - } else if (0 == strncasecmp(targv[idx], "file", strlen(targv[idx]))) { - if (NULL != outdir) { - prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); - return PRTE_ERR_FATAL; - } - if (NULL == ptr) { - prte_show_help("help-prte-rmaps-base.txt", - "missing-qualifier", true, - "output", "filename", "filename"); - return PRTE_ERR_FATAL; - } - /* If the given filename isn't an absolute path, then - * convert it to one so the name will be relative to - * the directory where prun was given as that is what - * the user will have seen */ - if (!prte_path_is_absolute(ptr)) { - char cwd[PRTE_PATH_MAX]; - if (NULL == getcwd(cwd, sizeof(cwd))) { - PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); - goto DONE; + if (NULL == ptr) { + prte_show_help("help-prte-rmaps-base.txt", + "missing-qualifier", true, + "output", "directory", "directory"); + return PRTE_ERR_FATAL; } - outfile = prte_os_path(false, cwd, ptr, NULL); - } else { - outfile = strdup(ptr); + /* If the given filename isn't an absolute path, then + * convert it to one so the name will be relative to + * the directory where prun was given as that is what + * the user will have seen */ + if (!prte_path_is_absolute(ptr)) { + char cwd[PRTE_PATH_MAX]; + if (NULL == getcwd(cwd, sizeof(cwd))) { + PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); + goto DONE; + } + outdir = prte_os_path(false, cwd, ptr, NULL); + } else { + outdir = strdup(ptr); + } + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_DIRECTORY, outdir, PMIX_STRING); + } else if (0 == strncasecmp(targv[idx], PRTE_CLI_FILE, strlen(targv[idx]))) { + if (NULL != outdir) { + prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); + return PRTE_ERR_FATAL; + } + if (NULL == ptr) { + prte_show_help("help-prte-rmaps-base.txt", + "missing-qualifier", true, + "output", "filename", "filename"); + return PRTE_ERR_FATAL; + } + /* If the given filename isn't an absolute path, then + * convert it to one so the name will be relative to + * the directory where prun was given as that is what + * the user will have seen */ + if (!prte_path_is_absolute(ptr)) { + char cwd[PRTE_PATH_MAX]; + if (NULL == getcwd(cwd, sizeof(cwd))) { + PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); + goto DONE; + } + outfile = prte_os_path(false, cwd, ptr, NULL); + } else { + outfile = strdup(ptr); + } + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_FILE, outfile, PMIX_STRING); } - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_FILE, outfile, PMIX_STRING); } + prte_argv_free(targv); } - prte_argv_free(targv); } if (NULL != outdir) { free(outdir); @@ -1020,52 +919,48 @@ int prte(int argc, char *argv[]) } /* check what user wants us to do with stdin */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "stdin", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_STDIN_TGT, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_STDIN); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_STDIN_TGT, opt->values[0], PMIX_STRING); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "map-by", 0, 0))) { - if (donotlaunch && NULL == strcasestr(pval->value.data.string, "donotlaunch")) { - /* must add directive */ - char *tval; - prte_asprintf(&tval, "%s:DONOTLAUNCH", pval->value.data.string); - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, tval, PMIX_STRING); - free(tval); - } else { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, pval->value.data.string, PMIX_STRING); - } + opt = prte_cmd_line_get_param(&results, PRTE_CLI_MAPBY); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, opt->values[0], PMIX_STRING); } /* if the user specified a ranking policy, then set it */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "rank-by", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_RANKBY, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_RANKBY); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_RANKBY, opt->values[0], PMIX_STRING); } /* if the user specified a binding policy, then set it */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "bind-to", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, PRTE_CLI_BINDTO); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, opt->values[0], PMIX_STRING); } /* mark if recovery was enabled on the cmd line */ - if (prte_cmd_line_is_taken(prte_cmd_line, "enable-recovery")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_ENABLE_RECOVERY)) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_JOB_RECOVERABLE, NULL, PMIX_BOOL); } /* record the max restarts */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "max-restarts", 0, 0)) - && 0 < pval->value.data.integer) { - ui32 = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_MAX_RESTARTS); + if (NULL != opt) { + ui32 = strtol(opt->values[0], NULL, 10); PRTE_LIST_FOREACH(app, &apps, prte_pmix_app_t) { PMIX_INFO_LIST_ADD(ret, app->info, PMIX_MAX_RESTARTS, &ui32, PMIX_UINT32); } } /* if continuous operation was specified */ - if (prte_cmd_line_is_taken(prte_cmd_line, "continuous")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_CONTINUOUS)) { /* mark this job as continuously operating */ PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_JOB_CONTINUOUS, NULL, PMIX_BOOL); } /* if stop-on-exec was specified */ - if (prte_cmd_line_is_taken(prte_cmd_line, "stop-on-exec")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_STOP_ON_EXEC)) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_DEBUG_STOP_ON_EXEC, NULL, PMIX_BOOL); } @@ -1073,19 +968,22 @@ int prte(int argc, char *argv[]) * as that is what MPICH used */ timeoutenv = NULL; - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "timeout", 0, 0)) || - NULL != (timeoutenv = getenv("MPIEXEC_TIMEOUT"))) { + opt = prte_cmd_line_get_param(&results, PRTE_CLI_TIMEOUT); + if (NULL != opt || NULL != (timeoutenv = getenv("MPIEXEC_TIMEOUT"))) { if (NULL != timeoutenv) { i = strtol(timeoutenv, NULL, 10); /* both cannot be present, or they must agree */ - if (NULL != pval && i != pval->value.data.integer) { - prte_show_help("help-prun.txt", "prun:timeoutconflict", false, prte_tool_basename, - pval->value.data.integer, timeoutenv); - PRTE_UPDATE_EXIT_STATUS(1); - goto DONE; + if (NULL != opt) { + n = strtol(opt->values[0], NULL, 10); + if (i != n) { + prte_show_help("help-prun.txt", "prun:timeoutconflict", false, + prte_tool_basename, n, timeoutenv); + PRTE_UPDATE_EXIT_STATUS(1); + goto DONE; + } } } else { - i = pval->value.data.integer; + i = strtol(opt->values[0], NULL, 10); } #ifdef PMIX_JOB_TIMEOUT PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_JOB_TIMEOUT, &i, PMIX_INT); @@ -1093,21 +991,22 @@ int prte(int argc, char *argv[]) PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_TIMEOUT, &i, PMIX_INT); #endif } - if (prte_cmd_line_is_taken(prte_cmd_line, "get-stack-traces")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_STACK_TRACES)) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_TIMEOUT_STACKTRACES, NULL, PMIX_BOOL); } - if (prte_cmd_line_is_taken(prte_cmd_line, "report-state-on-timeout")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_REPORT_STATE)) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_TIMEOUT_REPORT_STATE, NULL, PMIX_BOOL); } #ifdef PMIX_SPAWN_TIMEOUT - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "spawn-timeout", 0, 0))) { - i = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_SPAWN_TIMEOUT); + if (NULL != opt) { + i = strtol(opt->values[0], NULL, 10); PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_SPAWN_TIMEOUT, &i, PMIX_INT); } #endif /* give the schizo components a chance to add to the job info */ - prte_schizo.job_info(prte_cmd_line, jinfo); + schizo->job_info(&results, jinfo); /* pickup any relevant envars */ ninfo = 4; @@ -1192,12 +1091,6 @@ int prte(int argc, char *argv[]) papps[n].info = (pmix_info_t *) darray.array; papps[n].ninfo = darray.size; } - /* pickup any relevant envars */ - rc = prte_schizo.parse_env(prte_cmd_line, environ, &papps[n].env, false); - if (PRTE_SUCCESS != rc) { - PRTE_UPDATE_EXIT_STATUS(rc); - goto DONE; - } ++n; } diff --git a/src/tools/prte_info/help-prte-info.txt b/src/tools/prte_info/help-prte-info.txt index b237d44e11..57aabae424 100644 --- a/src/tools/prte_info/help-prte-info.txt +++ b/src/tools/prte_info/help-prte-info.txt @@ -12,6 +12,7 @@ # All rights reserved. # Copyright (c) 2010-2020 Cisco Systems, Inc. All rights reserved # Copyright (c) 2016-2020 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -21,12 +22,51 @@ # This is the US/English help file for PRTE pinfo error # messages. # -[usage] +[help] The prte_info command can be used to provide detailed information on your PRTE installation. Syntax: %s # +[version] +Output PRRTE version +# +[verbose] +Set typical debugging verbosity options, with level +determined by number of times this option is given +(e.g., -vvv equates to debugging level of 3) +# +[parseable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[parsable] +Output information (e.g., help messages) in machine-parseable +friendly format +# +[param] +Show MCA parameters. The first parameter is the framework (or the keyword "all"); +the second parameter is the specific component name (or the keyword "all"). +# +[internal] +Show internal MCA parameters (not meant to be modified by users) +# +[path] +Show paths that PRRTE was configured with. Accepts the following parameters: + prefix, bindir, libdir, incdir, mandir, pkglibdir, sysconfdir +# +[arch] +Show architecture PRRTE was compiled on +# +[config] +Show configuration options +# +[hostname] +Show the hostname that PRTE was configured and built on +# +[all] +Show all configuration options and MCA parameters +# [lib-call-fail] A library call unexpectedly failed. This is a terminal error; please show this message to a PRTE wizard: diff --git a/src/tools/prte_info/param.c b/src/tools/prte_info/param.c index eadc3a3f15..1d97ecbf06 100644 --- a/src/tools/prte_info/param.c +++ b/src/tools/prte_info/param.c @@ -18,7 +18,7 @@ * Copyright (c) 2018 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2018 Intel, Inc. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * Copyright (c) 2021 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * @@ -46,8 +46,8 @@ #include "src/include/prte_portable_platform.h" #include "src/include/version.h" #include "src/mca/prteinstalldirs/prteinstalldirs.h" +#include "src/util/argv.h" #include "src/util/printf.h" - #include "src/util/show_help.h" #include "src/tools/prte_info/pinfo.h" @@ -79,27 +79,28 @@ const char *prte_info_path_pkgincludedir = "pkgincludedir"; void prte_info_do_params(bool want_all_in, bool want_internal) { - int count; - char *type, *component, *str; + char *type, *component, *str, **tmp; bool found; - int i; + int i, j; bool want_all = false; prte_value_t *pval; + prte_cli_item_t *opt; prte_info_components_open(); + opt = prte_cmd_line_get_param(&prte_info_cmd_line, "param"); if (want_all_in) { want_all = true; } else { - /* See if the special param "all" was givin to --param; that + /* See if the special param "all" was given to --param; that * superceeds any individual type */ - count = prte_cmd_line_get_ninsts(prte_info_cmd_line, "param"); - for (i = 0; i < count; ++i) { - pval = prte_cmd_line_get_param(prte_info_cmd_line, "param", (int) i, 0); - if (0 == strcmp(prte_info_type_all, pval->value.data.string)) { - want_all = true; - break; + if (NULL != opt) { + for (i=0; NULL != opt->values[i]; i++) { + if (0 == strcmp(prte_info_type_all, opt->values[i])) { + want_all = true; + break; + } } } } @@ -113,30 +114,30 @@ void prte_info_do_params(bool want_all_in, bool want_internal) prte_info_show_mca_params(type, prte_info_component_all, want_internal); } } else { - for (i = 0; i < count; ++i) { - pval = prte_cmd_line_get_param(prte_info_cmd_line, "param", (int) i, 0); - type = pval->value.data.string; - pval = prte_cmd_line_get_param(prte_info_cmd_line, "param", (int) i, 1); - component = pval->value.data.string; - - for (found = false, i = 0; i < mca_types.size; ++i) { - if (NULL == (str = (char *) prte_pointer_array_get_item(&mca_types, i))) { - continue; + if (NULL != opt) { + for (j=0; NULL != opt->values[j]; j++) { + tmp = prte_argv_split(opt->values[j], ' '); + type = tmp[0]; + component = tmp[1]; + + for (found = false, i = 0; i < mca_types.size; ++i) { + if (NULL == (str = (char *) prte_pointer_array_get_item(&mca_types, i))) { + continue; + } + if (0 == strcmp(str, type)) { + found = true; + break; + } } - if (0 == strcmp(str, type)) { - found = true; - break; + + if (!found) { + prte_show_help("help-pinfo.txt", "not-found", true, type); + exit(1); } - } - if (!found) { - char *usage = prte_cmd_line_get_usage_msg(prte_info_cmd_line, false); - prte_show_help("help-pinfo.txt", "not-found", true, type); - free(usage); - exit(1); + prte_info_show_mca_params(type, component, want_internal); + prte_argv_free(tmp); } - - prte_info_show_mca_params(type, component, want_internal); } } } @@ -219,20 +220,22 @@ void prte_info_show_mca_params(const char *type, const char *component, bool wan } } -void prte_info_do_path(bool want_all, prte_cmd_line_t *cmd_line) +void prte_info_do_path(bool want_all) { int i, count; char *scope; prte_value_t *pval; + prte_cli_item_t *opt; /* Check bozo case */ - count = prte_cmd_line_get_ninsts(cmd_line, "path"); - for (i = 0; i < count; ++i) { - pval = prte_cmd_line_get_param(cmd_line, "path", i, 0); - scope = pval->value.data.string; - if (0 == strcmp("all", scope)) { - want_all = true; - break; + opt = prte_cmd_line_get_param(&prte_info_cmd_line, "path"); + if (NULL != opt) { + for (i=0; NULL != opt->values[i]; i++) { + scope = opt->values[i]; + if (0 == strcmp("all", scope)) { + want_all = true; + break; + } } } @@ -256,51 +259,49 @@ void prte_info_do_path(bool want_all, prte_cmd_line_t *cmd_line) prte_info_show_path(prte_info_path_pkglibdir, prte_install_dirs.prtelibdir); prte_info_show_path(prte_info_path_pkgincludedir, prte_install_dirs.prteincludedir); } else { - count = prte_cmd_line_get_ninsts(cmd_line, "path"); - for (i = 0; i < count; ++i) { - pval = prte_cmd_line_get_param(cmd_line, "path", i, 0); - scope = pval->value.data.string; - - if (0 == strcmp(prte_info_path_prefix, scope)) { - prte_info_show_path(prte_info_path_prefix, prte_install_dirs.prefix); - } else if (0 == strcmp(prte_info_path_bindir, scope)) { - prte_info_show_path(prte_info_path_bindir, prte_install_dirs.bindir); - } else if (0 == strcmp(prte_info_path_libdir, scope)) { - prte_info_show_path(prte_info_path_libdir, prte_install_dirs.libdir); - } else if (0 == strcmp(prte_info_path_incdir, scope)) { - prte_info_show_path(prte_info_path_incdir, prte_install_dirs.includedir); - } else if (0 == strcmp(prte_info_path_mandir, scope)) { - prte_info_show_path(prte_info_path_mandir, prte_install_dirs.mandir); - } else if (0 == strcmp(prte_info_path_pkglibdir, scope)) { - prte_info_show_path(prte_info_path_pkglibdir, prte_install_dirs.prtelibdir); - } else if (0 == strcmp(prte_info_path_sysconfdir, scope)) { - prte_info_show_path(prte_info_path_sysconfdir, prte_install_dirs.sysconfdir); - } else if (0 == strcmp(prte_info_path_exec_prefix, scope)) { - prte_info_show_path(prte_info_path_exec_prefix, prte_install_dirs.exec_prefix); - } else if (0 == strcmp(prte_info_path_sbindir, scope)) { - prte_info_show_path(prte_info_path_sbindir, prte_install_dirs.sbindir); - } else if (0 == strcmp(prte_info_path_libexecdir, scope)) { - prte_info_show_path(prte_info_path_libexecdir, prte_install_dirs.libexecdir); - } else if (0 == strcmp(prte_info_path_datarootdir, scope)) { - prte_info_show_path(prte_info_path_datarootdir, prte_install_dirs.datarootdir); - } else if (0 == strcmp(prte_info_path_datadir, scope)) { - prte_info_show_path(prte_info_path_datadir, prte_install_dirs.datadir); - } else if (0 == strcmp(prte_info_path_sharedstatedir, scope)) { - prte_info_show_path(prte_info_path_sharedstatedir, - prte_install_dirs.sharedstatedir); - } else if (0 == strcmp(prte_info_path_localstatedir, scope)) { - prte_info_show_path(prte_info_path_localstatedir, prte_install_dirs.localstatedir); - } else if (0 == strcmp(prte_info_path_infodir, scope)) { - prte_info_show_path(prte_info_path_infodir, prte_install_dirs.infodir); - } else if (0 == strcmp(prte_info_path_pkgdatadir, scope)) { - prte_info_show_path(prte_info_path_pkgdatadir, prte_install_dirs.prtedatadir); - } else if (0 == strcmp(prte_info_path_pkgincludedir, scope)) { - prte_info_show_path(prte_info_path_pkgincludedir, prte_install_dirs.prteincludedir); - } else { - char *usage = prte_cmd_line_get_usage_msg(cmd_line, false); - prte_show_help("help-pinfo.txt", "usage", true, usage); - free(usage); - exit(1); + if (NULL != opt) { + for (i=0; NULL != opt->values[i]; i++) { + scope = opt->values[i]; + + if (0 == strcmp(prte_info_path_prefix, scope)) { + prte_info_show_path(prte_info_path_prefix, prte_install_dirs.prefix); + } else if (0 == strcmp(prte_info_path_bindir, scope)) { + prte_info_show_path(prte_info_path_bindir, prte_install_dirs.bindir); + } else if (0 == strcmp(prte_info_path_libdir, scope)) { + prte_info_show_path(prte_info_path_libdir, prte_install_dirs.libdir); + } else if (0 == strcmp(prte_info_path_incdir, scope)) { + prte_info_show_path(prte_info_path_incdir, prte_install_dirs.includedir); + } else if (0 == strcmp(prte_info_path_mandir, scope)) { + prte_info_show_path(prte_info_path_mandir, prte_install_dirs.mandir); + } else if (0 == strcmp(prte_info_path_pkglibdir, scope)) { + prte_info_show_path(prte_info_path_pkglibdir, prte_install_dirs.prtelibdir); + } else if (0 == strcmp(prte_info_path_sysconfdir, scope)) { + prte_info_show_path(prte_info_path_sysconfdir, prte_install_dirs.sysconfdir); + } else if (0 == strcmp(prte_info_path_exec_prefix, scope)) { + prte_info_show_path(prte_info_path_exec_prefix, prte_install_dirs.exec_prefix); + } else if (0 == strcmp(prte_info_path_sbindir, scope)) { + prte_info_show_path(prte_info_path_sbindir, prte_install_dirs.sbindir); + } else if (0 == strcmp(prte_info_path_libexecdir, scope)) { + prte_info_show_path(prte_info_path_libexecdir, prte_install_dirs.libexecdir); + } else if (0 == strcmp(prte_info_path_datarootdir, scope)) { + prte_info_show_path(prte_info_path_datarootdir, prte_install_dirs.datarootdir); + } else if (0 == strcmp(prte_info_path_datadir, scope)) { + prte_info_show_path(prte_info_path_datadir, prte_install_dirs.datadir); + } else if (0 == strcmp(prte_info_path_sharedstatedir, scope)) { + prte_info_show_path(prte_info_path_sharedstatedir, + prte_install_dirs.sharedstatedir); + } else if (0 == strcmp(prte_info_path_localstatedir, scope)) { + prte_info_show_path(prte_info_path_localstatedir, prte_install_dirs.localstatedir); + } else if (0 == strcmp(prte_info_path_infodir, scope)) { + prte_info_show_path(prte_info_path_infodir, prte_install_dirs.infodir); + } else if (0 == strcmp(prte_info_path_pkgdatadir, scope)) { + prte_info_show_path(prte_info_path_pkgdatadir, prte_install_dirs.prtedatadir); + } else if (0 == strcmp(prte_info_path_pkgincludedir, scope)) { + prte_info_show_path(prte_info_path_pkgincludedir, prte_install_dirs.prteincludedir); + } else { + prte_show_help("help-pinfo.txt", "usage", true, "USAGE"); + exit(1); + } } } } diff --git a/src/tools/prte_info/pinfo.h b/src/tools/prte_info/pinfo.h index d906b91f61..eff70c81ec 100644 --- a/src/tools/prte_info/pinfo.h +++ b/src/tools/prte_info/pinfo.h @@ -14,7 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2016-2019 Intel, Inc. All rights reserved. * Copyright (c) 2018 Intel, Inc. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -39,7 +39,7 @@ BEGIN_C_DECLS */ extern bool prte_info_pretty; -extern prte_cmd_line_t *prte_info_cmd_line; +extern prte_cli_result_t prte_info_cmd_line; extern const char *prte_info_type_all; extern const char *prte_info_type_prte; @@ -58,7 +58,7 @@ extern const char *prte_info_ver_release; extern const char *prte_info_ver_greek; extern const char *prte_info_ver_svn; -void prte_info_do_version(bool want_all, prte_cmd_line_t *cmd_line); +void prte_info_do_version(bool want_all); void prte_info_show_prte_version(const char *scope); void prte_info_show_component_version(const char *type_name, const char *component_name, const char *scope, const char *ver_type); @@ -91,7 +91,7 @@ extern const char *prte_info_path_pkgincludedir; void prte_info_do_params(bool want_all, bool want_internal); void prte_info_show_mca_params(const char *type, const char *component, bool want_internal); -void prte_info_do_path(bool want_all, prte_cmd_line_t *cmd_line); +void prte_info_do_path(bool want_all); void prte_info_show_path(const char *type, const char *value); void prte_info_do_arch(void); diff --git a/src/tools/prte_info/prte_info.c b/src/tools/prte_info/prte_info.c index 7332fe6857..64f40ec054 100644 --- a/src/tools/prte_info/prte_info.c +++ b/src/tools/prte_info/prte_info.c @@ -16,7 +16,7 @@ * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -48,6 +48,7 @@ #include "src/mca/schizo/base/base.h" #include "src/prted/pmix/pmix_server.h" #include "src/util/argv.h" +#include "src/util/basename.h" #include "src/util/cmd_line.h" #include "src/util/error.h" #include "src/util/path.h" @@ -66,7 +67,7 @@ */ bool prte_info_pretty = true; -prte_cmd_line_t *prte_info_cmd_line = NULL; +prte_cli_result_t prte_info_cmd_line = PRTE_CLI_RESULT_STATIC_INIT; const char *prte_info_type_all = "all"; const char *prte_info_type_prte = "prte"; @@ -74,41 +75,6 @@ const char *prte_info_type_base = "base"; prte_pointer_array_t mca_types = {{0}}; -prte_cmd_line_init_t info_cmd_line_opts[] - = {{'h', "help", 0, PRTE_CMD_LINE_TYPE_BOOL, "This help message", PRTE_CMD_LINE_OTYPE_GENERAL}, - {'V', "version", 0, PRTE_CMD_LINE_TYPE_BOOL, "Print version and exit", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "show-version", 2, PRTE_CMD_LINE_TYPE_STRING, - "Show version of PRTE or a component. The first parameter can be the keywords \"prte\" or " - "\"all\", a framework name (indicating all components in a framework), or a " - "framework:component string (indicating a specific component). The second parameter can " - "be one of: full, major, minor, release, greek, svn.", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "param", 2, PRTE_CMD_LINE_TYPE_STRING, - "Show MCA parameters. The first parameter is the framework (or the keyword \"all\"); the " - "second parameter is the specific component name (or the keyword \"all\").", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "internal", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Show internal MCA parameters (not meant to be modified by users)", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "path", 1, PRTE_CMD_LINE_TYPE_STRING, - "Show paths that PRTE was configured with. Accepts the following parameters: prefix, " - "bindir, libdir, incdir, mandir, pkglibdir, sysconfdir", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "arch", 0, PRTE_CMD_LINE_TYPE_BOOL, "Show architecture PRTE was compiled on", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'c', "config", 0, PRTE_CMD_LINE_TYPE_BOOL, "Show configuration options", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'\0', "hostname", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Show the hostname that PRTE was configured " - "and built on", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'a', "all", 0, PRTE_CMD_LINE_TYPE_BOOL, "Show all configuration options and MCA parameters", - PRTE_CMD_LINE_OTYPE_GENERAL}, - - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; - int main(int argc, char *argv[]) { int ret = 0; @@ -118,11 +84,22 @@ int main(int argc, char *argv[]) bool want_all = false; int i; char *str; + int option_index = 0; /* getopt_long stores the option index here. */ + int n, opt, rc; + bool found; + char *ptr; + prte_info_item_t *instance; + char *personality; + prte_schizo_base_module_t *schizo; + prte_cli_result_t results; /* protect against problems if someone passes us thru a pipe * and then abnormally terminates the pipe early */ signal(SIGPIPE, SIG_IGN); + prte_tool_basename = prte_basename(argv[0]); + prte_tool_actual = "prte_info"; + /* Initialize the argv parsing stuff */ if (PRTE_SUCCESS != (ret = prte_init_util(PRTE_PROC_MASTER))) { prte_show_help("help-prte-info.txt", "lib-call-fail", true, "prte_init_util", __FILE__, @@ -130,50 +107,62 @@ int main(int argc, char *argv[]) exit(ret); } - prte_info_cmd_line = PRTE_NEW(prte_cmd_line_t); - if (NULL == prte_info_cmd_line) { - ret = errno; - prte_show_help("help-prte-info.txt", "lib-call-fail", true, "prte_cmd_line_create", - __FILE__, __LINE__, NULL); - exit(ret); + /* open the SCHIZO framework */ + ret = prte_mca_base_framework_open(&prte_schizo_base_framework, + PRTE_MCA_BASE_OPEN_DEFAULT); + if (PRTE_SUCCESS != ret) { + PRTE_ERROR_LOG(ret); + return ret; } - ret = prte_cmd_line_add(prte_info_cmd_line, info_cmd_line_opts); - if (PRTE_SUCCESS != ret) { + if (PRTE_SUCCESS != (ret = prte_schizo_base_select())) { + PRTE_ERROR_LOG(ret); return ret; } - /* Do the parsing */ - ret = prte_cmd_line_parse(prte_info_cmd_line, false, false, argc, argv); - if (PRTE_SUCCESS != ret) { - if (PRTE_ERR_SILENT != ret) { - fprintf(stderr, "%s: command line error (%s)\n", argv[0], prte_strerror(ret)); + /* look for any personality specification */ + personality = NULL; + for (i = 0; NULL != argv[i]; i++) { + if (0 == strcmp(argv[i], "--personality")) { + personality = argv[i + 1]; + break; } - cmd_error = true; } - if (!cmd_error - && (prte_cmd_line_is_taken(prte_info_cmd_line, "help") - || prte_cmd_line_is_taken(prte_info_cmd_line, "h"))) { - char *usage; - want_help = true; - usage = prte_cmd_line_get_usage_msg(prte_info_cmd_line, false); - str = prte_show_help_string("help-prte-info.txt", "usage", true, usage); - if (NULL != str) { - printf("%s", str); - free(str); - } - free(usage); + /* detect if we are running as a proxy and select the active + * schizo module for this tool */ + schizo = prte_schizo_base_detect_proxy(personality); + if (NULL == schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, personality); + return 1; } - if (cmd_error || want_help) { - prte_mca_base_close(); - PRTE_RELEASE(prte_info_cmd_line); - exit(cmd_error ? 1 : 0); + if (NULL == personality) { + personality = schizo->name; } - if (prte_cmd_line_is_taken(prte_info_cmd_line, "version")) { - fprintf(stdout, "PRTE v%s\n\n%s\n", PRTE_VERSION, PACKAGE_BUGREPORT); - exit(0); + /* parse the input argv to get values, including everyone's MCA params */ + PRTE_CONSTRUCT(&prte_info_cmd_line, prte_cli_result_t); + ret = schizo->parse_cli(argv, &prte_info_cmd_line); + if (PRTE_SUCCESS != ret) { + PRTE_DESTRUCT(&prte_info_cmd_line); + if (PRTE_ERR_SILENT != ret) { + fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); + } else { + ret = PRTE_SUCCESS; + } + return ret; + } + // we do NOT accept arguments other than our own + if (NULL != prte_info_cmd_line.tail) { + str = prte_argv_join(prte_info_cmd_line.tail, ' '); + ptr = prte_show_help_string("help-pterm.txt", "no-args", false, + prte_tool_basename, str, prte_tool_basename); + free(str); + if (NULL != ptr) { + printf("%s", ptr); + free(ptr); + } + return -1; } /* setup the mca_types array */ @@ -198,37 +187,29 @@ int main(int argc, char *argv[]) } /* Execute the desired action(s) */ - - if (prte_cmd_line_is_taken(prte_info_cmd_line, "prte_info_pretty")) { - prte_info_pretty = true; - } else if (prte_cmd_line_is_taken(prte_info_cmd_line, "parsable") - || prte_cmd_line_is_taken(prte_info_cmd_line, "parseable")) { - prte_info_pretty = false; - } - - want_all = prte_cmd_line_is_taken(prte_info_cmd_line, "all"); - if (want_all || prte_cmd_line_is_taken(prte_info_cmd_line, "show-version")) { - prte_info_do_version(want_all, prte_info_cmd_line); + want_all = prte_cmd_line_is_taken(&prte_info_cmd_line, "all"); + if (want_all) { + prte_info_do_version(want_all); acted = true; } - if (want_all || prte_cmd_line_is_taken(prte_info_cmd_line, "path")) { - prte_info_do_path(want_all, prte_info_cmd_line); + if (want_all || prte_cmd_line_is_taken(&prte_info_cmd_line, "path")) { + prte_info_do_path(want_all); acted = true; } - if (want_all || prte_cmd_line_is_taken(prte_info_cmd_line, "arch")) { + if (want_all || prte_cmd_line_is_taken(&prte_info_cmd_line, "arch")) { prte_info_do_arch(); acted = true; } - if (want_all || prte_cmd_line_is_taken(prte_info_cmd_line, "hostname")) { + if (want_all || prte_cmd_line_is_taken(&prte_info_cmd_line, "hostname")) { prte_info_do_hostname(); acted = true; } - if (want_all || prte_cmd_line_is_taken(prte_info_cmd_line, "config")) { + if (want_all || prte_cmd_line_is_taken(&prte_info_cmd_line, "config")) { prte_info_do_config(true); acted = true; } - if (want_all || prte_cmd_line_is_taken(prte_info_cmd_line, "param")) { - prte_info_do_params(want_all, prte_cmd_line_is_taken(prte_info_cmd_line, "internal")); + if (want_all || prte_cmd_line_is_taken(&prte_info_cmd_line, "param")) { + prte_info_do_params(want_all, prte_cmd_line_is_taken(&prte_info_cmd_line, "internal")); acted = true; } diff --git a/src/tools/prte_info/version.c b/src/tools/prte_info/version.c index 7f2b93b54e..c0362de4a6 100644 --- a/src/tools/prte_info/version.c +++ b/src/tools/prte_info/version.c @@ -15,7 +15,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2018-2020 Intel, Inc. All rights reserved. * Copyright (c) 2021 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -30,6 +30,7 @@ #include "src/include/version.h" #include "src/mca/base/base.h" +#include "src/util/argv.h" #include "src/util/printf.h" #include "pmix.h" @@ -93,14 +94,13 @@ void prte_info_show_prte_version(const char *scope) * - want_all: True if all components' info is required. * - cmd_line: The constructed command line argument */ -void prte_info_do_version(bool want_all, prte_cmd_line_t *cmd_line) +void prte_info_do_version(bool want_all) { - unsigned int count; - size_t i; - char *arg1, *scope, *type, *component; + size_t i, n; + char *arg1, *scope, *type, *component, **tmp; char *pos; int j; - prte_value_t *pval; + prte_cli_item_t *opt; prte_info_components_open(); @@ -114,36 +114,38 @@ void prte_info_do_version(bool want_all, prte_cmd_line_t *cmd_line) prte_info_type_all); } } else { - count = prte_cmd_line_get_ninsts(cmd_line, "show-version"); - for (i = 0; i < count; ++i) { - pval = prte_cmd_line_get_param(cmd_line, "show-version", (int) i, 0); - arg1 = pval->value.data.string; - pval = prte_cmd_line_get_param(cmd_line, "show-version", (int) i, 1); - scope = pval->value.data.string; + opt = prte_cmd_line_get_param(&prte_info_cmd_line, "show-version"); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + tmp = prte_argv_split(opt->values[n], ' '); + arg1 = tmp[0]; + scope = tmp[2]; - /* Version of PRTE */ + /* Version of PRTE */ - if (0 == strcmp(prte_info_type_prte, arg1)) { - prte_info_show_prte_version(scope); - } + if (0 == strcmp(prte_info_type_prte, arg1)) { + prte_info_show_prte_version(scope); + } - /* Specific type and component */ + /* Specific type and component */ - else if (NULL != (pos = strchr(arg1, ':'))) { - *pos = '\0'; - type = arg1; - pos++; - component = pos; + else if (NULL != (pos = strchr(arg1, ':'))) { + *pos = '\0'; + type = arg1; + pos++; + component = pos; - prte_info_show_component_version(type, component, scope, prte_info_ver_all); + prte_info_show_component_version(type, component, scope, prte_info_ver_all); - } + } - /* All components of a specific type */ + /* All components of a specific type */ - else { - prte_info_show_component_version(arg1, prte_info_component_all, scope, - prte_info_ver_all); + else { + prte_info_show_component_version(arg1, prte_info_component_all, scope, + prte_info_ver_all); + } + prte_argv_free(tmp); } } } diff --git a/src/tools/prted/prted.c b/src/tools/prted/prted.c index aa3a85e291..94242a5175 100644 --- a/src/tools/prted/prted.c +++ b/src/tools/prted/prted.c @@ -19,7 +19,7 @@ * Copyright (c) 2013-2020 Intel, Inc. All rights reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -129,55 +129,7 @@ static int ncollected = 0; static bool node_regex_waiting = false; static bool prted_abort = false; static char *prte_parent_uri = NULL; -static prte_cmd_line_t *prte_cmd_line = NULL; - -/* - * define the prted context table for obtaining parameters - */ -prte_cmd_line_init_t prted_cmd_line_opts[] = { - /* DVM-specific options */ - /* uri of PMIx publish/lookup server, or at least where to get it */ - {'\0', "prte-server", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify the URI of the publish/lookup server, or the name of the file (specified as " - "file:filename) that contains that info", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "dvm-master-uri", 1, PRTE_CMD_LINE_TYPE_STRING, "URI for the DVM master", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "parent-uri", 1, PRTE_CMD_LINE_TYPE_STRING, - "URI for the parent if tree launch is enabled.", PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "tree-spawn", 0, PRTE_CMD_LINE_TYPE_BOOL, "Tree-based spawn in progress", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "daemonize", 0, PRTE_CMD_LINE_TYPE_BOOL, "Daemonize the DVM daemons into the background", - PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "set-sid", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Direct the DVM daemons to separate from the current session", PRTE_CMD_LINE_OTYPE_DVM}, - {'\0', "prtemca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific PRTE MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - {'\0', "pmixmca", 2, PRTE_CMD_LINE_TYPE_STRING, - "Pass context-specific PMIx MCA parameters; they are considered global if --gmca is not used " - "and only one context is specified (arg0 is the parameter name; arg1 is the parameter value)", - PRTE_CMD_LINE_OTYPE_LAUNCH}, - - /* Debug options */ - {'\0', "debug", 0, PRTE_CMD_LINE_TYPE_BOOL, "Top-level PRTE debug switch (default: false)", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-daemons", 0, PRTE_CMD_LINE_TYPE_BOOL, "Debug daemons", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-verbose", 1, PRTE_CMD_LINE_TYPE_INT, - "Verbosity level for PRTE debug messages (default: 1)", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'d', "debug-devel", 0, PRTE_CMD_LINE_TYPE_BOOL, "Enable debugging of PRTE", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "debug-daemons-file", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Enable debugging of any PRTE daemons used by this application, storing output in files", - PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "leave-session-attached", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Do not discard stdout/stderr of remote PRTE daemons", PRTE_CMD_LINE_OTYPE_DEBUG}, - {'\0', "test-suicide", 1, PRTE_CMD_LINE_TYPE_BOOL, "Suicide instead of clean abort after delay", - PRTE_CMD_LINE_OTYPE_DEBUG}, - - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; +static prte_cli_result_t results; typedef struct { prte_pmix_lock_t lock; @@ -245,7 +197,7 @@ int main(int argc, char *argv[]) prte_value_t *pval; int8_t flag; uint8_t naliases, ni; - char **nonlocal = NULL; + char **nonlocal = NULL, *personality; int n; pmix_info_t info; size_t z1 = 1; @@ -254,6 +206,7 @@ int main(int argc, char *argv[]) char **pargv; int pargc; prte_schizo_base_module_t *schizo; + prte_cli_item_t *opt; char *umask_str = getenv("PRTE_DAEMON_UMASK_VALUE"); if (NULL != umask_str) { @@ -267,8 +220,10 @@ int main(int argc, char *argv[]) /* initialize the globals */ PMIX_DATA_BUFFER_CREATE(bucket); prte_tool_basename = prte_basename(argv[0]); + prte_tool_actual = "prted"; pargc = argc; - pargv = prte_argv_copy(argv); + pargv = prte_argv_copy_strip(argv); // strip any quoted arguments + /* save a pristine copy of the environment for launch purposes. * This MUST be done so that we can pass it to any local procs we * spawn - otherwise, those local procs will get a bunch of @@ -294,24 +249,9 @@ int main(int argc, char *argv[]) return ret; } - /* init the tiny part of PRTE we use */ + /* init the tiny part of PRTE we initially use */ prte_init_util(PRTE_PROC_DAEMON); - /* setup the base cmd line */ - prte_cmd_line = PRTE_NEW(prte_cmd_line_t); - ret = prte_cmd_line_add(prte_cmd_line, prted_cmd_line_opts); - if (PRTE_SUCCESS != ret) { - return ret; - } - - /* parse the result to get values - this will not include MCA params */ - if (PRTE_SUCCESS != (ret = prte_cmd_line_parse(prte_cmd_line, true, false, argc, argv))) { - if (PRTE_ERR_SILENT != ret) { - fprintf(stderr, "%s: command line error (%s)\n", argv[0], prte_strerror(ret)); - } - return ret; - } - /* open the SCHIZO framework */ if (PRTE_SUCCESS != (ret = prte_mca_base_framework_open(&prte_schizo_base_framework, @@ -325,38 +265,43 @@ int main(int argc, char *argv[]) return ret; } + /* look for any personality specification */ + personality = NULL; + for (i = 0; NULL != pargv[i]; i++) { + if (0 == strcmp(pargv[i], "--personality")) { + personality = pargv[i + 1]; + break; + } + } + /* get our schizo module */ - prte_unsetenv("PRTE_MCA_schizo_proxy", &environ); - schizo = prte_schizo.detect_proxy("prte"); - if (NULL == schizo || 0 != strcmp(schizo->name, "prte")) { - prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, "NONE"); + schizo = prte_schizo_base_detect_proxy(personality); + if (NULL == schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, personality); return 1; } /* parse the CLI to load the MCA params */ - if (PRTE_SUCCESS != (ret = schizo->parse_cli(pargc, 0, pargv, NULL))) { + PRTE_CONSTRUCT(&results, prte_cli_result_t); + ret = schizo->parse_cli(pargv, &results); + if (PRTE_SUCCESS != ret) { if (PRTE_ERR_SILENT != ret) { fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(ret)); + } else { + ret = PRTE_SUCCESS; // printed version or help } return ret; } - /* set debug flags */ - prte_debug_flag = prte_cmd_line_is_taken(prte_cmd_line, "debug"); - prte_debug_daemons_flag = prte_cmd_line_is_taken(prte_cmd_line, "debug-daemons"); - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "debug-verbose", 0, 0))) { - prte_debug_verbosity = pval->value.data.integer; - } - prte_debug_daemons_file_flag = prte_cmd_line_is_taken(prte_cmd_line, "debug-daemons-file"); - if (prte_debug_daemons_file_flag) { - prte_debug_daemons_flag = true; - } - prte_leave_session_attached = prte_cmd_line_is_taken(prte_cmd_line, "leave-session-attached"); - /* if any debug level is set, ensure we output debug level dumps */ - if (prte_debug_flag || prte_debug_daemons_flag || prte_leave_session_attached) { - prte_devel_level_output = true; + /* check if we are running as root - if we are, then only allow + * us to proceed if the allow-run-as-root flag was given. Otherwise, + * exit with a giant warning message + */ + if (0 == geteuid()) { + schizo->allow_run_as_root(&results); // will exit us if not allowed } + /* if prte_daemon_debug is set, let someone know we are alive right * away just in case we have a problem along the way */ @@ -368,8 +313,7 @@ int main(int argc, char *argv[]) /* detach from controlling terminal * otherwise, remain attached so output can get to us */ - if (!prte_debug_flag && !prte_debug_daemons_flag - && prte_cmd_line_is_taken(prte_cmd_line, "daemonize")) { + if (!prte_debug_flag && !prte_cmd_line_is_taken(&results, PRTE_CLI_DAEMONIZE)) { pipe(wait_pipe); prte_state_base_parent_fd = wait_pipe[1]; prte_daemon_init_callback(NULL, wait_dvm); @@ -377,7 +321,7 @@ int main(int argc, char *argv[]) } #if defined(HAVE_SETSID) /* see if we were directed to separate from current session */ - if (prte_cmd_line_is_taken(prte_cmd_line, "set-sid")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_SET_SID)) { setsid(); } #endif @@ -487,8 +431,8 @@ int main(int argc, char *argv[]) } PMIX_VALUE_LOAD(&val, myuri, PMIX_STRING); free(myuri); - if (PMIX_SUCCESS - != (prc = PMIx_Store_internal(&prte_process_info.myproc, PMIX_PROC_URI, &val))) { + prc = PMIx_Store_internal(&prte_process_info.myproc, PMIX_PROC_URI, &val); + if (PMIX_SUCCESS != prc) { PMIX_ERROR_LOG(prc); PMIX_VALUE_DESTRUCT(&val); ret = PRTE_ERROR; @@ -503,7 +447,7 @@ int main(int argc, char *argv[]) /* output a message indicating we are alive, our name, and our pid * for debugging purposes */ - if (prte_debug_daemons_flag) { + if (prte_debug_flag) { fprintf(stderr, "Daemon %s checking in as pid %ld on host %s\n", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), (long) prte_process_info.pid, prte_process_info.nodename); @@ -513,7 +457,8 @@ int main(int argc, char *argv[]) PMIX_VALUE_LOAD(&val, prte_process_info.my_hnp_uri, PMIX_STRING); PMIX_LOAD_NSPACE(proc.nspace, prte_process_info.myproc.nspace); proc.rank = PRTE_PROC_MY_HNP->rank; - if (PMIX_SUCCESS != (prc = PMIx_Store_internal(&proc, PMIX_PROC_URI, &val))) { + prc = PMIx_Store_internal(&proc, PMIX_PROC_URI, &val); + if (PMIX_SUCCESS != prc) { PMIX_ERROR_LOG(prc); PMIX_VALUE_DESTRUCT(&val); ret = PRTE_ERROR; @@ -551,21 +496,22 @@ int main(int argc, char *argv[]) /* tell the routed module that we have a path * back to the HNP */ - if (PRTE_SUCCESS - != (ret = prte_routed.update_route(PRTE_PROC_MY_HNP, PRTE_PROC_MY_PARENT))) { + ret = prte_routed.update_route(PRTE_PROC_MY_HNP, PRTE_PROC_MY_PARENT); + if (PRTE_SUCCESS != ret) { PRTE_ERROR_LOG(ret); goto DONE; } /* and a path to our parent */ - if (PRTE_SUCCESS - != (ret = prte_routed.update_route(PRTE_PROC_MY_PARENT, PRTE_PROC_MY_PARENT))) { + ret = prte_routed.update_route(PRTE_PROC_MY_PARENT, PRTE_PROC_MY_PARENT); + if (PRTE_SUCCESS != ret) { PRTE_ERROR_LOG(ret); goto DONE; } /* set the lifeline to point to our parent so that we * can handle the situation if that lifeline goes away */ - if (PRTE_SUCCESS != (ret = prte_routed.set_lifeline(PRTE_PROC_MY_PARENT))) { + ret = prte_routed.set_lifeline(PRTE_PROC_MY_PARENT); + if (PRTE_SUCCESS != ret) { PRTE_ERROR_LOG(ret); goto DONE; } @@ -824,52 +770,59 @@ int main(int argc, char *argv[]) * from our cmd line so we can pass them along to the daemons we spawn - * otherwise, only the first layer of daemons will ever see them */ - if (prte_cmd_line_is_taken(prte_cmd_line, "tree-spawn")) { + if (prte_cmd_line_is_taken(&results, PRTE_CLI_TREE_SPAWN)) { int j, k; bool ignore; - char *no_keep[] = {"prte_hnp_uri", - "prte_ess_jobid", - "prte_ess_vpid", - "prte_ess_num_procs", - "prte_parent_uri", - "mca_base_env_list", - NULL}; - for (i = 0; i < argc; i++) { - if (0 == strcmp("-" PRTE_MCA_CMD_LINE_ID, argv[i]) - || 0 == strcmp("--" PRTE_MCA_CMD_LINE_ID, argv[i])) { + char *no_keep[] = { + "prte_hnp_uri", + "prte_ess_jobid", + "prte_ess_vpid", + "prte_ess_num_procs", + "prte_parent_uri", + "mca_base_env_list", + NULL + }; + opt = prte_cmd_line_get_param(&results, PRTE_CLI_PRTEMCA); + if (NULL != opt) { + // cycle across found values + for (i=0; NULL != opt->values[i]; i++) { + char *t = strchr(opt->values[i], '='); + *t = '\0'; + ++t; ignore = false; /* see if this is something we cannot pass along */ for (k = 0; NULL != no_keep[k]; k++) { - if (0 == strcmp(no_keep[k], argv[i + 1])) { + if (0 == strcmp(no_keep[k], opt->values[i])) { ignore = true; break; } } if (!ignore) { - /* see if this is already present so we at least can - * avoid growing the cmd line with duplicates - */ - if (NULL != prted_cmd_line) { - for (j = 0; NULL != prted_cmd_line[j]; j++) { - if (0 == strcmp(argv[i + 1], prted_cmd_line[j])) { - /* already here - ignore it */ - ignore = true; - break; - } - } - } - if (!ignore) { - prte_argv_append_nosize(&prted_cmd_line, argv[i]); - prte_argv_append_nosize(&prted_cmd_line, argv[i + 1]); - prte_argv_append_nosize(&prted_cmd_line, argv[i + 2]); - } + prte_argv_append_nosize(&prted_cmd_line, "--"PRTE_CLI_PRTEMCA); + prte_argv_append_nosize(&prted_cmd_line, opt->values[i]); + prte_argv_append_nosize(&prted_cmd_line, t); } - i += 2; + --t; + *t = '='; + } + } + opt = prte_cmd_line_get_param(&results, PRTE_CLI_PMIXMCA); + if (NULL != opt) { + // cycle across found values - we always pass PMIx values + for (i=0; NULL != opt->values[i]; i++) { + char *t = strchr(opt->values[i], '='); + *t = '\0'; + ++t; + prte_argv_append_nosize(&prted_cmd_line, "--"PRTE_CLI_PMIXMCA); + prte_argv_append_nosize(&prted_cmd_line, opt->values[i]); + prte_argv_append_nosize(&prted_cmd_line, t); + --t; + *t = '='; } } } - if (prte_debug_daemons_flag) { + if (prte_debug_flag) { prte_output(0, "%s prted: up and running - waiting for commands!", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); } @@ -904,7 +857,7 @@ int main(int argc, char *argv[]) static void shutdown_callback(int fd, short flags, void *arg) { prte_timer_t *tm = (prte_timer_t *) arg; - bool suicide; + bool suicide = false; if (NULL != tm) { /* release the timer */ @@ -913,7 +866,9 @@ static void shutdown_callback(int fd, short flags, void *arg) /* if we were ordered to abort, do so */ if (prted_abort) { - suicide = prte_cmd_line_is_taken(prte_cmd_line, "test-suicide"); + if (prte_cmd_line_is_taken(&results, PRTE_CLI_TEST_SUICIDE)) { + suicide = true; + } prte_output(0, "%s is executing %s abort", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), suicide ? "suicide" : "clean"); /* do -not- call finalize as this will send a message to the HNP diff --git a/src/tools/prun/prun.c b/src/tools/prun/prun.c index fac23a06b3..66e16aea41 100644 --- a/src/tools/prun/prun.c +++ b/src/tools/prun/prun.c @@ -19,7 +19,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Geoffroy Vallee. All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * Copyright (c) 2021 Amazon.com, Inc. or its affiliates. All Rights * reserved. * $COPYRIGHT$ @@ -109,7 +109,6 @@ static prte_event_t term_handler; static int term_pipe[2]; static prte_mutex_t prun_abort_inprogress_lock = PRTE_MUTEX_STATIC_INIT; static bool verbose = false; -static prte_cmd_line_t *prte_cmd_line = NULL; static prte_list_t forwarded_signals; static void abort_signal_callback(int signal); @@ -276,42 +275,6 @@ static void setupcbfunc(pmix_status_t status, pmix_info_t info[], size_t ninfo, PRTE_PMIX_WAKEUP_THREAD(&mylock->lock); } -static prte_cmd_line_init_t prte_tool_options[] = { - /* look first for a system server */ - {'\0', "system-server-first", 0, PRTE_CMD_LINE_TYPE_BOOL, - "First look for a system server and connect to it if found", PRTE_CMD_LINE_OTYPE_DVM}, - /* connect only to a system server */ - {'\0', "system-server-only", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Connect only to a system-level server", PRTE_CMD_LINE_OTYPE_DVM}, - /* do not connect */ - {'\0', "do-not-connect", 0, PRTE_CMD_LINE_TYPE_BOOL, "Do not connect to a server", - PRTE_CMD_LINE_OTYPE_DVM}, - /* wait to connect */ - {'\0', "wait-to-connect", 1, PRTE_CMD_LINE_TYPE_INT, - "Delay specified number of seconds before trying to connect", PRTE_CMD_LINE_OTYPE_DVM}, - /* number of times to try to connect */ - {'\0', "num-connect-retries", 1, PRTE_CMD_LINE_TYPE_INT, - "Max number of times to try to connect", PRTE_CMD_LINE_OTYPE_DVM}, - /* provide a connection PID */ - {'\0', "pid", 1, PRTE_CMD_LINE_TYPE_STRING, - "PID of the daemon to which we should connect (int => PID or file: for file containing " - "the PID", - PRTE_CMD_LINE_OTYPE_DVM}, - /* provide a connection namespace */ - {'\0', "namespace", 1, PRTE_CMD_LINE_TYPE_STRING, - "Namespace of the daemon to which we should connect", PRTE_CMD_LINE_OTYPE_DVM}, - /* uri of the dvm, or at least where to get it */ - {'\0', "dvm-uri", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify the URI of the DVM master, or the name of the file (specified as file:filename) that " - "contains that info", - PRTE_CMD_LINE_OTYPE_DVM}, - /* override personality */ - {'\0', "personality", 1, PRTE_CMD_LINE_TYPE_STRING, "Specify the personality to be used", - PRTE_CMD_LINE_OTYPE_DVM}, - - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; - int prun(int argc, char *argv[]) { int rc = 1, i; @@ -328,7 +291,6 @@ int prun(int argc, char *argv[]) pmix_app_t *papps = NULL; size_t napps; mylock_t mylock; - prte_value_t *pval; uint32_t ui32; pid_t pid; char **pargv, **targv; @@ -345,13 +307,16 @@ int prun(int argc, char *argv[]) char *outfile = NULL; char *personality; pmix_proc_t parent; + prte_cli_result_t results; + prte_cli_item_t *opt; /* init the globals */ PRTE_CONSTRUCT(&apps, prte_list_t); PRTE_CONSTRUCT(&forwarded_signals, prte_list_t); prte_tool_basename = prte_basename(argv[0]); + prte_tool_actual = "prun"; pargc = argc; - pargv = prte_argv_copy(argv); + pargv = prte_argv_copy_strip(argv); // strip any quoted arguments gethostname(hostname, sizeof(hostname)); /* because we have to use the schizo framework and init our hostname @@ -414,9 +379,9 @@ int prun(int argc, char *argv[]) signal(SIGPIPE, epipe_signal_callback); /* open the SCHIZO framework */ - if (PRTE_SUCCESS - != (rc = prte_mca_base_framework_open(&prte_schizo_base_framework, - PRTE_MCA_BASE_OPEN_DEFAULT))) { + rc = prte_mca_base_framework_open(&prte_schizo_base_framework, + PRTE_MCA_BASE_OPEN_DEFAULT); + if (PRTE_SUCCESS != rc) { PRTE_ERROR_LOG(rc); return rc; } @@ -437,7 +402,7 @@ int prun(int argc, char *argv[]) /* detect if we are running as a proxy and select the active * schizo module for this tool */ - schizo = prte_schizo.detect_proxy(personality); + schizo = prte_schizo_base_detect_proxy(personality); if (NULL == schizo) { prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, personality); return 1; @@ -446,44 +411,15 @@ int prun(int argc, char *argv[]) personality = schizo->name; } - /* setup the cmd line - this is specific to the proxy */ - prte_cmd_line = PRTE_NEW(prte_cmd_line_t); - if (PRTE_SUCCESS != (rc = schizo->define_cli(prte_cmd_line))) { - PRTE_ERROR_LOG(rc); - return rc; - } - /* add the tool-specific options */ - if (PRTE_SUCCESS != (rc = prte_cmd_line_add(prte_cmd_line, prte_tool_options))) { - PRTE_ERROR_LOG(rc); - return rc; - } - - /* handle deprecated options */ - if (PRTE_SUCCESS != (rc = schizo->parse_deprecated_cli(prte_cmd_line, &pargc, &pargv))) { - if (PRTE_OPERATION_SUCCEEDED == rc) { - /* the cmd line was restructured - show them the end result */ - param = prte_argv_join(pargv, ' '); - fprintf(stderr, "\n******* Corrected cmd line: %s\n\n\n", param); - free(param); - } else { - return rc; - } - } - - /* parse the result to get values - this will not include MCA params */ - if (PRTE_SUCCESS != (rc = prte_cmd_line_parse(prte_cmd_line, true, false, pargc, pargv))) { - if (PRTE_ERR_SILENT != rc) { - fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); - } - return rc; - } - - /* let the schizo components take a pass at it to get the MCA params - this - * will include whatever default/user-level param files each schizo component - * supports */ - if (PRTE_SUCCESS != (rc = schizo->parse_cli(pargc, 0, pargv, NULL))) { + /* parse the input argv to get values, including everyone's MCA params */ + PRTE_CONSTRUCT(&results, prte_cli_result_t); + rc = schizo->parse_cli(pargv, &results); + if (PRTE_SUCCESS != rc) { + PRTE_DESTRUCT(&results); if (PRTE_ERR_SILENT != rc) { fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); + } else { + rc = PRTE_SUCCESS; } return rc; } @@ -493,46 +429,14 @@ int prun(int argc, char *argv[]) * exit with a giant warning message */ if (0 == geteuid()) { - schizo->allow_run_as_root(prte_cmd_line); // will exit us if not allowed - } - - /* check command line sanity - ensure there aren't multiple instances of - * options where there should be only one */ - rc = schizo->check_sanity(prte_cmd_line); - if (PRTE_SUCCESS != rc) { - if (PRTE_ERR_SILENT != rc) { - fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); - param = prte_argv_join(pargv, ' '); - fprintf(stderr, "\n******* Cmd line: %s\n\n\n", param); - free(param); - } - return rc; - } - - if (prte_cmd_line_is_taken(prte_cmd_line, "verbose")) { - verbose = true; - } - - /* see if print version is requested. Do this before - * check for help so that --version --help works as - * one might expect. */ - if (prte_cmd_line_is_taken(prte_cmd_line, "version")) { - fprintf(stdout, "%s (%s) %s\n\nReport bugs to %s\n", prte_tool_basename, - "PMIx Reference RunTime Environment", PRTE_VERSION, PACKAGE_BUGREPORT); - exit(0); - } - - /* Check for help request */ - rc = schizo->check_help(prte_cmd_line, pargv); - if (PRTE_ERR_SILENT == rc) { - /* help was printed */ - exit(0); + schizo->allow_run_as_root(&results); // will exit us if not allowed } /** setup callbacks for signals we should forward */ PRTE_CONSTRUCT(&prte_ess_base_signals, prte_list_t); - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "forward-signals", 0, 0))) { - param = pval->value.data.string; + opt = prte_cmd_line_get_param(&results, "forward-signals"); + if (NULL != opt) { + param = opt->values[0]; } else { param = NULL; } @@ -546,10 +450,10 @@ int prun(int argc, char *argv[]) /* setup the job data global table */ prte_job_data = PRTE_NEW(prte_pointer_array_t); - if (PRTE_SUCCESS - != (ret = prte_pointer_array_init(prte_job_data, PRTE_GLOBAL_ARRAY_BLOCK_SIZE, + ret = prte_pointer_array_init(prte_job_data, PRTE_GLOBAL_ARRAY_BLOCK_SIZE, PRTE_GLOBAL_ARRAY_MAX_SIZE, - PRTE_GLOBAL_ARRAY_BLOCK_SIZE))) { + PRTE_GLOBAL_ARRAY_BLOCK_SIZE); + if (PRTE_SUCCESS != ret) { PRTE_ERROR_LOG(ret); return rc; } @@ -572,49 +476,50 @@ int prun(int argc, char *argv[]) } PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_TOOL_RANK, &rank, PMIX_PROC_RANK); - if (prte_cmd_line_is_taken(prte_cmd_line, "do-not-connect")) { + if (prte_cmd_line_is_taken(&results, "do-not-connect")) { PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_TOOL_DO_NOT_CONNECT, NULL, PMIX_BOOL); - } else if (prte_cmd_line_is_taken(prte_cmd_line, "system-server-first")) { + } else if (prte_cmd_line_is_taken(&results, "system-server-first")) { PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_CONNECT_SYSTEM_FIRST, NULL, PMIX_BOOL); - } else if (prte_cmd_line_is_taken(prte_cmd_line, "system-server-only")) { + } else if (prte_cmd_line_is_taken(&results, "system-server-only")) { PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_CONNECT_TO_SYSTEM, NULL, PMIX_BOOL); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "wait-to-connect", 0, 0)) - && 0 < pval->value.data.integer) { - ui32 = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "wait-to-connect"); + if (NULL != opt) { + ui32 = strtol(opt->values[0], NULL, 10); PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_CONNECT_RETRY_DELAY, &ui32, PMIX_UINT32); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "num-connect-retries", 0, 0)) - && 0 < pval->value.data.integer) { - ui32 = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "num-connect-retries"); + if (NULL != opt) { + ui32 = strtol(opt->values[0], NULL, 10); PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_CONNECT_MAX_RETRIES, &ui32, PMIX_UINT32); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "pid", 0, 0))) { + opt = prte_cmd_line_get_param(&results, "pid"); + if (NULL != opt) { /* see if it is an integer value */ char *leftover; leftover = NULL; - pid = strtol(pval->value.data.string, &leftover, 10); + pid = strtol(opt->values[0], &leftover, 10); if (NULL == leftover || 0 == strlen(leftover)) { /* it is an integer */ PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_SERVER_PIDINFO, &pid, PMIX_PID); - } else if (0 == strncasecmp(pval->value.data.string, "file", 4)) { + } else if (0 == strncasecmp(opt->values[0], "file", 4)) { FILE *fp; /* step over the file: prefix */ - param = strchr(pval->value.data.string, ':'); + param = strchr(opt->values[0], ':'); if (NULL == param) { /* malformed input */ prte_show_help("help-prun.txt", "bad-option-input", true, prte_tool_basename, - "--pid", pval->value.data.string, "file:path"); + "--pid", opt->values[0], "file:path"); return PRTE_ERR_BAD_PARAM; } ++param; fp = fopen(param, "r"); if (NULL == fp) { prte_show_help("help-prun.txt", "file-open-error", true, prte_tool_basename, - "--pid", pval->value.data.string, param); + "--pid", opt->values[0], param); return PRTE_ERR_BAD_PARAM; } rc = fscanf(fp, "%lu", (unsigned long *) &pid); @@ -622,7 +527,7 @@ int prun(int argc, char *argv[]) /* if we were unable to obtain the single conversion we * require, then error out */ prte_show_help("help-prun.txt", "bad-file", true, prte_tool_basename, - "--pid", pval->value.data.string, param); + "--pid", opt->values[0], param); fclose(fp); return PRTE_ERR_BAD_PARAM; } @@ -631,12 +536,13 @@ int prun(int argc, char *argv[]) } else { /* a string that's neither an integer nor starts with 'file:' */ prte_show_help("help-prun.txt", "bad-option-input", true, prte_tool_basename, "--pid", - pval->value.data.string, "file:path"); + opt->values[0], "file:path"); return PRTE_ERR_BAD_PARAM; } } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "namespace", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_SERVER_NSPACE, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "namespace"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_SERVER_NSPACE, opt->values[0], PMIX_STRING); } /* set our session directory to something hopefully unique so @@ -655,8 +561,9 @@ int prun(int argc, char *argv[]) PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_SERVER_TOOL_SUPPORT, NULL, PMIX_BOOL); /* if they specified the URI, then pass it along */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "dvm-uri", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_SERVER_URI, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "dvm-uri"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, tinfo, PMIX_SERVER_URI, opt->values[0], PMIX_STRING); } /* output all IOF */ @@ -713,133 +620,139 @@ int prun(int argc, char *argv[]) PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_PERSONALITY, personality, PMIX_STRING); /* get display options */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "display", 0, 0))) { - targv = prte_argv_split(pval->value.data.string, ','); - - for (int idx = 0; idx < prte_argv_count(targv); idx++) { - if (0 == strncasecmp(targv[idx], "allocation", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYALLOC", PMIX_STRING); - } - if (0 == strcasecmp(targv[idx], "map")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAY", PMIX_STRING); - } - if (0 == strncasecmp(targv[idx], "bind", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, ":REPORT", PMIX_STRING); - } - if (0 == strcasecmp(targv[idx], "map-devel")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYDEVEL", PMIX_STRING); - } - if (0 == strncasecmp(targv[idx], "topo", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYTOPO", PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "display"); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + targv = prte_argv_split(opt->values[n], ','); + + for (int idx = 0; idx < prte_argv_count(targv); idx++) { + if (0 == strncasecmp(targv[idx], "allocation", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYALLOC", PMIX_STRING); + } + if (0 == strcasecmp(targv[idx], "map")) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAY", PMIX_STRING); + } + if (0 == strncasecmp(targv[idx], "bind", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, ":REPORT", PMIX_STRING); + } + if (0 == strcasecmp(targv[idx], "map-devel")) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYDEVEL", PMIX_STRING); + } + if (0 == strncasecmp(targv[idx], "topo", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, ":DISPLAYTOPO", PMIX_STRING); + } } + prte_argv_free(targv); } - prte_argv_free(targv); } /* cannot have both files and directory set for output */ outdir = NULL; outfile = NULL; - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "output", 0, 0))) { - targv = prte_argv_split(pval->value.data.string, ','); - - for (int idx = 0; NULL != targv[idx]; idx++) { - /* check for qualifiers */ - cptr = strchr(targv[idx], ':'); - if (NULL != cptr) { - *cptr = '\0'; - ++cptr; - /* could be multiple qualifiers, so separate them */ - options = prte_argv_split(cptr, ','); - for (int m=0; NULL != options[m]; m++) { - if (0 == strcasecmp(options[m], "nocopy")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_ONLY, NULL, PMIX_BOOL); - } else if (0 == strcasecmp(options[m], "pattern")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_PATTERN, NULL, PMIX_BOOL); -#ifdef PMIX_IOF_OUTPUT_RAW - } else if (0 == strcasecmp(options[m], "raw")) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_RAW, NULL, PMIX_BOOL); -#endif + opt = prte_cmd_line_get_param(&results, "output"); + if (NULL != opt) { + for (n=0; NULL != opt->values[n]; n++) { + targv = prte_argv_split(opt->values[n], ','); + + for (int idx = 0; NULL != targv[idx]; idx++) { + /* check for qualifiers */ + cptr = strchr(targv[idx], ':'); + if (NULL != cptr) { + *cptr = '\0'; + ++cptr; + /* could be multiple qualifiers, so separate them */ + options = prte_argv_split(cptr, ','); + for (int m=0; NULL != options[m]; m++) { + if (0 == strcasecmp(options[m], "nocopy")) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_ONLY, NULL, PMIX_BOOL); + } else if (0 == strcasecmp(options[m], "pattern")) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_FILE_PATTERN, NULL, PMIX_BOOL); + #ifdef PMIX_IOF_OUTPUT_RAW + } else if (0 == strcasecmp(options[m], "raw")) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_RAW, NULL, PMIX_BOOL); + #endif + } } + prte_argv_free(options); } - prte_argv_free(options); - } - if (0 == strlen(targv[idx])) { - // only qualifiers were given - continue; - } - /* remove any '=' sign in the directive */ - if (NULL != (ptr = strchr(targv[idx], '='))) { - *ptr = '\0'; - ++ptr; - } - if (0 == strncasecmp(targv[idx], "tag", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TAG_OUTPUT, &flag, PMIX_BOOL); - } - if (0 == strncasecmp(targv[idx], "timestamp", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TIMESTAMP_OUTPUT, &flag, PMIX_BOOL); - } - if (0 == strncasecmp(targv[idx], "xml", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_XML_OUTPUT, NULL, PMIX_BOOL); - } - if (0 == strncasecmp(targv[idx], "merge-stderr-to-stdout", strlen(targv[idx]))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_MERGE_STDERR_STDOUT, &flag, PMIX_BOOL); - } - if (0 == strncasecmp(targv[idx], "directory", strlen(targv[idx]))) { - if (NULL != outfile) { - prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); - return PRTE_ERR_FATAL; + if (0 == strlen(targv[idx])) { + // only qualifiers were given + continue; } - if (NULL == ptr) { - prte_show_help("help-prte-rmaps-base.txt", - "missing-qualifier", true, - "output", "directory", "directory"); - return PRTE_ERR_FATAL; + /* remove any '=' sign in the directive */ + if (NULL != (ptr = strchr(targv[idx], '='))) { + *ptr = '\0'; + ++ptr; } - /* If the given filename isn't an absolute path, then - * convert it to one so the name will be relative to - * the directory where prun was given as that is what - * the user will have seen */ - if (!prte_path_is_absolute(ptr)) { - char cwd[PRTE_PATH_MAX]; - if (NULL == getcwd(cwd, sizeof(cwd))) { - PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); - goto DONE; - } - outdir = prte_os_path(false, cwd, ptr, NULL); - } else { - outdir = strdup(ptr); + if (0 == strncasecmp(targv[idx], "tag", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TAG_OUTPUT, &flag, PMIX_BOOL); } - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_DIRECTORY, outdir, PMIX_STRING); - } - if (0 == strncasecmp(targv[idx], "file", strlen(targv[idx]))) { - if (NULL != outdir) { - prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); - return PRTE_ERR_FATAL; + if (0 == strncasecmp(targv[idx], "timestamp", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_TIMESTAMP_OUTPUT, &flag, PMIX_BOOL); + } + if (0 == strncasecmp(targv[idx], "xml", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_XML_OUTPUT, NULL, PMIX_BOOL); } - if (NULL == ptr) { - prte_show_help("help-prte-rmaps-base.txt", - "missing-qualifier", true, - "output", "filename", "filename"); - return PRTE_ERR_FATAL; + if (0 == strncasecmp(targv[idx], "merge-stderr-to-stdout", strlen(targv[idx]))) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_MERGE_STDERR_STDOUT, &flag, PMIX_BOOL); } - /* If the given filename isn't an absolute path, then - * convert it to one so the name will be relative to - * the directory where prun was given as that is what - * the user will have seen */ - if (!prte_path_is_absolute(ptr)) { - char cwd[PRTE_PATH_MAX]; - if (NULL == getcwd(cwd, sizeof(cwd))) { - PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); - goto DONE; + if (0 == strncasecmp(targv[idx], "directory", strlen(targv[idx]))) { + if (NULL != outfile) { + prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); + return PRTE_ERR_FATAL; } - outfile = prte_os_path(false, cwd, ptr, NULL); - } else { - outfile = strdup(ptr); + if (NULL == ptr) { + prte_show_help("help-prte-rmaps-base.txt", + "missing-qualifier", true, + "output", "directory", "directory"); + return PRTE_ERR_FATAL; + } + /* If the given filename isn't an absolute path, then + * convert it to one so the name will be relative to + * the directory where prun was given as that is what + * the user will have seen */ + if (!prte_path_is_absolute(ptr)) { + char cwd[PRTE_PATH_MAX]; + if (NULL == getcwd(cwd, sizeof(cwd))) { + PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); + goto DONE; + } + outdir = prte_os_path(false, cwd, ptr, NULL); + } else { + outdir = strdup(ptr); + } + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_DIRECTORY, outdir, PMIX_STRING); + } + if (0 == strncasecmp(targv[idx], "file", strlen(targv[idx]))) { + if (NULL != outdir) { + prte_show_help("help-prted.txt", "both-file-and-dir-set", true, outfile, outdir); + return PRTE_ERR_FATAL; + } + if (NULL == ptr) { + prte_show_help("help-prte-rmaps-base.txt", + "missing-qualifier", true, + "output", "filename", "filename"); + return PRTE_ERR_FATAL; + } + /* If the given filename isn't an absolute path, then + * convert it to one so the name will be relative to + * the directory where prun was given as that is what + * the user will have seen */ + if (!prte_path_is_absolute(ptr)) { + char cwd[PRTE_PATH_MAX]; + if (NULL == getcwd(cwd, sizeof(cwd))) { + PRTE_UPDATE_EXIT_STATUS(PRTE_ERR_FATAL); + goto DONE; + } + outfile = prte_os_path(false, cwd, ptr, NULL); + } else { + outfile = strdup(ptr); + } + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_FILE, outfile, PMIX_STRING); } - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_IOF_OUTPUT_TO_FILE, outfile, PMIX_STRING); } + prte_argv_free(targv); } - prte_argv_free(targv); } if (NULL != outdir) { free(outdir); @@ -849,48 +762,52 @@ int prun(int argc, char *argv[]) } /* check what user wants us to do with stdin */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "stdin", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_STDIN_TGT, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "stdin"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_STDIN_TGT, opt->values[0], PMIX_STRING); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "map-by", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, pval->value.data.string, PMIX_STRING); - if (NULL != strcasestr(pval->value.data.string, "DONOTLAUNCH")) { + opt = prte_cmd_line_get_param(&results, "map-by"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_MAPBY, opt->values[0], PMIX_STRING); + if (NULL != strcasestr(opt->values[0], "DONOTLAUNCH")) { PMIX_INFO_LIST_ADD(ret, jinfo, "PRTE_JOB_DO_NOT_LAUNCH", NULL, PMIX_BOOL); } } /* if the user specified a ranking policy, then set it */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "rank-by", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_RANKBY, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "rank-by"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_RANKBY, opt->values[0], PMIX_STRING); } /* if the user specified a binding policy, then set it */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "bind-to", 0, 0))) { - PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "bind-to"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_BINDTO, opt->values[0], PMIX_STRING); } /* mark if recovery was enabled on the cmd line */ - if (prte_cmd_line_is_taken(prte_cmd_line, "enable-recovery")) { + if (prte_cmd_line_is_taken(&results, "enable-recovery")) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_JOB_RECOVERABLE, &flag, PMIX_BOOL); } /* record the max restarts */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "max-restarts", 0, 0)) - && 0 < pval->value.data.integer) { - ui32 = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "max-restarts"); + if (NULL != opt) { + ui32 = strtol(opt->values[0], NULL, 10); PRTE_LIST_FOREACH(app, &apps, prte_pmix_app_t) { PMIX_INFO_LIST_ADD(ret, app->info, PMIX_MAX_RESTARTS, &ui32, PMIX_UINT32); } } /* if continuous operation was specified */ - if (prte_cmd_line_is_taken(prte_cmd_line, "continuous")) { + if (prte_cmd_line_is_taken(&results, "continuous")) { /* mark this job as continuously operating */ PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_JOB_CONTINUOUS, &flag, PMIX_BOOL); } /* if stop-on-exec was specified */ - if (prte_cmd_line_is_taken(prte_cmd_line, "stop-on-exec")) { + if (prte_cmd_line_is_taken(&results, "stop-on-exec")) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_DEBUG_STOP_ON_EXEC, &flag, PMIX_BOOL); } @@ -898,8 +815,9 @@ int prun(int argc, char *argv[]) * as that is what MPICH used */ i = 0; - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "timeout", 0, 0))) { - i = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "timeout"); + if (NULL != opt) { + i = strtol(opt->values[0], NULL, 10); } else if (NULL != (param = getenv("MPIEXEC_TIMEOUT"))) { i = strtol(param, NULL, 10); } @@ -911,21 +829,22 @@ int prun(int argc, char *argv[]) #endif } - if (prte_cmd_line_is_taken(prte_cmd_line, "get-stack-traces")) { + if (prte_cmd_line_is_taken(&results, "get-stack-traces")) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_TIMEOUT_STACKTRACES, &flag, PMIX_BOOL); } - if (prte_cmd_line_is_taken(prte_cmd_line, "report-state-on-timeout")) { + if (prte_cmd_line_is_taken(&results, "report-state-on-timeout")) { PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_TIMEOUT_REPORT_STATE, &flag, PMIX_BOOL); } #ifdef PMIX_SPAWN_TIMEOUT - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "spawn-timeout", 0, 0))) { - i = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "spawn-timeout"); + if (NULL != opt) { + i = strtol(opt->values[0], NULL, 10); PMIX_INFO_LIST_ADD(ret, jinfo, PMIX_SPAWN_TIMEOUT, &i, PMIX_INT); } #endif /* give the schizo components a chance to add to the job info */ - prte_schizo.job_info(prte_cmd_line, jinfo); + schizo->job_info(&results, jinfo); /* pickup any relevant envars */ ninfo = 4; @@ -970,7 +889,7 @@ int prun(int argc, char *argv[]) /* they want to run an application, so let's parse * the cmd line to get it */ - if (PRTE_SUCCESS != (rc = prte_parse_locals(prte_cmd_line, &apps, pargc, pargv, NULL, NULL))) { + if (PRTE_SUCCESS != (rc = prte_parse_locals(schizo, &apps, pargv, NULL, NULL))) { PRTE_ERROR_LOG(rc); PRTE_LIST_DESTRUCT(&apps); goto DONE; @@ -1002,11 +921,6 @@ int prun(int argc, char *argv[]) PMIX_INFO_LIST_CONVERT(ret, app->info, &darray); papps[n].info = (pmix_info_t *) darray.array; papps[n].ninfo = darray.size; - /* pickup any relevant envars */ - rc = prte_schizo.parse_env(prte_cmd_line, environ, &papps[n].env, false); - if (PRTE_SUCCESS != rc) { - goto DONE; - } ++n; } PRTE_LIST_DESTRUCT(&apps); diff --git a/src/tools/pterm/help-pterm.txt b/src/tools/pterm/help-pterm.txt index 857f3936dc..a61f7b0141 100644 --- a/src/tools/pterm/help-pterm.txt +++ b/src/tools/pterm/help-pterm.txt @@ -13,6 +13,7 @@ # Copyright (c) 2007-2020 Cisco Systems, Inc. All rights reserved # Copyright (c) 2012 Oak Ridge National Labs. All rights reserved. # Copyright (c) 2017-2020 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -21,16 +22,13 @@ # # This is the US/English general help file for PRTE's pterm. # -[usage] -%s (%s) %s - -Usage: %s [OPTION]... -Terminate an instance of the PMIx Reference RTE (PRTE) - -%s +# +[no-args] +The %s command does not accept arguments other than those +specifically defined by the command. The following were +not recognized: -Report bugs to %s -[version] -%s (%s) %s + Args: %s -Report bugs to %s +Please see "%s --help" for a description of all accepted +command options. diff --git a/src/tools/pterm/pterm.c b/src/tools/pterm/pterm.c index 3478e3b021..80e55d281d 100644 --- a/src/tools/pterm/pterm.c +++ b/src/tools/pterm/pterm.c @@ -19,7 +19,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Geoffroy Vallee. All rights reserved. * Copyright (c) 2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * Copyright (c) 2021 Amazon.com, Inc. or its affiliates. All Rights * reserved. * $COPYRIGHT$ @@ -108,41 +108,27 @@ static prte_mutex_t prun_abort_inprogress_lock = PRTE_MUTEX_STATIC_INIT; static prte_event_base_t *myevbase = NULL; static bool proxyrun = false; static bool verbose = false; -static prte_cmd_line_t *prte_cmd_line = NULL; /* prun-specific options */ -static prte_cmd_line_init_t cmd_line_init[] = { - /* Various "obvious" generalized options */ - {'h', "help", 0, PRTE_CMD_LINE_TYPE_BOOL, "This help message", PRTE_CMD_LINE_OTYPE_GENERAL}, - {'V', "version", 0, PRTE_CMD_LINE_TYPE_BOOL, "Print version and exit", - PRTE_CMD_LINE_OTYPE_GENERAL}, - {'v', "verbose", 0, PRTE_CMD_LINE_TYPE_BOOL, "Be verbose", PRTE_CMD_LINE_OTYPE_GENERAL}, - - /* look first for a system server */ - {'\0', "system-server-first", 0, PRTE_CMD_LINE_TYPE_BOOL, - "First look for a system server and connect to it if found", PRTE_CMD_LINE_OTYPE_DVM}, - /* connect only to a system server */ - {'\0', "system-server-only", 0, PRTE_CMD_LINE_TYPE_BOOL, - "Connect only to a system-level server", PRTE_CMD_LINE_OTYPE_DVM}, - /* wait to connect */ - {'\0', "wait-to-connect", 0, PRTE_CMD_LINE_TYPE_INT, - "Delay specified number of seconds before trying to connect", PRTE_CMD_LINE_OTYPE_DVM}, - /* number of times to try to connect */ - {'\0', "num-connect-retries", 0, PRTE_CMD_LINE_TYPE_INT, - "Max number of times to try to connect", PRTE_CMD_LINE_OTYPE_DVM}, - /* provide a connection PID */ - {'\0', "pid", 1, PRTE_CMD_LINE_TYPE_STRING, - "PID of the daemon to which we should connect (int => PID or file: for file containing " - "the PID", - PRTE_CMD_LINE_OTYPE_DVM}, - /* uri of the dvm, or at least where to get it */ - {'\0', "dvm-uri", 1, PRTE_CMD_LINE_TYPE_STRING, - "Specify the URI of the DVM master, or the name of the file (specified as file:filename) that " - "contains that info", - PRTE_CMD_LINE_OTYPE_DVM}, - - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; +static struct option myoptions[] = { + /* basic options */ + PRTE_OPTION_SHORT_DEFINE("help", PRTE_ARG_OPTIONAL, 'h'), + PRTE_OPTION_SHORT_DEFINE("version", PRTE_ARG_NONE, 'V'), + PRTE_OPTION_SHORT_DEFINE("verbose", PRTE_ARG_NONE, 'v'), + + // DVM options + PRTE_OPTION_DEFINE("system-server-first", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("system-server-only", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE("wait-to-connect", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("num-connect-retries", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("pid", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("namespace", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE("dvm-uri", PRTE_ARG_REQD), + + PRTE_OPTION_END +}; + +static char *shorts = "hvVp"; static void abort_signal_callback(int signal); static void clean_abort(int fd, short flags, void *arg); @@ -161,7 +147,7 @@ static void infocb(pmix_status_t status, pmix_info_t *info, size_t ninfo, void * PRTE_ACQUIRE_OBJECT(lock); if (verbose) { - prte_output(0, "PRUN: INFOCB"); + prte_output(0, "PTERM: INFOCB"); } if (NULL != release_fn) { @@ -229,20 +215,23 @@ static void evhandler(size_t evhdlr_registration_id, pmix_status_t status, int main(int argc, char *argv[]) { - int rc = PRTE_ERR_FATAL; + int rc = PRTE_ERR_FATAL, i; prte_pmix_lock_t lock, rellock; pmix_info_t info, *iptr; pmix_status_t ret; bool flag; size_t ninfo; - prte_value_t *pval; uint32_t ui32; - char *param; + char *param, *ptr; pid_t pid; void *tinfo; pmix_data_array_t darray; char hostname[PRTE_PATH_MAX]; + char *personality; pmix_rank_t rank; + prte_cli_result_t results; + prte_cli_item_t *opt; + prte_schizo_base_module_t *schizo; /* init the globals */ PRTE_CONSTRUCT(&job_info, prte_list_t); @@ -262,51 +251,61 @@ int main(int argc, char *argv[]) prte_init_util(PRTE_PROC_MASTER); prte_tool_basename = prte_basename(argv[0]); + prte_tool_actual = "pterm"; gethostname(hostname, sizeof(hostname)); + PRTE_CONSTRUCT(&results, prte_cli_result_t); - /* setup our cmd line */ - prte_cmd_line = PRTE_NEW(prte_cmd_line_t); - if (PRTE_SUCCESS != (rc = prte_cmd_line_add(prte_cmd_line, cmd_line_init))) { + /* open the SCHIZO framework */ + rc = prte_mca_base_framework_open(&prte_schizo_base_framework, + PRTE_MCA_BASE_OPEN_DEFAULT); + if (PRTE_SUCCESS != rc) { PRTE_ERROR_LOG(rc); return rc; } - /* parse the result to get values - this will not include MCA params */ - if (PRTE_SUCCESS != (rc = prte_cmd_line_parse(prte_cmd_line, true, false, argc, argv))) { - if (PRTE_ERR_SILENT != rc) { - fprintf(stderr, "%s: command line error (%s)\n", argv[0], prte_strerror(rc)); - } + if (PRTE_SUCCESS != (rc = prte_schizo_base_select())) { PRTE_ERROR_LOG(rc); return rc; } - if (prte_cmd_line_is_taken(prte_cmd_line, "verbose")) { - verbose = true; + /* look for any personality specification */ + personality = NULL; + for (i = 0; NULL != argv[i]; i++) { + if (0 == strcmp(argv[i], "--personality")) { + personality = argv[i + 1]; + break; + } } - /* see if print version is requested. Do this before - * check for help so that --version --help works as - * one might expect. */ - if (prte_cmd_line_is_taken(prte_cmd_line, "version")) { - fprintf(stdout, "%s (%s) %s\n\nReport bugs to %s\n", prte_tool_basename, - "PMIx Reference RunTime Environment", PRTE_VERSION, PACKAGE_BUGREPORT); - exit(0); + /* detect if we are running as a proxy and select the active + * schizo module for this tool */ + schizo = prte_schizo_base_detect_proxy(personality); + if (NULL == schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, personality); + return 1; } - /* Check for help request */ - if (prte_cmd_line_is_taken(prte_cmd_line, "help")) { - char *str, *args = NULL; - args = prte_cmd_line_get_usage_msg(prte_cmd_line, false); - str = prte_show_help_string("help-pterm.txt", "usage", false, prte_tool_basename, "PRTE", - PRTE_VERSION, prte_tool_basename, args, PACKAGE_BUGREPORT); - if (NULL != str) { - printf("%s", str); - free(str); + rc = schizo->parse_cli(argv, &results); + if (PRTE_SUCCESS != rc) { + PRTE_DESTRUCT(&results); + if (PRTE_ERR_SILENT != rc) { + fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); + } else { + rc = PRTE_SUCCESS; } - free(args); + return rc; + } - /* If someone asks for help, that should be all we do */ - exit(0); + // we do NOT accept arguments other than our own + if (NULL != results.tail) { + param = prte_argv_join(results.tail, ' '); + ptr = prte_show_help_string("help-pterm.txt", "no-args", false, + prte_tool_basename, param, prte_tool_basename); + if (NULL != ptr) { + printf("%s", ptr); + free(ptr); + } + return -1; } /* setup options */ @@ -319,44 +318,45 @@ int main(int argc, char *argv[]) rank = 0; PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_TOOL_RANK, &rank, PMIX_PROC_RANK); - if (prte_cmd_line_is_taken(prte_cmd_line, "system-server-first")) { + if (prte_cmd_line_is_taken(&results, "system-server-first")) { PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_CONNECT_SYSTEM_FIRST, NULL, PMIX_BOOL); - } else if (prte_cmd_line_is_taken(prte_cmd_line, "system-server-only")) { + } else if (prte_cmd_line_is_taken(&results, "system-server-only")) { PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_CONNECT_TO_SYSTEM, NULL, PMIX_BOOL); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "wait-to-connect", 0, 0)) - && 0 < pval->value.data.integer) { - ui32 = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "wait-to-connect"); + if (NULL != opt) { + ui32 = strtol(opt->values[0], NULL, 10); PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_CONNECT_RETRY_DELAY, &ui32, PMIX_UINT32); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "num-connect-retries", 0, 0)) - && 0 < pval->value.data.integer) { - ui32 = pval->value.data.integer; + opt = prte_cmd_line_get_param(&results, "num-connect-retries"); + if (NULL != opt) { + ui32 = strtol(opt->values[0], NULL, 10); PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_CONNECT_MAX_RETRIES, &ui32, PMIX_UINT32); } - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "pid", 0, 0))) { + opt = prte_cmd_line_get_param(&results, "pid"); + if (NULL != opt) { /* see if it is an integer value */ char *leftover; leftover = NULL; - pid = strtol(pval->value.data.string, &leftover, 10); + pid = strtol(opt->values[0], &leftover, 10); if (NULL == leftover || 0 == strlen(leftover)) { /* it is an integer */ PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_SERVER_PIDINFO, &pid, PMIX_PID); - } else if (0 == strncasecmp(pval->value.data.string, "file", 4)) { + } else if (0 == strncasecmp(opt->values[0], "file", 4)) { FILE *fp; /* step over the file: prefix */ - param = strchr(pval->value.data.string, ':'); + param = strchr(opt->values[0], ':'); if (NULL == param) { /* malformed input */ prte_show_help("help-prun.txt", "bad-option-input", true, prte_tool_basename, - "--pid", pval->value.data.string, "file:path"); + "--pid", opt->values[0], "file:path"); return PRTE_ERR_BAD_PARAM; } ++param; fp = fopen(param, "r"); if (NULL == fp) { prte_show_help("help-prun.txt", "file-open-error", true, prte_tool_basename, - "--pid", pval->value.data.string, param); + "--pid", opt->values[0], param); return PRTE_ERR_BAD_PARAM; } rc = fscanf(fp, "%lu", (unsigned long *) &pid); @@ -364,7 +364,7 @@ int main(int argc, char *argv[]) /* if we were unable to obtain the single conversion we * require, then error out */ prte_show_help("help-prun.txt", "bad-file", true, prte_tool_basename, - "--pid", pval->value.data.string, param); + "--pid", opt->values[0], param); return PRTE_ERR_BAD_PARAM; } fclose(fp); @@ -373,8 +373,9 @@ int main(int argc, char *argv[]) } /* if they specified the URI, then pass it along */ - if (NULL != (pval = prte_cmd_line_get_param(prte_cmd_line, "dvm-uri", 0, 0))) { - PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_SERVER_URI, pval->value.data.string, PMIX_STRING); + opt = prte_cmd_line_get_param(&results, "dvm-uri"); + if (NULL != opt) { + PMIX_INFO_LIST_ADD(rc, tinfo, PMIX_SERVER_URI, opt->values[0], PMIX_STRING); } /* convert to array of info */ diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 5be1cb832f..d65ed1f46f 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -17,7 +17,7 @@ # Copyright (c) 2016 Research Organization for Information Science # and Technology (RIST). All rights reserved. # Copyright (c) 2016-2017 IBM Corporation. All rights reserved. -# Copyright (c) 2021 Nanook Consulting. All rights reserved. +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -28,9 +28,10 @@ SUBDIRS = keyval hostfile dist_prtedata_DATA = help-prte-util.txt \ - help-regex.txt \ - hostfile/help-hostfile.txt \ - dash_host/help-dash-host.txt + help-cli.txt \ + help-regex.txt \ + hostfile/help-hostfile.txt \ + dash_host/help-dash-host.txt AM_LFLAGS = -Pprte_show_help_yy LEX_OUTPUT_ROOT = lex.prte_show_help_yy diff --git a/src/util/argv.c b/src/util/argv.c index f4a97eebe2..223c71c968 100644 --- a/src/util/argv.c +++ b/src/util/argv.c @@ -16,7 +16,7 @@ * * Copyright (c) 2019-2020 Intel, Inc. All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -388,6 +388,76 @@ char *prte_argv_join_range(char **argv, size_t start, size_t end, int delimiter) return str; } +/* + * Join all the elements of an argv array into a single + * newly-allocated string, stripping any leading/trailing + * quotes from each element + */ +char *prte_argv_join_strip(char **argv, int delimiter) +{ + char **p; + char *pp; + char *str; + size_t str_len = 0; + size_t i; + + /* Bozo case */ + + if (NULL == argv || NULL == argv[0]) { + return strdup(""); + } + + /* Find the total string length in argv including delimiters. The + last delimiter is replaced by the NULL character. */ + + for (p = argv; *p; ++p) { + str_len += strlen(*p) + 1; + } + + /* Allocate the string. */ + + if (NULL == (str = (char *) malloc(str_len))) + return NULL; + + /* Loop filling in the string. */ + + memset(str, 0, str_len); + p = argv; + pp = *p; + if ('\"' == *pp) { + // string starts with a quote - skip it + pp++; + } + + for (i = 0; i < str_len; ++i) { + if ('\0' == *pp) { + /* End of a string, fill in a delimiter and go to the next + string. */ + ++p; + pp = *p; + if (NULL == pp) { + // we are done - no delimiter at end + break; + } + if ('\"' == str[i-1]) { + // string ended in a quote - backup one + --i; + } + str[i] = (char) delimiter; + if ('\"' == *pp) { + // string starts with a quote - skip it + pp++; + } + } else { + str[i] = *pp++; + } + } + + /* All done */ + + return str; +} + /* * Return the number of bytes consumed by an argv array. */ @@ -438,6 +508,56 @@ char **prte_argv_copy(char **argv) return dupv; } +/* + * Copy a NULL-terminated argv array, stripping any leading/trailing + * quotes from each element + */ +char **prte_argv_copy_strip(char **argv) +{ + char **dupv = NULL; + int dupc = 0; + int n; + char *start; + bool mod; + size_t len; + + if (NULL == argv) { + return NULL; + } + + /* create an "empty" list, so that we return something valid if we + were passed a valid list with no contained elements */ + dupv = (char **) malloc(sizeof(char *)); + dupv[0] = NULL; + + for (n=0; NULL != argv[n]; n++) { + mod = false; + start = argv[n]; + if ('\"' == argv[n][0]) { + ++start; + } + len = strlen(argv[n]); + if ('\"' == argv[n][len-1]) { + argv[n][len-1] = '\0'; + mod = true; + } + if (PRTE_SUCCESS != prte_argv_append(&dupc, &dupv, start)) { + prte_argv_free(dupv); + if (mod) { + argv[n][len-1] = '\"'; + } + return NULL; + } + if (mod) { + argv[n][len-1] = '\"'; + } + } + + /* All done */ + + return dupv; +} + int prte_argv_delete(int *argc, char ***argv, int start, int num_to_delete) { int i; diff --git a/src/util/argv.h b/src/util/argv.h index 9e28721259..aba2742496 100644 --- a/src/util/argv.h +++ b/src/util/argv.h @@ -16,7 +16,7 @@ * * Copyright (c) 2019-2020 Intel, Inc. All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -228,6 +228,9 @@ PRTE_EXPORT size_t prte_argv_len(char **argv); PRTE_EXPORT char ** prte_argv_copy(char **argv) __prte_attribute_malloc__ __prte_attribute_warn_unused_result__; +PRTE_EXPORT +char **prte_argv_copy_strip(char **argv) __prte_attribute_malloc__ __prte_attribute_warn_unused_result__; + /** * Delete one or more tokens from the middle of an argv. * diff --git a/src/util/cmd_line.c b/src/util/cmd_line.c index 3da63f85f5..e68254f7cd 100644 --- a/src/util/cmd_line.c +++ b/src/util/cmd_line.c @@ -17,7 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2016-2020 Intel, Inc. All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -27,1109 +27,367 @@ #include "prte_config.h" -#include -#include -#include - #include "src/class/prte_list.h" #include "src/class/prte_object.h" -#include "src/threads/mutex.h" +#include "src/runtime/prte_globals.h" #include "src/util/argv.h" #include "src/util/cmd_line.h" #include "src/util/output.h" -#include "src/util/prte_environ.h" - -#include "constants.h" -#include "src/mca/base/prte_mca_base_var.h" - -/* - * Some usage message constants - * - * Max width for param listings before the description will be listed - * on the next line - */ -#define PARAM_WIDTH 37 -/* - * Max length of any line in the usage message - */ -#define MAX_WIDTH 110 - -static void option_constructor(prte_cmd_line_option_t *cmd); -static void option_destructor(prte_cmd_line_option_t *cmd); - -PRTE_CLASS_INSTANCE(prte_cmd_line_option_t, prte_list_item_t, option_constructor, - option_destructor); - -static void param_constructor(prte_cmd_line_param_t *cmd); -static void param_destructor(prte_cmd_line_param_t *cmd); -PRTE_CLASS_INSTANCE(prte_cmd_line_param_t, prte_list_item_t, param_constructor, param_destructor); +#include "src/util/show_help.h" -/* - * Instantiate the prte_cmd_line_t class - */ -static void cmd_line_constructor(prte_cmd_line_t *cmd); -static void cmd_line_destructor(prte_cmd_line_t *cmd); -PRTE_CLASS_INSTANCE(prte_cmd_line_t, prte_object_t, cmd_line_constructor, cmd_line_destructor); - -/* - * Private variables - */ -static char special_empty_token[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '\0'}; - -/* - * Private functions - */ -static int make_opt(prte_cmd_line_t *cmd, prte_cmd_line_init_t *e); -static void free_parse_results(prte_cmd_line_t *cmd); -static prte_value_t *set_dest(prte_cmd_line_option_t *option, char *sval); -static void fill(const prte_cmd_line_option_t *a, char result[3][BUFSIZ]); -static int qsort_callback(const void *a, const void *b); -static char *build_parsable(prte_cmd_line_option_t *option); - -/* - * Create an entire command line handle from a table - */ -int prte_cmd_line_create(prte_cmd_line_t *cmd, prte_cmd_line_init_t *table) +// Local functions +static int endswith(const char *str, const char *suffix) { - int ret = PRTE_SUCCESS; + size_t lenstr, lensuffix; - /* Check bozo case */ - - if (NULL == cmd) { + if (NULL == str || NULL == suffix) { return PRTE_ERR_BAD_PARAM; } - PRTE_CONSTRUCT(cmd, prte_cmd_line_t); - if (NULL != table) { - ret = prte_cmd_line_add(cmd, table); + lenstr = strlen(str); + lensuffix = strlen(suffix); + if (lensuffix > lenstr) { + return PRTE_ERR_BAD_PARAM; } - return ret; -} - -/* Add a table to an existing cmd line object */ -int prte_cmd_line_add(prte_cmd_line_t *cmd, prte_cmd_line_init_t *table) -{ - int i, ret; - - /* Ensure we got a table */ - if (NULL == table) { + if (0 == strncmp(str + lenstr - lensuffix, suffix, lensuffix)) { return PRTE_SUCCESS; } + return PRTE_ERR_BAD_PARAM; +} - /* Loop through the table */ - - for (i = 0;; ++i) { - /* Is this the end? */ - if ('\0' == table[i].ocl_cmd_short_name && NULL == table[i].ocl_cmd_long_name) { - break; - } - - /* Nope -- it's an entry. Process it. */ - ret = make_opt(cmd, &table[i]); - if (PRTE_SUCCESS != ret) { - return ret; +static void check_store(const char *name, const char *option, + prte_cli_result_t *results) +{ + prte_cli_item_t *opt; + + PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { + if (0 == strcmp(opt->key, name)) { + /* if the name is NULL, then this is just setting + * a boolean value - the presence of the option in + * the results is considered "true" */ + if (NULL != option) { + prte_argv_append_nosize(&opt->values, option); + } + return; } } - return PRTE_SUCCESS; -} -/* - * Append a command line entry to the previously constructed command line - */ -int prte_cmd_line_make_opt_mca(prte_cmd_line_t *cmd, prte_cmd_line_init_t entry) -{ - /* Ensure we got an entry */ - if ('\0' == entry.ocl_cmd_short_name && NULL == entry.ocl_cmd_long_name) { - return PRTE_SUCCESS; + // get here if this is new option + opt = PRTE_NEW(prte_cli_item_t); + opt->key = strdup(name); + prte_list_append(&results->instances, &opt->super); + /* if the name is NULL, then this is just setting + * a boolean value - the presence of the option in + * the results is considered "true" */ + if (NULL != option) { + prte_argv_append_nosize(&opt->values, option); } - - return make_opt(cmd, &entry); + return; } -/* - * Create a command line option, --long-name and/or -s (short name). - */ -int prte_cmd_line_make_opt3(prte_cmd_line_t *cmd, char short_name, const char *long_name, - int num_params, const char *desc, prte_cmd_line_otype_t otype) +int prte_cmd_line_parse(char **pargv, char *shorts, + struct option myoptions[], + prte_cmd_line_store_fn_t storefn, + prte_cli_result_t *results, + char *helpfile) { - prte_cmd_line_init_t e; - - e.ocl_cmd_short_name = short_name; - e.ocl_cmd_long_name = long_name; - - e.ocl_num_params = num_params; - - e.ocl_variable_type = PRTE_CMD_LINE_TYPE_NULL; - - e.ocl_description = desc; - e.ocl_otype = otype; - - return make_opt(cmd, &e); -} - -/* - * Parse a command line according to a pre-built PRTE command line - * handle. - */ -int prte_cmd_line_parse(prte_cmd_line_t *cmd, bool ignore_unknown, bool ignore_unknown_option, - int argc, char **argv) -{ - int i, j, orig; - prte_cmd_line_option_t *option; - prte_cmd_line_param_t *param; - bool is_unknown_option; - bool is_unknown_token; - bool is_option; - bool have_help_option = false; - bool printed_error = false; - bool help_without_arg = false; - prte_cmd_line_init_t e; - prte_value_t *val; - - /* Bozo check */ - - if (0 == argc || NULL == argv) { - return PRTE_SUCCESS; - } - - /* Thread serialization */ - - prte_mutex_lock(&cmd->lcl_mutex); - - /* Free any parsed results that are already on this handle */ - - free_parse_results(cmd); - - /* Analyze each token */ - - cmd->lcl_argc = argc; - cmd->lcl_argv = prte_argv_copy(argv); - - /* Check up front: do we have a --help option? */ - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_long_name = "help"; - option = prte_cmd_line_find_option(cmd, &e); - if (NULL != option) { - have_help_option = true; + int option_index = 0; /* getopt_long stores the option index here. */ + int n, opt, argc, rc; + bool found; + char *ptr, *str, c, **argv; + prte_cmd_line_store_fn_t mystore; + + /* the getopt_long parser reorders the input argv array, so + * we have to protect it here - remove all leading/trailing + * quotes to ensure we are looking at simple options/values */ + argv = prte_argv_copy_strip(pargv); + argc = prte_argv_count(argv); + // assign a default store_fn if one isn't provided + if (NULL == storefn) { + mystore = check_store; + } else { + mystore = storefn; } - /* Now traverse the easy-to-parse sequence of tokens. Note that - incrementing i must happen elsewhere; it can't be the third - clause in the "if" statement. */ - - param = NULL; - option = NULL; - for (i = 1; i < cmd->lcl_argc;) { - is_unknown_option = false; - is_unknown_token = false; - is_option = false; - - /* Are we done? i.e., did we find the special "--" token? If - so, copy everything beyond it into the tail (i.e., don't - bother copying the "--" into the tail). */ - - if (0 == strcmp(cmd->lcl_argv[i], "--")) { - ++i; - while (i < cmd->lcl_argc) { - if (0 != strcmp(cmd->lcl_argv[i], "&") || '>' != cmd->lcl_argv[i][0] - || '<' != cmd->lcl_argv[i][0]) { - prte_argv_append(&cmd->lcl_tail_argc, &cmd->lcl_tail_argv, cmd->lcl_argv[i]); - } - ++i; - } + /* reset the parser - must be done each time we use it + * to avoid hysteresis */ + optind = 0; + opterr = 0; + optopt = 0; + optarg = NULL; + // run the parser + while (1) { + opt = getopt_long(argc, argv, shorts, myoptions, &option_index); + if (-1 == opt) { break; } - - /* is it the ampersand or an output redirection? if so, - * then that should be at the end of the cmd line - either - * way, we ignore it */ - else if (0 == strcmp(cmd->lcl_argv[i], "&") || '>' == cmd->lcl_argv[i][0] - || '<' == cmd->lcl_argv[i][0]) { - ++i; - continue; - } - - /* If it's not an option, then this is an error. Note that - this is different than an unrecognized token; an - unrecognized option is *always* an error. */ - - else if ('-' != cmd->lcl_argv[i][0]) { - is_unknown_token = true; - } - - /* Nope, this is supposedly an option. Is it a long name? */ - - else if (0 == strncmp(cmd->lcl_argv[i], "--", 2)) { - is_option = true; - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_long_name = &cmd->lcl_argv[i][2]; - option = prte_cmd_line_find_option(cmd, &e); - } - - /* Is it the special-cased "-np" name? */ - else if (0 == strcmp(cmd->lcl_argv[i], "-np")) { - is_option = true; - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_long_name = &cmd->lcl_argv[i][1]; - option = prte_cmd_line_find_option(cmd, &e); - } - - /* It could be a short name. Is it? */ - - else { - if (2 < strlen(cmd->lcl_argv[i])) { - is_unknown_option = true; - } else { - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - e.ocl_cmd_short_name = cmd->lcl_argv[i][1]; - option = prte_cmd_line_find_option(cmd, &e); - - /* If we didn't find it, then it is an unknown option */ - if (NULL == option) { - is_unknown_option = true; - } else { - is_option = true; + switch (opt) { + case 0: + /* we allow someone to specify an option followed by + * the "help" directive - thus requesting detailed help + * on that specific option */ + if (NULL != optarg) { + if (0 == strcmp(optarg, "--help") || 0 == strcmp(optarg, "-help") || + 0 == strcmp(optarg, "help") || 0 == strcmp(optarg, "h") || + 0 == strcmp(optarg, "-h")) { + str = prte_show_help_string(helpfile, myoptions[option_index].name, false); + if (NULL != str) { + printf("%s", str); + free(str); + } + prte_argv_free(argv); + return PRTE_ERR_SILENT; + } } - } - } - - /* If we figured out above that this is an option, handle it */ - - if (is_option) { - if (NULL == option) { - is_unknown_option = true; - } else { - is_unknown_option = false; - orig = i; - ++i; - - /* Pull down the following parameters that belong to - this option. If we run out of parameters, then - print an error and return. */ - - param = PRTE_NEW(prte_cmd_line_param_t); - if (NULL == param) { - prte_mutex_unlock(&cmd->lcl_mutex); - return PRTE_ERR_OUT_OF_RESOURCE; + /* if this is an MCA param of some type, store it */ + if (0 == endswith(myoptions[option_index].name, "mca")) { + /* format mca params as param:value - the optind value + * will have been incremented since the MCA param options + * require an argument */ + prte_asprintf(&str, "%s=%s", argv[optind-1], argv[optind]); + mystore(myoptions[option_index].name, str, results); + free(str); + ++optind; + break; } - param->clp_arg = cmd->lcl_argv[i]; - param->clp_option = option; - - /* If we have any parameters to this option, pull down - tokens starting one beyond the token that we just - recognized */ - - for (j = 0; j < option->clo_num_params; ++j, ++i) { - /* If we run out of parameters, error, unless its a help request - which has no arguments */ - if (i >= cmd->lcl_argc) { - /* If this is a help or version request, can have no arguments */ - if (NULL != option->clo_long_name - && (0 == strcmp(option->clo_long_name, "help") - || 0 == strcmp(option->clo_long_name, "version"))) { - help_without_arg = true; - continue; + /* store actual option */ + mystore(myoptions[option_index].name, optarg, results); + break; + case 'h': + /* the "help" option can optionally take an argument. Since + * the argument _is_ optional, getopt will _NOT_ increment + * optind, so argv[optind] is the potential argument */ + if (NULL == optarg && + NULL != argv[optind]) { + /* strip any leading dashes */ + ptr = argv[optind]; + while ('-' == *ptr) { + ++ptr; + } + // check for standard options + if (0 == strcmp(ptr, "version") || 0 == strcmp(ptr, "V")) { + str = prte_show_help_string("help-cli.txt", "version", false); + if (NULL != str) { + printf("%s", str); + free(str); } - fprintf(stderr, - "%s: Error: option \"%s\" did not " - "have enough parameters (%d)\n", - cmd->lcl_argv[0], cmd->lcl_argv[orig], option->clo_num_params); - if (have_help_option) { - fprintf(stderr, "Type '%s --help' for usage.\n", cmd->lcl_argv[0]); + prte_argv_free(argv); + return PRTE_ERR_SILENT; + } + if (0 == strcmp(ptr, "verbose") || 0 == strcmp(ptr, "v")) { + str = prte_show_help_string("help-cli.txt", "verbose", false); + if (NULL != str) { + printf("%s", str); + free(str); } - PRTE_RELEASE(param); - printed_error = true; - goto error; - } else { - if (0 == strcmp(cmd->lcl_argv[i], special_empty_token)) { - fprintf(stderr, - "%s: Error: option \"%s\" did not " - "have enough parameters (%d)\n", - cmd->lcl_argv[0], cmd->lcl_argv[orig], option->clo_num_params); - if (have_help_option) { - fprintf(stderr, "Type '%s --help' for usage.\n", cmd->lcl_argv[0]); - } - PRTE_RELEASE(param); - printed_error = true; - goto error; + prte_argv_free(argv); + return PRTE_ERR_SILENT; + } + if (0 == strcmp(ptr, "help") || 0 == strcmp(ptr, "h")) { + // they requested help on the "help" option itself + str = prte_show_help_string("help-cli.txt", "help", false, + prte_tool_basename, prte_tool_basename, + prte_tool_basename, prte_tool_basename, + prte_tool_basename, prte_tool_basename, + prte_tool_basename, prte_tool_basename); + if (NULL != str) { + printf("%s", str); + free(str); } - - /* Otherwise, save this parameter */ - - else { - /* Save in the argv on the param entry */ - if (NULL == (val = set_dest(option, cmd->lcl_argv[i]))) { - PRTE_RELEASE(param); - printed_error = true; - goto error; + prte_argv_free(argv); + return PRTE_ERR_SILENT; + } + /* see if the argument is one of our options */ + found = false; + if (NULL != ptr) { + for (n=0; NULL != myoptions[n].name; n++) { + if (0 == strcmp(ptr, myoptions[n].name)) { + // it is, so they requested help on this option + str = prte_show_help_string(helpfile, ptr, false); + if (NULL != str) { + printf("%s", str); + free(str); + } + prte_argv_free(argv); + return PRTE_ERR_SILENT; } - prte_list_append(¶m->clp_values, &val->super); } } - } - - /* If there are no options to this command or it is - a help request with no argument, check if it is a - boolean option and set it accordingly. */ - - if (PRTE_CMD_LINE_TYPE_BOOL == option->clo_type - && (0 == option->clo_num_params || help_without_arg)) { - val = PRTE_NEW(prte_value_t); - val->value.type = PMIX_BOOL; - if (0 == strncasecmp(cmd->lcl_argv[orig], "t", 1) - || 0 != atoi(cmd->lcl_argv[orig])) { - val->value.data.flag = true; - } else { - val->value.data.flag = false; + if (!found) { + // let the user know we don't recognize that option + str = prte_show_help_string("help-cli.txt", "unknown-option", true, + ptr, prte_tool_basename); + if (NULL != str) { + printf("%s", str); + free(str); + } + prte_argv_free(argv); + return PRTE_ERR_SILENT; } - prte_list_append(¶m->clp_values, &val->super); - } - - /* If we succeeded in all that, save the param to the - list on the prte_cmd_line_t handle */ - - if (NULL != param) { - prte_list_append(&cmd->lcl_params, ¶m->super); - } - } - } - - /* If we figured out above that this was an unknown option, - handle it. Copy everything (including the current token) - into the tail. If we're not ignoring unknowns, then print - an error and return. */ - if (is_unknown_option || is_unknown_token) { - if (!ignore_unknown || (is_unknown_option && !ignore_unknown_option)) { - fprintf(stderr, "%s: Error: unknown option \"%s\"\n", cmd->lcl_argv[0], - cmd->lcl_argv[i]); - printed_error = true; - if (have_help_option) { - fprintf(stderr, "Type '%s --help' for usage.\n", cmd->lcl_argv[0]); - } - } - error: - while (i < cmd->lcl_argc) { - prte_argv_append(&cmd->lcl_tail_argc, &cmd->lcl_tail_argv, cmd->lcl_argv[i]); - ++i; - } - - /* Because i has advanced, we'll fall out of the loop */ - } - } - - /* Thread serialization */ - - prte_mutex_unlock(&cmd->lcl_mutex); - - /* All done */ - if (printed_error) { - return PRTE_ERR_SILENT; - } - - return PRTE_SUCCESS; -} - -static char *headers[] = {"/***** General Options *****/", - "/***** Debug Options *****/", - "/***** Output Options *****/", - "/***** Input Options *****/", - "/***** Mapping Options *****/", - "/***** Ranking Options *****/", - "/***** Binding Options *****/", - "/***** Developer Options *****/", - "/***** Launch Options *****/", - "/***** Fault Tolerance Options *****/", - "/***** DVM-Specific Options *****/", - "/***** Currently Unsupported *****/"}; - -/* - * Return a consolidated "usage" message for a PRTE command line handle. - */ -char *prte_cmd_line_get_usage_msg(prte_cmd_line_t *cmd, bool parseable) -{ - size_t i, len; - size_t j; - char **argv; - char *ret, temp[MAX_WIDTH * 2 - 1], line[MAX_WIDTH * 2]; - char *start, *desc, *ptr; - prte_list_item_t *item; - prte_cmd_line_option_t *option, **sorted; - prte_cmd_line_otype_t otype; - bool found; - - /* Thread serialization */ - - prte_mutex_lock(&cmd->lcl_mutex); - - /* Make an argv of all the usage strings */ - argv = NULL; - ret = NULL; - - for (otype = PRTE_CMD_LINE_OTYPE_GENERAL; otype < PRTE_CMD_LINE_OTYPE_NULL; otype++) { - found = false; - /* First, take the original list and sort it */ - sorted = (prte_cmd_line_option_t **) malloc(sizeof(prte_cmd_line_option_t *) - * prte_list_get_size(&cmd->lcl_options[otype])); - if (NULL == sorted) { - prte_mutex_unlock(&cmd->lcl_mutex); - prte_argv_free(argv); - return NULL; - } - i = 0; - PRTE_LIST_FOREACH(item, &cmd->lcl_options[otype], prte_list_item_t) - { - sorted[i++] = (prte_cmd_line_option_t *) item; - } - qsort(sorted, i, sizeof(prte_cmd_line_option_t *), qsort_callback); - - /* add all non-NULL descriptions */ - for (j = 0; j < prte_list_get_size(&cmd->lcl_options[otype]); j++) { - option = sorted[j]; - if (parseable) { - if (!found) { - /* we have at least one instance, so add the header for this type */ - prte_argv_append_nosize(&argv, headers[otype]); - prte_argv_append_nosize(&argv, " "); - found = true; - } - ret = build_parsable(option); - prte_argv_append_nosize(&argv, ret); - free(ret); - ret = NULL; - } else if (NULL != option->clo_description) { - bool filled = false; - - if (!found) { - /* we have at least one instance, so add the header for this type */ - prte_argv_append_nosize(&argv, headers[otype]); - prte_argv_append_nosize(&argv, " "); - found = true; - } - /* Build up the output line */ - memset(line, 0, sizeof(line)); - if ('\0' != option->clo_short_name) { - line[0] = '-'; - line[1] = option->clo_short_name; - filled = true; - } else { - line[0] = ' '; - line[1] = ' '; - } - if (NULL != option->clo_long_name) { - if (filled) { - strncat(line, "|", sizeof(line) - 1); - } else { - strncat(line, " ", sizeof(line) - 1); + } else if (NULL == optarg) { + // high-level help request + str = prte_show_help_string(helpfile, "usage", false, + prte_tool_basename, "PRRTE", + PRTE_PROXY_VERSION_STRING, + prte_tool_basename, + PRTE_PROXY_BUGREPORT); + if (NULL != str) { + printf("%s", str); + free(str); } - strncat(line, "--", sizeof(line) - 1); - strncat(line, option->clo_long_name, sizeof(line) - 1); - } - strncat(line, " ", sizeof(line) - 1); - for (i = 0; (int) i < option->clo_num_params; ++i) { - len = sizeof(temp); - snprintf(temp, len, " ", (int) i); - strncat(line, temp, sizeof(line) - 1); - } - if (option->clo_num_params > 0) { - strncat(line, " ", sizeof(line) - 1); - } - - /* If we're less than param width, then start adding the - description to this line. Otherwise, finish this line - and start adding the description on the next line. */ - - if (strlen(line) > PARAM_WIDTH) { - prte_argv_append_nosize(&argv, line); - - /* Now reset the line to be all blanks up to - PARAM_WIDTH so that we can start adding the - description */ - - memset(line, ' ', PARAM_WIDTH); - line[PARAM_WIDTH] = '\0'; - } else { - - /* Add enough blanks to the end of the line so that we - can start adding the description */ - - for (i = strlen(line); i < PARAM_WIDTH; ++i) { - line[i] = ' '; + prte_argv_free(argv); + return PRTE_ERR_SILENT; + } else { // unrecognized option + str = prte_show_help_string("help-cli.txt", "unrecognized-option", true, + prte_tool_basename, optarg); + if (NULL != str) { + printf("%s", str); + free(str); } - line[i] = '\0'; - } - - /* Loop over adding the description to the array, breaking - the string at most at MAX_WIDTH characters. We need a - modifyable description (for simplicity), so strdup the - clo_description (because it's likely a compiler - constant, and may barf if we write temporary \0's in - the middle). */ - - desc = strdup(option->clo_description); - if (NULL == desc) { - free(sorted); prte_argv_free(argv); - prte_mutex_unlock(&cmd->lcl_mutex); - return strdup(""); + return PRTE_ERR_SILENT; } - start = desc; - len = strlen(desc); - do { - - /* Trim off leading whitespace */ - - while (isspace(*start) && start < desc + len) { - ++start; - } - if (start >= desc + len) { - break; - } - - /* Last line */ - - if (strlen(start) < (MAX_WIDTH - PARAM_WIDTH)) { - strncat(line, start, sizeof(line) - 1); - prte_argv_append_nosize(&argv, line); - break; - } - - /* We have more than 1 line's worth left -- find this - line's worth and add it to the array. Then reset - and loop around to get the next line's worth. */ - - for (ptr = start + (MAX_WIDTH - PARAM_WIDTH); ptr > start; --ptr) { - if (isspace(*ptr)) { - *ptr = '\0'; - strncat(line, start, sizeof(line) - 1); - prte_argv_append_nosize(&argv, line); - - start = ptr + 1; - memset(line, ' ', PARAM_WIDTH); - line[PARAM_WIDTH] = '\0'; - break; + break; + case 'V': + str = prte_show_help_string(helpfile, "version", false, + prte_tool_basename, "PRRTE", + PRTE_PROXY_VERSION_STRING, + PRTE_PROXY_BUGREPORT); + if (NULL != str) { + printf("%s", str); + free(str); + } + // if they ask for the version, that is all we do + prte_argv_free(argv); + return PRTE_ERR_SILENT; + default: + /* this could be one of the short options other than 'h' or 'V', so + * we have to check */ + found = false; + for (n=0; '\0' != shorts[n]; n++) { + int ascii = shorts[n]; + bool optional=false, reqd=false, noarg=false; + if (opt == ascii) { + /* found it - now search for matching option. The + * getopt fn will have already incremented optind + * to point at the next argument. + * If this short option required an argument, then + * it will be indicated by a ':' in the next shorts + * spot and the argument will be in optarg. + * + * If the short option takes an optional argument, then + * it will be indicated by two ':' after the option - in + * this case optarg will contain the argument if given. + * Note that the proper form of the optional argument + * option is "-zfoo", where 'z' is the option and "foo" + * is the argument. Putting a space between the option + * and the argument is forbidden and results in reporting + * of 'z' without an argument - usually followed by + * incorrectly marking "foo" as the beginning of the + * command "tail" */ + if (':' == shorts[n+1]) { + // could be an optional arg + if (':' == shorts[n+2]) { + /* in this case, the argument (if given) must be immediately + * attached to the option */ + ptr = argv[optind-1]; + ptr += 2; // step over the '-' and option + } else { + ptr = optarg; + } + } else { + ptr = NULL; } - } - - /* If we got all the way back to the beginning of the - string, then go forward looking for a whitespace - and break there. */ - - if (ptr == start) { - for (ptr = start + (MAX_WIDTH - PARAM_WIDTH); ptr < start + len; ++ptr) { - if (isspace(*ptr)) { - *ptr = '\0'; - - strncat(line, start, sizeof(line) - 1); - prte_argv_append_nosize(&argv, line); - - start = ptr + 1; - memset(line, ' ', PARAM_WIDTH); - line[PARAM_WIDTH] = '\0'; + for (n=0; NULL != myoptions[n].name; n++) { + if (ascii == myoptions[n].val) { + if (NULL != ptr) { + /* we allow someone to specify an option followed by + * the "help" directive - thus requesting detailed help + * on that specific option */ + if (0 == strcmp(ptr, "--help") || 0 == strcmp(ptr, "-h") || + 0 == strcmp(ptr, "help") || 0 == strcmp(ptr, "h")) { + str = prte_show_help_string(helpfile, myoptions[n].name, true); + if (NULL != str) { + printf("%s", str); + free(str); + } + prte_argv_free(argv); + return PRTE_ERR_SILENT; + } + } + /* store actual option */ + if (PRTE_ARG_NONE == myoptions[n].has_arg) { + ptr = NULL; + } + mystore(myoptions[n].name, ptr, results); + found = true; break; } } - - /* If we reached the end of the string with no - whitespace, then just add it on and be done */ - - if (ptr >= start + len) { - strncat(line, start, sizeof(line) - 1); - prte_argv_append_nosize(&argv, line); - start = desc + len + 1; + if (found) { + break; } - } - } while (start < desc + len); - free(desc); - } - } - free(sorted); - if (found) { - /* add a spacer */ - prte_argv_append_nosize(&argv, " "); - prte_argv_append_nosize(&argv, " "); - prte_argv_append_nosize(&argv, " "); - } - } - if (NULL != argv) { - ret = prte_argv_join(argv, '\n'); - prte_argv_free(argv); - } else { - ret = strdup(""); - } - - /* Thread serialization */ - prte_mutex_unlock(&cmd->lcl_mutex); - - /* All done */ - return ret; -} - -/* - * Test if a given option was taken on the parsed command line. - */ -bool prte_cmd_line_is_taken(prte_cmd_line_t *cmd, const char *opt) -{ - return (prte_cmd_line_get_ninsts(cmd, opt) > 0); -} - -/* - * Return the number of instances of an option found during parsing. - */ -int prte_cmd_line_get_ninsts(prte_cmd_line_t *cmd, const char *opt) -{ - int ret; - prte_cmd_line_param_t *param; - prte_cmd_line_option_t *option; - prte_cmd_line_init_t e; - - /* Thread serialization */ - - prte_mutex_lock(&cmd->lcl_mutex); - - /* Find the corresponding option. If we find it, look through all - the parsed params and see if we have any matches. */ - - ret = 0; - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - if (1 < strlen(opt)) { - e.ocl_cmd_long_name = opt; - } else { - e.ocl_cmd_short_name = opt[0]; - } - option = prte_cmd_line_find_option(cmd, &e); - if (NULL != option) { - PRTE_LIST_FOREACH(param, &cmd->lcl_params, prte_cmd_line_param_t) - { - if (param->clp_option == option) { - ++ret; - } - } - } - - /* Thread serialization */ - - prte_mutex_unlock(&cmd->lcl_mutex); - - /* All done */ - - return ret; -} - -/* - * Return a specific parameter for a specific instance of a option - * from the parsed command line. - */ -prte_value_t *prte_cmd_line_get_param(prte_cmd_line_t *cmd, const char *opt, int inst, int idx) -{ - int num_found, ninst; - prte_cmd_line_param_t *param; - prte_cmd_line_option_t *option; - prte_cmd_line_init_t e; - prte_value_t *val; - - /* Thread serialization */ - prte_mutex_lock(&cmd->lcl_mutex); - - /* Find the corresponding option. If we find it, look through all - the parsed params and see if we have any matches. */ - - memset(&e, 0, sizeof(prte_cmd_line_init_t)); - if (1 < strlen(opt)) { - e.ocl_cmd_long_name = opt; - } else { - e.ocl_cmd_short_name = opt[0]; - } - option = prte_cmd_line_find_option(cmd, &e); - if (NULL != option) { - ninst = 0; - /* scan thru the found params */ - PRTE_LIST_FOREACH(param, &cmd->lcl_params, prte_cmd_line_param_t) - { - if (param->clp_option == option) { - if (ninst == inst) { - /* scan thru the found values for this option */ - num_found = 0; - PRTE_LIST_FOREACH(val, ¶m->clp_values, prte_value_t) - { - if (num_found == idx) { - prte_mutex_unlock(&cmd->lcl_mutex); - return val; + str = prte_show_help_string("help-cli.txt", "short-no-long", true, + prte_tool_basename, argv[optind-1]); + if (NULL != str) { + printf("%s", str); + free(str); } - ++num_found; + prte_argv_free(argv); + return PRTE_ERR_SILENT; } } - ++ninst; - } + if (found) { + break; + } + str = prte_show_help_string("help-cli.txt", "unregistered-option", true, + prte_tool_basename, argv[optind-1], prte_tool_basename); + if (NULL != str) { + printf("%s", str); + free(str); + } + prte_argv_free(argv); + return PRTE_ERR_SILENT; } } - - /* Thread serialization */ - prte_mutex_unlock(&cmd->lcl_mutex); - - /* All done */ - return NULL; -} - -/* - * Return the entire "tail" of unprocessed argv from a PRTE command - * line handle. - */ -int prte_cmd_line_get_tail(prte_cmd_line_t *cmd, int *tailc, char ***tailv) -{ - if (NULL != cmd) { - prte_mutex_lock(&cmd->lcl_mutex); - *tailc = cmd->lcl_tail_argc; - *tailv = prte_argv_copy(cmd->lcl_tail_argv); - prte_mutex_unlock(&cmd->lcl_mutex); - return PRTE_SUCCESS; - } else { - return PRTE_ERROR; - } -} - -/************************************************************************** - * Static functions - **************************************************************************/ - -static void option_constructor(prte_cmd_line_option_t *o) -{ - o->clo_short_name = '\0'; - o->clo_long_name = NULL; - o->clo_num_params = 0; - o->clo_description = NULL; - - o->clo_type = PRTE_CMD_LINE_TYPE_NULL; - o->clo_otype = PRTE_CMD_LINE_OTYPE_NULL; -} - -static void option_destructor(prte_cmd_line_option_t *o) -{ - if (NULL != o->clo_long_name) { - free(o->clo_long_name); - } - if (NULL != o->clo_description) { - free(o->clo_description); + if (optind < argc) { + results->tail = prte_argv_copy(&argv[optind]); } -} - -static void param_constructor(prte_cmd_line_param_t *p) -{ - p->clp_arg = NULL; - p->clp_option = NULL; - PRTE_CONSTRUCT(&p->clp_values, prte_list_t); -} - -static void param_destructor(prte_cmd_line_param_t *p) -{ - PRTE_LIST_DESTRUCT(&p->clp_values); -} - -static void cmd_line_constructor(prte_cmd_line_t *cmd) -{ - int i; - - /* Initialize the mutex. Since we're creating (and therefore the - only thread that has this instance), there's no need to lock it - right now. */ - - PRTE_CONSTRUCT(&cmd->lcl_mutex, prte_recursive_mutex_t); - - /* Initialize the lists */ - for (i = 0; i < PRTE_CMD_OPTIONS_MAX; i++) { - PRTE_CONSTRUCT(&cmd->lcl_options[i], prte_list_t); - } - PRTE_CONSTRUCT(&cmd->lcl_params, prte_list_t); - - /* Initialize the argc/argv pairs */ - - cmd->lcl_argc = 0; - cmd->lcl_argv = NULL; - cmd->lcl_tail_argc = 0; - cmd->lcl_tail_argv = NULL; -} - -static void cmd_line_destructor(prte_cmd_line_t *cmd) -{ - int i; - - /* Free the contents of the options list (do not free the list - itself; it was not allocated from the heap) */ - for (i = 0; i < PRTE_CMD_OPTIONS_MAX; i++) { - PRTE_LIST_DESTRUCT(&cmd->lcl_options[i]); - } - - /* Free any parsed results - destructs the list object */ - free_parse_results(cmd); - PRTE_DESTRUCT(&cmd->lcl_params); - - /* Destroy the mutex */ - PRTE_DESTRUCT(&cmd->lcl_mutex); -} - -static int make_opt(prte_cmd_line_t *cmd, prte_cmd_line_init_t *e) -{ - prte_cmd_line_option_t *option; - - /* Bozo checks */ - - if (NULL == cmd) { - return PRTE_ERR_BAD_PARAM; - } else if ('\0' == e->ocl_cmd_short_name && NULL == e->ocl_cmd_long_name) { - return PRTE_ERR_BAD_PARAM; - } else if (e->ocl_num_params < 0) { - return PRTE_ERR_BAD_PARAM; - } - - /* see if the option already exists */ - if (NULL != prte_cmd_line_find_option(cmd, e)) { - prte_output(0, "Duplicate cmd line entry %c:%s", - ('\0' == e->ocl_cmd_short_name) ? ' ' : e->ocl_cmd_short_name, - (NULL == e->ocl_cmd_long_name) ? "NULL" : e->ocl_cmd_long_name); - return PRTE_ERR_BAD_PARAM; - } - - /* Allocate and fill an option item */ - option = PRTE_NEW(prte_cmd_line_option_t); - if (NULL == option) { - return PRTE_ERR_OUT_OF_RESOURCE; - } - - option->clo_short_name = e->ocl_cmd_short_name; - if (NULL != e->ocl_cmd_long_name) { - option->clo_long_name = strdup(e->ocl_cmd_long_name); - } - option->clo_num_params = e->ocl_num_params; - if (NULL != e->ocl_description) { - option->clo_description = strdup(e->ocl_description); - } - - option->clo_type = e->ocl_variable_type; - option->clo_otype = e->ocl_otype; - - /* Append the item, serializing thread access */ - - prte_mutex_lock(&cmd->lcl_mutex); - prte_list_append(&cmd->lcl_options[option->clo_otype], &option->super); - prte_mutex_unlock(&cmd->lcl_mutex); - - /* All done */ - + prte_argv_free(argv); return PRTE_SUCCESS; } -static void free_parse_results(prte_cmd_line_t *cmd) -{ - /* Free the contents of the params list (do not free the list - itself; it was not allocated from the heap) */ - PRTE_LIST_DESTRUCT(&cmd->lcl_params); - PRTE_CONSTRUCT(&cmd->lcl_params, prte_list_t); - - /* Free the argv's */ - if (NULL != cmd->lcl_argv) { - prte_argv_free(cmd->lcl_argv); - } - cmd->lcl_argv = NULL; - cmd->lcl_argc = 0; - - if (NULL != cmd->lcl_tail_argv) { - prte_argv_free(cmd->lcl_tail_argv); - } - cmd->lcl_tail_argv = NULL; - cmd->lcl_tail_argc = 0; -} - -prte_cmd_line_option_t *prte_cmd_line_find_option(prte_cmd_line_t *cmd, prte_cmd_line_init_t *e) -{ - int i; - prte_cmd_line_option_t *option; - - /* Iterate through the list of options hanging off the - * prte_cmd_line_t and see if we find a match in single-char - * or long names */ - for (i = 0; i < PRTE_CMD_OPTIONS_MAX; i++) { - PRTE_LIST_FOREACH(option, &cmd->lcl_options[i], prte_cmd_line_option_t) - { - if ((NULL != option->clo_long_name && NULL != e->ocl_cmd_long_name - && 0 == strcmp(e->ocl_cmd_long_name, option->clo_long_name)) - || ('\0' != e->ocl_cmd_short_name - && e->ocl_cmd_short_name == option->clo_short_name)) { - return option; - } - } - } - - /* Not found */ - - return NULL; -} - -static prte_value_t *set_dest(prte_cmd_line_option_t *option, char *sval) +static void icon(prte_cli_item_t *p) { - size_t i; - prte_value_t *val; - - /* Set variable */ - switch (option->clo_type) { - case PRTE_CMD_LINE_TYPE_STRING: - val = PRTE_NEW(prte_value_t); - val->value.type = PMIX_STRING; - /* check for quotes and remove them */ - if ('\"' == sval[0] && '\"' == sval[strlen(sval) - 1]) { - val->value.data.string = strdup(&sval[1]); - val->value.data.string[strlen(val->value.data.string) - 1] = '\0'; - } else { - val->value.data.string = strdup(sval); - } - return val; - - case PRTE_CMD_LINE_TYPE_INT: - /* check to see that the value given to us truly is an int */ - for (i = 0; i < strlen(sval); i++) { - if (!isdigit(sval[i]) && '-' != sval[i]) { - /* show help isn't going to be available yet, so just - * print the msg - */ - fprintf(stderr, "------------------------------------------------------------------" - "----------\n"); - fprintf(stderr, "PRTE has detected that a parameter given to a command line\n"); - fprintf(stderr, "option does not match the expected format:\n\n"); - if (NULL != option->clo_long_name) { - fprintf(stderr, " Option: %s\n", option->clo_long_name); - } else if ('\0' != option->clo_short_name) { - fprintf(stderr, " Option: %c\n", option->clo_short_name); - } else { - fprintf(stderr, " Option: \n"); - } - fprintf(stderr, " Param: %s\n\n", sval); - fprintf(stderr, "This is frequently caused by omitting to provide the parameter\n"); - fprintf(stderr, "to an option that requires one. Please check the command line and " - "try again.\n"); - fprintf(stderr, "------------------------------------------------------------------" - "----------\n"); - return NULL; - } - } - val = PRTE_NEW(prte_value_t); - val->value.type = PMIX_INT; - val->value.data.integer = strtol(sval, NULL, 10); - return val; - - case PRTE_CMD_LINE_TYPE_SIZE_T: - /* check to see that the value given to us truly is a size_t */ - for (i = 0; i < strlen(sval); i++) { - if (!isdigit(sval[i]) && '-' != sval[i]) { - /* show help isn't going to be available yet, so just - * print the msg - */ - fprintf(stderr, "------------------------------------------------------------------" - "----------\n"); - fprintf(stderr, "PRTE has detected that a parameter given to a command line\n"); - fprintf(stderr, "option does not match the expected format:\n\n"); - if (NULL != option->clo_long_name) { - fprintf(stderr, " Option: %s\n", option->clo_long_name); - } else if ('\0' != option->clo_short_name) { - fprintf(stderr, " Option: %c\n", option->clo_short_name); - } else { - fprintf(stderr, " Option: \n"); - } - fprintf(stderr, " Param: %s\n\n", sval); - fprintf(stderr, "This is frequently caused by omitting to provide the parameter\n"); - fprintf(stderr, "to an option that requires one. Please check the command line and " - "try again.\n"); - fprintf(stderr, "------------------------------------------------------------------" - "----------\n"); - return NULL; - } - } - val = PRTE_NEW(prte_value_t); - val->value.type = PMIX_SIZE; - val->value.data.integer = strtol(sval, NULL, 10); - return val; - - case PRTE_CMD_LINE_TYPE_BOOL: - val = PRTE_NEW(prte_value_t); - val->value.type = PMIX_BOOL; - if (0 == strncasecmp(sval, "t", 1) || 0 != atoi(sval)) { - val->value.data.flag = true; - } else { - val->value.data.flag = false; - } - return val; - - default: - return NULL; - } + p->key = NULL; + p->values = NULL; } - -/* - * Helper function to qsort_callback - */ -static void fill(const prte_cmd_line_option_t *a, char result[3][BUFSIZ]) +static void ides(prte_cli_item_t *p) { - int i = 0; - - result[0][0] = '\0'; - result[1][0] = '\0'; - result[2][0] = '\0'; - - if ('\0' != a->clo_short_name) { - snprintf(&result[i][0], BUFSIZ, "%c", a->clo_short_name); - ++i; + if (NULL != p->key) { + free(p->key); } - if (NULL != a->clo_long_name) { - snprintf(&result[i][0], BUFSIZ, "%s", a->clo_long_name); - ++i; + if (NULL != p->values) { + prte_argv_free(p->values); } } +PRTE_CLASS_INSTANCE(prte_cli_item_t, + prte_list_item_t, + icon, ides); -static int qsort_callback(const void *aa, const void *bb) +static void ocon(prte_cli_result_t *p) { - int ret, i; - char str1[3][BUFSIZ], str2[3][BUFSIZ]; - const prte_cmd_line_option_t *a = *((const prte_cmd_line_option_t **) aa); - const prte_cmd_line_option_t *b = *((const prte_cmd_line_option_t **) bb); - - /* Icky comparison of command line options. There are multiple - forms of each command line option, so we first have to check - which forms each option has. Compare, in order: short name, - single-dash name, long name. */ - - fill(a, str1); - fill(b, str2); - - for (i = 0; i < 3; ++i) { - if (0 != (ret = strcasecmp(str1[i], str2[i]))) { - return ret; - } - } - - /* Shrug -- they must be equal */ - - return 0; + PRTE_CONSTRUCT(&p->instances, prte_list_t); + p->tail = NULL; } - -/* - * Helper function to build a parsable string for the help - * output. - */ -static char *build_parsable(prte_cmd_line_option_t *option) +static void odes(prte_cli_result_t *p) { - char *line; - int length; - - length = snprintf(NULL, 0, "%c:%s:%d:%s\n", option->clo_short_name, option->clo_long_name, - option->clo_num_params, option->clo_description); - - line = (char *) malloc(length * sizeof(char)); - - if ('\0' == option->clo_short_name) { - snprintf(line, length, "0:%s:%d:%s\n", option->clo_long_name, option->clo_num_params, - option->clo_description); - } else { - snprintf(line, length, "%c:%s:%d:%s\n", option->clo_short_name, option->clo_long_name, - option->clo_num_params, option->clo_description); + PRTE_LIST_DESTRUCT(&p->instances); + if (NULL != p->tail) { + prte_argv_free(p->tail); } - - return line; } +PRTE_CLASS_INSTANCE(prte_cli_result_t, + prte_object_t, + ocon, odes); diff --git a/src/util/cmd_line.h b/src/util/cmd_line.h index 7541d2dec6..a8b8fc890b 100644 --- a/src/util/cmd_line.h +++ b/src/util/cmd_line.h @@ -15,7 +15,7 @@ * Copyright (c) 2016-2017 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -23,569 +23,313 @@ * $HEADER$ */ -/** - * @file - * - * General command line parsing facility for use throughout PRTE. - * - * This scheme is inspired by the GNU getopt package. Command line - * options are registered. Each option can have up to three different - * matching tokens: a "short" name, a "single dash" name, and a "long" - * name. Each option can also take 0 or more arguments. Finally, - * each option can be repeated on the command line an arbitrary number - * of times. - * - * The "short" name can only be a single letter, and will be found - * after a single dash (e.g., "-a"). Multiple "short" names can be - * combined into a single command line argument (e.g., "-abc" can be - * equivalent to "-a -b -c"). - * - * The "single dash" name is a multi-character name that only - * requires a single dash. This only exists to provide backwards - * compatibility for some well-known command line options in prior - * MPI implementations (e.g., "mpirun -np 3"). It should be used - * sparingly. - * - * The "long" name is a multi-character name that is found after a - * pair of dashes. For example, "--some-option-name". - * - * A command line option is a combination of 1 or more of a short - * name, single dash name, and a long name. Any of the names may be - * used on the command line; they are treated as synonyms. For - * example, say the following was used in for an executable named - * "foo": - * - * \code - * prte_cmd_line_make_opt3(cmd, 'a', NULL, 'add', 1, "Add a user"); - * \endcode - * - * In this case, the following command lines are exactly equivalent: - * - * \verbatim - * shell$ foo -a jsmith - * shell$ foo --add jsmith - * \endverbatim - * - * Note that this interface can also track multiple invocations of the - * same option. For example, the following is both legal and able to - * be retrieved through this interface: - * - * \verbatim - * shell$ foo -a jsmith --add bjones - * \endverbatim - * - * The caller to this interface creates a command line handle - * (prte_cmd_line_t) with PRTE_NEW() and then uses it to register the - * desired parameters via prte_cmd_line_make_opt3(). Once all the - * parameters have been registered, the user invokes - * prte_cmd_line_parse() with the command line handle and the argv/argc - * pair to be parsed (typically the arguments from main()). The parser - * will examine the argv and find registered options and parameters. - * It will stop parsing when it runs into an recognized string token or - * the special "--" token. - * - * After the parse has occurred, various accessor functions can be - * used to determine which options were selected, what parameters were - * passed to them, etc.: - * - * - prte_cmd_line_get_usage_msg() returns a string suitable for "help" - * kinds of messages. - * - prte_cmd_line_is_taken() returns a true or false indicating - * whether a given command line option was found on the command - * line. - * - prte_cmd_line_get_argc() returns the number of tokens parsed on - * the handle. - * - prte_cmd_line_get_argv() returns any particular string from the - * original argv. - * - prte_cmd_line_get_ninsts() returns the number of times a - * particular option was found on a command line. - * - prte_cmd_line_get_param() returns the Nth parameter in the Mth - * instance of a given parameter. - * - prte_cmd_line_get_tail() returns an array of tokens not parsed - * (i.e., if the parser ran into "--" or an unrecognized token). - * - * Note that a shortcut to creating a large number of options exists - * -- one can make a table of prte_cmd_line_init_t instances and the - * table to prte_cmd_line_create(). This creates an prte_cmd_line_t - * handle that is pre-seeded with all the options from the table - * without the need to repeatedly invoke prte_cmd_line_make_opt3() (or - * equivalent). This prte_cmd_line_t instance is just like any other; - * it is still possible to add more options via - * prte_cmd_line_make_opt3(), etc. - */ - #ifndef PRTE_CMD_LINE_H #define PRTE_CMD_LINE_H #include "prte_config.h" +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + #include "src/class/prte_list.h" #include "src/class/prte_object.h" -#include "src/pmix/pmix-internal.h" -#include "src/threads/mutex.h" - -#define PRTE_CMD_OPTIONS_MAX 15 +#include "src/util/argv.h" BEGIN_C_DECLS -/** - * Data types supported by the parser - */ -typedef enum prte_cmd_line_type_t { - PRTE_CMD_LINE_TYPE_NULL, - PRTE_CMD_LINE_TYPE_STRING, - PRTE_CMD_LINE_TYPE_INT, - PRTE_CMD_LINE_TYPE_SIZE_T, - PRTE_CMD_LINE_TYPE_BOOL, - - PRTE_CMD_LINE_TYPE_MAX -} prte_cmd_line_type_t; - -/** - * Command line option type, for use in - * --help output. - */ -typedef enum prte_cmd_line_otype_t { - PRTE_CMD_LINE_OTYPE_GENERAL = 0, - PRTE_CMD_LINE_OTYPE_DEBUG, - PRTE_CMD_LINE_OTYPE_OUTPUT, - PRTE_CMD_LINE_OTYPE_INPUT, - PRTE_CMD_LINE_OTYPE_MAPPING, - PRTE_CMD_LINE_OTYPE_RANKING, - PRTE_CMD_LINE_OTYPE_BINDING, - PRTE_CMD_LINE_OTYPE_DEVEL, - PRTE_CMD_LINE_OTYPE_LAUNCH, - PRTE_CMD_LINE_OTYPE_FT, - PRTE_CMD_LINE_OTYPE_DVM, - PRTE_CMD_LINE_OTYPE_UNSUPPORTED, - PRTE_CMD_LINE_OTYPE_NULL -} prte_cmd_line_otype_t; - -/** - * Main top-level handle. This interface should not be used by users! - */ -typedef struct prte_cmd_line_t { - /** Make this an OBJ handle */ - prte_object_t super; - - /** Thread safety */ - prte_recursive_mutex_t lcl_mutex; - - /** List of prte_cmd_line_option_t's (defined internally) */ - prte_list_t lcl_options[PRTE_CMD_OPTIONS_MAX]; - - /** Duplicate of argc from opal_cmd_line_parse() */ - int lcl_argc; - /** Duplicate of argv from opal_cmd_line_parse() */ - char **lcl_argv; - - /** Parsed output; list of ompi_cmd_line_param_t's (defined internally) */ - prte_list_t lcl_params; - - /** List of tail (unprocessed) arguments */ - int lcl_tail_argc; - /** List of tail (unprocessed) arguments */ - char **lcl_tail_argv; -} prte_cmd_line_t; -PRTE_EXPORT PRTE_CLASS_DECLARATION(prte_cmd_line_t); - -/* - * Description of a command line option - */ -typedef struct prte_cmd_line_option_t { +typedef struct { prte_list_item_t super; + char *key; + char **values; +} prte_cli_item_t; +PRTE_CLASS_DECLARATION(prte_cli_item_t); - char clo_short_name; - char *clo_long_name; - - int clo_num_params; - char *clo_description; - - prte_cmd_line_type_t clo_type; - prte_cmd_line_otype_t clo_otype; - -} prte_cmd_line_option_t; -PRTE_EXPORT PRTE_CLASS_DECLARATION(prte_cmd_line_option_t); - -/* - * An option that was used in the argv that was parsed - */ -typedef struct prte_cmd_line_param_t { - prte_list_item_t super; - - /* Note that clp_arg points to storage "owned" by someone else; it - has the original option string by reference, not by value. - Hence, it should not be free()'ed. */ - - char *clp_arg; - - /* Pointer to the existing option. This is also by reference; it - should not be free()ed. */ - - prte_cmd_line_option_t *clp_option; - - /* This is a list of all the parameters of this option. - It is owned by this parameter, and should be freed when this - param_t is freed. */ - - prte_list_t clp_values; -} prte_cmd_line_param_t; -PRTE_EXPORT PRTE_CLASS_DECLARATION(prte_cmd_line_param_t); - -/** - * Datatype used to construct a command line handle; see - * prte_cmd_line_create(). - */ -typedef struct prte_cmd_line_init_t { - - /** "Short" name (i.e., "-X", where "X" is a single letter) */ - char ocl_cmd_short_name; - - /** Long name (i.e., "--foo"). */ - const char *ocl_cmd_long_name; - - /** Number of parameters that this option takes */ - int ocl_num_params; - - /** datatype of any provided parameter. */ - prte_cmd_line_type_t ocl_variable_type; - - /** Description of the command line option, to be used with - prte_cmd_line_get_usage_msg(). */ - const char *ocl_description; - - /** Category for --help output */ - prte_cmd_line_otype_t ocl_otype; -} prte_cmd_line_init_t; - -/** - * Top-level command line handle. - * - * This handle is used for accessing all command line functionality - * (i.e., all prte_cmd_line*() functions). Multiple handles can be - * created and simultaneously processed; each handle is independant - * from others. - * - * The prte_cmd_line_t handles are [simplistically] thread safe; - * processing is guaranteed to be mutually exclusive if multiple - * threads invoke functions on the same handle at the same time -- - * access will be serialized in an unspecified order. - * - * Once finished, handles should be released with PRTE_RELEASE(). The - * destructor for prte_cmd_line_t handles will free all memory - * associated with the handle. - */ - -/** - * Make a command line handle from a table of initializers. - * - * @param cmd PRTE command line handle. - * @param table Table of prte_cmd_line_init_t instances for all - * the options to be included in the resulting command line - * handler. - * - * @retval PRTE_SUCCESS Upon success. - * - * This function takes a table of prte_cmd_line_init_t instances - * to pre-seed an PRTE command line handle. The last instance in - * the table must have '\0' for the short name and NULL for the - * single-dash and long names. The handle is expected to have - * been PRTE_NEW'ed or PRTE_CONSTRUCT'ed already. - * - * Upon return, the command line handle is just like any other. A - * sample using this syntax: - * - * \code - * prte_cmd_line_init_t cmd_line_init[] = { - * { 'h', "help", 0, - * PRTE_CMD_LINE_TYPE_BOOL, - * "This help message" }, - * - * { '\0', "wd", 1, - * PRTE_CMD_LINE_TYPE_STRING, - * "Set the working directory of the started processes" }, - * - * { '\0', NULL, 0, - * PRTE_CMD_LINE_TYPE_NULL, NULL } - * }; - * \endcode - */ -PRTE_EXPORT int prte_cmd_line_create(prte_cmd_line_t *cmd, prte_cmd_line_init_t *table); - -/* Add a table of prte_cmd_line_init_t instances - * to an existing PRTE command line handle. - * - * Multiple calls to prte_cmd_line_add are permitted - each - * subsequent call will simply append new options to the existing - * handle. Note that any duplicates will return an error. - */ -PRTE_EXPORT int prte_cmd_line_add(prte_cmd_line_t *cmd, prte_cmd_line_init_t *table); - -/** - * Create a command line option. - * - * @param cmd PRTE command line handle. - * @param entry Command line entry to add to the command line. - * - * @retval PRTE_SUCCESS Upon success. - * - */ -PRTE_EXPORT int prte_cmd_line_make_opt_mca(prte_cmd_line_t *cmd, prte_cmd_line_init_t entry); - -/** - * Create a command line option. - * - * @param cmd PRTE command line handle. - * @param short_name "Short" name of the command line option. - * @param long_name "Long" name of the command line option. - * @param num_params How many parameters this option takes. - * @param dest Short string description of this option. - * - * @retval PRTE_ERR_OUT_OF_RESOURCE If out of memory. - * @retval PRTE_ERR_BAD_PARAM If bad parameters passed. - * @retval PRTE_SUCCESS Upon success. - * - * Adds a command line option to the list of options that an PRTE - * command line handle will accept. The short_name may take the - * special value '\0' to not have a short name. Likewise, the - * long_name may take the special value NULL to not have - * long name. However, one of the - * two must have a name. - * - * num_params indicates how many parameters this option takes. It - * must be greater than or equal to 0. - * - * Finally, desc is a short string description of this option. It is - * used to generate the output from prte_cmd_line_get_usage_msg(). - * - */ -PRTE_EXPORT int prte_cmd_line_make_opt3(prte_cmd_line_t *cmd, char short_name, - const char *long_name, int num_params, const char *desc, - prte_cmd_line_otype_t otype); - -/** - * Parse a command line according to a pre-built PRTE command line - * handle. - * - * @param cmd PRTE command line handle. - * @param ignore_unknown Whether to print an error message upon - * finding an unknown token or not - * @param ignore_unknown_option Whether to print an error message upon - * finding an unknown option or not - * @param argc Length of the argv array. - * @param argv Array of strings from the command line. - * - * @retval PRTE_SUCCESS Upon success. - * @retval PRTE_ERR_SILENT If an error message was printed. This - * value will only be returned if the command line was not - * successfully parsed. - * - * Parse a series of command line tokens according to the option - * descriptions from a PRTE command line handle. The PRTE command line - * handle can then be queried to see what options were used, what - * their parameters were, etc. - * - * If an unknown token is found in the command line (i.e., a token - * that is not a parameter or a registered option), the parsing will - * stop (see below). If ignore_unknown is false, an error message - * is displayed. If ignore_unknown is true, the error message is - * not displayed. - * - * Error messages are always displayed regardless of the value - * of ignore_unknown (to stderr, and PRTE_ERR_SILENT is - * returned) if: - * - * 1. A token was encountered that required N parameters, but verbosity level +#define PRTE_CLI_PARSEABLE "parseable" // none +#define PRTE_CLI_PARSABLE "parsable" // none +#define PRTE_CLI_PERSONALITY "personality" // required + +// MCA parameter options +#define PRTE_CLI_PRTEMCA "prtemca" // requires TWO +#define PRTE_CLI_PMIXMCA "pmixmca" // requires TWO +#define PRTE_CLI_TUNE "tune" // required + +// DVM options +#define PRTE_CLI_NO_READY_MSG "no-ready-msg" // none +#define PRTE_CLI_DAEMONIZE "daemonize" // none +#define PRTE_CLI_SYSTEM_SERVER "system-server" // none +#define PRTE_CLI_SET_SID "set-sid" // none +#define PRTE_CLI_REPORT_PID "report-pid" // required +#define PRTE_CLI_REPORT_URI "report-uri" // required +#define PRTE_CLI_TEST_SUICIDE "test-suicide" // none +#define PRTE_CLI_DEFAULT_HOSTFILE "default-hostfile" // required +#define PRTE_CLI_SINGLETON "singleton" // required +#define PRTE_CLI_KEEPALIVE "keepalive" // required +#define PRTE_CLI_LAUNCH_AGENT "launch-agent" // required +#define PRTE_CLI_MAX_VM_SIZE "max-vm-size" // required +#define PRTE_CLI_DEBUG_DAEMONS "debug-daemons" // none +#define PRTE_CLI_DEBUG_DAEMONS_FILE "debug-daemons-file" // none +#define PRTE_CLI_LEAVE_SESSION_ATTACHED "leave-session-attached" // none +#define PRTE_CLI_TMPDIR "tmpdir" // required +#define PRTE_CLI_PREFIX "prefix" // required +#define PRTE_CLI_NOPREFIX "noprefix" // none +#define PRTE_CLI_FWD_SIGNALS "forward-signals" // required +#define PRTE_CLI_RUN_AS_ROOT "allow-run-as-root" // none + +// Application options +#define PRTE_CLI_NP "np" // required +#define PRTE_CLI_NPERNODE "N" // required +#define PRTE_CLI_APPFILE "app" // required +#define PRTE_CLI_TIMEOUT "timeout" // required +#define PRTE_CLI_SPAWN_TIMEOUT "spawn-timeout" // required +#define PRTE_CLI_REPORT_STATE "report-state-on-timeout" // none +#define PRTE_CLI_STACK_TRACES "get-stack-traces" // none +#define PRTE_CLI_FWD_ENVAR "x" // required +#define PRTE_CLI_SHOW_PROGRESS "show-progress" // none +#define PRTE_CLI_HOSTFILE "hostfile" // required +#define PRTE_CLI_HOST "host" // required +#define PRTE_CLI_STREAM_BUF "stream-buffering" // required +#define PRTE_CLI_REPORT_CHILD_SEP "report-child-jobs-separately" // none +#define PRTE_CLI_PATH "path" // required +#define PRTE_CLI_PSET "pset" // required +#define PRTE_CLI_PRELOAD_FILES "preload-files" // required +#define PRTE_CLI_PRELOAD_BIN "preload-binary" // none +#define PRTE_CLI_STDIN "stdin" // required +#define PRTE_CLI_OUTPUT "output" // required +#define PRTE_CLI_WDIR "wdir" // required +#define PRTE_CLI_SET_CWD_SESSION "set-cwd-to-session-dir" // none +#define PRTE_CLI_ENABLE_RECOVERY "enable-recovery" // none +#define PRTE_CLI_MAX_RESTARTS "max-restarts" // required +#define PRTE_CLI_DISABLE_RECOVERY "disable-recovery" // none +#define PRTE_CLI_CONTINUOUS "continuous" // none + +// Placement options +#define PRTE_CLI_MAPBY "map-by" // required +#define PRTE_CLI_RANKBY "rank-by" // required +#define PRTE_CLI_BINDTO "bind-to" // required + +// Debug options +#define PRTE_CLI_DO_NOT_LAUNCH "do-not-launch" // none +#define PRTE_CLI_DISPLAY "display" // required +#define PRTE_CLI_XTERM "xterm" // none +#define PRTE_CLI_STOP_ON_EXEC "stop-on-exec" // none +#define PRTE_CLI_STOP_IN_INIT "stop-in-init" // required +#define PRTE_CLI_STOP_IN_APP "stop-in-app" // required + +// Tool connection options +#define PRTE_CLI_SYS_SERVER_FIRST "system-server-first" // none +#define PRTE_CLI_SYS_SERVER_ONLY "system-server-only" // none +#define PRTE_CLI_DO_NOT_CONNECT "do-not-connect" // none +#define PRTE_CLI_WAIT_TO_CONNECT "wait-to-connect" // required +#define PRTE_CLI_NUM_CONNECT_RETRIES "num-connect-retries" // required +#define PRTE_CLI_PID "pid" // required +#define PRTE_CLI_NAMESPACE "namespace" // required +#define PRTE_CLI_DVM_URI "dvm-uri" // required + +// Daemon-specific CLI options +#define PRTE_CLI_PUBSUB_SERVER "prte-server" // required +#define PRTE_CLI_CONTROLLER_URI "dvm-master-uri" // required +#define PRTE_CLI_PARENT_URI "parent-uri" // required +#define PRTE_CLI_TREE_SPAWN "tree-spawn" // required +#define PRTE_CLI_PLM "plm" // required + + +/* define accepted synonyms - these must be defined on the schizo component's + * command line in order to be accepted, but PRRTE will automatically translate + * them to their accepted synonym */ +#define PRTE_CLI_MACHINEFILE "machinefile" // synonym for "hostfile" +#define PRTE_CLI_WD "wd" // synonym for "wdir + + +/* define the command line directives PRRTE recognizes */ + +// Placement directives +#define PRTE_CLI_SLOT "slot" +#define PRTE_CLI_HWT "hwthread" +#define PRTE_CLI_CORE "core" +#define PRTE_CLI_L1CACHE "l1cache" +#define PRTE_CLI_L2CACHE "l2cache" +#define PRTE_CLI_L3CACHE "l3cache" +#define PRTE_CLI_NUMA "numa" +#define PRTE_CLI_PACKAGE "package" +#define PRTE_CLI_NODE "node" +#define PRTE_CLI_SEQ "seq" +#define PRTE_CLI_DIST "dist" +#define PRTE_CLI_PPR "ppr" +#define PRTE_CLI_RANKFILE "rankfile" +#define PRTE_CLI_NONE "none" +#define PRTE_CLI_HWTCPUS "hwtcpus" + +// Output directives +#define PRTE_CLI_TAG "tag" +#define PRTE_CLI_RANK "rank" +#define PRTE_CLI_TIMESTAMP "timestamp" +#define PRTE_CLI_XML "xml" +#define PRTE_CLI_MERGE_ERROUT "merge-stderr-to-stdout" +#define PRTE_CLI_DIR "directory" +#define PRTE_CLI_FILE "filename" + +// Display directives +#define PRTE_CLI_ALLOC "allocation" +#define PRTE_CLI_MAP "map" +#define PRTE_CLI_BIND "bind" +#define PRTE_CLI_MAPDEV "map-devel" +#define PRTE_CLI_TOPO "topo" + +/* define the command line qualifiers PRRTE recognizes */ + +// Placement qualifiers +#define PRTE_CLI_PE "pe=" +#define PRTE_CLI_SPAN "span" +#define PRTE_CLI_OVERSUB "oversubscribe" +#define PRTE_CLI_NOOVER "nooversubscribe" +#define PRTE_CLI_NOLOCAL "nolocal" +// PRTE_CLI_HWTCPUS reused here +#define PRTE_CLI_CORECPUS "corecpus" +#define PRTE_CLI_DEVICE "device=" +#define PRTE_CLI_INHERIT "inherit" +#define PRTE_CLI_NOINHERIT "noinherit" +#define PRTE_CLI_PELIST "pe-list=" +#define PRTE_CLI_QDIR "dir=" +#define PRTE_CLI_QFILE "file=" +#define PRTE_CLI_NOLAUNCH "donotlaunch" +#define PRTE_CLI_FILL "fill" +#define PRTE_CLI_OVERLOAD "overload-allowed" +#define PRTE_CLI_IF_SUPP "if-supported" +#define PRTE_CLI_ORDERED "ordered" +#define PRTE_CLI_REPORT "report" +#define PRTE_CLI_DISPALLOC "displayalloc" +// PRTE_CLI_DISPLAY reused here +#define PRTE_CLI_DISPDEV "displaydevel" +#define PRTE_CLI_DISPTOPO "displaytopo" + +// Output qualifiers +#define PRTE_CLI_NOCOPY "nocopy" +#define PRTE_CLI_RAW "raw" +#define PRTE_CLI_PATTERN "pattern" + +typedef void (*prte_cmd_line_store_fn_t)(const char *name, const char *option, + prte_cli_result_t *results); + +PRTE_EXPORT int prte_cmd_line_parse(char **argv, char *shorts, + struct option myoptions[], + prte_cmd_line_store_fn_t storefn, + prte_cli_result_t *results, + char *helpfile); + +static inline prte_cli_item_t* prte_cmd_line_get_param(prte_cli_result_t *results, + const char *key) +{ + prte_cli_item_t *opt; + + PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { + if (0 == strcmp(opt->key, key)) { + return opt; + } + } + return NULL; +} + +static inline bool prte_cmd_line_is_taken(prte_cli_result_t *results, + const char *key) +{ + if (NULL == prte_cmd_line_get_param(results, key)) { + return false; + } + return true; +} + +static inline int prte_cmd_line_get_ninsts(prte_cli_result_t *results, + const char *key) +{ + prte_cli_item_t *opt; + + opt = prte_cmd_line_get_param(results, key); + if (NULL == opt) { + return 0; + } + return prte_argv_count(opt->values); +} + +static inline char* prte_cmd_line_get_nth_instance(prte_cli_result_t *results, + const char *key, int idx) +{ + prte_cli_item_t *opt; + int n, ninst; + + opt = prte_cmd_line_get_param(results, key); + if (NULL == opt) { + return NULL; + } + ninst = prte_argv_count(opt->values); + if (ninst < idx) { + return NULL; + } + return opt->values[idx]; +} END_C_DECLS diff --git a/src/util/help-cli.txt b/src/util/help-cli.txt new file mode 100644 index 0000000000..0bac31341d --- /dev/null +++ b/src/util/help-cli.txt @@ -0,0 +1,86 @@ +# -*- text -*- +# +# Copyright (c) 2009-2020 Cisco Systems, Inc. All rights reserved +# Copyright (c) 2017-2020 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# This is the US/English general help file for PRTE CLI options. +# +[help] +Help can be requested in three ways: + +- a directive to the cmd. For example, the command + "%s --help" or "%s -h" + will provide the high-level help output giving a general + description of each available option. + +- an option to the help directive. For example, the command + "%s --help foo" or "%s -h foo" + will provide detailed help about the "foo" command line + directive. + +- specifying "help" as an option to the directive of interest. + For example, the command + "%s --foo --help" or "%s --foo -h" + will provide detailed help about the "foo" command line + directive. Note that the "help" and "h" options do not + require the dash prefixes - i.e., the following commands + "%s --foo help" or "%s --foo h" + will also output detailed help for "foo". Thus, directives + are precluded from defining options of "help" and "h". + +Note that the last two methods are functionally equivalent +and will return the same output. +# +[unknown-option] +Help was requested for an unknown option: + + Option: %s + +Please use the "%s --help" command to obtain a list of all +supported options. +# +[unrecognized-option] +The help system for %s does not recognize the following: + + Option: %s + +This might require help from the developers. +# +[version] +Print version and exit +# +[verbose] +Enable debug options - number of times specified sets level of verbosity +(e.g., -vvv => 3rd level of debug information) +# +[quiet] +Suppress helpful messages +# +[parsable] +When used in conjunction with other parameters, output information +(e.g., help messages) is displayed in a machine-parsable format +# +[parseable] +When used in conjunction with other parameters, the output information +(e.g., help messages) is displayed in a machine-parsable format +# +[short-no-long] +A short option was provided to %s and recognized by the parser, +but has no matching long option: + + Short option: %s + +This might require help from the developers. +[unregistered-option] +An unrecognized option was included on the %s command line: + + Option: %s + +Please use the "%s --help" command to obtain a list of all +supported options. diff --git a/src/util/help-prte-util.txt b/src/util/help-prte-util.txt index f749dcac86..e8f73809cd 100644 --- a/src/util/help-prte-util.txt +++ b/src/util/help-prte-util.txt @@ -11,106 +11,3 @@ # This is the US/English general help file for PRTE. # [stacktrace signal override] -PRTE was inserting a signal handler for signal %d but noticed -that there is already a non-default handler installed. PRTE's -handler was therefore not installed; your job will continue. This -warning message will only be displayed once, even if PRTE -encounters this situation again. - -To avoid displaying this warning message, you can either not install -the error handler for signal %d or you can have PRTE not try to -install its own signal handler for this signal by setting the -"prte_signals" MCA parameter. - - Signal: %d - Current prte_signal value: %s -# -[stacktrace bad signal] -PRTE was inserting a signal handler but was given an invalid -signal number: - - Signal string: %s - Bad value: %s - -The given value must be an integer within the signal number -range. Please correct the value and try again. -# -[malformed net_private_ipv4] -PRTE has detected at least one malformed IP address or netmask in -the value of the prte_net_private_ipv4 MCA parameter. The -prte_net_private_ipv4 MCA parameter accepts a semicolon-delimited list -of Classless Inter-Domain Routing (CIDR) notation specifications, each -of the form /. For example: - - 10.0.0.0/8;172.16.0.0/12;192.168.0.0/16;169.254.0.0/16 - -The first detected malformed entry was %s. -# -[invalid-net-mask] -PRTE has detected a malformed IPv4 address or netmask: - - Value provided: %s - -Accepted values follow the Classless Inter-Domain -Routing (CIDR) notation specifications. For example: - - 10.0.0.0/8 - 172.16/12 - 192.168 - 169.254.0.0/16 -# -[malformed-uri] -PRTE has detected a malformed URI: - - URI: %s - -Accepted values follow IETF RFC3986, e.g. file://192.168.1.1/over/there -# -[relative-path] -When creating a URI, all files must be specified in absolute paths: - - Value provided: %s - -Please update your application to provide the full path to the file. -# -[sys-limit-failed] -Per request, PRTE attempted to set a system resource -limit to a given value: - - Resource: %s - Limit: %s - -The system has refused to allow this operation. This is likely -due to a permission limitation, or specifying an unsupported -value. Please check the system or remove the request and try -again. -# -[sys-limit-unrecognized] -PRTE received a request to set a system resource limit. -Sadly, OMPI does not recognize or currently support the specified -resource: - - Resource: %s - Limit: %s - -Please correct the request and try again. -# -[dir-mode] -While working through a directory tree, we were unable to set -a directory to the desired mode: - - Directory: %s - Mode: %0x - Error: %s - -Please check to ensure you have adequate permissions to perform -the desired operation. -# -[mkdir-failed] -A call to mkdir was unable to create the desired directory: - - Directory: %s - Error: %s - -Please check to ensure you have adequate permissions to perform -the desired operation. From accbe039cc20259850b73fe1b7fff41b22d2ad66 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Thu, 13 Jan 2022 13:36:46 -0800 Subject: [PATCH 2/7] Split out setting of default placement policies Allow each schizo personality to define its own default mapping, ranking, and binding policies. Any they choose not to define will fallback to the PRRTE defaults. Add an MCA param to each schizo component allowing it to silence deprecation warnings. Default the PRRTE component to output them. Default the OMPI component to silence them. Update the OMPI component to set its own ranking policy for the PPR mapping option - leave all else to the defaults. Signed-off-by: Ralph Castain --- src/hwloc/hwloc-internal.h | 19 +- src/hwloc/hwloc.c | 143 +++++++++- src/mca/ess/base/ess_base_std_prted.c | 12 +- src/mca/ess/hnp/ess_hnp_module.c | 12 +- src/mca/plm/base/plm_base_receive.c | 18 +- src/mca/rmaps/base/base.h | 10 +- src/mca/rmaps/base/rmaps_base_frame.c | 55 +++- src/mca/rmaps/base/rmaps_base_map_job.c | 207 +++----------- src/mca/schizo/base/schizo_base_frame.c | 1 + src/mca/schizo/base/schizo_base_stubs.c | 17 +- src/mca/schizo/ompi/schizo_ompi.c | 291 ++++++++++++++------ src/mca/schizo/ompi/schizo_ompi.h | 3 +- src/mca/schizo/ompi/schizo_ompi_component.c | 22 +- src/mca/schizo/prte/schizo_prte.c | 225 ++++++++++----- src/mca/schizo/prte/schizo_prte.h | 1 + src/mca/schizo/prte/schizo_prte_component.c | 20 +- src/mca/schizo/schizo.h | 39 ++- src/prted/pmix/pmix_server_dyn.c | 3 +- src/util/cmd_line.h | 21 ++ 19 files changed, 772 insertions(+), 347 deletions(-) diff --git a/src/hwloc/hwloc-internal.h b/src/hwloc/hwloc-internal.h index 6fdd7c64d1..6e7a9f1f64 100644 --- a/src/hwloc/hwloc-internal.h +++ b/src/hwloc/hwloc-internal.h @@ -153,6 +153,8 @@ typedef uint16_t prte_binding_policy_t; /* bind each rank to the cpu in the given * cpu list based on its node-local-rank */ #define PRTE_BIND_ORDERED 0x8000 +// overload policy was given +#define PRTE_BIND_OVERLOAD_GIVEN 0x0100 /* binding policies - any changes in these * values must be reflected in prte/mca/rmaps/rmaps.h @@ -165,14 +167,14 @@ typedef uint16_t prte_binding_policy_t; #define PRTE_BIND_TO_L1CACHE 6 #define PRTE_BIND_TO_CORE 7 #define PRTE_BIND_TO_HWTHREAD 8 -#define PRTE_GET_BINDING_POLICY(pol) ((pol) &0x0fff) +#define PRTE_GET_BINDING_POLICY(pol) ((pol) &0x00ff) #define PRTE_SET_BINDING_POLICY(target, pol) \ - (target) = (pol) | (((target) &0x2000) | PRTE_BIND_GIVEN) -#define PRTE_SET_DEFAULT_BINDING_POLICY(target, pol) \ - do { \ - if (!PRTE_BINDING_POLICY_IS_SET((target))) { \ - (target) = (pol) | (((target) &0xf000) | PRTE_BIND_IF_SUPPORTED); \ - } \ + (target) = (pol) | (((target) & 0xff00) | PRTE_BIND_GIVEN) +#define PRTE_SET_DEFAULT_BINDING_POLICY(target, pol) \ + do { \ + if (!PRTE_BINDING_POLICY_IS_SET((target))) { \ + (target) = (pol) | (((target) & 0xff00) | PRTE_BIND_IF_SUPPORTED); \ + } \ } while (0); /* check if policy is set */ @@ -181,6 +183,7 @@ typedef uint16_t prte_binding_policy_t; #define PRTE_BINDING_REQUIRED(n) (!(PRTE_BIND_IF_SUPPORTED & (n))) /* macro to detect if binding is forced */ #define PRTE_BIND_OVERLOAD_ALLOWED(n) (PRTE_BIND_ALLOW_OVERLOAD & (n)) +#define PRTE_BIND_OVERLOAD_SET(n) (PRTE_BIND_OVERLOAD_GIVEN & (n)) #define PRTE_BIND_ORDERED_REQUESTED(n) (PRTE_BIND_ORDERED & (n)) /* some global values */ @@ -257,6 +260,8 @@ PRTE_EXPORT prte_hwloc_locality_t prte_hwloc_base_get_relative_locality(hwloc_to char *cpuset1, char *cpuset2); +PRTE_EXPORT int prte_hwloc_base_set_default_binding(void *jdata, + void *options); PRTE_EXPORT int prte_hwloc_base_set_binding_policy(void *jdata, char *spec); /** diff --git a/src/hwloc/hwloc.c b/src/hwloc/hwloc.c index f9108e969c..ccace9d0ab 100644 --- a/src/hwloc/hwloc.c +++ b/src/hwloc/hwloc.c @@ -3,7 +3,7 @@ * Copyright (c) 2013-2020 Intel, Inc. All rights reserved. * Copyright (c) 2016-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -18,6 +18,7 @@ #include "src/mca/base/base.h" #include "src/mca/mca.h" #include "src/mca/rmaps/rmaps_types.h" +#include "src/mca/schizo/schizo.h" #include "src/runtime/prte_globals.h" #include "src/threads/tsd.h" #include "src/util/argv.h" @@ -301,6 +302,141 @@ void prte_hwloc_base_close(void) prte_hwloc_base_inited = false; } +int prte_hwloc_base_set_default_binding(void *jd, + void *opt) +{ + prte_job_t *jdata = (prte_job_t*)jd; + prte_schizo_options_t *options = (prte_schizo_options_t*)opt; + prte_mapping_policy_t mpol; + + if (prte_get_attribute(&jdata->attributes, PRTE_JOB_PES_PER_PROC, NULL, PMIX_UINT16)) { + /* bind to cpus */ + if (options->use_hwthreads) { + /* if we are using hwthread cpus, then bind to those */ + prte_output_verbose(options->verbosity, options->stream, + "setdefaultbinding[%d] binding not given - using byhwthread", + __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); + } else { + /* bind to core */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bycore", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); + } + } else { + /* if the user explicitly mapped-by some object, then we default + * to binding to that object */ + mpol = PRTE_GET_MAPPING_POLICY(jdata->map->mapping); + if (PRTE_MAPPING_GIVEN & PRTE_GET_MAPPING_DIRECTIVE(jdata->map->mapping)) { + if (PRTE_MAPPING_BYHWTHREAD == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using byhwthread", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); + } else if (PRTE_MAPPING_BYCORE == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bycore", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); + } else if (PRTE_MAPPING_BYL1CACHE == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using byL1", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L1CACHE); + } else if (PRTE_MAPPING_BYL2CACHE == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using byL2", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L2CACHE); + } else if (PRTE_MAPPING_BYL3CACHE == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using byL3", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L3CACHE); + } else if (PRTE_MAPPING_BYNUMA == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bynuma", + __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); + } else if (PRTE_MAPPING_BYPACKAGE == mpol) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bypackage", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); + } else { + /* we are mapping by node or some other non-object method */ + if (options->nprocs <= 2) { + if (options->use_hwthreads) { + /* if we are using hwthread cpus, then bind to those */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using byhwthread", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, + PRTE_BIND_TO_HWTHREAD); + } else { + /* for performance, bind to core */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bycore", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, + PRTE_BIND_TO_CORE); + } + } else { + /* bind to numa (if present), or by package (if numa isn't present and package is) */ + if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bynuma", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); + } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bypackage", __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); + } else { + /* if we have neither, then just don't bind */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given and no NUMA " + "or packages - not binding", + __LINE__); + PRTE_SET_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NONE); + } + } + } + } else if (options->nprocs <= 2) { + if (options->use_hwthreads) { + /* if we are using hwthread cpus, then bind to those */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using byhwthread", + __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); + } else { + /* for performance, bind to core */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bycore", + __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); + } + } else { + /* for performance, bind to numa, if available, else try package */ + if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bynuma", + __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); + } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given - using bypackage", + __LINE__); + PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); + } else { + /* just don't bind */ + prte_output_verbose(options->verbosity, options->stream, + "mca:rmaps[%d] binding not given and no packages - not binding", + __LINE__); + PRTE_SET_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NONE); + } + } + } + /* they might have set the overload-allowed flag while wanting PRRTE + * to set the default binding - don't override it */ + if (!PRTE_BIND_OVERLOAD_SET(jdata->map->binding)) { + if (PRTE_BIND_OVERLOAD_ALLOWED(prte_hwloc_default_binding_policy)) { + jdata->map->binding |= PRTE_BIND_ALLOW_OVERLOAD; + } + } +} + static bool fns_init = false; static prte_tsd_key_t print_tsd_key; char *prte_hwloc_print_null = "NULL"; @@ -507,7 +643,10 @@ int prte_hwloc_base_set_binding_policy(void *jdat, char *spec) if (0 == strcasecmp(quals[i], "if-supported")) { tmp |= PRTE_BIND_IF_SUPPORTED; } else if (0 == strcasecmp(quals[i], "overload-allowed")) { - tmp |= PRTE_BIND_ALLOW_OVERLOAD; + tmp |= (PRTE_BIND_ALLOW_OVERLOAD | PRTE_BIND_OVERLOAD_GIVEN); + } else if (0 == strcasecmp(quals[i], "no-overload")) { + tmp = (tmp & ~PRTE_BIND_ALLOW_OVERLOAD); + tmp |= PRTE_BIND_OVERLOAD_GIVEN; } else if (0 == strcasecmp(quals[i], "ordered")) { tmp |= PRTE_BIND_ORDERED; } else if (0 == strcasecmp(quals[i], "REPORT")) { diff --git a/src/mca/ess/base/ess_base_std_prted.c b/src/mca/ess/base/ess_base_std_prted.c index 42a21f50f1..268c1343f5 100644 --- a/src/mca/ess/base/ess_base_std_prted.c +++ b/src/mca/ess/base/ess_base_std_prted.c @@ -18,7 +18,7 @@ * Copyright (c) 2017 IBM Corporation. All rights reserved. * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -64,6 +64,7 @@ #include "src/mca/routed/base/base.h" #include "src/mca/routed/routed.h" #include "src/mca/rtc/base/base.h" +#include "src/mca/schizo/base/base.h" #include "src/mca/state/base/base.h" #include "src/mca/state/state.h" #include "src/prted/pmix/pmix_server.h" @@ -288,6 +289,15 @@ int prte_ess_base_prted_setup(void) jdata = PRTE_NEW(prte_job_t); PMIX_LOAD_NSPACE(jdata->nspace, PRTE_PROC_MY_NAME->nspace); prte_set_job_data_object(jdata); + /* set the schizo personality to "prte" by default */ + jdata->schizo = (struct prte_schizo_base_module_t*)prte_schizo_base_detect_proxy("prte"); + if (NULL == jdata->schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, "prte"); + error = "select personality"; + ret = PRTE_ERR_SILENT; + goto error; + } + /* every job requires at least one app */ app = PRTE_NEW(prte_app_context_t); prte_pointer_array_set_item(jdata->apps, 0, app); diff --git a/src/mca/ess/hnp/ess_hnp_module.c b/src/mca/ess/hnp/ess_hnp_module.c index fbbda9b8a7..bf2c952086 100644 --- a/src/mca/ess/hnp/ess_hnp_module.c +++ b/src/mca/ess/hnp/ess_hnp_module.c @@ -17,7 +17,7 @@ * Copyright (c) 2013-2020 Intel, Inc. All rights reserved. * Copyright (c) 2017-2018 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -73,6 +73,7 @@ #include "src/mca/routed/base/base.h" #include "src/mca/routed/routed.h" #include "src/mca/rtc/base/base.h" +#include "src/mca/schizo/base/base.h" #include "src/mca/state/base/base.h" #include "src/mca/state/state.h" @@ -315,6 +316,15 @@ static int rte_init(int argc, char **argv) PMIX_LOAD_NSPACE(jdata->nspace, PRTE_PROC_MY_NAME->nspace); prte_set_job_data_object(jdata); + /* set the schizo personality to "prte" by default */ + jdata->schizo = (struct prte_schizo_base_module_t*)prte_schizo_base_detect_proxy("prte"); + if (NULL == jdata->schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, "prte"); + error = "select personality"; + ret = PRTE_ERR_SILENT; + goto error; + } + /* mark that the daemons have reported as we are the * only ones in the system right now, and we definitely * are running! diff --git a/src/mca/plm/base/plm_base_receive.c b/src/mca/plm/base/plm_base_receive.c index 123b9eb1b6..a3e33e9499 100644 --- a/src/mca/plm/base/plm_base_receive.c +++ b/src/mca/plm/base/plm_base_receive.c @@ -17,7 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved * Copyright (c) 2020 IBM Corporation. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -50,6 +50,7 @@ #include "src/mca/rml/rml.h" #include "src/mca/rml/rml_types.h" #include "src/mca/routed/routed.h" +#include "src/mca/schizo/base/base.h" #include "src/mca/state/state.h" #include "src/pmix/pmix-internal.h" #include "src/runtime/prte_globals.h" @@ -57,6 +58,7 @@ #include "src/util/error_strings.h" #include "src/util/name_fns.h" #include "src/util/proc_info.h" +#include "src/util/show_help.h" #include "types.h" #include "src/mca/plm/base/base.h" @@ -208,6 +210,20 @@ void prte_plm_base_recv(int status, pmix_proc_t *sender, pmix_data_buffer_t *buf /* record the sender so we know who to respond to */ PMIX_LOAD_PROCID(&jdata->originator, sender->nspace, sender->rank); + /* assign a schizo module */ + if (NULL == jdata->personality) { + prte_argv_append_nosize(&jdata->personality, "prte"); + } + tmp = prte_argv_join(jdata->personality, ','); + jdata->schizo = (struct prte_schizo_base_module_t*)prte_schizo_base_detect_proxy(tmp); + if (NULL == jdata->schizo) { + prte_show_help("help-schizo-base.txt", "no-proxy", true, prte_tool_basename, tmp); + free(tmp); + rc = PRTE_ERR_NOT_FOUND; + goto ANSWER_LAUNCH; + } + free(tmp); + /* get the name of the actual spawn parent - i.e., the proc that actually * requested the spawn */ if (!prte_get_attribute(&jdata->attributes, PRTE_JOB_LAUNCH_PROXY, (void **) &nptr, PMIX_PROC)) { diff --git a/src/mca/rmaps/base/base.h b/src/mca/rmaps/base/base.h index c8f8a3f42f..43ffd92433 100644 --- a/src/mca/rmaps/base/base.h +++ b/src/mca/rmaps/base/base.h @@ -13,7 +13,7 @@ * Copyright (c) 2011-2013 Los Alamos National Security, LLC. * All rights reserved. * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -35,9 +35,10 @@ #include "src/class/prte_list.h" #include "src/mca/mca.h" +#include "src/mca/base/prte_mca_base_framework.h" +#include "src/mca/schizo/schizo.h" #include "src/util/printf.h" -#include "src/mca/base/prte_mca_base_framework.h" #include "src/runtime/prte_globals.h" #include "src/mca/rmaps/rmaps.h" @@ -116,7 +117,12 @@ PRTE_EXPORT int prte_rmaps_base_prep_topology(hwloc_topology_t topo); PRTE_EXPORT int prte_rmaps_base_filter_nodes(prte_app_context_t *app, prte_list_t *nodes, bool remove); +PRTE_EXPORT int prte_rmaps_base_set_default_mapping(prte_job_t *jdata, + prte_schizo_options_t *options); PRTE_EXPORT int prte_rmaps_base_set_mapping_policy(prte_job_t *jdata, char *spec); + +PRTE_EXPORT int prte_rmaps_base_set_default_ranking(prte_job_t *jdata, + prte_schizo_options_t *options); PRTE_EXPORT int prte_rmaps_base_set_ranking_policy(prte_job_t *jdata, char *spec); PRTE_EXPORT void prte_rmaps_base_display_map(prte_job_t *jdata); diff --git a/src/mca/rmaps/base/rmaps_base_frame.c b/src/mca/rmaps/base/rmaps_base_frame.c index 9e9a9c6c8f..07c36354ab 100644 --- a/src/mca/rmaps/base/rmaps_base_frame.c +++ b/src/mca/rmaps/base/rmaps_base_frame.c @@ -15,7 +15,7 @@ * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. * Copyright (c) 2014-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -449,6 +449,51 @@ static int check_modifiers(char *ck, prte_job_t *jdata, prte_mapping_policy_t *t return PRTE_SUCCESS; } +int prte_rmaps_base_set_default_mapping(prte_job_t *jdata, + prte_schizo_options_t *options) +{ + /* default based on number of procs */ + if (options->nprocs <= 2) { + if (1 < options->cpus_per_rank) { + /* assigning multiple cpus to a rank requires that we map to + * objects that have multiple cpus in them, so default + * to byslot if nothing else was specified by the user. + */ + prte_output_verbose(5, prte_rmaps_base_framework.framework_output, + "mca:rmaps[%d] mapping not given - using byslot", __LINE__); + PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); + } else if (options->use_hwthreads) { + prte_output_verbose(5, prte_rmaps_base_framework.framework_output, + "mca:rmaps[%d] mapping not given - using byhwthread", + __LINE__); + PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYHWTHREAD); + } else { + prte_output_verbose(5, prte_rmaps_base_framework.framework_output, + "mca:rmaps[%d] mapping not given - using bycore", __LINE__); + PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYCORE); + } + } else { + /* if NUMA is available, map by that */ + if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { + prte_output_verbose(5, prte_rmaps_base_framework.framework_output, + "mca:rmaps[%d] mapping not set by user - using bynuma", __LINE__); + PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYNUMA); + } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { + /* if package is available, map by that */ + prte_output_verbose(5, prte_rmaps_base_framework.framework_output, + "mca:rmaps[%d] mapping not set by user - using bypackage", __LINE__); + PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYPACKAGE); + } else { + /* if we have neither, then just do by slot */ + prte_output_verbose(5, prte_rmaps_base_framework.framework_output, + "mca:rmaps[%d] mapping not given and no packages - using byslot", + __LINE__); + PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); + } + } + return PRTE_SUCCESS; +} + int prte_rmaps_base_set_mapping_policy(prte_job_t *jdata, char *inspec) { char *ck; @@ -646,6 +691,14 @@ int prte_rmaps_base_set_mapping_policy(prte_job_t *jdata, char *inspec) return PRTE_SUCCESS; } +int prte_rmaps_base_set_default_ranking(prte_job_t *jdata, + prte_schizo_options_t *options) +{ + int rc; + rc = prte_rmaps_base_set_ranking_policy(jdata, NULL); + return rc; +} + int prte_rmaps_base_set_ranking_policy(prte_job_t *jdata, char *spec) { prte_mapping_policy_t map, mapping; diff --git a/src/mca/rmaps/base/rmaps_base_map_job.c b/src/mca/rmaps/base/rmaps_base_map_job.c index 531c2f301f..cd926fef69 100644 --- a/src/mca/rmaps/base/rmaps_base_map_job.c +++ b/src/mca/rmaps/base/rmaps_base_map_job.c @@ -17,7 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2019 UT-Battelle, LLC. All rights reserved. * - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -69,12 +69,19 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) bool sequential = false; int32_t slots; hwloc_obj_t obj = NULL; + prte_schizo_base_module_t *schizo; + prte_schizo_options_t options; PRTE_HIDE_UNUSED_PARAMS(fd, args); PRTE_ACQUIRE_OBJECT(caddy); jdata = caddy->jdata; - + schizo = (prte_schizo_base_module_t*)jdata->schizo; + if (NULL == schizo) { + prte_output(0, "ARG"); + PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_MAP_FAILED); + goto cleanup; + } jdata->state = PRTE_JOB_STATE_MAP; prte_output_verbose(5, prte_rmaps_base_framework.framework_output, @@ -440,6 +447,12 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) PRTE_JOBID_PRINT(jdata->nspace), (int) nprocs, inherit ? "TRUE" : "FALSE", use_hwthreads ? "TRUE" : "FALSE"); + options.nprocs = nprocs; + options.cpus_per_rank = cpus_per_rank; + options.use_hwthreads = use_hwthreads; + options.stream = prte_rmaps_base_framework.framework_output; + options.verbosity = 5; // usual value for base-level functions + /* set the default mapping policy IFF it wasn't provided */ if (!PRTE_MAPPING_POLICY_IS_SET(jdata->map->mapping)) { did_map = false; @@ -455,44 +468,17 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) } } if (!did_map) { - /* default based on number of procs */ - if (nprocs <= 2) { - if (1 < cpus_per_rank) { - /* assigning multiple cpus to a rank requires that we map to - * objects that have multiple cpus in them, so default - * to byslot if nothing else was specified by the user. - */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] mapping not given - using byslot", __LINE__); - PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); - } else if (use_hwthreads) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] mapping not given - using byhwthread", - __LINE__); - PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYHWTHREAD); - } else { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] mapping not given - using bycore", __LINE__); - PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYCORE); - } + // let the job's personality set the default mapping behavior + if (NULL != schizo->set_default_mapping) { + rc = schizo->set_default_mapping(jdata, &options); } else { - /* if NUMA is available, map by that */ - if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] mapping not set by user - using bynuma", __LINE__); - PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYNUMA); - } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { - /* if package is available, map by that */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] mapping not set by user - using bypackage", __LINE__); - PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYPACKAGE); - } else { - /* if we have neither, then just do by slot */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] mapping not given and no packages - using byslot", - __LINE__); - PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); - } + rc = prte_rmaps_base_set_default_mapping(jdata, &options); + } + if (PRTE_SUCCESS != rc) { + // the error message should have been printed + jdata->exit_code = rc; + PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_MAP_FAILED); + goto cleanup; } } } @@ -537,13 +523,17 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) } } if (!did_map) { - rc = prte_rmaps_base_set_ranking_policy(jdata, NULL); + // let the job's personality set the default ranking behavior + if (NULL != schizo->set_default_ranking) { + rc = schizo->set_default_ranking(jdata, &options); + } else { + rc = prte_rmaps_base_set_default_ranking(jdata, &options); + } if (PRTE_SUCCESS != rc) { - PRTE_ERROR_LOG(rc); - PRTE_RELEASE(caddy); - jdata->exit_code = PRTE_ERR_NOT_FOUND; + // the error message should have been printed + jdata->exit_code = rc; PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_MAP_FAILED); - return; + goto cleanup; } } } @@ -568,128 +558,17 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) } } if (!did_map) { - if (prte_get_attribute(&jdata->attributes, PRTE_JOB_PES_PER_PROC, NULL, PMIX_UINT16)) { - /* bind to cpus */ - if (use_hwthreads) { - /* if we are using hwthread cpus, then bind to those */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byhwthread", - __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); - } else { - /* bind to core */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bycore", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); - } + // let the job's personality set the default binding behavior + if (NULL != schizo->set_default_binding) { + rc = schizo->set_default_binding(jdata, &options); } else { - /* if the user explicitly mapped-by some object, then we default - * to binding to that object */ - prte_mapping_policy_t mpol; - mpol = PRTE_GET_MAPPING_POLICY(jdata->map->mapping); - if (PRTE_MAPPING_GIVEN & PRTE_GET_MAPPING_DIRECTIVE(jdata->map->mapping)) { - if (PRTE_MAPPING_BYHWTHREAD == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byhwthread", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); - } else if (PRTE_MAPPING_BYCORE == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bycore", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); - } else if (PRTE_MAPPING_BYL1CACHE == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byL1", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L1CACHE); - } else if (PRTE_MAPPING_BYL2CACHE == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byL2", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L2CACHE); - } else if (PRTE_MAPPING_BYL3CACHE == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byL3", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L3CACHE); - } else if (PRTE_MAPPING_BYNUMA == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bynuma", - __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); - } else if (PRTE_MAPPING_BYPACKAGE == mpol) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bypackage", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); - } else { - /* we are mapping by node or some other non-object method */ - if (nprocs <= 2) { - if (use_hwthreads) { - /* if we are using hwthread cpus, then bind to those */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byhwthread", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, - PRTE_BIND_TO_HWTHREAD); - } else { - /* for performance, bind to core */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bycore", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, - PRTE_BIND_TO_CORE); - } - } else { - /* bind to numa (if present), or by package (if numa isn't present and package is) */ - if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bynuma", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); - } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bypackage", __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); - } else { - /* if we have neither, then just don't bind */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given and no NUMA " - "or packages - not binding", - __LINE__); - PRTE_SET_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NONE); - } - } - } - } else if (nprocs <= 2) { - if (use_hwthreads) { - /* if we are using hwthread cpus, then bind to those */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using byhwthread", - __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); - } else { - /* for performance, bind to core */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bycore", - __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); - } - } else { - /* for performance, bind to numa, if available, else try package */ - if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bynuma", - __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); - } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given - using bypackage", - __LINE__); - PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); - } else { - /* just don't bind */ - prte_output_verbose(5, prte_rmaps_base_framework.framework_output, - "mca:rmaps[%d] binding not given and no packages - not binding", - __LINE__); - PRTE_SET_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NONE); - } - } + rc = prte_hwloc_base_set_default_binding(jdata, &options); } - if (PRTE_BIND_OVERLOAD_ALLOWED(prte_hwloc_default_binding_policy)) { - jdata->map->binding |= PRTE_BIND_ALLOW_OVERLOAD; + if (PRTE_SUCCESS != rc) { + // the error message should have been printed + jdata->exit_code = rc; + PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_MAP_FAILED); + goto cleanup; } } } diff --git a/src/mca/schizo/base/schizo_base_frame.c b/src/mca/schizo/base/schizo_base_frame.c index ce72d5d317..5fe7a1ed99 100644 --- a/src/mca/schizo/base/schizo_base_frame.c +++ b/src/mca/schizo/base/schizo_base_frame.c @@ -365,6 +365,7 @@ int prte_schizo_base_sanity(prte_cli_result_t *cmd_line) }; char *bndquals[] = { PRTE_CLI_OVERLOAD, + PRTE_CLI_NOOVERLOAD, PRTE_CLI_IF_SUPP, PRTE_CLI_ORDERED, PRTE_CLI_REPORT, diff --git a/src/mca/schizo/base/schizo_base_stubs.c b/src/mca/schizo/base/schizo_base_stubs.c index 7b80dc066e..ccffd88a30 100644 --- a/src/mca/schizo/base/schizo_base_stubs.c +++ b/src/mca/schizo/base/schizo_base_stubs.c @@ -97,7 +97,9 @@ int prte_schizo_base_add_directive(prte_cli_result_t *results, prte_argv_append_nosize(&opt->values, directive); } else if (1 < prte_argv_count(opt->values)) { // cannot use this function - prte_show_help("help-schizo-base.txt", "too-many-values", true, target); + ptr = prte_show_help_string("help-schizo-base.txt", "too-many-values", + true, target); + fprintf(stderr, "%s\n", ptr); return PRTE_ERR_SILENT; } else { // does this contain only a qualifier? @@ -110,8 +112,9 @@ int prte_schizo_base_add_directive(prte_cli_result_t *results, // do we allow multiple directives? if (!check_multi(target)) { // report the error - prte_show_help("help-schizo-base.txt", "too-many-directives", true, - target, opt->values, deprecated, directive); + ptr = prte_show_help_string("help-schizo-base.txt", "too-many-directives", + true, target, opt->values, deprecated, directive); + fprintf(stderr, "%s\n", ptr); return PRTE_ERR_SILENT; } // does the value contain a qualifier? @@ -135,7 +138,8 @@ int prte_schizo_base_add_directive(prte_cli_result_t *results, // add the new option opt = PRTE_NEW(prte_cli_item_t); opt->key = strdup(target); - prte_argv_append_nosize(&opt->values, tmp); + prte_argv_append_nosize(&opt->values, directive); + prte_list_append(&results->instances, &opt->super); } if (report) { @@ -169,7 +173,9 @@ int prte_schizo_base_add_qualifier(prte_cli_result_t *results, free(tmp); } else if (1 < prte_argv_count(opt->values)) { // cannot use this function - prte_show_help("help-schizo-base.txt", "too-many-values", true, target); + ptr = prte_show_help_string("help-schizo-base.txt", "too-many-values", + true, target); + fprintf(stderr, "%s\n", ptr); return PRTE_ERR_SILENT; } else { // does it already contain a qualifier? @@ -192,6 +198,7 @@ int prte_schizo_base_add_qualifier(prte_cli_result_t *results, prte_asprintf(&tmp, ":%s", qualifier); prte_argv_append_nosize(&opt->values, tmp); free(tmp); + prte_list_append(&results->instances, &opt->super); } if (report) { diff --git a/src/mca/schizo/ompi/schizo_ompi.c b/src/mca/schizo/ompi/schizo_ompi.c index 470a0759a4..9695fde5d0 100644 --- a/src/mca/schizo/ompi/schizo_ompi.c +++ b/src/mca/schizo/ompi/schizo_ompi.c @@ -53,7 +53,7 @@ #include "src/mca/base/prte_mca_base_vari.h" #include "src/mca/errmgr/errmgr.h" #include "src/mca/ess/base/base.h" -#include "src/mca/rmaps/rmaps_types.h" +#include "src/mca/rmaps/base/base.h" #include "src/runtime/prte_globals.h" #include "schizo_ompi.h" @@ -63,6 +63,8 @@ static int parse_cli(char **argv, prte_cli_result_t *results); static int detect_proxy(char *argv); static int parse_env(char **srcenv, char ***dstenv, prte_cli_result_t *cli); static void allow_run_as_root(prte_cli_result_t *results); +static int set_default_ranking(prte_job_t *jdata, + prte_schizo_options_t *options); static int setup_fork(prte_job_t *jdata, prte_app_context_t *context); static void job_info(prte_cli_result_t *results, void *jobinfo); @@ -74,6 +76,7 @@ prte_schizo_base_module_t prte_schizo_ompi_module = { .setup_fork = setup_fork, .detect_proxy = detect_proxy, .allow_run_as_root = allow_run_as_root, + .set_default_ranking = set_default_ranking, .job_info = job_info }; @@ -125,7 +128,7 @@ static struct option ompioptions[] = { PRTE_OPTION_SHORT_DEFINE(PRTE_CLI_NP, PRTE_ARG_REQD, 'c'), PRTE_OPTION_DEFINE("n", PRTE_ARG_REQD), // will be converted to "np" after parsing PRTE_OPTION_SHORT_DEFINE("N", PRTE_ARG_REQD, 'N'), - PRTE_OPTION_DEFINE("app", PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_APPFILE, PRTE_ARG_REQD), /* output options */ PRTE_OPTION_DEFINE(PRTE_CLI_OUTPUT, PRTE_ARG_REQD), @@ -167,10 +170,10 @@ static struct option ompioptions[] = { #if PRTE_ENABLE_FT - PRTE_OPTION_DEFINE("enable-recovery", PRTE_ARG_NONE), - PRTE_OPTION_DEFINE("max-restarts", PRTE_ARG_REQD), - PRTE_OPTION_DEFINE("disable-recovery", PRTE_ARG_NONE), - PRTE_OPTION_DEFINE("continuous", PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_ENABLE_RECOVERY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_MAX_RESTARTS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DISABLE_RECOVERY, PRTE_ARG_NONE), + PRTE_OPTION_DEFINE(PRTE_CLI_CONTINUOUS, PRTE_ARG_NONE), PRTE_OPTION_DEFINE("with-ft", PRTE_ARG_REQD), #endif @@ -227,7 +230,7 @@ static struct option ompioptions[] = { PRTE_OPTION_END }; -static char *ompishorts = "h::vVpn:c:sHx:"; +static char *ompishorts = "h::vVpn:c:N:sH:x:"; static int convert_deprecated_cli(prte_cli_result_t *results); @@ -287,12 +290,12 @@ static int parse_cli(char **argv, prte_cli_result_t *results) // handle relevant MCA params PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { - if (0 == strcmp(opt->key, "prtemca")) { + 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, "pmixmca")) { + } 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_"); @@ -335,80 +338,126 @@ static int convert_deprecated_cli(prte_cli_result_t *results) { char *option, *p1, *p2, *tmp, *tmp2, *output, *modifier; int rc = PRTE_SUCCESS; - prte_cli_item_t *opt; + prte_cli_item_t *opt, *nxt; prte_value_t *pval, val; - PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { + PRTE_LIST_FOREACH_SAFE(opt, nxt, &results->instances, prte_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, "np", opt->values[0], false); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_NP, opt->values[0], false); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --nolocal -> --map-by :nolocal */ else if (0 == strcmp(option, "nolocal")) { - rc = prte_schizo_base_add_qualifier(results, option, "map-by", "NOLOCAL", true); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_NOLOCAL, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --oversubscribe -> --map-by :OVERSUBSCRIBE */ else if (0 == strcmp(option, "oversubscribe")) { - rc = prte_schizo_base_add_qualifier(results, option, "map-by", "OVERSUBSCRIBE", true); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_OVERSUB, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --nooversubscribe -> --map-by :NOOVERSUBSCRIBE */ else if (0 == strcmp(option, "nooversubscribe")) { - rc = prte_schizo_base_add_qualifier(results, option, "map-by", "NOOVERSUBSCRIBE", true); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_NOOVER, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --use-hwthread-cpus -> --bind-to hwthread */ else if (0 == strcmp(option, "use-hwthread-cpus")) { - rc = prte_schizo_base_add_directive(results, option, "bind-to", "hwthread", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_BINDTO, PRTE_CLI_HWT, + prte_schizo_ompi_component.warn_deprecations); + PRTE_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")) { - prte_asprintf(&p2, "PE-LIST=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_PELIST, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_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, "bind-to", "core", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_BINDTO, PRTE_CLI_CORE, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "bind-to-socket")) { - rc = prte_schizo_base_add_directive(results, option, "bind-to", "socket", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_BINDTO, PRTE_CLI_PACKAGE, + prte_schizo_ompi_component.warn_deprecations); + PRTE_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, "map-by", "node", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_NODE, + prte_schizo_ompi_component.warn_deprecations); + PRTE_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, "map-by", "core", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_CORE, + prte_schizo_ompi_component.warn_deprecations); + PRTE_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, "map-by", "slot", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_SLOT, + prte_schizo_ompi_component.warn_deprecations); + PRTE_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")) { - prte_asprintf(&p2, ":pe=%s", opt->values[0]); - rc = prte_schizo_base_add_qualifier(results, option, "map-by", p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_PE, opt->values[0]); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* -N -> map-by ppr:N:node */ else if (0 == strcmp(option, "N")) { prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --npernode X and --npersocket X -> --map-by ppr:X:node/socket */ else if (0 == strcmp(option, "npernode")) { prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "pernode")) { - rc = prte_schizo_base_add_directive(results, option, "map-by", "ppr:1:node", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, "ppr:1:node", + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "npersocket")) { - prte_asprintf(&p2, "ppr:%s:socket", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + prte_asprintf(&p2, "ppr:%s:package", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --ppr X -> --map-by ppr:X */ else if (0 == strcmp(option, "ppr")) { @@ -418,103 +467,148 @@ static int convert_deprecated_cli(prte_cli_result_t *results) return PRTE_ERR_SILENT; } prte_asprintf(&p2, "ppr:%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_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, "tune", opt->values[0], true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_TUNE, opt->values[0], + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --rankfile X -> map-by rankfile:file=X */ else if (0 == strcmp(option, "rankfile")) { - prte_asprintf(&p2, "file=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "map-by", p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --tag-output -> "--output tag */ else if (0 == strcmp(option, "tag-output")) { - rc = prte_schizo_base_add_directive(results, option, "output", "tag", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, PRTE_CLI_TAG, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --timestamp-output -> --output timestamp */ else if (0 == strcmp(option, "timestamp-output")) { - rc = prte_schizo_base_add_directive(results, option, "output", "timestamp", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, PRTE_CLI_TIMESTAMP, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-directory DIR -> --output dir=DIR */ else if (0 == strcmp(option, "output-directory")) { - prte_asprintf(&p2, "dir=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "output", p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_QDIR, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-filename DIR -> --output file=file */ - else if (0 == strcmp(option, "--output-filename")) { - prte_asprintf(&p2, "file=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, "output", p2, true); + else if (0 == strcmp(option, "output-filename")) { + prte_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, p2, + prte_schizo_ompi_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --xml -> --output xml */ else if (0 == strcmp(option, "xml")) { - rc = prte_schizo_base_add_directive(results, option, "output", "xml", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, PRTE_CLI_XML, + prte_schizo_ompi_component.warn_deprecations); + PRTE_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, "display", "map-devel", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-proctable -> --display map-devel */ else if (0 == strcmp(option, "output-proctable")) { - rc = prte_schizo_base_add_directive(results, option, "display", "map-devel", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-map -> --display map */ else if (0 == strcmp(option, "display-map")) { - rc = prte_schizo_base_add_directive(results, option, "display", "map", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_MAP, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-topo -> --display topo */ else if (0 == strcmp(option, "display-topo")) { - rc = prte_schizo_base_add_directive(results, option, "display", "topo", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_TOPO, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --report-bindings -> --display bind */ else if (0 == strcmp(option, "report-bindings")) { - rc = prte_schizo_base_add_directive(results, option, "display", "bind", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_BIND, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-allocation -> --display allocation */ else if (0 == strcmp(option, "display-allocation")) { - rc = prte_schizo_base_add_directive(results, option, "display", "allocation", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_ALLOC, + prte_schizo_ompi_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --debug will be deprecated starting with open mpi v5 */ else if (0 == strcmp(option, "debug")) { - prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, - "This CLI option will be deprecated starting in Open MPI v5"); - } + if (prte_schizo_ompi_component.warn_deprecations) { + prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, + "This CLI option will be deprecated starting in Open MPI v5"); + } + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } /* --map-by socket -> --map-by package */ - else if (0 == strcmp(option, "map-by")) { + 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("package"); + tmp = strdup(PRTE_CLI_PACKAGE); } else { *p2 = '\0'; ++p2; - prte_asprintf(&tmp, "package:%s", p2); + prte_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); + } + if (prte_schizo_ompi_component.warn_deprecations) { + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(tmp2); + free(p2); } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); free(p1); - free(p2); - free(tmp2); free(opt->values[0]); opt->values[0] = tmp; } } /* --rank-by socket -> --rank-by package */ - else if (0 == strcmp(option, "--rank-by")) { + 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 @@ -527,44 +621,48 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); + if (prte_schizo_ompi_component.warn_deprecations) { + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_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(p2); - free(tmp2); free(opt->values[0]); opt->values[0] = tmp; } } /* --bind-to socket -> --bind-to package */ - else if (0 == strcmp(option, "--bind-to")) { + 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("package"); + tmp = strdup(PRTE_CLI_PACKAGE); } else { *p2 = '\0'; ++p2; - prte_asprintf(&tmp, "package:%s", p2); + prte_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); + } + if (prte_schizo_ompi_component.warn_deprecations) { + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(tmp2); + free(p2); } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); free(p1); - free(p2); - free(tmp2); free(opt->values[0]); opt->values[0] = tmp; } @@ -1726,6 +1824,29 @@ static void allow_run_as_root(prte_cli_result_t *results) prte_schizo_base_root_error_msg(); } +static int set_default_ranking(prte_job_t *jdata, + prte_schizo_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(prte_cli_result_t *results, void *jobinfo) { diff --git a/src/mca/schizo/ompi/schizo_ompi.h b/src/mca/schizo/ompi/schizo_ompi.h index 83020c8cd3..d442271214 100644 --- a/src/mca/schizo/ompi/schizo_ompi.h +++ b/src/mca/schizo/ompi/schizo_ompi.h @@ -3,7 +3,7 @@ * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +26,7 @@ BEGIN_C_DECLS typedef struct { prte_schizo_base_component_t super; int priority; + bool warn_deprecations; } prte_schizo_ompi_component_t; PRTE_MODULE_EXPORT extern prte_schizo_ompi_component_t prte_schizo_ompi_component; diff --git a/src/mca/schizo/ompi/schizo_ompi_component.c b/src/mca/schizo/ompi/schizo_ompi_component.c index 4ef71bdefd..3b17a53373 100644 --- a/src/mca/schizo/ompi/schizo_ompi_component.c +++ b/src/mca/schizo/ompi/schizo_ompi_component.c @@ -6,7 +6,7 @@ * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2020 Cisco Systems, Inc. All rights reserved - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -25,6 +25,7 @@ #include "src/mca/schizo/schizo.h" static int component_query(prte_mca_base_module_t **module, int *priority); +static int component_register(void); /* * Struct of function pointers and all that to let us be initialized @@ -37,15 +38,32 @@ prte_schizo_ompi_component_t prte_schizo_ompi_component = { PRTE_MCA_BASE_MAKE_VERSION(component, PRTE_MAJOR_VERSION, PRTE_MINOR_VERSION, PRTE_RELEASE_VERSION), .mca_query_component = component_query, + .mca_register_component_params = component_register, }, .base_data = { /* The component is checkpoint ready */ PRTE_MCA_BASE_METADATA_PARAM_CHECKPOINT }, }, - .priority = 50 + .priority = 50, + .warn_deprecations = false }; +static int component_register(void) +{ + prte_mca_base_component_t *c = &prte_schizo_ompi_component.super.base_version; + + prte_schizo_ompi_component.warn_deprecations = false; + (void) prte_mca_base_component_var_register(c, "warn_deprecations", + "Issue warnings about deprecated command line options", + PRTE_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, + PRTE_MCA_BASE_VAR_FLAG_NONE, PRTE_INFO_LVL_9, + PRTE_MCA_BASE_VAR_SCOPE_READONLY, + &prte_schizo_ompi_component.warn_deprecations); + + return PRTE_SUCCESS; +} + static int component_query(prte_mca_base_module_t **module, int *priority) { *module = (prte_mca_base_module_t *) &prte_schizo_ompi_module; diff --git a/src/mca/schizo/prte/schizo_prte.c b/src/mca/schizo/prte/schizo_prte.c index 8f37633362..5e625982c6 100644 --- a/src/mca/schizo/prte/schizo_prte.c +++ b/src/mca/schizo/prte/schizo_prte.c @@ -487,80 +487,126 @@ static int convert_deprecated_cli(prte_cli_result_t *results) { char *option, *p1, *p2, *tmp, *tmp2, *output, *modifier; int rc = PRTE_SUCCESS; - prte_cli_item_t *opt; + prte_cli_item_t *opt, *nxt; prte_value_t *pval, val; - PRTE_LIST_FOREACH(opt, &results->instances, prte_cli_item_t) { + PRTE_LIST_FOREACH_SAFE(opt, nxt, &results->instances, prte_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); + PRTE_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, "NOLOCAL", true); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_NOLOCAL, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "OVERSUBSCRIBE", true); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_OVERSUB, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "NOOVERSUBSCRIBE", true); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_NOOVER, + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --use-hwthread-cpus -> --bind-to hwthread */ else if (0 == strcmp(option, "use-hwthread-cpus")) { - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, "hwthread", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_BINDTO, PRTE_CLI_HWT, + prte_schizo_prte_component.warn_deprecations); + PRTE_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")) { - prte_asprintf(&p2, "PE-LIST=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_PELIST, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_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, "core", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_BINDTO, PRTE_CLI_CORE, + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "bind-to-socket")) { - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, "socket", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_BINDTO, PRTE_CLI_PACKAGE, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "node", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_NODE, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "core", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_CORE, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "slot", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, PRTE_CLI_SLOT, + prte_schizo_prte_component.warn_deprecations); + PRTE_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")) { - prte_asprintf(&p2, ":pe=%s", opt->values[0]); - rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_PE, opt->values[0]); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* -N -> map-by ppr:N:node */ else if (0 == strcmp(option, "N")) { prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --npernode X and --npersocket X -> --map-by ppr:X:node/socket */ else if (0 == strcmp(option, "npernode")) { prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_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", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, "ppr:1:node", + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "npersocket")) { - prte_asprintf(&p2, "ppr:%s:socket", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + prte_asprintf(&p2, "ppr:%s:package", opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --ppr X -> --map-by ppr:X */ else if (0 == strcmp(option, "ppr")) { @@ -570,72 +616,117 @@ static int convert_deprecated_cli(prte_cli_result_t *results) return PRTE_ERR_SILENT; } prte_asprintf(&p2, "ppr:%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_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], true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_TUNE, opt->values[0], + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --rankfile X -> map-by rankfile:file=X */ else if (0 == strcmp(option, "rankfile")) { - prte_asprintf(&p2, "file=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, true); + prte_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_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, "tag", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, PRTE_CLI_TAG, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "timestamp", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, PRTE_CLI_TIMESTAMP, + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-directory DIR -> --output dir=DIR */ else if (0 == strcmp(option, "output-directory")) { prte_asprintf(&p2, "dir=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-filename DIR -> --output file=file */ else if (0 == strcmp(option, "--output-filename")) { prte_asprintf(&p2, "file=%s", opt->values[0]); - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, p2, + prte_schizo_prte_component.warn_deprecations); free(p2); + PRTE_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, "xml", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, PRTE_CLI_XML, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "map-devel", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-proctable -> --display map-devel */ else if (0 == strcmp(option, "output-proctable")) { - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "map-devel", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "map", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_MAP, + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-topo -> --display topo */ else if (0 == strcmp(option, "display-topo")) { - rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, "topo", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_TOPO, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "bind", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_BIND, + prte_schizo_prte_component.warn_deprecations); + PRTE_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, "allocation", true); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_DISPLAY, PRTE_CLI_ALLOC, + prte_schizo_prte_component.warn_deprecations); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --debug will be deprecated starting with open mpi v5 */ else if (0 == strcmp(option, "debug")) { - prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, - "This CLI option will be deprecated starting in Open MPI v5"); + if (prte_schizo_prte_component.warn_deprecations) { + prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, + "This CLI option will be deprecated starting in Open MPI v5"); + } + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --map-by socket -> --map-by package */ else if (0 == strcmp(option, PRTE_CLI_MAPBY)) { @@ -651,16 +742,18 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); + if (prte_schizo_prte_component.warn_deprecations) { + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p2); + free(tmp2); + } free(p1); - free(p2); - free(tmp2); free(opt->values[0]); opt->values[0] = tmp; } @@ -679,16 +772,18 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); + if (prte_schizo_prte_component.warn_deprecations) { + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p2); + free(tmp2); + } free(p1); - free(p2); - free(tmp2); free(opt->values[0]); opt->values[0] = tmp; } @@ -707,16 +802,18 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - prte_asprintf(&p2, "%s %s", option, p1); - prte_asprintf(&tmp2, "%s %s", option, tmp); - /* can't just call show_help as we want every instance to be reported */ - output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, - tmp2); - fprintf(stderr, "%s\n", output); - free(output); + if (prte_schizo_prte_component.warn_deprecations) { + prte_asprintf(&p2, "%s %s", option, p1); + prte_asprintf(&tmp2, "%s %s", option, tmp); + /* can't just call show_help as we want every instance to be reported */ + output = prte_show_help_string("help-schizo-base.txt", "deprecated-converted", true, p2, + tmp2); + fprintf(stderr, "%s\n", output); + free(output); + free(p2); + free(tmp2); + } free(p1); - free(p2); - free(tmp2); free(opt->values[0]); opt->values[0] = tmp; } diff --git a/src/mca/schizo/prte/schizo_prte.h b/src/mca/schizo/prte/schizo_prte.h index d12f5e6074..8e2a0aa6ee 100644 --- a/src/mca/schizo/prte/schizo_prte.h +++ b/src/mca/schizo/prte/schizo_prte.h @@ -26,6 +26,7 @@ BEGIN_C_DECLS typedef struct { prte_schizo_base_component_t super; int priority; + bool warn_deprecations; } prte_schizo_prte_component_t; PRTE_MODULE_EXPORT extern prte_schizo_prte_component_t prte_schizo_prte_component; diff --git a/src/mca/schizo/prte/schizo_prte_component.c b/src/mca/schizo/prte/schizo_prte_component.c index afcd30d153..5e427b9833 100644 --- a/src/mca/schizo/prte/schizo_prte_component.c +++ b/src/mca/schizo/prte/schizo_prte_component.c @@ -25,6 +25,7 @@ #include "src/mca/schizo/schizo.h" static int component_query(prte_mca_base_module_t **module, int *priority); +static int component_register(void); /* * Struct of function pointers and all that to let us be initialized @@ -37,15 +38,32 @@ prte_schizo_prte_component_t prte_schizo_prte_component = { PRTE_MCA_BASE_MAKE_VERSION(component, PRTE_MAJOR_VERSION, PRTE_MINOR_VERSION, PRTE_RELEASE_VERSION), .mca_query_component = component_query, + .mca_register_component_params = component_register, }, .base_data = { /* The component is checkpoint ready */ PRTE_MCA_BASE_METADATA_PARAM_CHECKPOINT }, }, - .priority = 5 + .priority = 5, + .warn_deprecations = true }; +static int component_register(void) +{ + prte_mca_base_component_t *c = &prte_schizo_prte_component.super.base_version; + + prte_schizo_prte_component.warn_deprecations = true; + (void) prte_mca_base_component_var_register(c, "warn_deprecations", + "Issue warnings about deprecated command line options", + PRTE_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, + PRTE_MCA_BASE_VAR_FLAG_NONE, PRTE_INFO_LVL_9, + PRTE_MCA_BASE_VAR_SCOPE_READONLY, + &prte_schizo_prte_component.warn_deprecations); + + return PRTE_SUCCESS; +} + static int component_query(prte_mca_base_module_t **module, int *priority) { *module = (prte_mca_base_module_t *) &prte_schizo_prte_module; diff --git a/src/mca/schizo/schizo.h b/src/mca/schizo/schizo.h index 7cc940d7d5..5fed3692ec 100644 --- a/src/mca/schizo/schizo.h +++ b/src/mca/schizo/schizo.h @@ -38,6 +38,14 @@ BEGIN_C_DECLS typedef int (*prte_schizo_convertor_fn_t)(char *option, char ***argv, int idx); +typedef struct { + pmix_rank_t nprocs; + uint16_t cpus_per_rank; + bool use_hwthreads; + int stream; + int verbosity; +} prte_schizo_options_t; + /* * schizo module functions */ @@ -75,6 +83,16 @@ typedef int (*prte_schizo_base_module_parse_env_fn_t)(char **srcenv, /* check if running as root is allowed in this environment */ typedef void (*prte_schizo_base_module_allow_run_as_root_fn_t)(prte_cli_result_t *results); +/* Set the default mapping policy for a job */ +typedef int (*prte_schizo_base_module_set_default_mapping_fn_t)(prte_job_t *jdata, + prte_schizo_options_t *options); + +typedef int (*prte_schizo_base_module_set_default_ranking_fn_t)(prte_job_t *jdata, + prte_schizo_options_t *options); + +typedef int (*prte_schizo_base_module_set_default_binding_fn_t)(prte_job_t *jdata, + prte_schizo_options_t *options); + /* do whatever preparation work * is required to setup the app for execution. This is intended to be * used by prun and other launcher tools to, for example, change @@ -100,15 +118,18 @@ typedef void (*prte_schizo_base_module_job_info_fn_t)(prte_cli_result_t *results */ typedef struct { char *name; - prte_schizo_base_module_init_fn_t init; - prte_schizo_base_module_parse_cli_fn_t parse_cli; - prte_schizo_base_module_parse_env_fn_t parse_env; - prte_schizo_base_detect_proxy_fn_t detect_proxy; - prte_schizo_base_module_allow_run_as_root_fn_t allow_run_as_root; - prte_schizo_base_module_setup_app_fn_t setup_app; - prte_schizo_base_module_setup_fork_fn_t setup_fork; - prte_schizo_base_module_job_info_fn_t job_info; - prte_schizo_base_module_finalize_fn_t finalize; + prte_schizo_base_module_init_fn_t init; + prte_schizo_base_module_parse_cli_fn_t parse_cli; + prte_schizo_base_module_parse_env_fn_t parse_env; + prte_schizo_base_detect_proxy_fn_t detect_proxy; + prte_schizo_base_module_allow_run_as_root_fn_t allow_run_as_root; + prte_schizo_base_module_set_default_mapping_fn_t set_default_mapping; + prte_schizo_base_module_set_default_ranking_fn_t set_default_ranking; + prte_schizo_base_module_set_default_binding_fn_t set_default_binding; + prte_schizo_base_module_setup_app_fn_t setup_app; + prte_schizo_base_module_setup_fork_fn_t setup_fork; + prte_schizo_base_module_job_info_fn_t job_info; + prte_schizo_base_module_finalize_fn_t finalize; } prte_schizo_base_module_t; /* diff --git a/src/prted/pmix/pmix_server_dyn.c b/src/prted/pmix/pmix_server_dyn.c index 9dbb68b400..b1e0ec333e 100644 --- a/src/prted/pmix/pmix_server_dyn.c +++ b/src/prted/pmix/pmix_server_dyn.c @@ -18,7 +18,7 @@ * All rights reserved. * Copyright (c) 2014-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2021 Nanook Consulting. All rights reserved. + * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -44,6 +44,7 @@ #include "src/mca/errmgr/errmgr.h" #include "src/mca/rmaps/base/base.h" #include "src/mca/rml/rml.h" +#include "src/mca/schizo/base/base.h" #include "src/mca/state/state.h" #include "src/runtime/prte_globals.h" #include "src/threads/threads.h" diff --git a/src/util/cmd_line.h b/src/util/cmd_line.h index a8b8fc890b..9c7e1b2e11 100644 --- a/src/util/cmd_line.h +++ b/src/util/cmd_line.h @@ -258,6 +258,7 @@ PRTE_CLASS_DECLARATION(prte_cli_result_t); #define PRTE_CLI_NOLAUNCH "donotlaunch" #define PRTE_CLI_FILL "fill" #define PRTE_CLI_OVERLOAD "overload-allowed" +#define PRTE_CLI_NOOVERLOAD "no-overload" #define PRTE_CLI_IF_SUPP "if-supported" #define PRTE_CLI_ORDERED "ordered" #define PRTE_CLI_REPORT "report" @@ -331,6 +332,26 @@ static inline char* prte_cmd_line_get_nth_instance(prte_cli_result_t *results, return opt->values[idx]; } +#define PRTE_CLI_DEBUG_LIST(r) \ +do { \ + prte_cli_item_t *_c; \ + prte_output(0, "\n[%s:%s:%d]", __FILE__, __func__, __LINE__); \ + PRTE_LIST_FOREACH(_c, &(r)->instances, prte_cli_item_t) { \ + prte_output(0, "KEY: %s", _c->key); \ + if (NULL != _c->values) { \ + for (int _n=0; NULL != _c->values[_n]; _n++) { \ + prte_output(0, " VAL[%d]: %s", _n, _c->values[_n]); \ + } \ + } \ + } \ + prte_output(0, "\n"); \ +} while(0) + +#define PRTE_CLI_REMOVE_DEPRECATED(r, o) \ +do { \ + prte_list_remove_item(&(r)->instances, &(o)->super); \ + PRTE_RELEASE(o); \ +} while(0) END_C_DECLS #endif /* PRTE_CMD_LINE_H */ From 8f20eb4b8b20a66440131dc8b61c0924228772c0 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Thu, 13 Jan 2022 14:59:58 -0800 Subject: [PATCH 3/7] Silence multiple output of deprecation warnings Only output them once, when we first parse the command line. Applications submitted via PMIx_Spawn should not generate warnings Signed-off-by: Ralph Castain --- src/mca/schizo/ompi/schizo_ompi.c | 84 +++++++++++++++++------------- src/mca/schizo/prte/schizo_prte.c | 86 +++++++++++++++++-------------- src/mca/schizo/schizo.h | 3 +- src/prted/prte_app_parse.c | 2 +- src/tools/prte/prte.c | 2 +- src/tools/prte_info/prte_info.c | 2 +- src/tools/prted/prted.c | 2 +- src/tools/prun/prun.c | 2 +- src/tools/pterm/pterm.c | 2 +- src/util/cmd_line.h | 5 ++ 10 files changed, 108 insertions(+), 82 deletions(-) diff --git a/src/mca/schizo/ompi/schizo_ompi.c b/src/mca/schizo/ompi/schizo_ompi.c index 9695fde5d0..c31e154cfb 100644 --- a/src/mca/schizo/ompi/schizo_ompi.c +++ b/src/mca/schizo/ompi/schizo_ompi.c @@ -59,7 +59,7 @@ #include "schizo_ompi.h" #include "src/mca/schizo/base/base.h" -static int parse_cli(char **argv, prte_cli_result_t *results); +static int parse_cli(char **argv, prte_cli_result_t *results, bool silent); static int detect_proxy(char *argv); static int parse_env(char **srcenv, char ***dstenv, prte_cli_result_t *cli); static void allow_run_as_root(prte_cli_result_t *results); @@ -232,9 +232,11 @@ static struct option ompioptions[] = { }; static char *ompishorts = "h::vVpn:c:N:sH:x:"; -static int convert_deprecated_cli(prte_cli_result_t *results); +static int convert_deprecated_cli(prte_cli_result_t *results, + bool silent); -static int parse_cli(char **argv, prte_cli_result_t *results) +static int parse_cli(char **argv, prte_cli_result_t *results, + bool silent) { int rc, n; prte_cli_item_t *opt; @@ -283,7 +285,7 @@ static int parse_cli(char **argv, prte_cli_result_t *results) } /* check for deprecated options - warn and convert them */ - rc = convert_deprecated_cli(results); + rc = convert_deprecated_cli(results, silent); if (PRTE_SUCCESS != rc) { return rc; } @@ -334,12 +336,20 @@ static int parse_cli(char **argv, prte_cli_result_t *results) return PRTE_SUCCESS; }; -static int convert_deprecated_cli(prte_cli_result_t *results) +static int convert_deprecated_cli(prte_cli_result_t *results, + bool silent) { char *option, *p1, *p2, *tmp, *tmp2, *output, *modifier; int rc = PRTE_SUCCESS; prte_cli_item_t *opt, *nxt; prte_value_t *pval, val; + bool warn; + + if (silent) { + warn = false; + } else { + warn = prte_schizo_ompi_component.warn_deprecations; + } PRTE_LIST_FOREACH_SAFE(opt, nxt, &results->instances, prte_cli_item_t) { option = opt->key; @@ -353,28 +363,28 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "nolocal")) { rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, PRTE_CLI_NOLOCAL, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --use-hwthread-cpus -> --bind-to hwthread */ else if (0 == strcmp(option, "use-hwthread-cpus")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, PRTE_CLI_HWT, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --cpu-set and --cpu-list -> --map-by pe-list:X @@ -383,7 +393,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_PELIST, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -391,33 +401,33 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "bind-to-core")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, PRTE_CLI_CORE, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --cpus-per-proc/rank X -> --map-by :pe=X */ @@ -425,7 +435,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_PE, opt->values[0]); rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -434,7 +444,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -443,19 +453,19 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_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", - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "npersocket")) { prte_asprintf(&p2, "ppr:%s:package", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -469,7 +479,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "ppr:%s", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -477,7 +487,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "amca") || 0 == strcmp(option, "am")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_TUNE, opt->values[0], - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --rankfile X -> map-by rankfile:file=X */ @@ -491,14 +501,14 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "tag-output")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_TAG, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-directory DIR -> --output dir=DIR */ @@ -506,7 +516,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_QDIR, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -515,7 +525,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, - prte_schizo_ompi_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -523,55 +533,55 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "xml")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_XML, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-proctable -> --display map-devel */ else if (0 == strcmp(option, "output-proctable")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-topo -> --display topo */ else if (0 == strcmp(option, "display-topo")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_TOPO, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_ompi_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --debug will be deprecated starting with open mpi v5 */ else if (0 == strcmp(option, "debug")) { - if (prte_schizo_ompi_component.warn_deprecations) { + if (warn) { prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, "This CLI option will be deprecated starting in Open MPI v5"); } @@ -591,7 +601,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); } - if (prte_schizo_ompi_component.warn_deprecations) { + if (warn) { prte_asprintf(&p2, "%s %s", option, p1); prte_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ @@ -621,7 +631,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - if (prte_schizo_ompi_component.warn_deprecations) { + if (warn) { prte_asprintf(&p2, "%s %s", option, p1); prte_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ @@ -651,7 +661,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); } - if (prte_schizo_ompi_component.warn_deprecations) { + if (warn) { prte_asprintf(&p2, "%s %s", option, p1); prte_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ diff --git a/src/mca/schizo/prte/schizo_prte.c b/src/mca/schizo/prte/schizo_prte.c index 5e625982c6..9b11135a27 100644 --- a/src/mca/schizo/prte/schizo_prte.c +++ b/src/mca/schizo/prte/schizo_prte.c @@ -57,7 +57,7 @@ #include "schizo_prte.h" #include "src/mca/schizo/base/base.h" -static int parse_cli(char **argv, prte_cli_result_t *results); +static int parse_cli(char **argv, prte_cli_result_t *results, bool silent); static int detect_proxy(char *argv); static int parse_env(char **srcenv, char ***dstenv, prte_cli_result_t *cli); static void allow_run_as_root(prte_cli_result_t *results); @@ -422,9 +422,11 @@ static struct option pinfooptions[] = { }; static char *pinfoshorts = "hVac"; -static int convert_deprecated_cli(prte_cli_result_t *results); +static int convert_deprecated_cli(prte_cli_result_t *results, + bool silent); -static int parse_cli(char **argv, prte_cli_result_t *results) +static int parse_cli(char **argv, prte_cli_result_t *results, + bool silent) { char *shorts, *helpfile; struct option *myoptions; @@ -463,7 +465,7 @@ static int parse_cli(char **argv, prte_cli_result_t *results) } /* check for deprecated options - warn and convert them */ - rc = convert_deprecated_cli(results); + rc = convert_deprecated_cli(results, silent); if (PRTE_SUCCESS != rc) { return rc; } @@ -483,12 +485,20 @@ static int parse_cli(char **argv, prte_cli_result_t *results) return PRTE_SUCCESS; }; -static int convert_deprecated_cli(prte_cli_result_t *results) +static int convert_deprecated_cli(prte_cli_result_t *results, + bool silent) { char *option, *p1, *p2, *tmp, *tmp2, *output, *modifier; int rc = PRTE_SUCCESS; prte_cli_item_t *opt, *nxt; prte_value_t *pval, val; + bool warn; + + if (silent) { + warn = false; + } else { + warn = prte_schizo_prte_component.warn_deprecations; + } PRTE_LIST_FOREACH_SAFE(opt, nxt, &results->instances, prte_cli_item_t) { option = opt->key; @@ -502,28 +512,28 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "nolocal")) { rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, PRTE_CLI_NOLOCAL, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --use-hwthread-cpus -> --bind-to hwthread */ else if (0 == strcmp(option, "use-hwthread-cpus")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, PRTE_CLI_HWT, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --cpu-set and --cpu-list -> --map-by pe-list:X @@ -532,7 +542,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_PELIST, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -540,33 +550,33 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "bind-to-core")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_BINDTO, PRTE_CLI_CORE, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --cpus-per-proc/rank X -> --map-by :pe=X */ @@ -574,7 +584,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_PE, opt->values[0]); rc = prte_schizo_base_add_qualifier(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -583,7 +593,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -592,19 +602,19 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "ppr:%s:node", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_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", - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } else if (0 == strcmp(option, "npersocket")) { prte_asprintf(&p2, "ppr:%s:package", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -618,7 +628,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "ppr:%s", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -626,7 +636,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "amca") || 0 == strcmp(option, "am")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_TUNE, opt->values[0], - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --rankfile X -> map-by rankfile:file=X */ @@ -634,7 +644,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_MAPBY, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -642,14 +652,14 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "tag-output")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_TAG, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-directory DIR -> --output dir=DIR */ @@ -657,7 +667,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "dir=%s", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -666,7 +676,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) prte_asprintf(&p2, "file=%s", opt->values[0]); rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, p2, - prte_schizo_prte_component.warn_deprecations); + warn); free(p2); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } @@ -674,55 +684,55 @@ static int convert_deprecated_cli(prte_cli_result_t *results) else if (0 == strcmp(option, "xml")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_OUTPUT, PRTE_CLI_XML, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --output-proctable -> --display map-devel */ else if (0 == strcmp(option, "output-proctable")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_MAPDEV, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --display-topo -> --display topo */ else if (0 == strcmp(option, "display-topo")) { rc = prte_schizo_base_add_directive(results, option, PRTE_CLI_DISPLAY, PRTE_CLI_TOPO, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_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, - prte_schizo_prte_component.warn_deprecations); + warn); PRTE_CLI_REMOVE_DEPRECATED(results, opt); } /* --debug will be deprecated starting with open mpi v5 */ else if (0 == strcmp(option, "debug")) { - if (prte_schizo_prte_component.warn_deprecations) { + if (warn) { prte_show_help("help-schizo-base.txt", "deprecated-inform", true, option, "This CLI option will be deprecated starting in Open MPI v5"); } @@ -742,7 +752,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - if (prte_schizo_prte_component.warn_deprecations) { + if (warn) { prte_asprintf(&p2, "%s %s", option, p1); prte_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ @@ -772,7 +782,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - if (prte_schizo_prte_component.warn_deprecations) { + if (warn) { prte_asprintf(&p2, "%s %s", option, p1); prte_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ @@ -802,7 +812,7 @@ static int convert_deprecated_cli(prte_cli_result_t *results) ++p2; prte_asprintf(&tmp, "package:%s", p2); } - if (prte_schizo_prte_component.warn_deprecations) { + if (warn) { prte_asprintf(&p2, "%s %s", option, p1); prte_asprintf(&tmp2, "%s %s", option, tmp); /* can't just call show_help as we want every instance to be reported */ diff --git a/src/mca/schizo/schizo.h b/src/mca/schizo/schizo.h index 5fed3692ec..92e6baf960 100644 --- a/src/mca/schizo/schizo.h +++ b/src/mca/schizo/schizo.h @@ -61,7 +61,8 @@ typedef int (*prte_schizo_base_module_init_fn_t)(void); /* parse a tool command line */ typedef int (*prte_schizo_base_module_parse_cli_fn_t)(char **argv, - prte_cli_result_t *results); + prte_cli_result_t *results, + bool silent); /* detect if we are running as a proxy * Check the environment to determine what, if any, host we are running diff --git a/src/prted/prte_app_parse.c b/src/prted/prte_app_parse.c index 288af1b705..dfc601bed5 100644 --- a/src/prted/prte_app_parse.c +++ b/src/prted/prte_app_parse.c @@ -97,7 +97,7 @@ static int create_app(prte_schizo_base_module_t *schizo, char **argv, prte_list_ /* parse the cmd line - do this every time thru so we can * repopulate the globals */ PRTE_CONSTRUCT(&results, prte_cli_result_t); - rc = schizo->parse_cli(argv, &results); + rc = schizo->parse_cli(argv, &results, PRTE_CLI_SILENT); if (PRTE_SUCCESS != rc) { if (PRTE_ERR_SILENT != rc) { fprintf(stderr, "%s: command line error (%s)\n", argv[0], prte_strerror(rc)); diff --git a/src/tools/prte/prte.c b/src/tools/prte/prte.c index 2196b530e5..8baa3b869e 100644 --- a/src/tools/prte/prte.c +++ b/src/tools/prte/prte.c @@ -392,7 +392,7 @@ int main(int argc, char *argv[]) /* parse the input argv to get values, including everyone's MCA params */ PRTE_CONSTRUCT(&results, prte_cli_result_t); - rc = schizo->parse_cli(pargv, &results); + rc = schizo->parse_cli(pargv, &results, PRTE_CLI_WARN); if (PRTE_SUCCESS != rc) { PRTE_DESTRUCT(&results); if (PRTE_ERR_SILENT != rc) { diff --git a/src/tools/prte_info/prte_info.c b/src/tools/prte_info/prte_info.c index 64f40ec054..1d073e54c5 100644 --- a/src/tools/prte_info/prte_info.c +++ b/src/tools/prte_info/prte_info.c @@ -142,7 +142,7 @@ int main(int argc, char *argv[]) /* parse the input argv to get values, including everyone's MCA params */ PRTE_CONSTRUCT(&prte_info_cmd_line, prte_cli_result_t); - ret = schizo->parse_cli(argv, &prte_info_cmd_line); + ret = schizo->parse_cli(argv, &prte_info_cmd_line, PRTE_CLI_SILENT); if (PRTE_SUCCESS != ret) { PRTE_DESTRUCT(&prte_info_cmd_line); if (PRTE_ERR_SILENT != ret) { diff --git a/src/tools/prted/prted.c b/src/tools/prted/prted.c index 94242a5175..33ff18e30e 100644 --- a/src/tools/prted/prted.c +++ b/src/tools/prted/prted.c @@ -283,7 +283,7 @@ int main(int argc, char *argv[]) /* parse the CLI to load the MCA params */ PRTE_CONSTRUCT(&results, prte_cli_result_t); - ret = schizo->parse_cli(pargv, &results); + ret = schizo->parse_cli(pargv, &results, PRTE_CLI_SILENT); if (PRTE_SUCCESS != ret) { if (PRTE_ERR_SILENT != ret) { fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, diff --git a/src/tools/prun/prun.c b/src/tools/prun/prun.c index 66e16aea41..8887984f4a 100644 --- a/src/tools/prun/prun.c +++ b/src/tools/prun/prun.c @@ -413,7 +413,7 @@ int prun(int argc, char *argv[]) /* parse the input argv to get values, including everyone's MCA params */ PRTE_CONSTRUCT(&results, prte_cli_result_t); - rc = schizo->parse_cli(pargv, &results); + rc = schizo->parse_cli(pargv, &results, PRTE_CLI_WARN); if (PRTE_SUCCESS != rc) { PRTE_DESTRUCT(&results); if (PRTE_ERR_SILENT != rc) { diff --git a/src/tools/pterm/pterm.c b/src/tools/pterm/pterm.c index 80e55d281d..f41dd027bb 100644 --- a/src/tools/pterm/pterm.c +++ b/src/tools/pterm/pterm.c @@ -285,7 +285,7 @@ int main(int argc, char *argv[]) return 1; } - rc = schizo->parse_cli(argv, &results); + rc = schizo->parse_cli(argv, &results, PRTE_CLI_WARN); if (PRTE_SUCCESS != rc) { PRTE_DESTRUCT(&results); if (PRTE_ERR_SILENT != rc) { diff --git a/src/util/cmd_line.h b/src/util/cmd_line.h index 9c7e1b2e11..559f2a0de4 100644 --- a/src/util/cmd_line.h +++ b/src/util/cmd_line.h @@ -68,6 +68,11 @@ PRTE_CLASS_DECLARATION(prte_cli_result_t); #define PRTE_ARG_NONE no_argument #define PRTE_ARG_OPTIONAL optional_argument +/* define PRTE-named flags for whether parsing + * CLI shall include deprecation warnings */ +#define PRTE_CLI_SILENT true +#define PRTE_CLI_WARN false + /* define a long option that has no short option equivalent * * n = name of the option (see below for definitions) From cb7b061aaf9c2b6c9536fa9552b5b961b1221373 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Thu, 13 Jan 2022 15:57:56 -0800 Subject: [PATCH 4/7] Silence warning Signed-off-by: Ralph Castain --- src/hwloc/hwloc.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/hwloc/hwloc.c b/src/hwloc/hwloc.c index ccace9d0ab..76784194fd 100644 --- a/src/hwloc/hwloc.c +++ b/src/hwloc/hwloc.c @@ -302,8 +302,7 @@ void prte_hwloc_base_close(void) prte_hwloc_base_inited = false; } -int prte_hwloc_base_set_default_binding(void *jd, - void *opt) +int prte_hwloc_base_set_default_binding(void *jd, void *opt) { prte_job_t *jdata = (prte_job_t*)jd; prte_schizo_options_t *options = (prte_schizo_options_t*)opt; @@ -320,7 +319,7 @@ int prte_hwloc_base_set_default_binding(void *jd, } else { /* bind to core */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bycore", __LINE__); + "setdefaultbinding[%d] binding not given - using bycore", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); } } else { @@ -330,32 +329,32 @@ int prte_hwloc_base_set_default_binding(void *jd, if (PRTE_MAPPING_GIVEN & PRTE_GET_MAPPING_DIRECTIVE(jdata->map->mapping)) { if (PRTE_MAPPING_BYHWTHREAD == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using byhwthread", __LINE__); + "setdefaultbinding[%d] binding not given - using byhwthread", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); } else if (PRTE_MAPPING_BYCORE == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bycore", __LINE__); + "setdefaultbinding[%d] binding not given - using bycore", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); } else if (PRTE_MAPPING_BYL1CACHE == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using byL1", __LINE__); + "setdefaultbinding[%d] binding not given - using byL1", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L1CACHE); } else if (PRTE_MAPPING_BYL2CACHE == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using byL2", __LINE__); + "setdefaultbinding[%d] binding not given - using byL2", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L2CACHE); } else if (PRTE_MAPPING_BYL3CACHE == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using byL3", __LINE__); + "setdefaultbinding[%d] binding not given - using byL3", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_L3CACHE); } else if (PRTE_MAPPING_BYNUMA == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bynuma", + "setdefaultbinding[%d] binding not given - using bynuma", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); } else if (PRTE_MAPPING_BYPACKAGE == mpol) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bypackage", __LINE__); + "setdefaultbinding[%d] binding not given - using bypackage", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); } else { /* we are mapping by node or some other non-object method */ @@ -363,13 +362,13 @@ int prte_hwloc_base_set_default_binding(void *jd, if (options->use_hwthreads) { /* if we are using hwthread cpus, then bind to those */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using byhwthread", __LINE__); + "setdefaultbinding[%d] binding not given - using byhwthread", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); } else { /* for performance, bind to core */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bycore", __LINE__); + "setdefaultbinding[%d] binding not given - using bycore", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); } @@ -377,16 +376,16 @@ int prte_hwloc_base_set_default_binding(void *jd, /* bind to numa (if present), or by package (if numa isn't present and package is) */ if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bynuma", __LINE__); + "setdefaultbinding[%d] binding not given - using bynuma", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bypackage", __LINE__); + "setdefaultbinding[%d] binding not given - using bypackage", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); } else { /* if we have neither, then just don't bind */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given and no NUMA " + "setdefaultbinding[%d] binding not given and no NUMA " "or packages - not binding", __LINE__); PRTE_SET_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NONE); @@ -397,13 +396,13 @@ int prte_hwloc_base_set_default_binding(void *jd, if (options->use_hwthreads) { /* if we are using hwthread cpus, then bind to those */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using byhwthread", + "setdefaultbinding[%d] binding not given - using byhwthread", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_HWTHREAD); } else { /* for performance, bind to core */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bycore", + "setdefaultbinding[%d] binding not given - using bycore", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_CORE); } @@ -411,18 +410,18 @@ int prte_hwloc_base_set_default_binding(void *jd, /* for performance, bind to numa, if available, else try package */ if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bynuma", + "setdefaultbinding[%d] binding not given - using bynuma", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NUMA); } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given - using bypackage", + "setdefaultbinding[%d] binding not given - using bypackage", __LINE__); PRTE_SET_DEFAULT_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_PACKAGE); } else { /* just don't bind */ prte_output_verbose(options->verbosity, options->stream, - "mca:rmaps[%d] binding not given and no packages - not binding", + "setdefaultbinding[%d] binding not given and no packages - not binding", __LINE__); PRTE_SET_BINDING_POLICY(jdata->map->binding, PRTE_BIND_TO_NONE); } @@ -435,6 +434,7 @@ int prte_hwloc_base_set_default_binding(void *jd, jdata->map->binding |= PRTE_BIND_ALLOW_OVERLOAD; } } + return PRTE_SUCCESS; } static bool fns_init = false; From 11e490bb0a444553d854b4d85c620002afa06d15 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Tue, 25 Jan 2022 18:16:39 -0800 Subject: [PATCH 5/7] Ensure the cmd lien parser exits when it hits the application name Don't look at the app's arguments Signed-off-by: Ralph Castain --- src/mca/schizo/ompi/schizo_ompi.c | 76 +++++++++++++++++++------------ src/util/cmd_line.c | 7 ++- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/mca/schizo/ompi/schizo_ompi.c b/src/mca/schizo/ompi/schizo_ompi.c index c31e154cfb..eb6e268868 100644 --- a/src/mca/schizo/ompi/schizo_ompi.c +++ b/src/mca/schizo/ompi/schizo_ompi.c @@ -241,45 +241,50 @@ static int parse_cli(char **argv, prte_cli_result_t *results, int rc, n; prte_cli_item_t *opt; char *p1; + char **pargv; + + /* backup the argv */ + pargv = prte_argv_copy(argv); /* handle the non-compliant options - i.e., the single-dash * multi-character options mandated by the MPI standard */ - for (n=0; NULL != argv[n]; n++) { - if (0 == strcmp(argv[n], "-soft")) { - free(argv[n]); - argv[n] = strdup("--soft"); - } else if (0 == strcmp(argv[n], "-host")) { - free(argv[n]); - argv[n] = strdup("--host"); - } else if (0 == strcmp(argv[n], "-arch")) { - free(argv[n]); - argv[n] = strdup("--arch"); - } else if (0 == strcmp(argv[n], "-wdir")) { - free(argv[n]); - argv[n] = strdup("--wdir"); - } else if (0 == strcmp(argv[n], "-path")) { - free(argv[n]); - argv[n] = strdup("--path"); - } else if (0 == strcmp(argv[n], "-file")) { - free(argv[n]); - argv[n] = strdup("--file"); - } else if (0 == strcmp(argv[n], "-initial-errhandler")) { - free(argv[n]); - argv[n] = strdup("--initial-errhandler"); - } else if (0 == strcmp(argv[n], "-np")) { - free(argv[n]); - argv[n] = strdup("--np"); + for (n=0; NULL != pargv[n]; n++) { + if (0 == strcmp(pargv[n], "-soft")) { + free(pargv[n]); + pargv[n] = strdup("--soft"); + } else if (0 == strcmp(pargv[n], "-host")) { + free(pargv[n]); + pargv[n] = strdup("--host"); + } else if (0 == strcmp(pargv[n], "-arch")) { + free(pargv[n]); + pargv[n] = strdup("--arch"); + } else if (0 == strcmp(pargv[n], "-wdir")) { + free(pargv[n]); + pargv[n] = strdup("--wdir"); + } else if (0 == strcmp(pargv[n], "-path")) { + free(pargv[n]); + pargv[n] = strdup("--path"); + } else if (0 == strcmp(pargv[n], "-file")) { + free(pargv[n]); + pargv[n] = strdup("--file"); + } else if (0 == strcmp(pargv[n], "-initial-errhandler")) { + free(pargv[n]); + pargv[n] = strdup("--initial-errhandler"); + } else if (0 == strcmp(pargv[n], "-np")) { + free(pargv[n]); + pargv[n] = strdup("--np"); } #if PRTE_ENABLE_FT - else if (0 == strcmp(argv[n], "-with-ft")) { - free(argv[n]); - argv[n] = strdup("--with-ft"); + else if (0 == strcmp(pargv[n], "-with-ft")) { + free(pargv[n]); + pargv[n] = strdup("--with-ft"); } #endif } - rc = prte_cmd_line_parse(argv, ompishorts, ompioptions, NULL, + rc = prte_cmd_line_parse(pargv, ompishorts, ompioptions, NULL, results, "help-schizo-ompi.txt"); + prte_argv_free(pargv); if (PRTE_SUCCESS != rc) { return rc; } @@ -333,6 +338,19 @@ static int parse_cli(char **argv, prte_cli_result_t *results, } } + 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 */ + prte_argv_free(results->tail); + results->tail = prte_argv_copy(&argv[n]); + break; + } + } + } + return PRTE_SUCCESS; }; diff --git a/src/util/cmd_line.c b/src/util/cmd_line.c index e68254f7cd..d3eb3f1785 100644 --- a/src/util/cmd_line.c +++ b/src/util/cmd_line.c @@ -92,7 +92,7 @@ int prte_cmd_line_parse(char **pargv, char *shorts, char *helpfile) { int option_index = 0; /* getopt_long stores the option index here. */ - int n, opt, argc, rc; + int n, opt, argc, rc, argind; bool found; char *ptr, *str, c, **argv; prte_cmd_line_store_fn_t mystore; @@ -118,6 +118,7 @@ int prte_cmd_line_parse(char **pargv, char *shorts, // run the parser while (1) { + argind = optind; opt = getopt_long(argc, argv, shorts, myoptions, &option_index); if (-1 == opt) { break; @@ -264,6 +265,10 @@ int prte_cmd_line_parse(char **pargv, char *shorts, default: /* this could be one of the short options other than 'h' or 'V', so * we have to check */ + if ('-' != argv[argind][0]) { + // this was not an option + break; + } found = false; for (n=0; '\0' != shorts[n]; n++) { int ascii = shorts[n]; From 0c85702ed2f035065a196d2c13e55fb3b2c77ff7 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Wed, 2 Feb 2022 08:53:14 -0800 Subject: [PATCH 6/7] Address review comments Signed-off-by: Ralph Castain --- src/mca/rmaps/base/help-prte-rmaps-base.txt | 10 +- src/mca/rmaps/base/rmaps_base_map_job.c | 5 +- src/tools/prte/prte.c | 2 - src/tools/prte_info/prte_info.c | 2 - src/util/help-prte-util.txt | 104 ++++++++++++++++++++ 5 files changed, 116 insertions(+), 7 deletions(-) diff --git a/src/mca/rmaps/base/help-prte-rmaps-base.txt b/src/mca/rmaps/base/help-prte-rmaps-base.txt index fd4f3c8163..fc2ebb2a77 100644 --- a/src/mca/rmaps/base/help-prte-rmaps-base.txt +++ b/src/mca/rmaps/base/help-prte-rmaps-base.txt @@ -14,7 +14,7 @@ # Copyright (c) 2011 Los Alamos National Security, LLC. # All rights reserved. # Copyright (c) 2014-2020 Intel, Inc. All rights reserved. -# Copyright (c) 2021 Nanook Consulting All rights reserved. +# Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -549,3 +549,11 @@ The %s option contains a directive that is missing a value: Valid directive: "%s=" Please check for a typo or ensure that the value is provided. +# +[missing-personality] +PRRTE has hit an internal problem that should never happen - it is +attempting to map a job that lacks an assigned personality. + + Job: %s + +Please report this to the PRRTE developers (https://github.com/openpmix/prrte/issues) diff --git a/src/mca/rmaps/base/rmaps_base_map_job.c b/src/mca/rmaps/base/rmaps_base_map_job.c index cd926fef69..1b57d39a56 100644 --- a/src/mca/rmaps/base/rmaps_base_map_job.c +++ b/src/mca/rmaps/base/rmaps_base_map_job.c @@ -78,7 +78,8 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) jdata = caddy->jdata; schizo = (prte_schizo_base_module_t*)jdata->schizo; if (NULL == schizo) { - prte_output(0, "ARG"); + prte_show_help("help-prte-rmaps-base.txt", "missing-personality", true, + PRTE_JOBID_PRINT(jdata->nspace)); PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_MAP_FAILED); goto cleanup; } @@ -584,7 +585,7 @@ void prte_rmaps_base_map_job(int fd, short args, void *cbdata) PRTE_RELEASE(caddy); jdata->exit_code = PRTE_ERR_NOT_FOUND; PRTE_ACTIVATE_JOB_STATE(jdata, PRTE_JOB_STATE_MAP_FAILED); - return; + goto cleanup; } t0 = node->topology; for (int i = 1; i < prte_node_pool->size; i++) { diff --git a/src/tools/prte/prte.c b/src/tools/prte/prte.c index 8baa3b869e..8cc1e2578c 100644 --- a/src/tools/prte/prte.c +++ b/src/tools/prte/prte.c @@ -397,8 +397,6 @@ int main(int argc, char *argv[]) PRTE_DESTRUCT(&results); if (PRTE_ERR_SILENT != rc) { fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); - } else { - rc = PRTE_SUCCESS; } return rc; } diff --git a/src/tools/prte_info/prte_info.c b/src/tools/prte_info/prte_info.c index 1d073e54c5..16be0019ca 100644 --- a/src/tools/prte_info/prte_info.c +++ b/src/tools/prte_info/prte_info.c @@ -147,8 +147,6 @@ int main(int argc, char *argv[]) PRTE_DESTRUCT(&prte_info_cmd_line); if (PRTE_ERR_SILENT != ret) { fprintf(stderr, "%s: command line error (%s)\n", prte_tool_basename, prte_strerror(rc)); - } else { - ret = PRTE_SUCCESS; } return ret; } diff --git a/src/util/help-prte-util.txt b/src/util/help-prte-util.txt index e8f73809cd..2497084730 100644 --- a/src/util/help-prte-util.txt +++ b/src/util/help-prte-util.txt @@ -2,6 +2,7 @@ # # Copyright (c) 2009-2020 Cisco Systems, Inc. All rights reserved # Copyright (c) 2017-2020 Intel, Inc. All rights reserved. +# Copyright (c) 2022 Nanook Consulting. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -11,3 +12,106 @@ # This is the US/English general help file for PRTE. # [stacktrace signal override] +PRTE was inserting a signal handler for signal %d but noticed +that there is already a non-default handler installed. PRTE's +handler was therefore not installed; your job will continue. This +warning message will only be displayed once, even if PRTE +encounters this situation again. + +To avoid displaying this warning message, you can either not install +the error handler for signal %d or you can have PRTE not try to +install its own signal handler for this signal by setting the +"prte_signals" MCA parameter. + + Signal: %d + Current prte_signal value: %s +# +[stacktrace bad signal] +PRTE was inserting a signal handler but was given an invalid +signal number: + + Signal string: %s + Bad value: %s + +The given value must be an integer within the signal number +range. Please correct the value and try again. +# +[malformed net_private_ipv4] +PRTE has detected at least one malformed IP address or netmask in +the value of the prte_net_private_ipv4 MCA parameter. The +prte_net_private_ipv4 MCA parameter accepts a semicolon-delimited list +of Classless Inter-Domain Routing (CIDR) notation specifications, each +of the form /. For example: + + 10.0.0.0/8;172.16.0.0/12;192.168.0.0/16;169.254.0.0/16 + +The first detected malformed entry was %s. +# +[invalid-net-mask] +PRTE has detected a malformed IPv4 address or netmask: + + Value provided: %s + +Accepted values follow the Classless Inter-Domain +Routing (CIDR) notation specifications. For example: + + 10.0.0.0/8 + 172.16/12 + 192.168 + 169.254.0.0/16 +# +[malformed-uri] +PRTE has detected a malformed URI: + + URI: %s + +Accepted values follow IETF RFC3986, e.g. file://192.168.1.1/over/there +# +[relative-path] +When creating a URI, all files must be specified in absolute paths: + + Value provided: %s + +Please update your application to provide the full path to the file. +# +[sys-limit-failed] +Per request, PRTE attempted to set a system resource +limit to a given value: + + Resource: %s + Limit: %s + +The system has refused to allow this operation. This is likely +due to a permission limitation, or specifying an unsupported +value. Please check the system or remove the request and try +again. +# +[sys-limit-unrecognized] +PRTE received a request to set a system resource limit. +Sadly, OMPI does not recognize or currently support the specified +resource: + + Resource: %s + Limit: %s + +Please correct the request and try again. +# +[dir-mode] +While working through a directory tree, we were unable to set +a directory to the desired mode: + + Directory: %s + Mode: %0x + Error: %s + +Please check to ensure you have adequate permissions to perform +the desired operation. +# +[mkdir-failed] +A call to mkdir was unable to create the desired directory: + + Directory: %s + Error: %s + +Please check to ensure you have adequate permissions to perform +the desired operation. From 1d9bd24d936d4eb0682e8d545469627e4e3e1352 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Thu, 3 Feb 2022 15:42:44 -0800 Subject: [PATCH 7/7] Address missed comments to correct a couple of options Signed-off-by: Ralph Castain --- src/mca/schizo/ompi/schizo_ompi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mca/schizo/ompi/schizo_ompi.c b/src/mca/schizo/ompi/schizo_ompi.c index eb6e268868..0beeed4862 100644 --- a/src/mca/schizo/ompi/schizo_ompi.c +++ b/src/mca/schizo/ompi/schizo_ompi.c @@ -145,7 +145,7 @@ static struct option ompioptions[] = { PRTE_OPTION_DEFINE(PRTE_CLI_WDIR, PRTE_ARG_REQD), PRTE_OPTION_DEFINE("wd", PRTE_ARG_REQD), PRTE_OPTION_DEFINE(PRTE_CLI_PATH, PRTE_ARG_REQD), - PRTE_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_SHOW_PROGRESS, PRTE_ARG_NONE), PRTE_OPTION_DEFINE(PRTE_CLI_PSET, PRTE_ARG_REQD), PRTE_OPTION_DEFINE(PRTE_CLI_HOSTFILE, PRTE_ARG_REQD), PRTE_OPTION_DEFINE("machinefile", PRTE_ARG_REQD), @@ -166,7 +166,7 @@ static struct option ompioptions[] = { PRTE_OPTION_DEFINE(PRTE_CLI_DISPLAY, PRTE_ARG_REQD), /* developer options */ - PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PRTE_ARG_REQD), + PRTE_OPTION_DEFINE(PRTE_CLI_DO_NOT_LAUNCH, PRTE_ARG_NONE), #if PRTE_ENABLE_FT