nodeocc 1.0.4__tar.gz → 1.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nodeocc-1.0.4 → nodeocc-1.0.6}/PKG-INFO +1 -1
- {nodeocc-1.0.4 → nodeocc-1.0.6}/pyproject.toml +1 -1
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/controller/controller.py +2 -2
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/model/infrastructure.py +1 -1
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/nodeocc.egg-info/PKG-INFO +1 -1
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/readers/slurmreader.py +14 -1
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/view/curses_multiwindow.py +66 -26
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/view/slurm_list.py +1 -1
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/view/slurm_viz.py +69 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/README.md +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/setup.cfg +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/setup.py +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/__init__.py +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/model/job.py +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/nodeocc.egg-info/SOURCES.txt +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/nodeocc.egg-info/dependency_links.txt +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/nodeocc.egg-info/entry_points.txt +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/nodeocc.egg-info/requires.txt +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/nodeocc.egg-info/top_level.txt +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/readers/compute_wait_time.py +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/view/__init__.py +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/view/styles.py +0 -0
- {nodeocc-1.0.4 → nodeocc-1.0.6}/src/view/utils.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nodeocc"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.6"
|
|
8
8
|
authors = [{ name = "Matteo Boschini" }]
|
|
9
9
|
maintainers = [{ name = "Lorenzo Bonicelli" }, { name = "Aniello Panariello" }]
|
|
10
10
|
description = "TUI application for viewing the status of GPU allocations on a Slurm cluster"
|
|
@@ -120,9 +120,9 @@ def update_data_master(instance):
|
|
|
120
120
|
running_jobs = [j.to_nested_dict() for j in jobs if j.state == 'CG' or j.state == 'R']
|
|
121
121
|
queue_jobs = [j.to_nested_dict() for j in jobs if j.state != 'R' and j.state != 'CG']
|
|
122
122
|
queue_jobs = sorted(queue_jobs, key=lambda x: x['priority'], reverse=True)
|
|
123
|
-
maxlen = min(
|
|
123
|
+
maxlen = min(100, len(running_jobs) + len(queue_jobs))
|
|
124
124
|
|
|
125
|
-
msg = json.dumps({'inf': inf.to_nested_dict(), 'jobs': running_jobs + queue_jobs[:maxlen]})
|
|
125
|
+
msg = json.dumps({'inf': inf.to_nested_dict(), 'jobs': running_jobs + queue_jobs[:maxlen - len(running_jobs)]})
|
|
126
126
|
|
|
127
127
|
# msg to bytes
|
|
128
128
|
msg = msg.encode('utf-8')
|
|
@@ -92,4 +92,4 @@ class Infrastructure:
|
|
|
92
92
|
|
|
93
93
|
def get_sorted_nodes(self):
|
|
94
94
|
|
|
95
|
-
return sorted(self.nodes, key=lambda x: self.prior.index(x.gpu_model) if x.gpu_model in self.prior else -1)
|
|
95
|
+
return sorted(self.nodes, key=lambda x: self.prior.index(x.gpu_model.split(',')[0]) if x.gpu_model.split(',')[0] in self.prior else -1)
|
|
@@ -41,11 +41,24 @@ def _node_from_sinfo(x):
|
|
|
41
41
|
return n
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
def _parse_gpu_models(line):
|
|
45
|
+
line = line[0].split(',')
|
|
46
|
+
if line[0] == '(null)':
|
|
47
|
+
return 'n/a'
|
|
48
|
+
else:
|
|
49
|
+
if len(line) == 1:
|
|
50
|
+
return line[0].split(':')[1]
|
|
51
|
+
else:
|
|
52
|
+
# return line[0].split(':')[1] + ',' + line[1].split(':')[1]
|
|
53
|
+
return ','.join([x.split(':')[1] for x in line])
|
|
54
|
+
|
|
55
|
+
|
|
44
56
|
def _read_nodes(reservations, pending_res):
|
|
45
57
|
sinfo_df = pd.read_csv(StringIO(os.popen(r'sinfo -N -o "%N;%G;%t;%m;%c"').read()), sep=';')
|
|
46
58
|
sinfo_df = _split_column(sinfo_df, 'NODELIST').drop_duplicates()
|
|
47
59
|
sinfo_df['n_gpu'] = sinfo_df['GRES'].apply(lambda x: 0 if x.split('(')[0].split(':')[0] in ('(null)', '') else int(x.split('(')[0].split(':')[-1]))
|
|
48
|
-
sinfo_df['m_gpu'] = sinfo_df['GRES'].str.split(':').apply(lambda x: 'n/a' if x[0] in ('(null)', '') else x[1])
|
|
60
|
+
# sinfo_df['m_gpu'] = sinfo_df['GRES'].str.split(':').apply(lambda x: 'n/a' if x[0] in ('(null)', '') else x[1])
|
|
61
|
+
sinfo_df['m_gpu'] = sinfo_df['GRES'].str.split(';').apply(_parse_gpu_models)
|
|
49
62
|
sinfo_df['reserved'] = 'no'
|
|
50
63
|
if reservations is not None:
|
|
51
64
|
sinfo_df.loc[sinfo_df['NODELIST'].isin(reservations.Nodes.unique()), 'reserved'] = 'yes'
|
|
@@ -15,6 +15,24 @@ from view import update_views
|
|
|
15
15
|
|
|
16
16
|
a_filter_values = [None, 'me', 'prod', 'stud', 'cvcs']
|
|
17
17
|
|
|
18
|
+
BUTTON_ACTIONS = {
|
|
19
|
+
'up_1': [ord('w'), curses.KEY_UP, ord('k')],
|
|
20
|
+
'down_1': [ord('s'), curses.KEY_DOWN, ord('j')],
|
|
21
|
+
'left_1': [ord('a'), curses.KEY_LEFT, ord('h')],
|
|
22
|
+
'right_1': [ord('d'), curses.KEY_RIGHT, ord('l')],
|
|
23
|
+
'up_tab': [curses.KEY_NPAGE],
|
|
24
|
+
'down_tab': [curses.KEY_PPAGE],
|
|
25
|
+
'quit': [ord('q'), 'q'],
|
|
26
|
+
'sort_prio': [ord('S')],
|
|
27
|
+
'res_view_mode': [ord('g')],
|
|
28
|
+
'job_id_type': [ord('b')],
|
|
29
|
+
'show_starttime': [ord('z')],
|
|
30
|
+
'show_account': [ord('t')],
|
|
31
|
+
'show_prio': [ord('p')],
|
|
32
|
+
'refresh': [ord('y')],
|
|
33
|
+
'info': [ord('i')],
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
|
|
19
37
|
def try_open_socket_as_slave(instance):
|
|
20
38
|
if not instance.port_file_exists():
|
|
@@ -289,8 +307,8 @@ class Buffer(object):
|
|
|
289
307
|
xacc += len(chunk)
|
|
290
308
|
if len(self.buffer) > self.lines - 2:
|
|
291
309
|
self.screen.addstr(self.lines - 2, instance.xoffset + instance.left_width // 2 - 6, ' ▼ SCROLL ▲ ', curses.color_pair(2) | curses.A_REVERSE)
|
|
292
|
-
instance.add_button(self.lines - 2, instance.xoffset + 31, 'D',
|
|
293
|
-
instance.add_button(self.lines - 2, instance.xoffset + 40, 'U',
|
|
310
|
+
instance.add_button(self.lines - 2, instance.xoffset + 31, 'D', BUTTON_ACTIONS['down_1'][0])
|
|
311
|
+
instance.add_button(self.lines - 2, instance.xoffset + 40, 'U', BUTTON_ACTIONS['up_1'][0])
|
|
294
312
|
|
|
295
313
|
self.window.border()
|
|
296
314
|
self.window.noutrefresh()
|
|
@@ -330,35 +348,50 @@ def handle_keys(stdscr, instance):
|
|
|
330
348
|
|
|
331
349
|
# process input
|
|
332
350
|
# RIGHT
|
|
333
|
-
if k
|
|
351
|
+
if k in BUTTON_ACTIONS['right_1']:
|
|
334
352
|
instance.a_filter = (instance.a_filter + 1) % len(a_filter_values)
|
|
335
353
|
instance.voff = 0
|
|
336
354
|
# LEFT
|
|
337
|
-
elif k
|
|
355
|
+
elif k in BUTTON_ACTIONS['left_1']:
|
|
338
356
|
instance.a_filter = (instance.a_filter + (len(a_filter_values) - 1)) % len(a_filter_values)
|
|
339
357
|
instance.voff = 0
|
|
340
358
|
elif valid_mouse and isinstance(k, str) and k.startswith('AF_'):
|
|
341
359
|
instance.a_filter = int(k.split('AF_')[1])
|
|
342
360
|
# DOWN
|
|
343
|
-
elif k
|
|
361
|
+
elif k in BUTTON_ACTIONS['down_1']:
|
|
344
362
|
instance.voff += 1
|
|
345
363
|
# UP
|
|
346
|
-
elif k
|
|
364
|
+
elif k in BUTTON_ACTIONS['up_1']:
|
|
347
365
|
instance.voff -= 1
|
|
348
366
|
|
|
349
|
-
|
|
367
|
+
elif k in BUTTON_ACTIONS['sort_prio']:
|
|
350
368
|
instance.sort_by_prio = not instance.sort_by_prio
|
|
351
|
-
|
|
369
|
+
elif k in BUTTON_ACTIONS['res_view_mode']:
|
|
352
370
|
instance.view_mode = {"gpu": "ram", "ram": "cpu", "cpu": "gpu"}[instance.view_mode]
|
|
353
|
-
|
|
371
|
+
instance.right_width = 33 if instance.view_mode != 'info' else 39
|
|
372
|
+
stdscr.clear()
|
|
373
|
+
elif k in BUTTON_ACTIONS['job_id_type']:
|
|
354
374
|
instance.job_id_type = "true" if instance.job_id_type == "agg" else "agg"
|
|
355
|
-
|
|
375
|
+
elif k in BUTTON_ACTIONS['show_starttime']:
|
|
356
376
|
# instance.show_starttime = not instance.show_starttime
|
|
357
377
|
pass
|
|
358
|
-
|
|
378
|
+
elif k in BUTTON_ACTIONS['show_account']:
|
|
359
379
|
instance.show_account = not instance.show_account
|
|
360
|
-
|
|
380
|
+
elif k in BUTTON_ACTIONS['show_prio']:
|
|
361
381
|
instance.show_prio = not instance.show_prio
|
|
382
|
+
elif k in BUTTON_ACTIONS['info']:
|
|
383
|
+
instance.view_mode = 'info' if instance.view_mode != 'info' else 'gpu'
|
|
384
|
+
instance.right_width = 33 if instance.view_mode != 'info' else 39
|
|
385
|
+
stdscr.clear()
|
|
386
|
+
elif k in BUTTON_ACTIONS['up_tab']:
|
|
387
|
+
# get screen size
|
|
388
|
+
height, width = stdscr.getmaxyx()
|
|
389
|
+
|
|
390
|
+
instance.voff += ((height - 4) // 2) + 1
|
|
391
|
+
elif k in BUTTON_ACTIONS['down_tab']:
|
|
392
|
+
height, width = stdscr.getmaxyx()
|
|
393
|
+
|
|
394
|
+
instance.voff -= ((height - 4) // 2) + 1
|
|
362
395
|
|
|
363
396
|
|
|
364
397
|
def update_screen(stdscr, instance):
|
|
@@ -369,7 +402,7 @@ def update_screen(stdscr, instance):
|
|
|
369
402
|
lines, columns = os.get_terminal_size().lines, os.get_terminal_size().columns
|
|
370
403
|
s_lines, s_columns = stdscr.getmaxyx()
|
|
371
404
|
instance.max_columns = s_columns
|
|
372
|
-
if instance.k
|
|
405
|
+
if instance.k in BUTTON_ACTIONS['refresh']:
|
|
373
406
|
stdscr.clear()
|
|
374
407
|
|
|
375
408
|
totsize = 106
|
|
@@ -395,11 +428,12 @@ def update_screen(stdscr, instance):
|
|
|
395
428
|
|
|
396
429
|
stdscr.refresh()
|
|
397
430
|
|
|
398
|
-
left_width = columns -
|
|
431
|
+
left_width = columns - instance.right_width # 72
|
|
432
|
+
right_width = instance.right_width # 33
|
|
399
433
|
instance.left_width = left_width
|
|
400
434
|
left_window = curses.newwin(lines - 1, left_width, 0, xoffset)
|
|
401
435
|
left_buffer = Buffer(left_window, lines, stdscr)
|
|
402
|
-
right_window = curses.newwin(lines - 1,
|
|
436
|
+
right_window = curses.newwin(lines - 1, right_width - 2, 0, xoffset + left_width + 1)
|
|
403
437
|
right_buffer = Buffer(right_window, lines, stdscr)
|
|
404
438
|
|
|
405
439
|
left_buffer.write(instance.rens)
|
|
@@ -409,7 +443,7 @@ def update_screen(stdscr, instance):
|
|
|
409
443
|
|
|
410
444
|
# render menu
|
|
411
445
|
stdscr.addstr(lines - 1, xoffset + 1 + 0, '◀')
|
|
412
|
-
instance.add_button(lines - 1, xoffset + 1 + 0, '◀',
|
|
446
|
+
instance.add_button(lines - 1, xoffset + 1 + 0, '◀', BUTTON_ACTIONS['left_1'][0])
|
|
413
447
|
stdscr.addstr(lines - 1, xoffset + 1 + 2, 'ALL', curses.color_pair(2) | (curses.A_REVERSE if a_filter_values[instance.a_filter] is None else 0))
|
|
414
448
|
|
|
415
449
|
instance.add_button(lines - 1, xoffset + 1 + 2, 'ALL', 'AF_0')
|
|
@@ -424,37 +458,42 @@ def update_screen(stdscr, instance):
|
|
|
424
458
|
instance.add_button(lines - 1, xoffset + 1 + 19, 'CVCS', 'AF_4')
|
|
425
459
|
|
|
426
460
|
stdscr.addstr(lines - 1, xoffset + 1 + 24, '▶')
|
|
427
|
-
instance.add_button(lines - 1, xoffset + 1 + 24, '▶',
|
|
461
|
+
instance.add_button(lines - 1, xoffset + 1 + 24, '▶', BUTTON_ACTIONS['right_1'][0])
|
|
428
462
|
stdscr.addstr(lines - 1, xoffset + 1 + 25, ' ' * (columns - 27 - xoffset))
|
|
429
463
|
|
|
430
464
|
stdscr.addstr(lines - 1, left_width - 8, '[Q:QUIT]', curses.color_pair(2))
|
|
431
|
-
instance.add_button(lines - 1, left_width - 8, '[Q:QUIT]',
|
|
465
|
+
instance.add_button(lines - 1, left_width - 8, '[Q:QUIT]', BUTTON_ACTIONS['quit'][0]) # 53
|
|
432
466
|
|
|
433
467
|
stdscr.addstr(lines - 1, left_width - 18 + 19, '[Y:REDRAW]', curses.color_pair(2))
|
|
434
|
-
instance.add_button(lines - 1, left_width - 18 + 19, '[Y:REDRAW]',
|
|
468
|
+
instance.add_button(lines - 1, left_width - 18 + 19, '[Y:REDRAW]', BUTTON_ACTIONS['refresh'][0])
|
|
435
469
|
|
|
470
|
+
stdscr.addstr(0, left_width + 2, '[I:', curses.color_pair(2))
|
|
471
|
+
stdscr.addstr(0, left_width + 5, 'INFO', curses.color_pair(2) | (curses.A_REVERSE if instance.view_mode == 'info' else 0))
|
|
472
|
+
stdscr.addstr(0, left_width + 9, ']', curses.color_pair(2))
|
|
473
|
+
instance.add_button(0, left_width + 2, '[I:INFO]', BUTTON_ACTIONS['info'][0])
|
|
474
|
+
stdscr.addstr(0, left_width + 10, '─' * (columns - 15 - left_width - 3), curses.color_pair(2))
|
|
436
475
|
stdscr.addstr(0, columns - 15, '[G:', curses.color_pair(2))
|
|
437
476
|
stdscr.addstr(0, columns - 12, 'GPU', curses.color_pair(2) | (curses.A_REVERSE if instance.view_mode == 'gpu' else 0))
|
|
438
477
|
stdscr.addstr(0, columns - 12 + 3, 'RAM', curses.color_pair(2) | (curses.A_REVERSE if instance.view_mode == 'ram' else 0))
|
|
439
478
|
stdscr.addstr(0, columns - 12 + 6, 'CPU', curses.color_pair(2) | (curses.A_REVERSE if instance.view_mode == 'cpu' else 0))
|
|
440
479
|
stdscr.addstr(0, columns - 12 + 9, ']', curses.color_pair(2))
|
|
441
|
-
instance.add_button(0, columns - 15, '[G:GPURAMCPU]',
|
|
480
|
+
instance.add_button(0, columns - 15, '[G:GPURAMCPU]', BUTTON_ACTIONS['res_view_mode'][0])
|
|
442
481
|
|
|
443
|
-
stdscr.addstr(lines - 1, xoffset + 25 + 2, '[
|
|
482
|
+
stdscr.addstr(lines - 1, xoffset + 25 + 2, '[B:', curses.color_pair(2))
|
|
444
483
|
stdscr.addstr(lines - 1, xoffset + 25 + 2 + 3, 'AGG', curses.color_pair(2) | (curses.A_REVERSE if instance.job_id_type == 'agg' else 0))
|
|
445
484
|
stdscr.addstr(lines - 1, xoffset + 25 + 2 + 3 + 3, 'TRUE', curses.color_pair(2) | (curses.A_REVERSE if instance.job_id_type == 'true' else 0))
|
|
446
485
|
stdscr.addstr(lines - 1, xoffset + 25 + 2 + 3 + 3 + 4, ']', curses.color_pair(2))
|
|
447
|
-
instance.add_button(lines - 1, xoffset + 25 + 2, '[
|
|
486
|
+
instance.add_button(lines - 1, xoffset + 25 + 2, '[B:AGGTRUE]', BUTTON_ACTIONS['job_id_type'][0])
|
|
448
487
|
|
|
449
488
|
stdscr.addstr(lines - 1, xoffset + 37 + 2, '[P:', curses.color_pair(2))
|
|
450
489
|
stdscr.addstr(lines - 1, xoffset + 37 + 2 + 3, 'PRIORITY', curses.color_pair(2) | (curses.A_REVERSE if instance.show_prio else 0))
|
|
451
490
|
stdscr.addstr(lines - 1, xoffset + 37 + 2 + 3 + 8, ']', curses.color_pair(2))
|
|
452
|
-
instance.add_button(lines - 1, xoffset + 37 + 2, '[P:PRIORITY]',
|
|
491
|
+
instance.add_button(lines - 1, xoffset + 37 + 2, '[P:PRIORITY]', BUTTON_ACTIONS['show_prio'][0])
|
|
453
492
|
|
|
454
493
|
stdscr.addstr(lines - 1, xoffset + 50 + 2, '[T:', curses.color_pair(2))
|
|
455
494
|
stdscr.addstr(lines - 1, xoffset + 50 + 2 + 3, 'ACCOUNT', curses.color_pair(2) | (curses.A_REVERSE if instance.show_account else 0))
|
|
456
495
|
stdscr.addstr(lines - 1, xoffset + 50 + 2 + 3 + 7, ']', curses.color_pair(2))
|
|
457
|
-
instance.add_button(lines - 1, xoffset + 50 + 2, '[T:ACCOUNT]',
|
|
496
|
+
instance.add_button(lines - 1, xoffset + 50 + 2, '[T:ACCOUNT]', BUTTON_ACTIONS['show_account'][0])
|
|
458
497
|
|
|
459
498
|
# get slurm user partition
|
|
460
499
|
stdscr.addstr(lines - 1, xoffset + 62 + 2, f'(Avg time {instance.avg_wait_time})', curses.color_pair(2))
|
|
@@ -467,7 +506,7 @@ def update_screen(stdscr, instance):
|
|
|
467
506
|
|
|
468
507
|
|
|
469
508
|
def get_char_async(stdscr, instance):
|
|
470
|
-
while instance.k
|
|
509
|
+
while instance.k not in BUTTON_ACTIONS['quit']: # != 'q'
|
|
471
510
|
handle_keys(stdscr, instance)
|
|
472
511
|
update_screen(stdscr, instance)
|
|
473
512
|
|
|
@@ -476,7 +515,7 @@ def get_char_async(stdscr, instance):
|
|
|
476
515
|
|
|
477
516
|
|
|
478
517
|
async def update_screen_info(stdscr, instance):
|
|
479
|
-
while instance.k
|
|
518
|
+
while instance.k not in BUTTON_ACTIONS['quit']:
|
|
480
519
|
await instance.fetch()
|
|
481
520
|
instance.log("GOT DATA FROM MASTER")
|
|
482
521
|
update_screen(stdscr, instance)
|
|
@@ -547,6 +586,7 @@ async def main(stdscr):
|
|
|
547
586
|
# status
|
|
548
587
|
|
|
549
588
|
instance.a_filter = 0
|
|
589
|
+
instance.right_width = 33
|
|
550
590
|
|
|
551
591
|
stdscr.clear()
|
|
552
592
|
|
|
@@ -21,7 +21,7 @@ def _joblet_format(instance, job, width=74, jobid_type='agg'):
|
|
|
21
21
|
if instance.show_prio:
|
|
22
22
|
joblet_repr += '(' + _format_to(job.priority, len(str(job.priority))) + ')'
|
|
23
23
|
joblet_repr += ' '
|
|
24
|
-
loffset +=
|
|
24
|
+
loffset += len(str(job.priority)) + 3
|
|
25
25
|
if instance.show_account:
|
|
26
26
|
joblet_repr += _format_to(job.account, 9)
|
|
27
27
|
joblet_repr += ' '
|
|
@@ -115,6 +115,8 @@ def view_viz(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=Non
|
|
|
115
115
|
return view_viz_ram(infrastructure, jobs, work, stylefn, current_user)
|
|
116
116
|
elif mode == 'cpu':
|
|
117
117
|
return view_viz_cpu(infrastructure, jobs, work, stylefn, current_user)
|
|
118
|
+
elif mode == 'info':
|
|
119
|
+
return view_viz_info(infrastructure, jobs, work, stylefn, current_user)
|
|
118
120
|
|
|
119
121
|
|
|
120
122
|
def view_viz_ram(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None):
|
|
@@ -354,6 +356,9 @@ def get_cpu_icon(stat):
|
|
|
354
356
|
}.get(stat, cpu_avail)
|
|
355
357
|
|
|
356
358
|
|
|
359
|
+
GPU_MEM = {"K80": 12, "P100": 16, "1080": 11, "TitanXP": 12, "2080": 11, "RTX5000": 16, "RTX6000": 24, "RTXA5000": 24, "A40": 48}
|
|
360
|
+
|
|
361
|
+
|
|
357
362
|
def view_viz_cpu(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None):
|
|
358
363
|
# this is for hot reload
|
|
359
364
|
if not work:
|
|
@@ -480,6 +485,70 @@ def view_viz_cpu(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user
|
|
|
480
485
|
return RetScope.return_string
|
|
481
486
|
|
|
482
487
|
|
|
488
|
+
def view_viz_info(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None):
|
|
489
|
+
# this is for hot reload
|
|
490
|
+
if not work:
|
|
491
|
+
return "UPDATE IN PROGRESS - PLZ W8 M8 B8"
|
|
492
|
+
|
|
493
|
+
# who is the current user?
|
|
494
|
+
if current_user is None:
|
|
495
|
+
import os
|
|
496
|
+
current_user = os.path.basename(os.environ['HOME'])
|
|
497
|
+
|
|
498
|
+
nodes = infrastructure.get_sorted_nodes()
|
|
499
|
+
infrast_down = all([x.status == 'down' for x in nodes])
|
|
500
|
+
|
|
501
|
+
class RetScope:
|
|
502
|
+
return_string = ''
|
|
503
|
+
|
|
504
|
+
def cust_print(thing, style=None):
|
|
505
|
+
RetScope.return_string += (thing if style is None else stylefn(style, thing)) + '\n'
|
|
506
|
+
|
|
507
|
+
if not infrast_down:
|
|
508
|
+
stalled_jobs = sum([j.state == 'S' for j in jobs])
|
|
509
|
+
max_gpu_len = max([len(n.gpu_model) + len(str(n.n_gpus)) if n.gpu_model is not None else 0 for n in nodes])
|
|
510
|
+
max_n_gpu_len = max([len(str(n.n_gpus)) for n in nodes])
|
|
511
|
+
max_cpu_len = max([len(str(n.cpus)) for n in nodes] + [len('CPUs')])
|
|
512
|
+
max_ram_len = max([len(str(n.mem // 1024)) for n in nodes])
|
|
513
|
+
RetScope.return_string += f'{"":{gpu_name_chars}} {"GPUs":{max_gpu_len+1}}\n'
|
|
514
|
+
for n in nodes:
|
|
515
|
+
gpu_model = n.gpu_model if n.gpu_model is not None else 'N/A'
|
|
516
|
+
# gpu_mem = n.gpu_mem if n.gpu_mem is not None else 'N/A'
|
|
517
|
+
mem = n.mem // 1024 if n.mem is not None else 'N/A'
|
|
518
|
+
n_gpus = n.n_gpus if n.n_gpus is not None else 'N/A'
|
|
519
|
+
n_cpus = n.cpus if n.cpus is not None else 'N/A'
|
|
520
|
+
# gpu_mem = GPU_MEM.get(gpu_model, 'N/A')
|
|
521
|
+
gpu_mem = ','.join([str(GPU_MEM.get(x, 'N/A')) for x in gpu_model.split(',')])
|
|
522
|
+
# gpu_str = f'{n_gpus}x{gpu_model:{max_gpu_len-(1*(len(str(n_gpus))))}}' if n_gpus != 0 else f'{"N/A":{max_gpu_len+1}}'
|
|
523
|
+
if n_gpus != 0:
|
|
524
|
+
gpu_str = f'{stylefn("RED", str(n_gpus))}'
|
|
525
|
+
gpu_str += f'x{stylefn("YELLOW", gpu_model)}'
|
|
526
|
+
gpu_str += f'@{stylefn("GREEN", str(gpu_mem))}G'
|
|
527
|
+
else:
|
|
528
|
+
gpu_str = f'{"N/A":{max_gpu_len+1}}'
|
|
529
|
+
RetScope.return_string += f'{_format_to(n.name, gpu_name_chars, "right")} {gpu_str}\n'
|
|
530
|
+
# RetScope.return_string += f'{"":{gpu_name_chars}} {"VRAM":{max_gpu_len+1}} {f"{mem}G"}\n'
|
|
531
|
+
|
|
532
|
+
onmain, waitString = maintenance_status(infrastructure)
|
|
533
|
+
if onmain:
|
|
534
|
+
cust_print(' ◀ ONGOING MAINTENANCE ▶ ', 'BG_MAGENTA')
|
|
535
|
+
elif len(infrastructure.maintenances):
|
|
536
|
+
cust_print(' ◀ MAINTENANCE in %4s ▶ ' % waitString, 'BG_MAGENTA')
|
|
537
|
+
elif len(jobs) == 0:
|
|
538
|
+
cust_print(' ◀ NO JOBS ▶ ', 'BG_GREEN')
|
|
539
|
+
elif stalled_jobs / len(jobs) > 0.5:
|
|
540
|
+
cust_print(' ◀ JOBS ON HOLD ▶ ', 'BG_YELLOW')
|
|
541
|
+
else:
|
|
542
|
+
cust_print('')
|
|
543
|
+
|
|
544
|
+
# print summary
|
|
545
|
+
# cust_print(''.join([' ['+ ram_occ + 'run', paused + 'hld', drain + 'drn', down + 'dwn', '()res]']))
|
|
546
|
+
# cust_print(''.join(['[' + ram_occ + f'{cpu_size}{cpu_unit}', cpu_paused + 'hld', cpu_drain + 'drn', cpu_pendr + 'pnd', cpu_down + 'dwn', '()res]']))
|
|
547
|
+
# gpuc = 'GREEN'
|
|
548
|
+
|
|
549
|
+
return RetScope.return_string
|
|
550
|
+
|
|
551
|
+
|
|
483
552
|
if __name__ == '__main__':
|
|
484
553
|
import sys
|
|
485
554
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|