PageRenderTime 140ms CodeModel.GetById 26ms RepoModel.GetById 2ms app.codeStats 0ms

/src/sview/node_info.c

https://github.com/cfenoy/slurm
C | 1886 lines | 1587 code | 195 blank | 104 comment | 289 complexity | 1cb578c7296cc44ed9217a1a6f4f4811 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*****************************************************************************\
  2. * node_info.c - Functions related to node display
  3. * mode of sview.
  4. *****************************************************************************
  5. * Copyright (C) 2004-2007 The Regents of the University of California.
  6. * Copyright (C) 2008-2010 Lawrence Livermore National Security.
  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 <http://www.schedmd.com/slurmdocs/>.
  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. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  29. \*****************************************************************************/
  30. #include "src/sview/sview.h"
  31. #define _DEBUG 0
  32. #define ECLIPSE_RT 0
  33. int cpus_per_node = 1;
  34. int g_node_scaling = 1;
  35. //static int _l_topo_color_ndx = MAKE_TOPO_1;
  36. //static int _l_sw_color_ndx = 0;
  37. /* These need to be in alpha order (except POS and CNT) */
  38. enum {
  39. SORTID_POS = POS_LOC,
  40. SORTID_ARCH,
  41. SORTID_BOARDS,
  42. SORTID_BOOT_TIME,
  43. SORTID_COLOR,
  44. SORTID_CPUS,
  45. SORTID_CPU_LOAD,
  46. SORTID_CORES,
  47. SORTID_ERR_CPUS,
  48. SORTID_FEATURES,
  49. SORTID_GRES,
  50. SORTID_NAME,
  51. SORTID_NODE_ADDR,
  52. SORTID_NODE_HOSTNAME,
  53. SORTID_MEMORY, /* RealMemory */
  54. SORTID_REASON,
  55. SORTID_RACK_MP,
  56. SORTID_SLURMD_START_TIME,
  57. SORTID_SOCKETS,
  58. SORTID_STATE,
  59. SORTID_STATE_NUM,
  60. SORTID_THREADS,
  61. SORTID_DISK, /* TmpDisk */
  62. SORTID_UPDATED,
  63. SORTID_USED_CPUS,
  64. SORTID_WEIGHT,
  65. SORTID_CNT
  66. };
  67. typedef struct {
  68. int node_col;
  69. char *nodelist;
  70. } process_node_t;
  71. /*these are the settings to apply for the user
  72. * on the first startup after a fresh slurm install.*/
  73. static char *_initial_page_opts = "Name,RackMidplane,State,CPU_Count,"
  74. "Used_CPU_Count,Error_CPU_Count,CoresPerSocket,Sockets,ThreadsPerCore,"
  75. "Real_Memory,Tmp_Disk";
  76. static display_data_t display_data_node[] = {
  77. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE, refresh_node,
  78. create_model_node, admin_edit_node},
  79. {G_TYPE_STRING, SORTID_NAME, "Name", FALSE, EDIT_NONE, refresh_node,
  80. create_model_node, admin_edit_node},
  81. {G_TYPE_STRING, SORTID_COLOR, NULL, TRUE, EDIT_COLOR, refresh_node,
  82. create_model_node, admin_edit_node},
  83. #ifdef HAVE_BG
  84. {G_TYPE_STRING, SORTID_RACK_MP, "RackMidplane", FALSE, EDIT_NONE,
  85. refresh_node, create_model_node, admin_edit_node},
  86. #else
  87. {G_TYPE_STRING, SORTID_RACK_MP, NULL, TRUE, EDIT_NONE, refresh_node,
  88. create_model_node, admin_edit_node},
  89. #endif
  90. {G_TYPE_STRING, SORTID_NODE_ADDR, "NodeAddr", FALSE, EDIT_NONE,
  91. refresh_node, create_model_node, admin_edit_node},
  92. {G_TYPE_STRING, SORTID_NODE_HOSTNAME, "NodeHostName", FALSE, EDIT_NONE,
  93. refresh_node, create_model_node, admin_edit_node},
  94. {G_TYPE_STRING, SORTID_STATE, "State", FALSE, EDIT_MODEL, refresh_node,
  95. create_model_node, admin_edit_node},
  96. {G_TYPE_INT, SORTID_STATE_NUM, NULL, FALSE, EDIT_NONE, refresh_node,
  97. create_model_node, admin_edit_node},
  98. {G_TYPE_STRING, SORTID_CPUS, "CPU Count", FALSE,
  99. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  100. {G_TYPE_STRING, SORTID_USED_CPUS, "Used CPU Count", FALSE,
  101. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  102. {G_TYPE_STRING, SORTID_ERR_CPUS, "Error CPU Count", FALSE,
  103. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  104. {G_TYPE_INT, SORTID_BOARDS, "Boards", FALSE,
  105. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  106. {G_TYPE_INT, SORTID_SOCKETS, "Sockets", FALSE,
  107. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  108. {G_TYPE_INT, SORTID_CORES, "CoresPerSocket", FALSE,
  109. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  110. {G_TYPE_INT, SORTID_THREADS, "ThreadsPerCore", FALSE,
  111. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  112. {G_TYPE_STRING, SORTID_MEMORY, "Real Memory", FALSE,
  113. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  114. {G_TYPE_STRING, SORTID_DISK, "Tmp Disk", FALSE, EDIT_NONE, refresh_node,
  115. create_model_node, admin_edit_node},
  116. {G_TYPE_INT, SORTID_WEIGHT,"Weight", FALSE, EDIT_NONE, refresh_node,
  117. create_model_node, admin_edit_node},
  118. {G_TYPE_STRING, SORTID_CPU_LOAD, "CPU Load", FALSE, EDIT_NONE,
  119. refresh_node, create_model_node, admin_edit_node},
  120. {G_TYPE_STRING, SORTID_ARCH, "Arch", FALSE,
  121. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  122. {G_TYPE_STRING, SORTID_FEATURES, "Features", FALSE,
  123. EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node},
  124. {G_TYPE_STRING, SORTID_GRES, "Gres", FALSE,
  125. EDIT_TEXTBOX, refresh_node, create_model_node, admin_edit_node},
  126. {G_TYPE_STRING, SORTID_BOOT_TIME, "BootTime", FALSE,
  127. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  128. {G_TYPE_STRING, SORTID_SLURMD_START_TIME, "SlurmdStartTime", FALSE,
  129. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  130. {G_TYPE_STRING, SORTID_REASON, "Reason", FALSE,
  131. EDIT_NONE, refresh_node, create_model_node, admin_edit_node},
  132. {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, EDIT_NONE, refresh_node,
  133. create_model_node, admin_edit_node},
  134. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  135. };
  136. static display_data_t options_data_node[] = {
  137. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE},
  138. {G_TYPE_STRING, INFO_PAGE, "Full Info", TRUE, NODE_PAGE},
  139. #ifdef HAVE_BG
  140. {G_TYPE_STRING, NODE_PAGE, "Drain Midplane", TRUE, ADMIN_PAGE},
  141. {G_TYPE_STRING, NODE_PAGE, "Resume Midplane", TRUE, ADMIN_PAGE},
  142. {G_TYPE_STRING, NODE_PAGE, "Set Midplane Down",
  143. TRUE, ADMIN_PAGE},
  144. {G_TYPE_STRING, NODE_PAGE, "Make Midplane Idle",
  145. TRUE, ADMIN_PAGE},
  146. #else
  147. {G_TYPE_STRING, NODE_PAGE, "Drain Node", TRUE, ADMIN_PAGE},
  148. {G_TYPE_STRING, NODE_PAGE, "Resume Node", TRUE, ADMIN_PAGE},
  149. {G_TYPE_STRING, NODE_PAGE, "Set Node(s) Down", TRUE, ADMIN_PAGE},
  150. {G_TYPE_STRING, NODE_PAGE, "Make Node(s) Idle", TRUE, ADMIN_PAGE},
  151. #endif
  152. {G_TYPE_STRING, NODE_PAGE, "Update Features", TRUE, ADMIN_PAGE},
  153. {G_TYPE_STRING, NODE_PAGE, "Update Gres", TRUE, ADMIN_PAGE},
  154. {G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, NODE_PAGE},
  155. #ifdef HAVE_BG
  156. {G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, NODE_PAGE},
  157. #else
  158. {G_TYPE_STRING, BLOCK_PAGE, NULL, TRUE, NODE_PAGE},
  159. #endif
  160. {G_TYPE_STRING, PART_PAGE, "Partitions", TRUE, NODE_PAGE},
  161. {G_TYPE_STRING, RESV_PAGE, "Reservations", TRUE, NODE_PAGE},
  162. //{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", FALSE, NODE_PAGE},
  163. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  164. };
  165. static display_data_t *local_display_data = NULL;
  166. static void _layout_node_record(GtkTreeView *treeview,
  167. sview_node_info_t *sview_node_info_ptr,
  168. int update)
  169. {
  170. char tmp_cnt[50];
  171. char *upper = NULL, *lower = NULL;
  172. GtkTreeIter iter;
  173. uint16_t err_cpus = 0, alloc_cpus = 0;
  174. node_info_t *node_ptr = sview_node_info_ptr->node_ptr;
  175. int idle_cpus = node_ptr->cpus;
  176. GtkTreeStore *treestore =
  177. GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
  178. if (!treestore)
  179. return;
  180. add_display_treestore_line(update, treestore, &iter,
  181. find_col_name(display_data_node,
  182. SORTID_NAME),
  183. node_ptr->name);
  184. if (sview_node_info_ptr->rack_mp)
  185. add_display_treestore_line(update, treestore, &iter,
  186. find_col_name(display_data_node,
  187. SORTID_RACK_MP),
  188. sview_node_info_ptr->rack_mp);
  189. add_display_treestore_line(update, treestore, &iter,
  190. find_col_name(display_data_node,
  191. SORTID_NODE_ADDR),
  192. node_ptr->node_addr);
  193. add_display_treestore_line(update, treestore, &iter,
  194. find_col_name(display_data_node,
  195. SORTID_NODE_HOSTNAME),
  196. node_ptr->node_hostname);
  197. convert_num_unit((float)node_ptr->cpus, tmp_cnt, sizeof(tmp_cnt),
  198. UNIT_NONE);
  199. add_display_treestore_line(update, treestore, &iter,
  200. find_col_name(display_data_node,
  201. SORTID_CPUS),
  202. tmp_cnt);
  203. if (node_ptr->cpu_load == NO_VAL) {
  204. snprintf(tmp_cnt, sizeof(tmp_cnt), "N/A");
  205. } else {
  206. snprintf(tmp_cnt, sizeof(tmp_cnt), "%.2f",
  207. (node_ptr->cpu_load / 100.0));
  208. }
  209. add_display_treestore_line(update, treestore, &iter,
  210. find_col_name(display_data_node,
  211. SORTID_CPU_LOAD),
  212. tmp_cnt);
  213. select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
  214. SELECT_NODEDATA_SUBCNT,
  215. NODE_STATE_ALLOCATED,
  216. &alloc_cpus);
  217. if (cluster_flags & CLUSTER_FLAG_BG) {
  218. if (!alloc_cpus
  219. && ((node_ptr->node_state & NODE_STATE_ALLOCATED)
  220. || (node_ptr->node_state & NODE_STATE_COMPLETING)))
  221. alloc_cpus = node_ptr->cpus;
  222. else
  223. alloc_cpus *= cpus_per_node;
  224. }
  225. idle_cpus -= alloc_cpus;
  226. convert_num_unit((float)alloc_cpus, tmp_cnt,
  227. sizeof(tmp_cnt), UNIT_NONE);
  228. add_display_treestore_line(update, treestore, &iter,
  229. find_col_name(display_data_node,
  230. SORTID_USED_CPUS),
  231. tmp_cnt);
  232. select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
  233. SELECT_NODEDATA_SUBCNT,
  234. NODE_STATE_ERROR,
  235. &err_cpus);
  236. if (cluster_flags & CLUSTER_FLAG_BG)
  237. err_cpus *= cpus_per_node;
  238. idle_cpus -= err_cpus;
  239. convert_num_unit((float)err_cpus, tmp_cnt, sizeof(tmp_cnt), UNIT_NONE);
  240. add_display_treestore_line(update, treestore, &iter,
  241. find_col_name(display_data_node,
  242. SORTID_ERR_CPUS),
  243. tmp_cnt);
  244. upper = node_state_string(node_ptr->node_state);
  245. lower = str_tolower(upper);
  246. add_display_treestore_line(update, treestore, &iter,
  247. find_col_name(display_data_node,
  248. SORTID_STATE),
  249. lower);
  250. xfree(lower);
  251. convert_num_unit((float)node_ptr->boards, tmp_cnt, sizeof(tmp_cnt),
  252. UNIT_NONE);
  253. add_display_treestore_line(update, treestore, &iter,
  254. find_col_name(display_data_node,
  255. SORTID_BOARDS),
  256. tmp_cnt);
  257. convert_num_unit((float)node_ptr->sockets, tmp_cnt, sizeof(tmp_cnt),
  258. UNIT_NONE);
  259. add_display_treestore_line(update, treestore, &iter,
  260. find_col_name(display_data_node,
  261. SORTID_SOCKETS),
  262. tmp_cnt);
  263. convert_num_unit((float)node_ptr->cores, tmp_cnt, sizeof(tmp_cnt),
  264. UNIT_NONE);
  265. add_display_treestore_line(update, treestore, &iter,
  266. find_col_name(display_data_node,
  267. SORTID_CORES),
  268. tmp_cnt);
  269. convert_num_unit((float)node_ptr->threads, tmp_cnt, sizeof(tmp_cnt),
  270. UNIT_NONE);
  271. add_display_treestore_line(update, treestore, &iter,
  272. find_col_name(display_data_node,
  273. SORTID_THREADS),
  274. tmp_cnt);
  275. convert_num_unit((float)node_ptr->real_memory, tmp_cnt, sizeof(tmp_cnt),
  276. UNIT_MEGA);
  277. add_display_treestore_line(update, treestore, &iter,
  278. find_col_name(display_data_node,
  279. SORTID_MEMORY),
  280. tmp_cnt);
  281. convert_num_unit((float)node_ptr->tmp_disk, tmp_cnt, sizeof(tmp_cnt),
  282. UNIT_MEGA);
  283. add_display_treestore_line(update, treestore, &iter,
  284. find_col_name(display_data_node,
  285. SORTID_DISK),
  286. tmp_cnt);
  287. snprintf(tmp_cnt, sizeof(tmp_cnt), "%u", node_ptr->weight);
  288. add_display_treestore_line(update, treestore, &iter,
  289. find_col_name(display_data_node,
  290. SORTID_WEIGHT),
  291. tmp_cnt);
  292. add_display_treestore_line(update, treestore, &iter,
  293. find_col_name(display_data_node,
  294. SORTID_ARCH),
  295. node_ptr->arch);
  296. add_display_treestore_line(update, treestore, &iter,
  297. find_col_name(display_data_node,
  298. SORTID_FEATURES),
  299. node_ptr->features);
  300. add_display_treestore_line(update, treestore, &iter,
  301. find_col_name(display_data_node,
  302. SORTID_GRES),
  303. node_ptr->gres);
  304. add_display_treestore_line(update, treestore, &iter,
  305. find_col_name(display_data_node,
  306. SORTID_BOOT_TIME),
  307. sview_node_info_ptr->boot_time);
  308. add_display_treestore_line(update, treestore, &iter,
  309. find_col_name(display_data_node,
  310. SORTID_SLURMD_START_TIME),
  311. sview_node_info_ptr->slurmd_start_time);
  312. add_display_treestore_line(update, treestore, &iter,
  313. find_col_name(display_data_node,
  314. SORTID_REASON),
  315. sview_node_info_ptr->reason);
  316. return;
  317. }
  318. static void _update_node_record(sview_node_info_t *sview_node_info_ptr,
  319. GtkTreeStore *treestore)
  320. {
  321. uint16_t alloc_cpus = 0, err_cpus = 0, idle_cpus;
  322. node_info_t *node_ptr = sview_node_info_ptr->node_ptr;
  323. char tmp_disk[20], tmp_cpus[20], tmp_err_cpus[20],
  324. tmp_mem[20], tmp_used_cpus[20], tmp_cpu_load[20];
  325. char *tmp_state_lower, *tmp_state_upper;
  326. if (node_ptr->cpu_load == NO_VAL) {
  327. strcpy(tmp_cpu_load, "N/A");
  328. } else {
  329. snprintf(tmp_cpu_load, sizeof(tmp_cpu_load),
  330. "%.2f", (node_ptr->cpu_load / 100.0));
  331. }
  332. convert_num_unit((float)node_ptr->cpus, tmp_cpus,
  333. sizeof(tmp_cpus), UNIT_NONE);
  334. select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
  335. SELECT_NODEDATA_SUBCNT,
  336. NODE_STATE_ALLOCATED,
  337. &alloc_cpus);
  338. if (cluster_flags & CLUSTER_FLAG_BG) {
  339. if (!alloc_cpus &&
  340. (IS_NODE_ALLOCATED(node_ptr) ||
  341. IS_NODE_COMPLETING(node_ptr)))
  342. alloc_cpus = node_ptr->cpus;
  343. else
  344. alloc_cpus *= cpus_per_node;
  345. }
  346. idle_cpus = node_ptr->cpus - alloc_cpus;
  347. convert_num_unit((float)alloc_cpus, tmp_used_cpus,
  348. sizeof(tmp_used_cpus), UNIT_NONE);
  349. select_g_select_nodeinfo_get(node_ptr->select_nodeinfo,
  350. SELECT_NODEDATA_SUBCNT,
  351. NODE_STATE_ERROR,
  352. &err_cpus);
  353. if (cluster_flags & CLUSTER_FLAG_BG)
  354. err_cpus *= cpus_per_node;
  355. idle_cpus -= err_cpus;
  356. convert_num_unit((float)err_cpus, tmp_err_cpus, sizeof(tmp_err_cpus),
  357. UNIT_NONE);
  358. if (IS_NODE_DRAIN(node_ptr)) {
  359. /* don't worry about mixed since the
  360. * whole node is being drained. */
  361. } else if ((alloc_cpus && err_cpus) ||
  362. (idle_cpus && (idle_cpus != node_ptr->cpus))) {
  363. node_ptr->node_state &= NODE_STATE_FLAGS;
  364. node_ptr->node_state |= NODE_STATE_MIXED;
  365. }
  366. tmp_state_upper = node_state_string(node_ptr->node_state);
  367. tmp_state_lower = str_tolower(tmp_state_upper);
  368. convert_num_unit((float)node_ptr->real_memory, tmp_mem, sizeof(tmp_mem),
  369. UNIT_MEGA);
  370. convert_num_unit((float)node_ptr->tmp_disk, tmp_disk, sizeof(tmp_disk),
  371. UNIT_MEGA);
  372. /* Combining these records provides a slight performance improvement */
  373. gtk_tree_store_set(treestore, &sview_node_info_ptr->iter_ptr,
  374. SORTID_ARCH, node_ptr->arch,
  375. SORTID_BOARDS, node_ptr->boards,
  376. SORTID_BOOT_TIME, sview_node_info_ptr->boot_time,
  377. SORTID_COLOR,
  378. sview_colors[sview_node_info_ptr->pos
  379. % sview_colors_cnt],
  380. SORTID_CORES, node_ptr->cores,
  381. SORTID_CPUS, tmp_cpus,
  382. SORTID_CPU_LOAD, tmp_cpu_load,
  383. SORTID_DISK, tmp_disk,
  384. SORTID_ERR_CPUS, tmp_err_cpus,
  385. SORTID_FEATURES, node_ptr->features,
  386. SORTID_GRES, node_ptr->gres,
  387. SORTID_MEMORY, tmp_mem,
  388. SORTID_NAME, node_ptr->name,
  389. SORTID_NODE_ADDR, node_ptr->node_addr,
  390. SORTID_NODE_HOSTNAME, node_ptr->node_hostname,
  391. SORTID_RACK_MP, sview_node_info_ptr->rack_mp,
  392. SORTID_REASON, sview_node_info_ptr->reason,
  393. SORTID_SLURMD_START_TIME,
  394. sview_node_info_ptr->slurmd_start_time,
  395. SORTID_SOCKETS, node_ptr->sockets,
  396. SORTID_STATE, tmp_state_lower,
  397. SORTID_STATE_NUM, node_ptr->node_state,
  398. SORTID_THREADS, node_ptr->threads,
  399. SORTID_USED_CPUS, tmp_used_cpus,
  400. SORTID_WEIGHT, node_ptr->weight,
  401. SORTID_UPDATED, 1,
  402. -1);
  403. xfree(tmp_state_lower);
  404. return;
  405. }
  406. static void _append_node_record(sview_node_info_t *sview_node_info,
  407. GtkTreeStore *treestore)
  408. {
  409. gtk_tree_store_append(treestore, &sview_node_info->iter_ptr, NULL);
  410. gtk_tree_store_set(treestore, &sview_node_info->iter_ptr, SORTID_POS,
  411. sview_node_info->pos, -1);
  412. _update_node_record(sview_node_info, treestore);
  413. }
  414. static void _update_info_node(List info_list, GtkTreeView *tree_view)
  415. {
  416. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  417. static GtkTreeModel *last_model = NULL;
  418. node_info_t *node_ptr = NULL;
  419. char *name;
  420. ListIterator itr = NULL;
  421. sview_node_info_t *sview_node_info = NULL;
  422. set_for_update(model, SORTID_UPDATED);
  423. itr = list_iterator_create(info_list);
  424. while ((sview_node_info = (sview_node_info_t*) list_next(itr))) {
  425. node_ptr = sview_node_info->node_ptr;
  426. /* This means the tree_store changed (added new column
  427. or something). */
  428. if (last_model != model)
  429. sview_node_info->iter_set = false;
  430. if (sview_node_info->iter_set) {
  431. gtk_tree_model_get(model, &sview_node_info->iter_ptr,
  432. SORTID_NAME, &name, -1);
  433. if (strcmp(name, node_ptr->name)) { /* Bad pointer */
  434. sview_node_info->iter_set = false;
  435. //g_print("bad node iter pointer\n");
  436. }
  437. g_free(name);
  438. }
  439. if (sview_node_info->iter_set) {
  440. _update_node_record(sview_node_info,
  441. GTK_TREE_STORE(model));
  442. } else {
  443. GtkTreePath *path = gtk_tree_path_new_first();
  444. /* get the iter, or find out the list is empty
  445. * goto add */
  446. if (gtk_tree_model_get_iter(
  447. model, &sview_node_info->iter_ptr, path)) {
  448. do {
  449. /* search for the node name and check
  450. * to see if it is in the list */
  451. gtk_tree_model_get(
  452. model,
  453. &sview_node_info->iter_ptr,
  454. SORTID_NAME,
  455. &name, -1);
  456. if (name && node_ptr->name &&
  457. !strcmp(name, node_ptr->name)) {
  458. /* update with new info */
  459. g_free(name);
  460. _update_node_record(
  461. sview_node_info,
  462. GTK_TREE_STORE(model));
  463. sview_node_info->iter_set = 1;
  464. break;
  465. }
  466. g_free(name);
  467. } while (gtk_tree_model_iter_next(
  468. model,
  469. &sview_node_info->iter_ptr));
  470. }
  471. if (!sview_node_info->iter_set) {
  472. _append_node_record(sview_node_info,
  473. GTK_TREE_STORE(model));
  474. sview_node_info->iter_set = true;
  475. }
  476. gtk_tree_path_free(path);
  477. }
  478. }
  479. list_iterator_destroy(itr);
  480. /* remove all old nodes */
  481. remove_old(model, SORTID_UPDATED);
  482. last_model = model;
  483. }
  484. static void _node_info_list_del(void *object)
  485. {
  486. sview_node_info_t *sview_node_info = (sview_node_info_t *)object;
  487. if (sview_node_info) {
  488. xfree(sview_node_info->slurmd_start_time);
  489. xfree(sview_node_info->boot_time);
  490. xfree(sview_node_info->rack_mp);
  491. xfree(sview_node_info->reason);
  492. xfree(sview_node_info);
  493. }
  494. }
  495. static void _display_info_node(List info_list, popup_info_t *popup_win)
  496. {
  497. specific_info_t *spec_info = popup_win->spec_info;
  498. char *name = (char *)spec_info->search_info->gchar_data;
  499. int found = 0;
  500. node_info_t *node_ptr = NULL;
  501. GtkTreeView *treeview = NULL;
  502. int update = 0;
  503. ListIterator itr = NULL;
  504. sview_node_info_t *sview_node_info = NULL;
  505. int i = -1;
  506. if (!spec_info->search_info->gchar_data) {
  507. goto finished;
  508. }
  509. need_refresh:
  510. if (!spec_info->display_widget) {
  511. treeview = create_treeview_2cols_attach_to_table(
  512. popup_win->table);
  513. spec_info->display_widget =
  514. gtk_widget_ref(GTK_WIDGET(treeview));
  515. } else {
  516. treeview = GTK_TREE_VIEW(spec_info->display_widget);
  517. update = 1;
  518. }
  519. itr = list_iterator_create(info_list);
  520. while ((sview_node_info = (sview_node_info_t*) list_next(itr))) {
  521. node_ptr = sview_node_info->node_ptr;
  522. i++;
  523. if (!strcmp(node_ptr->name, name)) {
  524. change_grid_color(popup_win->grid_button_list,
  525. i, i, i, true, 0);
  526. _layout_node_record(treeview, sview_node_info, update);
  527. found = 1;
  528. break;
  529. }
  530. }
  531. list_iterator_destroy(itr);
  532. if (!found) {
  533. if (!popup_win->not_found) {
  534. char *temp;
  535. GtkTreeIter iter;
  536. GtkTreeModel *model = NULL;
  537. if (cluster_flags & CLUSTER_FLAG_BG)
  538. temp = "MIDPLANE NOT FOUND\n";
  539. else
  540. temp = "NODE NOT FOUND\n";
  541. /* only time this will be run so no update */
  542. model = gtk_tree_view_get_model(treeview);
  543. add_display_treestore_line(0,
  544. GTK_TREE_STORE(model),
  545. &iter,
  546. temp, "");
  547. }
  548. popup_win->not_found = true;
  549. } else {
  550. if (popup_win->not_found) {
  551. popup_win->not_found = false;
  552. gtk_widget_destroy(spec_info->display_widget);
  553. goto need_refresh;
  554. }
  555. }
  556. gtk_widget_show(spec_info->display_widget);
  557. finished:
  558. return;
  559. }
  560. static void _selected_page(GtkMenuItem *menuitem,
  561. display_data_t *display_data)
  562. {
  563. switch(display_data->extra) {
  564. case NODE_PAGE:
  565. popup_all_node_name(display_data->user_data, display_data->id);
  566. break;
  567. case ADMIN_PAGE:
  568. admin_node_name(display_data->user_data,
  569. NULL, display_data->name);
  570. break;
  571. default:
  572. g_print("node got %d %d\n", display_data->extra,
  573. display_data->id);
  574. }
  575. }
  576. static void _process_each_node(GtkTreeModel *model, GtkTreePath *path,
  577. GtkTreeIter *iter, gpointer userdata)
  578. {
  579. char *name = NULL;
  580. process_node_t *process_node = userdata;
  581. gtk_tree_model_get(model, iter, process_node->node_col, &name, -1);
  582. if (process_node->nodelist)
  583. xstrfmtcat(process_node->nodelist, ",%s", name);
  584. else
  585. process_node->nodelist = xstrdup(name);
  586. g_free(name);
  587. }
  588. /*process_each_node ^^^*/
  589. extern void refresh_node(GtkAction *action, gpointer user_data)
  590. {
  591. popup_info_t *popup_win = (popup_info_t *)user_data;
  592. xassert(popup_win);
  593. xassert(popup_win->spec_info);
  594. xassert(popup_win->spec_info->title);
  595. popup_win->force_refresh = 1;
  596. specific_info_node(popup_win);
  597. }
  598. /* don't destroy the list from this function */
  599. extern List create_node_info_list(node_info_msg_t *node_info_ptr,
  600. bool by_partition)
  601. {
  602. static List info_list = NULL;
  603. static node_info_msg_t *last_node_info_ptr = NULL;
  604. int i = 0;
  605. sview_node_info_t *sview_node_info_ptr = NULL;
  606. node_info_t *node_ptr = NULL;
  607. char user[32], time_str[32];
  608. if (!by_partition) {
  609. if (!node_info_ptr
  610. || (info_list && (node_info_ptr == last_node_info_ptr)))
  611. goto update_color;
  612. }
  613. last_node_info_ptr = node_info_ptr;
  614. if (info_list)
  615. list_flush(info_list);
  616. else
  617. info_list = list_create(_node_info_list_del);
  618. if (!info_list) {
  619. g_print("malloc error\n");
  620. return NULL;
  621. }
  622. for (i=0; i<node_info_ptr->record_count; i++) {
  623. char *select_reason_str = NULL;
  624. node_ptr = &(node_info_ptr->node_array[i]);
  625. if (!node_ptr->name || (node_ptr->name[0] == '\0'))
  626. continue;
  627. /* constrain list to included partitions' nodes */
  628. /* and there are excluded values to process */
  629. /* and user has not requested to show hidden */
  630. /* if (by_partition && apply_partition_check */
  631. /* && !working_sview_config.show_hidden */
  632. /* && !check_part_includes_node(i)) */
  633. /* continue; */
  634. sview_node_info_ptr = xmalloc(sizeof(sview_node_info_t));
  635. list_append(info_list, sview_node_info_ptr);
  636. sview_node_info_ptr->node_ptr = node_ptr;
  637. sview_node_info_ptr->pos = i;
  638. slurm_get_select_nodeinfo(node_ptr->select_nodeinfo,
  639. SELECT_NODEDATA_RACK_MP,
  640. 0, &sview_node_info_ptr->rack_mp);
  641. if (node_ptr->reason &&
  642. (node_ptr->reason_uid != NO_VAL) && node_ptr->reason_time) {
  643. struct passwd *pw = NULL;
  644. if ((pw=getpwuid(node_ptr->reason_uid)))
  645. snprintf(user, sizeof(user), "%s", pw->pw_name);
  646. else
  647. snprintf(user, sizeof(user), "Unk(%u)",
  648. node_ptr->reason_uid);
  649. slurm_make_time_str(&node_ptr->reason_time,
  650. time_str, sizeof(time_str));
  651. sview_node_info_ptr->reason = xstrdup_printf(
  652. "%s [%s@%s]", node_ptr->reason, user, time_str);
  653. } else if (node_ptr->reason)
  654. sview_node_info_ptr->reason = xstrdup(node_ptr->reason);
  655. slurm_get_select_nodeinfo(node_ptr->select_nodeinfo,
  656. SELECT_NODEDATA_EXTRA_INFO,
  657. 0, &select_reason_str);
  658. if (select_reason_str && select_reason_str[0]) {
  659. if (sview_node_info_ptr->reason)
  660. xstrfmtcat(sview_node_info_ptr->reason, "\n%s",
  661. select_reason_str);
  662. else {
  663. sview_node_info_ptr->reason = select_reason_str;
  664. select_reason_str = NULL;
  665. }
  666. }
  667. xfree(select_reason_str);
  668. if (node_ptr->boot_time) {
  669. slurm_make_time_str(&node_ptr->boot_time,
  670. time_str, sizeof(time_str));
  671. sview_node_info_ptr->boot_time = xstrdup(time_str);
  672. }
  673. if (node_ptr->slurmd_start_time) {
  674. slurm_make_time_str(&node_ptr->slurmd_start_time,
  675. time_str, sizeof(time_str));
  676. sview_node_info_ptr->slurmd_start_time =
  677. xstrdup(time_str);
  678. }
  679. }
  680. update_color:
  681. return info_list;
  682. }
  683. extern int get_new_info_node(node_info_msg_t **info_ptr, int force)
  684. {
  685. node_info_msg_t *new_node_ptr = NULL;
  686. uint16_t show_flags = 0;
  687. int error_code = SLURM_NO_CHANGE_IN_DATA;
  688. time_t now = time(NULL), delay;
  689. static time_t last;
  690. static bool changed = 0;
  691. static uint16_t last_flags = 0;
  692. delay = now - last;
  693. if (delay < 2) {
  694. /* Avoid re-loading node information within 2 secs as the data
  695. * may still be in use. If we load new node data and free the
  696. * old data while it it still in use, the result is likely
  697. * invalid memory references. */
  698. force = 0;
  699. /* FIXME: Add an "in use" flag, copy the data, or otherwise
  700. * permit the timely loading of new node information. */
  701. }
  702. if (g_node_info_ptr && !force &&
  703. (delay < working_sview_config.refresh_delay)) {
  704. if (*info_ptr != g_node_info_ptr)
  705. error_code = SLURM_SUCCESS;
  706. *info_ptr = g_node_info_ptr;
  707. return error_code;
  708. }
  709. last = now;
  710. //if (working_sview_config.show_hidden)
  711. show_flags |= SHOW_ALL;
  712. if (g_node_info_ptr) {
  713. if (show_flags != last_flags)
  714. g_node_info_ptr->last_update = 0;
  715. error_code = slurm_load_node(g_node_info_ptr->last_update,
  716. &new_node_ptr, show_flags);
  717. if (error_code == SLURM_SUCCESS) {
  718. slurm_free_node_info_msg(g_node_info_ptr);
  719. changed = 1;
  720. } else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) {
  721. error_code = SLURM_NO_CHANGE_IN_DATA;
  722. new_node_ptr = g_node_info_ptr;
  723. changed = 0;
  724. }
  725. } else {
  726. new_node_ptr = NULL;
  727. error_code = slurm_load_node((time_t) NULL, &new_node_ptr,
  728. show_flags);
  729. changed = 1;
  730. }
  731. last_flags = show_flags;
  732. g_node_info_ptr = new_node_ptr;
  733. if (g_node_info_ptr && (*info_ptr != g_node_info_ptr))
  734. error_code = SLURM_SUCCESS;
  735. if (new_node_ptr && new_node_ptr->node_array && changed) {
  736. int i;
  737. node_info_t *node_ptr = NULL;
  738. uint16_t err_cpus = 0, alloc_cpus = 0;
  739. int idle_cpus;
  740. g_node_scaling = new_node_ptr->node_scaling;
  741. cpus_per_node =
  742. new_node_ptr->node_array[0].cpus / g_node_scaling;
  743. for (i=0; i<g_node_info_ptr->record_count; i++) {
  744. node_ptr = &(g_node_info_ptr->node_array[i]);
  745. if (!node_ptr->name || (node_ptr->name[0] == '\0'))
  746. continue; /* bad node */
  747. idle_cpus = node_ptr->cpus;
  748. slurm_get_select_nodeinfo(
  749. node_ptr->select_nodeinfo,
  750. SELECT_NODEDATA_SUBCNT,
  751. NODE_STATE_ALLOCATED,
  752. &alloc_cpus);
  753. if (cluster_flags & CLUSTER_FLAG_BG) {
  754. if (!alloc_cpus
  755. && (IS_NODE_ALLOCATED(node_ptr)
  756. || IS_NODE_COMPLETING(node_ptr)))
  757. alloc_cpus = node_ptr->cpus;
  758. else
  759. alloc_cpus *= cpus_per_node;
  760. }
  761. idle_cpus -= alloc_cpus;
  762. slurm_get_select_nodeinfo(
  763. node_ptr->select_nodeinfo,
  764. SELECT_NODEDATA_SUBCNT,
  765. NODE_STATE_ERROR,
  766. &err_cpus);
  767. if (cluster_flags & CLUSTER_FLAG_BG)
  768. err_cpus *= cpus_per_node;
  769. idle_cpus -= err_cpus;
  770. if (IS_NODE_DRAIN(node_ptr)) {
  771. /* don't worry about mixed since the
  772. whole node is being drained. */
  773. } else if ((alloc_cpus && err_cpus) ||
  774. (idle_cpus &&
  775. (idle_cpus != node_ptr->cpus))) {
  776. node_ptr->node_state &= NODE_STATE_FLAGS;
  777. if (err_cpus)
  778. node_ptr->node_state
  779. |= NODE_STATE_ERROR;
  780. node_ptr->node_state |= NODE_STATE_MIXED;
  781. } else if (err_cpus) {
  782. node_ptr->node_state &= NODE_STATE_FLAGS;
  783. node_ptr->node_state |= NODE_STATE_ERROR;
  784. }
  785. /* if (alloc_cpus && err_cpus && !idle_cpus) { */
  786. /* node_ptr->node_state &= NODE_STATE_FLAGS; */
  787. /* node_ptr->node_state |= NODE_STATE_AE; */
  788. /* } else if (alloc_cpus && err_cpus && idle_cpus) { */
  789. /* node_ptr->node_state &= NODE_STATE_FLAGS; */
  790. /* node_ptr->node_state |= NODE_STATE_AEI; */
  791. /* } else if (alloc_cpus && !err_cpus && idle_cpus) { */
  792. /* node_ptr->node_state &= NODE_STATE_FLAGS; */
  793. /* node_ptr->node_state |= NODE_STATE_AI; */
  794. /* } else if (!alloc_cpus && err_cpus && idle_cpus) { */
  795. /* node_ptr->node_state &= NODE_STATE_FLAGS; */
  796. /* node_ptr->node_state |= NODE_STATE_EI; */
  797. /* } */
  798. }
  799. }
  800. *info_ptr = g_node_info_ptr;
  801. if (!g_topo_info_msg_ptr &&
  802. default_sview_config.grid_topological) {
  803. get_topo_conf(); /* pull in topology NOW */
  804. }
  805. return error_code;
  806. }
  807. extern int update_features_node(GtkDialog *dialog, const char *nodelist,
  808. const char *old_features)
  809. {
  810. char tmp_char[100];
  811. char *edit = NULL;
  812. GtkWidget *entry = NULL;
  813. GtkWidget *label = NULL;
  814. update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
  815. int response = 0;
  816. int no_dialog = 0;
  817. int rc = SLURM_SUCCESS;
  818. if (_DEBUG)
  819. g_print("update_features_node:global_row_count: %d "
  820. "node_names %s\n",
  821. global_row_count, nodelist);
  822. if (!dialog) {
  823. snprintf(tmp_char, sizeof(tmp_char),
  824. "Update Features for Node(s) %s?",
  825. nodelist);
  826. dialog = GTK_DIALOG(
  827. gtk_dialog_new_with_buttons(
  828. tmp_char,
  829. GTK_WINDOW(main_window),
  830. GTK_DIALOG_MODAL
  831. | GTK_DIALOG_DESTROY_WITH_PARENT,
  832. NULL));
  833. no_dialog = 1;
  834. }
  835. label = gtk_dialog_add_button(dialog,
  836. GTK_STOCK_YES, GTK_RESPONSE_OK);
  837. gtk_window_set_default(GTK_WINDOW(dialog), label);
  838. gtk_dialog_add_button(dialog,
  839. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  840. slurm_init_update_node_msg(node_msg);
  841. node_msg->node_names = xstrdup(nodelist);
  842. snprintf(tmp_char, sizeof(tmp_char),
  843. "Features for Node(s) %s?", nodelist);
  844. label = gtk_label_new(tmp_char);
  845. gtk_box_pack_start(GTK_BOX(dialog->vbox),
  846. label, FALSE, FALSE, 0);
  847. entry = create_entry();
  848. if (!entry)
  849. goto end_it;
  850. if (old_features)
  851. gtk_entry_set_text(GTK_ENTRY(entry), old_features);
  852. gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, TRUE, TRUE, 0);
  853. gtk_widget_show_all(GTK_WIDGET(dialog));
  854. response = gtk_dialog_run(dialog);
  855. if (response == GTK_RESPONSE_OK) {
  856. node_msg->features =
  857. xstrdup(gtk_entry_get_text(GTK_ENTRY(entry)));
  858. if (!node_msg->features) {
  859. edit = g_strdup_printf("No features given.");
  860. display_edit_note(edit);
  861. g_free(edit);
  862. goto end_it;
  863. }
  864. if ((rc = slurm_update_node(node_msg) == SLURM_SUCCESS)) {
  865. edit = g_strdup_printf(
  866. "Node(s) %s updated successfully.",
  867. nodelist);
  868. display_edit_note(edit);
  869. g_free(edit);
  870. } else {
  871. edit = g_strdup_printf(
  872. "Problem updating node(s) %s: %s",
  873. nodelist, slurm_strerror(rc));
  874. display_edit_note(edit);
  875. g_free(edit);
  876. }
  877. }
  878. end_it:
  879. slurm_free_update_node_msg(node_msg);
  880. if (no_dialog)
  881. gtk_widget_destroy(GTK_WIDGET(dialog));
  882. return rc;
  883. }
  884. extern int update_gres_node(GtkDialog *dialog, const char *nodelist,
  885. const char *old_gres)
  886. {
  887. char tmp_char[100];
  888. char *edit = NULL;
  889. GtkWidget *entry = NULL;
  890. GtkWidget *label = NULL;
  891. update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
  892. int response = 0;
  893. int no_dialog = 0;
  894. int rc = SLURM_SUCCESS;
  895. if (_DEBUG)
  896. g_print("update_gres_node:global_row_count:"
  897. " %d node_names %s\n",
  898. global_row_count, nodelist);
  899. if (!dialog) {
  900. snprintf(tmp_char, sizeof(tmp_char),
  901. "Update Gres for Node(s) %s?",
  902. nodelist);
  903. dialog = GTK_DIALOG(
  904. gtk_dialog_new_with_buttons(
  905. tmp_char,
  906. GTK_WINDOW(main_window),
  907. GTK_DIALOG_MODAL
  908. | GTK_DIALOG_DESTROY_WITH_PARENT,
  909. NULL));
  910. no_dialog = 1;
  911. }
  912. label = gtk_dialog_add_button(dialog, GTK_STOCK_YES, GTK_RESPONSE_OK);
  913. gtk_window_set_default(GTK_WINDOW(dialog), label);
  914. gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  915. slurm_init_update_node_msg(node_msg);
  916. node_msg->node_names = xstrdup(nodelist);
  917. snprintf(tmp_char, sizeof(tmp_char), "Gres for Node(s) %s?", nodelist);
  918. label = gtk_label_new(tmp_char);
  919. gtk_box_pack_start(GTK_BOX(dialog->vbox), label, FALSE, FALSE, 0);
  920. entry = create_entry();
  921. if (!entry)
  922. goto end_it;
  923. if (old_gres)
  924. gtk_entry_set_text(GTK_ENTRY(entry), old_gres);
  925. gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, TRUE, TRUE, 0);
  926. gtk_widget_show_all(GTK_WIDGET(dialog));
  927. response = gtk_dialog_run(dialog);
  928. if (response == GTK_RESPONSE_OK) {
  929. node_msg->gres = xstrdup(gtk_entry_get_text(GTK_ENTRY(entry)));
  930. if (!node_msg->gres) {
  931. edit = g_strdup_printf("No gres given.");
  932. display_edit_note(edit);
  933. g_free(edit);
  934. goto end_it;
  935. }
  936. if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) {
  937. edit = g_strdup_printf(
  938. "Nodes %s updated successfully.",
  939. nodelist);
  940. display_edit_note(edit);
  941. g_free(edit);
  942. } else {
  943. edit = g_strdup_printf(
  944. "Problem updating nodes %s: %s",
  945. nodelist, slurm_strerror(rc));
  946. display_edit_note(edit);
  947. g_free(edit);
  948. }
  949. }
  950. end_it:
  951. slurm_free_update_node_msg(node_msg);
  952. if (no_dialog)
  953. gtk_widget_destroy(GTK_WIDGET(dialog));
  954. return rc;
  955. }
  956. extern int update_state_node(GtkDialog *dialog,
  957. const char *nodelist, const char *type)
  958. {
  959. uint16_t state = (uint16_t) NO_VAL;
  960. char *upper = NULL, *lower = NULL;
  961. int i = 0;
  962. int rc = SLURM_SUCCESS;
  963. char tmp_char[100];
  964. update_node_msg_t *node_msg = xmalloc(sizeof(update_node_msg_t));
  965. GtkWidget *label = NULL;
  966. GtkWidget *entry = NULL;
  967. int no_dialog = 0;
  968. if (!dialog) {
  969. dialog = GTK_DIALOG(
  970. gtk_dialog_new_with_buttons(
  971. type,
  972. GTK_WINDOW(main_window),
  973. GTK_DIALOG_MODAL
  974. | GTK_DIALOG_DESTROY_WITH_PARENT,
  975. NULL));
  976. no_dialog = 1;
  977. }
  978. label = gtk_dialog_add_button(dialog, GTK_STOCK_YES, GTK_RESPONSE_OK);
  979. gtk_window_set_default(GTK_WINDOW(dialog), label);
  980. gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  981. slurm_init_update_node_msg(node_msg);
  982. node_msg->node_names = xstrdup(nodelist);
  983. if (!strncasecmp("drain", type, 5)) {
  984. snprintf(tmp_char, sizeof(tmp_char),
  985. "Are you sure you want to drain node(s) %s?\n\n"
  986. "Please put reason.",
  987. nodelist);
  988. entry = create_entry();
  989. label = gtk_label_new(tmp_char);
  990. state = NODE_STATE_DRAIN;
  991. } else if (!strncasecmp("resume", type, 5)) {
  992. snprintf(tmp_char, sizeof(tmp_char),
  993. "Are you sure you want to resume node(s) %s?",
  994. nodelist);
  995. label = gtk_label_new(tmp_char);
  996. state = NODE_RESUME;
  997. } else if (!strncasecmp("set", type, 3)) {
  998. snprintf(tmp_char, sizeof(tmp_char),
  999. "Are you sure you want to down node(s) %s?\n\n"
  1000. "Please put reason.",
  1001. nodelist);
  1002. entry = create_entry();
  1003. label = gtk_label_new(tmp_char);
  1004. state = NODE_STATE_DOWN;
  1005. } else {
  1006. if (!strncasecmp("make", type, 4))
  1007. type = "idle";
  1008. for(i = 0; i < NODE_STATE_END; i++) {
  1009. upper = node_state_string(i);
  1010. lower = str_tolower(upper);
  1011. if (!strcmp(lower, type)) {
  1012. snprintf(tmp_char, sizeof(tmp_char),
  1013. "Are you sure you want to set "
  1014. "node(s) %s to %s?",
  1015. nodelist, lower);
  1016. label = gtk_label_new(tmp_char);
  1017. state = i;
  1018. xfree(lower);
  1019. break;
  1020. }
  1021. xfree(lower);
  1022. }
  1023. }
  1024. if (!label)
  1025. goto end_it;
  1026. node_msg->node_state = (uint16_t)state;
  1027. gtk_box_pack_start(GTK_BOX(dialog->vbox), label, FALSE, FALSE, 0);
  1028. if (entry)
  1029. gtk_box_pack_start(GTK_BOX(dialog->vbox), entry, TRUE, TRUE, 0);
  1030. gtk_widget_show_all(GTK_WIDGET(dialog));
  1031. i = gtk_dialog_run(dialog);
  1032. if (i == GTK_RESPONSE_OK) {
  1033. if (entry) {
  1034. node_msg->reason = xstrdup(
  1035. gtk_entry_get_text(GTK_ENTRY(entry)));
  1036. if (!node_msg->reason || !strlen(node_msg->reason)) {
  1037. lower = g_strdup_printf(
  1038. "You need a reason to do that.");
  1039. display_edit_note(lower);
  1040. g_free(lower);
  1041. goto end_it;
  1042. }
  1043. if (uid_from_string(getlogin(),
  1044. &node_msg->reason_uid) < 0)
  1045. node_msg->reason_uid = getuid();
  1046. }
  1047. if ((rc = slurm_update_node(node_msg)) == SLURM_SUCCESS) {
  1048. lower = g_strdup_printf(
  1049. "Nodes %s updated successfully.",
  1050. nodelist);
  1051. display_edit_note(lower);
  1052. g_free(lower);
  1053. } else {
  1054. lower = g_strdup_printf(
  1055. "Problem updating nodes %s: %s",
  1056. nodelist, slurm_strerror(rc));
  1057. display_edit_note(lower);
  1058. g_free(lower);
  1059. }
  1060. }
  1061. end_it:
  1062. slurm_free_update_node_msg(node_msg);
  1063. if (no_dialog)
  1064. gtk_widget_destroy(GTK_WIDGET(dialog));
  1065. return rc;
  1066. }
  1067. extern GtkListStore *create_model_node(int type)
  1068. {
  1069. GtkListStore *model = NULL;
  1070. GtkTreeIter iter;
  1071. char *upper = NULL, *lower = NULL;
  1072. int i=0;
  1073. switch(type) {
  1074. case SORTID_STATE:
  1075. model = gtk_list_store_new(2, G_TYPE_STRING,
  1076. G_TYPE_INT);
  1077. gtk_list_store_append(model, &iter);
  1078. gtk_list_store_set(model, &iter,
  1079. 0, "drain",
  1080. 1, i,
  1081. -1);
  1082. gtk_list_store_append(model, &iter);
  1083. gtk_list_store_set(model, &iter,
  1084. 0, "NoResp",
  1085. 1, i,
  1086. -1);
  1087. gtk_list_store_append(model, &iter);
  1088. gtk_list_store_set(model, &iter,
  1089. 0, "resume",
  1090. 1, i,
  1091. -1);
  1092. for(i = 0; i < NODE_STATE_END; i++) {
  1093. upper = node_state_string(i);
  1094. gtk_list_store_append(model, &iter);
  1095. lower = str_tolower(upper);
  1096. gtk_list_store_set(model, &iter,
  1097. 0, lower,
  1098. 1, i,
  1099. -1);
  1100. xfree(lower);
  1101. }
  1102. break;
  1103. }
  1104. return model;
  1105. }
  1106. extern void admin_edit_node(GtkCellRendererText *cell,
  1107. const char *path_string,
  1108. const char *new_text,
  1109. gpointer data)
  1110. {
  1111. GtkTreeStore *treestore = GTK_TREE_STORE(data);
  1112. GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
  1113. GtkTreeIter iter;
  1114. char *nodelist = NULL;
  1115. int column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell),
  1116. "column"));
  1117. if (!new_text || !strcmp(new_text, ""))
  1118. goto no_input;
  1119. gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path);
  1120. switch(column) {
  1121. case SORTID_STATE:
  1122. gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
  1123. SORTID_NAME,
  1124. &nodelist, -1);
  1125. update_state_node(NULL, nodelist, new_text);
  1126. g_free(nodelist);
  1127. default:
  1128. break;
  1129. }
  1130. no_input:
  1131. gtk_tree_path_free(path);
  1132. g_static_mutex_unlock(&sview_mutex);
  1133. }
  1134. extern void get_info_node(GtkTable *table, display_data_t *display_data)
  1135. {
  1136. int error_code = SLURM_SUCCESS;
  1137. static int view = -1;
  1138. static node_info_msg_t *node_info_ptr = NULL;
  1139. char error_char[100];
  1140. GtkWidget *label = NULL;
  1141. GtkTreeView *tree_view = NULL;
  1142. static GtkWidget *display_widget = NULL;
  1143. List info_list = NULL;
  1144. int i = 0, sort_key;
  1145. sview_node_info_t *sview_node_info_ptr = NULL;
  1146. ListIterator itr = NULL;
  1147. GtkTreePath *path = NULL;
  1148. static bool set_opts = FALSE;
  1149. if (!set_opts)
  1150. set_page_opts(NODE_PAGE, display_data_node,
  1151. SORTID_CNT, _initial_page_opts);
  1152. set_opts = TRUE;
  1153. /* reset */
  1154. if (!table && !display_data) {
  1155. if (display_widget)
  1156. gtk_widget_destroy(display_widget);
  1157. display_widget = NULL;
  1158. goto reset_curs;
  1159. }
  1160. if (display_data)
  1161. local_display_data = display_data;
  1162. if (!table) {
  1163. display_data_node->set_menu = local_display_data->set_menu;
  1164. goto reset_curs;
  1165. }
  1166. if (display_widget && toggled) {
  1167. gtk_widget_destroy(display_widget);
  1168. display_widget = NULL;
  1169. goto display_it;
  1170. }
  1171. if ((error_code = get_new_info_node(&node_info_ptr, force_refresh))
  1172. == SLURM_NO_CHANGE_IN_DATA) {
  1173. if (!display_widget || view == ERROR_VIEW)
  1174. goto display_it;
  1175. } else if (error_code != SLURM_SUCCESS) {
  1176. if (view == ERROR_VIEW)
  1177. goto end_it;
  1178. view = ERROR_VIEW;
  1179. if (display_widget)
  1180. gtk_widget_destroy(display_widget);
  1181. sprintf(error_char, "slurm_load_node: %s",
  1182. slurm_strerror(slurm_get_errno()));
  1183. label = gtk_label_new(error_char);
  1184. display_widget = gtk_widget_ref(label);
  1185. gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
  1186. gtk_widget_show(label);
  1187. goto end_it;
  1188. }
  1189. display_it:
  1190. info_list = create_node_info_list(node_info_ptr, FALSE);
  1191. if (!info_list)
  1192. goto reset_curs;
  1193. i = 0;
  1194. /* set up the grid */
  1195. if (display_widget && GTK_IS_TREE_VIEW(display_widget) &&
  1196. gtk_tree_selection_count_selected_rows(
  1197. gtk_tree_view_get_selection(
  1198. GTK_TREE_VIEW(display_widget)))) {
  1199. GtkTreeViewColumn *focus_column = NULL;
  1200. /* highlight the correct nodes from the last selection */
  1201. gtk_tree_view_get_cursor(GTK_TREE_VIEW(display_widget),
  1202. &path, &focus_column);
  1203. }
  1204. if (!path) {
  1205. int array_size = node_info_ptr->record_count;
  1206. int *color_inx = xmalloc(sizeof(int) * array_size);
  1207. bool *color_set_flag = xmalloc(sizeof(bool) * array_size);
  1208. itr = list_iterator_create(info_list);
  1209. while ((sview_node_info_ptr = list_next(itr))) {
  1210. color_set_flag[i] = true;
  1211. color_inx[i] = i;
  1212. i++;
  1213. }
  1214. list_iterator_destroy(itr);
  1215. change_grid_color_array(grid_button_list, array_size,
  1216. color_inx, color_set_flag, true, 0);
  1217. xfree(color_inx);
  1218. xfree(color_set_flag);
  1219. } else
  1220. highlight_grid(GTK_TREE_VIEW(display_widget),
  1221. SORTID_POS, (int)NO_VAL, grid_button_list);
  1222. if (view == ERROR_VIEW && display_widget) {
  1223. gtk_widget_destroy(display_widget);
  1224. display_widget = NULL;
  1225. }
  1226. if (!display_widget) {
  1227. tree_view = create_treeview(local_display_data,
  1228. &grid_button_list);
  1229. /*set multiple capability here*/
  1230. gtk_tree_selection_set_mode(
  1231. gtk_tree_view_get_selection(tree_view),
  1232. GTK_SELECTION_MULTIPLE);
  1233. display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
  1234. gtk_table_attach_defaults(GTK_TABLE(table),
  1235. GTK_WIDGET(tree_view),
  1236. 0, 1, 0, 1);
  1237. /* Since this function sets the model of the tree_view to the
  1238. * treestore we don't really care about the return value
  1239. * On large clusters, sorting on the node name slows GTK down
  1240. * by a large margin. */
  1241. if (node_info_ptr->record_count > 1000)
  1242. sort_key = -1;
  1243. else
  1244. sort_key = SORTID_NAME;
  1245. create_treestore(tree_view, display_data_node,
  1246. SORTID_CNT, sort_key, SORTID_COLOR);
  1247. }
  1248. view = INFO_VIEW;
  1249. /* If the system has a large number of nodes then not all lines
  1250. * will be displayed. You can try different values for the third
  1251. * argument of gtk_widget_set_size_request() in an attempt to
  1252. * maximumize the data displayed in your environment. These are my
  1253. * results: Y=1000 good for 43 lines, Y=-1 good for 1151 lines,
  1254. * Y=64000 good for 2781 lines, Y=99000 good for 1453 lines */
  1255. /* gtk_widget_set_size_request(display_widget, -1, -1); */
  1256. _update_info_node(info_list, GTK_TREE_VIEW(display_widget));
  1257. end_it:
  1258. toggled = FALSE;
  1259. force_refresh = 1;
  1260. reset_curs:
  1261. if (main_window && main_window->window)
  1262. gdk_window_set_cursor(main_window->window, NULL);
  1263. return;
  1264. }
  1265. extern void specific_info_node(popup_info_t *popup_win)
  1266. {
  1267. int error_code = SLURM_SUCCESS;
  1268. static node_info_msg_t *node_info_ptr = NULL;
  1269. specific_info_t *spec_info = popup_win->spec_info;
  1270. char error_char[100];
  1271. GtkWidget *label = NULL;
  1272. GtkTreeView *tree_view = NULL;
  1273. List info_list = NULL;
  1274. List send_info_list = NULL;
  1275. ListIterator itr = NULL;
  1276. sview_node_info_t *sview_node_info_ptr = NULL;
  1277. node_info_t *node_ptr = NULL;
  1278. hostlist_t hostlist = NULL;
  1279. hostlist_iterator_t host_itr = NULL;
  1280. int i = -1, sort_key;
  1281. sview_search_info_t *search_info = spec_info->search_info;
  1282. if (!spec_info->display_widget)
  1283. setup_popup_info(popup_win, display_data_node, SORTID_CNT);
  1284. if (node_info_ptr && popup_win->toggled) {
  1285. gtk_widget_destroy(spec_info->display_widget);
  1286. spec_info->display_widget = NULL;
  1287. goto display_it;
  1288. }
  1289. if ((error_code = get_new_info_node(&node_info_ptr,
  1290. popup_win->force_refresh))
  1291. == SLURM_NO_CHANGE_IN_DATA) {
  1292. if (!spec_info->display_widget || spec_info->view == ERROR_VIEW)
  1293. goto display_it;
  1294. } else if (error_code != SLURM_SUCCESS) {
  1295. if (spec_info->view == ERROR_VIEW)
  1296. goto end_it;
  1297. spec_info->view = ERROR_VIEW;
  1298. if (spec_info->display_widget)
  1299. gtk_widget_destroy(spec_info->display_widget);
  1300. sprintf(error_char, "slurm_load_node: %s",
  1301. slurm_strerror(slurm_get_errno()));
  1302. label = gtk_label_new(error_char);
  1303. gtk_table_attach_defaults(popup_win->table,
  1304. label,
  1305. 0, 1, 0, 1);
  1306. gtk_widget_show(label);
  1307. spec_info->display_widget = gtk_widget_ref(label);
  1308. return;
  1309. }
  1310. display_it:
  1311. info_list = create_node_info_list(node_info_ptr, FALSE);
  1312. if (!info_list)
  1313. return;
  1314. if (spec_info->view == ERROR_VIEW && spec_info->display_widget) {
  1315. gtk_widget_destroy(spec_info->display_widget);
  1316. spec_info->display_widget = NULL;
  1317. }
  1318. if (spec_info->type != INFO_PAGE && !spec_info->display_widget) {
  1319. tree_view = create_treeview(local_display_data,
  1320. &popup_win->grid_button_list);
  1321. /*set multiple capability here*/
  1322. gtk_tree_selection_set_mode(
  1323. gtk_tree_view_get_selection(tree_view),
  1324. GTK_SELECTION_MULTIPLE);
  1325. spec_info->display_widget =
  1326. gtk_widget_ref(GTK_WIDGET(tree_view));
  1327. gtk_table_attach_defaults(popup_win->table,
  1328. GTK_WIDGET(tree_view),
  1329. 0, 1, 0, 1);
  1330. /* Since this function sets the model of the tree_view to the
  1331. * treestore we don't really care about the return value
  1332. * On large clusters, sorting on the node name slows GTK down
  1333. * by a large margin. */
  1334. if (node_info_ptr->record_count > 1000)
  1335. sort_key = -1;
  1336. else
  1337. sort_key = SORTID_NAME;
  1338. create_treestore(tree_view, popup_win->display_data,
  1339. SORTID_CNT, sort_key, SORTID_COLOR);
  1340. }
  1341. setup_popup_grid_list(popup_win);
  1342. spec_info->view = INFO_VIEW;
  1343. if (spec_info->type == INFO_PAGE) {
  1344. _display_info_node(info_list, popup_win);
  1345. goto end_it;
  1346. }
  1347. setup_popup_grid_list(popup_win);
  1348. /* just linking to another list, don't free the inside, just
  1349. the list */
  1350. send_info_list = list_create(NULL);
  1351. if (search_info->gchar_data) {
  1352. hostlist = hostlist_create(search_info->gchar_data);
  1353. host_itr = hostlist_iterator_create(hostlist);
  1354. }
  1355. i = -1;
  1356. itr = list_iterator_create(info_list);
  1357. while ((sview_node_info_ptr = list_next(itr))) {
  1358. int found = 0;
  1359. char *host = NULL;
  1360. i++;
  1361. node_ptr = sview_node_info_ptr->node_ptr;
  1362. switch(search_info->search_type) {
  1363. case SEARCH_NODE_STATE:
  1364. if (search_info->int_data == NO_VAL)
  1365. continue;
  1366. else if (search_info->int_data
  1367. != node_ptr->node_state) {
  1368. if (IS_NODE_MIXED(node_ptr)) {
  1369. uint16_t alloc_cnt = 0, err_cnt = 0;
  1370. uint16_t idle_cnt = node_ptr->cpus;
  1371. select_g_select_nodeinfo_get(
  1372. node_ptr->select_nodeinfo,
  1373. SELECT_NODEDATA_SUBCNT,
  1374. NODE_STATE_ALLOCATED,
  1375. &alloc_cnt);
  1376. select_g_select_nodeinfo_get(
  1377. node_ptr->select_nodeinfo,
  1378. SELECT_NODEDATA_SUBCNT,
  1379. NODE_STATE_ERROR,
  1380. &err_cnt);
  1381. idle_cnt -= (alloc_cnt + err_cnt);
  1382. if ((search_info->int_data
  1383. & NODE_STATE_BASE)
  1384. == NODE_STATE_ALLOCATED) {
  1385. if (alloc_cnt)
  1386. break;
  1387. } else if ((search_info->int_data
  1388. & NODE_STATE_BASE)
  1389. == NODE_STATE_ERROR) {
  1390. if (err_cnt)
  1391. break;
  1392. } else if ((search_info->int_data
  1393. & NODE_STATE_BASE)
  1394. == NODE_STATE_IDLE) {
  1395. if (idle_cnt)
  1396. break;
  1397. }
  1398. }
  1399. continue;
  1400. }
  1401. break;
  1402. case SEARCH_NODE_NAME:
  1403. default:
  1404. if (!search_info->gchar_data)
  1405. continue;
  1406. while ((host = hostlist_next(host_itr))) {
  1407. if (!strcmp(host, node_ptr->name)) {
  1408. free(host);
  1409. found = 1;
  1410. break;
  1411. }
  1412. free(host);
  1413. }
  1414. hostlist_iterator_reset(host_itr);
  1415. if (!found)
  1416. continue;
  1417. break;
  1418. }
  1419. list_push(send_info_list, sview_node_info_ptr);
  1420. change_grid_color(popup_win->grid_button_list,
  1421. i, i, 0, true, 0);
  1422. }
  1423. list_iterator_destroy(itr);
  1424. post_setup_popup_grid_list(popup_win);
  1425. if (search_info->gchar_data) {
  1426. hostlist_iterator_destroy(host_itr);
  1427. hostlist_destroy(hostlist);
  1428. }
  1429. _update_info_node(send_info_list,
  1430. GTK_TREE_VIEW(spec_info->display_widget));
  1431. list_destroy(send_info_list);
  1432. end_it:
  1433. popup_win->toggled = 0;
  1434. popup_win->force_refresh = 0;
  1435. return;
  1436. }
  1437. extern void set_menus_node(void *arg, void *arg2, GtkTreePath *path, int type)
  1438. {
  1439. GtkTreeView *tree_view = (GtkTreeView *)arg;
  1440. popup_info_t *popup_win = (popup_info_t *)arg;
  1441. GtkMenu *menu = (GtkMenu *)arg2;
  1442. List button_list = (List)arg2;
  1443. switch(type) {
  1444. case TAB_CLICKED:
  1445. make_fields_menu(NULL, menu, display_data_node, SORTID_CNT);
  1446. break;
  1447. case ROW_CLICKED:
  1448. make_options_menu(tree_view, path, menu, options_data_node);
  1449. break;
  1450. case ROW_LEFT_CLICKED:
  1451. {
  1452. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  1453. GtkTreeIter iter;
  1454. if (!gtk_tree_model_get_iter(model, &iter, path)) {
  1455. g_error("error getting iter from model\n");
  1456. break;
  1457. }
  1458. highlight_grid(tree_view, SORTID_POS, (int)NO_VAL, button_list);
  1459. break;
  1460. }
  1461. case FULL_CLICKED:
  1462. {
  1463. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  1464. GtkTreeIter iter;
  1465. if (!gtk_tree_model_get_iter(model, &iter, path)) {
  1466. g_error("error getting iter from model\n");
  1467. break;
  1468. }
  1469. popup_all_node(model, &iter, INFO_PAGE);
  1470. break;
  1471. }
  1472. case POPUP_CLICKED:
  1473. make_fields_menu(popup_win, menu,
  1474. popup_win->display_data, SORTID_CNT);
  1475. break;
  1476. default:
  1477. g_error("UNKNOWN type %d given to set_fields\n", type);
  1478. }
  1479. }
  1480. extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id)
  1481. {
  1482. char *name = NULL;
  1483. gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
  1484. if (_DEBUG)
  1485. g_print("popup_all_node: name = %s\n", name);
  1486. popup_all_node_name(name, id);
  1487. /* this name gets g_strdup'ed in the previous function */
  1488. g_free(name);
  1489. }
  1490. extern void popup_all_node_name(char *name, int id)
  1491. {
  1492. char title[100];
  1493. ListIterator itr = NULL;
  1494. popup_info_t *popup_win = NULL;
  1495. GError *error = NULL;
  1496. char *node;
  1497. if (cluster_flags & CLUSTER_FLAG_BG)
  1498. node = "Midplane";
  1499. else
  1500. node = "Node";
  1501. switch(id) {
  1502. case JOB_PAGE:
  1503. snprintf(title, 100, "Job(s) with %s %s", node, name);
  1504. break;
  1505. case PART_PAGE:
  1506. snprintf(title, 100, "Partition(s) with %s %s", node, name);
  1507. break;
  1508. case RESV_PAGE:
  1509. snprintf(title, 100, "Reservation(s) with %s %s", node, name);
  1510. break;
  1511. case BLOCK_PAGE:
  1512. snprintf(title, 100, "Blocks(s) with %s %s", node, name);
  1513. break;
  1514. case SUBMIT_PAGE:
  1515. snprintf(title, 100, "Submit job on %s %s", node, name);
  1516. break;
  1517. case INFO_PAGE:
  1518. snprintf(title, 100, "Full Info for %s %s", node, name);
  1519. break;
  1520. default:
  1521. g_print("%s got %d\n", node, id);
  1522. }
  1523. itr = list_iterator_create(popup_list);
  1524. while ((popup_win = list_next(itr))) {
  1525. if (popup_win->spec_info)
  1526. if (!strcmp(popup_win->spec_info->title, title)) {
  1527. break;
  1528. }
  1529. }
  1530. list_iterator_destroy(itr);
  1531. if (!

Large files files are truncated, but you can click here to view the full file