-
Moe Jette authored
Added explicit call to log_init in scontrol and some additional logging VS: ----------------------------------------------------------------------
Moe Jette authoredAdded explicit call to log_init in scontrol and some additional logging VS: ----------------------------------------------------------------------
scontrol.c 18.63 KiB
/*
* scontrol - administration tool for slurm.
* provides interface to read, write, update, and configurations.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#if HAVE_INTTYPES_H
# include <inttypes.h>
#else /* !HAVE_INTTYPES_H */
# if HAVE_STDINT_H
# include <stdint.h>
# endif
#endif /* HAVE_INTTYPES_H */
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <src/api/slurm.h>
#include <src/common/log.h>
#include <src/common/nodelist.h>
#include <src/common/slurm_protocol_api.h>
#include <src/common/xmalloc.h>
#define BUF_SIZE 1024
#define max_input_fields 128
static char *command_name;
static int exit_flag; /* program to terminate if =1 */
static int quiet_flag; /* quiet=1, verbose=-1, normal=0 */
static int input_words; /* number of words of input permitted */
void dump_command (int argc, char *argv[]);
int get_command (int *argc, char *argv[]);
void print_build (char *build_param);
void print_job (char * job_id_str);
void print_node (char *node_name, node_info_msg_t *node_info_ptr);
void print_node_list (char *node_list);
void print_part (char *partition_name);
int process_command (int argc, char *argv[]);
int update_it (int argc, char *argv[]);
void usage ();
int
main (int argc, char *argv[])
{
int error_code, i, input_field_count;
char **input_fields;
log_options_t opts = LOG_OPTS_STDERR_ONLY ;
command_name = argv[0];
exit_flag = 0;
input_field_count = 0;
quiet_flag = 0;
log_init(argv[0], opts, SYSLOG_FACILITY_DAEMON, NULL);
if (argc > max_input_fields) /* bogus input, but let's continue anyway */
input_words = argc;
else
input_words = 128;
input_fields = (char **) xmalloc (sizeof (char *) * input_words);
for (i = 1; i < argc; i++) {
if (strcmp (argv[i], "-q") == 0) {
quiet_flag = 1;
}
else if (strcmp (argv[i], "quiet") == 0) {
quiet_flag = 1;
}
else if (strcmp (argv[i], "-v") == 0) {
quiet_flag = -1;
}
else if (strcmp (argv[i], "verbose") == 0) {
quiet_flag = -1;
}
else {
input_fields[input_field_count++] = argv[i];
}
}
if (input_field_count)
exit_flag = 1;
else
error_code = get_command (&input_field_count, input_fields);
while (1) {
#if DEBUG_MODULE
dump_command (input_field_count, input_fields);
#endif
error_code =
process_command (input_field_count, input_fields);
if (error_code != 0)
break;
if (exit_flag == 1)
break;
error_code = get_command (&input_field_count, input_fields);
if (error_code != 0)
break;
}
exit (error_code);
}
/*
* dump_command - dump the user's command
* input: argc - count of arguments
* argv - the arguments
*/
void
dump_command (int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++) {
printf ("arg %d:%s:\n", i, argv[i]);
}
}
/*
* get_command - get a command from the user
* input: argc - location to store count of arguments
* argv - location to store the argument list
* output: returns error code, 0 if no problems
*/
int
get_command (int *argc, char **argv)
{
static char *in_line;
static int in_line_size = 0;
int in_line_pos = 0;
int temp_char, i;
if (in_line_size == 0) {
in_line_size += BUF_SIZE;
in_line = (char *) xmalloc (in_line_size);
if (in_line == NULL) {
fprintf (stderr, "%s: error %d allocating memory\n",
command_name, errno);
in_line_size = 0;
return ENOMEM;
}
}
printf ("scontrol: ");
*argc = 0;
in_line_pos = 0;
while (1) {
temp_char = getc (stdin);
if (temp_char == EOF)
break;
if (temp_char == (int) '\n')
break;
if ((in_line_pos + 2) >= in_line_size) {
in_line_size += BUF_SIZE;
xrealloc (in_line, in_line_size);
if (in_line == NULL) {
fprintf (stderr,
"%s: error %d allocating memory\n",
command_name, errno);
in_line_size = 0;
return ENOMEM;
}
}
in_line[in_line_pos++] = (char) temp_char;
}
in_line[in_line_pos] = (char) NULL;
for (i = 0; i < in_line_pos; i++) {
if (isspace ((int) in_line[i]))
continue;
if (((*argc) + 1) > max_input_fields) { /* really bogus input line */
fprintf (stderr, "%s: over %d fields in line: %s\n",
command_name, input_words, in_line);
return E2BIG;
}
argv[(*argc)++] = &in_line[i];
for (i++; i < in_line_pos; i++) {
if (!isspace ((int) in_line[i]))
continue;
in_line[i] = (char) NULL;
break;
}
}
return 0;
}
/*
* print_build - print the specified build parameter and value
* input: build_param - NULL to print all parameters and values
*/
void
print_build (char *build_param)
{
int error_code;
static build_info_msg_t *old_build_table_ptr = NULL;
build_info_msg_t *build_table_ptr = NULL;
if (old_build_table_ptr) {
error_code = slurm_load_build (old_build_table_ptr->last_update,
&build_table_ptr);
if (error_code == 0)
slurm_free_build_info(old_build_table_ptr);
else if (error_code == SLURM_NO_CHANGE_IN_DATA) {
build_table_ptr = old_build_table_ptr;
error_code = 0;
if (quiet_flag == -1)
printf ("slurm_load_build no change in data\n");
}
}
else
error_code = slurm_load_build ((time_t) NULL, &build_table_ptr);
if (error_code) {
if (quiet_flag != 1)
printf ("slurm_load_build error %d\n", error_code);
return;
}
old_build_table_ptr = build_table_ptr;
if (build_param == NULL ||
strcmp (build_param, "BACKUP_INTERVAL") == 0)
printf ("BACKUP_INTERVAL = %u\n",
build_table_ptr->backup_interval);
if (build_param == NULL ||
strcmp (build_param, "BACKUP_LOCATION") == 0)
printf ("BACKUP_LOCATION = %s\n",
build_table_ptr->backup_location);
if (build_param == NULL ||
strcmp (build_param, "BACKUP_MACHINE") == 0)
printf ("BACKUP_MACHINE = %s\n",
build_table_ptr->backup_machine);
if (build_param == NULL ||
strcmp (build_param, "CONTROL_DAEMON") == 0)
printf ("CONTROL_DAEMON = %s\n",
build_table_ptr->control_daemon);
if (build_param == NULL ||
strcmp (build_param, "CONTROL_MACHINE") == 0)
printf ("CONTROL_MACHINE = %s\n",
build_table_ptr->control_machine);
if (build_param == NULL ||
strcmp (build_param, "EPILOG") == 0)
printf ("EPILOG = %s\n", build_table_ptr->epilog);
if (build_param == NULL ||
strcmp (build_param, "FAST_SCHEDULE") == 0)
printf ("FAST_SCHEDULE = %u\n",
build_table_ptr->fast_schedule);
if (build_param == NULL ||
strcmp (build_param, "HASH_BASE") == 0)
printf ("HASH_BASE = %u\n",
build_table_ptr->hash_base);
if (build_param == NULL ||
strcmp (build_param, "HEARTBEAT_INTERVAL") == 0)
printf ("HEARTBEAT_INTERVAL = %u\n",
build_table_ptr->heartbeat_interval);
if (build_param == NULL ||
strcmp (build_param, "INIT_PROGRAM") == 0)
printf ("INIT_PROGRAM = %s\n", build_table_ptr->init_program);
if (build_param == NULL ||
strcmp (build_param, "KILL_WAIT") == 0)
printf ("KILL_WAIT = %u\n", build_table_ptr->kill_wait);
if (build_param == NULL ||
strcmp (build_param, "PRIORITIZE") == 0)
printf ("PRIORITIZE = %s\n", build_table_ptr->prioritize);
if (build_param == NULL ||
strcmp (build_param, "PROLOG") == 0)
printf ("PROLOG = %s\n", build_table_ptr->prolog);
if (build_param == NULL ||
strcmp (build_param, "SERVER_DAEMON") == 0)
printf ("SERVER_DAEMON = %s\n",
build_table_ptr->server_daemon);
if (build_param == NULL ||
strcmp (build_param, "SERVER_TIMEOUT") == 0)
printf ("SERVER_TIMEOUT = %u\n",
build_table_ptr->server_timeout);
if (build_param == NULL ||
strcmp (build_param, "SLURM_CONF") == 0)
printf ("SLURM_CONF = %s\n", build_table_ptr->slurm_conf);
if (build_param == NULL ||
strcmp (build_param, "TMP_FS") == 0)
printf ("TMP_FS = %s\n", build_table_ptr->tmp_fs);
}
/*
* print_job - print the specified job's information
* input: job_id - job's id or NULL to print information about all jobs
*/
void
print_job (char * job_id_str)
{
int error_code, i;
uint32_t job_id = 0;
static job_info_msg_t *old_job_buffer_ptr = NULL;
job_info_msg_t * job_buffer_ptr = NULL;
job_table_t *job_ptr = NULL;
if (old_job_buffer_ptr) {
error_code = slurm_load_jobs (old_job_buffer_ptr->last_update,
&job_buffer_ptr);
if (error_code == 0)
slurm_free_job_info (old_job_buffer_ptr);
else if (error_code == SLURM_NO_CHANGE_IN_DATA) {
job_buffer_ptr = old_job_buffer_ptr;
error_code = 0;
if (quiet_flag == -1)
printf ("slurm_free_job_info no change in data\n");
}
}
else
error_code = slurm_load_jobs ((time_t) NULL, &job_buffer_ptr);
if (error_code) {
if (quiet_flag != 1)
printf ("slurm_load_job error %d\n", error_code);
return;
}
else if (error_code == 0)
old_job_buffer_ptr = job_buffer_ptr;
if (quiet_flag == -1)
printf ("last_update_time=%ld\n", (long) job_buffer_ptr->last_update);
if (job_id_str)
job_id = (uint32_t) strtol (job_id_str, (char **)NULL, 10);
job_ptr = job_buffer_ptr->job_array ;
for (i = 0; i < job_buffer_ptr->record_count; i++) {
if (job_id_str && job_id != job_ptr[i].job_id)
continue;
slurm_print_job_table (stdout, & job_ptr[i] ) ;
if (job_id_str)
break;
}
}
/*
* print_node - print the specified node's information
* input: node_name - NULL to print all node information
* node_ptr - pointer to node table of information
* NOTE: call this only after executing load_node, called from print_node_list
* NOTE: To avoid linear searches, we remember the location of the last name match
*/
void
print_node (char *node_name, node_info_msg_t * node_buffer_ptr)
{
int i, j;
static int last_inx = 0;
for (j = 0; j < node_buffer_ptr->record_count; j++) {
if (node_name) {
i = (j + last_inx) % node_buffer_ptr->record_count;
if (strcmp (node_name, node_buffer_ptr->node_array[i].name) != 0)
continue;
}
else
i = j;
slurm_print_node_table (stdout, & node_buffer_ptr->node_array[i]);
if (node_name) {
last_inx = i;
break;
}
}
}
/*
* print_node_list - print information about the supplied node list (or regular expression)
* input: node_list - print information about the supplied node list (or regular expression)
*/
void
print_node_list (char *node_list)
{
static node_info_msg_t *old_node_info_ptr = NULL;
node_info_msg_t *node_info_ptr = NULL;
int start_inx, end_inx, count_inx, error_code, i;
char *str_ptr1, *str_ptr2, *format, *my_node_list;
char this_node_name[BUF_SIZE];
if (old_node_info_ptr) {
error_code = slurm_load_node (old_node_info_ptr->last_update,
&node_info_ptr);
if (error_code == 0)
slurm_free_node_info (old_node_info_ptr);
else if (error_code == SLURM_NO_CHANGE_IN_DATA) {
node_info_ptr = old_node_info_ptr;
error_code = 0;
if (quiet_flag == -1)
printf ("slurm_free_job_info no change in data\n");
}
}
else
error_code = slurm_load_node ((time_t) NULL, &node_info_ptr);
if (error_code) {
if (quiet_flag != 1)
printf ("load_node error %d\n", error_code);
return;
}
else if (error_code == 0)
old_node_info_ptr = node_info_ptr;
if (quiet_flag == -1)
printf ("last_update_time=%ld, records=%d\n",
(long) node_info_ptr->last_update, node_info_ptr->record_count);
if (node_list == NULL) {
print_node (NULL, node_info_ptr);
}
else {
format = NULL;
my_node_list = xmalloc (strlen (node_list) + 1);
if (my_node_list == NULL) {
if (quiet_flag != 1)
fprintf (stderr,
"unable to allocate memory\n");
abort ();
}
strcpy (my_node_list, node_list);
str_ptr2 = (char *) strtok_r (my_node_list, ",", &str_ptr1);
while (str_ptr2) { /* break apart by comma separators */
error_code =
parse_node_names (str_ptr2, &format,
&start_inx, &end_inx,
&count_inx);
if (error_code) {
if (quiet_flag != 1)
fprintf (stderr,
"invalid node name specification: %s\n",
str_ptr2);
break;
}
if (strlen (format) >= sizeof (this_node_name)) {
if (quiet_flag != 1)
fprintf (stderr,
"invalid node name specification: %s\n",
format);
xfree (format);
break;
}
for (i = start_inx; i <= end_inx; i++) {
if (count_inx == 0)
strncpy (this_node_name, format,
sizeof (this_node_name));
else
sprintf (this_node_name, format, i);
print_node (this_node_name, node_info_ptr);
}
if (format)
xfree (format);
str_ptr2 = (char *) strtok_r (NULL, ",", &str_ptr1);
}
xfree (my_node_list);
}
/* Temporary logic to clean out immediately */
slurm_free_node_info (old_node_info_ptr);
old_node_info_ptr=NULL;
return;
}
/*
* print_part - print the specified partition's information
* input: partition_name - NULL to print information about all partition
*/
void
print_part (char *partition_name)
{
int error_code, i;
static partition_info_msg_t *old_part_info_ptr = NULL;
partition_info_msg_t *part_info_ptr = NULL;
partition_table_msg_t *part_ptr = NULL;
if (old_part_info_ptr) {
error_code = slurm_load_partitions (old_part_info_ptr->last_update,
&part_info_ptr);
if (error_code == 0) {
/* slurm_free_partition_info (old_part_info_ptr); */
}
else if (error_code == SLURM_NO_CHANGE_IN_DATA) {
part_info_ptr = old_part_info_ptr;
error_code = 0;
if (quiet_flag == -1)
printf ("slurm_load_part no change in data\n");
}
}
else
error_code = slurm_load_partitions ((time_t) NULL, &part_info_ptr);
if (error_code > 0) {
if (quiet_flag != 1)
printf ("slurm_load_part error %d\n", error_code);
return;
}
else
old_part_info_ptr = part_info_ptr;
if (quiet_flag == -1)
printf ("last_update_time=%ld\n", (long) part_info_ptr->last_update);
part_ptr = part_info_ptr->partition_array;
for (i = 0; i < part_info_ptr->record_count; i++) {
if (partition_name &&
strcmp (partition_name, part_ptr[i].name) != 0)
continue;
slurm_print_partition_table (stdout, & part_ptr[i] ) ;
if (partition_name)
break;
}
/* Temporary logic to clean out immediately */
slurm_free_partition_info (old_part_info_ptr);
old_part_info_ptr=NULL;
}
/*
* process_command - process the user's command
* input: argc - count of arguments
* argv - the arguments
* ourput: return code is 0 or errno (only for errors fatal to scontrol)
*/
int
process_command (int argc, char *argv[])
{
int error_code;
if ((strcmp (argv[0], "exit") == 0) ||
(strcmp (argv[0], "quit") == 0)) {
if (argc > 1)
fprintf (stderr,
"too many arguments for keyword:%s\n",
argv[0]);
exit_flag = 1;
}
else if (strcmp (argv[0], "help") == 0) {
if (argc > 1)
fprintf (stderr,
"too many arguments for keyword:%s\n",
argv[0]);
usage ();
}
else if (strcmp (argv[0], "quiet") == 0) {
if (argc > 1)
fprintf (stderr,
"too many arguments for keyword:%s\n",
argv[0]);
quiet_flag = 1;
}
else if (strncmp (argv[0], "reconfigure", 7) == 0) {
if (argc > 2)
fprintf (stderr,
"too many arguments for keyword:%s\n",
argv[0]);
error_code = slurm_reconfigure ();
if ((error_code != 0) && (quiet_flag != 1))
fprintf (stderr, "error %d from reconfigure\n",
error_code);
}
else if (strcmp (argv[0], "show") == 0) {
if (argc > 3) {
if (quiet_flag != 1)
fprintf (stderr,
"too many arguments for keyword:%s\n",
argv[0]);
}
else if (argc < 2) {
if (quiet_flag != 1)
fprintf (stderr,
"too few arguments for keyword:%s\n",
argv[0]);
}
else if (strncmp (argv[1], "build", 3) == 0) {
if (argc > 2)
print_build (argv[2]);
else
print_build (NULL);
}
else if (strncmp (argv[1], "jobs", 3) == 0) {
if (argc > 2)
print_job (argv[2]);
else
print_job (NULL);
}
else if (strncmp (argv[1], "nodes", 3) == 0) {
if (argc > 2)
print_node_list (argv[2]);
else
print_node_list (NULL);
}
else if (strncmp (argv[1], "partitions", 3) == 0) {
if (argc > 2)
print_part (argv[2]);
else
print_part (NULL);
}
else if (quiet_flag != 1) {
fprintf (stderr,
"invalid entity:%s for keyword:%s \n",
argv[1], argv[0]);
}
}
else if (strcmp (argv[0], "update") == 0) {
if (argc < 2) {
fprintf (stderr, "too few arguments for %s keyword\n",
argv[0]);
return 0;
}
update_it ((argc - 1), &argv[1]);
}
else if (strcmp (argv[0], "verbose") == 0) {
if (argc > 1) {
fprintf (stderr,
"too many arguments for %s keyword\n",
argv[0]);
}
quiet_flag = -1;
}
else if (strcmp (argv[0], "version") == 0) {
if (argc > 1) {
fprintf (stderr,
"too many arguments for %s keyword\n",
argv[0]);
}
printf ("%s version 0.1\n", command_name);
}
else
fprintf (stderr, "invalid keyword: %s\n", argv[0]);
return 0;
}
/*
* update_it - update the slurm configuration per the supplied arguments
* input: argc - count of arguments
* argv - list of arguments
* output: returns 0 if no error, errno otherwise
*/
int
update_it (int argc, char *argv[])
{
char *in_line;
int error_code, i, in_line_size;
in_line_size = BUF_SIZE;
in_line = (char *) xmalloc (in_line_size);
if (in_line == NULL) {
fprintf (stderr, "%s: error %d allocating memory\n",
command_name, errno);
return ENOMEM;
}
strcpy (in_line, "");
for (i = 0; i < argc; i++) {
if ((strlen (in_line) + strlen (argv[i]) + 2) > in_line_size) {
in_line_size += BUF_SIZE;
xrealloc (in_line, in_line_size);
if (in_line == NULL) {
fprintf (stderr,
"%s: error %d allocating memory\n",
command_name, errno);
return ENOMEM;
}
}
strcat (in_line, argv[i]);
strcat (in_line, " ");
}
error_code = slurm_update_config (in_line);
xfree (in_line);
return error_code;
}
/* usage - show the valid scontrol commands */
void
usage () {
printf ("%s [-q | -v] [<keyword>]\n", command_name);
printf (" -q is equivalent to the keyword \"quiet\" described below.\n");
printf (" -v is equivalent to the keyword \"verbose\" described below.\n");
printf (" <keyword> may be omitted from the execute line and %s will execute in interactive\n",
command_name);
printf (" mode to process multiple keywords (i.e. commands). valid <entity> values are:\n");
printf (" build, job, node, and partition. node names may be sepcified using regular simple \n");
printf (" expressions. valid <keyword> values are:\n");
printf (" exit terminate this command.\n");
printf (" help print this description of use.\n");
printf (" quiet print no messages other than error messages.\n");
printf (" quit terminate this command.\n");
printf (" reconfigure re-read configuration files.\n");
printf (" show <entity> [<id>] display state of identified entity, default is all records.\n");
printf (" update <options> update configuration per configuration file format.\n");
printf (" verbose enable detailed logging.\n");
printf (" version display tool version number.\n");
}