diff --git a/src/slurmctld/node_mgr.c b/src/slurmctld/node_mgr.c index 0bcffab0df0a66c9771011e7ea3dedfbbc76f609..362b75078c19ac28021fc6cdf02bff213239ae4c 100644 --- a/src/slurmctld/node_mgr.c +++ b/src/slurmctld/node_mgr.c @@ -1094,8 +1094,7 @@ int update_node ( update_node_msg_t * update_node_msg ) } hostlist_destroy (host_list); - if ((error_code == 0) && (update_node_msg->features) && - (update_node_msg->features[0])) { + if ((error_code == 0) && (update_node_msg->features)) { error_code = _update_node_features( update_node_msg->node_names, update_node_msg->features); diff --git a/src/sview/node_info.c b/src/sview/node_info.c index 9d1da3d2f2e0f6614d748445ecd4b2bef05fb7a9..9dde59206d808de058528b2889f312ac98fb9fab 100644 --- a/src/sview/node_info.c +++ b/src/sview/node_info.c @@ -63,7 +63,7 @@ static display_data_t display_data_node[] = { create_model_node, admin_edit_node}, {G_TYPE_INT, SORTID_WEIGHT,"Weight", FALSE, -1, refresh_node, create_model_node, admin_edit_node}, - {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE, -1, refresh_node, + {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE, 1, refresh_node, create_model_node, admin_edit_node}, {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE, -1, refresh_node, create_model_node, admin_edit_node}, @@ -88,6 +88,7 @@ static display_data_t options_data_node[] = { {G_TYPE_STRING, NODE_PAGE, "Put Node Down", TRUE, ADMIN_PAGE}, {G_TYPE_STRING, NODE_PAGE, "Make Node Idle", TRUE, ADMIN_PAGE}, #endif + {G_TYPE_STRING, NODE_PAGE, "Update Features", TRUE, ADMIN_PAGE}, {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, NODE_PAGE}, #ifdef HAVE_BG {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, NODE_PAGE}, @@ -436,9 +437,95 @@ extern int get_new_info_node(node_info_msg_t **info_ptr, int force) *info_ptr = new_node_ptr; return error_code; } + +extern int update_features_node(GtkDialog *dialog, const char *nodelist, + const char *old_features) +{ + char tmp_char[100]; + char *edit = NULL; + GtkWidget *entry = NULL; + GtkWidget *label = NULL; + update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t)); + int response = 0; + int no_dialog = 0; + int rc = SLURM_SUCCESS; + + if(!dialog) { + snprintf(tmp_char, sizeof(tmp_char), + "Update Features for Node(s) %s?", nodelist); + + dialog = GTK_DIALOG( + gtk_dialog_new_with_buttons( + tmp_char, + GTK_WINDOW(main_window), + GTK_DIALOG_MODAL + | GTK_DIALOG_DESTROY_WITH_PARENT, + NULL)); + no_dialog = 1; + } + label = gtk_dialog_add_button(dialog, + GTK_STOCK_YES, GTK_RESPONSE_OK); + gtk_window_set_default(GTK_WINDOW(dialog), label); + gtk_dialog_add_button(dialog, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + + node_msg->node_names = xstrdup(nodelist); + node_msg->features = NULL; + node_msg->reason = NULL; + node_msg->node_state = (uint16_t) NO_VAL; + + snprintf(tmp_char, sizeof(tmp_char), + "Features for Node(s) %s?", nodelist); + label = gtk_label_new(tmp_char); + gtk_box_pack_start(GTK_BOX(dialog->vbox), + label, FALSE, FALSE, 0); + + entry = create_entry(); + if(!entry) + goto end_it; + + if(old_features) + gtk_entry_set_text(GTK_ENTRY(entry), old_features); + + gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, TRUE, TRUE, 0); + gtk_widget_show_all(GTK_WIDGET(dialog)); + + response = gtk_dialog_run(dialog); + if (response == GTK_RESPONSE_OK) { + node_msg->features = + xstrdup(gtk_entry_get_text(GTK_ENTRY(entry))); + if(!node_msg->features) { + edit = g_strdup_printf("No features given."); + display_edit_note(edit); + g_free(edit); + goto end_it; + } + if(slurm_update_node(node_msg) == SLURM_SUCCESS) { + edit = g_strdup_printf( + "Nodes %s updated successfully.", + nodelist); + display_edit_note(edit); + g_free(edit); + + } else { + edit = g_strdup_printf( + "Problem updating nodes %s.", + nodelist); + display_edit_note(edit); + g_free(edit); + } + } + +end_it: + slurm_free_update_node_msg(node_msg); + if(no_dialog) + gtk_widget_destroy(GTK_WIDGET(dialog)); -extern int update_state_node2(GtkDialog *dialog, - const char *nodelist, const char *type) + return rc; +} + +extern int update_state_node(GtkDialog *dialog, + const char *nodelist, const char *type) { uint16_t state = (uint16_t) NO_VAL; char *upper = NULL, *lower = NULL; @@ -505,6 +592,8 @@ extern int update_state_node2(GtkDialog *dialog, xfree(lower); } } + if(!label) + goto end_it; node_msg->node_state = (uint16_t)state; gtk_box_pack_start(GTK_BOX(dialog->vbox), label, FALSE, FALSE, 0); if(entry) @@ -612,10 +701,7 @@ extern void admin_edit_node(GtkCellRendererText *cell, SORTID_NAME, &nodelist, -1); -/* update_state_node(treestore, &iter, */ -/* SORTID_STATE, SORTID_STATE_NUM, */ -/* new_text, &node_msg); */ - update_state_node2(NULL, nodelist, new_text); + update_state_node(NULL, nodelist, new_text); g_free(nodelist); default: @@ -1000,7 +1086,6 @@ extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id) extern void admin_node(GtkTreeModel *model, GtkTreeIter *iter, char *type) { char *name = NULL; - GtkWidget *popup = gtk_dialog_new_with_buttons( type, GTK_WINDOW(main_window), @@ -1010,9 +1095,15 @@ extern void admin_node(GtkTreeModel *model, GtkTreeIter *iter, char *type) gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); - /* something that has to deal with a node state change */ - update_state_node2(GTK_DIALOG(popup), name, type); - + if(!strcasecmp("Update Features", type)) { /* update features */ + char *old_features = NULL; + gtk_tree_model_get(model, iter, SORTID_FEATURES, + &old_features, -1); + update_features_node(GTK_DIALOG(popup), name, old_features); + g_free(old_features); + + } else /* something that has to deal with a node state change */ + update_state_node(GTK_DIALOG(popup), name, type); g_free(name); gtk_widget_destroy(popup); diff --git a/src/sview/part_info.c b/src/sview/part_info.c index 3c78593baf08eea5e8470c5c72948a54c1a44ae6..a4ea7b789ee9be764cbe1551e92226af7229cc46 100644 --- a/src/sview/part_info.c +++ b/src/sview/part_info.c @@ -74,6 +74,7 @@ enum { #endif SORTID_CPUS, SORTID_DEFAULT, + SORTID_FEATURES, SORTID_GROUPS, SORTID_HIDDEN, SORTID_JOB_SIZE, @@ -86,6 +87,7 @@ enum { #endif SORTID_NODES, SORTID_ONLY_LINE, + SORTID_REASON, SORTID_ROOT, SORTID_SHARE, SORTID_STATE, @@ -140,6 +142,10 @@ static display_data_t display_data_part[] = { create_model_part, admin_edit_part}, {G_TYPE_STRING, SORTID_WEIGHT, "Weight", FALSE, -1, refresh_part, create_model_part, admin_edit_part}, + {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE, 1, refresh_part, + create_model_part, admin_edit_part}, + {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE, -1, refresh_part, + create_model_part, admin_edit_part}, {G_TYPE_INT, SORTID_STATE_NUM, NULL, FALSE, -1, refresh_part, create_model_part, admin_edit_part}, {G_TYPE_INT, SORTID_ONLY_LINE, NULL, FALSE, -1, refresh_part, @@ -160,11 +166,14 @@ static display_data_t options_data_part[] = { TRUE, ADMIN_PAGE}, {G_TYPE_STRING, PART_PAGE, "Make Base Partitions Idle", TRUE, ADMIN_PAGE}, + {G_TYPE_STRING, PART_PAGE, "Update Base Partition Features", + TRUE, ADMIN_PAGE}, #else {G_TYPE_STRING, PART_PAGE, "Drain Nodes", TRUE, ADMIN_PAGE}, {G_TYPE_STRING, PART_PAGE, "Resume Nodes", TRUE, ADMIN_PAGE}, {G_TYPE_STRING, PART_PAGE, "Put Nodes Down", TRUE, ADMIN_PAGE}, {G_TYPE_STRING, PART_PAGE, "Make Nodes Idle", TRUE, ADMIN_PAGE}, + {G_TYPE_STRING, PART_PAGE, "Update Node Features", TRUE, ADMIN_PAGE}, #endif {G_TYPE_STRING, PART_PAGE, "Change Availablity Up/Down", TRUE, ADMIN_PAGE}, @@ -660,6 +669,7 @@ static void _layout_part_record(GtkTreeView *treeview, sview_part_sub_t other_part_sub; char tmp[1024]; char *temp_char = NULL; + int global_set = 0; GtkTreeStore *treestore = GTK_TREE_STORE(gtk_tree_view_get_model(treeview)); @@ -810,6 +820,13 @@ static void _layout_part_record(GtkTreeView *treeview, temp_part_sub->min_weight += sview_part_sub->min_weight; temp_part_sub->max_weight += sview_part_sub->max_weight; + if(!global_set) { + global_set = 1; + /* store features and reasons in the others + group */ + other_part_sub.features = temp_part_sub->features; + other_part_sub.reason = temp_part_sub->reason; + } } convert_num_unit((float)alloc_part_sub.node_cnt, tmp_cnt, UNIT_NONE); convert_num_unit((float)idle_part_sub.node_cnt, tmp_cnt1, UNIT_NONE); @@ -819,6 +836,15 @@ static void _layout_part_record(GtkTreeView *treeview, add_display_treestore_line(update, treestore, &iter, "Nodes (Allocated/Idle/Other)", tmp); + add_display_treestore_line(update, treestore, &iter, + find_col_name(display_data_part, + SORTID_FEATURES), + other_part_sub.features); + add_display_treestore_line(update, treestore, &iter, + find_col_name(display_data_part, + SORTID_REASON), + other_part_sub.reason); + } static void _update_part_record(sview_part_info_t *sview_part_info, @@ -922,6 +948,8 @@ static void _update_part_record(sview_part_info_t *sview_part_info, gtk_tree_store_set(treestore, iter, SORTID_MEM, "", -1); gtk_tree_store_set(treestore, iter, SORTID_WEIGHT, "", -1); gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); + gtk_tree_store_set(treestore, iter, SORTID_FEATURES, "", -1); + gtk_tree_store_set(treestore, iter, SORTID_REASON, "", -1); childern = gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore), &sub_iter, iter); @@ -983,6 +1011,10 @@ static void _update_part_sub_record(sview_part_sub_t *sview_part_sub, tmp, -1); gtk_tree_store_set(treestore, iter, SORTID_UPDATED, 1, -1); + gtk_tree_store_set(treestore, iter, SORTID_FEATURES, + sview_part_sub->features, -1); + gtk_tree_store_set(treestore, iter, SORTID_REASON, + sview_part_sub->reason, -1); return; } @@ -1574,7 +1606,6 @@ extern void admin_edit_part(GtkCellRendererText *cell, GtkTreeStore *treestore = GTK_TREE_STORE(data); GtkTreePath *path = gtk_tree_path_new_from_string(path_string); GtkTreeIter iter; - update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t)); update_part_msg_t *part_msg = xmalloc(sizeof(update_part_msg_t)); char *temp = NULL; @@ -1636,7 +1667,6 @@ extern void admin_edit_part(GtkCellRendererText *cell, } no_input: slurm_free_update_part_msg(part_msg); - slurm_free_update_node_msg(node_msg); gtk_tree_path_free (path); g_free(old_text); g_static_mutex_unlock(&sview_mutex); @@ -2127,7 +2157,7 @@ extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type) slurm_init_part_desc_msg(part_msg); part_msg->name = xstrdup(partid); - + if(!strcasecmp("Change Availablity Up/Down", type)) { label = gtk_dialog_add_button(GTK_DIALOG(popup), GTK_STOCK_YES, GTK_RESPONSE_OK); @@ -2158,9 +2188,17 @@ extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type) label = gtk_label_new(tmp_char); edit_type = EDIT_EDIT; entry = _admin_full_edit_part(part_msg, model, iter); + } else if(!strncasecmp("Update", type, 6)) { + char *old_features = NULL; + gtk_tree_model_get(model, iter, SORTID_FEATURES, + &old_features, -1); + update_features_node(GTK_DIALOG(popup), + nodelist, old_features); + g_free(old_features); + goto end_it; } else { /* something that has to deal with a node state change */ - update_state_node2(GTK_DIALOG(popup), nodelist, type); + update_state_node(GTK_DIALOG(popup), nodelist, type); goto end_it; } @@ -2194,6 +2232,7 @@ extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type) } } end_it: + g_free(state); g_free(partid); g_free(nodelist); diff --git a/src/sview/sview.h b/src/sview/sview.h index b543574795ded24b59c1a0720cf09004bc3db55f..a8726955b6f38c08234375b34a87738d806914bd 100644 --- a/src/sview/sview.h +++ b/src/sview/sview.h @@ -331,8 +331,10 @@ extern void admin_job(GtkTreeModel *model, GtkTreeIter *iter, char *type); extern void refresh_node(GtkAction *action, gpointer user_data); /* don't destroy the list from this function */ extern List create_node_info_list(node_info_msg_t *node_info_ptr, int changed); -extern int update_state_node2(GtkDialog *dialog, - const char *nodelist, const char *type); +extern int update_features_node(GtkDialog *dialog, const char *nodelist, + const char *old_features); +extern int update_state_node(GtkDialog *dialog, + const char *nodelist, const char *type); extern GtkListStore *create_model_node(int type); extern void admin_edit_node(GtkCellRendererText *cell, const char *path_string,