| /*****************************************************************************\ |
| * part_info.c - Functions related to partition 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" |
| #include "src/common/parse_time.h" |
| #include <grp.h> |
| |
| #define _DEBUG 0 |
| |
| static GtkListStore *_create_model_part2(int type); |
| |
| typedef struct { |
| uint32_t cpu_cnt; |
| uint32_t cpu_alloc_cnt; |
| uint32_t cpu_idle_cnt; |
| uint32_t disk_total; |
| char *features; |
| char *features_act; |
| hostlist_t *hl; |
| uint64_t mem_total; |
| uint32_t node_cnt; |
| uint32_t node_alloc_cnt; |
| uint32_t node_error_cnt; |
| uint32_t node_idle_cnt; |
| list_t *node_ptr_list; |
| uint32_t node_state; |
| partition_info_t* part_ptr; |
| char *reason; |
| } sview_part_sub_t; |
| |
| /* Collection of data for printing reports. Like data is combined here */ |
| typedef struct { |
| int color_inx; |
| GtkTreeIter iter_ptr; |
| bool iter_set; |
| char *part_name; |
| char *cluster_name; |
| /* part_info contains partition, avail, max_time, job_size, |
| * root, share, groups */ |
| partition_info_t* part_ptr; |
| int pos; |
| list_t *sub_list; |
| sview_part_sub_t sub_part_total; |
| } sview_part_info_t; |
| |
| enum { |
| EDIT_PART_STATE = 1, |
| EDIT_REMOVE_PART, |
| EDIT_EDIT |
| }; |
| |
| /* These need to be in alpha order (except POS and CNT) */ |
| enum { |
| SORTID_POS = POS_LOC, |
| SORTID_ALLOW_ACCOUNTS, |
| SORTID_ALLOW_GROUPS, |
| SORTID_ALLOW_QOS, |
| SORTID_ALTERNATE, |
| SORTID_CLUSTER_NAME, |
| SORTID_COLOR, |
| SORTID_COLOR_INX, |
| SORTID_CPUS, |
| SORTID_DEFAULT, |
| SORTID_DENY_ACCOUNTS, |
| SORTID_DENY_QOS, |
| SORTID_EXCLUSIVE_USER, |
| SORTID_FEATURES, |
| SORTID_FEATURES_ACT, |
| SORTID_GRACE_TIME, |
| SORTID_HIDDEN, |
| SORTID_JOB_DEFAULTS, |
| SORTID_JOB_SIZE, |
| SORTID_MAX_CPUS_PER_NODE, |
| SORTID_MAX_CPUS_PER_SOCKET, |
| SORTID_MEM, |
| SORTID_NAME, |
| SORTID_NODELIST, |
| SORTID_NODES_ALLOWED, |
| SORTID_NODE_INX, |
| SORTID_NODE_STATE, |
| SORTID_NODE_STATE_NUM, |
| SORTID_NODES, |
| SORTID_NODES_MAX, |
| SORTID_NODES_MIN, |
| SORTID_ONLY_LINE, |
| SORTID_OVER_SUBSCRIBE, |
| SORTID_OVER_TIME_LIMIT, |
| SORTID_PART_STATE, |
| SORTID_POWER_DOWN_ON_IDLE, |
| SORTID_PREEMPT_MODE, |
| SORTID_PRIORITY_JOB_FACTOR, |
| SORTID_PRIORITY_TIER, |
| SORTID_QOS_CHAR, |
| SORTID_REASON, |
| SORTID_ROOT, |
| SORTID_TMP_DISK, |
| SORTID_TIMELIMIT, |
| SORTID_UPDATED, |
| SORTID_CNT |
| }; |
| |
| /* |
| * These are the settings to apply for the user |
| * on the first startup after a fresh slurm install. |
| */ |
| static char *_initial_page_opts = "Partition,Default,Part_State,Time_Limit," |
| "Node_Count,Node_State,NodeList"; |
| |
| static display_data_t display_data_part[] = { |
| {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE, refresh_part}, |
| {G_TYPE_STRING, SORTID_CLUSTER_NAME, "ClusterName", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NAME, "Partition", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_COLOR, NULL, true, EDIT_COLOR, refresh_part, |
| create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALTERNATE, "Alternate", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_DEFAULT, "Default", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_EXCLUSIVE_USER, "ExclusiveUser", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_GRACE_TIME, "GraceTime", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_HIDDEN, "Hidden", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PART_STATE, "Part State", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES, "Node Count", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_CPUS, "CPU Count", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODE_STATE, "Node State", false, |
| EDIT_MODEL, refresh_part, |
| create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_JOB_DEFAULTS, "Job Defaults", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_JOB_SIZE, "Job Size", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_POWER_DOWN_ON_IDLE, "PowerDownOnIdle", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PREEMPT_MODE, "PreemptMode", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PRIORITY_JOB_FACTOR, "PriorityJobFactor", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PRIORITY_TIER, "PriorityTier", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES_MIN, "Nodes (minimum)", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_MAX_CPUS_PER_NODE, "Max CPUs Per Node", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_MAX_CPUS_PER_SOCKET, "Max CPUs Per Socket", |
| false, EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_OVER_SUBSCRIBE, "OverSubscribe", false, |
| EDIT_MODEL, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_OVER_TIME_LIMIT, "OverTimeLimit", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ROOT, "RootOnly", false, EDIT_MODEL, |
| refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_QOS_CHAR, "Qos", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALLOW_ACCOUNTS, "Allowed Accounts", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALLOW_GROUPS, "Allowed Groups", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALLOW_QOS, "Allowed Qos", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_DENY_ACCOUNTS, "Denied Accounts", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_DENY_QOS, "Denied Qos", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES_ALLOWED, "Nodes Allowed Allocating", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_TMP_DISK, "Temp Disk", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_MEM, "Memory", false, EDIT_NONE, refresh_part, |
| create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_FEATURES, "Available Features", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_FEATURES_ACT, "Active Features", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_REASON, "Reason", false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODELIST, "NodeList", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_INT, SORTID_NODE_STATE_NUM, NULL, false, |
| EDIT_NONE, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_INT, SORTID_ONLY_LINE, NULL, false, EDIT_NONE, refresh_part, |
| create_model_part, admin_edit_part}, |
| {G_TYPE_INT, SORTID_COLOR_INX, NULL, false, EDIT_NONE, refresh_part, |
| create_model_part, admin_edit_part}, |
| {G_TYPE_POINTER, SORTID_NODE_INX, NULL, false, EDIT_NONE, |
| refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_INT, SORTID_UPDATED, NULL, false, EDIT_NONE, refresh_part, |
| create_model_part, admin_edit_part}, |
| {G_TYPE_NONE, -1, NULL, false, EDIT_NONE} |
| }; |
| |
| static display_data_t create_data_part[] = { |
| {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE, refresh_part}, |
| {G_TYPE_STRING, SORTID_CLUSTER_NAME, "ClusterName", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NAME, "Name", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALTERNATE, "Alternate", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_DEFAULT, "Default", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_EXCLUSIVE_USER, "ExclusiveUser", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_GRACE_TIME, "GraceTime", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_HIDDEN, "Hidden", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_JOB_DEFAULTS, "Job Defaults", false, |
| EDIT_TEXTBOX, refresh_part, create_model_part, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PART_STATE, "State", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_POWER_DOWN_ON_IDLE, "PowerDownOnIdle", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PREEMPT_MODE, "PreemptMode", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PRIORITY_JOB_FACTOR, "PriorityJobFactor", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_PRIORITY_TIER, "PriorityTier", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES_MIN, "Nodes (minimum)", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_MAX_CPUS_PER_NODE, "Max CPUs Per Node", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_MAX_CPUS_PER_SOCKET, "Max CPUs Per Socket", |
| false, EDIT_TEXTBOX, refresh_part, |
| _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ROOT, "RootOnly", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_OVER_SUBSCRIBE, "OverSubscribe", false, |
| EDIT_MODEL, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_OVER_TIME_LIMIT, "OverTimeLimit", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALLOW_ACCOUNTS, "Accounts Allowed", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALLOW_GROUPS, "Groups Allowed", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_ALLOW_QOS, "Qos Allowed", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_DENY_ACCOUNTS, "Accounts Denied", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_DENY_QOS, "Qos Denied", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODES_ALLOWED, "Nodes Allowed Allocating", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_FEATURES, "Available Features", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_FEATURES_ACT, "Active Features", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_NONE, SORTID_REASON, "Reason", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_STRING, SORTID_NODELIST, "NodeList", false, |
| EDIT_TEXTBOX, refresh_part, _create_model_part2, admin_edit_part}, |
| {G_TYPE_NONE, -1, NULL, false, EDIT_NONE} |
| }; |
| |
| static display_data_t options_data_part[] = { |
| {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE}, |
| {G_TYPE_STRING, INFO_PAGE, "Full Info", true, PART_PAGE}, |
| {G_TYPE_STRING, PART_PAGE, "Edit Partition", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, PART_PAGE, "Remove Partition", true, ADMIN_PAGE}, |
| {G_TYPE_STRING, PART_PAGE, "Drain Nodes", |
| true, ADMIN_PAGE | EXTRA_NODES}, |
| {G_TYPE_STRING, PART_PAGE, "Resume Nodes", |
| true, ADMIN_PAGE | EXTRA_NODES}, |
| {G_TYPE_STRING, PART_PAGE, "Put Nodes Down", |
| true, ADMIN_PAGE | EXTRA_NODES}, |
| {G_TYPE_STRING, PART_PAGE, "Make Nodes Idle", |
| true, ADMIN_PAGE | EXTRA_NODES}, |
| {G_TYPE_STRING, PART_PAGE, "Update Node Features", |
| true, ADMIN_PAGE | EXTRA_NODES}, |
| {G_TYPE_STRING, PART_PAGE, "Change Partition State", |
| true, ADMIN_PAGE}, |
| {G_TYPE_STRING, JOB_PAGE, "Jobs", true, PART_PAGE}, |
| {G_TYPE_STRING, NODE_PAGE, "Nodes", true, PART_PAGE}, |
| //{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", false, PART_PAGE}, |
| {G_TYPE_STRING, RESV_PAGE, "Reservations", true, PART_PAGE}, |
| {G_TYPE_NONE, -1, NULL, false, EDIT_NONE} |
| }; |
| |
| static display_data_t *local_display_data = NULL; |
| static char *got_edit_signal = NULL; |
| static char *got_features_edit_signal = NULL; |
| static GtkTreeModel *last_model = NULL; |
| |
| static void _append_part_sub_record(sview_part_sub_t *sview_part_sub, |
| GtkTreeStore *treestore, GtkTreeIter *iter, |
| int line); |
| static void _update_part_sub_record(sview_part_sub_t *sview_part_sub, |
| GtkTreeStore *treestore, |
| GtkTreeIter *iter); |
| |
| static int _build_min_max_32_string(char *buffer, int buf_size, |
| uint32_t min, uint32_t max, bool range) |
| { |
| char tmp_min[8]; |
| char tmp_max[8]; |
| convert_num_unit((float)min, tmp_min, sizeof(tmp_min), UNIT_NONE, |
| NO_VAL, working_sview_config.convert_flags); |
| convert_num_unit((float)max, tmp_max, sizeof(tmp_max), UNIT_NONE, |
| NO_VAL, working_sview_config.convert_flags); |
| |
| if (max == min) |
| return snprintf(buffer, buf_size, "%s", tmp_max); |
| else if (range) { |
| if (max == INFINITE) |
| return snprintf(buffer, buf_size, "%s-infinite", |
| tmp_min); |
| else |
| return snprintf(buffer, buf_size, "%s-%s", |
| tmp_min, tmp_max); |
| } else |
| return snprintf(buffer, buf_size, "%s+", tmp_min); |
| } |
| |
| static void _set_active_combo_part(GtkComboBox *combo, |
| GtkTreeModel *model, GtkTreeIter *iter, |
| int type) |
| { |
| char *temp_char = NULL; |
| int action = 0; |
| int i = 0, unknown_found = 0; |
| char *upper = NULL; |
| |
| if (model) |
| gtk_tree_model_get(model, iter, type, &temp_char, -1); |
| if (!temp_char) |
| goto end_it; |
| switch(type) { |
| case SORTID_DEFAULT: |
| case SORTID_EXCLUSIVE_USER: |
| case SORTID_HIDDEN: |
| case SORTID_POWER_DOWN_ON_IDLE: |
| case SORTID_ROOT: |
| if (!xstrcmp(temp_char, "yes")) |
| action = 0; |
| else if (!xstrcmp(temp_char, "no")) |
| action = 1; |
| else |
| action = 0; |
| |
| break; |
| case SORTID_OVER_SUBSCRIBE: |
| if (!xstrncmp(temp_char, "force", 5)) |
| action = 0; |
| else if (!xstrcmp(temp_char, "no")) |
| action = 1; |
| else if (!xstrncmp(temp_char, "yes", 3)) |
| action = 2; |
| else if (!xstrcmp(temp_char, "exclusive")) |
| action = 3; |
| else |
| action = 0; |
| break; |
| case SORTID_PART_STATE: |
| if (!xstrcmp(temp_char, "up")) |
| action = 0; |
| else if (!xstrcmp(temp_char, "down")) |
| action = 1; |
| else if (!xstrcmp(temp_char, "inactive")) |
| action = 2; |
| else if (!xstrcmp(temp_char, "drain")) |
| action = 3; |
| else |
| action = 0; |
| break; |
| case SORTID_NODE_STATE: |
| if (!xstrcasecmp(temp_char, "drain")) |
| action = 0; |
| else if (!xstrcasecmp(temp_char, "resume")) |
| action = 1; |
| else |
| for(i = 0; i < NODE_STATE_END; i++) { |
| upper = node_state_string(i); |
| if (!xstrcmp(upper, "UNKNOWN")) { |
| unknown_found++; |
| continue; |
| } |
| |
| if (!xstrcasecmp(temp_char, upper)) { |
| action = i + 2 - unknown_found; |
| break; |
| } |
| } |
| |
| break; |
| case SORTID_PREEMPT_MODE: |
| if (!xstrcasecmp(temp_char, "cancel")) |
| action = 0; |
| else if (!xstrcasecmp(temp_char, "off")) |
| action = 2; |
| else if (!xstrcasecmp(temp_char, "requeue")) |
| action = 3; |
| else if (!xstrcasecmp(temp_char, "suspend")) |
| action = 4; |
| else |
| action = 2; /* off */ |
| break; |
| default: |
| break; |
| } |
| g_free(temp_char); |
| end_it: |
| gtk_combo_box_set_active(combo, action); |
| |
| } |
| |
| static uint16_t _set_part_over_subscribe_popup(void) |
| { |
| GtkWidget *table = gtk_table_new(1, 2, false); |
| GtkWidget *label = NULL; |
| GtkObject *adjustment = gtk_adjustment_new(4, |
| 1, 1000, |
| 1, 60, |
| 0); |
| GtkWidget *spin_button = |
| gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1, 0); |
| GtkWidget *popup = gtk_dialog_new_with_buttons( |
| "Count", |
| GTK_WINDOW (main_window), |
| GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, |
| NULL); |
| int response = 0; |
| uint16_t count = 4; |
| |
| gtk_window_set_type_hint(GTK_WINDOW(popup), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| |
| label = gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_OK, GTK_RESPONSE_OK); |
| gtk_window_set_default(GTK_WINDOW(popup), label); |
| |
| label = gtk_label_new("OverSubscribe Job Count "); |
| |
| gtk_container_set_border_width(GTK_CONTAINER(table), 10); |
| |
| gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), |
| table, false, false, 0); |
| |
| gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); |
| gtk_table_attach_defaults(GTK_TABLE(table), spin_button, 1, 2, 0, 1); |
| |
| gtk_widget_show_all(popup); |
| response = gtk_dialog_run (GTK_DIALOG(popup)); |
| |
| if (response == GTK_RESPONSE_OK) { |
| count = gtk_spin_button_get_value_as_int( |
| GTK_SPIN_BUTTON(spin_button)); |
| } |
| |
| gtk_widget_destroy(popup); |
| |
| return count; |
| } |
| |
| /* don't free this char */ |
| static const char *_set_part_msg(update_part_msg_t *part_msg, |
| const char *new_text, |
| int column) |
| { |
| char *type = "", *temp_char; |
| int temp_int = 0; |
| |
| global_edit_error = 0; |
| |
| if (!part_msg) |
| return NULL; |
| |
| switch(column) { |
| case SORTID_ALTERNATE: |
| type = "alternate"; |
| part_msg->alternate = xstrdup(new_text); |
| break; |
| case SORTID_DEFAULT: |
| if (!xstrncasecmp(new_text, "yes", 3)) { |
| part_msg->flags |= PART_FLAG_DEFAULT; |
| part_msg->flags &= (~PART_FLAG_DEFAULT_CLR); |
| } else if (!xstrncasecmp(new_text, "no", 2)) { |
| part_msg->flags &= (~PART_FLAG_DEFAULT); |
| part_msg->flags |= PART_FLAG_DEFAULT_CLR; |
| } |
| type = "default"; |
| break; |
| case SORTID_EXCLUSIVE_USER: |
| if (!xstrncasecmp(new_text, "yes", 3)) { |
| part_msg->flags |= PART_FLAG_EXCLUSIVE_USER; |
| part_msg->flags &= (~PART_FLAG_EXC_USER_CLR); |
| } else if (!xstrncasecmp(new_text, "no", 2)) { |
| part_msg->flags &= (~PART_FLAG_EXCLUSIVE_USER); |
| part_msg->flags |= PART_FLAG_EXC_USER_CLR; |
| } |
| type = "hidden"; |
| break; |
| case SORTID_GRACE_TIME: |
| temp_int = time_str2mins((char *)new_text); |
| type = "grace_time"; |
| if (temp_int <= 0) |
| goto return_error; |
| /* convert to seconds */ |
| part_msg->grace_time = (uint32_t)(temp_int * 60); |
| break; |
| case SORTID_HIDDEN: |
| if (!xstrncasecmp(new_text, "yes", 3)) { |
| part_msg->flags |= PART_FLAG_HIDDEN; |
| part_msg->flags &= (~PART_FLAG_HIDDEN_CLR); |
| } else if (!xstrncasecmp(new_text, "no", 2)) { |
| part_msg->flags &= (~PART_FLAG_HIDDEN); |
| part_msg->flags |= PART_FLAG_HIDDEN_CLR; |
| } |
| type = "hidden"; |
| break; |
| case SORTID_JOB_DEFAULTS: |
| type = "job_defaults"; |
| part_msg->job_defaults_str = xstrdup(new_text); |
| break; |
| case SORTID_TIMELIMIT: |
| if ((xstrcasecmp(new_text, "infinite") == 0)) |
| temp_int = INFINITE; |
| else |
| temp_int = time_str2mins((char *)new_text); |
| |
| type = "timelimit"; |
| if ((temp_int <= 0) && (temp_int != INFINITE)) |
| goto return_error; |
| part_msg->max_time = (uint32_t)temp_int; |
| break; |
| case SORTID_POWER_DOWN_ON_IDLE: |
| if (!xstrncasecmp(new_text, "yes", 3)) { |
| part_msg->flags |= PART_FLAG_PDOI; |
| part_msg->flags &= (~PART_FLAG_PDOI_CLR); |
| } else if (!xstrncasecmp(new_text, "no", 2)) { |
| part_msg->flags &= (~PART_FLAG_PDOI); |
| part_msg->flags |= PART_FLAG_PDOI_CLR; |
| } |
| type = "power_down_on_idle"; |
| break; |
| case SORTID_PREEMPT_MODE: |
| if (!xstrcasecmp(new_text, "cancel")) |
| part_msg->preempt_mode = PREEMPT_MODE_CANCEL; |
| else if (!xstrcasecmp(new_text, "off")) |
| part_msg->preempt_mode = PREEMPT_MODE_OFF; |
| else if (!xstrcasecmp(new_text, "requeue")) |
| part_msg->preempt_mode = PREEMPT_MODE_REQUEUE; |
| else if (!xstrcasecmp(new_text, "suspend")) |
| part_msg->preempt_mode = PREEMPT_MODE_SUSPEND; |
| type = "preempt_mode"; |
| break; |
| case SORTID_PRIORITY_JOB_FACTOR: |
| temp_int = strtol(new_text, (char **)NULL, 10); |
| type = "priority_job_factor"; |
| part_msg->priority_job_factor = (uint16_t)temp_int; |
| break; |
| case SORTID_PRIORITY_TIER: |
| temp_int = strtol(new_text, (char **)NULL, 10); |
| type = "priority_tier"; |
| part_msg->priority_tier = (uint16_t)temp_int; |
| break; |
| case SORTID_NAME: |
| type = "name"; |
| part_msg->name = xstrdup(new_text); |
| break; |
| case SORTID_MAX_CPUS_PER_NODE: |
| temp_int = strtol(new_text, (char **)NULL, 10); |
| type = "max_cpus_per_node"; |
| |
| if (temp_int <= 0) |
| goto return_error; |
| part_msg->max_cpus_per_node = temp_int; |
| break; |
| case SORTID_MAX_CPUS_PER_SOCKET: |
| temp_int = strtol(new_text, (char **)NULL, 10); |
| type = "max_cpus_per_socket"; |
| |
| if (temp_int <= 0) |
| goto return_error; |
| part_msg->max_cpus_per_socket = temp_int; |
| break; |
| case SORTID_NODES_MIN: |
| temp_int = strtol(new_text, (char **)NULL, 10); |
| type = "min_nodes"; |
| |
| if (temp_int <= 0) |
| goto return_error; |
| part_msg->min_nodes = (uint32_t)temp_int; |
| break; |
| case SORTID_NODES_MAX: |
| if (!xstrcasecmp(new_text, "infinite")) { |
| temp_int = INFINITE; |
| } else { |
| temp_int = strtol(new_text, &temp_char, 10); |
| if ((temp_char[0] == 'k') || (temp_char[0] == 'K')) |
| temp_int *= 1024; |
| if ((temp_char[0] == 'm') || (temp_char[0] == 'M')) |
| temp_int *= (1024 * 1024); |
| } |
| |
| type = "max_nodes"; |
| if ((temp_int <= 0) && (temp_int != INFINITE)) |
| goto return_error; |
| part_msg->max_nodes = (uint32_t)temp_int; |
| break; |
| case SORTID_ROOT: |
| if (!xstrncasecmp(new_text, "yes", 3)) { |
| part_msg->flags |= PART_FLAG_ROOT_ONLY; |
| part_msg->flags &= (~PART_FLAG_ROOT_ONLY_CLR); |
| } else if (!xstrncasecmp(new_text, "no", 2)) { |
| part_msg->flags &= (~PART_FLAG_ROOT_ONLY); |
| part_msg->flags |= PART_FLAG_ROOT_ONLY_CLR; |
| } |
| |
| type = "rootonly"; |
| break; |
| case SORTID_OVER_SUBSCRIBE: |
| if (!xstrncasecmp(new_text, "yes", 3)) { |
| part_msg->max_share = _set_part_over_subscribe_popup(); |
| } else if (!xstrcasecmp(new_text, "exclusive")) { |
| part_msg->max_share = 0; |
| } else if (!xstrcasecmp(new_text, "force")) { |
| part_msg->max_share = _set_part_over_subscribe_popup() |
| | SHARED_FORCE; |
| } else if (!xstrncasecmp(new_text, "no", 2)) |
| part_msg->max_share = 1; |
| else |
| goto return_error; |
| type = "oversubscribe"; |
| break; |
| case SORTID_OVER_TIME_LIMIT: |
| if (!xstrcasecmp(new_text, "INFINITE") || |
| !xstrcasecmp(new_text, "UNLIMITED")) { |
| part_msg->over_time_limit = INFINITE16; |
| } else if (new_text[0] >= '0' && new_text[0] <= '9') |
| part_msg->over_time_limit = atoi(new_text); |
| else |
| goto return_error; |
| type = "overtimelimit"; |
| break; |
| case SORTID_ALLOW_ACCOUNTS: |
| type = "accounts"; |
| part_msg->allow_accounts = xstrdup(new_text); |
| break; |
| case SORTID_ALLOW_GROUPS: |
| type = "groups"; |
| part_msg->allow_groups = xstrdup(new_text); |
| break; |
| case SORTID_ALLOW_QOS: |
| type = "qos"; |
| part_msg->allow_qos = xstrdup(new_text); |
| break; |
| case SORTID_DENY_ACCOUNTS: |
| type = "deny account"; |
| part_msg->deny_accounts = xstrdup(new_text); |
| break; |
| case SORTID_DENY_QOS: |
| type = "deny qos"; |
| part_msg->deny_qos = xstrdup(new_text); |
| break; |
| case SORTID_NODES_ALLOWED: |
| type = "allowed alloc nodes"; |
| part_msg->allow_alloc_nodes = xstrdup(new_text); |
| break; |
| case SORTID_NODELIST: |
| part_msg->nodes = xstrdup(new_text); |
| type = "nodelist"; |
| break; |
| case SORTID_PART_STATE: |
| if (!xstrncasecmp(new_text, "up", 2)) |
| part_msg->state_up = PARTITION_UP; |
| else if (!xstrncasecmp(new_text, "down", 4)) |
| part_msg->state_up = PARTITION_DOWN; |
| else if (!xstrncasecmp(new_text, "inactive", 8)) |
| part_msg->state_up = PARTITION_INACTIVE; |
| else if (!xstrncasecmp(new_text, "drain", 5)) |
| part_msg->state_up = PARTITION_DRAIN; |
| else |
| goto return_error; |
| type = "availability"; |
| |
| break; |
| case SORTID_NODE_STATE: |
| type = (char *)new_text; |
| got_edit_signal = xstrdup(new_text); |
| break; |
| case SORTID_FEATURES: |
| type = "Update Features"; |
| got_features_edit_signal = xstrdup(new_text); |
| break; |
| case SORTID_QOS_CHAR: |
| type = "QOS Char"; |
| part_msg->qos_char = xstrdup(new_text); |
| break; |
| default: |
| type = "unknown"; |
| break; |
| } |
| |
| if (xstrcmp(type, "unknown")) |
| global_send_update_msg = 1; |
| |
| return type; |
| |
| return_error: |
| global_edit_error = 1; |
| return type; |
| |
| } |
| |
| static void _admin_edit_combo_box_part(GtkComboBox *combo, |
| update_part_msg_t *part_msg) |
| { |
| GtkTreeModel *model = NULL; |
| GtkTreeIter iter; |
| int column = 0; |
| char *name = NULL; |
| |
| if (!part_msg) |
| return; |
| |
| if (!gtk_combo_box_get_active_iter(combo, &iter)) { |
| g_print("nothing selected\n"); |
| return; |
| } |
| model = gtk_combo_box_get_model(combo); |
| if (!model) { |
| g_print("nothing selected\n"); |
| return; |
| } |
| |
| gtk_tree_model_get(model, &iter, 0, &name, -1); |
| gtk_tree_model_get(model, &iter, 1, &column, -1); |
| |
| (void) _set_part_msg(part_msg, name, column); |
| if (name) |
| g_free(name); |
| } |
| |
| static gboolean _admin_focus_out_part(GtkEntry *entry, |
| GdkEventFocus *event, |
| update_part_msg_t *part_msg) |
| { |
| if (global_entry_changed) { |
| const char *col_name = NULL; |
| int type = gtk_entry_get_max_length(entry); |
| const char *name = gtk_entry_get_text(entry); |
| type -= DEFAULT_ENTRY_LENGTH; |
| col_name = _set_part_msg(part_msg, name, type); |
| if (global_edit_error) { |
| if (global_edit_error_msg) |
| g_free(global_edit_error_msg); |
| global_edit_error_msg = g_strdup_printf( |
| "Partition %s %s can't be set to %s", |
| part_msg->name, |
| col_name, |
| name); |
| } |
| |
| global_entry_changed = 0; |
| } |
| return false; |
| } |
| |
| static GtkWidget *_admin_full_edit_part(update_part_msg_t *part_msg, |
| GtkTreeModel *model, GtkTreeIter *iter) |
| { |
| GtkScrolledWindow *window = create_scrolled_window(); |
| GtkBin *bin = NULL; |
| GtkViewport *view = NULL; |
| GtkTable *table = NULL; |
| int i = 0, row = 0; |
| display_data_t *display_data = display_data_part; |
| |
| gtk_scrolled_window_set_policy(window, |
| GTK_POLICY_NEVER, |
| GTK_POLICY_AUTOMATIC); |
| bin = GTK_BIN(&window->container); |
| view = GTK_VIEWPORT(bin->child); |
| bin = GTK_BIN(&view->bin); |
| table = GTK_TABLE(bin->child); |
| gtk_table_resize(table, SORTID_CNT, 2); |
| |
| gtk_table_set_homogeneous(table, false); |
| |
| for (i = 0; i < SORTID_CNT; i++) { |
| while (display_data++) { |
| if (display_data->id == -1) |
| break; |
| if (!display_data->name) |
| continue; |
| if (display_data->id != i) |
| continue; |
| display_admin_edit( |
| table, part_msg, &row, model, iter, |
| display_data, |
| G_CALLBACK(_admin_edit_combo_box_part), |
| G_CALLBACK(_admin_focus_out_part), |
| _set_active_combo_part); |
| break; |
| } |
| display_data = display_data_part; |
| } |
| gtk_table_resize(table, row, 2); |
| |
| return GTK_WIDGET(window); |
| } |
| |
| static void _subdivide_part(sview_part_info_t *sview_part_info, |
| GtkTreeModel *model, |
| GtkTreeIter *sub_iter, |
| GtkTreeIter *iter) |
| { |
| GtkTreeIter first_sub_iter; |
| list_itr_t *itr = NULL; |
| int i = 0, line = 0; |
| sview_part_sub_t *sview_part_sub = NULL; |
| int set = 0; |
| |
| memset(&first_sub_iter, 0, sizeof(GtkTreeIter)); |
| |
| /* make sure all the steps are still here */ |
| if (sub_iter) { |
| first_sub_iter = *sub_iter; |
| while (1) { |
| gtk_tree_store_set(GTK_TREE_STORE(model), sub_iter, |
| SORTID_UPDATED, 0, -1); |
| if (!gtk_tree_model_iter_next(model, sub_iter)) { |
| break; |
| } |
| } |
| memcpy(sub_iter, &first_sub_iter, sizeof(GtkTreeIter)); |
| set = 1; |
| } |
| itr = list_iterator_create(sview_part_info->sub_list); |
| if ((list_count(sview_part_info->sub_list) == 1) && |
| (sview_part_sub = list_next(itr))) { |
| gtk_tree_store_set(GTK_TREE_STORE(model), iter, |
| SORTID_ONLY_LINE, 1, -1); |
| _update_part_sub_record(sview_part_sub, |
| GTK_TREE_STORE(model), |
| iter); |
| } else { |
| while ((sview_part_sub = list_next(itr))) { |
| if (!sub_iter) { |
| i = NO_VAL; |
| goto adding; |
| } else { |
| memcpy(sub_iter, &first_sub_iter, |
| sizeof(GtkTreeIter)); |
| } |
| line = 0; |
| while (1) { |
| int state; |
| /* Search for the state number and |
| check to see if it is in the |
| list. Here we need to pass an int |
| for system where endian is an |
| issue passing a uint16_t may seg |
| fault. */ |
| gtk_tree_model_get(model, sub_iter, |
| SORTID_NODE_STATE_NUM, |
| &state, -1); |
| if ((uint16_t)state |
| == sview_part_sub->node_state) { |
| /* update with new info */ |
| _update_part_sub_record( |
| sview_part_sub, |
| GTK_TREE_STORE(model), |
| sub_iter); |
| goto found; |
| } |
| |
| line++; |
| if (!gtk_tree_model_iter_next(model, |
| sub_iter)) { |
| break; |
| } |
| } |
| adding: |
| _append_part_sub_record(sview_part_sub, |
| GTK_TREE_STORE(model), |
| iter, line); |
| /* if (i == NO_VAL) */ |
| /* line++; */ |
| found: |
| ; |
| } |
| } |
| list_iterator_destroy(itr); |
| |
| if (set) { |
| sub_iter = &first_sub_iter; |
| /* clear all steps that aren't active */ |
| while (1) { |
| gtk_tree_model_get(model, sub_iter, |
| SORTID_UPDATED, &i, -1); |
| if (!i) { |
| if (!gtk_tree_store_remove( |
| GTK_TREE_STORE(model), |
| sub_iter)) |
| break; |
| else |
| continue; |
| } |
| if (!gtk_tree_model_iter_next(model, sub_iter)) { |
| break; |
| } |
| } |
| } |
| return; |
| } |
| |
| static void _layout_part_record(GtkTreeView *treeview, |
| sview_part_info_t *sview_part_info, |
| int update) |
| { |
| GtkTreeIter iter; |
| char time_buf[20], tmp_buf[20]; |
| char tmp_cnt[8]; |
| char tmp_cnt1[8]; |
| char tmp_cnt2[8]; |
| partition_info_t *part_ptr = sview_part_info->part_ptr; |
| sview_part_sub_t *sview_part_sub = NULL; |
| char ind_cnt[1024]; |
| const char *job_def_str = NULL, *temp_char = NULL; |
| uint16_t temp_uint16 = 0; |
| int i; |
| int yes_no = -1; |
| uint32_t limit_set = NO_VAL; |
| GtkTreeStore *treestore = |
| GTK_TREE_STORE(gtk_tree_view_get_model(treeview)); |
| |
| convert_num_unit((float)sview_part_info->sub_part_total.node_alloc_cnt, |
| tmp_cnt, sizeof(tmp_cnt), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| convert_num_unit((float)sview_part_info->sub_part_total.node_idle_cnt, |
| tmp_cnt1, sizeof(tmp_cnt1), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| convert_num_unit((float)sview_part_info->sub_part_total.node_error_cnt, |
| tmp_cnt2, sizeof(tmp_cnt2), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| snprintf(ind_cnt, sizeof(ind_cnt), "%s/%s/%s", |
| tmp_cnt, tmp_cnt1, tmp_cnt2); |
| |
| for (i = 0; i < SORTID_CNT; i++) { |
| switch (i) { |
| case SORTID_PART_STATE: |
| switch (part_ptr->state_up) { |
| case PARTITION_UP: |
| temp_char = "up"; |
| break; |
| case PARTITION_DOWN: |
| temp_char = "down"; |
| break; |
| case PARTITION_INACTIVE: |
| temp_char = "inactive"; |
| break; |
| case PARTITION_DRAIN: |
| temp_char = "drain"; |
| break; |
| default: |
| temp_char = "unknown"; |
| break; |
| } |
| break; |
| case SORTID_ALTERNATE: |
| if (part_ptr->alternate) |
| temp_char = part_ptr->alternate; |
| else |
| temp_char = ""; |
| break; |
| case SORTID_CPUS: |
| convert_num_unit((float)part_ptr->total_cpus, |
| tmp_cnt, sizeof(tmp_cnt), |
| UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| temp_char = tmp_cnt; |
| break; |
| case SORTID_DEFAULT: |
| if (part_ptr->flags & PART_FLAG_DEFAULT) |
| yes_no = 1; |
| else |
| yes_no = 0; |
| break; |
| case SORTID_FEATURES: |
| if (sview_part_sub) |
| temp_char = sview_part_sub->features; |
| else |
| temp_char = ""; |
| break; |
| case SORTID_GRACE_TIME: |
| limit_set = part_ptr->grace_time; |
| break; |
| case SORTID_ALLOW_ACCOUNTS: |
| if (part_ptr->allow_accounts) |
| temp_char = part_ptr->allow_accounts; |
| else |
| temp_char = "all"; |
| break; |
| case SORTID_ALLOW_GROUPS: |
| if (part_ptr->allow_groups) |
| temp_char = part_ptr->allow_groups; |
| else |
| temp_char = "all"; |
| break; |
| case SORTID_ALLOW_QOS: |
| if (part_ptr->allow_qos) |
| temp_char = part_ptr->allow_qos; |
| else |
| temp_char = "all"; |
| break; |
| case SORTID_CLUSTER_NAME: |
| if (part_ptr->cluster_name) |
| temp_char = part_ptr->cluster_name; |
| break; |
| case SORTID_DENY_ACCOUNTS: |
| if (part_ptr->deny_accounts) |
| temp_char = part_ptr->deny_accounts; |
| else |
| temp_char = "none"; |
| break; |
| case SORTID_DENY_QOS: |
| if (part_ptr->deny_qos) |
| temp_char = part_ptr->deny_qos; |
| else |
| temp_char = "none"; |
| break; |
| case SORTID_EXCLUSIVE_USER: |
| if (part_ptr->flags & PART_FLAG_EXCLUSIVE_USER) |
| yes_no = 1; |
| else |
| yes_no = 0; |
| break; |
| case SORTID_HIDDEN: |
| if (part_ptr->flags & PART_FLAG_HIDDEN) |
| yes_no = 1; |
| else |
| yes_no = 0; |
| break; |
| case SORTID_JOB_DEFAULTS: |
| job_def_str = |
| job_defaults_str(part_ptr->job_defaults_list); |
| temp_char = job_def_str; |
| break; |
| case SORTID_JOB_SIZE: |
| _build_min_max_32_string(time_buf, sizeof(time_buf), |
| part_ptr->min_nodes, |
| part_ptr->max_nodes, true); |
| temp_char = time_buf; |
| break; |
| case SORTID_MEM: |
| convert_num_unit((float)sview_part_info-> |
| sub_part_total.mem_total, |
| tmp_cnt, sizeof(tmp_cnt), |
| UNIT_MEGA, NO_VAL, |
| working_sview_config.convert_flags); |
| temp_char = tmp_cnt; |
| break; |
| case SORTID_NODELIST: |
| temp_char = part_ptr->nodes; |
| break; |
| case SORTID_NODES_ALLOWED: |
| temp_char = part_ptr->allow_alloc_nodes; |
| break; |
| case SORTID_NODES: |
| sprintf(tmp_cnt, "%u", part_ptr->total_nodes); |
| temp_char = tmp_cnt; |
| break; |
| case SORTID_NODES_MAX: |
| limit_set = part_ptr->max_nodes; |
| break; |
| case SORTID_NODES_MIN: |
| limit_set = part_ptr->min_nodes; |
| break; |
| case SORTID_MAX_CPUS_PER_NODE: |
| limit_set = part_ptr->max_cpus_per_node; |
| break; |
| case SORTID_MAX_CPUS_PER_SOCKET: |
| limit_set = part_ptr->max_cpus_per_socket; |
| break; |
| case SORTID_NODE_INX: |
| break; |
| case SORTID_ONLY_LINE: |
| break; |
| case SORTID_POWER_DOWN_ON_IDLE: |
| if (part_ptr->flags & PART_FLAG_PDOI) |
| yes_no = 1; |
| else |
| yes_no = 0; |
| break; |
| case SORTID_PREEMPT_MODE: |
| temp_uint16 = part_ptr->preempt_mode; |
| if (temp_uint16 == NO_VAL16) |
| temp_uint16 = slurm_conf.preempt_mode; |
| temp_char = preempt_mode_string(temp_uint16); |
| break; |
| case SORTID_PRIORITY_JOB_FACTOR: |
| convert_num_unit((float)part_ptr->priority_job_factor, |
| time_buf, sizeof(time_buf), UNIT_NONE, |
| NO_VAL, |
| working_sview_config.convert_flags); |
| temp_char = time_buf; |
| break; |
| case SORTID_PRIORITY_TIER: |
| convert_num_unit((float)part_ptr->priority_tier, |
| time_buf, sizeof(time_buf), UNIT_NONE, |
| NO_VAL, |
| working_sview_config.convert_flags); |
| temp_char = time_buf; |
| break; |
| case SORTID_REASON: |
| sview_part_sub = list_peek(sview_part_info->sub_list); |
| if (sview_part_sub) |
| temp_char = sview_part_sub->reason; |
| else |
| temp_char = ""; |
| break; |
| case SORTID_ROOT: |
| if (part_ptr->flags & PART_FLAG_ROOT_ONLY) |
| yes_no = 1; |
| else |
| yes_no = 0; |
| break; |
| case SORTID_OVER_SUBSCRIBE: |
| if (part_ptr->max_share & SHARED_FORCE) { |
| snprintf(tmp_buf, sizeof(tmp_buf), "force:%u", |
| (part_ptr->max_share |
| & ~(SHARED_FORCE))); |
| temp_char = tmp_buf; |
| } else if (part_ptr->max_share == 0) |
| temp_char = "exclusive"; |
| else if (part_ptr->max_share > 1) { |
| snprintf(tmp_buf, sizeof(tmp_buf), "yes:%u", |
| part_ptr->max_share); |
| temp_char = tmp_buf; |
| } else |
| temp_char = "no"; |
| break; |
| case SORTID_OVER_TIME_LIMIT: |
| if (part_ptr->over_time_limit == INFINITE16) { |
| temp_char = "UNLIMITED"; |
| } else if (part_ptr->over_time_limit == NO_VAL16) { |
| temp_char = "N/A"; |
| } else { |
| snprintf(tmp_buf, sizeof(tmp_buf), "%u", |
| part_ptr->over_time_limit); |
| temp_char = tmp_buf; |
| } |
| break; |
| case SORTID_TMP_DISK: |
| convert_num_unit( |
| (float)sview_part_info->sub_part_total. |
| disk_total, |
| time_buf, sizeof(time_buf), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| temp_char = time_buf; |
| break; |
| case SORTID_TIMELIMIT: |
| limit_set = part_ptr->max_time; |
| break; |
| case SORTID_QOS_CHAR: |
| if (part_ptr->qos_char) |
| temp_char = part_ptr->qos_char; |
| else |
| temp_char = "N/A"; |
| break; |
| default: |
| break; |
| } |
| |
| if (yes_no != -1) { |
| if (yes_no) |
| temp_char = "yes"; |
| else |
| temp_char = "no"; |
| yes_no = -1; |
| } else if (limit_set != NO_VAL) { |
| if (limit_set == INFINITE) |
| temp_char = "infinite"; |
| else { |
| convert_num_unit( |
| (float)limit_set, time_buf, |
| sizeof(time_buf), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| temp_char = time_buf; |
| } |
| limit_set = NO_VAL; |
| } |
| |
| if (temp_char) { |
| add_display_treestore_line( |
| update, treestore, &iter, |
| find_col_name(display_data_part, |
| i), |
| temp_char); |
| if (i == SORTID_NODES) { |
| add_display_treestore_line( |
| update, treestore, &iter, |
| "Nodes (Allocated/Idle/Other)", |
| ind_cnt); |
| } |
| temp_char = NULL; |
| } |
| xfree(job_def_str); |
| } |
| } |
| |
| static void _update_part_record(sview_part_info_t *sview_part_info, |
| GtkTreeStore *treestore) |
| { |
| char tmp_prio_job_factor[40], tmp_prio_tier[40]; |
| char tmp_size[40], tmp_over_subscribe_buf[40], tmp_time[40]; |
| char tmp_max_nodes[40], tmp_min_nodes[40], tmp_grace[40]; |
| char tmp_over_time_limit_buf[40]; |
| char tmp_cpu_cnt[40], tmp_node_cnt[40], tmp_max_cpus_per_node[40]; |
| char tmp_max_cpus_per_socket[40]; |
| char *tmp_alt, *tmp_default, *tmp_accounts, *tmp_groups, *tmp_hidden; |
| char *tmp_deny_accounts, *tmp_qos_char, *tmp_pdoi, *tmp_exc_user; |
| char *tmp_qos, *tmp_deny_qos, *job_def_str = NULL; |
| char *tmp_root, *tmp_over_subscribe, *tmp_over_time_limit, *tmp_state; |
| uint16_t tmp_preempt; |
| partition_info_t *part_ptr = sview_part_info->part_ptr; |
| GtkTreeIter sub_iter; |
| |
| if (part_ptr->alternate) |
| tmp_alt = part_ptr->alternate; |
| else |
| tmp_alt = ""; |
| |
| sprintf(tmp_cpu_cnt, "%u", part_ptr->total_cpus); |
| |
| if (part_ptr->flags & PART_FLAG_DEFAULT) |
| tmp_default = "yes"; |
| else |
| tmp_default = "no"; |
| |
| if (part_ptr->allow_accounts) |
| tmp_accounts = part_ptr->allow_accounts; |
| else |
| tmp_accounts = "all"; |
| |
| if (part_ptr->allow_groups) |
| tmp_groups = part_ptr->allow_groups; |
| else |
| tmp_groups = "all"; |
| |
| if (part_ptr->allow_qos) |
| tmp_qos = part_ptr->allow_qos; |
| else |
| tmp_qos = "all"; |
| |
| if (part_ptr->deny_accounts) |
| tmp_deny_accounts = part_ptr->deny_accounts; |
| else |
| tmp_deny_accounts = "none"; |
| |
| if (part_ptr->deny_qos) |
| tmp_deny_qos = part_ptr->deny_qos; |
| else |
| tmp_deny_qos = "none"; |
| |
| if (part_ptr->flags & PART_FLAG_PDOI) |
| tmp_pdoi = "yes"; |
| else |
| tmp_pdoi = "no"; |
| |
| if (part_ptr->flags & PART_FLAG_EXCLUSIVE_USER) |
| tmp_exc_user = "yes"; |
| else |
| tmp_exc_user = "no"; |
| |
| if (part_ptr->flags & PART_FLAG_HIDDEN) |
| tmp_hidden = "yes"; |
| else |
| tmp_hidden = "no"; |
| |
| if (part_ptr->grace_time == NO_VAL) |
| snprintf(tmp_grace, sizeof(tmp_grace), "none"); |
| else { |
| secs2time_str(part_ptr->grace_time, |
| tmp_grace, sizeof(tmp_grace)); |
| } |
| |
| job_def_str = job_defaults_str(part_ptr->job_defaults_list); |
| |
| if (part_ptr->max_nodes == INFINITE) |
| snprintf(tmp_max_nodes, sizeof(tmp_max_nodes), "infinite"); |
| else { |
| convert_num_unit((float)part_ptr->max_nodes, tmp_max_nodes, |
| sizeof(tmp_max_nodes), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| } |
| |
| if (part_ptr->min_nodes == INFINITE) |
| snprintf(tmp_min_nodes, sizeof(tmp_min_nodes), "infinite"); |
| else { |
| convert_num_unit((float)part_ptr->min_nodes, tmp_min_nodes, |
| sizeof(tmp_min_nodes), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| } |
| |
| if (part_ptr->max_cpus_per_node == INFINITE) { |
| sprintf(tmp_max_cpus_per_node, "UNLIMITED"); |
| } else { |
| sprintf(tmp_max_cpus_per_node, "%u", |
| part_ptr->max_cpus_per_node); |
| } |
| |
| if (part_ptr->max_cpus_per_socket == INFINITE) { |
| sprintf(tmp_max_cpus_per_socket, "UNLIMITED"); |
| } else { |
| sprintf(tmp_max_cpus_per_socket, "%u", |
| part_ptr->max_cpus_per_socket); |
| } |
| |
| sprintf(tmp_node_cnt, "%u", part_ptr->total_nodes); |
| |
| if (part_ptr->flags & PART_FLAG_ROOT_ONLY) |
| tmp_root = "yes"; |
| else |
| tmp_root = "no"; |
| |
| if (part_ptr->state_up == PARTITION_UP) |
| tmp_state = "up"; |
| else if (part_ptr->state_up == PARTITION_DOWN) |
| tmp_state = "down"; |
| else if (part_ptr->state_up == PARTITION_INACTIVE) |
| tmp_state = "inact"; |
| else if (part_ptr->state_up == PARTITION_DRAIN) |
| tmp_state = "drain"; |
| else |
| tmp_state = "unk"; |
| |
| _build_min_max_32_string(tmp_size, sizeof(tmp_size), |
| part_ptr->min_nodes, |
| part_ptr->max_nodes, true); |
| |
| tmp_preempt = part_ptr->preempt_mode; |
| if (tmp_preempt == NO_VAL16) |
| tmp_preempt = slurm_conf.preempt_mode; /* use cluster param */ |
| |
| convert_num_unit((float)part_ptr->priority_job_factor, |
| tmp_prio_job_factor, sizeof(tmp_prio_job_factor), |
| UNIT_NONE, NO_VAL, working_sview_config.convert_flags); |
| |
| convert_num_unit((float)part_ptr->priority_tier, tmp_prio_tier, |
| sizeof(tmp_prio_tier), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| |
| if (part_ptr->max_share & SHARED_FORCE) { |
| snprintf(tmp_over_subscribe_buf, sizeof(tmp_over_subscribe_buf), |
| "force:%u", (part_ptr->max_share & ~(SHARED_FORCE))); |
| tmp_over_subscribe = tmp_over_subscribe_buf; |
| } else if (part_ptr->max_share == 0) { |
| tmp_over_subscribe = "exclusive"; |
| } else if (part_ptr->max_share > 1) { |
| snprintf(tmp_over_subscribe_buf, |
| sizeof(tmp_over_subscribe_buf), "yes:%u", |
| part_ptr->max_share); |
| tmp_over_subscribe = tmp_over_subscribe_buf; |
| } else |
| tmp_over_subscribe = "no"; |
| |
| if (part_ptr->over_time_limit == INFINITE16) { |
| tmp_over_time_limit = "UNLIMITED"; |
| } else if (part_ptr->over_time_limit == NO_VAL16) { |
| tmp_over_time_limit = "N/A"; |
| } else { |
| snprintf(tmp_over_time_limit_buf, |
| sizeof(tmp_over_time_limit_buf), "%u", |
| part_ptr->over_time_limit); |
| tmp_over_time_limit = tmp_over_time_limit_buf; |
| } |
| |
| if (part_ptr->max_time == INFINITE) |
| snprintf(tmp_time, sizeof(tmp_time), "infinite"); |
| else { |
| secs2time_str((part_ptr->max_time * 60), |
| tmp_time, sizeof(tmp_time)); |
| } |
| |
| if (part_ptr->qos_char) |
| tmp_qos_char = part_ptr->qos_char; |
| else |
| tmp_qos_char = "N/A"; |
| |
| /* Combining these records provides a slight performance improvement |
| * NOTE: Some of these fields are cleared here and filled in based upon |
| * the configuration of nodes within this partition. */ |
| gtk_tree_store_set(treestore, &sview_part_info->iter_ptr, |
| SORTID_ALTERNATE, tmp_alt, |
| SORTID_CLUSTER_NAME, part_ptr->cluster_name, |
| SORTID_COLOR, |
| sview_colors[sview_part_info->color_inx], |
| SORTID_COLOR_INX, sview_part_info->color_inx, |
| SORTID_CPUS, tmp_cpu_cnt, |
| SORTID_DEFAULT, tmp_default, |
| SORTID_FEATURES, "", |
| SORTID_FEATURES_ACT, "", |
| SORTID_GRACE_TIME, tmp_grace, |
| SORTID_QOS_CHAR, tmp_qos_char, |
| SORTID_ALLOW_ACCOUNTS, tmp_accounts, |
| SORTID_ALLOW_GROUPS, tmp_groups, |
| SORTID_ALLOW_QOS, tmp_qos, |
| SORTID_DENY_ACCOUNTS, tmp_deny_accounts, |
| SORTID_DENY_QOS, tmp_deny_qos, |
| SORTID_EXCLUSIVE_USER, tmp_exc_user, |
| SORTID_HIDDEN, tmp_hidden, |
| SORTID_JOB_DEFAULTS, job_def_str, |
| SORTID_JOB_SIZE, tmp_size, |
| SORTID_MAX_CPUS_PER_NODE, tmp_max_cpus_per_node, |
| SORTID_MAX_CPUS_PER_SOCKET, tmp_max_cpus_per_socket, |
| SORTID_MEM, "", |
| SORTID_NAME, part_ptr->name, |
| SORTID_NODE_INX, part_ptr->node_inx, |
| SORTID_NODE_STATE, "", |
| SORTID_NODE_STATE_NUM, -1, |
| SORTID_NODES, tmp_node_cnt, |
| SORTID_NODES_MAX, tmp_max_nodes, |
| SORTID_NODES_MIN, tmp_min_nodes, |
| SORTID_NODELIST, part_ptr->nodes, |
| SORTID_ONLY_LINE, 0, |
| SORTID_OVER_SUBSCRIBE, tmp_over_subscribe, |
| SORTID_OVER_TIME_LIMIT, tmp_over_time_limit, |
| SORTID_PART_STATE, tmp_state, |
| SORTID_POWER_DOWN_ON_IDLE, tmp_pdoi, |
| SORTID_PREEMPT_MODE, |
| preempt_mode_string(tmp_preempt), |
| SORTID_PRIORITY_JOB_FACTOR, tmp_prio_job_factor, |
| SORTID_PRIORITY_TIER, tmp_prio_tier, |
| SORTID_REASON, "", |
| SORTID_ROOT, tmp_root, |
| SORTID_TIMELIMIT, tmp_time, |
| SORTID_TMP_DISK, "", |
| SORTID_UPDATED, 1, |
| -1); |
| xfree(job_def_str); |
| |
| if (gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore), |
| &sub_iter, |
| &sview_part_info->iter_ptr)) |
| _subdivide_part(sview_part_info, |
| GTK_TREE_MODEL(treestore), &sub_iter, |
| &sview_part_info->iter_ptr); |
| else |
| _subdivide_part(sview_part_info, |
| GTK_TREE_MODEL(treestore), NULL, |
| &sview_part_info->iter_ptr); |
| |
| return; |
| } |
| |
| static void _update_part_sub_record(sview_part_sub_t *sview_part_sub, |
| GtkTreeStore *treestore, GtkTreeIter *iter) |
| { |
| partition_info_t *part_ptr = sview_part_sub->part_ptr; |
| char *tmp_cpus = NULL, *tmp_nodes = NULL, *tmp_nodelist; |
| char *tmp_state_lower, *tmp_state_upper; |
| char tmp_cnt[40], tmp_disk[40], tmp_mem[40]; |
| |
| tmp_state_upper = node_state_string(sview_part_sub->node_state); |
| tmp_state_lower = str_tolower(tmp_state_upper); |
| |
| if ((sview_part_sub->node_state & NODE_STATE_BASE) |
| == NODE_STATE_MIXED) { |
| if (sview_part_sub->cpu_alloc_cnt) { |
| convert_num_unit((float)sview_part_sub->cpu_alloc_cnt, |
| tmp_cnt, |
| sizeof(tmp_cnt), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| xstrfmtcat(tmp_cpus, "Alloc:%s", tmp_cnt); |
| } |
| if (sview_part_sub->cpu_idle_cnt) { |
| convert_num_unit((float)sview_part_sub->cpu_idle_cnt, |
| tmp_cnt, |
| sizeof(tmp_cnt), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| if (tmp_cpus) |
| xstrcat(tmp_cpus, " "); |
| xstrfmtcat(tmp_cpus, "Idle:%s", tmp_cnt); |
| } |
| } else { |
| tmp_cpus = xmalloc(20); |
| convert_num_unit((float)sview_part_sub->cpu_cnt, |
| tmp_cpus, 20, UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| } |
| |
| if (!tmp_nodes) { |
| convert_num_unit((float)sview_part_sub->node_cnt, tmp_cnt, |
| sizeof(tmp_cnt), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| tmp_nodes = xstrdup(tmp_cnt); |
| } |
| |
| convert_num_unit((float)sview_part_sub->disk_total, tmp_disk, |
| sizeof(tmp_disk), UNIT_NONE, NO_VAL, |
| working_sview_config.convert_flags); |
| |
| convert_num_unit((float)sview_part_sub->mem_total, tmp_mem, |
| sizeof(tmp_mem), UNIT_MEGA, NO_VAL, |
| working_sview_config.convert_flags); |
| |
| tmp_nodelist = hostlist_ranged_string_xmalloc(sview_part_sub->hl); |
| |
| gtk_tree_store_set(treestore, iter, |
| SORTID_CPUS, tmp_cpus, |
| SORTID_FEATURES, sview_part_sub->features, |
| SORTID_FEATURES_ACT, sview_part_sub->features_act, |
| SORTID_MEM, tmp_mem, |
| SORTID_NAME, part_ptr->name, |
| SORTID_NODE_STATE_NUM, sview_part_sub->node_state, |
| SORTID_NODELIST, tmp_nodelist, |
| SORTID_NODES, tmp_nodes, |
| SORTID_NODE_STATE, tmp_state_lower, |
| SORTID_REASON, sview_part_sub->reason, |
| SORTID_TMP_DISK, tmp_disk, |
| SORTID_UPDATED, 1, |
| -1); |
| |
| xfree(tmp_cpus); |
| xfree(tmp_nodelist); |
| xfree(tmp_nodes); |
| xfree(tmp_state_lower); |
| |
| return; |
| } |
| |
| static void _append_part_record(sview_part_info_t *sview_part_info, |
| GtkTreeStore *treestore) |
| { |
| gtk_tree_store_append(treestore, &sview_part_info->iter_ptr, NULL); |
| gtk_tree_store_set(treestore, &sview_part_info->iter_ptr, |
| SORTID_POS, sview_part_info->pos, -1); |
| _update_part_record(sview_part_info, treestore); |
| } |
| |
| static void _append_part_sub_record(sview_part_sub_t *sview_part_sub, |
| GtkTreeStore *treestore, GtkTreeIter *iter, |
| int line) |
| { |
| GtkTreeIter sub_iter; |
| |
| gtk_tree_store_append(treestore, &sub_iter, iter); |
| gtk_tree_store_set(treestore, &sub_iter, SORTID_POS, line, -1); |
| _update_part_sub_record(sview_part_sub, treestore, &sub_iter); |
| } |
| |
| static void _update_info_part(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_part_info_t *sview_part_info = NULL; |
| |
| set_for_update(model, SORTID_UPDATED); |
| |
| itr = list_iterator_create(info_list); |
| while ((sview_part_info = list_next(itr))) { |
| /* This means the tree_store changed (added new column |
| or something). */ |
| if (last_model != model) |
| sview_part_info->iter_set = false; |
| |
| if (sview_part_info->iter_set) { |
| gtk_tree_model_get(model, &sview_part_info->iter_ptr, |
| SORTID_NAME, &name, -1); |
| if (xstrcmp(name, sview_part_info->part_name)) |
| /* Bad pointer */ |
| sview_part_info->iter_set = false; |
| g_free(name); |
| } |
| if (sview_part_info->iter_set) |
| _update_part_record(sview_part_info, |
| GTK_TREE_STORE(model)); |
| else { |
| _append_part_record(sview_part_info, |
| GTK_TREE_STORE(model)); |
| sview_part_info->iter_set = true; |
| } |
| } |
| list_iterator_destroy(itr); |
| /* remove all old partitions */ |
| remove_old(model, SORTID_UPDATED); |
| last_model = model; |
| return; |
| } |
| |
| static void _part_info_free(sview_part_info_t *sview_part_info) |
| { |
| if (sview_part_info) { |
| xfree(sview_part_info->cluster_name); |
| xfree(sview_part_info->part_name); |
| memset(&sview_part_info->sub_part_total, 0, |
| sizeof(sview_part_sub_t)); |
| FREE_NULL_LIST(sview_part_info->sub_list); |
| } |
| } |
| |
| static void _part_info_list_del(void *object) |
| { |
| sview_part_info_t *sview_part_info = (sview_part_info_t *)object; |
| |
| if (sview_part_info) { |
| _part_info_free(sview_part_info); |
| xfree(sview_part_info); |
| } |
| } |
| |
| static void _destroy_part_sub(void *object) |
| { |
| sview_part_sub_t *sview_part_sub = (sview_part_sub_t *)object; |
| |
| if (sview_part_sub) { |
| xfree(sview_part_sub->features); |
| xfree(sview_part_sub->features_act); |
| xfree(sview_part_sub->reason); |
| FREE_NULL_HOSTLIST(sview_part_sub->hl); |
| FREE_NULL_LIST(sview_part_sub->node_ptr_list); |
| xfree(sview_part_sub); |
| } |
| } |
| |
| static void _update_sview_part_sub(sview_part_sub_t *sview_part_sub, |
| node_info_t *node_ptr) |
| { |
| int idle_cpus = node_ptr->cpus; |
| uint16_t alloc_cpus = 0; |
| |
| xassert(sview_part_sub); |
| xassert(sview_part_sub->node_ptr_list); |
| xassert(sview_part_sub->hl); |
| |
| if (sview_part_sub->node_cnt == 0) { /* first node added */ |
| sview_part_sub->node_state = node_ptr->node_state; |
| sview_part_sub->features = xstrdup(node_ptr->features); |
| sview_part_sub->features_act = xstrdup(node_ptr->features_act); |
| sview_part_sub->reason = xstrdup(node_ptr->reason); |
| } else if (hostlist_find(sview_part_sub->hl, node_ptr->name) != -1) { |
| /* we already have this node in this record, |
| * just return, don't duplicate */ |
| g_print("already been here\n"); |
| return; |
| } |
| |
| if ((sview_part_sub->node_state & NODE_STATE_BASE) |
| == NODE_STATE_MIXED) { |
| alloc_cpus = node_ptr->alloc_cpus; |
| idle_cpus -= node_ptr->alloc_cpus; |
| } else if (sview_part_sub->node_state == NODE_STATE_ALLOCATED) { |
| alloc_cpus = idle_cpus; |
| idle_cpus = 0; |
| } |
| |
| sview_part_sub->cpu_cnt += alloc_cpus + idle_cpus; |
| sview_part_sub->cpu_alloc_cnt += alloc_cpus; |
| sview_part_sub->cpu_idle_cnt += idle_cpus; |
| sview_part_sub->disk_total += node_ptr->tmp_disk; |
| sview_part_sub->mem_total += node_ptr->real_memory; |
| sview_part_sub->node_cnt++; |
| |
| list_append(sview_part_sub->node_ptr_list, node_ptr); |
| hostlist_push_host(sview_part_sub->hl, node_ptr->name); |
| } |
| |
| /* |
| * _create_sview_part_sub - create an sview_part_sub record for |
| * the given partition |
| * sview_part_sub OUT - ptr to an inited sview_part_sub_t |
| */ |
| static sview_part_sub_t *_create_sview_part_sub(partition_info_t *part_ptr, |
| node_info_t *node_ptr) |
| { |
| sview_part_sub_t *sview_part_sub_ptr = |
| xmalloc(sizeof(sview_part_sub_t)); |
| |
| if (!part_ptr) { |
| g_print("got no part_ptr!\n"); |
| xfree(sview_part_sub_ptr); |
| return NULL; |
| } |
| if (!node_ptr) { |
| g_print("got no node_ptr!\n"); |
| xfree(sview_part_sub_ptr); |
| return NULL; |
| } |
| sview_part_sub_ptr->part_ptr = part_ptr; |
| sview_part_sub_ptr->hl = hostlist_create(NULL); |
| sview_part_sub_ptr->node_ptr_list = list_create(NULL); |
| _update_sview_part_sub(sview_part_sub_ptr, node_ptr); |
| |
| return sview_part_sub_ptr; |
| } |
| |
| static int _insert_sview_part_sub(sview_part_info_t *sview_part_info, |
| partition_info_t *part_ptr, |
| node_info_t *node_ptr) |
| { |
| sview_part_sub_t *sview_part_sub = NULL; |
| list_itr_t *itr = list_iterator_create(sview_part_info->sub_list); |
| |
| while ((sview_part_sub = list_next(itr))) { |
| if (sview_part_sub->node_state |
| == node_ptr->node_state) { |
| _update_sview_part_sub(sview_part_sub, |
| node_ptr); |
| break; |
| } |
| } |
| list_iterator_destroy(itr); |
| |
| if (!sview_part_sub) { |
| if ((sview_part_sub = _create_sview_part_sub( |
| part_ptr, node_ptr))) |
| list_push(sview_part_info->sub_list, |
| sview_part_sub); |
| } |
| return SLURM_SUCCESS; |
| } |
| |
| static int _sview_part_sort_aval_dec(void *a, void *b) |
| { |
| sview_part_info_t *rec_a = *(sview_part_info_t **)a; |
| sview_part_info_t *rec_b = *(sview_part_info_t **)b; |
| int size_a; |
| int size_b; |
| |
| size_a = rec_a->part_ptr->total_nodes; |
| size_b = rec_b->part_ptr->total_nodes; |
| |
| if (size_a < size_b) |
| return -1; |
| else if (size_a > size_b) |
| return 1; |
| |
| if (rec_a->part_ptr->nodes && rec_b->part_ptr->nodes) { |
| size_a = xstrcmp(rec_a->part_ptr->nodes, |
| rec_b->part_ptr->nodes); |
| if (size_a < 0) |
| return -1; |
| else if (size_a > 0) |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int _sview_sub_part_sort(void *a, void *b) |
| { |
| sview_part_sub_t *rec_a = *(sview_part_sub_t **)a; |
| sview_part_sub_t *rec_b = *(sview_part_sub_t **)b; |
| int size_a; |
| int size_b; |
| |
| size_a = rec_a->node_state & NODE_STATE_BASE; |
| size_b = rec_b->node_state & NODE_STATE_BASE; |
| |
| if (size_a < size_b) |
| return -1; |
| else if (size_a > size_b) |
| return 1; |
| return 0; |
| } |
| |
| static list_t *_create_part_info_list(partition_info_msg_t *part_info_ptr, |
| node_info_msg_t *node_info_ptr) |
| { |
| sview_part_info_t *sview_part_info = NULL; |
| partition_info_t *part_ptr = NULL; |
| static node_info_msg_t *last_node_info_ptr = NULL; |
| static partition_info_msg_t *last_part_info_ptr = NULL; |
| list_t *last_list = NULL; |
| list_itr_t *last_list_itr = NULL; |
| node_info_t *node_ptr = NULL; |
| static list_t *info_list = NULL; |
| int i, j2; |
| sview_part_sub_t *sview_part_sub = NULL; |
| list_itr_t *itr; |
| |
| if (info_list && (node_info_ptr == last_node_info_ptr) |
| && (part_info_ptr == last_part_info_ptr)) |
| return info_list; |
| |
| last_node_info_ptr = node_info_ptr; |
| last_part_info_ptr = part_info_ptr; |
| |
| if (info_list) |
| last_list = info_list; |
| |
| info_list = list_create(_part_info_list_del); |
| |
| if (last_list) |
| last_list_itr = list_iterator_create(last_list); |
| for (i = 0; i < part_info_ptr->record_count; i++) { |
| int c_offset = 0; |
| part_ptr = &(part_info_ptr->partition_array[i]); |
| |
| /* don't include configured excludes */ |
| if (!working_sview_config.show_hidden && |
| part_ptr->flags & PART_FLAG_HIDDEN) |
| continue; |
| |
| sview_part_info = NULL; |
| |
| if (last_list_itr) { |
| while ((sview_part_info = |
| list_next(last_list_itr))) { |
| if (sview_part_info->cluster_name && |
| xstrcmp(sview_part_info->cluster_name, |
| part_ptr->cluster_name)) |
| continue; |
| if (!xstrcmp(sview_part_info->part_name, |
| part_ptr->name)) { |
| list_remove(last_list_itr); |
| _part_info_free(sview_part_info); |
| break; |
| } |
| } |
| list_iterator_reset(last_list_itr); |
| } |
| |
| if (!sview_part_info) |
| sview_part_info = xmalloc(sizeof(sview_part_info_t)); |
| sview_part_info->part_name = xstrdup(part_ptr->name); |
| sview_part_info->cluster_name = xstrdup(part_ptr->cluster_name); |
| sview_part_info->part_ptr = part_ptr; |
| sview_part_info->sub_list = list_create(_destroy_part_sub); |
| sview_part_info->pos = i; |
| list_append(info_list, sview_part_info); |
| sview_part_info->color_inx = i % sview_colors_cnt; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) |
| c_offset = |
| get_cluster_node_offset(part_ptr->cluster_name, |
| node_info_ptr); |
| |
| j2 = 0; |
| while (part_ptr->node_inx[j2] >= 0) { |
| int i2 = 0; |
| for ((i2 = part_ptr->node_inx[j2]); |
| (i2 <= part_ptr->node_inx[j2+1]); |
| i2++) { |
| node_info_t *node_array; |
| node_array = node_info_ptr->node_array; |
| node_ptr = &(node_array[i2 + c_offset]); |
| |
| _insert_sview_part_sub(sview_part_info, |
| part_ptr, |
| node_ptr); |
| } |
| j2 += 2; |
| } |
| list_sort(sview_part_info->sub_list, |
| (ListCmpF)_sview_sub_part_sort); |
| |
| /* Need to do this after the fact so we deal with |
| complete sub parts. |
| */ |
| |
| itr = list_iterator_create(sview_part_info->sub_list); |
| while ((sview_part_sub = list_next(itr))) { |
| sview_part_info->sub_part_total.node_cnt += |
| sview_part_sub->node_cnt; |
| sview_part_info->sub_part_total.cpu_cnt += |
| sview_part_sub->cpu_cnt; |
| |
| if (((sview_part_sub->node_state |
| & NODE_STATE_BASE) == NODE_STATE_MIXED) || |
| (sview_part_sub->node_state |
| == NODE_STATE_ALLOCATED)) |
| sview_part_info->sub_part_total.node_alloc_cnt |
| += sview_part_sub->node_cnt; |
| else if (sview_part_sub->node_state |
| != NODE_STATE_IDLE) |
| sview_part_info->sub_part_total.node_error_cnt |
| += sview_part_sub->node_cnt; |
| else |
| sview_part_info->sub_part_total.node_idle_cnt |
| += sview_part_sub->node_cnt; |
| |
| sview_part_info->sub_part_total.cpu_alloc_cnt += |
| sview_part_sub->cpu_alloc_cnt; |
| sview_part_info->sub_part_total.cpu_idle_cnt += |
| sview_part_sub->cpu_idle_cnt; |
| sview_part_info->sub_part_total.disk_total += |
| sview_part_sub->disk_total; |
| sview_part_info->sub_part_total.mem_total += |
| sview_part_sub->mem_total; |
| if (!sview_part_info->sub_part_total.features) { |
| /* store features and reasons |
| in the others group */ |
| sview_part_info->sub_part_total.features |
| = sview_part_sub->features; |
| sview_part_info->sub_part_total.features_act |
| = sview_part_sub->features_act; |
| sview_part_info->sub_part_total.reason |
| = sview_part_sub->reason; |
| } |
| hostlist_sort(sview_part_sub->hl); |
| } |
| list_iterator_destroy(itr); |
| } |
| list_sort(info_list, (ListCmpF)_sview_part_sort_aval_dec); |
| |
| if (last_list) { |
| list_iterator_destroy(last_list_itr); |
| FREE_NULL_LIST(last_list); |
| } |
| |
| return info_list; |
| } |
| |
| static void _display_info_part(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; |
| char *cluster_name = (char *)spec_info->search_info->cluster_name; |
| int found = 0; |
| partition_info_t *part_ptr = NULL; |
| GtkTreeView *treeview = NULL; |
| list_itr_t *itr = NULL; |
| sview_part_info_t *sview_part_info = NULL; |
| int update = 0; |
| int j = 0; |
| |
| if (!spec_info->search_info->gchar_data) { |
| //info = xstrdup("No pointer given!"); |
| 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_part_info = list_next(itr))) { |
| part_ptr = sview_part_info->part_ptr; |
| |
| if (cluster_name && |
| xstrcmp(part_ptr->cluster_name, cluster_name)) |
| continue; |
| |
| if (!xstrcmp(part_ptr->name, name)) { |
| j = 0; |
| while (part_ptr->node_inx[j] >= 0) { |
| change_grid_color( |
| popup_win->grid_button_list, |
| part_ptr->node_inx[j], |
| part_ptr->node_inx[j+1], |
| sview_part_info->color_inx, |
| true, 0); |
| j += 2; |
| } |
| _layout_part_record(treeview, sview_part_info, update); |
| found = 1; |
| break; |
| } |
| } |
| list_iterator_destroy(itr); |
| post_setup_popup_grid_list(popup_win); |
| |
| if (!found) { |
| if (!popup_win->not_found) { |
| char *temp = "PARTITION DOESN'T EXIST\n"; |
| GtkTreeIter iter; |
| GtkTreeModel *model = NULL; |
| |
| /* 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 _process_each_partition(GtkTreeModel *model, |
| GtkTreePath *path, |
| GtkTreeIter *iter, |
| gpointer userdata) |
| { |
| char *type = userdata; |
| if (_DEBUG) |
| g_print("process_each_partition: global_multi_error = %d\n", |
| global_multi_error); |
| |
| if (!global_multi_error) { |
| admin_part(model, iter, type); |
| } |
| } |
| /*process_each_partition ^^^*/ |
| |
| extern GtkWidget *create_part_entry(update_part_msg_t *part_msg, |
| GtkTreeModel *model, GtkTreeIter *iter) |
| { |
| GtkScrolledWindow *window = create_scrolled_window(); |
| GtkBin *bin = NULL; |
| GtkViewport *view = NULL; |
| GtkTable *table = NULL; |
| int i = 0, row = 0; |
| display_data_t *display_data = create_data_part; |
| |
| gtk_scrolled_window_set_policy(window, |
| GTK_POLICY_NEVER, |
| GTK_POLICY_AUTOMATIC); |
| bin = GTK_BIN(&window->container); |
| view = GTK_VIEWPORT(bin->child); |
| bin = GTK_BIN(&view->bin); |
| table = GTK_TABLE(bin->child); |
| gtk_table_resize(table, SORTID_CNT, 2); |
| |
| gtk_table_set_homogeneous(table, false); |
| |
| for(i = 0; i < SORTID_CNT; i++) { |
| while (display_data++) { |
| if (display_data->id == -1) |
| break; |
| if (!display_data->name) |
| continue; |
| if (display_data->id != i) |
| continue; |
| display_admin_edit( |
| table, part_msg, &row, model, iter, |
| display_data, |
| G_CALLBACK(_admin_edit_combo_box_part), |
| G_CALLBACK(_admin_focus_out_part), |
| _set_active_combo_part); |
| break; |
| } |
| display_data = create_data_part; |
| } |
| gtk_table_resize(table, row, 2); |
| |
| return GTK_WIDGET(window); |
| } |
| |
| extern bool check_part_includes_node(int node_dx) |
| { |
| partition_info_t *part_ptr = NULL; |
| bool rc = false; |
| int i; |
| static partition_info_msg_t *part_info_ptr = NULL; |
| |
| if (working_sview_config.show_hidden) |
| return true; |
| |
| if (!g_part_info_ptr) { |
| i = get_new_info_part(&part_info_ptr, true); |
| if (!g_part_info_ptr || (i && (i != SLURM_NO_CHANGE_IN_DATA))) { |
| if (_DEBUG) |
| g_print("%s : error %d ", __func__, i); |
| return false; |
| } |
| } |
| |
| for (i = 0; i < g_part_info_ptr->record_count; i++) { |
| /* don't include allow group or hidden excludes */ |
| part_ptr = &(g_part_info_ptr->partition_array[i]); |
| if (part_ptr->flags & PART_FLAG_HIDDEN) |
| continue; |
| if (part_ptr->node_inx[0] >= 0) { |
| if (_DEBUG) { |
| g_print("node_dx = %d ", node_dx); |
| g_print("part_node_inx[0] = %d ", |
| part_ptr->node_inx[0]); |
| g_print("part_node_inx[1] = %d \n", |
| part_ptr->node_inx[1]); |
| } |
| if (node_dx >= part_ptr->node_inx[0] && |
| node_dx <= part_ptr->node_inx[1]) { |
| rc = true; |
| if (_DEBUG) |
| g_print("hit!!\n"); |
| } |
| } |
| if (rc) |
| break; |
| } |
| return rc; |
| } |
| |
| |
| extern void refresh_part(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_part(popup_win); |
| } |
| |
| |
| extern int get_new_info_part(partition_info_msg_t **part_ptr, int force) |
| { |
| static partition_info_msg_t *new_part_ptr = NULL; |
| uint16_t show_flags = 0; |
| int error_code = SLURM_NO_CHANGE_IN_DATA; |
| time_t now = time(NULL); |
| static time_t last; |
| static bool changed = 0; |
| static uint16_t last_flags = 0; |
| |
| if (g_part_info_ptr && !force |
| && ((now - last) < working_sview_config.refresh_delay)) { |
| if (*part_ptr != g_part_info_ptr) |
| error_code = SLURM_SUCCESS; |
| *part_ptr = g_part_info_ptr; |
| if (changed) |
| error_code = SLURM_SUCCESS; |
| goto end_it; |
| } |
| last = now; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) |
| show_flags |= SHOW_FEDERATION; |
| if (working_sview_config.show_hidden) |
| /*ignore 'AllowGroups, Hidden settings*/ |
| show_flags |= SHOW_ALL; |
| |
| if (g_part_info_ptr) { |
| if (show_flags != last_flags) |
| g_part_info_ptr->last_update = 0; |
| error_code = slurm_load_partitions(g_part_info_ptr->last_update, |
| &new_part_ptr, show_flags); |
| if (error_code == SLURM_SUCCESS) { |
| slurm_free_partition_info_msg(g_part_info_ptr); |
| changed = 1; |
| } else if (errno == SLURM_NO_CHANGE_IN_DATA) { |
| error_code = SLURM_NO_CHANGE_IN_DATA; |
| new_part_ptr = g_part_info_ptr; |
| changed = 0; |
| } |
| } else { |
| new_part_ptr = NULL; |
| error_code = slurm_load_partitions((time_t) NULL, &new_part_ptr, |
| show_flags); |
| changed = 1; |
| } |
| |
| last_flags = show_flags; |
| g_part_info_ptr = new_part_ptr; |
| |
| if (g_part_info_ptr && (*part_ptr != g_part_info_ptr)) |
| error_code = SLURM_SUCCESS; |
| |
| *part_ptr = new_part_ptr; |
| end_it: |
| |
| return error_code; |
| } |
| |
| static GtkListStore *_create_model_part2(int type) |
| { |
| GtkListStore *model = NULL; |
| GtkTreeIter iter; |
| |
| last_model = NULL; /* Reformat display */ |
| switch (type) { |
| case SORTID_DEFAULT: |
| case SORTID_EXCLUSIVE_USER: |
| case SORTID_HIDDEN: |
| case SORTID_POWER_DOWN_ON_IDLE: |
| case SORTID_ROOT: |
| 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, "no (default)", 1, type, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "yes", 1, type, -1); |
| break; |
| case SORTID_OVER_SUBSCRIBE: |
| 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, "no (default)", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, 0, "yes", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, 0, "force", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, 0, "exclusive", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| break; |
| case SORTID_PART_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, "up (default)", 1, SORTID_PART_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "down", 1, SORTID_PART_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "inactive", 1, SORTID_PART_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "drain", 1, SORTID_PART_STATE, -1); |
| break; |
| case SORTID_PREEMPT_MODE: |
| 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, |
| preempt_mode_string(slurm_conf.preempt_mode), |
| 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "cancel", 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "off", 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "requeue", 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "suspend", 1, SORTID_PREEMPT_MODE, -1); |
| break; |
| } |
| |
| return model; |
| } |
| |
| extern GtkListStore *create_model_part(int type) |
| { |
| GtkListStore *model = NULL; |
| GtkTreeIter iter; |
| char *upper = NULL, *lower = NULL; |
| int i = 0; |
| |
| last_model = NULL; /* Reformat display */ |
| switch (type) { |
| case SORTID_DEFAULT: |
| case SORTID_EXCLUSIVE_USER: |
| case SORTID_HIDDEN: |
| case SORTID_ROOT: |
| case SORTID_POWER_DOWN_ON_IDLE: |
| 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, "yes", 1, type, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "no", 1, type, -1); |
| break; |
| case SORTID_PREEMPT_MODE: |
| 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, "cancel", 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "off", 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "requeue", 1, SORTID_PREEMPT_MODE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "suspend", 1, SORTID_PREEMPT_MODE, -1); |
| break; |
| case SORTID_GRACE_TIME: |
| case SORTID_JOB_DEFAULTS: |
| case SORTID_PRIORITY_JOB_FACTOR: |
| case SORTID_PRIORITY_TIER: |
| case SORTID_TIMELIMIT: |
| case SORTID_NODES_MIN: |
| case SORTID_NODES_MAX: |
| case SORTID_MAX_CPUS_PER_NODE: |
| case SORTID_MAX_CPUS_PER_SOCKET: |
| case SORTID_OVER_TIME_LIMIT: |
| break; |
| case SORTID_OVER_SUBSCRIBE: |
| 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, "force", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, 0, "no", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, 0, "yes", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, 0, "exclusive", |
| 1, SORTID_OVER_SUBSCRIBE, -1); |
| break; |
| case SORTID_ALLOW_ACCOUNTS: |
| break; |
| case SORTID_ALLOW_GROUPS: |
| break; |
| case SORTID_ALLOW_QOS: |
| break; |
| case SORTID_DENY_ACCOUNTS: |
| break; |
| case SORTID_DENY_QOS: |
| break; |
| case SORTID_NODELIST: |
| break; |
| case SORTID_PART_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, "up", 1, SORTID_PART_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "down", 1, SORTID_PART_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "inactive", 1, SORTID_PART_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "drain", 1, SORTID_PART_STATE, -1); |
| break; |
| case SORTID_NODE_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, SORTID_NODE_STATE, -1); |
| gtk_list_store_append(model, &iter); |
| gtk_list_store_set(model, &iter, |
| 0, "resume", 1, SORTID_NODE_STATE, -1); |
| for (i = 0; i < NODE_STATE_END; i++) { |
| upper = node_state_string(i); |
| if (!xstrcmp(upper, "UNKNOWN")) |
| continue; |
| |
| gtk_list_store_append(model, &iter); |
| lower = str_tolower(upper); |
| gtk_list_store_set(model, &iter, |
| 0, lower, 1, SORTID_NODE_STATE, -1); |
| xfree(lower); |
| } |
| |
| break; |
| } |
| |
| return model; |
| } |
| |
| extern void admin_edit_part(GtkCellRendererText *cell, |
| const char *path_string, |
| const char *new_text, |
| gpointer data) |
| { |
| GtkTreeStore *treestore = NULL; |
| GtkTreePath *path = NULL; |
| GtkTreeIter iter; |
| update_part_msg_t *part_msg = NULL; |
| |
| char *temp = NULL; |
| char *old_text = NULL; |
| const char *type = NULL; |
| int column; |
| |
| if (!new_text || !xstrcmp(new_text, "")) |
| goto no_input; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) { |
| display_fed_disabled_popup(type); |
| goto no_input; |
| } |
| |
| part_msg = xmalloc(sizeof(update_part_msg_t)); |
| |
| 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")); |
| if (column != SORTID_NODE_STATE) { |
| slurm_init_part_desc_msg(part_msg); |
| gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter, |
| SORTID_NAME, &temp, |
| column, &old_text, |
| -1); |
| part_msg->name = xstrdup(temp); |
| g_free(temp); |
| } |
| |
| type = _set_part_msg(part_msg, new_text, column); |
| if (global_edit_error) |
| goto print_error; |
| if (got_edit_signal) { |
| temp = got_edit_signal; |
| got_edit_signal = NULL; |
| admin_part(GTK_TREE_MODEL(treestore), &iter, temp); |
| xfree(temp); |
| goto no_input; |
| } |
| |
| if (got_features_edit_signal) { |
| admin_part(GTK_TREE_MODEL(treestore), &iter, (char *)type); |
| goto no_input; |
| } |
| |
| if ((column != SORTID_NODE_STATE) && (column != SORTID_FEATURES)) { |
| if (old_text && !xstrcmp(old_text, new_text)) { |
| temp = g_strdup_printf("No change in value."); |
| } else if (slurm_update_partition(part_msg) |
| == SLURM_SUCCESS) { |
| gtk_tree_store_set(treestore, &iter, column, |
| new_text, -1); |
| temp = g_strdup_printf("Partition %s %s changed to %s", |
| part_msg->name, |
| type, |
| new_text); |
| } else { |
| print_error: |
| temp = g_strdup_printf("Partition %s %s can't be " |
| "set to %s", |
| part_msg->name, |
| type, |
| new_text); |
| } |
| display_edit_note(temp); |
| g_free(temp); |
| } |
| no_input: |
| slurm_free_update_part_msg(part_msg); |
| gtk_tree_path_free(path); |
| g_free(old_text); |
| g_mutex_unlock(sview_mutex); |
| } |
| |
| extern void get_info_part(GtkTable *table, display_data_t *display_data) |
| { |
| int part_error_code = SLURM_SUCCESS; |
| int node_error_code = SLURM_SUCCESS; |
| static int view = -1; |
| static partition_info_msg_t *part_info_ptr = NULL; |
| 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 j, k; |
| sview_part_info_t *sview_part_info = NULL; |
| partition_info_t *part_ptr = NULL; |
| list_itr_t *itr = NULL; |
| GtkTreePath *path = NULL; |
| static bool set_opts = false; |
| |
| if (!set_opts) |
| set_page_opts(PART_PAGE, display_data_part, |
| SORTID_CNT, _initial_page_opts); |
| set_opts = true; |
| |
| /* reset */ |
| if (!table && !display_data) { |
| if (display_widget) |
| gtk_widget_destroy(display_widget); |
| display_widget = NULL; |
| part_info_ptr = NULL; |
| node_info_ptr = NULL; |
| goto reset_curs; |
| } |
| |
| if (display_data) |
| local_display_data = display_data; |
| if (!table) { |
| display_data_part->set_menu = local_display_data->set_menu; |
| goto reset_curs; |
| } |
| if (display_widget && toggled) { |
| gtk_widget_destroy(display_widget); |
| display_widget = NULL; |
| goto display_it; |
| } |
| |
| if ((part_error_code = get_new_info_part(&part_info_ptr, force_refresh)) |
| == SLURM_NO_CHANGE_IN_DATA) { |
| // just goto the new info node |
| } else if (part_error_code != SLURM_SUCCESS) { |
| if (view == ERROR_VIEW) |
| goto end_it; |
| if (display_widget) |
| gtk_widget_destroy(display_widget); |
| view = ERROR_VIEW; |
| snprintf(error_char, 100, "slurm_load_partitions: %s", |
| slurm_strerror(errno)); |
| label = gtk_label_new(error_char); |
| display_widget = g_object_ref(GTK_WIDGET(label)); |
| gtk_table_attach_defaults(table, label, 0, 1, 0, 1); |
| gtk_widget_show(label); |
| goto end_it; |
| } |
| |
| if ((node_error_code = get_new_info_node(&node_info_ptr, force_refresh)) |
| == SLURM_NO_CHANGE_IN_DATA) { |
| if ((!display_widget || view == ERROR_VIEW) |
| || (part_error_code != SLURM_NO_CHANGE_IN_DATA)) |
| goto display_it; |
| } else if (node_error_code != SLURM_SUCCESS) { |
| if (view == ERROR_VIEW) |
| goto end_it; |
| if (display_widget) |
| gtk_widget_destroy(display_widget); |
| view = ERROR_VIEW; |
| snprintf(error_char, 100, "slurm_load_node: %s", |
| slurm_strerror(errno)); |
| label = gtk_label_new(error_char); |
| display_widget = g_object_ref(GTK_WIDGET(label)); |
| gtk_table_attach_defaults(table, label, 0, 1, 0, 1); |
| gtk_widget_show(label); |
| goto end_it; |
| } |
| |
| display_it: |
| |
| info_list = _create_part_info_list(part_info_ptr, node_info_ptr); |
| if (!info_list) |
| goto reset_curs; |
| |
| /* 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_part_info = list_next(itr))) { |
| part_ptr = sview_part_info->part_ptr; |
| j = 0; |
| while (part_ptr->node_inx[j] >= 0) { |
| for (k = part_ptr->node_inx[j]; |
| k <= part_ptr->node_inx[j+1]; k++) { |
| color_set_flag[k] = true; |
| color_inx[k] = sview_part_info-> |
| color_inx; |
| } |
| j += 2; |
| } |
| } |
| list_iterator_destroy(itr); |
| change_grid_color_array(grid_button_list, array_size, |
| color_inx, color_set_flag, true, 0); |
| change_grid_color(grid_button_list, -1, -1, |
| MAKE_WHITE, true, 0); |
| xfree(color_inx); |
| xfree(color_set_flag); |
| } else { |
| highlight_grid(GTK_TREE_VIEW(display_widget), |
| SORTID_NODE_INX, SORTID_COLOR_INX, |
| 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) { |
| int def_sort_col = SORTID_NAME; |
| 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(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 */ |
| if (cluster_flags & CLUSTER_FLAG_FED) |
| def_sort_col = SORTID_CLUSTER_NAME; |
| create_treestore(tree_view, display_data_part, SORTID_CNT, |
| def_sort_col, SORTID_COLOR); |
| |
| set_column_width_fixed(tree_view, SORTID_NODELIST, 100); |
| } |
| |
| view = INFO_VIEW; |
| _update_info_part(info_list, GTK_TREE_VIEW(display_widget)); |
| end_it: |
| toggled = false; |
| force_refresh = false; |
| reset_curs: |
| if (main_window && main_window->window) |
| gdk_window_set_cursor(main_window->window, NULL); |
| return; |
| } |
| |
| extern void specific_info_part(popup_info_t *popup_win) |
| { |
| int part_error_code = SLURM_SUCCESS; |
| int node_error_code = SLURM_SUCCESS; |
| static partition_info_msg_t *part_info_ptr = NULL; |
| 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; |
| int j=0; |
| sview_part_info_t *sview_part_info_ptr = NULL; |
| partition_info_t *part_ptr = NULL; |
| list_itr_t *itr = NULL; |
| hostset_t *hostset = NULL; |
| |
| if (!spec_info->display_widget) |
| setup_popup_info(popup_win, display_data_part, SORTID_CNT); |
| |
| if (spec_info->display_widget && popup_win->toggled) { |
| gtk_widget_destroy(spec_info->display_widget); |
| spec_info->display_widget = NULL; |
| goto display_it; |
| } |
| |
| if ((part_error_code = get_new_info_part(&part_info_ptr, |
| popup_win->force_refresh)) |
| == SLURM_NO_CHANGE_IN_DATA) { |
| |
| } else if (part_error_code != SLURM_SUCCESS) { |
| if (spec_info->view == ERROR_VIEW) |
| goto end_it; |
| if (spec_info->display_widget) { |
| gtk_widget_destroy(spec_info->display_widget); |
| spec_info->display_widget = NULL; |
| } |
| spec_info->view = ERROR_VIEW; |
| snprintf(error_char, 100, "slurm_load_partitions: %s", |
| slurm_strerror(errno)); |
| label = gtk_label_new(error_char); |
| spec_info->display_widget = g_object_ref(GTK_WIDGET(label)); |
| gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1); |
| gtk_widget_show(label); |
| goto end_it; |
| } |
| |
| if ((node_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) |
| || (part_error_code != SLURM_NO_CHANGE_IN_DATA)) |
| goto display_it; |
| } else if (node_error_code != SLURM_SUCCESS) { |
| if (spec_info->view == ERROR_VIEW) |
| goto end_it; |
| if (spec_info->display_widget) |
| gtk_widget_destroy(spec_info->display_widget); |
| spec_info->view = ERROR_VIEW; |
| snprintf(error_char, 100, "slurm_load_node: %s", |
| slurm_strerror(errno)); |
| label = gtk_label_new(error_char); |
| spec_info->display_widget = g_object_ref(GTK_WIDGET(label)); |
| gtk_table_attach_defaults(popup_win->table, label, 0, 1, 0, 1); |
| gtk_widget_show(label); |
| goto end_it; |
| } |
| |
| display_it: |
| |
| info_list = _create_part_info_list(part_info_ptr, node_info_ptr); |
| |
| 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 */ |
| create_treestore(tree_view, popup_win->display_data, |
| SORTID_CNT, SORTID_NAME, SORTID_COLOR); |
| } |
| |
| setup_popup_grid_list(popup_win); |
| |
| spec_info->view = INFO_VIEW; |
| if (spec_info->type == INFO_PAGE) { |
| _display_info_part(info_list, popup_win); |
| goto end_it; |
| } |
| |
| /* just linking to another list, don't free the inside, just |
| the list */ |
| send_info_list = list_create(NULL); |
| |
| itr = list_iterator_create(info_list); |
| while ((sview_part_info_ptr = list_next(itr))) { |
| part_ptr = sview_part_info_ptr->part_ptr; |
| switch (spec_info->type) { |
| case RESV_PAGE: |
| case NODE_PAGE: |
| if (!part_ptr->nodes) |
| continue; |
| |
| if (!(hostset = hostset_create( |
| spec_info->search_info->gchar_data))) |
| continue; |
| if (!hostset_intersects(hostset, part_ptr->nodes)) { |
| hostset_destroy(hostset); |
| continue; |
| } |
| hostset_destroy(hostset); |
| break; |
| case PART_PAGE: |
| switch(spec_info->search_info->search_type) { |
| case SEARCH_PARTITION_NAME: |
| if (!spec_info->search_info->gchar_data) |
| continue; |
| |
| if (xstrcmp(part_ptr->name, |
| spec_info->search_info->gchar_data)) |
| continue; |
| |
| if (spec_info->search_info->cluster_name && |
| xstrcmp( |
| part_ptr->cluster_name, |
| spec_info->search_info->cluster_name)) |
| continue; |
| break; |
| case SEARCH_PARTITION_STATE: |
| if (spec_info->search_info->int_data == NO_VAL) |
| continue; |
| if (part_ptr->state_up != |
| spec_info->search_info->int_data) |
| continue; |
| break; |
| default: |
| continue; |
| break; |
| } |
| break; |
| case JOB_PAGE: |
| if (!spec_info->search_info->gchar_data) |
| continue; |
| |
| if (xstrcmp(part_ptr->name, |
| spec_info->search_info->gchar_data)) |
| continue; |
| |
| if (spec_info->search_info->cluster_name && |
| xstrcmp(part_ptr->cluster_name, |
| spec_info->search_info->cluster_name)) |
| continue; |
| break; |
| default: |
| g_print("Unknown type %d\n", spec_info->type); |
| list_iterator_destroy(itr); |
| goto end_it; |
| } |
| list_push(send_info_list, sview_part_info_ptr); |
| j=0; |
| while (part_ptr->node_inx[j] >= 0) { |
| change_grid_color( |
| popup_win->grid_button_list, |
| part_ptr->node_inx[j], |
| part_ptr->node_inx[j+1], |
| sview_part_info_ptr->color_inx, true, 0); |
| j += 2; |
| } |
| } |
| list_iterator_destroy(itr); |
| post_setup_popup_grid_list(popup_win); |
| |
| _update_info_part(send_info_list, |
| GTK_TREE_VIEW(spec_info->display_widget)); |
| end_it: |
| FREE_NULL_LIST(send_info_list); |
| popup_win->toggled = 0; |
| popup_win->force_refresh = 0; |
| |
| return; |
| } |
| |
| extern void set_menus_part(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_part, SORTID_CNT); |
| break; |
| case ROW_CLICKED: |
| make_options_menu(tree_view, path, menu, options_data_part); |
| break; |
| case ROW_LEFT_CLICKED: |
| highlight_grid(tree_view, SORTID_NODE_INX, |
| SORTID_COLOR_INX, 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_part(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_part(GtkTreeModel *model, GtkTreeIter *iter, int id) |
| { |
| char *name = NULL; |
| char *cluster_name = NULL; |
| char *state = NULL; |
| char title[100] = {0}; |
| int only_line = 0; |
| list_itr_t *itr = NULL; |
| popup_info_t *popup_win = NULL; |
| GError *error = NULL; |
| GtkTreeIter par_iter; |
| |
| gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1); |
| gtk_tree_model_get(model, iter, SORTID_CLUSTER_NAME, &cluster_name, -1); |
| |
| switch(id) { |
| case JOB_PAGE: |
| snprintf(title, 100, "Job(s) in partition %s", name); |
| break; |
| case RESV_PAGE: |
| snprintf(title, 100, "Reservation(s) in partition %s", name); |
| break; |
| case NODE_PAGE: |
| gtk_tree_model_get(model, iter, SORTID_ONLY_LINE, |
| &only_line, -1); |
| if (!only_line) |
| gtk_tree_model_get(model, iter, |
| SORTID_NODE_STATE, &state, -1); |
| if (!state || !strlen(state)) |
| snprintf(title, 100, "Node(s) in partition %s ", |
| name); |
| else |
| snprintf(title, 100, |
| "Node(s) in partition %s that are in " |
| "'%s' state", |
| name, state); |
| break; |
| case SUBMIT_PAGE: |
| snprintf(title, 100, "Submit job in partition %s", name); |
| break; |
| case INFO_PAGE: |
| snprintf(title, 100, "Full info for partition %s", name); |
| break; |
| default: |
| g_print("part 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, PART_PAGE, title); |
| else |
| popup_win = create_popup_info(PART_PAGE, id, title); |
| } else { |
| g_free(name); |
| g_free(cluster_name); |
| g_free(state); |
| gtk_window_present(GTK_WINDOW(popup_win->popup)); |
| return; |
| } |
| |
| /* Pass the model and the structs from the iter so we can always get |
| the current node_inx. |
| */ |
| popup_win->model = model; |
| popup_win->iter = *iter; |
| popup_win->node_inx_id = SORTID_NODE_INX; |
| |
| if (cluster_flags & CLUSTER_FLAG_FED) { |
| popup_win->spec_info->search_info->cluster_name = cluster_name; |
| cluster_name = NULL; |
| } |
| g_free(cluster_name); |
| |
| switch (id) { |
| case JOB_PAGE: |
| case INFO_PAGE: |
| popup_win->spec_info->search_info->gchar_data = name; |
| //specific_info_job(popup_win); |
| break; |
| case RESV_PAGE: |
| case NODE_PAGE: |
| g_free(name); |
| /* we want to include the parent's nodes here not just |
| the subset */ |
| if (gtk_tree_model_iter_parent(model, &par_iter, iter)) |
| gtk_tree_model_get(model, &par_iter, |
| SORTID_NODELIST, &name, -1); |
| else |
| gtk_tree_model_get(model, iter, |
| SORTID_NODELIST, &name, -1); |
| popup_win->spec_info->search_info->gchar_data = name; |
| if (state && strlen(state)) { |
| popup_win->spec_info->search_info->search_type = |
| SEARCH_NODE_STATE; |
| gtk_tree_model_get( |
| model, iter, SORTID_NODE_STATE_NUM, |
| &popup_win->spec_info->search_info->int_data, |
| -1); |
| } else { |
| popup_win->spec_info->search_info->search_type = |
| SEARCH_NODE_NAME; |
| } |
| g_free(state); |
| |
| //specific_info_node(popup_win); |
| break; |
| case SUBMIT_PAGE: |
| break; |
| default: |
| g_print("part got unknown type %d\n", id); |
| } |
| if (!sview_thread_new((gpointer)popup_thr, popup_win, &error)) { |
| g_printerr ("Failed to create part popup thread: %s\n", |
| error->message); |
| return; |
| } |
| } |
| |
| extern void select_admin_partitions(GtkTreeModel *model, |
| GtkTreeIter *iter, |
| display_data_t *display_data, |
| GtkTreeView *treeview) |
| { |
| select_admin_common(model, iter, display_data, treeview, |
| SORTID_NODELIST, _process_each_partition); |
| } /*select_admin_partitions ^^^*/ |
| |
| |
| extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type) |
| { |
| char *nodelist = NULL; |
| char *partid = NULL; |
| update_part_msg_t *part_msg = NULL; |
| int edit_type = 0; |
| int response = 0; |
| char tmp_char[100]; |
| char *temp = NULL; |
| GtkWidget *label = NULL; |
| GtkWidget *entry = NULL; |
| 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_transient_for(GTK_WINDOW(popup), NULL); |
| |
| gtk_window_set_type_hint(GTK_WINDOW(popup), |
| GDK_WINDOW_TYPE_HINT_NORMAL); |
| |
| gtk_tree_model_get(model, iter, SORTID_NAME, &partid, -1); |
| gtk_tree_model_get(model, iter, SORTID_NODELIST, &nodelist, -1); |
| |
| part_msg = xmalloc(sizeof(update_part_msg_t)); |
| slurm_init_part_desc_msg(part_msg); |
| part_msg->name = xstrdup(partid); |
| |
| if (!xstrcasecmp("Change Partition State", type)) { |
| GtkCellRenderer *renderer = NULL; |
| GtkTreeModel *model2 = GTK_TREE_MODEL( |
| create_model_part(SORTID_PART_STATE)); |
| if (!model2) { |
| g_print("In change part, no model set up for %d(%s)\n", |
| SORTID_PART_STATE, partid); |
| xfree(part_msg); |
| return; |
| } |
| entry = gtk_combo_box_new_with_model(model2); |
| g_object_unref(model2); |
| |
| _set_active_combo_part(GTK_COMBO_BOX(entry), |
| model, iter, SORTID_PART_STATE); |
| |
| g_signal_connect(entry, "changed", |
| G_CALLBACK(_admin_edit_combo_box_part), |
| part_msg); |
| |
| renderer = gtk_cell_renderer_text_new(); |
| gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(entry), |
| renderer, true); |
| gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(entry), |
| renderer, "text", 0); |
| |
| label = gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_YES, GTK_RESPONSE_OK); |
| gtk_window_set_default(GTK_WINDOW(popup), label); |
| gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Which state would you like to set partition '%s' to?", |
| partid); |
| label = gtk_label_new(tmp_char); |
| edit_type = EDIT_PART_STATE; |
| } else if (!xstrcasecmp("Remove Partition", type)) { |
| label = gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_YES, GTK_RESPONSE_OK); |
| gtk_window_set_default(GTK_WINDOW(popup), label); |
| gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Are you sure you want to remove partition %s?", |
| partid); |
| label = gtk_label_new(tmp_char); |
| edit_type = EDIT_REMOVE_PART; |
| } else if (!xstrcasecmp("Edit Partition", type)) { |
| label = gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_OK, GTK_RESPONSE_OK); |
| gtk_window_set_default(GTK_WINDOW(popup), label); |
| gtk_dialog_add_button(GTK_DIALOG(popup), |
| GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); |
| |
| gtk_window_set_default_size(GTK_WINDOW(popup), 200, 400); |
| snprintf(tmp_char, sizeof(tmp_char), |
| "Editing partition %s think before you type", |
| partid); |
| label = gtk_label_new(tmp_char); |
| edit_type = EDIT_EDIT; |
| entry = _admin_full_edit_part(part_msg, model, iter); |
| } else if (!xstrncasecmp("Update", type, 6)) { |
| char *old_features = NULL; |
| if (got_features_edit_signal) |
| old_features = got_features_edit_signal; |
| else |
| gtk_tree_model_get(model, iter, SORTID_FEATURES, |
| &old_features, -1); |
| update_avail_features_node(GTK_DIALOG(popup), |
| nodelist, old_features); |
| if (got_features_edit_signal) { |
| got_features_edit_signal = NULL; |
| xfree(old_features); |
| } else |
| g_free(old_features); |
| goto end_it; |
| } else { |
| /* something that has to deal with a node state change */ |
| update_state_node(GTK_DIALOG(popup), nodelist, type); |
| goto end_it; |
| } |
| |
| gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), |
| label, false, false, 0); |
| if (entry) |
| gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox), |
| entry, true, true, 0); |
| gtk_widget_show_all(popup); |
| response = gtk_dialog_run (GTK_DIALOG(popup)); |
| |
| if (response == GTK_RESPONSE_OK) { |
| int rc; |
| if (global_edit_error) |
| temp = global_edit_error_msg; |
| else if (edit_type == EDIT_REMOVE_PART) { |
| delete_part_msg_t part_del_msg; |
| part_del_msg.name = partid; |
| rc = slurm_delete_partition(&part_del_msg); |
| if (rc == SLURM_SUCCESS) { |
| temp = g_strdup_printf( |
| "Partition %s removed successfully", |
| partid); |
| } else { |
| temp = g_strdup_printf( |
| "Problem removing partition %s: %s", |
| partid, slurm_strerror(rc)); |
| global_multi_error = true; |
| } |
| } else if (!global_send_update_msg) { |
| temp = g_strdup_printf("No change detected."); |
| } else if ((rc = slurm_update_partition(part_msg)) |
| == SLURM_SUCCESS) { |
| temp = g_strdup_printf( |
| "Partition %s updated successfully", |
| partid); |
| } else { |
| temp = g_strdup_printf( |
| "Problem updating partition %s: %s", |
| partid, slurm_strerror(rc)); |
| global_multi_error = true; |
| } |
| display_edit_note(temp); |
| g_free(temp); |
| } |
| end_it: |
| |
| g_free(partid); |
| g_free(nodelist); |
| global_entry_changed = 0; |
| slurm_free_update_part_msg(part_msg); |
| gtk_widget_destroy(popup); |
| if (got_edit_signal) { |
| type = got_edit_signal; |
| got_edit_signal = NULL; |
| admin_part(model, iter, type); |
| xfree(type); |
| } |
| if (got_features_edit_signal) { |
| type = "Update Features"; |
| admin_part(model, iter, type); |
| } |
| return; |
| } |
| |
| extern void cluster_change_part(void) |
| { |
| display_data_t *display_data = display_data_part; |
| 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_part(NULL, NULL); |
| } |