diff --git a/doc/man/man1/sinfo.1 b/doc/man/man1/sinfo.1 index 68ab82404138c400f843ec9d59055a8a72371206..ec7affb8bd5a44add2fa0819b5b09427cfadbfa8 100644 --- a/doc/man/man1/sinfo.1 +++ b/doc/man/man1/sinfo.1 @@ -1,4 +1,4 @@ -.TH sinfo "1" "Slurm Commands" "Janury 2016" "Slurm Commands" +.TH sinfo "1" "Slurm Commands" "January 2016" "Slurm Commands" .SH "NAME" sinfo \- view information about Slurm nodes and partitions. @@ -325,7 +325,10 @@ Default time for any job in the format "days\-hours:minutes:seconds". Size of temporary disk space per node in megabytes. .TP \fBfeatures\fR -Features associated with the nodes. +Features available on the nodes. Also see \fBfeatures_act\fR. +.TP +\fBfeatures_act\fR +Features currently active on the nodes. Also see \fBfeatures\fR. .TP \fBgroups\fR Groups which may use the nodes. diff --git a/src/api/node_info.c b/src/api/node_info.c index 8a8ff14a8ba5a1baa2e01fbfcf9aaf78f6de821d..92ca2da352c8ea013105937aff82a37be5c83a6c 100644 --- a/src/api/node_info.c +++ b/src/api/node_info.c @@ -231,8 +231,16 @@ slurm_sprint_node_table (node_info_t * node_ptr, /****** Line ******/ snprintf(tmp_line, sizeof(tmp_line), - "AvailableFeatures=%s ActiveFeatures=%s", - node_ptr->features, node_ptr->features_act); + "AvailableFeatures=%s", node_ptr->features); + xstrcat(out, tmp_line); + if (one_liner) + xstrcat(out, " "); + else + xstrcat(out, "\n "); + + /****** Line ******/ + snprintf(tmp_line, sizeof(tmp_line), + "ActiveFeatures=%s", node_ptr->features_act); xstrcat(out, tmp_line); if (one_liner) xstrcat(out, " "); diff --git a/src/common/read_config.c b/src/common/read_config.c index 231e717ba692cdfe63fd73417a042c98d24ea8c9..35d1b651be7066dcaac9075abbd92c6b3c218a97 100644 --- a/src/common/read_config.c +++ b/src/common/read_config.c @@ -571,7 +571,8 @@ static int _parse_frontend(void **dest, slurm_parser_enum_t type, /* should not get here */ } -static void _add_knl_features(slurm_conf_node_t *n) +/* Expand a feature of "knl" to all appropriate KNL options */ +extern void add_knl_features(char **features) { static uint16_t avail_mcdram = 0, avail_numa = 0; static uint16_t default_mcdram = 0, default_numa = 0; @@ -580,17 +581,17 @@ static void _add_knl_features(slurm_conf_node_t *n) char *tmp_str, *token, *last = NULL; int i, j; - if (!n->feature) + if ((features == NULL) || (features[0] == NULL)) return; - i = strlen(n->feature) + 1; /* oversized */ + i = strlen(features[0]) + 1; /* oversized */ tmp_str = xmalloc(i); /* Remove white space from feature specification */ - for (i = 0, j = 0; n->feature[i]; i++) { - if (!isspace(n->feature[i])) - tmp_str[j++] = n->feature[i]; + for (i = 0, j = 0; features[0][i]; i++) { + if (!isspace(features[0][i])) + tmp_str[j++] = features[0][i]; } - strcpy(n->feature, tmp_str); + strcpy(*features, tmp_str); token = strtok_r(tmp_str, ",", &last); while (token) { @@ -614,13 +615,13 @@ static void _add_knl_features(slurm_conf_node_t *n) if (!has_mcdram) { tmp_str = knl_mcdram_str(avail_mcdram); - xstrfmtcat(n->feature, ",%s", tmp_str); + xstrfmtcat(*features, ",%s", tmp_str); xfree(tmp_str); } if (!has_numa) { tmp_str = knl_numa_str(avail_numa); - xstrfmtcat(n->feature, ",%s", tmp_str); + xstrfmtcat(*features, ",%s", tmp_str); xfree(tmp_str); } } @@ -639,6 +640,7 @@ static int _parse_nodename(void **dest, slurm_parser_enum_t type, {"CPUs", S_P_UINT16}, {"CPUSpecList", S_P_STRING}, {"Feature", S_P_STRING}, + {"Features", S_P_STRING}, {"Gres", S_P_STRING}, {"MemSpecLimit", S_P_UINT32}, {"NodeAddr", S_P_STRING}, @@ -726,9 +728,11 @@ static int _parse_nodename(void **dest, slurm_parser_enum_t type, if (!s_p_get_string(&n->cpu_spec_list, "CPUSpecList", tbl)) s_p_get_string(&n->cpu_spec_list, "CPUSpecList", dflt); - if (!s_p_get_string(&n->feature, "Feature", tbl)) - s_p_get_string(&n->feature, "Feature", dflt); - _add_knl_features(n); + if (!s_p_get_string(&n->feature, "Feature", tbl) && + !s_p_get_string(&n->feature, "Features", tbl) && + !s_p_get_string(&n->feature, "Feature", dflt)) + s_p_get_string(&n->feature, "Features", dflt); + add_knl_features(&n->feature); if (!s_p_get_string(&n->gres, "Gres", tbl)) s_p_get_string(&n->gres, "Gres", dflt); diff --git a/src/common/read_config.h b/src/common/read_config.h index 96f0ea20a834a56dbf40563c817a47dbe5b22a3c..7a322fed4a8f9ce7251adfede542d9b032e518d5 100644 --- a/src/common/read_config.h +++ b/src/common/read_config.h @@ -578,4 +578,8 @@ extern char *get_extra_conf_path(char *conf_name); */ extern bool run_in_daemon(char *daemons); +/* Expand a feature of "knl" to all appropriate KNL options + * features IN/OUT - Expand string as appropriate, must be xmalloc'ed */ +extern void add_knl_features(char **features); + #endif /* !_READ_CONFIG_H */ diff --git a/src/sinfo/opts.c b/src/sinfo/opts.c index c901b9f472c0302991fbb5bf3454e8336cacab33..0184cf3c3fb2f8f860643faf27e08e99394a50e7 100644 --- a/src/sinfo/opts.c +++ b/src/sinfo/opts.c @@ -3,7 +3,7 @@ ***************************************************************************** * Copyright (C) 2002-2007 The Regents of the University of California. * Copyright (C) 2008-2010 Lawrence Livermore National Security. - * Portions Copyright (C) 2010 SchedMD <http://www.schedmd.com>. + * Portions Copyright (C) 2010-2016 SchedMD <http://www.schedmd.com>. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Joey Ekstrom <ekstrom1@llnl.gov>, Morris Jette <jette1@llnl.gov> * CODE-OCEC-09-009. All rights reserved. @@ -606,6 +606,7 @@ _parse_format( char* format ) right_justify, suffix ); } else if (field[0] == 'b') { + params.match_flags.features_act_flag = true; format_add_features_act( params.format_list, field_size, right_justify, @@ -937,6 +938,12 @@ static int _parse_long_format (char* format_long) field_size, right_justify, suffix ); + } else if (!strcasecmp(token, "features_act")) { + params.match_flags.features_act_flag = true; + format_add_features_act( params.format_list, + field_size, + right_justify, + suffix ); } else if (!strcasecmp(token, "groups")) { params.match_flags.groups_flag = true; format_add_groups( params.format_list, @@ -1241,6 +1248,8 @@ void _print_options( void ) "true" : "false"); printf("features_flag = %s\n", params.match_flags.features_flag ? "true" : "false"); + printf("features_flag_act = %s\n", params.match_flags.features_act_flag? + "true" : "false"); printf("groups_flag = %s\n", params.match_flags.groups_flag ? "true" : "false"); printf("gres_flag = %s\n", params.match_flags.gres_flag ? diff --git a/src/sinfo/sinfo.c b/src/sinfo/sinfo.c index 47ea1597b68baff12e57f93af2c6c66d1dc9a23f..477357806fcf38bfa210bd7d18efac012f53d21f 100644 --- a/src/sinfo/sinfo.c +++ b/src/sinfo/sinfo.c @@ -3,7 +3,7 @@ ***************************************************************************** * Copyright (C) 2002-2007 The Regents of the University of California. * Copyright (C) 2008-2010 Lawrence Livermore National Security. - * Portions Copyright (C) 2010-2011 SchedMD <http://www.schedmd.com>. + * Portions Copyright (C) 2010-2016 SchedMD <http://www.schedmd.com>. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Joey Ekstrom <ekstrom1@llnl.gov>, Morris Jette <jette1@llnl.gov> * CODE-OCEC-09-009. All rights reserved. @@ -753,6 +753,11 @@ static bool _match_node_data(sinfo_data_t *sinfo_ptr, node_info_t *node_ptr) (xstrcmp(node_ptr->features, sinfo_ptr->features))) return false; + if (sinfo_ptr->nodes && + params.match_flags.features_act_flag && + (xstrcmp(node_ptr->features_act, sinfo_ptr->features_act))) + return false; + if (sinfo_ptr->nodes && params.match_flags.gres_flag && (xstrcmp(node_ptr->gres, sinfo_ptr->gres))) diff --git a/src/sinfo/sinfo.h b/src/sinfo/sinfo.h index e7e9eeede34bfaeebddfba8522b193a454776244..290fb85d2f06ada69c3e59f1abf3c9cbaacbdda6 100644 --- a/src/sinfo/sinfo.h +++ b/src/sinfo/sinfo.h @@ -137,6 +137,7 @@ struct sinfo_match_flags { bool sct_flag; bool disk_flag; bool features_flag; + bool features_act_flag; bool groups_flag; bool gres_flag; bool hostnames_flag; diff --git a/src/slurmctld/node_mgr.c b/src/slurmctld/node_mgr.c index 0f5d10afed6092a3b397f0834337eecf7665779e..154e9541fec33a70e6c2f15065eeddd3578cd6e9 100644 --- a/src/slurmctld/node_mgr.c +++ b/src/slurmctld/node_mgr.c @@ -1200,6 +1200,41 @@ _equivalent_node_state(struct node_record *node_ptr, uint32_t new_state) return false; } +/* Confirm that the selected ActiveFeatures are a subset of AvailableFeatures */ +static bool _valid_features_act(char *features_act, char *features) +{ + bool valid_subset = true; + char *tmp_act, *last_act = NULL, *tok_act; + char *tmp_avail, *last_avail = NULL, *tok_avail; + + if (!features_act || (features_act[0] == '\0')) + return true; + if (!features || (features[0] == '\0')) + return false; + + tmp_act = xstrdup(features_act); + tok_act = strtok_r(tmp_act, ",", &last_act); + while (tok_act) { + last_avail = NULL; + tmp_avail = xstrdup(features); + tok_avail = strtok_r(tmp_avail, ",", &last_avail); + while (tok_avail) { + if (!xstrcmp(tok_act, tok_avail)) + break; + tok_avail = strtok_r(NULL, ",", &last_avail); + } + xfree(tmp_avail); + if (!tok_avail) { /* No match found */ + valid_subset = false; + break; + } + tok_act = strtok_r(NULL, ",", &last_act); + } + xfree(tmp_act); + + return valid_subset; +} + /* * update_node - update the configuration data for one or more nodes * IN update_node_msg - update node request @@ -1263,6 +1298,8 @@ int update_node ( update_node_msg_t * update_node_msg ) } } + add_knl_features(&update_node_msg->features); + while ( (this_node_name = hostlist_shift (host_list)) ) { int err_code = 0; @@ -1296,17 +1333,26 @@ int update_node ( update_node_msg_t * update_node_msg ) if (update_node_msg->features) { xfree(node_ptr->features); - if (update_node_msg->features[0]) + if (update_node_msg->features[0]) { node_ptr->features = xstrdup(update_node_msg->features); + } /* _update_node_features() logs and updates config */ } - if (update_node_msg->features_act) { + if (update_node_msg->features_act && + !_valid_features_act(update_node_msg->features_act, + node_ptr->features)) { + info("Invalid node ActiveFeatures (%s not subset of %s)", + update_node_msg->features_act, + node_ptr->features); + error_code = ESLURM_INVALID_FEATURE; + } else if (update_node_msg->features_act) { xfree(node_ptr->features_act); - if (update_node_msg->features_act[0]) + if (update_node_msg->features_act[0]) { node_ptr->features_act = xstrdup(update_node_msg->features_act); + } /* _update_node_features() logs and updates config */ }