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..76784194fd 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, + "setdefaultbinding[%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, + "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, + "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, + "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, + "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, + "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, + "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, + "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 */ + 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, + "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, + "setdefaultbinding[%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, + "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, + "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, + "setdefaultbinding[%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, + "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, + "setdefaultbinding[%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, + "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, + "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, + "setdefaultbinding[%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; + } + } + return PRTE_SUCCESS; +} + 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/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/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/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/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/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_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..1b57d39a56 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,20 @@ 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_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; + } jdata->state = PRTE_JOB_STATE_MAP; prte_output_verbose(5, prte_rmaps_base_framework.framework_output, @@ -440,6 +448,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 +469,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 +524,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 +559,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; } } } @@ -705,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/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..5fe7a1ed99 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,220 @@ 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_NOOVERLOAD, + 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 +465,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..ccffd88a30 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,155 @@ 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 + 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? + 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 + 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? + 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, directive); + prte_list_append(&results->instances, &opt->super); } - 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 + 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? + 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); + prte_list_append(&results->instances, &opt->super); } - 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 +308,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 +368,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 +449,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 +507,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..0beeed4862 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 @@ -53,678 +53,653 @@ #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" #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, bool silent); 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 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); 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 + .set_default_ranking = set_default_ranking, + .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(PRTE_CLI_APPFILE, 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_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), + 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_NONE), + #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(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 /* 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:N:sH:x:"; - /* End of list */ - {'\0', NULL, 0, PRTE_CMD_LINE_TYPE_NULL, NULL}}; +static int convert_deprecated_cli(prte_cli_result_t *results, + bool silent); -static int define_cli(prte_cmd_line_t *cli) +static int parse_cli(char **argv, prte_cli_result_t *results, + bool silent) { - int rc; + 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 != 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(pargv[n], "-with-ft")) { + free(pargv[n]); + pargv[n] = strdup("--with-ft"); + } +#endif + } - prte_output_verbose(1, prte_schizo_base_framework.framework_output, - "%s schizo:ompi: define_cli", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME)); + rc = prte_cmd_line_parse(pargv, ompishorts, ompioptions, NULL, + results, "help-schizo-ompi.txt"); + prte_argv_free(pargv); + if (PRTE_SUCCESS != rc) { + return rc; + } - /* protect against bozo error */ - if (NULL == cli) { - return PRTE_ERR_BAD_PARAM; + /* check for deprecated options - warn and convert them */ + rc = convert_deprecated_cli(results, silent); + if (PRTE_SUCCESS != rc) { + return rc; } - rc = prte_cmd_line_add(cli, ompi_cmd_line_init); - 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++) { + p1 = opt->values[n]; + prte_schizo_base_expose(p1, "PRTE_MCA_"); + } + } else if (0 == strcmp(opt->key, PRTE_CLI_PMIXMCA)) { + for (n=0; NULL != opt->values[n]; n++) { + p1 = opt->values[n]; + prte_schizo_base_expose(p1, "PMIX_MCA_"); + } +#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 + } + } -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; + 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; -} +}; -static int convert_deprecated_cli(char *option, char ***argv, int i) +static int convert_deprecated_cli(prte_cli_result_t *results, + bool silent) { - char **pargs, *p1, *p2, *tmp, *tmp2, *output, *modifier; + 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; - pargs = *argv; - - /* --nolocal -> --map-by :nolocal */ - if (0 == strcmp(option, "--nolocal")) { - rc = prte_schizo_base_convert(argv, i, 1, "--map-by", NULL, "NOLOCAL", true); + if (silent) { + warn = false; + } else { + warn = prte_schizo_ompi_component.warn_deprecations; } - /* --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_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); } - 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, + PRTE_CLI_MAPBY, PRTE_CLI_NOLOCAL, + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - } - /* --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, + PRTE_CLI_MAPBY, PRTE_CLI_OVERSUB, + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - } - /* --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, + PRTE_CLI_MAPBY, PRTE_CLI_NOOVER, + warn); + 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", 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, + PRTE_CLI_BINDTO, PRTE_CLI_HWT, + warn); + 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, "%s%s", PRTE_CLI_PELIST, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + warn); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - 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, PRTE_CLI_CORE, + 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, + 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, + 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, + 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, + warn); + 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, "%s%s", PRTE_CLI_PE, opt->values[0]); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, p2, + warn); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - 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, + PRTE_CLI_MAPBY, p2, + warn); + 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, + 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", + 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, + warn); + free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --ppr X -> --map-by ppr:X */ + else if (0 == strcmp(option, "ppr")) { + /* if they didn't specify a complete pattern, then this is an error */ + if (NULL == strchr(opt->values[0], ':')) { + 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, + PRTE_CLI_MAPBY, p2, + warn); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; + 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], + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --rankfile X -> map-by rankfile:file=X */ + else if (0 == strcmp(option, "rankfile")) { + 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, + PRTE_CLI_OUTPUT, PRTE_CLI_TAG, + 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, + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --output-directory DIR -> --output dir=DIR */ + else if (0 == strcmp(option, "output-directory")) { + prte_asprintf(&p2, "%s%s", PRTE_CLI_QDIR, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_OUTPUT, p2, + warn); + free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --output-filename DIR -> --output file=file */ + 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, + warn); + 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, PRTE_CLI_XML, + 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, + 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, + 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, + 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, + 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, + 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, + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --debug will be deprecated starting with open mpi v5 + */ + else if (0 == strcmp(option, "debug")) { + if (warn) { + 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)) { + /* check the value of the option for "socket" */ + if (0 == strncasecmp(opt->values[0], "socket", strlen("socket"))) { + p1 = strdup(opt->values[0]); // save the original option + /* replace "socket" with "package" */ + if (NULL == (p2 = strchr(opt->values[0], ':'))) { + /* no modifiers */ + tmp = strdup(PRTE_CLI_PACKAGE); + } else { + *p2 = '\0'; + ++p2; + prte_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); + } + 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 */ + 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(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); + } + 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 */ + 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(opt->values[0]); + opt->values[0] = tmp; + } + } + /* --bind-to socket -> --bind-to package */ + else if (0 == strcmp(option, PRTE_CLI_BINDTO)) { + /* check the value of the option for "socket" */ + if (0 == strncasecmp(opt->values[0], "socket", strlen("socket"))) { + p1 = strdup(opt->values[0]); // save the original option + /* replace "socket" with "package" */ + if (NULL == (p2 = strchr(opt->values[0], ':'))) { + /* no modifiers */ + tmp = strdup(PRTE_CLI_PACKAGE); + } else { + *p2 = '\0'; + ++p2; + prte_asprintf(&tmp, "%s:%s", PRTE_CLI_PACKAGE, p2); + } + 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 */ + 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(opt->values[0]); + opt->values[0] = tmp; + } } - 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[] = {"--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 +1025,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 +1176,26 @@ static bool check_generic(char *p1) return false; } -static int parse_cli(int argc, int start, char **argv, char ***target) +static int parse_env(char **srcenv, char ***dstenv, + prte_cli_result_t *results) { - 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) -{ - 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 +1219,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 +1228,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 +1237,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 +1271,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 +1293,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 +1319,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 +1389,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 +1400,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 +1408,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 +1415,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 +1536,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 +1833,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 +1852,41 @@ 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 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) { - 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/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/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..9b11135a27 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,784 @@ #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, bool silent); 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 */ - {'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_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 */ + 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, + bool silent); -static int parse_cli(int argc, int start, char **argv, char ***target) +static int parse_cli(char **argv, prte_cli_result_t *results, + bool silent) { - 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, silent); + 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, + bool silent) { - 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; + 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; } - /* --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); + + 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, PRTE_CLI_NOLOCAL, + 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, + 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, + 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, + warn); + 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, "%s%s", PRTE_CLI_PELIST, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + warn); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - 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, PRTE_CLI_CORE, + 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, + 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, + 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, + 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, + warn); + 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, "%s%s", PRTE_CLI_PE, opt->values[0]); + rc = prte_schizo_base_add_qualifier(results, option, + PRTE_CLI_MAPBY, p2, + warn); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - 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, + PRTE_CLI_MAPBY, p2, + warn); + 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, + 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", + 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, + warn); + free(p2); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --ppr X -> --map-by ppr:X */ + else if (0 == strcmp(option, "ppr")) { + /* if they didn't specify a complete pattern, then this is an error */ + if (NULL == strchr(opt->values[0], ':')) { + 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, + PRTE_CLI_MAPBY, p2, + warn); free(p2); - free(tmp2); - free(pargs[i + 1]); - pargs[i + 1] = tmp; - return PRTE_ERR_TAKE_NEXT_OPTION; + PRTE_CLI_REMOVE_DEPRECATED(results, opt); } - 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; + /* --am[ca] X -> --tune X */ + else if (0 == strcmp(option, "amca") || 0 == strcmp(option, "am")) { + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_TUNE, opt->values[0], + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --rankfile X -> map-by rankfile:file=X */ + else if (0 == strcmp(option, "rankfile")) { + prte_asprintf(&p2, "%s%s", PRTE_CLI_QFILE, opt->values[0]); + rc = prte_schizo_base_add_directive(results, option, + PRTE_CLI_MAPBY, p2, + warn); + 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, PRTE_CLI_TAG, + 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, + warn); + 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, + warn); + 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, + warn); + 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, PRTE_CLI_XML, + 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, + 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, + 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, + 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, + 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, + 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, + warn); + PRTE_CLI_REMOVE_DEPRECATED(results, opt); + } + /* --debug will be deprecated starting with open mpi v5 + */ + else if (0 == strcmp(option, "debug")) { + if (warn) { + 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); } - 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"); + /* --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); + } + 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 */ + 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(opt->values[0]); + opt->values[0] = tmp; + } } - 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); + /* --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); + } + 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 */ + 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(opt->values[0]); + opt->values[0] = tmp; + } } - 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); + /* --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); + } + 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 */ + 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(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 +842,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 +868,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 +886,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 +897,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 +911,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 +1106,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 +1124,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..8e2a0aa6ee 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 @@ -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; @@ -33,4 +34,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..5e427b9833 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 @@ -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 053c483767..92e6baf960 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 @@ -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 */ @@ -51,31 +59,10 @@ 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, + bool silent); /* detect if we are running as a proxy * Check the environment to determine what, if any, host we are running @@ -90,11 +77,22 @@ 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); + +/* 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 @@ -109,56 +107,32 @@ 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 */ 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_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; -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/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/prted/prte_app_parse.c b/src/prted/prte_app_parse.c index 2fa5004709..dfc601bed5 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, 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)); } + 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 920cacb3e6..42e5c54dd5 100644 --- a/src/runtime/prte_globals.h +++ b/src/runtime/prte_globals.h @@ -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 PRTE_EXPORT extern char *prte_progress_thread_cpus; PRTE_EXPORT extern bool prte_bind_progress_thread_reqd; @@ -201,6 +203,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 */ @@ -247,6 +251,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); @@ -309,6 +315,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 @@ -369,6 +376,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..8cc1e2578c 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,32 +390,11 @@ 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, PRTE_CLI_WARN); + 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)); } @@ -430,83 +406,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 +426,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 +464,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 +511,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 +539,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 +587,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 +643,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 +673,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 +718,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 +731,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 +742,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 +779,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 +917,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 +966,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 +989,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 +1089,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..16be0019ca 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,60 @@ 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, PRTE_CLI_SILENT); + 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)); + } + 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 +185,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..33ff18e30e 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, PRTE_CLI_SILENT); + 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..8887984f4a 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, PRTE_CLI_WARN); + 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..f41dd027bb 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, PRTE_CLI_WARN); + 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..d3eb3f1785 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,372 @@ #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, argind; + 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) { + argind = optind; + 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 */ + if ('-' != argv[argind][0]) { + // this was not an option + break; + } + 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); - } -} - -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; + if (optind < argc) { + results->tail = prte_argv_copy(&argv[optind]); } - - /* 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) +static void icon(prte_cli_item_t *p) { - /* 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; + p->key = NULL; + p->values = NULL; } - -prte_cmd_line_option_t *prte_cmd_line_find_option(prte_cmd_line_t *cmd, prte_cmd_line_init_t *e) +static void ides(prte_cli_item_t *p) { - 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; - } - } + if (NULL != p->key) { + free(p->key); } - - /* Not found */ - - return NULL; -} - -static prte_value_t *set_dest(prte_cmd_line_option_t *option, char *sval) -{ - 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; - } -} - -/* - * Helper function to qsort_callback - */ -static void fill(const prte_cmd_line_option_t *a, char result[3][BUFSIZ]) -{ - 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 != 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..559f2a0de4 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,570 +23,340 @@ * $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_NOOVERLOAD "no-overload" +#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]; +} + +#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 */ 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..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