| /*****************************************************************************\ |
| * node_info.c - Functions related to node display mode of sview. |
| ***************************************************************************** |
| * Copyright (C) 2004-2007 The Regents of the University of California. |
| * Copyright (C) 2008-2010 Lawrence Livermore National Security. |
| * Copyright (C) SchedMD LLC. |
| * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). |
| * Written by Danny Auble <da@llnl.gov> |
| * |
| * CODE-OCEC-09-009. All rights reserved. |
| * |
| * This file is part of Slurm, a resource management program. |
| * For details, see <https://slurm.schedmd.com/>. |
| * 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. |
| * |
| * 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. |
| \*****************************************************************************/ |
| |
| #include "src/sview/sview.h" |
| |
| #define _DEBUG 0 |
| #define ECLIPSE_RT 0 |
| |
| //static int _l_topo_color_ndx = MAKE_TOPO_1; |
| //static int _l_sw_color_ndx = 0; |
| |
| /* These need to be in alpha order (except POS and CNT) */ |
| enum { |
| SORTID_POS = POS_LOC, |
| SORTID_ACTIVE_FEATURES, |
| SORTID_ARCH, |
| SORTID_AVAIL_FEATURES, |
| SORTID_AVE_WATTS, |
| SORTID_BOARDS, |
| SORTID_BOOT_TIME, |
| SORTID_CAP_WATTS, |
| SORTID_CLUSTER_NAME, |
| SORTID_COLOR, |
| SORTID_COMMENT, |
| SORTID_CPUS, |
| SORTID_CPU_LOAD, |
| SORTID_CORES, |
| SORTID_CURRENT_WATTS, |
| SORTID_ERR_CPUS, |
| SORTID_EXTRA, |
| SORTID_FREE_MEM, |
| SORTID_GRES, |
| SORTID_IDLE_CPUS, |
| SORTID_MCS_LABEL, |
| SORTID_NAME, |
| SORTID_NODE_ADDR, |
| SORTID_NODE_HOSTNAME, |
| SORTID_OWNER, |
| SORTID_PORT, |
| SORTID_REAL_MEMORY, |
| SORTID_REASON, |
| SORTID_RES_CORES_PER_GPU, |
| SORTID_RESV_NAME, |
| SORTID_SLURMD_START_TIME, |
| SORTID_SOCKETS, |
| SORTID_STATE, |
| SORTID_STATE_COMPLETE, |
| SORTID_STATE_NUM, |
| SORTID_THREADS, |
| SORTID_TMP_DISK, |
| SORTID_TRES_ALLOC, |
| SORTID_TRES_CONFIG, |
| SORTID_UPDATED, |
| SORTID_USED_CPUS, |
| SORTID_USED_MEMORY, |
| SORTID_VERSION, |
| SORTID_WEIGHT, |
| SORTID_CNT |
| }; |
| |
| typedef struct { |
| int node_col; |
| char *nodelist; |
| } process_node_t; |
| |
| /*these are the settings to apply for the user |
| * on the first startup after a fresh slurm install.*/ |
| static char *_initial_page_opts = "Name,RackMidplane,State,CPU_Count," |
| "Used_CPU_Count,Error_CPU_Count,CoresPerSocket,Sockets,ThreadsPerCore," |
| "Real_Memory,Tmp_Disk"; |
| |
| static display_data_t display_data_node[] = { |
| {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_CLUSTER_NAME, "ClusterName", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_NAME, "Name", false, EDIT_NONE, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_COLOR, NULL, true, EDIT_COLOR, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_NODE_ADDR, "NodeAddr", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_NODE_HOSTNAME, "NodeHostName", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_OWNER, "Owner", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_MCS_LABEL, "MCS_Label", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_STATE, "State", false, EDIT_MODEL, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_STATE_COMPLETE, "StateComplete", false, |
| EDIT_MODEL, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_STATE_NUM, NULL, false, EDIT_NONE, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_CPUS, "CPU Count", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_USED_CPUS, "Used CPU Count", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_ERR_CPUS, "Error CPU Count", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_EXTRA, "Extra", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_IDLE_CPUS, "Idle CPU Count", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_TRES_CONFIG, "Config TRES", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_TRES_ALLOC, "Alloc TRES", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_BOARDS, "Boards", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_SOCKETS, "Sockets", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_CORES, "CoresPerSocket", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_THREADS, "ThreadsPerCore", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_REAL_MEMORY, "Real Memory", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_USED_MEMORY, "Used Memory", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_FREE_MEM, "Free Memory", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_PORT, "Port", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_TMP_DISK, "Tmp Disk", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_ACTIVE_FEATURES, "Active Features", false, |
| EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_ARCH, "Arch", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_AVAIL_FEATURES, "Available Features", false, |
| EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_BOOT_TIME, "BootTime", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_CPU_LOAD, "CPU Load", false, EDIT_NONE, |
| refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_COMMENT, "Comment", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_GRES, "Gres", false, |
| EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_REASON, "Reason", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_RES_CORES_PER_GPU, |
| "RestrictedCoresPerGPU", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_RESV_NAME, "ReservationName", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_SLURMD_START_TIME, "SlurmdStartTime", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_CURRENT_WATTS, "Current Watts", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_AVE_WATTS, "Average Watts", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_CAP_WATTS,"Cap Watts", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_STRING, SORTID_VERSION, "Version", false, |
| EDIT_NONE, refresh_node, create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_WEIGHT,"Weight", false, EDIT_NONE, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_INT, SORTID_UPDATED, NULL, false, EDIT_NONE, refresh_node, |
| create_model_node, admin_edit_node}, |
| {G_TYPE_NONE, -1, NULL, false, EDIT_NONE} |
| }; |
| |
| static display_data_t options_data_node[] = { |
| {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE}, |
| {G_TYPE_STRING, INFO_PAGE, "Full Info", true, NODE_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Drain Node", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Undrain Node", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Resume Node", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Set Node(s) Down", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Make Node(s) Idle", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Update Active Features", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Update Available Features", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Update Gres", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, JOB_PAGE, "Jobs", true, NODE_PAGE}, |
| {G_TYPE_STRING, PART_PAGE, "Partitions", true, NODE_PAGE}, |
| {G_TYPE_STRING, RESV_PAGE, "Reservations", true, NODE_PAGE}, |
| //{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", false, NODE_PAGE}, |
| {G_TYPE_NONE, -1, NULL, false, EDIT_NONE} |
| }; |
| |
| static display_data_t *local_display_data = NULL; |
| static GtkTreeModel *last_model = NULL; |
| |
| static void _layout_node_record(GtkTreeView *treeview, |
| sview_node_info_t *sview_node_info_ptr, |
| int update) |
| { |
| char tmp_cnt[50]; |
| char tmp_current_watts[50]; |
| char tmp_ave_watts[50]; |
| char tmp_owner[32]; |
| char tmp_version[50]; |
| char *upper = NULL, *lower = NULL; |
| GtkTreeIter iter; |
| uint16_t alloc_cpus = 0; |
| node_info_t *node_ptr = sview_node_info_ptr->node_ptr; |
| int idle_cpus = node_ptr->cpus_efctv; |
| GtkTreeStore *treestore = |
| GTK_TREE_STORE(gtk_tree_view_get_model(treeview)); |
| if (!treestore) |
| return; |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_CLUSTER_NAME), |
| node_ptr->cluster_name); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_NAME), |
| node_ptr->name); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_NODE_ADDR), |
| node_ptr->node_addr); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_NODE_HOSTNAME), |
| node_ptr->node_hostname); |
| |
| if (node_ptr->owner == NO_VAL) { |
| snprintf(tmp_owner, sizeof(tmp_owner), "N/A"); |
| } else { |
| char *user_name; |
| user_name = uid_to_string((uid_t) node_ptr->owner); |
| snprintf(tmp_owner, sizeof(tmp_owner), "%s(%u)", |
| user_name, node_ptr->owner); |
| xfree(user_name); |
| } |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_OWNER), tmp_owner); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_MCS_LABEL), |
| (node_ptr->mcs_label == NULL) ? "N/A" : |
| node_ptr->mcs_label), |
| |
| convert_num_unit((float)node_ptr->cpus, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_CPUS), |
| tmp_cnt); |
| |
| snprintf(tmp_cnt, sizeof(tmp_cnt), "%.2f", |
| (node_ptr->cpu_load / 100.0)); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_CPU_LOAD), |
| tmp_cnt); |
| |
| if (node_ptr->free_mem == NO_VAL64) { |
| snprintf(tmp_cnt, sizeof(tmp_cnt), "N/A"); |
| } else { |
| snprintf(tmp_cnt, sizeof(tmp_cnt), "%"PRIu64"M", |
| node_ptr->free_mem); |
| } |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_FREE_MEM), |
| tmp_cnt); |
| |
| alloc_cpus = node_ptr->alloc_cpus; |
| idle_cpus -= alloc_cpus; |
| convert_num_unit((float)alloc_cpus, tmp_cnt, |
| sizeof(tmp_cnt), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_USED_CPUS), |
| tmp_cnt); |
| |
| convert_num_unit((float)idle_cpus, tmp_cnt, sizeof(tmp_cnt), UNIT_NONE, |
| NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_IDLE_CPUS), |
| tmp_cnt); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_TRES_CONFIG), |
| node_ptr->tres_fmt_str); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_TRES_ALLOC), |
| (node_ptr->alloc_tres_fmt_str ? |
| node_ptr->alloc_tres_fmt_str : "")); |
| |
| upper = node_state_string(node_ptr->node_state); |
| lower = str_tolower(upper); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_STATE), |
| lower); |
| xfree(lower); |
| |
| lower = node_state_string_complete(node_ptr->node_state); |
| xstrtolower(lower); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_STATE_COMPLETE), |
| lower); |
| xfree(lower); |
| |
| convert_num_unit((float)node_ptr->boards, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_BOARDS), |
| tmp_cnt); |
| |
| convert_num_unit((float)node_ptr->sockets, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_SOCKETS), |
| tmp_cnt); |
| |
| convert_num_unit((float)node_ptr->cores, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_CORES), |
| tmp_cnt); |
| |
| convert_num_unit((float)node_ptr->port, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_PORT), |
| tmp_cnt); |
| |
| convert_num_unit((float)node_ptr->threads, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_THREADS), |
| tmp_cnt); |
| |
| convert_num_unit((float)node_ptr->real_memory, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_MEGA, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_REAL_MEMORY), |
| tmp_cnt); |
| |
| snprintf(tmp_cnt, sizeof(tmp_cnt), "%"PRIu64"M", |
| node_ptr->alloc_memory); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_USED_MEMORY), |
| tmp_cnt); |
| |
| convert_num_unit((float)node_ptr->tmp_disk, tmp_cnt, sizeof(tmp_cnt), |
| UNIT_MEGA, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_TMP_DISK), |
| tmp_cnt); |
| snprintf(tmp_cnt, sizeof(tmp_cnt), "%u", node_ptr->weight); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_WEIGHT), |
| tmp_cnt); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_ARCH), |
| node_ptr->arch); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_AVAIL_FEATURES), |
| node_ptr->features); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_ACTIVE_FEATURES), |
| node_ptr->features_act); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_GRES), |
| node_ptr->gres); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_BOOT_TIME), |
| sview_node_info_ptr->boot_time); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_SLURMD_START_TIME), |
| sview_node_info_ptr->slurmd_start_time); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_REASON), |
| sview_node_info_ptr->reason); |
| convert_num_unit((float)node_ptr->res_cores_per_gpu, |
| tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_RES_CORES_PER_GPU), |
| tmp_cnt); |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_RESV_NAME), |
| node_ptr->resv_name); |
| |
| if (node_ptr->energy->current_watts == NO_VAL) { |
| snprintf(tmp_current_watts, sizeof(tmp_current_watts), |
| "N/A"); |
| snprintf(tmp_ave_watts, sizeof(tmp_ave_watts), |
| "N/A"); |
| } else { |
| snprintf(tmp_current_watts, sizeof(tmp_current_watts), |
| "%u", node_ptr->energy->current_watts); |
| snprintf(tmp_ave_watts, sizeof(tmp_ave_watts), |
| "%u", node_ptr->energy->ave_watts); |
| } |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_CURRENT_WATTS), |
| tmp_current_watts); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_AVE_WATTS), |
| tmp_ave_watts); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_COMMENT), |
| node_ptr->comment); |
| |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_EXTRA), |
| node_ptr->extra); |
| |
| if (node_ptr->version == NULL) { |
| snprintf(tmp_version, sizeof(tmp_version), "N/A"); |
| } else { |
| snprintf(tmp_version, sizeof(tmp_version), "%s", |
| node_ptr->version); |
| } |
| add_display_treestore_line(update, treestore, &iter, |
| find_col_name(display_data_node, |
| SORTID_VERSION), |
| tmp_version); |
| return; |
| } |
| |
| static void _update_node_record(sview_node_info_t *sview_node_info_ptr, |
| GtkTreeStore *treestore) |
| { |
| uint16_t alloc_cpus = 0, idle_cpus; |
| node_info_t *node_ptr = sview_node_info_ptr->node_ptr; |
| char tmp_disk[20], tmp_cpus[20], tmp_idle_cpus[20]; |
| char tmp_mem[20], tmp_used_memory[20]; |
| char tmp_used_cpus[20], tmp_cpu_load[20], tmp_free_mem[20], tmp_owner[32]; |
| char tmp_current_watts[50], tmp_ave_watts[50]; |
| char tmp_version[50]; |
| char *tmp_state_lower, *tmp_state_upper, *tmp_state_complete; |
| |
| if (node_ptr->energy->current_watts == NO_VAL) { |
| snprintf(tmp_current_watts, sizeof(tmp_current_watts), |
| "N/A"); |
| snprintf(tmp_ave_watts, sizeof(tmp_ave_watts), |
| "N/A"); |
| } else { |
| snprintf(tmp_current_watts, sizeof(tmp_current_watts), |
| "%u ", node_ptr->energy->current_watts); |
| snprintf(tmp_ave_watts, sizeof(tmp_ave_watts), |
| "%u", node_ptr->energy->ave_watts); |
| } |
| |
| snprintf(tmp_cpu_load, sizeof(tmp_cpu_load), "%.2f", |
| (node_ptr->cpu_load / 100.0)); |
| |
| if (node_ptr->free_mem == NO_VAL64) { |
| strlcpy(tmp_free_mem, "N/A", sizeof(tmp_free_mem)); |
| } else { |
| snprintf(tmp_free_mem, sizeof(tmp_free_mem), |
| "%"PRIu64"M", node_ptr->free_mem); |
| } |
| |
| convert_num_unit((float)node_ptr->cpus, tmp_cpus, |
| sizeof(tmp_cpus), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| |
| alloc_cpus = node_ptr->alloc_cpus; |
| idle_cpus = node_ptr->cpus_efctv - alloc_cpus; |
| convert_num_unit((float)alloc_cpus, tmp_used_cpus, |
| sizeof(tmp_used_cpus), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| |
| snprintf(tmp_used_memory, sizeof(tmp_used_memory), "%"PRIu64"M", |
| node_ptr->alloc_memory); |
| |
| convert_num_unit((float)alloc_cpus, tmp_used_cpus, |
| sizeof(tmp_used_cpus), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| |
| convert_num_unit((float)idle_cpus, tmp_idle_cpus, sizeof(tmp_idle_cpus), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| |
| tmp_state_upper = node_state_string(node_ptr->node_state); |
| tmp_state_lower = str_tolower(tmp_state_upper); |
| |
| tmp_state_complete = node_state_string_complete(node_ptr->node_state); |
| xstrtolower(tmp_state_complete); |
| |
| convert_num_unit((float)node_ptr->real_memory, tmp_mem, sizeof(tmp_mem), |
| UNIT_MEGA, NO_VAL, working_sview_config.convert_flags); |
| |
| convert_num_unit((float)node_ptr->tmp_disk, tmp_disk, sizeof(tmp_disk), |
| UNIT_MEGA, NO_VAL, working_sview_config.convert_flags); |
| |
| if (node_ptr->version == NULL) { |
| snprintf(tmp_version, sizeof(tmp_version), "N/A"); |
| } else { |
| snprintf(tmp_version, sizeof(tmp_version), "%s", |
| node_ptr->version); |
| } |
| |
| if (node_ptr->owner == NO_VAL) { |
| snprintf(tmp_owner, sizeof(tmp_owner), "N/A"); |
| } else { |
| char *user_name; |
| user_name = uid_to_string((uid_t) node_ptr->owner); |
| snprintf(tmp_owner, sizeof(tmp_owner), "%s(%u)", |
| user_name, node_ptr->owner); |
| xfree(user_name); |
| } |
| |
| /* Combining these records provides a slight performance improvement */ |
| gtk_tree_store_set(treestore, &sview_node_info_ptr->iter_ptr, |
| SORTID_ACTIVE_FEATURES, node_ptr->features_act, |
| SORTID_ARCH, node_ptr->arch, |
| SORTID_AVAIL_FEATURES, node_ptr->features, |
| SORTID_AVE_WATTS, tmp_ave_watts, |
| SORTID_BOARDS, node_ptr->boards, |
| SORTID_BOOT_TIME, sview_node_info_ptr->boot_time, |
| SORTID_CLUSTER_NAME, node_ptr->cluster_name, |
| SORTID_COLOR, |
| sview_colors[sview_node_info_ptr->pos |
| % sview_colors_cnt], |
| SORTID_COMMENT, node_ptr->comment, |
| SORTID_CORES, node_ptr->cores, |
| SORTID_CPUS, tmp_cpus, |
| SORTID_CURRENT_WATTS, tmp_current_watts, |
| SORTID_CPU_LOAD, tmp_cpu_load, |
| SORTID_EXTRA, node_ptr->extra, |
| SORTID_FREE_MEM, tmp_free_mem, |
| SORTID_TMP_DISK, tmp_disk, |
| SORTID_IDLE_CPUS, tmp_idle_cpus, |
| SORTID_GRES, node_ptr->gres, |
| SORTID_MCS_LABEL, (node_ptr->mcs_label == NULL) ? |
| "N/A" : node_ptr->mcs_label, |
| SORTID_REAL_MEMORY, tmp_mem, |
| SORTID_NAME, node_ptr->name, |
| SORTID_NODE_ADDR, node_ptr->node_addr, |
| SORTID_NODE_HOSTNAME, node_ptr->node_hostname, |
| SORTID_OWNER, tmp_owner, |
| SORTID_REASON, sview_node_info_ptr->reason, |
| SORTID_RES_CORES_PER_GPU, |
| node_ptr->res_cores_per_gpu, |
| SORTID_RESV_NAME, node_ptr->resv_name, |
| SORTID_SLURMD_START_TIME, |
| sview_node_info_ptr->slurmd_start_time, |
| SORTID_SOCKETS, node_ptr->sockets, |
| SORTID_STATE, tmp_state_lower, |
| SORTID_STATE_COMPLETE, tmp_state_complete, |
| SORTID_STATE_NUM, node_ptr->node_state, |
| SORTID_THREADS, node_ptr->threads, |
| SORTID_TRES_ALLOC, node_ptr->alloc_tres_fmt_str ? |
| node_ptr->alloc_tres_fmt_str : "", |
| SORTID_TRES_CONFIG, node_ptr->tres_fmt_str, |
| SORTID_USED_CPUS, tmp_used_cpus, |
| SORTID_USED_MEMORY, tmp_used_memory, |
| SORTID_VERSION, tmp_version, |
| SORTID_WEIGHT, node_ptr->weight, |
| SORTID_UPDATED, 1, |
| -1); |
| |
| xfree(tmp_state_complete); |
| xfree(tmp_state_lower); |
| return; |
| } |
| |
| static void _append_node_record(sview_node_info_t *sview_node_info, |
| GtkTreeStore *treestore) |
| { |
| gtk_tree_store_append(treestore, &sview_node_info->iter_ptr, NULL); |
| gtk_tree_store_set(treestore, &sview_node_info->iter_ptr, SORTID_POS, |
| sview_node_info->pos, -1); |
| _update_node_record(sview_node_info, treestore); |
| } |
| |
| static void _update_info_node(list_t *info_list, GtkTreeView *tree_view) |
| { |
| GtkTreeModel *model = gtk_tree_view_get_model(tree_view); |
| char *name = NULL; |
| list_itr_t *itr = NULL; |
| sview_node_info_t *sview_node_info = NULL; |
| |
| set_for_update(model, SORTID_UPDATED); |
| |
| itr = list_iterator_create(info_list); |
| while ((sview_node_info = list_next(itr))) { |
| /* This means the tree_store changed (added new column |
| * or something). */ |
| if (last_model != model) |
| sview_node_info->iter_set = false; |
| |
| if (sview_node_info->iter_set) { |
| gtk_tree_model_get(model, &sview_node_info->iter_ptr, |
| SORTID_NAME, &name, -1); |
| if (xstrcmp(name, sview_node_info->node_name)) { |
| /* Bad pointer */ |
| sview_node_info->iter_set = false; |
| //g_print("bad node iter pointer\n"); |
| } |
| g_free(name); |
| } |
| if (sview_node_info->iter_set) |
| _update_node_record(sview_node_info, |
| GTK_TREE_STORE(model)); |
| else { |
| _append_node_record(sview_node_info, |
| GTK_TREE_STORE(model)); |
| sview_node_info->iter_set = true; |
| } |
| } |
| list_iterator_destroy(itr); |
| |
| /* remove all old nodes */ |
| remove_old(model, SORTID_UPDATED); |
| last_model = model; |
| } |
| |
| static void _node_info_free(sview_node_info_t *sview_node_info) |
| { |
| if (sview_node_info) { |
| xfree(sview_node_info->slurmd_start_time); |
| xfree(sview_node_info->boot_time); |
| xfree(sview_node_info->node_name); |
| xfree(sview_node_info->rack_mp); |
| xfree(sview_node_info->reason); |
| } |
| } |
| |
| static void _node_info_list_del(void *object) |
| { |
| sview_node_info_t *sview_node_info = (sview_node_info_t *)object; |
| |
| if (sview_node_info) { |
| _node_info_free(sview_node_info); |
| xfree(sview_node_info); |
| } |
| } |
| |
| static void _display_info_node(list_t *info_list, popup_info_t *popup_win) |
| { |
| specific_info_t *spec_info = popup_win->spec_info; |
| char *name = (char *)spec_info->search_info->gchar_data; |
| int found = 0; |
| node_info_t *node_ptr = NULL; |
| GtkTreeView *treeview = NULL; |
| int update = 0; |
| list_itr_t *itr = NULL; |
| sview_node_info_t *sview_node_info = NULL; |
| int i = -1; |
| |
| if (!spec_info->search_info->gchar_data) { |
| goto finished; |
| } |
| need_refresh: |
| if (!spec_info->display_widget) { |
| treeview = create_treeview_2cols_attach_to_table( |
| popup_win->table); |
| spec_info->display_widget = |
| g_object_ref(GTK_WIDGET(treeview)); |
| } else { |
| treeview = GTK_TREE_VIEW(spec_info->display_widget); |
| update = 1; |
| } |
| |
| itr = list_iterator_create(info_list); |
| while ((sview_node_info = list_next(itr))) { |
| node_ptr = sview_node_info->node_ptr; |
| i++; |
| if (!xstrcmp(node_ptr->name, name)) { |
| change_grid_color(popup_win->grid_button_list, |
| i, i, i, true, 0); |
| _layout_node_record(treeview, sview_node_info, update); |
| found = 1; |
| break; |
| } |
| } |
| list_iterator_destroy(itr); |
| if (!found) { |
| if (!popup_win->not_found) { |
| char *temp; |
| GtkTreeIter iter; |
| GtkTreeModel *model = NULL; |
| |
| temp = "NODE NOT FOUND\n"; |
| /* only time this will be run so no update */ |
| model = gtk_tree_view_get_model(treeview); |
| add_display_treestore_line(0, |
| GTK_TREE_STORE(model), |
| &iter, |
| temp, ""); |
| } |
| popup_win->not_found = true; |
| } else { |
| if (popup_win->not_found) { |
| popup_win->not_found = false; |
| gtk_widget_destroy(spec_info->display_widget); |
| |
| goto need_refresh; |
| } |
| } |
| gtk_widget_show(spec_info->display_widget); |
| |
| finished: |
| return; |
| } |
| |
| static void _selected_page(GtkMenuItem *menuitem, |
| display_data_t *display_data) |
| { |
| switch(display_data->extra) { |
| case NODE_PAGE: |
| popup_all_node_name(display_data->user_data, display_data->id, |
| NULL); |
| break; |
| case ADMIN_PAGE: |
| admin_node_name(display_data->user_data, |
| NULL, display_data->name); |
| break; |
| default: |
| g_print("node got %d %d\n", display_data->extra, |
| display_data->id); |
| } |
| |
| } |
| |
| static void _process_each_node(GtkTreeModel *model, GtkTreePath *path, |
| GtkTreeIter *iter, gpointer userdata) |
| { |
| char *name = NULL; |
| process_node_t *process_node = userdata; |
| |
| gtk_tree_model_get(model, iter, process_node->node_col, &name, -1); |
| if (process_node->nodelist) |
| xstrfmtcat(process_node->nodelist, ",%s", name); |
| else |
| process_node->nodelist = xstrdup(name); |
| g_free(name); |
| } |
| /*process_each_node ^^^*/ |
| |
| |
| |
| extern void refresh_node(GtkAction *action, gpointer user_data) |
| { |
| popup_info_t *popup_win = (popup_info_t *)user_data; |
| xassert(popup_win); |
| xassert(popup_win->spec_info); |
| xassert(popup_win->spec_info->title); |
| popup_win->force_refresh = 1; |
| specific_info_node(popup_win); |
| } |
| |
| /* don't destroy the list from this function */ |
| extern list_t *create_node_info_list(node_info_msg_t *node_info_ptr, |
| bool by_partition) |
| { |
| static list_t *info_list = NULL; |
| static node_info_msg_t *last_node_info_ptr = NULL; |
| list_t *last_list = NULL; |
| list_itr_t *last_list_itr = NULL; |
| int i = 0; |
| sview_node_info_t *sview_node_info_ptr = NULL; |
| node_info_t *node_ptr = NULL; |
| char time_str[256]; |
| |
| if (!by_partition) { |
| if (!node_info_ptr |
| || (info_list && (node_info_ptr == last_node_info_ptr))) |
| goto update_color; |
| } |
| |
| last_node_info_ptr = node_info_ptr; |
| |
| if (info_list) |
| last_list = info_list; |
| |
| info_list = list_create(_node_info_list_del); |
| |
| if (last_list) |
| last_list_itr = list_iterator_create(last_list); |
| for (i=0; i<node_info_ptr->record_count; i++) { |
| node_ptr = &(node_info_ptr->node_array[i]); |
| |
| if (!node_ptr->name || (node_ptr->name[0] == '\0')) |
| continue; |
| |
| sview_node_info_ptr = NULL; |
| |
| if (last_list_itr) { |
| while ((sview_node_info_ptr = |
| list_next(last_list_itr))) { |
| if (!xstrcmp(sview_node_info_ptr->node_name, |
| node_ptr->name)) { |
| list_remove(last_list_itr); |
| _node_info_free(sview_node_info_ptr); |
| break; |
| } |
| } |
| list_iterator_reset(last_list_itr); |
| } |
| |
| /* constrain list to included partitions' nodes */ |
| /* and there are excluded values to process */ |
| /* and user has not requested to show hidden */ |
| /* if (by_partition && apply_partition_check */ |
| /* && !working_sview_config.show_hidden */ |
| /* && !check_part_includes_node(i)) */ |
| /* continue; */ |
| |
| if (!sview_node_info_ptr) |
| sview_node_info_ptr = |
| xmalloc(sizeof(sview_node_info_t)); |
| list_append(info_list, sview_node_info_ptr); |
| sview_node_info_ptr->node_name = xstrdup(node_ptr->name); |
| sview_node_info_ptr->node_ptr = node_ptr; |
| sview_node_info_ptr->pos = i; |
| |
| if (node_ptr->reason && |
| (node_ptr->reason_uid != NO_VAL) && node_ptr->reason_time) { |
| char *user = uid_to_string(node_ptr->reason_uid); |
| slurm_make_time_str(&node_ptr->reason_time, |
| time_str, sizeof(time_str)); |
| sview_node_info_ptr->reason = xstrdup_printf( |
| "%s [%s@%s]", node_ptr->reason, user, time_str); |
| xfree(user); |
| } else if (node_ptr->reason) |
| sview_node_info_ptr->reason = xstrdup(node_ptr->reason); |
| |
| if (node_ptr->boot_time) { |
| slurm_make_time_str(&node_ptr->boot_time, |
| time_str, sizeof(time_str)); |
| sview_node_info_ptr->boot_time = xstrdup(time_str); |
| } |
| if (node_ptr->slurmd_start_time) { |
| slurm_make_time_str(&node_ptr->slurmd_start_time, |
| time_str, sizeof(time_str)); |
| sview_node_info_ptr->slurmd_start_time = |
| xstrdup(time_str); |
| } |
| } |
| |
| if (last_list) { |
| list_iterator_destroy(last_list_itr); |
| FREE_NULL_LIST(last_list); |
| } |
| |
| update_color: |
| |
| return info_list; |
| } |
| |
| extern int get_new_info_node(node_info_msg_t **info_ptr, int force) |
| { |
| node_info_msg_t *new_node_ptr = NULL; |
| uint16_t show_flags = SHOW_MIXED; |
| int error_code = SLURM_NO_CHANGE_IN_DATA; |
| time_t now = time(NULL), delay; |
| static time_t last; |
| static uint16_t last_flags = 0; |
| |
| delay = now - last; |
| if (delay < 2) { |
| /* Avoid re-loading node information within 2 secs as the data |
| * may still be in use. If we load new node data and free the |
| * old data while it it still in use, the result is likely |
| * invalid memory references. */ |
| force = 0; |
| /* FIXME: Add an "in use" flag, copy the data, or otherwise |
| * permit the timely loading of new node information. */ |
| } |
| |
| if (g_node_info_ptr && !force && |
| (delay < working_sview_config.refresh_delay)) { |
| if (*info_ptr != g_node_info_ptr) |
| error_code = SLURM_SUCCESS; |
| *info_ptr = g_node_info_ptr; |
| return error_code; |
| } |
| last = now; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) |
| show_flags |= SHOW_FEDERATION; |
| //if (working_sview_config.show_hidden) |
| show_flags |= SHOW_ALL; |
| if (g_node_info_ptr) { |
| if (show_flags != last_flags) |
| g_node_info_ptr->last_update = 0; |
| error_code = slurm_load_node(g_node_info_ptr->last_update, |
| &new_node_ptr, show_flags); |
| if (error_code == SLURM_SUCCESS) { |
| slurm_free_node_info_msg(g_node_info_ptr); |
| } else if (errno == SLURM_NO_CHANGE_IN_DATA) { |
| error_code = SLURM_NO_CHANGE_IN_DATA; |
| new_node_ptr = g_node_info_ptr; |
| } |
| } else { |
| new_node_ptr = NULL; |
| error_code = slurm_load_node((time_t) NULL, &new_node_ptr, |
| show_flags); |
| } |
| |
| last_flags = show_flags; |
| g_node_info_ptr = new_node_ptr; |
| |
| if (g_node_info_ptr && (*info_ptr != g_node_info_ptr)) |
| error_code = SLURM_SUCCESS; |
| |
| *info_ptr = g_node_info_ptr; |
| |
| if (!g_topo_info_msg_ptr && |
| default_sview_config.grid_topological) { |
| get_topo_conf(); /* pull in topology NOW */ |
| } |
| |
| return error_code; |
| } |
| |
| extern int update_active_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 (_DEBUG) |
| g_print("update_active_features_node:global_row_count: %d " |
| "node_names %s\n", |
| global_row_count, nodelist); |
| if (!dialog) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Update Active 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_type_hint(GTK_WINDOW(dialog), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| gtk_window_set_default(GTK_WINDOW(dialog), label); |
| gtk_dialog_add_button(dialog, |
| GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| slurm_init_update_node_msg(node_msg); |
| node_msg->node_names = xstrdup(nodelist); |
| |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Active 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_act = |
| xstrdup(gtk_entry_get_text(GTK_ENTRY(entry))); |
| if (!node_msg->features_act) { |
| edit = g_strdup_printf("No features given."); |
| display_edit_note(edit); |
| g_free(edit); |
| goto end_it; |
| } |
| if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) { |
| edit = g_strdup_printf( |
| "Node(s) %s updated successfully.", |
| nodelist); |
| display_edit_note(edit); |
| g_free(edit); |
| |
| } else { |
| edit = g_strdup_printf( |
| "Problem updating node(s) %s: %s", |
| nodelist, slurm_strerror(rc)); |
| 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)); |
| |
| return rc; |
| } |
| |
| extern int update_avail_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 (_DEBUG) |
| g_print("update_avail_features_node:global_row_count: %d " |
| "node_names %s\n", |
| global_row_count, nodelist); |
| if (!dialog) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Update Available 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_type_hint(GTK_WINDOW(dialog), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| gtk_window_set_default(GTK_WINDOW(dialog), label); |
| gtk_dialog_add_button(dialog, |
| GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| slurm_init_update_node_msg(node_msg); |
| node_msg->node_names = xstrdup(nodelist); |
| |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Available 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 ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) { |
| edit = g_strdup_printf( |
| "Node(s) %s updated successfully.", |
| nodelist); |
| display_edit_note(edit); |
| g_free(edit); |
| |
| } else { |
| edit = g_strdup_printf( |
| "Problem updating node(s) %s: %s", |
| nodelist, slurm_strerror(rc)); |
| 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)); |
| |
| return rc; |
| } |
| |
| extern int update_gres_node(GtkDialog *dialog, const char *nodelist, |
| const char *old_gres) |
| { |
| 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 (_DEBUG) |
| g_print("update_gres_node:global_row_count:" |
| " %d node_names %s\n", |
| global_row_count, nodelist); |
| if (!dialog) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Update Gres 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_type_hint(GTK_WINDOW(dialog), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| gtk_window_set_default(GTK_WINDOW(dialog), label); |
| gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| slurm_init_update_node_msg(node_msg); |
| node_msg->node_names = xstrdup(nodelist); |
| |
| snprintf(tmp_char, sizeof(tmp_char), "Gres 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_gres) |
| gtk_entry_set_text(GTK_ENTRY(entry), old_gres); |
| |
| 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->gres = xstrdup(gtk_entry_get_text(GTK_ENTRY(entry))); |
| if (!node_msg->gres) { |
| edit = g_strdup_printf("No gres given."); |
| display_edit_note(edit); |
| g_free(edit); |
| goto end_it; |
| } |
| if ((rc = 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: %s", |
| nodelist, slurm_strerror(rc)); |
| 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)); |
| |
| return rc; |
| } |
| |
| extern int update_state_node(GtkDialog *dialog, |
| const char *nodelist, const char *type) |
| { |
| uint16_t state = NO_VAL16; |
| char *upper = NULL, *lower = NULL; |
| int i = 0; |
| int rc = SLURM_SUCCESS; |
| char tmp_char[100]; |
| update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t)); |
| GtkWidget *label = NULL; |
| GtkWidget *entry = NULL; |
| int no_dialog = 0; |
| |
| if (!dialog) { |
| dialog = GTK_DIALOG( |
| gtk_dialog_new_with_buttons( |
| type, |
| 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_type_hint(GTK_WINDOW(dialog), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| gtk_window_set_default(GTK_WINDOW(dialog), label); |
| gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| slurm_init_update_node_msg(node_msg); |
| node_msg->node_names = xstrdup(nodelist); |
| |
| if (!xstrncasecmp("drain", type, 5)) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Are you sure you want to drain node(s) %s?\n\n" |
| "Please put reason.", |
| nodelist); |
| entry = create_entry(); |
| label = gtk_label_new(tmp_char); |
| state = NODE_STATE_DRAIN; |
| } else if (!xstrncasecmp("resume", type, 5)) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Are you sure you want to resume node(s) %s?", |
| nodelist); |
| label = gtk_label_new(tmp_char); |
| state = NODE_RESUME; |
| } else if (!xstrncasecmp("set", type, 3)) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Are you sure you want to down node(s) %s?\n\n" |
| "Please put reason.", |
| nodelist); |
| entry = create_entry(); |
| label = gtk_label_new(tmp_char); |
| state = NODE_STATE_DOWN; |
| } else if (!xstrncasecmp("undrain", type, 5)) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Are you sure you want to undrain node(s) %s?", |
| nodelist); |
| label = gtk_label_new(tmp_char); |
| state = NODE_STATE_UNDRAIN; |
| } else { |
| |
| if (!xstrncasecmp("make", type, 4)) |
| type = "idle"; |
| for(i = 0; i < NODE_STATE_END; i++) { |
| upper = node_state_string(i); |
| lower = str_tolower(upper); |
| if (!xstrcmp(lower, type)) { |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Are you sure you want to set " |
| "node(s) %s to %s?", |
| nodelist, lower); |
| label = gtk_label_new(tmp_char); |
| state = i; |
| xfree(lower); |
| break; |
| } |
| 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) |
| gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, true, true, 0); |
| gtk_widget_show_all(GTK_WIDGET(dialog)); |
| i = gtk_dialog_run(dialog); |
| if (i == GTK_RESPONSE_OK) { |
| if (entry) { |
| node_msg->reason = xstrdup( |
| gtk_entry_get_text(GTK_ENTRY(entry))); |
| if (!node_msg->reason || !strlen(node_msg->reason)) { |
| lower = g_strdup_printf( |
| "You need a reason to do that."); |
| display_edit_note(lower); |
| g_free(lower); |
| goto end_it; |
| } |
| if (uid_from_string(getlogin(), |
| &node_msg->reason_uid) != |
| SLURM_SUCCESS) |
| node_msg->reason_uid = getuid(); |
| |
| } |
| if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) { |
| lower = g_strdup_printf( |
| "Nodes %s updated successfully.", |
| nodelist); |
| display_edit_note(lower); |
| g_free(lower); |
| } else { |
| lower = g_strdup_printf( |
| "Problem updating nodes %s: %s", |
| nodelist, slurm_strerror(rc)); |
| display_edit_note(lower); |
| g_free(lower); |
| } |
| } |
| end_it: |
| slurm_free_update_node_msg(node_msg); |
| if (no_dialog) |
| gtk_widget_destroy(GTK_WIDGET(dialog)); |
| |
| return rc; |
| } |
| |
| extern GtkListStore *create_model_node(int type) |
| { |
| GtkListStore *model = NULL; |
| GtkTreeIter iter; |
| char *upper = NULL, *lower = NULL; |
| int i=0; |
| |
| last_model = NULL; /* Reformat display */ |
| switch(type) { |
| case SORTID_STATE: |
| model = gtk_list_store_new(2, G_TYPE_STRING, |
| G_TYPE_INT); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "drain", |
| 1, i, |
| -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "NoResp", |
| 1, i, |
| -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "resume", |
| 1, i, |
| -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "undrain", |
| 1, i, |
| -1); |
| for(i = 0; i < NODE_STATE_END; i++) { |
| upper = node_state_string(i); |
| gtk_list_store_append(model, &iter); |
| lower = str_tolower(upper); |
| gtk_list_store_set(model, &iter, |
| 0, lower, |
| 1, i, |
| -1); |
| xfree(lower); |
| } |
| |
| break; |
| |
| } |
| return model; |
| } |
| |
| extern void admin_edit_node(GtkCellRendererText *cell, |
| const char *path_string, |
| const char *new_text, |
| gpointer data) |
| { |
| GtkTreeStore *treestore = NULL; |
| GtkTreePath *path = NULL; |
| GtkTreeIter iter; |
| char *nodelist = NULL; |
| int column; |
| |
| if (!new_text || !xstrcmp(new_text, "")) |
| goto no_input; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) { |
| display_fed_disabled_popup(new_text); |
| goto no_input; |
| } |
| |
| treestore = GTK_TREE_STORE(data); |
| path = gtk_tree_path_new_from_string(path_string); |
| gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path); |
| |
| column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column")); |
| switch(column) { |
| case SORTID_STATE: |
| gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter, |
| SORTID_NAME, |
| &nodelist, -1); |
| |
| update_state_node(NULL, nodelist, new_text); |
| |
| g_free(nodelist); |
| default: |
| break; |
| } |
| |
| gtk_tree_path_free(path); |
| no_input: |
| g_mutex_unlock(sview_mutex); |
| } |
| |
| extern void get_info_node(GtkTable *table, display_data_t *display_data) |
| { |
| int error_code = SLURM_SUCCESS; |
| static int view = -1; |
| static node_info_msg_t *node_info_ptr = NULL; |
| char error_char[100]; |
| GtkWidget *label = NULL; |
| GtkTreeView *tree_view = NULL; |
| static GtkWidget *display_widget = NULL; |
| list_t *info_list = NULL; |
| int i = 0, sort_key; |
| sview_node_info_t *sview_node_info_ptr = NULL; |
| list_itr_t *itr = NULL; |
| GtkTreePath *path = NULL; |
| static bool set_opts = false; |
| |
| if (!set_opts) |
| set_page_opts(NODE_PAGE, display_data_node, |
| SORTID_CNT, _initial_page_opts); |
| set_opts = true; |
| |
| /* reset */ |
| if (!table && !display_data) { |
| if (display_widget) |
| gtk_widget_destroy(display_widget); |
| display_widget = NULL; |
| goto reset_curs; |
| } |
| |
| if (display_data) |
| local_display_data = display_data; |
| if (!table) { |
| display_data_node->set_menu = local_display_data->set_menu; |
| goto reset_curs; |
| } |
| |
| if (display_widget && toggled) { |
| gtk_widget_destroy(display_widget); |
| display_widget = NULL; |
| /* Since the node_info_ptr could change out from under |
| * us we always need to check if it is new or not. |
| */ |
| /* goto display_it; */ |
| } |
| if ((error_code = get_new_info_node(&node_info_ptr, force_refresh)) |
| == SLURM_NO_CHANGE_IN_DATA) { |
| if (!display_widget || view == ERROR_VIEW) |
| goto display_it; |
| } else if (error_code != SLURM_SUCCESS) { |
| if (view == ERROR_VIEW) |
| goto end_it; |
| view = ERROR_VIEW; |
| if (display_widget) |
| gtk_widget_destroy(display_widget); |
| sprintf(error_char, "slurm_load_node: %s", |
| slurm_strerror(errno)); |
| label = gtk_label_new(error_char); |
| display_widget = g_object_ref(label); |
| gtk_table_attach_defaults(table, label, 0, 1, 0, 1); |
| gtk_widget_show(label); |
| goto end_it; |
| } |
| |
| display_it: |
| info_list = create_node_info_list(node_info_ptr, false); |
| if (!info_list) |
| goto reset_curs; |
| i = 0; |
| /* set up the grid */ |
| if (display_widget && GTK_IS_TREE_VIEW(display_widget) && |
| gtk_tree_selection_count_selected_rows( |
| gtk_tree_view_get_selection( |
| GTK_TREE_VIEW(display_widget)))) { |
| GtkTreeViewColumn *focus_column = NULL; |
| /* highlight the correct nodes from the last selection */ |
| gtk_tree_view_get_cursor(GTK_TREE_VIEW(display_widget), |
| &path, &focus_column); |
| } |
| if (!path) { |
| int array_size = node_info_ptr->record_count; |
| int *color_inx = xmalloc(sizeof(int) * array_size); |
| bool *color_set_flag = xmalloc(sizeof(bool) * array_size); |
| itr = list_iterator_create(info_list); |
| while ((sview_node_info_ptr = list_next(itr))) { |
| color_set_flag[i] = true; |
| color_inx[i] = i; |
| i++; |
| } |
| list_iterator_destroy(itr); |
| change_grid_color_array(grid_button_list, array_size, |
| color_inx, color_set_flag, true, 0); |
| xfree(color_inx); |
| xfree(color_set_flag); |
| } else { |
| highlight_grid(GTK_TREE_VIEW(display_widget), |
| SORTID_POS, (int)NO_VAL, grid_button_list); |
| gtk_tree_path_free(path); |
| } |
| |
| if (view == ERROR_VIEW && display_widget) { |
| gtk_widget_destroy(display_widget); |
| display_widget = NULL; |
| } |
| if (!display_widget) { |
| tree_view = create_treeview(local_display_data, |
| &grid_button_list); |
| /*set multiple capability here*/ |
| gtk_tree_selection_set_mode( |
| gtk_tree_view_get_selection(tree_view), |
| GTK_SELECTION_MULTIPLE); |
| display_widget = g_object_ref(GTK_WIDGET(tree_view)); |
| gtk_table_attach_defaults(GTK_TABLE(table), |
| GTK_WIDGET(tree_view), |
| 0, 1, 0, 1); |
| /* Since this function sets the model of the tree_view to the |
| * treestore we don't really care about the return value |
| * On large clusters, sorting on the node name slows GTK down |
| * by a large margin. */ |
| if (node_info_ptr->record_count > 1000) |
| sort_key = -1; |
| else |
| sort_key = SORTID_NAME; |
| create_treestore(tree_view, display_data_node, |
| SORTID_CNT, sort_key, SORTID_COLOR); |
| } |
| |
| view = INFO_VIEW; |
| /* If the system has a large number of nodes then not all lines |
| * will be displayed. You can try different values for the third |
| * argument of gtk_widget_set_size_request() in an attempt to |
| * maximumize the data displayed in your environment. These are my |
| * results: Y=1000 good for 43 lines, Y=-1 good for 1151 lines, |
| * Y=64000 good for 2781 lines, Y=99000 good for 1453 lines */ |
| /* gtk_widget_set_size_request(display_widget, -1, -1); */ |
| _update_info_node(info_list, GTK_TREE_VIEW(display_widget)); |
| end_it: |
| toggled = false; |
| force_refresh = 1; |
| reset_curs: |
| if (main_window && main_window->window) |
| gdk_window_set_cursor(main_window->window, NULL); |
| return; |
| |
| } |
| |
| extern void specific_info_node(popup_info_t *popup_win) |
| { |
| int error_code = SLURM_SUCCESS; |
| static node_info_msg_t *node_info_ptr = NULL; |
| specific_info_t *spec_info = popup_win->spec_info; |
| char error_char[100]; |
| GtkWidget *label = NULL; |
| GtkTreeView *tree_view = NULL; |
| list_t *info_list = NULL; |
| list_t *send_info_list = NULL; |
| list_itr_t *itr = NULL; |
| sview_node_info_t *sview_node_info_ptr = NULL; |
| node_info_t *node_ptr = NULL; |
| hostlist_t *hostlist = NULL; |
| hostlist_iterator_t *host_itr = NULL; |
| int i = -1, sort_key; |
| sview_search_info_t *search_info = spec_info->search_info; |
| |
| if (!spec_info->display_widget) |
| setup_popup_info(popup_win, display_data_node, SORTID_CNT); |
| |
| if (node_info_ptr && popup_win->toggled) { |
| gtk_widget_destroy(spec_info->display_widget); |
| spec_info->display_widget = NULL; |
| /* Since the node_info_ptr could change out from under |
| * us we always need to check if it is new or not. |
| */ |
| /* goto display_it; */ |
| } |
| |
| if ((error_code = get_new_info_node(&node_info_ptr, |
| popup_win->force_refresh)) |
| == SLURM_NO_CHANGE_IN_DATA) { |
| if (!spec_info->display_widget || spec_info->view == ERROR_VIEW) |
| goto display_it; |
| } else if (error_code != SLURM_SUCCESS) { |
| if (spec_info->view == ERROR_VIEW) |
| goto end_it; |
| spec_info->view = ERROR_VIEW; |
| if (spec_info->display_widget) |
| gtk_widget_destroy(spec_info->display_widget); |
| sprintf(error_char, "slurm_load_node: %s", |
| slurm_strerror(errno)); |
| label = gtk_label_new(error_char); |
| gtk_table_attach_defaults(popup_win->table, |
| label, |
| 0, 1, 0, 1); |
| gtk_widget_show(label); |
| spec_info->display_widget = g_object_ref(label); |
| return; |
| } |
| display_it: |
| |
| info_list = create_node_info_list(node_info_ptr, false); |
| |
| if (!info_list) |
| return; |
| |
| if (spec_info->view == ERROR_VIEW && spec_info->display_widget) { |
| gtk_widget_destroy(spec_info->display_widget); |
| spec_info->display_widget = NULL; |
| } |
| if (spec_info->type != INFO_PAGE && !spec_info->display_widget) { |
| tree_view = create_treeview(local_display_data, |
| &popup_win->grid_button_list); |
| /*set multiple capability here*/ |
| gtk_tree_selection_set_mode( |
| gtk_tree_view_get_selection(tree_view), |
| GTK_SELECTION_MULTIPLE); |
| spec_info->display_widget = |
| g_object_ref(GTK_WIDGET(tree_view)); |
| gtk_table_attach_defaults(popup_win->table, |
| GTK_WIDGET(tree_view), |
| 0, 1, 0, 1); |
| /* Since this function sets the model of the tree_view to the |
| * treestore we don't really care about the return value |
| * On large clusters, sorting on the node name slows GTK down |
| * by a large margin. */ |
| if (node_info_ptr->record_count > 1000) |
| sort_key = -1; |
| else |
| sort_key = SORTID_NAME; |
| create_treestore(tree_view, popup_win->display_data, |
| SORTID_CNT, sort_key, SORTID_COLOR); |
| } |
| |
| setup_popup_grid_list(popup_win); |
| |
| spec_info->view = INFO_VIEW; |
| if (spec_info->type == INFO_PAGE) { |
| _display_info_node(info_list, popup_win); |
| goto end_it; |
| } |
| |
| setup_popup_grid_list(popup_win); |
| |
| /* just linking to another list, don't free the inside, just |
| the list */ |
| send_info_list = list_create(NULL); |
| if (search_info->gchar_data) { |
| hostlist = hostlist_create(search_info->gchar_data); |
| host_itr = hostlist_iterator_create(hostlist); |
| } |
| |
| i = -1; |
| |
| itr = list_iterator_create(info_list); |
| while ((sview_node_info_ptr = list_next(itr))) { |
| int found = 0; |
| char *host = NULL; |
| i++; |
| node_ptr = sview_node_info_ptr->node_ptr; |
| |
| switch(search_info->search_type) { |
| case SEARCH_NODE_STATE: |
| if (search_info->int_data == NO_VAL) |
| continue; |
| if ((node_ptr->node_state & NODE_STATE_BASE) == |
| (search_info->int_data & NODE_STATE_BASE)) |
| found = 1; |
| if ((node_ptr->node_state & NODE_STATE_FLAGS) & |
| (search_info->int_data & NODE_STATE_FLAGS)) |
| found = 1; |
| if (!found) |
| continue; |
| break; |
| case SEARCH_NODE_NAME: |
| default: |
| if (!search_info->gchar_data) |
| continue; |
| while ((host = hostlist_next(host_itr))) { |
| if (!xstrcmp(host, node_ptr->name)) { |
| free(host); |
| found = 1; |
| break; |
| } |
| free(host); |
| } |
| hostlist_iterator_reset(host_itr); |
| |
| if (!found) |
| continue; |
| break; |
| } |
| list_push(send_info_list, sview_node_info_ptr); |
| change_grid_color(popup_win->grid_button_list, |
| i, i, 0, true, 0); |
| } |
| list_iterator_destroy(itr); |
| post_setup_popup_grid_list(popup_win); |
| |
| if (search_info->gchar_data) { |
| hostlist_iterator_destroy(host_itr); |
| hostlist_destroy(hostlist); |
| } |
| |
| _update_info_node(send_info_list, |
| GTK_TREE_VIEW(spec_info->display_widget)); |
| FREE_NULL_LIST(send_info_list); |
| end_it: |
| popup_win->toggled = 0; |
| popup_win->force_refresh = 0; |
| |
| return; |
| |
| } |
| |
| extern void set_menus_node(void *arg, void *arg2, GtkTreePath *path, int type) |
| { |
| GtkTreeView *tree_view = (GtkTreeView *)arg; |
| popup_info_t *popup_win = (popup_info_t *)arg; |
| GtkMenu *menu = (GtkMenu *)arg2; |
| list_t *button_list = arg2; |
| |
| switch(type) { |
| case TAB_CLICKED: |
| make_fields_menu(NULL, menu, display_data_node, SORTID_CNT); |
| break; |
| case ROW_CLICKED: |
| make_options_menu(tree_view, path, menu, options_data_node); |
| break; |
| case ROW_LEFT_CLICKED: |
| { |
| GtkTreeModel *model = gtk_tree_view_get_model(tree_view); |
| GtkTreeIter iter; |
| if (!gtk_tree_model_get_iter(model, &iter, path)) { |
| g_error("error getting iter from model\n"); |
| break; |
| } |
| highlight_grid(tree_view, SORTID_POS, (int)NO_VAL, button_list); |
| break; |
| } |
| case FULL_CLICKED: |
| { |
| GtkTreeModel *model = gtk_tree_view_get_model(tree_view); |
| GtkTreeIter iter; |
| if (!gtk_tree_model_get_iter(model, &iter, path)) { |
| g_error("error getting iter from model\n"); |
| break; |
| } |
| |
| popup_all_node(model, &iter, INFO_PAGE); |
| |
| break; |
| } |
| case POPUP_CLICKED: |
| make_fields_menu(popup_win, menu, |
| popup_win->display_data, SORTID_CNT); |
| break; |
| default: |
| g_error("UNKNOWN type %d given to set_fields\n", type); |
| } |
| } |
| |
| extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id) |
| { |
| char *name = NULL, *cluster_name = NULL; |
| |
| gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); |
| gtk_tree_model_get(model, iter, SORTID_CLUSTER_NAME, &cluster_name, -1); |
| if (_DEBUG) |
| g_print("popup_all_node: name = %s\n", name); |
| popup_all_node_name(name, id, cluster_name); |
| /* this name gets g_strdup'ed in the previous function */ |
| g_free(name); |
| g_free(cluster_name); |
| } |
| |
| extern void popup_all_node_name(char *name, int id, char *cluster_name) |
| { |
| char title[100] = {0}; |
| list_itr_t *itr = NULL; |
| popup_info_t *popup_win = NULL; |
| GError *error = NULL; |
| |
| switch(id) { |
| case JOB_PAGE: |
| snprintf(title, 100, "Job(s) with Node %s", name); |
| break; |
| case PART_PAGE: |
| snprintf(title, 100, "Partition(s) with Node %s", name); |
| break; |
| case RESV_PAGE: |
| snprintf(title, 100, "Reservation(s) with Node %s", name); |
| break; |
| case SUBMIT_PAGE: |
| snprintf(title, 100, "Submit job on Node %s", name); |
| break; |
| case INFO_PAGE: |
| snprintf(title, 100, "Full Info for Node %s", name); |
| break; |
| default: |
| g_print("Node got %d\n", id); |
| } |
| |
| if (cluster_name && federation_name && |
| (cluster_flags & CLUSTER_FLAG_FED)) { |
| char *tmp_cname = |
| xstrdup_printf(" (%s:%s)", |
| federation_name, cluster_name); |
| strncat(title, tmp_cname, sizeof(title) - strlen(title) - 1); |
| xfree(tmp_cname); |
| } |
| |
| itr = list_iterator_create(popup_list); |
| while ((popup_win = list_next(itr))) { |
| if (popup_win->spec_info) |
| if (!xstrcmp(popup_win->spec_info->title, title)) { |
| break; |
| } |
| } |
| list_iterator_destroy(itr); |
| |
| if (!popup_win) { |
| if (id == INFO_PAGE) |
| popup_win = create_popup_info(id, NODE_PAGE, title); |
| else |
| popup_win = create_popup_info(NODE_PAGE, id, title); |
| popup_win->spec_info->search_info->gchar_data = g_strdup(name); |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) |
| popup_win->spec_info->search_info->cluster_name = |
| g_strdup(cluster_name); |
| if (!sview_thread_new((gpointer)popup_thr, popup_win, &error)) { |
| g_printerr ("Failed to create node popup thread: " |
| "%s\n", |
| error->message); |
| return; |
| } |
| } else |
| gtk_window_present(GTK_WINDOW(popup_win->popup)); |
| } |
| |
| extern void admin_menu_node_name(char *name, GdkEventButton *event) |
| { |
| GtkMenu *menu = GTK_MENU(gtk_menu_new()); |
| display_data_t *display_data = options_data_node; |
| GtkWidget *menuitem; |
| |
| while (display_data++) { |
| if (display_data->id == -1) |
| break; |
| if (!display_data->name) |
| continue; |
| |
| display_data->user_data = name; |
| menuitem = gtk_menu_item_new_with_label(display_data->name); |
| g_signal_connect(menuitem, "activate", |
| G_CALLBACK(_selected_page), |
| display_data); |
| gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
| } |
| gtk_widget_show_all(GTK_WIDGET(menu)); |
| gtk_menu_popup(menu, NULL, NULL, NULL, NULL, |
| event ? event->button : 0, |
| gdk_event_get_time((GdkEvent*)event)); |
| } |
| |
| extern void select_admin_nodes(GtkTreeModel *model, |
| GtkTreeIter *iter, |
| display_data_t *display_data, |
| uint32_t node_col, |
| GtkTreeView *treeview) |
| { |
| if (treeview) { |
| char *old_value = NULL; |
| hostlist_t *hl = NULL; |
| process_node_t process_node; |
| memset(&process_node, 0, sizeof(process_node_t)); |
| if (node_col == NO_VAL) |
| process_node.node_col = SORTID_NAME; |
| else |
| process_node.node_col = node_col; |
| |
| gtk_tree_selection_selected_foreach( |
| gtk_tree_view_get_selection(treeview), |
| _process_each_node, &process_node); |
| hl = hostlist_create(process_node.nodelist); |
| hostlist_uniq(hl); |
| hostlist_sort(hl); |
| xfree(process_node.nodelist); |
| process_node.nodelist = hostlist_ranged_string_xmalloc(hl); |
| hostlist_destroy(hl); |
| |
| if (!xstrcasecmp("Update Features", display_data->name)) { |
| /* get old features */ |
| gtk_tree_model_get(model, iter, SORTID_AVAIL_FEATURES, |
| &old_value, -1); |
| } else if (!xstrcasecmp("Update Gres", display_data->name)) { |
| /* get old gres */ |
| gtk_tree_model_get(model, iter, SORTID_GRES, |
| &old_value, -1); |
| } |
| admin_node_name(process_node.nodelist, old_value, |
| display_data->name); |
| xfree(process_node.nodelist); |
| if (old_value) |
| g_free(old_value); |
| |
| |
| } |
| } /*select_admin_nodes ^^^*/ |
| |
| extern void admin_node_name(char *name, char *old_value, char *type) |
| { |
| GtkWidget *popup = NULL; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) { |
| display_fed_disabled_popup(type); |
| return; |
| } |
| |
| popup = gtk_dialog_new_with_buttons( |
| type, |
| GTK_WINDOW(main_window), |
| GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, |
| NULL); |
| gtk_window_set_type_hint(GTK_WINDOW(popup), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| gtk_window_set_transient_for(GTK_WINDOW(popup), NULL); |
| |
| if (!xstrcasecmp("Update Available Features", type) |
| || !xstrcasecmp("Update Node Features", type) |
| || !xstrcasecmp("Update Midplane Features", |
| type)) { /* update features */ |
| update_avail_features_node(GTK_DIALOG(popup), name, old_value); |
| } else if (!xstrcasecmp("Update Active Features", type)) { |
| update_active_features_node(GTK_DIALOG(popup), name, old_value); |
| } else if (!xstrcasecmp("Update Gres", type)) { /* update gres */ |
| update_gres_node(GTK_DIALOG(popup), name, old_value); |
| } else /* something that has to deal with a node state change */ |
| update_state_node(GTK_DIALOG(popup), name, type); |
| |
| gtk_widget_destroy(popup); |
| |
| return; |
| } |
| |
| extern void cluster_change_node(void) |
| { |
| display_data_t *display_data = display_data_node; |
| while (display_data++) { |
| if (display_data->id == -1) |
| break; |
| if (cluster_flags & CLUSTER_FLAG_FED) { |
| switch(display_data->id) { |
| case SORTID_CLUSTER_NAME: |
| display_data->show = true; |
| break; |
| } |
| } else { |
| switch(display_data->id) { |
| case SORTID_CLUSTER_NAME: |
| display_data->show = false; |
| break; |
| } |
| } |
| } |
| |
| get_info_node(NULL, NULL); |
| } |