static int _set_cond(int *start, int argc, char *argv[], slurmdb_event_cond_t *event_cond, List format_list) { int i, end = 0; int set = 0; int command_len = 0; int local_cluster_flag = 0; int all_time_flag = 0; if(!event_cond->cluster_list) event_cond->cluster_list = list_create(slurm_destroy_char); for (i=(*start); i<argc; i++) { end = parse_option_end(argv[i]); if(!end) command_len=strlen(argv[i]); else { command_len=end-1; if (argv[i][end] == '=') { end++; } } if(!end && !strncasecmp(argv[i], "all_clusters", MAX(command_len, 5))) { local_cluster_flag = 1; } else if(!end && !strncasecmp(argv[i], "all_time", MAX(command_len, 5))) { all_time_flag = 1; } else if(!end && !strncasecmp(argv[i], "where", MAX(command_len, 5))) { continue; } else if(!end || (!strncasecmp (argv[i], "Events", MAX(command_len, 1)))) { ListIterator itr = NULL; List tmp_list = list_create(slurm_destroy_char); char *temp = NULL; if(slurm_addto_char_list(tmp_list, argv[i]+end)) set = 1; /* check to make sure user gave ints here */ itr = list_iterator_create(tmp_list); while ((temp = list_next(itr))) { if(!strncasecmp("Node", temp, MAX(strlen(temp), 1))) { if(event_cond->event_type) event_cond->event_type = SLURMDB_EVENT_ALL; else event_cond->event_type = SLURMDB_EVENT_NODE; } else if(!strncasecmp("Cluster", temp, MAX(strlen(temp), 1))) { if(event_cond->event_type) event_cond->event_type = SLURMDB_EVENT_ALL; else event_cond->event_type = SLURMDB_EVENT_CLUSTER; } else { exit_code=1; fprintf(stderr, " Unknown event type: '%s' " "Valid events are Cluster " "and Node.\n", temp); } } list_iterator_destroy(itr); list_destroy(tmp_list); } else if (!strncasecmp (argv[i], "Clusters", MAX(command_len, 1))) { if(!event_cond->cluster_list) event_cond->cluster_list = list_create(slurm_destroy_char); if(slurm_addto_char_list(event_cond->cluster_list, argv[i]+end)) set = 1; } else if (!strncasecmp (argv[i], "End", MAX(command_len, 1))) { event_cond->period_end = parse_time(argv[i]+end, 1); set = 1; } else if (!strncasecmp (argv[i], "Format", MAX(command_len, 1))) { if(format_list) slurm_addto_char_list(format_list, argv[i]+end); } else if (!strncasecmp (argv[i], "MinCpus", MAX(command_len, 2))) { if (get_uint(argv[i]+end, &event_cond->cpus_min, "MinCpus") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "MaxCpus", MAX(command_len, 2))) { if (get_uint(argv[i]+end, &event_cond->cpus_max, "MaxCpus") == SLURM_SUCCESS) set = 1; } else if (!strncasecmp (argv[i], "Nodes", MAX(command_len, 1))) { if(!event_cond->node_list) event_cond->node_list = list_create(slurm_destroy_char); if(slurm_addto_char_list(event_cond->node_list, argv[i]+end)) set = 1; } else if (!strncasecmp (argv[i], "Reason", MAX(command_len, 1))) { if(!event_cond->reason_list) event_cond->reason_list = list_create(slurm_destroy_char); if(slurm_addto_char_list(event_cond->reason_list, argv[i]+end)) set = 1; } else if (!strncasecmp (argv[i], "Start", MAX(command_len, 4))) { event_cond->period_start = parse_time(argv[i]+end, 1); set = 1; } else if (!strncasecmp (argv[i], "States", MAX(command_len, 4))) { if(!event_cond->state_list) event_cond->state_list = list_create(slurm_destroy_char); if(_addto_state_char_list(event_cond->state_list, argv[i]+end)) { event_cond->event_type = SLURMDB_EVENT_NODE; set = 1; } } else if (!strncasecmp (argv[i], "User", MAX(command_len, 1))) { if(!event_cond->reason_uid_list) event_cond->reason_uid_list = list_create(slurm_destroy_char); if(_addto_id_char_list(event_cond->reason_uid_list, argv[i]+end, 0)) { event_cond->event_type = SLURMDB_EVENT_NODE; set = 1; } } else { exit_code=1; fprintf(stderr, " Unknown condition: %s\n", argv[i]); } } (*start) = i; if(!local_cluster_flag && !list_count(event_cond->cluster_list)) { char *temp = slurm_get_cluster_name(); if(temp) list_append(event_cond->cluster_list, temp); } if(!all_time_flag && !event_cond->period_start) { event_cond->period_start = time(NULL); if(!event_cond->state_list) { struct tm start_tm; if(!localtime_r(&event_cond->period_start, &start_tm)) { fprintf(stderr, " Couldn't get localtime from %ld", (long)event_cond->period_start); exit_code=1; return 0; } start_tm.tm_sec = 0; start_tm.tm_min = 0; start_tm.tm_hour = 0; start_tm.tm_mday--; start_tm.tm_isdst = -1; event_cond->period_start = mktime(&start_tm); } } return set; }
void parse_command_line(int argc, char **argv) { extern int optind; int c, i, optionIndex = 0; char *end = NULL, *start = NULL, *acct_type = NULL; slurmdb_selected_step_t *selected_step = NULL; ListIterator itr = NULL; struct stat stat_buf; char *dot = NULL; bool brief_output = FALSE, long_output = FALSE; bool all_users = 0; bool all_clusters = 0; slurmdb_job_cond_t *job_cond = params.job_cond; log_options_t opts = LOG_OPTS_STDERR_ONLY ; int verbosity; /* count of -v options */ bool set; static struct option long_options[] = { {"allusers", no_argument, 0, 'a'}, {"accounts", required_argument, 0, 'A'}, {"allocations", no_argument, ¶ms.opt_allocs, OPT_LONG_ALLOCS}, {"brief", no_argument, 0, 'b'}, {"completion", no_argument, ¶ms.opt_completion, 'c'}, {"duplicates", no_argument, ¶ms.opt_dup, OPT_LONG_DUP}, {"helpformat", no_argument, 0, 'e'}, {"help-fields", no_argument, 0, 'e'}, {"endtime", required_argument, 0, 'E'}, {"file", required_argument, 0, 'f'}, {"gid", required_argument, 0, 'g'}, {"group", required_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {"helpformat", no_argument, ¶ms.opt_help, OPT_LONG_HELP}, {"name", required_argument, 0, OPT_LONG_NAME}, {"nnodes", required_argument, 0, 'i'}, {"ncpus", required_argument, 0, 'I'}, {"jobs", required_argument, 0, 'j'}, {"timelimit-min", required_argument, 0, 'k'}, {"timelimit-max", required_argument, 0, 'K'}, {"long", no_argument, 0, 'l'}, {"allclusters", no_argument, 0, 'L'}, {"cluster", required_argument, 0, 'M'}, {"clusters", required_argument, 0, 'M'}, {"nodelist", required_argument, 0, 'N'}, {"noheader", no_argument, 0, 'n'}, {"fields", required_argument, 0, 'o'}, {"format", required_argument, 0, 'o'}, {"parsable", no_argument, 0, 'p'}, {"parsable2", no_argument, 0, 'P'}, {"qos", required_argument, 0, 'q'}, {"partition", required_argument, 0, 'r'}, {"state", required_argument, 0, 's'}, {"starttime", required_argument, 0, 'S'}, {"truncate", no_argument, 0, 'T'}, {"uid", required_argument, 0, 'u'}, {"usage", no_argument, ¶ms.opt_help, OPT_LONG_USAGE}, {"user", required_argument, 0, 'u'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"wckeys", required_argument, 0, 'W'}, {"associations", required_argument, 0, 'x'}, {0, 0, 0, 0}}; params.opt_uid = getuid(); params.opt_gid = getgid(); verbosity = 0; log_init("sacct", opts, SYSLOG_FACILITY_DAEMON, NULL); opterr = 1; /* Let getopt report problems to the user */ while (1) { /* now cycle through the command line */ c = getopt_long(argc, argv, "aA:bcC:dDeE:f:g:hi:I:j:k:K:lLM:nN:o:OpPq:r:s:S:Ttu:vVW:x:X", long_options, &optionIndex); if (c == -1) break; switch (c) { case 'a': all_users = 1; break; case 'A': if(!job_cond->acct_list) job_cond->acct_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->acct_list, optarg); break; case 'b': brief_output = true; break; case 'c': params.opt_completion = 1; break; case 'C': /* 'C' is deprecated since 'M' is cluster on everything else. */ case 'M': if(!strcasecmp(optarg, "-1")) { all_clusters = 1; break; } all_clusters=0; if(!job_cond->cluster_list) job_cond->cluster_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->cluster_list, optarg); break; case 'D': params.opt_dup = 1; break; case 'e': params.opt_help = 2; break; case 'E': job_cond->usage_end = parse_time(optarg, 1); if (errno == ESLURM_INVALID_TIME_VALUE) exit(1); break; case 'f': xfree(params.opt_filein); params.opt_filein = xstrdup(optarg); break; case 'g': if(!job_cond->groupid_list) job_cond->groupid_list = list_create(slurm_destroy_char); _addto_id_char_list(job_cond->groupid_list, optarg, 1); break; case 'h': params.opt_help = 1; break; case 'i': set = get_resource_arg_range( optarg, "requested node range", (int *)&job_cond->nodes_min, (int *)&job_cond->nodes_max, true); if (set == false) { error("invalid node range -i '%s'", optarg); exit(1); } break; case 'I': set = get_resource_arg_range( optarg, "requested cpu range", (int *)&job_cond->cpus_min, (int *)&job_cond->cpus_max, true); if (set == false) { error("invalid cpu range -i '%s'", optarg); exit(1); } break; case 'j': if ((strspn(optarg, "0123456789, ") < strlen(optarg)) && (strspn(optarg, ".batch0123456789, ") < strlen(optarg))) { fprintf(stderr, "Invalid jobs list: %s\n", optarg); exit(1); } if(!job_cond->step_list) job_cond->step_list = list_create( slurmdb_destroy_selected_step); _addto_step_list(job_cond->step_list, optarg); break; case 'k': job_cond->timelimit_min = time_str2mins(optarg); if (((int32_t)job_cond->timelimit_min <= 0) && (job_cond->timelimit_min != INFINITE)) fatal("Invalid time limit specification"); break; case 'K': job_cond->timelimit_max = time_str2mins(optarg); if (((int32_t)job_cond->timelimit_max <= 0) && (job_cond->timelimit_max != INFINITE)) fatal("Invalid time limit specification"); break; case 'L': all_clusters = 1; break; case 'l': long_output = true; break; case 'n': print_fields_have_header = 0; break; case 'N': if(job_cond->used_nodes) { error("Aleady asked for nodes '%s'", job_cond->used_nodes); break; } job_cond->used_nodes = xstrdup(optarg); break; case OPT_LONG_NAME: if(!job_cond->jobname_list) job_cond->jobname_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->jobname_list, optarg); break; case 'o': xstrfmtcat(params.opt_field_list, "%s,", optarg); break; case 'p': print_fields_parsable_print = PRINT_FIELDS_PARSABLE_ENDING; break; case 'P': print_fields_parsable_print = PRINT_FIELDS_PARSABLE_NO_ENDING; break; case 'q': if (!g_qos_list) { slurmdb_qos_cond_t qos_cond; memset(&qos_cond, 0, sizeof(slurmdb_qos_cond_t)); qos_cond.with_deleted = 1; g_qos_list = slurmdb_qos_get( acct_db_conn, &qos_cond); } if(!job_cond->qos_list) job_cond->qos_list = list_create(slurm_destroy_char); if(!slurmdb_addto_qos_char_list(job_cond->qos_list, g_qos_list, optarg, 0)) fatal("problem processing qos list"); break; case 'r': if(!job_cond->partition_list) job_cond->partition_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->partition_list, optarg); break; case 's': if(!job_cond->state_list) job_cond->state_list = list_create(slurm_destroy_char); _addto_state_char_list(job_cond->state_list, optarg); break; case 'S': job_cond->usage_start = parse_time(optarg, 1); if (errno == ESLURM_INVALID_TIME_VALUE) exit(1); break; case 'T': job_cond->without_usage_truncation = 0; break; case 'U': params.opt_help = 3; break; case 'u': if(!strcmp(optarg, "-1")) { all_users = 1; break; } all_users = 0; if(!job_cond->userid_list) job_cond->userid_list = list_create(slurm_destroy_char); _addto_id_char_list(job_cond->userid_list, optarg, 0); break; case 'v': /* Handle -vvv thusly... */ verbosity++; break; case 'W': if(!job_cond->wckey_list) job_cond->wckey_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->wckey_list, optarg); break; case 'V': print_slurm_version(); exit(0); case 'x': if(!job_cond->associd_list) job_cond->associd_list = list_create(slurm_destroy_char); slurm_addto_char_list(job_cond->associd_list, optarg); break; case 't': case 'X': params.opt_allocs = 1; break; case ':': case '?': /* getopt() has explained it */ exit(1); } } if (verbosity) { opts.stderr_level += verbosity; opts.prefix_level = 1; log_alter(opts, 0, NULL); } /* Now set params.opt_dup, unless they've already done so */ if (params.opt_dup < 0) /* not already set explicitly */ params.opt_dup = 0; job_cond->duplicates = params.opt_dup; job_cond->without_steps = params.opt_allocs; if(!job_cond->usage_start && !job_cond->step_list) { struct tm start_tm; job_cond->usage_start = time(NULL); if (!localtime_r(&job_cond->usage_start, &start_tm)) { error("Couldn't get localtime from %ld", (long)job_cond->usage_start); return; } start_tm.tm_sec = 0; start_tm.tm_min = 0; start_tm.tm_hour = 0; start_tm.tm_isdst = -1; job_cond->usage_start = mktime(&start_tm); } if(verbosity > 0) { char *start_char =NULL, *end_char = NULL; start_char = xstrdup(ctime(&job_cond->usage_start)); /* remove the new line */ start_char[strlen(start_char)-1] = '\0'; if(job_cond->usage_end) { end_char = xstrdup(ctime(&job_cond->usage_end)); /* remove the new line */ end_char[strlen(end_char)-1] = '\0'; } else end_char = xstrdup("Now"); info("Jobs eligible from %s - %s", start_char, end_char); xfree(start_char); xfree(end_char); } debug("Options selected:\n" "\topt_completion=%d\n" "\topt_dup=%d\n" "\topt_field_list=%s\n" "\topt_help=%d\n" "\topt_allocs=%d", params.opt_completion, params.opt_dup, params.opt_field_list, params.opt_help, params.opt_allocs); if(params.opt_completion) { g_slurm_jobcomp_init(params.opt_filein); acct_type = slurm_get_jobcomp_type(); if ((strcmp(acct_type, "jobcomp/none") == 0) && (stat(params.opt_filein, &stat_buf) != 0)) { fprintf(stderr, "SLURM job completion is disabled\n"); exit(1); } xfree(acct_type); } else { slurm_acct_storage_init(params.opt_filein); acct_type = slurm_get_accounting_storage_type(); if ((strcmp(acct_type, "accounting_storage/none") == 0) && (stat(params.opt_filein, &stat_buf) != 0)) { fprintf(stderr, "SLURM accounting storage is disabled\n"); exit(1); } xfree(acct_type); acct_db_conn = slurmdb_connection_get(); if(errno != SLURM_SUCCESS) { error("Problem talking to the database: %m"); exit(1); } } /* specific clusters requested? */ if(all_clusters) { if(job_cond->cluster_list && list_count(job_cond->cluster_list)) { list_destroy(job_cond->cluster_list); job_cond->cluster_list = NULL; } debug2("Clusters requested:\tall"); } else if (job_cond->cluster_list && list_count(job_cond->cluster_list)) { debug2( "Clusters requested:"); itr = list_iterator_create(job_cond->cluster_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } else if(!job_cond->cluster_list || !list_count(job_cond->cluster_list)) { if(!job_cond->cluster_list) job_cond->cluster_list = list_create(slurm_destroy_char); if((start = slurm_get_cluster_name())) { list_append(job_cond->cluster_list, start); debug2("Clusters requested:\t%s", start); } } /* if any jobs or nodes are specified set to look for all users if none are set */ if(!job_cond->userid_list || !list_count(job_cond->userid_list)) if((job_cond->step_list && list_count(job_cond->step_list)) || job_cond->used_nodes) all_users=1; /* set all_users for user root if not requesting any */ if(!job_cond->userid_list && !params.opt_uid) all_users = 1; if(all_users) { if(job_cond->userid_list && list_count(job_cond->userid_list)) { list_destroy(job_cond->userid_list); job_cond->userid_list = NULL; } debug2("Userids requested:\tall"); } else if (job_cond->userid_list && list_count(job_cond->userid_list)) { debug2("Userids requested:"); itr = list_iterator_create(job_cond->userid_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } else if(!job_cond->userid_list || !list_count(job_cond->userid_list)) { if(!job_cond->userid_list) job_cond->userid_list = list_create(slurm_destroy_char); start = xstrdup_printf("%u", params.opt_uid); list_append(job_cond->userid_list, start); debug2("Userid requested\t: %s", start); } if (job_cond->groupid_list && list_count(job_cond->groupid_list)) { debug2("Groupids requested:"); itr = list_iterator_create(job_cond->groupid_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } /* specific partitions requested? */ if (job_cond->partition_list && list_count(job_cond->partition_list)) { debug2("Partitions requested:"); itr = list_iterator_create(job_cond->partition_list); while((start = list_next(itr))) debug2("\t: %s", start); list_iterator_destroy(itr); } /* specific qos' requested? */ if (job_cond->qos_list && list_count(job_cond->qos_list)) { start = get_qos_complete_str(g_qos_list, job_cond->qos_list); debug2("QOS requested\t: %s\n", start); xfree(start); } /* specific jobs requested? */ if (job_cond->step_list && list_count(job_cond->step_list)) { debug2("Jobs requested:"); itr = list_iterator_create(job_cond->step_list); while((selected_step = list_next(itr))) { if(selected_step->stepid != NO_VAL) debug2("\t: %d.%d", selected_step->jobid, selected_step->stepid); else debug2("\t: %d", selected_step->jobid); } list_iterator_destroy(itr); } /* specific states (completion state) requested? */ if (job_cond->state_list && list_count(job_cond->state_list)) { debug2("States requested:"); itr = list_iterator_create(job_cond->state_list); while((start = list_next(itr))) { debug2("\t: %s", job_state_string(atoi(start))); } list_iterator_destroy(itr); } if (job_cond->wckey_list && list_count(job_cond->wckey_list)) { debug2("Wckeys requested:"); itr = list_iterator_create(job_cond->wckey_list); while((start = list_next(itr))) debug2("\t: %s\n", start); list_iterator_destroy(itr); } if (job_cond->timelimit_min) { char time_str[128], tmp1[32], tmp2[32]; mins2time_str(job_cond->timelimit_min, tmp1, sizeof(tmp1)); sprintf(time_str, "%s", tmp1); if(job_cond->timelimit_max) { int len = strlen(tmp1); mins2time_str(job_cond->timelimit_max, tmp2, sizeof(tmp2)); sprintf(time_str+len, " - %s", tmp2); } debug2("Timelimit requested\t: %s", time_str); } /* specific jobnames requested? */ if (job_cond->jobname_list && list_count(job_cond->jobname_list)) { debug2("Jobnames requested:"); itr = list_iterator_create(job_cond->jobname_list); while((start = list_next(itr))) { debug2("\t: %s", start); } list_iterator_destroy(itr); } /* select the output fields */ if(brief_output) { if(params.opt_completion) dot = BRIEF_COMP_FIELDS; else dot = BRIEF_FIELDS; xstrfmtcat(params.opt_field_list, "%s,", dot); } if(long_output) { if(params.opt_completion) dot = LONG_COMP_FIELDS; else dot = LONG_FIELDS; xstrfmtcat(params.opt_field_list, "%s,", dot); } if (params.opt_field_list==NULL) { if(params.opt_completion) dot = DEFAULT_COMP_FIELDS; else dot = DEFAULT_FIELDS; xstrfmtcat(params.opt_field_list, "%s,", dot); } start = params.opt_field_list; while ((end = strstr(start, ","))) { char *tmp_char = NULL; int command_len = 0; int newlen = 0; *end = 0; while (isspace(*start)) start++; /* discard whitespace */ if(!(int)*start) continue; if((tmp_char = strstr(start, "\%"))) { newlen = atoi(tmp_char+1); tmp_char[0] = '\0'; } command_len = strlen(start); for (i = 0; fields[i].name; i++) { if (!strncasecmp(fields[i].name, start, command_len)) goto foundfield; } error("Invalid field requested: \"%s\"", start); exit(1); foundfield: if(newlen) fields[i].len = newlen; list_append(print_fields_list, &fields[i]); start = end + 1; }