1 /*****************************************************************************\
2 * node_info.c - Functions related to node display mode of sview.
3 *****************************************************************************
4 * Copyright (C) 2004-2007 The Regents of the University of California.
5 * Copyright (C) 2008-2010 Lawrence Livermore National Security.
6 * Portions Copyright (C) 2010-2015 SchedMD LLC.
7 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8 * Written by Danny Auble <da@llnl.gov>
9 *
10 * CODE-OCEC-09-009. All rights reserved.
11 *
12 * This file is part of Slurm, a resource management program.
13 * For details, see <https://slurm.schedmd.com/>.
14 * Please also read the included file: DISCLAIMER.
15 *
16 * Slurm is free software; you can redistribute it and/or modify it under
17 * the terms of the GNU General Public License as published by the Free
18 * Software Foundation; either version 2 of the License, or (at your option)
19 * any later version.
20 *
21 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
22 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
24 * details.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with Slurm; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 \*****************************************************************************/
30
31 #include "src/sview/sview.h"
32
33 #define _DEBUG 0
34 #define ECLIPSE_RT 0
35
36 //static int _l_topo_color_ndx = MAKE_TOPO_1;
37 //static int _l_sw_color_ndx = 0;
38
39 /* These need to be in alpha order (except POS and CNT) */
40 enum {
41 SORTID_POS = POS_LOC,
42 SORTID_ACTIVE_FEATURES,
43 SORTID_ARCH,
44 SORTID_AVAIL_FEATURES,
45 SORTID_AVE_WATTS,
46 SORTID_BOARDS,
47 SORTID_BOOT_TIME,
48 SORTID_CAP_WATTS,
49 SORTID_CLUSTER_NAME,
50 SORTID_COLOR,
51 SORTID_CPUS,
52 SORTID_CPU_LOAD,
53 SORTID_CORES,
54 SORTID_CURRENT_WATTS,
55 SORTID_ERR_CPUS,
56 SORTID_FREE_MEM,
57 SORTID_GRES,
58 SORTID_IDLE_CPUS,
59 SORTID_MCS_LABEL,
60 SORTID_NAME,
61 SORTID_NODE_ADDR,
62 SORTID_NODE_HOSTNAME,
63 SORTID_OWNER,
64 SORTID_PORT,
65 SORTID_REAL_MEMORY,
66 SORTID_REASON,
67 SORTID_SLURMD_START_TIME,
68 SORTID_SOCKETS,
69 SORTID_STATE,
70 SORTID_STATE_NUM,
71 SORTID_THREADS,
72 SORTID_TMP_DISK,
73 SORTID_TRES_ALLOC,
74 SORTID_TRES_CONFIG,
75 SORTID_UPDATED,
76 SORTID_USED_CPUS,
77 SORTID_USED_MEMORY,
78 SORTID_VERSION,
79 SORTID_WEIGHT,
80 SORTID_CNT
81 };
82
83 typedef struct {
84 int node_col;
85 char *nodelist;
86 } process_node_t;
87
88 /*these are the settings to apply for the user
89 * on the first startup after a fresh slurm install.*/
90 static char *_initial_page_opts = "Name,RackMidplane,State,CPU_Count,"
91 "Used_CPU_Count,Error_CPU_Count,CoresPerSocket,Sockets,ThreadsPerCore,"
92 "Real_Memory,Tmp_Disk";
93
94 static display_data_t display_data_node[] = {
95 {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE, refresh_node,
96 create_model_node, admin_edit_node},
97 {G_TYPE_STRING, SORTID_CLUSTER_NAME, "ClusterName", false, EDIT_NONE,
98 refresh_node, create_model_node, admin_edit_node},
99 {G_TYPE_STRING, SORTID_NAME, "Name", false, EDIT_NONE, refresh_node,
100 create_model_node, admin_edit_node},
101 {G_TYPE_STRING, SORTID_COLOR, NULL, true, EDIT_COLOR, refresh_node,
102 create_model_node, admin_edit_node},
103 {G_TYPE_STRING, SORTID_NODE_ADDR, "NodeAddr", false, EDIT_NONE,
104 refresh_node, create_model_node, admin_edit_node},
105 {G_TYPE_STRING, SORTID_NODE_HOSTNAME, "NodeHostName", false, EDIT_NONE,
106 refresh_node, create_model_node, admin_edit_node},
107 {G_TYPE_STRING, SORTID_OWNER, "Owner", false, EDIT_NONE,
108 refresh_node, create_model_node, admin_edit_node},
109 {G_TYPE_STRING, SORTID_MCS_LABEL, "MCS_Label", false, EDIT_NONE,
110 refresh_node, create_model_node, admin_edit_node},
111 {G_TYPE_STRING, SORTID_STATE, "State", false, EDIT_MODEL, refresh_node,
112 create_model_node, admin_edit_node},
113 {G_TYPE_INT, SORTID_STATE_NUM, NULL, false, EDIT_NONE, refresh_node,
114 create_model_node, admin_edit_node},
115 {G_TYPE_STRING, SORTID_CPUS, "CPU Count", false,
116 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
117 {G_TYPE_STRING, SORTID_USED_CPUS, "Used CPU Count", false,
118 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
119 {G_TYPE_STRING, SORTID_ERR_CPUS, "Error CPU Count", false,
120 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
121 {G_TYPE_STRING, SORTID_IDLE_CPUS, "Idle CPU Count", false,
122 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
123 {G_TYPE_STRING, SORTID_TRES_CONFIG, "Config TRES", false,
124 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
125 {G_TYPE_STRING, SORTID_TRES_ALLOC, "Alloc TRES", false,
126 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
127 {G_TYPE_INT, SORTID_BOARDS, "Boards", false,
128 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
129 {G_TYPE_INT, SORTID_SOCKETS, "Sockets", false,
130 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
131 {G_TYPE_INT, SORTID_CORES, "CoresPerSocket", false,
132 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
133 {G_TYPE_INT, SORTID_THREADS, "ThreadsPerCore", false,
134 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
135 {G_TYPE_STRING, SORTID_REAL_MEMORY, "Real Memory", false,
136 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
137 {G_TYPE_STRING, SORTID_USED_MEMORY, "Used Memory", false,
138 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
139 {G_TYPE_STRING, SORTID_FREE_MEM, "Free Memory", false, EDIT_NONE,
140 refresh_node, create_model_node, admin_edit_node},
141 {G_TYPE_STRING, SORTID_PORT, "Port", false, EDIT_NONE,
142 refresh_node, create_model_node, admin_edit_node},
143 {G_TYPE_STRING, SORTID_TMP_DISK, "Tmp Disk", false, EDIT_NONE,
144 refresh_node, create_model_node, admin_edit_node},
145 {G_TYPE_STRING, SORTID_ACTIVE_FEATURES, "Active Features", false,
146 EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node},
147 {G_TYPE_STRING, SORTID_ARCH, "Arch", false,
148 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
149 {G_TYPE_STRING, SORTID_AVAIL_FEATURES, "Available Features", false,
150 EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node},
151 {G_TYPE_STRING, SORTID_BOOT_TIME, "BootTime", false,
152 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
153 {G_TYPE_STRING, SORTID_CPU_LOAD, "CPU Load", false, EDIT_NONE,
154 refresh_node, create_model_node, admin_edit_node},
155 {G_TYPE_STRING, SORTID_GRES, "Gres", false,
156 EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node},
157 {G_TYPE_STRING, SORTID_REASON, "Reason", false,
158 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
159 {G_TYPE_STRING, SORTID_SLURMD_START_TIME, "SlurmdStartTime", false,
160 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
161 {G_TYPE_STRING, SORTID_CURRENT_WATTS, "Current Watts", false,
162 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
163 {G_TYPE_STRING, SORTID_AVE_WATTS, "Average Watts", false,
164 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
165 {G_TYPE_STRING, SORTID_CAP_WATTS,"Cap Watts", false,
166 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
167 {G_TYPE_STRING, SORTID_VERSION, "Version", false,
168 EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
169 {G_TYPE_INT, SORTID_WEIGHT,"Weight", false, EDIT_NONE, refresh_node,
170 create_model_node, admin_edit_node},
171 {G_TYPE_INT, SORTID_UPDATED, NULL, false, EDIT_NONE, refresh_node,
172 create_model_node, admin_edit_node},
173 {G_TYPE_NONE, -1, NULL, false, EDIT_NONE}
174 };
175
176 static display_data_t options_data_node[] = {
177 {G_TYPE_INT, SORTID_POS, NULL, false, EDIT_NONE},
178 {G_TYPE_STRING, INFO_PAGE, "Full Info", true, NODE_PAGE},
179 {G_TYPE_STRING, NODE_PAGE, "Drain Node", true, ADMIN_PAGE},
180 {G_TYPE_STRING, NODE_PAGE, "Undrain Node", true, ADMIN_PAGE},
181 {G_TYPE_STRING, NODE_PAGE, "Resume Node", true, ADMIN_PAGE},
182 {G_TYPE_STRING, NODE_PAGE, "Set Node(s) Down", true, ADMIN_PAGE},
183 {G_TYPE_STRING, NODE_PAGE, "Make Node(s) Idle", true, ADMIN_PAGE},
184 {G_TYPE_STRING, NODE_PAGE, "Update Active Features", true, ADMIN_PAGE},
185 {G_TYPE_STRING, NODE_PAGE, "Update Available Features", true, ADMIN_PAGE},
186 {G_TYPE_STRING, NODE_PAGE, "Update Gres", true, ADMIN_PAGE},
187 {G_TYPE_STRING, JOB_PAGE, "Jobs", true, NODE_PAGE},
188 {G_TYPE_STRING, PART_PAGE, "Partitions", true, NODE_PAGE},
189 {G_TYPE_STRING, RESV_PAGE, "Reservations", true, NODE_PAGE},
190 //{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", false, NODE_PAGE},
191 {G_TYPE_NONE, -1, NULL, false, EDIT_NONE}
192 };
193
194 static display_data_t *local_display_data = NULL;
195 static GtkTreeModel *last_model = NULL;
196
_layout_node_record(GtkTreeView * treeview,sview_node_info_t * sview_node_info_ptr,int update)197 static void _layout_node_record(GtkTreeView *treeview,
198 sview_node_info_t *sview_node_info_ptr,
199 int update)
200 {
201 char tmp_cnt[50];
202 char tmp_current_watts[50];
203 char tmp_ave_watts[50];
204 char tmp_cap_watts[50], tmp_owner[32];
205 char tmp_version[50];
206 char *upper = NULL, *lower = NULL;
207 GtkTreeIter iter;
208 uint16_t alloc_cpus = 0;
209 uint64_t alloc_memory = 0;
210 node_info_t *node_ptr = sview_node_info_ptr->node_ptr;
211 int idle_cpus = node_ptr->cpus;
212 char *node_alloc_tres = NULL;
213 GtkTreeStore *treestore =
214 GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
215 if (!treestore)
216 return;
217
218 add_display_treestore_line(update, treestore, &iter,
219 find_col_name(display_data_node,
220 SORTID_CLUSTER_NAME),
221 node_ptr->cluster_name);
222
223 add_display_treestore_line(update, treestore, &iter,
224 find_col_name(display_data_node,
225 SORTID_NAME),
226 node_ptr->name);
227
228 add_display_treestore_line(update, treestore, &iter,
229 find_col_name(display_data_node,
230 SORTID_NODE_ADDR),
231 node_ptr->node_addr);
232
233 add_display_treestore_line(update, treestore, &iter,
234 find_col_name(display_data_node,
235 SORTID_NODE_HOSTNAME),
236 node_ptr->node_hostname);
237
238 if (node_ptr->owner == NO_VAL) {
239 snprintf(tmp_owner, sizeof(tmp_owner), "N/A");
240 } else {
241 char *user_name;
242 user_name = uid_to_string((uid_t) node_ptr->owner);
243 snprintf(tmp_owner, sizeof(tmp_owner), "%s(%u)",
244 user_name, node_ptr->owner);
245 xfree(user_name);
246 }
247 add_display_treestore_line(update, treestore, &iter,
248 find_col_name(display_data_node,
249 SORTID_OWNER), tmp_owner);
250
251 add_display_treestore_line(update, treestore, &iter,
252 find_col_name(display_data_node,
253 SORTID_MCS_LABEL),
254 (node_ptr->mcs_label == NULL) ? "N/A" :
255 node_ptr->mcs_label),
256
257 convert_num_unit((float)node_ptr->cpus, tmp_cnt, sizeof(tmp_cnt),
258 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
259 add_display_treestore_line(update, treestore, &iter,
260 find_col_name(display_data_node,
261 SORTID_CPUS),
262 tmp_cnt);
263
264 if (node_ptr->cpu_load == NO_VAL) {
265 snprintf(tmp_cnt, sizeof(tmp_cnt), "N/A");
266 } else {
267 snprintf(tmp_cnt, sizeof(tmp_cnt), "%.2f",
268 (node_ptr->cpu_load / 100.0));
269 }
270 add_display_treestore_line(update, treestore, &iter,
271 find_col_name(display_data_node,
272 SORTID_CPU_LOAD),
273 tmp_cnt);
274
275 if (node_ptr->free_mem == NO_VAL64) {
276 snprintf(tmp_cnt, sizeof(tmp_cnt), "N/A");
277 } else {
278 snprintf(tmp_cnt, sizeof(tmp_cnt), "%"PRIu64"M",
279 node_ptr->free_mem);
280 }
281 add_display_treestore_line(update, treestore, &iter,
282 find_col_name(display_data_node,
283 SORTID_FREE_MEM),
284 tmp_cnt);
285
286 select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
287 SELECT_NODEDATA_SUBCNT,
288 NODE_STATE_ALLOCATED,
289 &alloc_cpus);
290 idle_cpus -= alloc_cpus;
291 convert_num_unit((float)alloc_cpus, tmp_cnt,
292 sizeof(tmp_cnt), UNIT_NONE, NO_VAL,
293 working_sview_config.convert_flags);
294 add_display_treestore_line(update, treestore, &iter,
295 find_col_name(display_data_node,
296 SORTID_USED_CPUS),
297 tmp_cnt);
298
299 convert_num_unit((float)idle_cpus, tmp_cnt, sizeof(tmp_cnt), UNIT_NONE,
300 NO_VAL, working_sview_config.convert_flags);
301 add_display_treestore_line(update, treestore, &iter,
302 find_col_name(display_data_node,
303 SORTID_IDLE_CPUS),
304 tmp_cnt);
305
306 add_display_treestore_line(update, treestore, &iter,
307 find_col_name(display_data_node,
308 SORTID_TRES_CONFIG),
309 node_ptr->tres_fmt_str);
310
311 select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
312 SELECT_NODEDATA_TRES_ALLOC_FMT_STR,
313 NODE_STATE_ALLOCATED, &node_alloc_tres);
314
315 add_display_treestore_line(update, treestore, &iter,
316 find_col_name(display_data_node,
317 SORTID_TRES_ALLOC),
318 node_alloc_tres ? node_alloc_tres : "");
319 xfree(node_alloc_tres);
320
321 upper = node_state_string(node_ptr->node_state);
322 lower = str_tolower(upper);
323
324 add_display_treestore_line(update, treestore, &iter,
325 find_col_name(display_data_node,
326 SORTID_STATE),
327 lower);
328 xfree(lower);
329
330 convert_num_unit((float)node_ptr->boards, tmp_cnt, sizeof(tmp_cnt),
331 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
332 add_display_treestore_line(update, treestore, &iter,
333 find_col_name(display_data_node,
334 SORTID_BOARDS),
335 tmp_cnt);
336
337 convert_num_unit((float)node_ptr->sockets, tmp_cnt, sizeof(tmp_cnt),
338 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
339 add_display_treestore_line(update, treestore, &iter,
340 find_col_name(display_data_node,
341 SORTID_SOCKETS),
342 tmp_cnt);
343
344 convert_num_unit((float)node_ptr->cores, tmp_cnt, sizeof(tmp_cnt),
345 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
346 add_display_treestore_line(update, treestore, &iter,
347 find_col_name(display_data_node,
348 SORTID_CORES),
349 tmp_cnt);
350
351 convert_num_unit((float)node_ptr->port, tmp_cnt, sizeof(tmp_cnt),
352 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
353 add_display_treestore_line(update, treestore, &iter,
354 find_col_name(display_data_node,
355 SORTID_PORT),
356 tmp_cnt);
357
358 convert_num_unit((float)node_ptr->threads, tmp_cnt, sizeof(tmp_cnt),
359 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
360 add_display_treestore_line(update, treestore, &iter,
361 find_col_name(display_data_node,
362 SORTID_THREADS),
363 tmp_cnt);
364
365 convert_num_unit((float)node_ptr->real_memory, tmp_cnt, sizeof(tmp_cnt),
366 UNIT_MEGA, NO_VAL, working_sview_config.convert_flags);
367 add_display_treestore_line(update, treestore, &iter,
368 find_col_name(display_data_node,
369 SORTID_REAL_MEMORY),
370 tmp_cnt);
371
372 select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
373 SELECT_NODEDATA_MEM_ALLOC,
374 NODE_STATE_ALLOCATED,
375 &alloc_memory);
376 snprintf(tmp_cnt, sizeof(tmp_cnt), "%"PRIu64"M", alloc_memory);
377 add_display_treestore_line(update, treestore, &iter,
378 find_col_name(display_data_node,
379 SORTID_USED_MEMORY),
380 tmp_cnt);
381
382 convert_num_unit((float)node_ptr->tmp_disk, tmp_cnt, sizeof(tmp_cnt),
383 UNIT_MEGA, NO_VAL, working_sview_config.convert_flags);
384 add_display_treestore_line(update, treestore, &iter,
385 find_col_name(display_data_node,
386 SORTID_TMP_DISK),
387 tmp_cnt);
388 snprintf(tmp_cnt, sizeof(tmp_cnt), "%u", node_ptr->weight);
389 add_display_treestore_line(update, treestore, &iter,
390 find_col_name(display_data_node,
391 SORTID_WEIGHT),
392 tmp_cnt);
393 add_display_treestore_line(update, treestore, &iter,
394 find_col_name(display_data_node,
395 SORTID_ARCH),
396 node_ptr->arch);
397 add_display_treestore_line(update, treestore, &iter,
398 find_col_name(display_data_node,
399 SORTID_AVAIL_FEATURES),
400 node_ptr->features);
401 add_display_treestore_line(update, treestore, &iter,
402 find_col_name(display_data_node,
403 SORTID_ACTIVE_FEATURES),
404 node_ptr->features_act);
405 add_display_treestore_line(update, treestore, &iter,
406 find_col_name(display_data_node,
407 SORTID_GRES),
408 node_ptr->gres);
409 add_display_treestore_line(update, treestore, &iter,
410 find_col_name(display_data_node,
411 SORTID_BOOT_TIME),
412 sview_node_info_ptr->boot_time);
413 add_display_treestore_line(update, treestore, &iter,
414 find_col_name(display_data_node,
415 SORTID_SLURMD_START_TIME),
416 sview_node_info_ptr->slurmd_start_time);
417 add_display_treestore_line(update, treestore, &iter,
418 find_col_name(display_data_node,
419 SORTID_REASON),
420 sview_node_info_ptr->reason);
421
422 if (node_ptr->energy->current_watts == NO_VAL) {
423 snprintf(tmp_current_watts, sizeof(tmp_current_watts),
424 "N/A");
425 snprintf(tmp_ave_watts, sizeof(tmp_ave_watts),
426 "N/A");
427 } else {
428 snprintf(tmp_current_watts, sizeof(tmp_current_watts),
429 "%u", node_ptr->energy->current_watts);
430 snprintf(tmp_ave_watts, sizeof(tmp_ave_watts),
431 "%u", node_ptr->energy->ave_watts);
432 }
433
434 add_display_treestore_line(update, treestore, &iter,
435 find_col_name(display_data_node,
436 SORTID_CURRENT_WATTS),
437 tmp_current_watts);
438
439 add_display_treestore_line(update, treestore, &iter,
440 find_col_name(display_data_node,
441 SORTID_AVE_WATTS),
442 tmp_ave_watts);
443
444 if (!node_ptr->power || (node_ptr->power->cap_watts == NO_VAL)) {
445 snprintf(tmp_cap_watts, sizeof(tmp_cap_watts), "N/A");
446 } else {
447 snprintf(tmp_cap_watts, sizeof(tmp_cap_watts), "%u",
448 node_ptr->power->cap_watts);
449 }
450 add_display_treestore_line(update, treestore, &iter,
451 find_col_name(display_data_node,
452 SORTID_CAP_WATTS),
453 tmp_cap_watts);
454
455 if (node_ptr->version == NULL) {
456 snprintf(tmp_version, sizeof(tmp_version), "N/A");
457 } else {
458 snprintf(tmp_version, sizeof(tmp_version), "%s",
459 node_ptr->version);
460 }
461 add_display_treestore_line(update, treestore, &iter,
462 find_col_name(display_data_node,
463 SORTID_VERSION),
464 tmp_version);
465 return;
466 }
467
_update_node_record(sview_node_info_t * sview_node_info_ptr,GtkTreeStore * treestore)468 static void _update_node_record(sview_node_info_t *sview_node_info_ptr,
469 GtkTreeStore *treestore)
470 {
471 uint16_t alloc_cpus = 0, idle_cpus;
472 uint64_t alloc_memory;
473 node_info_t *node_ptr = sview_node_info_ptr->node_ptr;
474 char tmp_disk[20], tmp_cpus[20], tmp_idle_cpus[20];
475 char tmp_mem[20], tmp_used_memory[20];
476 char tmp_used_cpus[20], tmp_cpu_load[20], tmp_free_mem[20], tmp_owner[32];
477 char tmp_current_watts[50], tmp_ave_watts[50];
478 char tmp_cap_watts[50], tmp_version[50];
479 char *tmp_state_lower, *tmp_state_upper;
480 char *node_alloc_tres = NULL;
481
482 if (node_ptr->energy->current_watts == NO_VAL) {
483 snprintf(tmp_current_watts, sizeof(tmp_current_watts),
484 "N/A");
485 snprintf(tmp_ave_watts, sizeof(tmp_ave_watts),
486 "N/A");
487 } else {
488 snprintf(tmp_current_watts, sizeof(tmp_current_watts),
489 "%u ", node_ptr->energy->current_watts);
490 snprintf(tmp_ave_watts, sizeof(tmp_ave_watts),
491 "%u", node_ptr->energy->ave_watts);
492 }
493
494 if (!node_ptr->power || (node_ptr->power->cap_watts == NO_VAL)) {
495 snprintf(tmp_cap_watts, sizeof(tmp_cap_watts), "N/A");
496 } else {
497 snprintf(tmp_cap_watts, sizeof(tmp_cap_watts), "%u",
498 node_ptr->power->cap_watts);
499 }
500
501 if (node_ptr->cpu_load == NO_VAL) {
502 strlcpy(tmp_cpu_load, "N/A", sizeof(tmp_cpu_load));
503 } else {
504 snprintf(tmp_cpu_load, sizeof(tmp_cpu_load),
505 "%.2f", (node_ptr->cpu_load / 100.0));
506 }
507
508 if (node_ptr->free_mem == NO_VAL64) {
509 strlcpy(tmp_free_mem, "N/A", sizeof(tmp_free_mem));
510 } else {
511 snprintf(tmp_free_mem, sizeof(tmp_free_mem),
512 "%"PRIu64"M", node_ptr->free_mem);
513 }
514
515 convert_num_unit((float)node_ptr->cpus, tmp_cpus,
516 sizeof(tmp_cpus), UNIT_NONE, NO_VAL,
517 working_sview_config.convert_flags);
518
519 select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
520 SELECT_NODEDATA_SUBCNT,
521 NODE_STATE_ALLOCATED,
522 &alloc_cpus);
523
524 idle_cpus = node_ptr->cpus - alloc_cpus;
525 convert_num_unit((float)alloc_cpus, tmp_used_cpus,
526 sizeof(tmp_used_cpus), UNIT_NONE, NO_VAL,
527 working_sview_config.convert_flags);
528
529 select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
530 SELECT_NODEDATA_MEM_ALLOC,
531 NODE_STATE_ALLOCATED,
532 &alloc_memory);
533 snprintf(tmp_used_memory, sizeof(tmp_used_memory), "%"PRIu64"M", alloc_memory);
534
535 convert_num_unit((float)alloc_cpus, tmp_used_cpus,
536 sizeof(tmp_used_cpus), UNIT_NONE, NO_VAL,
537 working_sview_config.convert_flags);
538
539 convert_num_unit((float)idle_cpus, tmp_idle_cpus, sizeof(tmp_idle_cpus),
540 UNIT_NONE, NO_VAL, working_sview_config.convert_flags);
541
542 if (IS_NODE_DRAIN(node_ptr)) {
543 /* don't worry about mixed since the
544 * whole node is being drained. */
545 } else if (idle_cpus && (idle_cpus != node_ptr->cpus)) {
546 node_ptr->node_state &= NODE_STATE_FLAGS;
547 node_ptr->node_state |= NODE_STATE_MIXED;
548 }
549 tmp_state_upper = node_state_string(node_ptr->node_state);
550 tmp_state_lower = str_tolower(tmp_state_upper);
551
552 convert_num_unit((float)node_ptr->real_memory, tmp_mem, sizeof(tmp_mem),
553 UNIT_MEGA, NO_VAL, working_sview_config.convert_flags);
554
555 convert_num_unit((float)node_ptr->tmp_disk, tmp_disk, sizeof(tmp_disk),
556 UNIT_MEGA, NO_VAL, working_sview_config.convert_flags);
557
558 if (node_ptr->version == NULL) {
559 snprintf(tmp_version, sizeof(tmp_version), "N/A");
560 } else {
561 snprintf(tmp_version, sizeof(tmp_version), "%s",
562 node_ptr->version);
563 }
564
565 if (node_ptr->owner == NO_VAL) {
566 snprintf(tmp_owner, sizeof(tmp_owner), "N/A");
567 } else {
568 char *user_name;
569 user_name = uid_to_string((uid_t) node_ptr->owner);
570 snprintf(tmp_owner, sizeof(tmp_owner), "%s(%u)",
571 user_name, node_ptr->owner);
572 xfree(user_name);
573 }
574
575 select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
576 SELECT_NODEDATA_TRES_ALLOC_FMT_STR,
577 NODE_STATE_ALLOCATED, &node_alloc_tres);
578
579 /* Combining these records provides a slight performance improvement */
580 gtk_tree_store_set(treestore, &sview_node_info_ptr->iter_ptr,
581 SORTID_ACTIVE_FEATURES, node_ptr->features_act,
582 SORTID_ARCH, node_ptr->arch,
583 SORTID_AVAIL_FEATURES, node_ptr->features,
584 SORTID_AVE_WATTS, tmp_ave_watts,
585 SORTID_BOARDS, node_ptr->boards,
586 SORTID_BOOT_TIME, sview_node_info_ptr->boot_time,
587 SORTID_CLUSTER_NAME, node_ptr->cluster_name,
588 SORTID_CAP_WATTS, tmp_cap_watts,
589 SORTID_COLOR,
590 sview_colors[sview_node_info_ptr->pos
591 % sview_colors_cnt],
592 SORTID_CORES, node_ptr->cores,
593 SORTID_CPUS, tmp_cpus,
594 SORTID_CURRENT_WATTS, tmp_current_watts,
595 SORTID_CPU_LOAD, tmp_cpu_load,
596 SORTID_FREE_MEM, tmp_free_mem,
597 SORTID_TMP_DISK, tmp_disk,
598 SORTID_IDLE_CPUS, tmp_idle_cpus,
599 SORTID_GRES, node_ptr->gres,
600 SORTID_MCS_LABEL, (node_ptr->mcs_label == NULL) ?
601 "N/A" : node_ptr->mcs_label,
602 SORTID_REAL_MEMORY, tmp_mem,
603 SORTID_NAME, node_ptr->name,
604 SORTID_NODE_ADDR, node_ptr->node_addr,
605 SORTID_NODE_HOSTNAME, node_ptr->node_hostname,
606 SORTID_OWNER, tmp_owner,
607 SORTID_REASON, sview_node_info_ptr->reason,
608 SORTID_SLURMD_START_TIME,
609 sview_node_info_ptr->slurmd_start_time,
610 SORTID_SOCKETS, node_ptr->sockets,
611 SORTID_STATE, tmp_state_lower,
612 SORTID_STATE_NUM, node_ptr->node_state,
613 SORTID_THREADS, node_ptr->threads,
614 SORTID_TRES_ALLOC, node_alloc_tres ?
615 node_alloc_tres : "",
616 SORTID_TRES_CONFIG, node_ptr->tres_fmt_str,
617 SORTID_USED_CPUS, tmp_used_cpus,
618 SORTID_USED_MEMORY, tmp_used_memory,
619 SORTID_VERSION, tmp_version,
620 SORTID_WEIGHT, node_ptr->weight,
621 SORTID_UPDATED, 1,
622 -1);
623
624 xfree(tmp_state_lower);
625 xfree(node_alloc_tres);
626 return;
627 }
628
_append_node_record(sview_node_info_t * sview_node_info,GtkTreeStore * treestore)629 static void _append_node_record(sview_node_info_t *sview_node_info,
630 GtkTreeStore *treestore)
631 {
632 gtk_tree_store_append(treestore, &sview_node_info->iter_ptr, NULL);
633 gtk_tree_store_set(treestore, &sview_node_info->iter_ptr, SORTID_POS,
634 sview_node_info->pos, -1);
635 _update_node_record(sview_node_info, treestore);
636 }
637
_update_info_node(List info_list,GtkTreeView * tree_view)638 static void _update_info_node(List info_list, GtkTreeView *tree_view)
639 {
640 GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
641 char *name = NULL;
642 ListIterator itr = NULL;
643 sview_node_info_t *sview_node_info = NULL;
644
645 set_for_update(model, SORTID_UPDATED);
646
647 itr = list_iterator_create(info_list);
648 while ((sview_node_info = list_next(itr))) {
649 /* This means the tree_store changed (added new column
650 * or something). */
651 if (last_model != model)
652 sview_node_info->iter_set = false;
653
654 if (sview_node_info->iter_set) {
655 gtk_tree_model_get(model, &sview_node_info->iter_ptr,
656 SORTID_NAME, &name, -1);
657 if (xstrcmp(name, sview_node_info->node_name)) {
658 /* Bad pointer */
659 sview_node_info->iter_set = false;
660 //g_print("bad node iter pointer\n");
661 }
662 g_free(name);
663 }
664 if (sview_node_info->iter_set)
665 _update_node_record(sview_node_info,
666 GTK_TREE_STORE(model));
667 else {
668 _append_node_record(sview_node_info,
669 GTK_TREE_STORE(model));
670 sview_node_info->iter_set = true;
671 }
672 }
673 list_iterator_destroy(itr);
674
675 /* remove all old nodes */
676 remove_old(model, SORTID_UPDATED);
677 last_model = model;
678 }
679
_node_info_free(sview_node_info_t * sview_node_info)680 static void _node_info_free(sview_node_info_t *sview_node_info)
681 {
682 if (sview_node_info) {
683 xfree(sview_node_info->slurmd_start_time);
684 xfree(sview_node_info->boot_time);
685 xfree(sview_node_info->node_name);
686 xfree(sview_node_info->rack_mp);
687 xfree(sview_node_info->reason);
688 }
689 }
690
_node_info_list_del(void * object)691 static void _node_info_list_del(void *object)
692 {
693 sview_node_info_t *sview_node_info = (sview_node_info_t *)object;
694
695 if (sview_node_info) {
696 _node_info_free(sview_node_info);
697 xfree(sview_node_info);
698 }
699 }
700
_display_info_node(List info_list,popup_info_t * popup_win)701 static void _display_info_node(List info_list, popup_info_t *popup_win)
702 {
703 specific_info_t *spec_info = popup_win->spec_info;
704 char *name = (char *)spec_info->search_info->gchar_data;
705 int found = 0;
706 node_info_t *node_ptr = NULL;
707 GtkTreeView *treeview = NULL;
708 int update = 0;
709 ListIterator itr = NULL;
710 sview_node_info_t *sview_node_info = NULL;
711 int i = -1;
712
713 if (!spec_info->search_info->gchar_data) {
714 goto finished;
715 }
716 need_refresh:
717 if (!spec_info->display_widget) {
718 treeview = create_treeview_2cols_attach_to_table(
719 popup_win->table);
720 spec_info->display_widget =
721 g_object_ref(GTK_WIDGET(treeview));
722 } else {
723 treeview = GTK_TREE_VIEW(spec_info->display_widget);
724 update = 1;
725 }
726
727 itr = list_iterator_create(info_list);
728 while ((sview_node_info = list_next(itr))) {
729 node_ptr = sview_node_info->node_ptr;
730 i++;
731 if (!xstrcmp(node_ptr->name, name)) {
732 change_grid_color(popup_win->grid_button_list,
733 i, i, i, true, 0);
734 _layout_node_record(treeview, sview_node_info, update);
735 found = 1;
736 break;
737 }
738 }
739 list_iterator_destroy(itr);
740 if (!found) {
741 if (!popup_win->not_found) {
742 char *temp;
743 GtkTreeIter iter;
744 GtkTreeModel *model = NULL;
745
746 temp = "NODE NOT FOUND\n";
747 /* only time this will be run so no update */
748 model = gtk_tree_view_get_model(treeview);
749 add_display_treestore_line(0,
750 GTK_TREE_STORE(model),
751 &iter,
752 temp, "");
753 }
754 popup_win->not_found = true;
755 } else {
756 if (popup_win->not_found) {
757 popup_win->not_found = false;
758 gtk_widget_destroy(spec_info->display_widget);
759
760 goto need_refresh;
761 }
762 }
763 gtk_widget_show(spec_info->display_widget);
764
765 finished:
766 return;
767 }
768
_selected_page(GtkMenuItem * menuitem,display_data_t * display_data)769 static void _selected_page(GtkMenuItem *menuitem,
770 display_data_t *display_data)
771 {
772 switch(display_data->extra) {
773 case NODE_PAGE:
774 popup_all_node_name(display_data->user_data, display_data->id,
775 NULL);
776 break;
777 case ADMIN_PAGE:
778 admin_node_name(display_data->user_data,
779 NULL, display_data->name);
780 break;
781 default:
782 g_print("node got %d %d\n", display_data->extra,
783 display_data->id);
784 }
785
786 }
787
_process_each_node(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata)788 static void _process_each_node(GtkTreeModel *model, GtkTreePath *path,
789 GtkTreeIter *iter, gpointer userdata)
790 {
791 char *name = NULL;
792 process_node_t *process_node = userdata;
793
794 gtk_tree_model_get(model, iter, process_node->node_col, &name, -1);
795 if (process_node->nodelist)
796 xstrfmtcat(process_node->nodelist, ",%s", name);
797 else
798 process_node->nodelist = xstrdup(name);
799 g_free(name);
800 }
801 /*process_each_node ^^^*/
802
803
804
refresh_node(GtkAction * action,gpointer user_data)805 extern void refresh_node(GtkAction *action, gpointer user_data)
806 {
807 popup_info_t *popup_win = (popup_info_t *)user_data;
808 xassert(popup_win);
809 xassert(popup_win->spec_info);
810 xassert(popup_win->spec_info->title);
811 popup_win->force_refresh = 1;
812 specific_info_node(popup_win);
813 }
814
815 /* don't destroy the list from this function */
create_node_info_list(node_info_msg_t * node_info_ptr,bool by_partition)816 extern List create_node_info_list(node_info_msg_t *node_info_ptr,
817 bool by_partition)
818 {
819 static List info_list = NULL;
820 static node_info_msg_t *last_node_info_ptr = NULL;
821 List last_list = NULL;
822 ListIterator last_list_itr = NULL;
823 int i = 0;
824 sview_node_info_t *sview_node_info_ptr = NULL;
825 node_info_t *node_ptr = NULL;
826 char user[32], time_str[32];
827
828 if (!by_partition) {
829 if (!node_info_ptr
830 || (info_list && (node_info_ptr == last_node_info_ptr)))
831 goto update_color;
832 }
833
834 last_node_info_ptr = node_info_ptr;
835
836 if (info_list)
837 last_list = info_list;
838
839 info_list = list_create(_node_info_list_del);
840
841 if (last_list)
842 last_list_itr = list_iterator_create(last_list);
843 for (i=0; i<node_info_ptr->record_count; i++) {
844 node_ptr = &(node_info_ptr->node_array[i]);
845
846 if (!node_ptr->name || (node_ptr->name[0] == '\0'))
847 continue;
848
849 sview_node_info_ptr = NULL;
850
851 if (last_list_itr) {
852 while ((sview_node_info_ptr =
853 list_next(last_list_itr))) {
854 if (!xstrcmp(sview_node_info_ptr->node_name,
855 node_ptr->name)) {
856 list_remove(last_list_itr);
857 _node_info_free(sview_node_info_ptr);
858 break;
859 }
860 }
861 list_iterator_reset(last_list_itr);
862 }
863
864 /* constrain list to included partitions' nodes */
865 /* and there are excluded values to process */
866 /* and user has not requested to show hidden */
867 /* if (by_partition && apply_partition_check */
868 /* && !working_sview_config.show_hidden */
869 /* && !check_part_includes_node(i)) */
870 /* continue; */
871
872 if (!sview_node_info_ptr)
873 sview_node_info_ptr =
874 xmalloc(sizeof(sview_node_info_t));
875 list_append(info_list, sview_node_info_ptr);
876 sview_node_info_ptr->node_name = xstrdup(node_ptr->name);
877 sview_node_info_ptr->node_ptr = node_ptr;
878 sview_node_info_ptr->pos = i;
879
880 if (node_ptr->reason &&
881 (node_ptr->reason_uid != NO_VAL) && node_ptr->reason_time) {
882 struct passwd *pw = NULL;
883
884 if ((pw=getpwuid(node_ptr->reason_uid)))
885 snprintf(user, sizeof(user), "%s", pw->pw_name);
886 else
887 snprintf(user, sizeof(user), "Unk(%u)",
888 node_ptr->reason_uid);
889 slurm_make_time_str(&node_ptr->reason_time,
890 time_str, sizeof(time_str));
891 sview_node_info_ptr->reason = xstrdup_printf(
892 "%s [%s@%s]", node_ptr->reason, user, time_str);
893 } else if (node_ptr->reason)
894 sview_node_info_ptr->reason = xstrdup(node_ptr->reason);
895
896 if (node_ptr->boot_time) {
897 slurm_make_time_str(&node_ptr->boot_time,
898 time_str, sizeof(time_str));
899 sview_node_info_ptr->boot_time = xstrdup(time_str);
900 }
901 if (node_ptr->slurmd_start_time) {
902 slurm_make_time_str(&node_ptr->slurmd_start_time,
903 time_str, sizeof(time_str));
904 sview_node_info_ptr->slurmd_start_time =
905 xstrdup(time_str);
906 }
907 }
908
909 if (last_list) {
910 list_iterator_destroy(last_list_itr);
911 FREE_NULL_LIST(last_list);
912 }
913
914 update_color:
915
916 return info_list;
917 }
918
get_new_info_node(node_info_msg_t ** info_ptr,int force)919 extern int get_new_info_node(node_info_msg_t **info_ptr, int force)
920 {
921 node_info_msg_t *new_node_ptr = NULL;
922 uint16_t show_flags = 0;
923 int error_code = SLURM_NO_CHANGE_IN_DATA;
924 time_t now = time(NULL), delay;
925 static time_t last;
926 static bool changed = 0;
927 static uint16_t last_flags = 0;
928
929 delay = now - last;
930 if (delay < 2) {
931 /* Avoid re-loading node information within 2 secs as the data
932 * may still be in use. If we load new node data and free the
933 * old data while it it still in use, the result is likely
934 * invalid memory references. */
935 force = 0;
936 /* FIXME: Add an "in use" flag, copy the data, or otherwise
937 * permit the timely loading of new node information. */
938 }
939
940 if (g_node_info_ptr && !force &&
941 (delay < working_sview_config.refresh_delay)) {
942 if (*info_ptr != g_node_info_ptr)
943 error_code = SLURM_SUCCESS;
944 *info_ptr = g_node_info_ptr;
945 return error_code;
946 }
947 last = now;
948
949 if (cluster_flags & CLUSTER_FLAG_FED)
950 show_flags |= SHOW_FEDERATION;
951 //if (working_sview_config.show_hidden)
952 show_flags |= SHOW_ALL;
953 if (g_node_info_ptr) {
954 if (show_flags != last_flags)
955 g_node_info_ptr->last_update = 0;
956 error_code = slurm_load_node(g_node_info_ptr->last_update,
957 &new_node_ptr, show_flags);
958 if (error_code == SLURM_SUCCESS) {
959 slurm_free_node_info_msg(g_node_info_ptr);
960 changed = 1;
961 } else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) {
962 error_code = SLURM_NO_CHANGE_IN_DATA;
963 new_node_ptr = g_node_info_ptr;
964 changed = 0;
965 }
966 } else {
967 new_node_ptr = NULL;
968 error_code = slurm_load_node((time_t) NULL, &new_node_ptr,
969 show_flags);
970 changed = 1;
971 }
972
973 last_flags = show_flags;
974 g_node_info_ptr = new_node_ptr;
975
976 if (g_node_info_ptr && (*info_ptr != g_node_info_ptr))
977 error_code = SLURM_SUCCESS;
978
979 if (new_node_ptr && new_node_ptr->node_array && changed) {
980 int i;
981 node_info_t *node_ptr = NULL;
982 uint16_t alloc_cpus = 0;
983 int idle_cpus;
984
985 for (i=0; i<g_node_info_ptr->record_count; i++) {
986 node_ptr = &(g_node_info_ptr->node_array[i]);
987 if (!node_ptr->name || (node_ptr->name[0] == '\0'))
988 continue; /* bad node */
989 idle_cpus = node_ptr->cpus;
990
991 slurm_get_select_nodeinfo(
992 node_ptr->select_nodeinfo,
993 SELECT_NODEDATA_SUBCNT,
994 NODE_STATE_ALLOCATED,
995 &alloc_cpus);
996 idle_cpus -= alloc_cpus;
997
998 if (IS_NODE_DRAIN(node_ptr)) {
999 /* don't worry about mixed since the
1000 whole node is being drained. */
1001 } else if (idle_cpus &&
1002 (idle_cpus != node_ptr->cpus)) {
1003 node_ptr->node_state &= NODE_STATE_FLAGS;
1004 node_ptr->node_state |= NODE_STATE_MIXED;
1005 }
1006 }
1007 }
1008
1009 *info_ptr = g_node_info_ptr;
1010
1011 if (!g_topo_info_msg_ptr &&
1012 default_sview_config.grid_topological) {
1013 get_topo_conf(); /* pull in topology NOW */
1014 }
1015
1016 return error_code;
1017 }
1018
update_active_features_node(GtkDialog * dialog,const char * nodelist,const char * old_features)1019 extern int update_active_features_node(GtkDialog *dialog, const char *nodelist,
1020 const char *old_features)
1021 {
1022 char tmp_char[100];
1023 char *edit = NULL;
1024 GtkWidget *entry = NULL;
1025 GtkWidget *label = NULL;
1026 update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
1027 int response = 0;
1028 int no_dialog = 0;
1029 int rc = SLURM_SUCCESS;
1030
1031
1032 if (_DEBUG)
1033 g_print("update_active_features_node:global_row_count: %d "
1034 "node_names %s\n",
1035 global_row_count, nodelist);
1036 if (!dialog) {
1037 snprintf(tmp_char, sizeof(tmp_char),
1038 "Update Acitve Features for Node(s) %s?",
1039 nodelist);
1040
1041 dialog = GTK_DIALOG(
1042 gtk_dialog_new_with_buttons(
1043 tmp_char,
1044 GTK_WINDOW(main_window),
1045 GTK_DIALOG_MODAL
1046 | GTK_DIALOG_DESTROY_WITH_PARENT,
1047 NULL));
1048 no_dialog = 1;
1049 }
1050 label = gtk_dialog_add_button(dialog,
1051 GTK_STOCK_YES, GTK_RESPONSE_OK);
1052 gtk_window_set_type_hint(GTK_WINDOW(dialog),
1053 GDK_WINDOW_TYPE_HINT_NORMAL);
1054 gtk_window_set_default(GTK_WINDOW(dialog), label);
1055 gtk_dialog_add_button(dialog,
1056 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1057
1058 slurm_init_update_node_msg(node_msg);
1059 node_msg->node_names = xstrdup(nodelist);
1060
1061 snprintf(tmp_char, sizeof(tmp_char),
1062 "Active Features for Node(s) %s?", nodelist);
1063 label = gtk_label_new(tmp_char);
1064 gtk_box_pack_start(GTK_BOX(dialog->vbox),
1065 label, false, false, 0);
1066
1067 entry = create_entry();
1068 if (!entry)
1069 goto end_it;
1070
1071 if (old_features)
1072 gtk_entry_set_text(GTK_ENTRY(entry), old_features);
1073
1074 gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, true, true, 0);
1075 gtk_widget_show_all(GTK_WIDGET(dialog));
1076
1077 response = gtk_dialog_run(dialog);
1078 if (response == GTK_RESPONSE_OK) {
1079 node_msg->features_act =
1080 xstrdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1081 if (!node_msg->features_act) {
1082 edit = g_strdup_printf("No features given.");
1083 display_edit_note(edit);
1084 g_free(edit);
1085 goto end_it;
1086 }
1087 if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) {
1088 edit = g_strdup_printf(
1089 "Node(s) %s updated successfully.",
1090 nodelist);
1091 display_edit_note(edit);
1092 g_free(edit);
1093
1094 } else {
1095 edit = g_strdup_printf(
1096 "Problem updating node(s) %s: %s",
1097 nodelist, slurm_strerror(rc));
1098 display_edit_note(edit);
1099 g_free(edit);
1100 }
1101 }
1102
1103 end_it:
1104 slurm_free_update_node_msg(node_msg);
1105 if (no_dialog)
1106 gtk_widget_destroy(GTK_WIDGET(dialog));
1107
1108 return rc;
1109 }
1110
update_avail_features_node(GtkDialog * dialog,const char * nodelist,const char * old_features)1111 extern int update_avail_features_node(GtkDialog *dialog, const char *nodelist,
1112 const char *old_features)
1113 {
1114 char tmp_char[100];
1115 char *edit = NULL;
1116 GtkWidget *entry = NULL;
1117 GtkWidget *label = NULL;
1118 update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
1119 int response = 0;
1120 int no_dialog = 0;
1121 int rc = SLURM_SUCCESS;
1122
1123
1124 if (_DEBUG)
1125 g_print("update_avail_features_node:global_row_count: %d "
1126 "node_names %s\n",
1127 global_row_count, nodelist);
1128 if (!dialog) {
1129 snprintf(tmp_char, sizeof(tmp_char),
1130 "Update Available Features for Node(s) %s?",
1131 nodelist);
1132
1133 dialog = GTK_DIALOG(
1134 gtk_dialog_new_with_buttons(
1135 tmp_char,
1136 GTK_WINDOW(main_window),
1137 GTK_DIALOG_MODAL
1138 | GTK_DIALOG_DESTROY_WITH_PARENT,
1139 NULL));
1140 no_dialog = 1;
1141 }
1142 label = gtk_dialog_add_button(dialog,
1143 GTK_STOCK_YES, GTK_RESPONSE_OK);
1144 gtk_window_set_type_hint(GTK_WINDOW(dialog),
1145 GDK_WINDOW_TYPE_HINT_NORMAL);
1146 gtk_window_set_default(GTK_WINDOW(dialog), label);
1147 gtk_dialog_add_button(dialog,
1148 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1149
1150 slurm_init_update_node_msg(node_msg);
1151 node_msg->node_names = xstrdup(nodelist);
1152
1153 snprintf(tmp_char, sizeof(tmp_char),
1154 "Available Features for Node(s) %s?", nodelist);
1155 label = gtk_label_new(tmp_char);
1156 gtk_box_pack_start(GTK_BOX(dialog->vbox),
1157 label, false, false, 0);
1158
1159 entry = create_entry();
1160 if (!entry)
1161 goto end_it;
1162
1163 if (old_features)
1164 gtk_entry_set_text(GTK_ENTRY(entry), old_features);
1165
1166 gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, true, true, 0);
1167 gtk_widget_show_all(GTK_WIDGET(dialog));
1168
1169 response = gtk_dialog_run(dialog);
1170 if (response == GTK_RESPONSE_OK) {
1171 node_msg->features =
1172 xstrdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1173 if (!node_msg->features) {
1174 edit = g_strdup_printf("No features given.");
1175 display_edit_note(edit);
1176 g_free(edit);
1177 goto end_it;
1178 }
1179 if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) {
1180 edit = g_strdup_printf(
1181 "Node(s) %s updated successfully.",
1182 nodelist);
1183 display_edit_note(edit);
1184 g_free(edit);
1185
1186 } else {
1187 edit = g_strdup_printf(
1188 "Problem updating node(s) %s: %s",
1189 nodelist, slurm_strerror(rc));
1190 display_edit_note(edit);
1191 g_free(edit);
1192 }
1193 }
1194
1195 end_it:
1196 slurm_free_update_node_msg(node_msg);
1197 if (no_dialog)
1198 gtk_widget_destroy(GTK_WIDGET(dialog));
1199
1200 return rc;
1201 }
1202
update_gres_node(GtkDialog * dialog,const char * nodelist,const char * old_gres)1203 extern int update_gres_node(GtkDialog *dialog, const char *nodelist,
1204 const char *old_gres)
1205 {
1206 char tmp_char[100];
1207 char *edit = NULL;
1208 GtkWidget *entry = NULL;
1209 GtkWidget *label = NULL;
1210 update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
1211 int response = 0;
1212 int no_dialog = 0;
1213 int rc = SLURM_SUCCESS;
1214
1215 if (_DEBUG)
1216 g_print("update_gres_node:global_row_count:"
1217 " %d node_names %s\n",
1218 global_row_count, nodelist);
1219 if (!dialog) {
1220 snprintf(tmp_char, sizeof(tmp_char),
1221 "Update Gres for Node(s) %s?",
1222 nodelist);
1223
1224 dialog = GTK_DIALOG(
1225 gtk_dialog_new_with_buttons(
1226 tmp_char,
1227 GTK_WINDOW(main_window),
1228 GTK_DIALOG_MODAL
1229 | GTK_DIALOG_DESTROY_WITH_PARENT,
1230 NULL));
1231 no_dialog = 1;
1232 }
1233 label = gtk_dialog_add_button(dialog, GTK_STOCK_YES, GTK_RESPONSE_OK);
1234 gtk_window_set_type_hint(GTK_WINDOW(dialog),
1235 GDK_WINDOW_TYPE_HINT_NORMAL);
1236 gtk_window_set_default(GTK_WINDOW(dialog), label);
1237 gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1238
1239 slurm_init_update_node_msg(node_msg);
1240 node_msg->node_names = xstrdup(nodelist);
1241
1242 snprintf(tmp_char, sizeof(tmp_char), "Gres for Node(s) %s?", nodelist);
1243
1244 label = gtk_label_new(tmp_char);
1245 gtk_box_pack_start(GTK_BOX(dialog->vbox), label, false, false, 0);
1246
1247 entry = create_entry();
1248 if (!entry)
1249 goto end_it;
1250
1251 if (old_gres)
1252 gtk_entry_set_text(GTK_ENTRY(entry), old_gres);
1253
1254 gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, true, true, 0);
1255 gtk_widget_show_all(GTK_WIDGET(dialog));
1256
1257 response = gtk_dialog_run(dialog);
1258 if (response == GTK_RESPONSE_OK) {
1259 node_msg->gres = xstrdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1260 if (!node_msg->gres) {
1261 edit = g_strdup_printf("No gres given.");
1262 display_edit_note(edit);
1263 g_free(edit);
1264 goto end_it;
1265 }
1266 if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) {
1267 edit = g_strdup_printf(
1268 "Nodes %s updated successfully.",
1269 nodelist);
1270 display_edit_note(edit);
1271 g_free(edit);
1272 } else {
1273 edit = g_strdup_printf(
1274 "Problem updating nodes %s: %s",
1275 nodelist, slurm_strerror(rc));
1276 display_edit_note(edit);
1277 g_free(edit);
1278 }
1279 }
1280
1281 end_it:
1282 slurm_free_update_node_msg(node_msg);
1283 if (no_dialog)
1284 gtk_widget_destroy(GTK_WIDGET(dialog));
1285
1286 return rc;
1287 }
1288
update_state_node(GtkDialog * dialog,const char * nodelist,const char * type)1289 extern int update_state_node(GtkDialog *dialog,
1290 const char *nodelist, const char *type)
1291 {
1292 uint16_t state = NO_VAL16;
1293 char *upper = NULL, *lower = NULL;
1294 int i = 0;
1295 int rc = SLURM_SUCCESS;
1296 char tmp_char[100];
1297 update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
1298 GtkWidget *label = NULL;
1299 GtkWidget *entry = NULL;
1300 int no_dialog = 0;
1301
1302 if (!dialog) {
1303 dialog = GTK_DIALOG(
1304 gtk_dialog_new_with_buttons(
1305 type,
1306 GTK_WINDOW(main_window),
1307 GTK_DIALOG_MODAL
1308 | GTK_DIALOG_DESTROY_WITH_PARENT,
1309 NULL));
1310 no_dialog = 1;
1311 }
1312 label = gtk_dialog_add_button(dialog, GTK_STOCK_YES, GTK_RESPONSE_OK);
1313 gtk_window_set_type_hint(GTK_WINDOW(dialog),
1314 GDK_WINDOW_TYPE_HINT_NORMAL);
1315 gtk_window_set_default(GTK_WINDOW(dialog), label);
1316 gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1317
1318 slurm_init_update_node_msg(node_msg);
1319 node_msg->node_names = xstrdup(nodelist);
1320
1321 if (!xstrncasecmp("drain", type, 5)) {
1322 snprintf(tmp_char, sizeof(tmp_char),
1323 "Are you sure you want to drain node(s) %s?\n\n"
1324 "Please put reason.",
1325 nodelist);
1326 entry = create_entry();
1327 label = gtk_label_new(tmp_char);
1328 state = NODE_STATE_DRAIN;
1329 } else if (!xstrncasecmp("resume", type, 5)) {
1330 snprintf(tmp_char, sizeof(tmp_char),
1331 "Are you sure you want to resume node(s) %s?",
1332 nodelist);
1333 label = gtk_label_new(tmp_char);
1334 state = NODE_RESUME;
1335 } else if (!xstrncasecmp("set", type, 3)) {
1336 snprintf(tmp_char, sizeof(tmp_char),
1337 "Are you sure you want to down node(s) %s?\n\n"
1338 "Please put reason.",
1339 nodelist);
1340 entry = create_entry();
1341 label = gtk_label_new(tmp_char);
1342 state = NODE_STATE_DOWN;
1343 } else if (!xstrncasecmp("undrain", type, 5)) {
1344 snprintf(tmp_char, sizeof(tmp_char),
1345 "Are you sure you want to undrain node(s) %s?",
1346 nodelist);
1347 label = gtk_label_new(tmp_char);
1348 state = NODE_STATE_UNDRAIN;
1349 } else {
1350
1351 if (!xstrncasecmp("make", type, 4))
1352 type = "idle";
1353 for(i = 0; i < NODE_STATE_END; i++) {
1354 upper = node_state_string(i);
1355 lower = str_tolower(upper);
1356 if (!xstrcmp(lower, type)) {
1357 snprintf(tmp_char, sizeof(tmp_char),
1358 "Are you sure you want to set "
1359 "node(s) %s to %s?",
1360 nodelist, lower);
1361 label = gtk_label_new(tmp_char);
1362 state = i;
1363 xfree(lower);
1364 break;
1365 }
1366 xfree(lower);
1367 }
1368 }
1369 if (!label)
1370 goto end_it;
1371 node_msg->node_state = (uint16_t)state;
1372 gtk_box_pack_start(GTK_BOX(dialog->vbox), label, false, false, 0);
1373 if (entry)
1374 gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, true, true, 0);
1375 gtk_widget_show_all(GTK_WIDGET(dialog));
1376 i = gtk_dialog_run(dialog);
1377 if (i == GTK_RESPONSE_OK) {
1378 if (entry) {
1379 node_msg->reason = xstrdup(
1380 gtk_entry_get_text(GTK_ENTRY(entry)));
1381 if (!node_msg->reason || !strlen(node_msg->reason)) {
1382 lower = g_strdup_printf(
1383 "You need a reason to do that.");
1384 display_edit_note(lower);
1385 g_free(lower);
1386 goto end_it;
1387 }
1388 if (uid_from_string(getlogin(),
1389 &node_msg->reason_uid) < 0)
1390 node_msg->reason_uid = getuid();
1391
1392 }
1393 if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) {
1394 lower = g_strdup_printf(
1395 "Nodes %s updated successfully.",
1396 nodelist);
1397 display_edit_note(lower);
1398 g_free(lower);
1399 } else {
1400 lower = g_strdup_printf(
1401 "Problem updating nodes %s: %s",
1402 nodelist, slurm_strerror(rc));
1403 display_edit_note(lower);
1404 g_free(lower);
1405 }
1406 }
1407 end_it:
1408 slurm_free_update_node_msg(node_msg);
1409 if (no_dialog)
1410 gtk_widget_destroy(GTK_WIDGET(dialog));
1411
1412 return rc;
1413 }
1414
create_model_node(int type)1415 extern GtkListStore *create_model_node(int type)
1416 {
1417 GtkListStore *model = NULL;
1418 GtkTreeIter iter;
1419 char *upper = NULL, *lower = NULL;
1420 int i=0;
1421
1422 last_model = NULL; /* Reformat display */
1423 switch(type) {
1424 case SORTID_STATE:
1425 model = gtk_list_store_new(2, G_TYPE_STRING,
1426 G_TYPE_INT);
1427 gtk_list_store_append(model, &iter);
1428 gtk_list_store_set(model, &iter,
1429 0, "drain",
1430 1, i,
1431 -1);
1432 gtk_list_store_append(model, &iter);
1433 gtk_list_store_set(model, &iter,
1434 0, "NoResp",
1435 1, i,
1436 -1);
1437 gtk_list_store_append(model, &iter);
1438 gtk_list_store_set(model, &iter,
1439 0, "resume",
1440 1, i,
1441 -1);
1442 gtk_list_store_append(model, &iter);
1443 gtk_list_store_set(model, &iter,
1444 0, "undrain",
1445 1, i,
1446 -1);
1447 for(i = 0; i < NODE_STATE_END; i++) {
1448 upper = node_state_string(i);
1449 gtk_list_store_append(model, &iter);
1450 lower = str_tolower(upper);
1451 gtk_list_store_set(model, &iter,
1452 0, lower,
1453 1, i,
1454 -1);
1455 xfree(lower);
1456 }
1457
1458 break;
1459
1460 }
1461 return model;
1462 }
1463
admin_edit_node(GtkCellRendererText * cell,const char * path_string,const char * new_text,gpointer data)1464 extern void admin_edit_node(GtkCellRendererText *cell,
1465 const char *path_string,
1466 const char *new_text,
1467 gpointer data)
1468 {
1469 GtkTreeStore *treestore = NULL;
1470 GtkTreePath *path = NULL;
1471 GtkTreeIter iter;
1472 char *nodelist = NULL;
1473 int column;
1474
1475 if (!new_text || !xstrcmp(new_text, ""))
1476 goto no_input;
1477
1478 if (cluster_flags & CLUSTER_FLAG_FED) {
1479 display_fed_disabled_popup(new_text);
1480 goto no_input;
1481 }
1482
1483 treestore = GTK_TREE_STORE(data);
1484 path = gtk_tree_path_new_from_string(path_string);
1485 gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path);
1486
1487 column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column"));
1488 switch(column) {
1489 case SORTID_STATE:
1490 gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
1491 SORTID_NAME,
1492 &nodelist, -1);
1493
1494 update_state_node(NULL, nodelist, new_text);
1495
1496 g_free(nodelist);
1497 default:
1498 break;
1499 }
1500
1501 gtk_tree_path_free(path);
1502 no_input:
1503 g_mutex_unlock(sview_mutex);
1504 }
1505
get_info_node(GtkTable * table,display_data_t * display_data)1506 extern void get_info_node(GtkTable *table, display_data_t *display_data)
1507 {
1508 int error_code = SLURM_SUCCESS;
1509 static int view = -1;
1510 static node_info_msg_t *node_info_ptr = NULL;
1511 char error_char[100];
1512 GtkWidget *label = NULL;
1513 GtkTreeView *tree_view = NULL;
1514 static GtkWidget *display_widget = NULL;
1515 List info_list = NULL;
1516 int i = 0, sort_key;
1517 sview_node_info_t *sview_node_info_ptr = NULL;
1518 ListIterator itr = NULL;
1519 GtkTreePath *path = NULL;
1520 static bool set_opts = false;
1521
1522 if (!set_opts)
1523 set_page_opts(NODE_PAGE, display_data_node,
1524 SORTID_CNT, _initial_page_opts);
1525 set_opts = true;
1526
1527 /* reset */
1528 if (!table && !display_data) {
1529 if (display_widget)
1530 gtk_widget_destroy(display_widget);
1531 display_widget = NULL;
1532 goto reset_curs;
1533 }
1534
1535 if (display_data)
1536 local_display_data = display_data;
1537 if (!table) {
1538 display_data_node->set_menu = local_display_data->set_menu;
1539 goto reset_curs;
1540 }
1541
1542 if (display_widget && toggled) {
1543 gtk_widget_destroy(display_widget);
1544 display_widget = NULL;
1545 /* Since the node_info_ptr could change out from under
1546 * us we always need to check if it is new or not.
1547 */
1548 /* goto display_it; */
1549 }
1550 if ((error_code = get_new_info_node(&node_info_ptr, force_refresh))
1551 == SLURM_NO_CHANGE_IN_DATA) {
1552 if (!display_widget || view == ERROR_VIEW)
1553 goto display_it;
1554 } else if (error_code != SLURM_SUCCESS) {
1555 if (view == ERROR_VIEW)
1556 goto end_it;
1557 view = ERROR_VIEW;
1558 if (display_widget)
1559 gtk_widget_destroy(display_widget);
1560 sprintf(error_char, "slurm_load_node: %s",
1561 slurm_strerror(slurm_get_errno()));
1562 label = gtk_label_new(error_char);
1563 display_widget = g_object_ref(label);
1564 gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
1565 gtk_widget_show(label);
1566 goto end_it;
1567 }
1568
1569 display_it:
1570 info_list = create_node_info_list(node_info_ptr, false);
1571 if (!info_list)
1572 goto reset_curs;
1573 i = 0;
1574 /* set up the grid */
1575 if (display_widget && GTK_IS_TREE_VIEW(display_widget) &&
1576 gtk_tree_selection_count_selected_rows(
1577 gtk_tree_view_get_selection(
1578 GTK_TREE_VIEW(display_widget)))) {
1579 GtkTreeViewColumn *focus_column = NULL;
1580 /* highlight the correct nodes from the last selection */
1581 gtk_tree_view_get_cursor(GTK_TREE_VIEW(display_widget),
1582 &path, &focus_column);
1583 }
1584 if (!path) {
1585 int array_size = node_info_ptr->record_count;
1586 int *color_inx = xmalloc(sizeof(int) * array_size);
1587 bool *color_set_flag = xmalloc(sizeof(bool) * array_size);
1588 itr = list_iterator_create(info_list);
1589 while ((sview_node_info_ptr = list_next(itr))) {
1590 color_set_flag[i] = true;
1591 color_inx[i] = i;
1592 i++;
1593 }
1594 list_iterator_destroy(itr);
1595 change_grid_color_array(grid_button_list, array_size,
1596 color_inx, color_set_flag, true, 0);
1597 xfree(color_inx);
1598 xfree(color_set_flag);
1599 } else {
1600 highlight_grid(GTK_TREE_VIEW(display_widget),
1601 SORTID_POS, (int)NO_VAL, grid_button_list);
1602 gtk_tree_path_free(path);
1603 }
1604
1605 if (view == ERROR_VIEW && display_widget) {
1606 gtk_widget_destroy(display_widget);
1607 display_widget = NULL;
1608 }
1609 if (!display_widget) {
1610 tree_view = create_treeview(local_display_data,
1611 &grid_button_list);
1612 /*set multiple capability here*/
1613 gtk_tree_selection_set_mode(
1614 gtk_tree_view_get_selection(tree_view),
1615 GTK_SELECTION_MULTIPLE);
1616 display_widget = g_object_ref(GTK_WIDGET(tree_view));
1617 gtk_table_attach_defaults(GTK_TABLE(table),
1618 GTK_WIDGET(tree_view),
1619 0, 1, 0, 1);
1620 /* Since this function sets the model of the tree_view to the
1621 * treestore we don't really care about the return value
1622 * On large clusters, sorting on the node name slows GTK down
1623 * by a large margin. */
1624 if (node_info_ptr->record_count > 1000)
1625 sort_key = -1;
1626 else
1627 sort_key = SORTID_NAME;
1628 create_treestore(tree_view, display_data_node,
1629 SORTID_CNT, sort_key, SORTID_COLOR);
1630 }
1631
1632 view = INFO_VIEW;
1633 /* If the system has a large number of nodes then not all lines
1634 * will be displayed. You can try different values for the third
1635 * argument of gtk_widget_set_size_request() in an attempt to
1636 * maximumize the data displayed in your environment. These are my
1637 * results: Y=1000 good for 43 lines, Y=-1 good for 1151 lines,
1638 * Y=64000 good for 2781 lines, Y=99000 good for 1453 lines */
1639 /* gtk_widget_set_size_request(display_widget, -1, -1); */
1640 _update_info_node(info_list, GTK_TREE_VIEW(display_widget));
1641 end_it:
1642 toggled = false;
1643 force_refresh = 1;
1644 reset_curs:
1645 if (main_window && main_window->window)
1646 gdk_window_set_cursor(main_window->window, NULL);
1647 return;
1648
1649 }
1650
specific_info_node(popup_info_t * popup_win)1651 extern void specific_info_node(popup_info_t *popup_win)
1652 {
1653 int error_code = SLURM_SUCCESS;
1654 static node_info_msg_t *node_info_ptr = NULL;
1655 specific_info_t *spec_info = popup_win->spec_info;
1656 char error_char[100];
1657 GtkWidget *label = NULL;
1658 GtkTreeView *tree_view = NULL;
1659 List info_list = NULL;
1660 List send_info_list = NULL;
1661 ListIterator itr = NULL;
1662 sview_node_info_t *sview_node_info_ptr = NULL;
1663 node_info_t *node_ptr = NULL;
1664 hostlist_t hostlist = NULL;
1665 hostlist_iterator_t host_itr = NULL;
1666 int i = -1, sort_key;
1667 sview_search_info_t *search_info = spec_info->search_info;
1668
1669 if (!spec_info->display_widget)
1670 setup_popup_info(popup_win, display_data_node, SORTID_CNT);
1671
1672 if (node_info_ptr && popup_win->toggled) {
1673 gtk_widget_destroy(spec_info->display_widget);
1674 spec_info->display_widget = NULL;
1675 /* Since the node_info_ptr could change out from under
1676 * us we always need to check if it is new or not.
1677 */
1678 /* goto display_it; */
1679 }
1680
1681 if ((error_code = get_new_info_node(&node_info_ptr,
1682 popup_win->force_refresh))
1683 == SLURM_NO_CHANGE_IN_DATA) {
1684 if (!spec_info->display_widget || spec_info->view == ERROR_VIEW)
1685 goto display_it;
1686 } else if (error_code != SLURM_SUCCESS) {
1687 if (spec_info->view == ERROR_VIEW)
1688 goto end_it;
1689 spec_info->view = ERROR_VIEW;
1690 if (spec_info->display_widget)
1691 gtk_widget_destroy(spec_info->display_widget);
1692 sprintf(error_char, "slurm_load_node: %s",
1693 slurm_strerror(slurm_get_errno()));
1694 label = gtk_label_new(error_char);
1695 gtk_table_attach_defaults(popup_win->table,
1696 label,
1697 0, 1, 0, 1);
1698 gtk_widget_show(label);
1699 spec_info->display_widget = g_object_ref(label);
1700 return;
1701 }
1702 display_it:
1703
1704 info_list = create_node_info_list(node_info_ptr, false);
1705
1706 if (!info_list)
1707 return;
1708
1709 if (spec_info->view == ERROR_VIEW && spec_info->display_widget) {
1710 gtk_widget_destroy(spec_info->display_widget);
1711 spec_info->display_widget = NULL;
1712 }
1713 if (spec_info->type != INFO_PAGE && !spec_info->display_widget) {
1714 tree_view = create_treeview(local_display_data,
1715 &popup_win->grid_button_list);
1716 /*set multiple capability here*/
1717 gtk_tree_selection_set_mode(
1718 gtk_tree_view_get_selection(tree_view),
1719 GTK_SELECTION_MULTIPLE);
1720 spec_info->display_widget =
1721 g_object_ref(GTK_WIDGET(tree_view));
1722 gtk_table_attach_defaults(popup_win->table,
1723 GTK_WIDGET(tree_view),
1724 0, 1, 0, 1);
1725 /* Since this function sets the model of the tree_view to the
1726 * treestore we don't really care about the return value
1727 * On large clusters, sorting on the node name slows GTK down
1728 * by a large margin. */
1729 if (node_info_ptr->record_count > 1000)
1730 sort_key = -1;
1731 else
1732 sort_key = SORTID_NAME;
1733 create_treestore(tree_view, popup_win->display_data,
1734 SORTID_CNT, sort_key, SORTID_COLOR);
1735 }
1736
1737 setup_popup_grid_list(popup_win);
1738
1739 spec_info->view = INFO_VIEW;
1740 if (spec_info->type == INFO_PAGE) {
1741 _display_info_node(info_list, popup_win);
1742 goto end_it;
1743 }
1744
1745 setup_popup_grid_list(popup_win);
1746
1747 /* just linking to another list, don't free the inside, just
1748 the list */
1749 send_info_list = list_create(NULL);
1750 if (search_info->gchar_data) {
1751 hostlist = hostlist_create(search_info->gchar_data);
1752 host_itr = hostlist_iterator_create(hostlist);
1753 }
1754
1755 i = -1;
1756
1757 itr = list_iterator_create(info_list);
1758 while ((sview_node_info_ptr = list_next(itr))) {
1759 int found = 0;
1760 char *host = NULL;
1761 i++;
1762 node_ptr = sview_node_info_ptr->node_ptr;
1763
1764 switch(search_info->search_type) {
1765 case SEARCH_NODE_STATE:
1766 if (search_info->int_data == NO_VAL)
1767 continue;
1768 else if (search_info->int_data
1769 != node_ptr->node_state) {
1770 if (IS_NODE_MIXED(node_ptr)) {
1771 uint16_t alloc_cnt = 0;
1772 uint16_t idle_cnt = node_ptr->cpus;
1773 select_g_select_nodeinfo_get(
1774 node_ptr->select_nodeinfo,
1775 SELECT_NODEDATA_SUBCNT,
1776 NODE_STATE_ALLOCATED,
1777 &alloc_cnt);
1778 idle_cnt -= alloc_cnt;
1779 if ((search_info->int_data
1780 & NODE_STATE_BASE)
1781 == NODE_STATE_ALLOCATED) {
1782 if (alloc_cnt)
1783 break;
1784 } else if ((search_info->int_data
1785 & NODE_STATE_BASE)
1786 == NODE_STATE_IDLE) {
1787 if (idle_cnt)
1788 break;
1789 }
1790 }
1791 continue;
1792 }
1793 break;
1794 case SEARCH_NODE_NAME:
1795 default:
1796 if (!search_info->gchar_data)
1797 continue;
1798 while ((host = hostlist_next(host_itr))) {
1799 if (!xstrcmp(host, node_ptr->name)) {
1800 free(host);
1801 found = 1;
1802 break;
1803 }
1804 free(host);
1805 }
1806 hostlist_iterator_reset(host_itr);
1807
1808 if (!found)
1809 continue;
1810 break;
1811 }
1812 list_push(send_info_list, sview_node_info_ptr);
1813 change_grid_color(popup_win->grid_button_list,
1814 i, i, 0, true, 0);
1815 }
1816 list_iterator_destroy(itr);
1817 post_setup_popup_grid_list(popup_win);
1818
1819 if (search_info->gchar_data) {
1820 hostlist_iterator_destroy(host_itr);
1821 hostlist_destroy(hostlist);
1822 }
1823
1824 _update_info_node(send_info_list,
1825 GTK_TREE_VIEW(spec_info->display_widget));
1826 FREE_NULL_LIST(send_info_list);
1827 end_it:
1828 popup_win->toggled = 0;
1829 popup_win->force_refresh = 0;
1830
1831 return;
1832
1833 }
1834
set_menus_node(void * arg,void * arg2,GtkTreePath * path,int type)1835 extern void set_menus_node(void *arg, void *arg2, GtkTreePath *path, int type)
1836 {
1837 GtkTreeView *tree_view = (GtkTreeView *)arg;
1838 popup_info_t *popup_win = (popup_info_t *)arg;
1839 GtkMenu *menu = (GtkMenu *)arg2;
1840 List button_list = (List)arg2;
1841
1842 switch(type) {
1843 case TAB_CLICKED:
1844 make_fields_menu(NULL, menu, display_data_node, SORTID_CNT);
1845 break;
1846 case ROW_CLICKED:
1847 make_options_menu(tree_view, path, menu, options_data_node);
1848 break;
1849 case ROW_LEFT_CLICKED:
1850 {
1851 GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
1852 GtkTreeIter iter;
1853 if (!gtk_tree_model_get_iter(model, &iter, path)) {
1854 g_error("error getting iter from model\n");
1855 break;
1856 }
1857 highlight_grid(tree_view, SORTID_POS, (int)NO_VAL, button_list);
1858 break;
1859 }
1860 case FULL_CLICKED:
1861 {
1862 GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
1863 GtkTreeIter iter;
1864 if (!gtk_tree_model_get_iter(model, &iter, path)) {
1865 g_error("error getting iter from model\n");
1866 break;
1867 }
1868
1869 popup_all_node(model, &iter, INFO_PAGE);
1870
1871 break;
1872 }
1873 case POPUP_CLICKED:
1874 make_fields_menu(popup_win, menu,
1875 popup_win->display_data, SORTID_CNT);
1876 break;
1877 default:
1878 g_error("UNKNOWN type %d given to set_fields\n", type);
1879 }
1880 }
1881
popup_all_node(GtkTreeModel * model,GtkTreeIter * iter,int id)1882 extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id)
1883 {
1884 char *name = NULL, *cluster_name = NULL;
1885
1886 gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
1887 gtk_tree_model_get(model, iter, SORTID_CLUSTER_NAME, &cluster_name, -1);
1888 if (_DEBUG)
1889 g_print("popup_all_node: name = %s\n", name);
1890 popup_all_node_name(name, id, cluster_name);
1891 /* this name gets g_strdup'ed in the previous function */
1892 g_free(name);
1893 g_free(cluster_name);
1894 }
1895
popup_all_node_name(char * name,int id,char * cluster_name)1896 extern void popup_all_node_name(char *name, int id, char *cluster_name)
1897 {
1898 char title[100] = {0};
1899 ListIterator itr = NULL;
1900 popup_info_t *popup_win = NULL;
1901 GError *error = NULL;
1902
1903 switch(id) {
1904 case JOB_PAGE:
1905 snprintf(title, 100, "Job(s) with Node %s", name);
1906 break;
1907 case PART_PAGE:
1908 snprintf(title, 100, "Partition(s) with Node %s", name);
1909 break;
1910 case RESV_PAGE:
1911 snprintf(title, 100, "Reservation(s) with Node %s", name);
1912 break;
1913 case SUBMIT_PAGE:
1914 snprintf(title, 100, "Submit job on Node %s", name);
1915 break;
1916 case INFO_PAGE:
1917 snprintf(title, 100, "Full Info for Node %s", name);
1918 break;
1919 default:
1920 g_print("Node got %d\n", id);
1921 }
1922
1923 if (cluster_name && federation_name &&
1924 (cluster_flags & CLUSTER_FLAG_FED)) {
1925 char *tmp_cname =
1926 xstrdup_printf(" (%s:%s)",
1927 federation_name, cluster_name);
1928 strncat(title, tmp_cname, sizeof(title) - strlen(title) - 1);
1929 xfree(tmp_cname);
1930 }
1931
1932 itr = list_iterator_create(popup_list);
1933 while ((popup_win = list_next(itr))) {
1934 if (popup_win->spec_info)
1935 if (!xstrcmp(popup_win->spec_info->title, title)) {
1936 break;
1937 }
1938 }
1939 list_iterator_destroy(itr);
1940
1941 if (!popup_win) {
1942 if (id == INFO_PAGE)
1943 popup_win = create_popup_info(id, NODE_PAGE, title);
1944 else
1945 popup_win = create_popup_info(NODE_PAGE, id, title);
1946 popup_win->spec_info->search_info->gchar_data = g_strdup(name);
1947
1948 if (cluster_flags & CLUSTER_FLAG_FED)
1949 popup_win->spec_info->search_info->cluster_name =
1950 g_strdup(cluster_name);
1951 if (!sview_thread_new((gpointer)popup_thr, popup_win,
1952 false, &error)) {
1953 g_printerr ("Failed to create node popup thread: "
1954 "%s\n",
1955 error->message);
1956 return;
1957 }
1958 } else
1959 gtk_window_present(GTK_WINDOW(popup_win->popup));
1960 }
1961
admin_menu_node_name(char * name,GdkEventButton * event)1962 extern void admin_menu_node_name(char *name, GdkEventButton *event)
1963 {
1964 GtkMenu *menu = GTK_MENU(gtk_menu_new());
1965 display_data_t *display_data = options_data_node;
1966 GtkWidget *menuitem;
1967
1968 while (display_data++) {
1969 if (display_data->id == -1)
1970 break;
1971 if (!display_data->name)
1972 continue;
1973
1974 display_data->user_data = name;
1975 menuitem = gtk_menu_item_new_with_label(display_data->name);
1976 g_signal_connect(menuitem, "activate",
1977 G_CALLBACK(_selected_page),
1978 display_data);
1979 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1980 }
1981 gtk_widget_show_all(GTK_WIDGET(menu));
1982 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
1983 event ? event->button : 0,
1984 gdk_event_get_time((GdkEvent*)event));
1985 }
1986
select_admin_nodes(GtkTreeModel * model,GtkTreeIter * iter,display_data_t * display_data,uint32_t node_col,GtkTreeView * treeview)1987 extern void select_admin_nodes(GtkTreeModel *model,
1988 GtkTreeIter *iter,
1989 display_data_t *display_data,
1990 uint32_t node_col,
1991 GtkTreeView *treeview)
1992 {
1993 if (treeview) {
1994 char *old_value = NULL;
1995 hostlist_t hl = NULL;
1996 process_node_t process_node;
1997 memset(&process_node, 0, sizeof(process_node_t));
1998 if (node_col == NO_VAL)
1999 process_node.node_col = SORTID_NAME;
2000 else
2001 process_node.node_col = node_col;
2002
2003 gtk_tree_selection_selected_foreach(
2004 gtk_tree_view_get_selection(treeview),
2005 _process_each_node, &process_node);
2006 hl = hostlist_create(process_node.nodelist);
2007 hostlist_uniq(hl);
2008 hostlist_sort(hl);
2009 xfree(process_node.nodelist);
2010 process_node.nodelist = hostlist_ranged_string_xmalloc(hl);
2011 hostlist_destroy(hl);
2012
2013 if (!xstrcasecmp("Update Features", display_data->name)) {
2014 /* get old features */
2015 gtk_tree_model_get(model, iter, SORTID_AVAIL_FEATURES,
2016 &old_value, -1);
2017 } else if (!xstrcasecmp("Update Gres", display_data->name)) {
2018 /* get old gres */
2019 gtk_tree_model_get(model, iter, SORTID_GRES,
2020 &old_value, -1);
2021 }
2022 admin_node_name(process_node.nodelist, old_value,
2023 display_data->name);
2024 xfree(process_node.nodelist);
2025 if (old_value)
2026 g_free(old_value);
2027
2028
2029 }
2030 } /*select_admin_nodes ^^^*/
2031
admin_node_name(char * name,char * old_value,char * type)2032 extern void admin_node_name(char *name, char *old_value, char *type)
2033 {
2034 GtkWidget *popup = NULL;
2035
2036 if (cluster_flags & CLUSTER_FLAG_FED) {
2037 display_fed_disabled_popup(type);
2038 return;
2039 }
2040
2041 popup = gtk_dialog_new_with_buttons(
2042 type,
2043 GTK_WINDOW(main_window),
2044 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2045 NULL);
2046 gtk_window_set_type_hint(GTK_WINDOW(popup),
2047 GDK_WINDOW_TYPE_HINT_NORMAL);
2048 gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);
2049
2050 if (!xstrcasecmp("Update Available Features", type)
2051 || !xstrcasecmp("Update Node Features", type)
2052 || !xstrcasecmp("Update Midplane Features",
2053 type)) { /* update features */
2054 update_avail_features_node(GTK_DIALOG(popup), name, old_value);
2055 } else if (!xstrcasecmp("Update Active Features", type)) {
2056 update_active_features_node(GTK_DIALOG(popup), name, old_value);
2057 } else if (!xstrcasecmp("Update Gres", type)) { /* update gres */
2058 update_gres_node(GTK_DIALOG(popup), name, old_value);
2059 } else /* something that has to deal with a node state change */
2060 update_state_node(GTK_DIALOG(popup), name, type);
2061
2062 gtk_widget_destroy(popup);
2063
2064 return;
2065 }
2066
cluster_change_node(void)2067 extern void cluster_change_node(void)
2068 {
2069 display_data_t *display_data = display_data_node;
2070 while (display_data++) {
2071 if (display_data->id == -1)
2072 break;
2073 if (cluster_flags & CLUSTER_FLAG_FED) {
2074 switch(display_data->id) {
2075 case SORTID_CLUSTER_NAME:
2076 display_data->show = true;
2077 break;
2078 }
2079 } else {
2080 switch(display_data->id) {
2081 case SORTID_CLUSTER_NAME:
2082 display_data->show = false;
2083 break;
2084 }
2085 }
2086 }
2087
2088 get_info_node(NULL, NULL);
2089 }
2090