/src/sbatch/opt.c
C | 2972 lines | 2708 code | 115 blank | 149 comment | 151 complexity | 71d473eb8a0fe05c4e9dbf46f0db8568 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*****************************************************************************\
- * opt.c - options processing for sbatch
- *****************************************************************************
- * Copyright (C) 2002-2007 The Regents of the University of California.
- * Copyright (C) 2008-2010 Lawrence Livermore National Security.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Mark Grondona <grondona1@llnl.gov>, et. al.
- * CODE-OCEC-09-009. All rights reserved.
- *
- * This file is part of SLURM, a resource management program.
- * For details, see <http://www.schedmd.com/slurmdocs/>.
- * Please also read the included file: DISCLAIMER.
- *
- * SLURM is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * In addition, as a special exception, the copyright holders give permission
- * to link the code of portions of this program with the OpenSSL library under
- * certain conditions as described in each individual source file, and
- * distribute linked combinations including the two. You must obey the GNU
- * General Public License in all respects for all of the code used other than
- * OpenSSL. If you modify file(s) with this exception, you may extend this
- * exception to your version of the file(s), but you are not obligated to do
- * so. If you do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source files in
- * the program, then also delete it here.
- *
- * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along
- * with SLURM; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- \*****************************************************************************/
- #if HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <string.h> /* strcpy, strncasecmp */
- #ifdef HAVE_STRINGS_H
- # include <strings.h>
- #endif
- #ifndef _GNU_SOURCE
- # define _GNU_SOURCE
- #endif
- #if HAVE_GETOPT_H
- # include <getopt.h>
- #else
- # include "src/common/getopt.h"
- #endif
- #ifdef HAVE_LIMITS_H
- # include <limits.h>
- #endif
- #include <fcntl.h>
- #include <stdarg.h> /* va_start */
- #include <stdio.h>
- #include <stdlib.h> /* getenv */
- #include <ctype.h> /* isdigit */
- #include <sys/param.h> /* MAXPATHLEN */
- #include <sys/stat.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/utsname.h>
- #include "src/common/list.h"
- #include "src/common/log.h"
- #include "src/common/parse_time.h"
- #include "src/common/plugstack.h"
- #include "src/common/proc_args.h"
- #include "src/common/read_config.h" /* contains getnodename() */
- #include "src/common/slurm_protocol_api.h"
- #include "src/common/slurm_resource_info.h"
- #include "src/common/slurm_rlimits_info.h"
- #include "src/common/uid.h"
- #include "src/common/xmalloc.h"
- #include "src/common/xstring.h"
- #include "src/sbatch/opt.h"
- /* generic OPT_ definitions -- mainly for use with env vars */
- #define OPT_NONE 0x00
- #define OPT_INT 0x01
- #define OPT_STRING 0x02
- #define OPT_DEBUG 0x03
- #define OPT_NODES 0x04
- #define OPT_BOOL 0x05
- #define OPT_CORE 0x06
- #define OPT_CONN_TYPE 0x07
- #define OPT_DISTRIB 0x08
- #define OPT_NO_ROTATE 0x09
- #define OPT_GEOMETRY 0x0a
- #define OPT_MULTI 0x0b
- #define OPT_EXCLUSIVE 0x0c
- #define OPT_OVERCOMMIT 0x0d
- #define OPT_OPEN_MODE 0x0e
- #define OPT_ACCTG_FREQ 0x0f
- #define OPT_NO_REQUEUE 0x10
- #define OPT_REQUEUE 0x11
- #define OPT_CPU_BIND 0x12
- #define OPT_MEM_BIND 0x13
- #define OPT_WCKEY 0x14
- #define OPT_SIGNAL 0x15
- #define OPT_GET_USER_ENV 0x16
- #define OPT_EXPORT 0x17
- #define OPT_CLUSTERS 0x18
- #define OPT_TIME_VAL 0x19
- /* generic getopt_long flags, integers and *not* valid characters */
- #define LONG_OPT_PROPAGATE 0x100
- #define LONG_OPT_CPU_BIND 0x101
- #define LONG_OPT_MEM_BIND 0x102
- #define LONG_OPT_JOBID 0x105
- #define LONG_OPT_TMP 0x106
- #define LONG_OPT_MEM 0x107
- #define LONG_OPT_MINCPU 0x108
- #define LONG_OPT_CONT 0x109
- #define LONG_OPT_UID 0x10a
- #define LONG_OPT_GID 0x10b
- #define LONG_OPT_MINSOCKETS 0x10c
- #define LONG_OPT_MINCORES 0x10d
- #define LONG_OPT_MINTHREADS 0x10e
- #define LONG_OPT_CORE 0x10f
- #define LONG_OPT_CONNTYPE 0x110
- #define LONG_OPT_EXCLUSIVE 0x111
- #define LONG_OPT_BEGIN 0x112
- #define LONG_OPT_MAIL_TYPE 0x113
- #define LONG_OPT_MAIL_USER 0x114
- #define LONG_OPT_NICE 0x115
- #define LONG_OPT_NO_REQUEUE 0x116
- #define LONG_OPT_COMMENT 0x117
- #define LONG_OPT_WRAP 0x118
- #define LONG_OPT_REQUEUE 0x119
- #define LONG_OPT_NETWORK 0x120
- #define LONG_OPT_QOS 0x127
- #define LONG_OPT_SOCKETSPERNODE 0x130
- #define LONG_OPT_CORESPERSOCKET 0x131
- #define LONG_OPT_THREADSPERCORE 0x132
- #define LONG_OPT_NTASKSPERNODE 0x136
- #define LONG_OPT_NTASKSPERSOCKET 0x137
- #define LONG_OPT_NTASKSPERCORE 0x138
- #define LONG_OPT_MEM_PER_CPU 0x13a
- #define LONG_OPT_HINT 0x13b
- #define LONG_OPT_BLRTS_IMAGE 0x140
- #define LONG_OPT_LINUX_IMAGE 0x141
- #define LONG_OPT_MLOADER_IMAGE 0x142
- #define LONG_OPT_RAMDISK_IMAGE 0x143
- #define LONG_OPT_REBOOT 0x144
- #define LONG_OPT_GET_USER_ENV 0x146
- #define LONG_OPT_OPEN_MODE 0x147
- #define LONG_OPT_ACCTG_FREQ 0x148
- #define LONG_OPT_WCKEY 0x149
- #define LONG_OPT_RESERVATION 0x14a
- #define LONG_OPT_CHECKPOINT 0x14b
- #define LONG_OPT_CHECKPOINT_DIR 0x14c
- #define LONG_OPT_SIGNAL 0x14d
- #define LONG_OPT_TIME_MIN 0x14e
- #define LONG_OPT_GRES 0x14f
- #define LONG_OPT_WAIT_ALL_NODES 0x150
- #define LONG_OPT_EXPORT 0x151
- #define LONG_OPT_REQ_SWITCH 0x152
- #define LONG_OPT_EXPORT_FILE 0x153
- /*---- global variables, defined in opt.h ----*/
- opt_t opt;
- int error_exit = 1;
- /*---- forward declarations of static functions ----*/
- typedef struct env_vars env_vars_t;
- /* Get a decimal integer from arg */
- static int _get_int(const char *arg, const char *what);
- static void _help(void);
- /* fill in default options */
- static void _opt_default(void);
- /* set options from batch script */
- static void _opt_batch_script(const char *file, const void *body, int size);
- /* set options from pbs batch script */
- static void _opt_pbs_batch_script(const char *file, const void *body, int size);
- /* set options based upon env vars */
- static void _opt_env(void);
- static void _proc_get_user_env(char *val);
- /* list known options and their settings */
- static void _opt_list(void);
- /* verify options sanity */
- static bool _opt_verify(void);
- static void _process_env_var(env_vars_t *e, const char *val);
- static uint16_t _parse_pbs_mail_type(const char *arg);
- static void _usage(void);
- static void _fullpath(char **filename, const char *cwd);
- static void _set_options(int argc, char **argv);
- static void _set_pbs_options(int argc, char **argv);
- static void _parse_pbs_resource_list(char *rl);
- /*---[ end forward declarations of static functions ]---------------------*/
- /*
- * print error message to stderr with opt.progname prepended
- */
- #undef USE_ARGERROR
- #if USE_ARGERROR
- static void argerror(const char *msg, ...)
- __attribute__ ((format (printf, 1, 2)));
- static void argerror(const char *msg, ...)
- {
- va_list ap;
- char buf[256];
- va_start(ap, msg);
- vsnprintf(buf, sizeof(buf), msg, ap);
- fprintf(stderr, "%s: %s\n",
- opt.progname ? opt.progname : "sbatch", buf);
- va_end(ap);
- }
- #else
- # define argerror error
- #endif /* USE_ARGERROR */
- /*
- * If the node list supplied is a file name, translate that into
- * a list of nodes, we orphan the data pointed to
- * RET true if the node list is a valid one
- */
- static bool _valid_node_list(char **node_list_pptr)
- {
- int count = NO_VAL;
- /* If we are using Arbitrary and we specified the number of
- procs to use then we need exactly this many since we are
- saying, lay it out this way! Same for max and min nodes.
- Other than that just read in as many in the hostfile */
- if(opt.ntasks_set)
- count = opt.ntasks;
- else if(opt.nodes_set) {
- if(opt.max_nodes)
- count = opt.max_nodes;
- else if(opt.min_nodes)
- count = opt.min_nodes;
- }
- return verify_node_list(node_list_pptr, opt.distribution, count);
- }
- /*
- * _opt_default(): used by initialize_and_process_args to set defaults
- */
- static void _opt_default()
- {
- char buf[MAXPATHLEN + 1];
- int i;
- uid_t uid = getuid();
- opt.user = uid_to_string(uid);
- if (strcmp(opt.user, "nobody") == 0)
- fatal("Invalid user id: %u", uid);
- opt.script_argc = 0;
- opt.script_argv = NULL;
- opt.uid = uid;
- opt.gid = getgid();
- if ((getcwd(buf, MAXPATHLEN)) == NULL) {
- error("getcwd failed: %m");
- exit(error_exit);
- }
- opt.cwd = xstrdup(buf);
- opt.clusters = NULL;
- opt.progname = NULL;
- opt.ntasks = 1;
- opt.ntasks_set = false;
- opt.cpus_per_task = 0;
- opt.cpus_set = false;
- opt.min_nodes = 1;
- opt.max_nodes = 0;
- opt.nodes_set = false;
- opt.sockets_per_node = NO_VAL; /* requested sockets */
- opt.cores_per_socket = NO_VAL; /* requested cores */
- opt.threads_per_core = NO_VAL; /* requested threads */
- opt.ntasks_per_node = 0; /* ntask max limits */
- opt.ntasks_per_socket = NO_VAL;
- opt.ntasks_per_core = NO_VAL;
- opt.cpu_bind_type = 0;
- opt.cpu_bind = NULL;
- opt.mem_bind_type = 0;
- opt.mem_bind = NULL;
- opt.time_limit = NO_VAL;
- opt.time_min = NO_VAL;
- opt.partition = NULL;
- opt.job_name = NULL;
- opt.jobid = NO_VAL;
- opt.jobid_set = false;
- opt.dependency = NULL;
- opt.account = NULL;
- opt.comment = NULL;
- opt.qos = NULL;
- opt.distribution = SLURM_DIST_UNKNOWN;
- opt.plane_size = NO_VAL;
- opt.shared = (uint16_t)NO_VAL;
- opt.no_kill = false;
- opt.immediate = false;
- opt.requeue = NO_VAL;
- opt.overcommit = false;
- opt.quiet = 0;
- opt.verbose = 0;
- opt.warn_signal = 0;
- opt.warn_time = 0;
- opt.wait_all_nodes = (uint16_t) NO_VAL;
- /* constraint default (-1 is no constraint) */
- opt.mincpus = -1;
- opt.mem_per_cpu = -1;
- opt.realmem = -1;
- opt.tmpdisk = -1;
- opt.hold = false;
- opt.constraints = NULL;
- opt.gres = NULL;
- opt.contiguous = false;
- opt.nodelist = NULL;
- opt.exc_nodes = NULL;
- for (i=0; i<HIGHEST_DIMENSIONS; i++) {
- opt.conn_type[i] = (uint16_t) NO_VAL;
- opt.geometry[i] = (uint16_t) NO_VAL;
- }
- opt.reboot = false;
- opt.no_rotate = false;
- opt.euid = (uid_t) -1;
- opt.egid = (gid_t) -1;
- opt.propagate = NULL; /* propagate specific rlimits */
- opt.ifname = xstrdup("/dev/null");
- opt.ofname = NULL;
- opt.efname = NULL;
- opt.export_env = NULL;
- opt.export_file = NULL;
- opt.get_user_env_time = -1;
- opt.get_user_env_mode = -1;
- opt.acctg_freq = -1;
- opt.reservation = NULL;
- opt.wckey = NULL;
- opt.req_switch = -1;
- opt.wait4switch = -1;
- opt.ckpt_interval = 0;
- opt.ckpt_interval_str = NULL;
- opt.ckpt_dir = xstrdup(opt.cwd);
- }
- static void _set_distribution(task_dist_states_t distribution,
- char **dist, char **lllp_dist)
- {
- if (((int)distribution >= 0)
- && (distribution != SLURM_DIST_UNKNOWN)) {
- switch(distribution) {
- case SLURM_DIST_CYCLIC:
- *dist = "cyclic";
- break;
- case SLURM_DIST_BLOCK:
- *dist = "block";
- break;
- case SLURM_DIST_PLANE:
- *dist = "plane";
- *lllp_dist = "plane";
- break;
- case SLURM_DIST_ARBITRARY:
- *dist = "arbitrary";
- break;
- case SLURM_DIST_CYCLIC_CYCLIC:
- *dist = "cyclic";
- *lllp_dist = "cyclic";
- break;
- case SLURM_DIST_CYCLIC_BLOCK:
- *dist = "cyclic";
- *lllp_dist = "block";
- break;
- case SLURM_DIST_BLOCK_CYCLIC:
- *dist = "block";
- *lllp_dist = "cyclic";
- break;
- case SLURM_DIST_BLOCK_BLOCK:
- *dist = "block";
- *lllp_dist = "block";
- break;
- default:
- error("unknown dist, type %d", distribution);
- break;
- }
- }
- }
- /*---[ env var processing ]-----------------------------------------------*/
- /*
- * try to use a similar scheme as popt.
- *
- * in order to add a new env var (to be processed like an option):
- *
- * define a new entry into env_vars[], if the option is a simple int
- * or string you may be able to get away with adding a pointer to the
- * option to set. Otherwise, process var based on "type" in _opt_env.
- */
- struct env_vars {
- const char *var;
- int type;
- void *arg;
- void *set_flag;
- };
- env_vars_t env_vars[] = {
- {"SBATCH_ACCOUNT", OPT_STRING, &opt.account, NULL },
- {"SBATCH_ACCTG_FREQ", OPT_INT, &opt.acctg_freq, NULL },
- {"SBATCH_BLRTS_IMAGE", OPT_STRING, &opt.blrtsimage, NULL },
- {"SBATCH_CHECKPOINT", OPT_STRING, &opt.ckpt_interval_str, NULL },
- {"SBATCH_CHECKPOINT_DIR",OPT_STRING, &opt.ckpt_dir, NULL },
- {"SBATCH_CLUSTERS", OPT_CLUSTERS, &opt.clusters, NULL },
- {"SLURM_CLUSTERS", OPT_CLUSTERS, &opt.clusters, NULL },
- {"SBATCH_CNLOAD_IMAGE", OPT_STRING, &opt.linuximage, NULL },
- {"SBATCH_CONN_TYPE", OPT_CONN_TYPE, NULL, NULL },
- {"SBATCH_CPU_BIND", OPT_CPU_BIND, NULL, NULL },
- {"SBATCH_DEBUG", OPT_DEBUG, NULL, NULL },
- {"SBATCH_DISTRIBUTION", OPT_DISTRIB , NULL, NULL },
- {"SBATCH_EXCLUSIVE", OPT_EXCLUSIVE, NULL, NULL },
- {"SBATCH_GEOMETRY", OPT_GEOMETRY, NULL, NULL },
- {"SBATCH_IMMEDIATE", OPT_BOOL, &opt.immediate, NULL },
- {"SBATCH_IOLOAD_IMAGE", OPT_STRING, &opt.ramdiskimage, NULL },
- {"SBATCH_JOBID", OPT_INT, &opt.jobid, NULL },
- {"SBATCH_JOB_NAME", OPT_STRING, &opt.job_name, NULL },
- {"SBATCH_LINUX_IMAGE", OPT_STRING, &opt.linuximage, NULL },
- {"SBATCH_MEM_BIND", OPT_MEM_BIND, NULL, NULL },
- {"SBATCH_MLOADER_IMAGE", OPT_STRING, &opt.mloaderimage, NULL },
- {"SBATCH_NETWORK", OPT_STRING, &opt.network, NULL },
- {"SBATCH_NO_REQUEUE", OPT_NO_REQUEUE, NULL, NULL },
- {"SBATCH_NO_ROTATE", OPT_BOOL, &opt.no_rotate, NULL },
- {"SBATCH_OPEN_MODE", OPT_OPEN_MODE, NULL, NULL },
- {"SBATCH_OVERCOMMIT", OPT_OVERCOMMIT, NULL, NULL },
- {"SBATCH_PARTITION", OPT_STRING, &opt.partition, NULL },
- {"SBATCH_QOS", OPT_STRING, &opt.qos, NULL },
- {"SBATCH_RAMDISK_IMAGE", OPT_STRING, &opt.ramdiskimage, NULL },
- {"SBATCH_REQUEUE", OPT_REQUEUE, NULL, NULL },
- {"SBATCH_SIGNAL", OPT_SIGNAL, NULL, NULL },
- {"SBATCH_TIMELIMIT", OPT_STRING, &opt.time_limit_str,NULL },
- {"SBATCH_WAIT_ALL_NODES",OPT_INT, &opt.wait_all_nodes,NULL },
- {"SBATCH_WCKEY", OPT_STRING, &opt.wckey, NULL },
- {"SBATCH_GET_USER_ENV", OPT_GET_USER_ENV, NULL, NULL },
- {"SBATCH_EXPORT", OPT_STRING, &opt.export_env, NULL },
- {"SBATCH_REQ_SWITCH", OPT_INT, &opt.req_switch, NULL },
- {"SBATCH_WAIT4SWITCH", OPT_TIME_VAL, NULL, NULL },
- {NULL, 0, NULL, NULL}
- };
- /*
- * _opt_env(): used by initialize_and_process_args to set options via
- * environment variables. See comments above for how to
- * extend srun to process different vars
- */
- static void _opt_env()
- {
- char *val = NULL;
- env_vars_t *e = env_vars;
- while (e->var) {
- if ((val = getenv(e->var)) != NULL)
- _process_env_var(e, val);
- e++;
- }
- }
- static void
- _process_env_var(env_vars_t *e, const char *val)
- {
- char *end = NULL;
- debug2("now processing env var %s=%s", e->var, val);
- if (e->set_flag) {
- *((bool *) e->set_flag) = true;
- }
- switch (e->type) {
- case OPT_STRING:
- *((char **) e->arg) = xstrdup(val);
- break;
- case OPT_INT:
- if (val != NULL) {
- *((int *) e->arg) = (int) strtol(val, &end, 10);
- if (!(end && *end == '\0')) {
- error("%s=%s invalid. ignoring...",
- e->var, val);
- }
- }
- break;
- case OPT_BOOL:
- /* A boolean env variable is true if:
- * - set, but no argument
- * - argument is "yes"
- * - argument is a non-zero number
- */
- if (val == NULL || strcmp(val, "") == 0) {
- *((bool *)e->arg) = true;
- } else if (strcasecmp(val, "yes") == 0) {
- *((bool *)e->arg) = true;
- } else if ((strtol(val, &end, 10) != 0)
- && end != val) {
- *((bool *)e->arg) = true;
- } else {
- *((bool *)e->arg) = false;
- }
- break;
- case OPT_DEBUG:
- if (val != NULL) {
- opt.verbose = (int) strtol(val, &end, 10);
- if (!(end && *end == '\0'))
- error("%s=%s invalid", e->var, val);
- }
- break;
- case OPT_CPU_BIND:
- if (slurm_verify_cpu_bind(val, &opt.cpu_bind,
- &opt.cpu_bind_type))
- exit(error_exit);
- break;
- case OPT_MEM_BIND:
- if (slurm_verify_mem_bind(val, &opt.mem_bind,
- &opt.mem_bind_type))
- exit(error_exit);
- break;
- case OPT_DISTRIB:
- opt.distribution = verify_dist_type(val,
- &opt.plane_size);
- if (opt.distribution == SLURM_DIST_UNKNOWN)
- error("distribution type `%s' is invalid", val);
- break;
- case OPT_NODES:
- opt.nodes_set = verify_node_count( val,
- &opt.min_nodes,
- &opt.max_nodes );
- if (opt.nodes_set == false) {
- error("\"%s=%s\" -- invalid node count. ignoring...",
- e->var, val);
- }
- break;
- case OPT_CONN_TYPE:
- verify_conn_type(val, opt.conn_type);
- break;
- case OPT_NO_ROTATE:
- opt.no_rotate = true;
- break;
- case OPT_GEOMETRY:
- if (verify_geometry(val, opt.geometry)) {
- error("\"%s=%s\" -- invalid geometry, ignoring...",
- e->var, val);
- }
- break;
- case OPT_EXCLUSIVE:
- opt.shared = 0;
- break;
- case OPT_OVERCOMMIT:
- opt.overcommit = true;
- break;
- case OPT_OPEN_MODE:
- if ((val[0] == 'a') || (val[0] == 'A'))
- opt.open_mode = OPEN_MODE_APPEND;
- else if ((val[0] == 't') || (val[0] == 'T'))
- opt.open_mode = OPEN_MODE_TRUNCATE;
- else
- error("Invalid SBATCH_OPEN_MODE: %s. Ignored", val);
- break;
- case OPT_NO_REQUEUE:
- opt.requeue = 0;
- break;
- case OPT_REQUEUE:
- opt.requeue = 1;
- break;
- case OPT_WCKEY:
- xfree(opt.wckey);
- opt.wckey = xstrdup(val);
- break;
- case OPT_SIGNAL:
- if (get_signal_opts((char *)val, &opt.warn_signal,
- &opt.warn_time)) {
- error("Invalid signal specification: %s", val);
- exit(error_exit);
- }
- break;
- case OPT_GET_USER_ENV:
- if (val)
- _proc_get_user_env((char *)val);
- else
- opt.get_user_env_time = 0;
- break;
- case OPT_CLUSTERS:
- if (!(opt.clusters = slurmdb_get_info_cluster((char *)val))) {
- error("'%s' can't be reached now, "
- "or it is an invalid entry for "
- "--cluster. Use 'sacctmgr --list "
- "cluster' to see available clusters.",
- optarg);
- exit(1);
- }
- break;
- case OPT_TIME_VAL:
- opt.wait4switch = time_str2secs(val);
- break;
- default:
- /* do nothing */
- break;
- }
- }
- /*---[ command line option processing ]-----------------------------------*/
- static struct option long_options[] = {
- {"account", required_argument, 0, 'A'},
- {"batch", no_argument, 0, 'b'}, /* batch option
- is only here for
- moab tansition
- doesn't do anything */
- {"extra-node-info", required_argument, 0, 'B'},
- {"cpus-per-task", required_argument, 0, 'c'},
- {"constraint", required_argument, 0, 'C'},
- {"dependency", required_argument, 0, 'd'},
- {"workdir", required_argument, 0, 'D'},
- {"error", required_argument, 0, 'e'},
- {"nodefile", required_argument, 0, 'F'},
- {"geometry", required_argument, 0, 'g'},
- {"help", no_argument, 0, 'h'},
- {"hold", no_argument, 0, 'H'}, /* undocumented */
- {"input", required_argument, 0, 'i'},
- {"immediate", no_argument, 0, 'I'},
- {"job-name", required_argument, 0, 'J'},
- {"no-kill", no_argument, 0, 'k'},
- {"licenses", required_argument, 0, 'L'},
- {"distribution", required_argument, 0, 'm'},
- {"cluster", required_argument, 0, 'M'},
- {"clusters", required_argument, 0, 'M'},
- {"tasks", required_argument, 0, 'n'},
- {"ntasks", required_argument, 0, 'n'},
- {"nodes", required_argument, 0, 'N'},
- {"output", required_argument, 0, 'o'},
- {"overcommit", no_argument, 0, 'O'},
- {"partition", required_argument, 0, 'p'},
- {"quiet", no_argument, 0, 'Q'},
- {"no-rotate", no_argument, 0, 'R'},
- {"share", no_argument, 0, 's'},
- {"time", required_argument, 0, 't'},
- {"usage", no_argument, 0, 'u'},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 'V'},
- {"nodelist", required_argument, 0, 'w'},
- {"exclude", required_argument, 0, 'x'},
- {"acctg-freq", required_argument, 0, LONG_OPT_ACCTG_FREQ},
- {"begin", required_argument, 0, LONG_OPT_BEGIN},
- {"blrts-image", required_argument, 0, LONG_OPT_BLRTS_IMAGE},
- {"checkpoint", required_argument, 0, LONG_OPT_CHECKPOINT},
- {"checkpoint-dir",required_argument, 0, LONG_OPT_CHECKPOINT_DIR},
- {"cnload-image", required_argument, 0, LONG_OPT_LINUX_IMAGE},
- {"comment", required_argument, 0, LONG_OPT_COMMENT},
- {"conn-type", required_argument, 0, LONG_OPT_CONNTYPE},
- {"contiguous", no_argument, 0, LONG_OPT_CONT},
- {"cores-per-socket", required_argument, 0, LONG_OPT_CORESPERSOCKET},
- {"cpu_bind", required_argument, 0, LONG_OPT_CPU_BIND},
- {"exclusive", no_argument, 0, LONG_OPT_EXCLUSIVE},
- {"export", required_argument, 0, LONG_OPT_EXPORT},
- {"export-file", required_argument, 0, LONG_OPT_EXPORT_FILE},
- {"get-user-env", optional_argument, 0, LONG_OPT_GET_USER_ENV},
- {"gres", required_argument, 0, LONG_OPT_GRES},
- {"gid", required_argument, 0, LONG_OPT_GID},
- {"hint", required_argument, 0, LONG_OPT_HINT},
- {"ioload-image", required_argument, 0, LONG_OPT_RAMDISK_IMAGE},
- {"jobid", required_argument, 0, LONG_OPT_JOBID},
- {"linux-image", required_argument, 0, LONG_OPT_LINUX_IMAGE},
- {"mail-type", required_argument, 0, LONG_OPT_MAIL_TYPE},
- {"mail-user", required_argument, 0, LONG_OPT_MAIL_USER},
- {"mem", required_argument, 0, LONG_OPT_MEM},
- {"mem-per-cpu", required_argument, 0, LONG_OPT_MEM_PER_CPU},
- {"mem_bind", required_argument, 0, LONG_OPT_MEM_BIND},
- {"mincores", required_argument, 0, LONG_OPT_MINCORES},
- {"mincpus", required_argument, 0, LONG_OPT_MINCPU},
- {"minsockets", required_argument, 0, LONG_OPT_MINSOCKETS},
- {"minthreads", required_argument, 0, LONG_OPT_MINTHREADS},
- {"mloader-image", required_argument, 0, LONG_OPT_MLOADER_IMAGE},
- {"network", required_argument, 0, LONG_OPT_NETWORK},
- {"nice", optional_argument, 0, LONG_OPT_NICE},
- {"no-requeue", no_argument, 0, LONG_OPT_NO_REQUEUE},
- {"ntasks-per-core", required_argument, 0, LONG_OPT_NTASKSPERCORE},
- {"ntasks-per-node", required_argument, 0, LONG_OPT_NTASKSPERNODE},
- {"ntasks-per-socket",required_argument, 0, LONG_OPT_NTASKSPERSOCKET},
- {"open-mode", required_argument, 0, LONG_OPT_OPEN_MODE},
- {"propagate", optional_argument, 0, LONG_OPT_PROPAGATE},
- {"qos", required_argument, 0, LONG_OPT_QOS},
- {"ramdisk-image", required_argument, 0, LONG_OPT_RAMDISK_IMAGE},
- {"reboot", no_argument, 0, LONG_OPT_REBOOT},
- {"requeue", no_argument, 0, LONG_OPT_REQUEUE},
- {"reservation", required_argument, 0, LONG_OPT_RESERVATION},
- {"signal", required_argument, 0, LONG_OPT_SIGNAL},
- {"sockets-per-node", required_argument, 0, LONG_OPT_SOCKETSPERNODE},
- {"tasks-per-node",required_argument, 0, LONG_OPT_NTASKSPERNODE},
- {"time-min", required_argument, 0, LONG_OPT_TIME_MIN},
- {"threads-per-core", required_argument, 0, LONG_OPT_THREADSPERCORE},
- {"tmp", required_argument, 0, LONG_OPT_TMP},
- {"uid", required_argument, 0, LONG_OPT_UID},
- {"wait-all-nodes",required_argument, 0, LONG_OPT_WAIT_ALL_NODES},
- {"wckey", required_argument, 0, LONG_OPT_WCKEY},
- {"wrap", required_argument, 0, LONG_OPT_WRAP},
- {"switches", required_argument, 0, LONG_OPT_REQ_SWITCH},
- {NULL, 0, 0, 0}
- };
- static char *opt_string =
- "+bA:B:c:C:d:D:e:F:g:hHi:IJ:kL:m:M:n:N:o:Op:P:QRst:uU:vVw:x:";
- char *pos_delimit;
- /*
- * process_options_first_pass()
- *
- * In this first pass we only look at the command line options, and we
- * will only handle a few options (help, usage, quiet, verbose, version),
- * and look for the script name and arguments (if provided).
- *
- * We will parse the environment variable options, batch script options,
- * and all of the rest of the command line options in
- * process_options_second_pass().
- *
- * Return a pointer to the batch script file name is provided on the command
- * line, otherwise return NULL, and the script will need to be read from
- * standard input.
- */
- char *process_options_first_pass(int argc, char **argv)
- {
- int opt_char, option_index = 0;
- char *str = NULL;
- struct option *optz = spank_option_table_create(long_options);
- if (!optz) {
- error("Unable to create options table");
- exit(error_exit);
- }
- /* initialize option defaults */
- _opt_default();
- opt.progname = xbasename(argv[0]);
- optind = 0;
- while((opt_char = getopt_long(argc, argv, opt_string,
- optz, &option_index)) != -1) {
- switch (opt_char) {
- case '?':
- fprintf(stderr, "Try \"sbatch --help\" for more "
- "information\n");
- exit(error_exit);
- break;
- case 'h':
- _help();
- exit(0);
- break;
- case 'Q':
- opt.quiet++;
- break;
- case 'u':
- _usage();
- exit(0);
- case 'v':
- opt.verbose++;
- break;
- case 'V':
- print_slurm_version();
- exit(0);
- break;
- case LONG_OPT_WRAP:
- opt.wrap = xstrdup(optarg);
- break;
- default:
- /* will be parsed in second pass function */
- break;
- }
- }
- xfree(str);
- spank_option_table_destroy(optz);
- if (argc > optind && opt.wrap != NULL) {
- error("Script arguments are not permitted with the"
- " --wrap option.");
- exit(error_exit);
- }
- if (argc > optind) {
- int i;
- char **leftover;
- opt.script_argc = argc - optind;
- leftover = argv + optind;
- opt.script_argv = (char **) xmalloc((opt.script_argc + 1)
- * sizeof(char *));
- for (i = 0; i < opt.script_argc; i++)
- opt.script_argv[i] = xstrdup(leftover[i]);
- opt.script_argv[i] = NULL;
- }
- if (opt.script_argc > 0) {
- char *fullpath;
- char *cmd = opt.script_argv[0];
- int mode = R_OK;
- if ((fullpath = search_path(opt.cwd, cmd, true, mode))) {
- xfree(opt.script_argv[0]);
- opt.script_argv[0] = fullpath;
- }
- return opt.script_argv[0];
- } else {
- return NULL;
- }
- }
- /* process options:
- * 1. update options with option set in the script
- * 2. update options with env vars
- * 3. update options with commandline args
- * 4. perform some verification that options are reasonable
- */
- int process_options_second_pass(int argc, char *argv[], const char *file,
- const void *script_body, int script_size)
- {
- /* set options from batch script */
- _opt_batch_script(file, script_body, script_size);
- /* set options from pbs batch script */
- _opt_pbs_batch_script(file, script_body, script_size);
- /* set options from env vars */
- _opt_env();
- /* set options from command line */
- _set_options(argc, argv);
- if (!_opt_verify())
- exit(error_exit);
- if (opt.verbose > 3)
- _opt_list();
- return 1;
- }
- /*
- * _next_line - Interpret the contents of a byte buffer as characters in
- * a file. _next_line will find and return the next line in the buffer.
- *
- * If "state" is NULL, it will start at the beginning of the buffer.
- * _next_line will update the "state" pointer to point at the
- * spot in the buffer where it left off.
- *
- * IN buf - buffer containing file contents
- * IN size - size of buffer "buf"
- * IN/OUT state - used by _next_line to determine where the last line ended
- *
- * RET - xmalloc'ed character string, or NULL if no lines remaining in buf.
- */
- static char *_next_line(const void *buf, int size, void **state)
- {
- char *line;
- char *current, *ptr;
- if (*state == NULL) /* initial state */
- *state = (void *)buf;
- if ((*state - buf) >= size) /* final state */
- return NULL;
- ptr = current = (char *)*state;
- while ((*ptr != '\n') && (ptr < ((char *)buf+size)))
- ptr++;
- line = xstrndup(current, (ptr-current));
- /*
- * Advance state past newline
- */
- *state = (ptr < ((char *) buf + size)) ? ptr+1 : ptr;
- return line;
- }
- /*
- * _get_argument - scans a line for something that looks like a command line
- * argument, and return an xmalloc'ed string containing the argument.
- * Quotes can be used to group characters, including whitespace.
- * Quotes can be included in an argument be escaping the quotes,
- * preceding the quote with a backslash (\").
- *
- * IN - line
- * OUT - skipped - number of characters parsed from line
- * RET - xmalloc'ed argument string (may be shorter than "skipped")
- * or NULL if no arguments remaining
- */
- static char *
- _get_argument(const char *file, int lineno, const char *line, int *skipped)
- {
- const char *ptr;
- char argument[BUFSIZ];
- char q_char = '\0';
- bool escape_flag = false;
- bool quoted = false;
- int i;
- ptr = line;
- *skipped = 0;
- /* skip whitespace */
- while (isspace(*ptr) && *ptr != '\0') {
- ptr++;
- }
- if (*ptr == '\0')
- return NULL;
- /* copy argument into "argument" buffer, */
- i = 0;
- while ((quoted || !isspace(*ptr)) && *ptr != '\n' && *ptr != '\0') {
- if (escape_flag) {
- escape_flag = false;
- } else if (*ptr == '\\') {
- escape_flag = true;
- ptr++;
- continue;
- } else if (quoted) {
- if (*ptr == q_char) {
- quoted = false;
- ptr++;
- continue;
- }
- } else if (*ptr == '"' || *ptr == '\'') {
- quoted = true;
- q_char = *(ptr++);
- continue;
- } else if (*ptr == '#') {
- /* found an un-escaped #, rest of line is a comment */
- break;
- }
- argument[i++] = *(ptr++);
- }
- argument[i] = '\0';
- if (quoted) /* Unmatched quote */
- fatal("%s: line %d: Unmatched `%c` in [%s]",
- file, lineno, q_char, line);
- *skipped = ptr - line;
- return (i > 0 ? xstrdup (argument) : NULL);
- }
- /*
- * set options from batch script
- *
- * Build an argv-style array of options from the script "body",
- * then pass the array to _set_options for() further parsing.
- */
- static void _opt_batch_script(const char * file, const void *body, int size)
- {
- char *magic_word1 = "#SBATCH";
- char *magic_word2 = "#SLURM";
- int magic_word_len1, magic_word_len2;
- int argc;
- char **argv;
- void *state = NULL;
- char *line;
- char *option;
- char *ptr;
- int skipped = 0, warned = 0, lineno = 0;
- int i;
- magic_word_len1 = strlen(magic_word1);
- magic_word_len2 = strlen(magic_word2);
- /* getopt_long skips over the first argument, so fill it in */
- argc = 1;
- argv = xmalloc(sizeof(char *));
- argv[0] = "sbatch";
- while((line = _next_line(body, size, &state)) != NULL) {
- lineno++;
- if (!strncmp(line, magic_word1, magic_word_len1))
- ptr = line + magic_word_len1;
- else if (!strncmp(line, magic_word2, magic_word_len2)) {
- ptr = line + magic_word_len2;
- if (!warned) {
- error("Change from #SLURM to #SBATCH in your "
- "script and verify the options are "
- "valid in sbatch");
- warned = 1;
- }
- } else {
- xfree(line);
- continue;
- }
- /* this line starts with the magic word */
- while ((option = _get_argument(file, lineno, ptr, &skipped))) {
- debug2("Found in script, argument \"%s\"", option);
- argc += 1;
- xrealloc(argv, sizeof(char*) * argc);
- argv[argc-1] = option;
- ptr += skipped;
- }
- xfree(line);
- }
- if (argc > 0)
- _set_options(argc, argv);
- for (i = 1; i < argc; i++)
- xfree(argv[i]);
- xfree(argv);
- }
- /*
- * set pbs options from batch script
- *
- * Build an argv-style array of options from the script "body",
- * then pass the array to _set_options for() further parsing.
- */
- static void _opt_pbs_batch_script(const char *file, const void *body, int size)
- {
- char *magic_word = "#PBS";
- int magic_word_len;
- int argc;
- char **argv;
- void *state = NULL;
- char *line;
- char *option;
- char *ptr;
- int skipped = 0;
- int lineno = 0;
- int i;
- magic_word_len = strlen(magic_word);
- /* getopt_long skips over the first argument, so fill it in */
- argc = 1;
- argv = xmalloc(sizeof(char *));
- argv[0] = "sbatch";
- while((line = _next_line(body, size, &state)) != NULL) {
- lineno++;
- if (strncmp(line, magic_word, magic_word_len) != 0) {
- xfree(line);
- continue;
- }
- /* this line starts with the magic word */
- ptr = line + magic_word_len;
- while ((option = _get_argument(file, lineno, ptr, &skipped))) {
- debug2("Found in script, argument \"%s\"", option);
- argc += 1;
- xrealloc(argv, sizeof(char*) * argc);
- argv[argc-1] = option;
- ptr += skipped;
- }
- xfree(line);
- }
- if (argc > 0)
- _set_pbs_options(argc, argv);
- for (i = 1; i < argc; i++)
- xfree(argv[i]);
- xfree(argv);
- }
- static void _set_options(int argc, char **argv)
- {
- int opt_char, option_index = 0, max_val = 0;
- char *tmp;
- struct option *optz = spank_option_table_create(long_options);
- if (!optz) {
- error("Unable to create options table");
- exit(error_exit);
- }
- optind = 0;
- while((opt_char = getopt_long(argc, argv, opt_string,
- optz, &option_index)) != -1) {
- switch (opt_char) {
- case '?':
- error("Try \"sbatch --help\" for more information");
- exit(error_exit);
- break;
- case 'A':
- case 'U': /* backwards compatibility */
- xfree(opt.account);
- opt.account = xstrdup(optarg);
- break;
- case 'b':
- /* Only here for Moab transition not suppose
- to do anything */
- break;
- case 'B':
- opt.extra_set = verify_socket_core_thread_count(
- optarg,
- &opt.sockets_per_node,
- &opt.cores_per_socket,
- &opt.threads_per_core,
- &opt.cpu_bind_type);
- if (opt.extra_set == false) {
- error("invalid resource allocation -B `%s'",
- optarg);
- exit(error_exit);
- }
- break;
- case 'c':
- opt.cpus_set = true;
- opt.cpus_per_task = _get_int(optarg, "cpus-per-task");
- break;
- case 'C':
- xfree(opt.constraints);
- opt.constraints = xstrdup(optarg);
- break;
- case 'd':
- xfree(opt.dependency);
- opt.dependency = xstrdup(optarg);
- break;
- case 'D':
- xfree(opt.cwd);
- opt.cwd = xstrdup(optarg);
- break;
- case 'e':
- xfree(opt.efname);
- if (strcasecmp(optarg, "none") == 0)
- opt.efname = xstrdup("/dev/null");
- else
- opt.efname = xstrdup(optarg);
- break;
- case 'F':
- xfree(opt.nodelist);
- tmp = slurm_read_hostfile(optarg, 0);
- if (tmp != NULL) {
- opt.nodelist = xstrdup(tmp);
- free(tmp);
- } else {
- error("\"%s\" is not a valid node file",
- optarg);
- exit(error_exit);
- }
- break;
- case 'g':
- if (verify_geometry(optarg, opt.geometry))
- exit(error_exit);
- break;
- case 'h':
- _help();
- exit(0);
- case 'H':
- opt.hold = true;
- break;
- case 'i':
- xfree(opt.ifname);
- if (strcasecmp(optarg, "none") == 0)
- opt.ifname = xstrdup("/dev/null");
- else
- opt.ifname = xstrdup(optarg);
- break;
- case 'I':
- opt.immediate = true;
- break;
- case 'J':
- xfree(opt.job_name);
- opt.job_name = xstrdup(optarg);
- break;
- case 'k':
- opt.no_kill = true;
- break;
- case 'L':
- xfree(opt.licenses);
- opt.licenses = xstrdup(optarg);
- break;
- case 'm':
- opt.distribution = verify_dist_type(optarg,
- &opt.plane_size);
- if (opt.distribution == SLURM_DIST_UNKNOWN) {
- error("distribution type `%s' "
- "is not recognized", optarg);
- exit(error_exit);
- }
- break;
- case 'M':
- if (opt.clusters)
- list_destroy(opt.clusters);
- if (!(opt.clusters =
- slurmdb_get_info_cluster(optarg))) {
- error("'%s' can't be reached now, "
- "or it is an invalid entry for "
- "--cluster. Use 'sacctmgr --list "
- "cluster' to see available clusters.",
- optarg);
- exit(1);
- }
- break;
- case 'n':
- opt.ntasks_set = true;
- opt.ntasks =
- _get_int(optarg, "number of tasks");
- break;
- case 'N':
- opt.nodes_set =
- verify_node_count(optarg,
- &opt.min_nodes,
- &opt.max_nodes);
- if (opt.nodes_set == false) {
- error("invalid node count `%s'",
- optarg);
- exit(error_exit);
- }
- break;
- case 'o':
- xfree(opt.ofname);
- if (strcasecmp(optarg, "none") == 0)
- opt.ofname = xstrdup("/dev/null");
- else
- opt.ofname = xstrdup(optarg);
- break;
- case 'O':
- opt.overcommit = true;
- break;
- case 'p':
- xfree(opt.partition);
- opt.partition = xstrdup(optarg);
- break;
- case 'P':
- verbose("-P option is deprecated, use -d instead");
- xfree(opt.dependency);
- opt.dependency = xstrdup(optarg);
- break;
- case 'Q':
- opt.quiet++;
- break;
- case 'R':
- opt.no_rotate = true;
- break;
- case 's':
- opt.shared = 1;
- break;
- case 't':
- xfree(opt.time_limit_str);
- opt.time_limit_str = xstrdup(optarg);
- break;
- case 'u':
- _usage();
- exit(0);
- case 'v':
- opt.verbose++;
- break;
- case 'V':
- print_slurm_version();
- exit(0);
- break;
- case 'w':
- xfree(opt.nodelist);
- opt.nodelist = xstrdup(optarg);
- #ifdef HAVE_BG
- info("\tThe nodelist option should only be used if\n"
- "\tthe block you are asking for can be created.\n"
- "\tIt should also include all the midplanes you\n"
- "\twant to use, partial lists may not\n"
- "\twork correctly.\n"
- "\tPlease consult smap before using this option\n"
- "\tor your job may be stuck with no way to run.");
- #endif
- break;
- case 'x':
- xfree(opt.exc_nodes);
- opt.exc_nodes = xstrdup(optarg);
- if (!_valid_node_list(&opt.exc_nodes))
- exit(error_exit);
- break;
- case LONG_OPT_CONT:
- opt.contiguous = true;
- break;
- case LONG_OPT_EXCLUSIVE:
- opt.shared = 0;
- break;
- case LONG_OPT_CPU_BIND:
- if (slurm_verify_cpu_bind(optarg, &opt.cpu_bind,
- &opt.cpu_bind_type))
- exit(error_exit);
- break;
- case LONG_OPT_MEM_BIND:
- if (slurm_verify_mem_bind(optarg, &opt.mem_bind,
- &opt.mem_bind_type))
- exit(error_exit);
- break;
- case LONG_OPT_MINCPU:
- opt.mincpus = _get_int(optarg, "mincpus");
- if (opt.mincpus < 0) {
- error("invalid mincpus constraint %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MINCORES:
- verbose("mincores option has been deprecated, use "
- "cores-per-socket");
- opt.cores_per_socket = _get_int(optarg, "mincores");
- if (opt.cores_per_socket < 0) {
- error("invalid mincores constraint %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MINSOCKETS:
- verbose("minsockets option has been deprecated, use "
- "sockets-per-node");
- opt.sockets_per_node = _get_int(optarg, "minsockets");
- if (opt.sockets_per_node < 0) {
- error("invalid minsockets constraint %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MINTHREADS:
- verbose("minthreads option has been deprecated, use "
- "threads-per-core");
- opt.threads_per_core = _get_int(optarg, "minthreads");
- if (opt.threads_per_core < 0) {
- error("invalid minthreads constraint %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MEM:
- opt.realmem = (int) str_to_mbytes(optarg);
- if (opt.realmem < 0) {
- error("invalid memory constraint %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MEM_PER_CPU:
- opt.mem_per_cpu = (int) str_to_mbytes(optarg);
- if (opt.mem_per_cpu < 0) {
- error("invalid memory constraint %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_TMP:
- opt.tmpdisk = str_to_mbytes(optarg);
- if (opt.tmpdisk < 0) {
- error("invalid tmp value %s", optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_JOBID:
- opt.jobid = _get_int(optarg, "jobid");
- opt.jobid_set = true;
- break;
- case LONG_OPT_UID:
- if (opt.euid != (uid_t) -1) {
- error("duplicate --uid option");
- exit(error_exit);
- }
- if (uid_from_string (optarg, &opt.euid) < 0) {
- error("--uid=\"%s\" invalid", optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_GID:
- if (opt.egid != (gid_t) -1) {
- error("duplicate --gid option");
- exit(error_exit);
- }
- if (gid_from_string (optarg, &opt.egid) < 0) {
- error("--gid=\"%s\" invalid", optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_CONNTYPE:
- verify_conn_type(optarg, opt.conn_type);
- break;
- case LONG_OPT_BEGIN:
- opt.begin = parse_time(optarg, 0);
- if (opt.begin == 0) {
- error("Invalid time specification %s", optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MAIL_TYPE:
- opt.mail_type |= parse_mail_type(optarg);
- if (opt.mail_type == 0) {
- error("--mail-type=%s invalid", optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_MAIL_USER:
- xfree(opt.mail_user);
- opt.mail_user = xstrdup(optarg);
- break;
- case LONG_OPT_NICE:
- if (optarg)
- opt.nice = strtol(optarg, NULL, 10);
- else
- opt.nice = 100;
- if (abs(opt.nice) > NICE_OFFSET) {
- error("Invalid nice value, must be between "
- "-%d and %d", NICE_OFFSET, NICE_OFFSET);
- exit(error_exit);
- }
- if (opt.nice < 0) {
- uid_t my_uid = getuid();
- if ((my_uid != 0) &&
- (my_uid != slurm_get_slurm_user_id())) {
- error("Nice value must be "
- "non-negative, value ignored");
- opt.nice = 0;
- }
- }
- break;
- case LONG_OPT_NO_REQUEUE:
- opt.requeue = 0;
- break;
- case LONG_OPT_REQUEUE:
- opt.requeue = 1;
- break;
- case LONG_OPT_COMMENT:
- xfree(opt.comment);
- opt.comment = xstrdup(optarg);
- break;
- case LONG_OPT_QOS:
- xfree(opt.qos);
- opt.qos = xstrdup(optarg);
- break;
- case LONG_OPT_SOCKETSPERNODE:
- max_val = 0;
- get_resource_arg_range( optarg, "sockets-per-node",
- &opt.sockets_per_node,
- &max_val, true );
- if ((opt.sockets_per_node == 1) &&
- (max_val == INT_MAX))
- opt.sockets_per_node = NO_VAL;
- break;
- case LONG_OPT_CORESPERSOCKET:
- max_val = 0;
- get_resource_arg_range( optarg, "cores-per-socket",
- &opt.cores_per_socket,
- &max_val, true );
- if ((opt.cores_per_socket == 1) &&
- (max_val == INT_MAX))
- opt.cores_per_socket = NO_VAL;
- break;
- case LONG_OPT_THREADSPERCORE:
- max_val = 0;
- get_resource_arg_range( optarg, "threads-per-core",
- &opt.threads_per_core,
- &max_val, true );
- if ((opt.threads_per_core == 1) &&
- (max_val == INT_MAX))
- opt.threads_per_core = NO_VAL;
- break;
- case LONG_OPT_NTASKSPERNODE:
- opt.ntasks_per_node = _get_int(optarg,
- "ntasks-per-node");
- setenvf(NULL, "SLURM_NTASKS_PER_NODE", "%d",
- opt.ntasks_per_node);
- break;
- case LONG_OPT_NTASKSPERSOCKET:
- opt.ntasks_per_socket = _get_int(optarg,
- "ntasks-per-socket");
- setenvf(NULL, "SLURM_NTASKS_PER_SOCKET", "%d",
- opt.ntasks_per_socket);
- break;
- case LONG_OPT_NTASKSPERCORE:
- opt.ntasks_per_core = _get_int(optarg,
- "ntasks-per-core");
- setenvf(NULL, "SLURM_NTASKS_PER_CORE", "%d",
- opt.ntasks_per_socket);
- break;
- case LONG_OPT_HINT:
- /* Keep after other options filled in */
- if (verify_hint(optarg,
- &opt.sockets_per_node,
- &opt.cores_per_socket,
- &opt.threads_per_core,
- &opt.ntasks_per_core,
- &opt.cpu_bind_type)) {
- exit(error_exit);
- }
- break;
- case LONG_OPT_BLRTS_IMAGE:
- xfree(opt.blrtsimage);
- opt.blrtsimage = xstrdup(optarg);
- break;
- case LONG_OPT_LINUX_IMAGE:
- xfree(opt.linuximage);
- opt.linuximage = xstrdup(optarg);
- break;
- case LONG_OPT_MLOADER_IMAGE:
- xfree(opt.mloaderimage);
- opt.mloaderimage = xstrdup(optarg);
- break;
- case LONG_OPT_RAMDISK_IMAGE:
- xfree(opt.ramdiskimage);
- opt.ramdiskimage = xstrdup(optarg);
- break;
- case LONG_OPT_REBOOT:
- #if defined HAVE_BG && !defined HAVE_BG_L_P
- info("WARNING: If your job is smaller than the block "
- "it is going to run on and other jobs are "
- "running on it the --reboot option will not be "
- "honored. If this is the case, contact your "
- "admin to reboot the block for you.");
- #endif
- opt.reboot = true;
- break;
- case LONG_OPT_WRAP:
- /* handled in process_options_first_pass() */
- break;
- case LONG_OPT_GET_USER_ENV:
- if (optarg)
- _proc_get_user_env(optarg);
- else
- opt.get_user_env_time = 0;
- break;
- case LONG_OPT_OPEN_MODE:
- if ((optarg[0] == 'a') || (optarg[0] == 'A'))
- opt.open_mode = OPEN_MODE_APPEND;
- else if ((optarg[0] == 't') || (optarg[0] == 'T'))
- opt.open_mode = OPEN_MODE_TRUNCATE;
- else {
- error("Invalid --open-mode argument: %s. "
- "Ignored", optarg);
- }
- break;
- case LONG_OPT_ACCTG_FREQ:
- opt.acctg_freq = _get_int(optarg, "acctg-freq");
- break;
- case LONG_OPT_PROPAGATE:
- xfree(opt.propagate);
- if (optarg)
- opt.propagate = xstrdup(optarg);
- else
- opt.propagate = xstrdup("ALL");
- break;
- case LONG_OPT_NETWORK:
- xfree(opt.network);
- opt.network = xstrdup(optarg);
- break;
- case LONG_OPT_WCKEY:
- xfree(opt.wckey);
- opt.wckey = xstrdup(optarg);
- break;
- case LONG_OPT_RESERVATION:
- xfree(opt.reservation);
- opt.reservation = xstrdup(optarg);
- break;
- case LONG_OPT_CHECKPOINT:
- xfree(opt.ckpt_interval_str);
- opt.ckpt_interval_str = xstrdup(optarg);
- break;
- case LONG_OPT_CHECKPOINT_DIR:
- xfree(opt.ckpt_dir);
- opt.ckpt_dir = xstrdup(optarg);
- break;
- case LONG_OPT_SIGNAL:
- if (get_signal_opts(optarg, &opt.warn_signal,
- &opt.warn_time)) {
- error("Invalid signal specification: %s",
- optarg);
- exit(error_exit);
- }
- break;
- case LONG_OPT_TIME_MIN:
- xfree(opt.time_min_str);
- opt.time_min_str = xstrdup(optarg);
- break;
- case LONG_OPT_GRES:
- if (!strcasecmp(optarg, "help") ||
- !strcasecmp(optarg, "list")) {
- print_gres_help();
- exit(0);
- }
- xfree(opt.gres);
- opt.gres = xstrdup(optarg);
- break;
- case LONG_OPT_WAIT_ALL_NODES:
- opt.wait_all_nodes = strtol(optarg, NULL, 10);
- break;
- case LONG_OPT_EXPORT:
- xfree(opt.export_env);
- opt.export_env = xstrdup(optarg);
- break;
- case LONG_OPT_EXPORT_FILE:
- xfree(opt.export_file);
- opt.export_file = xstrdup(optarg);
- break;
- case LONG_OPT_REQ_SWITCH:
- pos_delimit = strstr(optarg,"@");
- if (pos_delimit != NULL) {
- pos_delimit[0] = '\0';
- pos_delimit++;
- opt.wait4switch = time_str2secs(pos_delimit);
- }
- opt.req_switch = _get_int(optarg, "switches");
- break;
- default:
- if (spank_process_option (opt_char, optarg) < 0) {
- error("Unrecognized command line parameter %c",
- opt_char);
- exit(error_exit);
- }
- }
- }
- if (optind < argc) {
- error("Invalid argument: %s", argv[optind]);
- exit(error_exit);
- }
- spank_option_table_destroy (optz);
- }
- static void _proc_get_user_env(char *optarg)
- {
- char *end_ptr;
- if ((optarg[0] >= '0') && (optarg[0] <= '9'))
- opt.get_user_env_time = strtol(optarg, &end_ptr, 10);
- else {
- opt.get_user_env_time = 0;
- end_ptr = optarg;
- }
- if ((end_ptr == NULL) || (end_ptr[0] == '\0'))
- return;
- if ((end_ptr[0] == 's') || (end_ptr[0] == 'S'))
- opt.get_user_env_mode = 1;
- else if ((end_ptr[0] == 'l') || (end_ptr[0] == 'L'))
- opt.get_user_env_mode = 2;
- }
- static void _set_pbs_options(int argc, char **argv)
- {
- int opt_char, option_index = 0;
- char *pbs_opt_string = "+a:A:c:C:e:hIj:k:l:m:M:N:o:p:q:r:S:u:v:VWz";
- struct option pbs_long_options[] = {
- {"start_time", required_argument, 0, 'a'},
- {"account", required_argument, 0, 'A'},
- {"checkpoint", required_argument, 0, 'c'},
- {"working_dir", required_argument, 0, 'C'},
- {"error", required_argument, 0, 'e'},
- {"hold", no_argument, 0, 'h'},
- {"interactive", no_argument, 0, 'I'},
- {"join", optional_argument, 0, 'j'},
- {"keep", required_argument, 0, 'k'},
- {"resource_list", required_argument, 0, 'l'},
- {"mail_options", required_argument, 0, 'm'},
- {"mail_user_list", required_argument, 0, 'M'},
- {"job_name", required_argument, 0, 'N'},
- {"out", required_argument, 0, 'o'},
- {"priority", required_argument, 0, 'p'},
- {"destination", required_argument, 0, 'q'},
- {"rerunable", required_argument, 0, 'r'},
- {"script_path", required_argument, 0, 'S'},
- {"running_user", required_argument, 0, 'u'},
- {"variable_list", required_argument, 0, 'v'},
- {"all_env", no_argument, 0, 'V'},
- {"attributes", no_argument, 0, 'W'},
- {"no_std", no_argument, 0, 'z'},
- {NULL, 0, 0, 0}
- };
- optind = 0;
- while((opt_char = getopt_long(argc, argv, pbs_opt_string,
- pbs_long_options, &option_index))
- != -1) {
- switch (opt_char) {
- case 'a':
- opt.begin = parse_time(optarg, 0);
- break;
- case 'A':
- xfree(opt.account);
- opt.account = xstrdup(optarg);
- break;
- case 'c':
- break;
- case 'C':
- xfree(opt.cwd);
- opt.cwd = xstrdup(optarg);
- break;
- case 'e':
- xfree(opt.efname);
- if (strcasecmp(optarg, "none") == 0)
- opt.efname = xstrdup("/dev/null");
- else
- opt.efname = xstrdup(optarg);
- break;
- case 'h':
- opt.hold = true;
- break;
- case 'I':
- break;
- case 'j':
- break;
- case 'k':
- break;
- case 'l':
- _parse_pbs_resource_list(optarg);
- break;
- case 'm':
- opt.mail_type |= _parse_pbs_mail_type(optarg);
- if ((opt.mail_type == 0) && strcasecmp(optarg, "n")) {
- error("-m=%s invalid", optarg);
- exit(error_exit);
- }
- break;
- case 'M':
- xfree(opt.mail_user);…
Large files files are truncated, but you can click here to view the full file