nodeocc 1.0.1__py3-none-any.whl
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.
- __init__.py +1 -0
- controller/controller.py +255 -0
- model/infrastructure.py +95 -0
- model/job.py +75 -0
- nodeocc-1.0.1.dist-info/METADATA +33 -0
- nodeocc-1.0.1.dist-info/RECORD +17 -0
- nodeocc-1.0.1.dist-info/WHEEL +5 -0
- nodeocc-1.0.1.dist-info/entry_points.txt +2 -0
- nodeocc-1.0.1.dist-info/top_level.txt +5 -0
- readers/compute_wait_time.py +28 -0
- readers/slurmreader.py +308 -0
- view/__init__.py +12 -0
- view/curses_multiwindow.py +580 -0
- view/slurm_list.py +148 -0
- view/slurm_viz.py +494 -0
- view/styles.py +76 -0
- view/utils.py +60 -0
view/slurm_list.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from view.styles import _format_to, cmdstyle
|
|
4
|
+
from view.utils import is_cvcs_viz, is_student_viz, is_dev, is_prod
|
|
5
|
+
|
|
6
|
+
midlane = "─────────── ▲ DEV ──────────────────────────────── ▼ PROD ────────────"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def format_date(str_date):
|
|
10
|
+
return datetime.strftime(datetime.strptime(str_date, '%Y-%m-%dT%H:%M:%S'), '%m/%d-%H:%M')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _joblet_format(instance, job, width=74, jobid_type='agg'):
|
|
14
|
+
joblet_reprs = []
|
|
15
|
+
for i, joblet in enumerate(job.joblets):
|
|
16
|
+
jid = str(job.jobid if jobid_type == 'agg' else job.true_jobid)
|
|
17
|
+
joblet_repr = ''
|
|
18
|
+
joblet_repr += _format_to(jid.replace('[', '').replace(']', '').split('%')[0], 14)
|
|
19
|
+
joblet_repr += ' '
|
|
20
|
+
loffset = 0
|
|
21
|
+
if instance.show_prio:
|
|
22
|
+
joblet_repr += '(' + _format_to(job.priority, len(str(job.priority))) + ')'
|
|
23
|
+
joblet_repr += ' '
|
|
24
|
+
loffset += 9
|
|
25
|
+
if instance.show_account:
|
|
26
|
+
joblet_repr += _format_to(job.account, 9)
|
|
27
|
+
joblet_repr += ' '
|
|
28
|
+
loffset += 10
|
|
29
|
+
if instance.show_starttime:
|
|
30
|
+
joblet_repr += _format_to(format_date(job.starttime), 12) if not isinstance(job.starttime, float) else _format_to('¯\\_(ツ)_/¯', 11)
|
|
31
|
+
joblet_repr += ' '
|
|
32
|
+
loffset += 13
|
|
33
|
+
joblet_repr += _format_to(job.name if i == 0 else '"', width - 65 - loffset, 'right')
|
|
34
|
+
joblet_repr += ' '
|
|
35
|
+
joblet_repr += _format_to(job.user if i == 0 else '"', 13, 'right')
|
|
36
|
+
joblet_repr += ' '
|
|
37
|
+
joblet_repr += _format_to(job.state if i == 0 else '"', 2, 'right')
|
|
38
|
+
joblet_repr += ' '
|
|
39
|
+
joblet_repr += _format_to(job.runtime if i == 0 else '"', 8, 'right')
|
|
40
|
+
joblet_repr += ' '
|
|
41
|
+
if isinstance(joblet.mem, str):
|
|
42
|
+
mem = '0'
|
|
43
|
+
else:
|
|
44
|
+
mem = round(joblet.mem / 1024)
|
|
45
|
+
joblet_repr += _format_to(f'{mem}G', 4, 'right')
|
|
46
|
+
joblet_repr += ' '
|
|
47
|
+
if instance.view_mode in ('gpu', 'ram'):
|
|
48
|
+
joblet_repr += _format_to((f'{joblet.n_gpus}gp' if joblet.n_gpus > 0 else " - "), 3, 'left')
|
|
49
|
+
elif instance.view_mode == 'cpu':
|
|
50
|
+
joblet_repr += _format_to((f'{joblet.cpus}cp' if joblet.cpus > 0 else "-"), 3, 'left')
|
|
51
|
+
joblet_repr += ' '
|
|
52
|
+
joblet_repr += _format_to(joblet.node if joblet.node is not None else job.reason, 11)
|
|
53
|
+
joblet_reprs.append(joblet_repr)
|
|
54
|
+
job_repr = '\n'.join(joblet_reprs)
|
|
55
|
+
return job_repr
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
STYLE_MAPPING = {'R': None, 'S': 'MAGENTA', 'PD': 'YELLOW', 'CG': 'MAGENTA'}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def dev_sort_key(x):
|
|
62
|
+
return (x.user,
|
|
63
|
+
x.jobid.split('_')[0],
|
|
64
|
+
int(x.jobid.split('_')[1]) if '_' in x.jobid and '[' not in x.jobid else (999 if '[' in x.jobid else 0))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def prod_sort_key(x, instance):
|
|
68
|
+
return ((x.user if not instance.sort_by_prio else -x.priority,
|
|
69
|
+
x.jobid.split('_')[0],
|
|
70
|
+
int(x.jobid.split('_')[1]) if '_' in x.jobid and '[' not in x.jobid else (999 if '[' in x.jobid else 0)))
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def view_list(instance, jobs, filter=None, work=True, stylefn=cmdstyle, current_user=None, width=74, jit='agg'):
|
|
74
|
+
# this is for hot reload
|
|
75
|
+
if not work:
|
|
76
|
+
return "UPDATE IN PROGRESS - PLZ W8 M8 B8"
|
|
77
|
+
|
|
78
|
+
# who is the current user?
|
|
79
|
+
if current_user is None:
|
|
80
|
+
import os
|
|
81
|
+
current_user = os.path.basename(os.environ['HOME'])
|
|
82
|
+
|
|
83
|
+
# what will this function print?
|
|
84
|
+
printable = set()
|
|
85
|
+
if filter is None:
|
|
86
|
+
printable.add('me')
|
|
87
|
+
printable.add('prod')
|
|
88
|
+
printable.add('stud')
|
|
89
|
+
printable.add('cvcs')
|
|
90
|
+
elif filter == 'me':
|
|
91
|
+
printable.add('me')
|
|
92
|
+
elif filter == 'prod':
|
|
93
|
+
printable.add('prod')
|
|
94
|
+
elif filter == 'stud':
|
|
95
|
+
printable.add('stud')
|
|
96
|
+
elif filter == 'cvcs':
|
|
97
|
+
printable.add('cvcs')
|
|
98
|
+
|
|
99
|
+
jobs_to_print = []
|
|
100
|
+
for j in jobs:
|
|
101
|
+
if j.user == current_user and 'me' in printable:
|
|
102
|
+
jobs_to_print.append(j)
|
|
103
|
+
elif 'stud' in printable and is_student_viz(j):
|
|
104
|
+
jobs_to_print.append(j)
|
|
105
|
+
elif 'prod' in printable and not is_student_viz(j):
|
|
106
|
+
jobs_to_print.append(j)
|
|
107
|
+
elif 'cvcs' in printable and is_cvcs_viz(j):
|
|
108
|
+
jobs_to_print.append(j)
|
|
109
|
+
|
|
110
|
+
class RetScope:
|
|
111
|
+
return_string = ''
|
|
112
|
+
|
|
113
|
+
def cust_print(thing, style=None):
|
|
114
|
+
RetScope.return_string += (thing if style is None else stylefn(style, thing)) + '\n'
|
|
115
|
+
|
|
116
|
+
devjobs = sorted([x for x in jobs_to_print if is_dev(x)], key=lambda x: dev_sort_key(x))
|
|
117
|
+
|
|
118
|
+
for state in STYLE_MAPPING:
|
|
119
|
+
for x in devjobs:
|
|
120
|
+
if x.state == state:
|
|
121
|
+
cust_print(_joblet_format(instance, x, width=width, jobid_type=jit), style=STYLE_MAPPING[x.state])
|
|
122
|
+
|
|
123
|
+
cust_print('─' * ((width - 72) // 2) + midlane + '─' * (width - 72 - ((width - 72) // 2)))
|
|
124
|
+
|
|
125
|
+
prodjobs = sorted([x for x in jobs_to_print if not is_dev(x)], key=lambda x: prod_sort_key(x, instance))
|
|
126
|
+
|
|
127
|
+
for state in STYLE_MAPPING:
|
|
128
|
+
for x in prodjobs:
|
|
129
|
+
if x.state == state:
|
|
130
|
+
cust_print(_joblet_format(instance, x, width=width, jobid_type=jit), style=STYLE_MAPPING[x.state])
|
|
131
|
+
|
|
132
|
+
return RetScope.return_string
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if __name__ == '__main__':
|
|
136
|
+
import sys
|
|
137
|
+
|
|
138
|
+
from curses_multiwindow import Singleton
|
|
139
|
+
|
|
140
|
+
from readers.slurmreader import read_jobs
|
|
141
|
+
instance = Singleton.getInstance()
|
|
142
|
+
jobs, _ = read_jobs()
|
|
143
|
+
if len(sys.argv) > 1 and sys.argv[1] == 'work':
|
|
144
|
+
print(view_list(instance, jobs, work=True, filter='me'))
|
|
145
|
+
elif len(sys.argv) > 1:
|
|
146
|
+
print(view_list(instance, jobs, filter=sys.argv[1]))
|
|
147
|
+
else:
|
|
148
|
+
print(view_list(instance, jobs))
|
view/slurm_viz.py
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
from view.styles import _format_to, cmdstyle
|
|
6
|
+
from view.utils import is_cvcs_viz, is_student_viz, maintenance_status, to_font
|
|
7
|
+
|
|
8
|
+
ogre = '''⢀⡴⠑⡄⠀⠀⠀⠀⠀⠀⠀⣀⣀⣤⣤⣤⣀⡀⠀⠀⠀⠀⠀⠀
|
|
9
|
+
⠸⡇⠀⠿⡀⠀⠀⠀⣀⡴⢿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
10
|
+
⠀⠀⠀⠀⠑⢄⣠⠾⠁⣀⣄⡈⠙⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀
|
|
11
|
+
⠀⠀⠀⠀⢀⡀⠁⠀⠀⠈⠙⠛⠂⠈⣿⣿⣿⣿⣿⠿⡿⢿⣆⠀⠀⠀⠀⠀⠀⠀
|
|
12
|
+
⠀⠀⠀⢀⡾⣁⣀⠀⠴⠂⠙⣗⡀⠀⢻⣿⣿⠭⢤⣴⣦⣤⣹⠀⠀⠀⢀⢴⣶⣆
|
|
13
|
+
⠀⠀⢀⣾⣿⣿⣿⣷⣮⣽⣾⣿⣥⣴⣿⣿⡿⢂⠔⢚⡿⢿⣿⣦⣴⣾⠸⣼⡿
|
|
14
|
+
⠀⢀⡞⠁⠙⠻⠿⠟⠉⠀⠛⢹⣿⣿⣿⣿⣿⣌⢤⣼⣿⣾⣿⡟⠉⠀⠀⠀⠀
|
|
15
|
+
⠀⣾⣷⣶⠇⠀⠀⣤⣄⣀⡀⠈⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀
|
|
16
|
+
⠀⠉⠈⠉⠀⠀⢦⡈⢻⣿⣿⣿⣶⣶⣶⣶⣤⣽⡹⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀
|
|
17
|
+
⠀⠀⠀⠀⠀⠀⠀⠉⠲⣽⡻⢿⣿⣿⣿⣿⣿⣿⣷⣜⣿⣿⣿⡇⠀⠀⠀⠀⠀
|
|
18
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣷⣶⣮⣭⣽⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀
|
|
19
|
+
⠀⠀⠀⠀⠀⠀⣀⣀⣈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
|
20
|
+
⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀
|
|
21
|
+
⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀
|
|
22
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠻⠿⠿⠿⠿⠛⠉
|
|
23
|
+
'''
|
|
24
|
+
flip = ''' ⣰⣾⣿⣿⣿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣆
|
|
25
|
+
⣿⣿⣿⡿⠋⠄⡀⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠋⣉⣉⣉⡉⠙⠻⣿⣿
|
|
26
|
+
⣿⣿⣿⣇⠔⠈⣿⣿⣿⣿⣿⡿⠛⢉⣤⣶⣾⣿⣿⣿⣿⣿⣿⣦⡀⠹
|
|
27
|
+
⣿⣿⠃⠄⢠⣾⣿⣿⣿⠟⢁⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄
|
|
28
|
+
⣿⣿⣿⣿⣿⣿⣿⠟⢁⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷
|
|
29
|
+
⣿⣿⣿⣿⣿⡟⠁⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
30
|
+
⣿⣿⣿⣿⠋⢠⣾⣿⣿⣿⣿⣿⣿⡿⠿⠿⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
31
|
+
⣿⣿⡿⠁⣰⣿⣿⣿⣿⣿⣿⣿⣿⠗⠄⠄⠄⠄⣿⣿⣿⣿⣿⣿⣿⡟
|
|
32
|
+
⣿⡿⠁⣼⣿⣿⣿⣿⣿⣿⡿⠋⠄⠄⠄⣠⣄⢰⣿⣿⣿⣿⣿⣿⣿⠃
|
|
33
|
+
⡿⠁⣼⣿⣿⣿⣿⣿⣿⣿⡇⠄⢀⡴⠚⢿⣿⣿⣿⣿⣿⣿⣿⣿⡏⢠
|
|
34
|
+
⠃⢰⣿⣿⣿⣿⣿⣿⡿⣿⣿⠴⠋⠄⠄⢸⣿⣿⣿⣿⣿⣿⣿⡟⢀⣾
|
|
35
|
+
⢀⣿⣿⣿⣿⣿⣿⣿⠃⠈⠁⠄⠄⢀⣴⣿⣿⣿⣿⣿⣿⣿⡟⢀⣾⣿
|
|
36
|
+
⢸⣿⣿⣿⣿⣿⣿⣿⠄⠄⠄⠄⢶⣿⣿⣿⣿⣿⣿⣿⣿⠏⢀⣾⣿⣿
|
|
37
|
+
⣿⣿⣿⣿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣿⣿⠋⣠⣿⣿⣿⣿
|
|
38
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢁⣼⣿⣿⣿⣿⣿
|
|
39
|
+
⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢁⣴⣿⣿⣿⣿⣿⣿⣿
|
|
40
|
+
⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⢁⣴⣿⣿⣿⣿⠗⠄⠄⣿⣿
|
|
41
|
+
⣆⠈⠻⢿⣿⣿⣿⣿⣿⣿⠿⠛⣉⣤⣾⣿⣿⣿⣿⣿⣇⠠⠺⣷⣿⣿
|
|
42
|
+
⣿⣿⣦⣄⣈⣉⣉⣉⣡⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⠉⠁⣀⣼⣿⣿⣿
|
|
43
|
+
⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣾⣿⣿⡿⠟
|
|
44
|
+
'''
|
|
45
|
+
chunga = '''⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣧⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
46
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣧⠀⠀⠀⢰⡿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
47
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡟⡆⠀⠀⣿⡇⢻⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
48
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⣿⠀⢰⣿⡇⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
49
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡄⢸⠀⢸⣿⡇⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
50
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡇⢸⡄⠸⣿⡇⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
51
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⢸⡅⠀⣿⢠⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
52
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣥⣾⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
53
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀
|
|
54
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⡿⡿⣿⣿⡿⡅⠀⠀⠀⠀⠀⠀⠀
|
|
55
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠉⠀⠉⡙⢔⠛⣟⢋⠦⢵⠀⠀⠀⠀⠀⠀
|
|
56
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣄⠀⠀⠁⣿⣯⡥⠃⠀⢳⠀⠀⠀⠀⠀⠀
|
|
57
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡇⠀⠀⠀⠐⠠⠊⢀⠀⢸⠀⠀⠀⠀⠀⠀
|
|
58
|
+
⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⡿⠀⠀⠀⠀⠀⠈⠁⠀⠀⠘⣿⣄⠀⠀⠀⠀
|
|
59
|
+
⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣷⡀⠀⠀
|
|
60
|
+
⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣧⠀
|
|
61
|
+
⠀⠀⠀⡜⣭⠤⢍⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⢛⢭⣗
|
|
62
|
+
⠀⠀⠀⠁⠈⠀⠀⣀⠝⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠠⠀⠀⠰⡅
|
|
63
|
+
⠀⠀⠀⢀⠀⠀⡀⠡⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠔⠠⡕
|
|
64
|
+
⠀⠀⠀⠀⣿⣷⣶⠒⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⠀⠀
|
|
65
|
+
⠀⠀⠀⠀⠘⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀
|
|
66
|
+
⠀⠀⠀⠀⠀⠈⢿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠊⠉⢆⠀⠀⠀
|
|
67
|
+
⠀⢀⠤⠀⠀⢤⣤⣽⣿⣿⣦⣀⢀⡠⢤⡤⠄⠀⠒⠀⠁⠀⠀⠀⢘⠔⠀
|
|
68
|
+
⠀⠀⠀⡐⠈⠁⠈⠛⣛⠿⠟⠑⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
69
|
+
⠀⠀⠉⠑⠒⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
70
|
+
'''
|
|
71
|
+
|
|
72
|
+
gpu_avail = '□'
|
|
73
|
+
gpu_occ = '■'
|
|
74
|
+
gpu_drain = '△'
|
|
75
|
+
gpu_pendr = '⧖'
|
|
76
|
+
gpu_down = '⨯'
|
|
77
|
+
gpu_paused = '◆'
|
|
78
|
+
gpu_name_chars = 12
|
|
79
|
+
gpu_box_chars = 16
|
|
80
|
+
|
|
81
|
+
mem_size = 16
|
|
82
|
+
mem_unit = 'ᴳ'
|
|
83
|
+
ram_occ = '█' # '▄'#
|
|
84
|
+
ram_occ_alt = '▀'
|
|
85
|
+
ram_avail = '░'
|
|
86
|
+
ram_drain = '△'
|
|
87
|
+
ram_pendr = '⧖'
|
|
88
|
+
ram_paused = '▚'
|
|
89
|
+
ram_down = '⨯'
|
|
90
|
+
|
|
91
|
+
cpu_size = 4
|
|
92
|
+
cpu_unit = 'ᶜᵖᵘ'
|
|
93
|
+
cpu_occ = '█' # '▄'#
|
|
94
|
+
cpu_occ_alt = '▀'
|
|
95
|
+
cpu_avail = '░'
|
|
96
|
+
cpu_half = '▌'
|
|
97
|
+
cpu_drain = '△'
|
|
98
|
+
cpu_pendr = '⧖'
|
|
99
|
+
cpu_paused = '▚'
|
|
100
|
+
cpu_down = '⨯'
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_ram_block(megs):
|
|
104
|
+
return int(round(megs / 1024 / mem_size))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def get_cpu_block(cpus):
|
|
108
|
+
return cpus // cpu_size
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def view_viz(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None, mode='gpu'):
|
|
112
|
+
if mode == 'gpu':
|
|
113
|
+
return view_viz_gpu(infrastructure, jobs, work, stylefn, current_user)
|
|
114
|
+
elif mode == 'ram':
|
|
115
|
+
return view_viz_ram(infrastructure, jobs, work, stylefn, current_user)
|
|
116
|
+
elif mode == 'cpu':
|
|
117
|
+
return view_viz_cpu(infrastructure, jobs, work, stylefn, current_user)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def view_viz_ram(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None):
|
|
121
|
+
# this is for hot reload
|
|
122
|
+
if not work:
|
|
123
|
+
return "UPDATE IN PROGRESS - PLZ W8 M8 B8"
|
|
124
|
+
|
|
125
|
+
# who is the current user?
|
|
126
|
+
if current_user is None:
|
|
127
|
+
import os
|
|
128
|
+
current_user = os.path.basename(os.environ['HOME'])
|
|
129
|
+
|
|
130
|
+
nodes = infrastructure.get_sorted_nodes()
|
|
131
|
+
infrast_down = all([x.status == 'down' for x in nodes])
|
|
132
|
+
|
|
133
|
+
class RetScope:
|
|
134
|
+
return_string = ''
|
|
135
|
+
|
|
136
|
+
def cust_print(thing, style=None):
|
|
137
|
+
RetScope.return_string += (thing if style is None else stylefn(style, thing)) + '\n'
|
|
138
|
+
|
|
139
|
+
if not infrast_down:
|
|
140
|
+
highlighted_users = [current_user]
|
|
141
|
+
highlighted_users += pd.DataFrame([(j.user, sum([get_ram_block(x.mem) for x in j.joblets])) for j in jobs if j.user !=
|
|
142
|
+
current_user and j.state in ('R', 'S')]).groupby(0).sum()[1].sort_values(ascending=False).iloc[:3].index.to_list()
|
|
143
|
+
|
|
144
|
+
user_styles = dict(zip(highlighted_users, ['RED', 'YELLOW', 'GREEN', 'MAGENTA', 'BLUE']))
|
|
145
|
+
students = [j.user for j in jobs if is_student_viz(j)]
|
|
146
|
+
for s in students:
|
|
147
|
+
user_styles[s] = 'CYAN'
|
|
148
|
+
|
|
149
|
+
cvcs_students = [j.user for j in jobs if is_cvcs_viz(j)]
|
|
150
|
+
for s in cvcs_students:
|
|
151
|
+
user_styles[s] = 'BLUE'
|
|
152
|
+
|
|
153
|
+
stalled_jobs = sum([j.state == 'S' for j in jobs])
|
|
154
|
+
total_jobs_prod = 0
|
|
155
|
+
total_jobs_stud = 0
|
|
156
|
+
|
|
157
|
+
# print jobs
|
|
158
|
+
for n in nodes:
|
|
159
|
+
joblet_icons = []
|
|
160
|
+
occs = 0
|
|
161
|
+
for j in sorted(jobs, key=lambda x: (x.partition, x.user)):
|
|
162
|
+
for jj in j.joblets:
|
|
163
|
+
if n.name == jj.node:
|
|
164
|
+
if j.is_student() and 'all_usr_prod' in j.partition:
|
|
165
|
+
total_jobs_stud += int(round((jj.mem) / 1024))
|
|
166
|
+
elif 'all_usr_prod' in j.partition:
|
|
167
|
+
total_jobs_prod += int(round((jj.mem) / 1024))
|
|
168
|
+
occs += jj.mem
|
|
169
|
+
icon = ram_paused if j.state == 'S' else ram_occ
|
|
170
|
+
st = icon * get_ram_block(jj.mem)
|
|
171
|
+
joblet_icons.append((st, user_styles[j.user] if j.user in user_styles else None))
|
|
172
|
+
joblet_icons += [(ram_drain if n.status == 'drain' else (ram_down if n.status == 'down' else (ram_pendr if n.reserved == 'pending' else ram_avail)), None)] * get_ram_block(n.mem - occs)
|
|
173
|
+
|
|
174
|
+
jobsplit = [""]
|
|
175
|
+
count = 0
|
|
176
|
+
for ic, c in joblet_icons:
|
|
177
|
+
for i in ic:
|
|
178
|
+
if count == gpu_box_chars - 3:
|
|
179
|
+
jobsplit.append("")
|
|
180
|
+
count = 0
|
|
181
|
+
bb = ram_occ_alt if len(jobsplit) > 1 and i == ram_occ else i
|
|
182
|
+
jobsplit[-1] += stylefn(c, bb) if c is not None else bb
|
|
183
|
+
count += 1
|
|
184
|
+
# if count < gpu_box_chars:
|
|
185
|
+
jobsplit[-1] += f'{to_font(int((n.mem-occs) / 1024))}'
|
|
186
|
+
|
|
187
|
+
for i, l in enumerate(jobsplit):
|
|
188
|
+
RetScope.return_string += f'{_format_to(n.name if i == 0 else "", gpu_name_chars, "right")}{"(" if n.reserved == "yes" and i == 0 else " "}{l}{")" if n.reserved == "yes" and i == (len(jobsplit) - 1) else ""}\n'
|
|
189
|
+
|
|
190
|
+
# verify maintenance status
|
|
191
|
+
onmain, waitString = maintenance_status(infrastructure)
|
|
192
|
+
|
|
193
|
+
# print banner
|
|
194
|
+
if onmain:
|
|
195
|
+
cust_print(' ◀ ONGOING MAINTENANCE ▶ ', 'BG_MAGENTA')
|
|
196
|
+
elif len(infrastructure.maintenances):
|
|
197
|
+
cust_print(' ◀ MAINTENANCE in %4s ▶ ' % waitString, 'BG_MAGENTA')
|
|
198
|
+
elif len(jobs) == 0:
|
|
199
|
+
cust_print(' ◀ NO JOBS ▶ ', 'BG_GREEN')
|
|
200
|
+
elif stalled_jobs / len(jobs) > 0.5:
|
|
201
|
+
cust_print(' ◀ JOBS ON HOLD ▶ ', 'BG_YELLOW')
|
|
202
|
+
else:
|
|
203
|
+
cust_print('')
|
|
204
|
+
|
|
205
|
+
cust_print(''.join(['[' + ram_occ + f'{mem_size}{mem_unit}', ram_paused + 'hld', ram_drain + 'drn', ram_pendr + 'pnd', ram_down + 'dwn', '()res]']))
|
|
206
|
+
gpuc = 'GREEN'
|
|
207
|
+
|
|
208
|
+
cust_print(' '.join([" ram:", stylefn(gpuc, (f"{int(round(infrastructure.ram_limit_pu / 1024)):4d}{mem_unit}")
|
|
209
|
+
if not pd.isna(infrastructure.ram_limit_pu) else " ∞"),
|
|
210
|
+
" grp:", stylefn(gpuc, f"{total_jobs_prod:4d}{mem_unit}/{int(round(infrastructure.ram_limit_grp / 1024))}{mem_unit}"
|
|
211
|
+
if not pd.isna(infrastructure.ram_limit_grp) else " ∞")]))
|
|
212
|
+
cust_print(' '.join([" Sram:", stylefn('CYAN', (f"{int(round(infrastructure.ram_limit_stu / 1024)):4d}{mem_unit}")
|
|
213
|
+
if not pd.isna(infrastructure.ram_limit_stu) else " ∞"),
|
|
214
|
+
"Sgrp:", stylefn('CYAN', f"{total_jobs_stud:4d}{mem_unit}/{int(round(infrastructure.ram_limit_stugrp / 1024))}{mem_unit}"
|
|
215
|
+
if not pd.isna(infrastructure.ram_limit_stugrp) else " ∞")]))
|
|
216
|
+
|
|
217
|
+
# print user list
|
|
218
|
+
for u, c in user_styles.items():
|
|
219
|
+
if c in ('CYAN', 'BLUE'):
|
|
220
|
+
continue
|
|
221
|
+
cust_print(
|
|
222
|
+
f" {stylefn(c, gpu_occ)} {stylefn('CYAN', u) if any(['stu' in j.partition for j in jobs if j.user == u]) else u} ({int(round(sum([sum([jj.mem / 1024 for jj in j.joblets if jj.node is not None]) for j in jobs if j.user == u])))}{mem_unit})")
|
|
223
|
+
cust_print(f" {stylefn('CYAN', gpu_occ)} {stylefn('CYAN', 'students')}")
|
|
224
|
+
cust_print(f" {stylefn('BLUE', gpu_occ)} {stylefn('BLUE', 'cvcs/ai4a')}")
|
|
225
|
+
|
|
226
|
+
else: # if infrastrcture_down
|
|
227
|
+
# print emergency screen
|
|
228
|
+
cust_print(' ◀ INFRASTRUCTURE IS DOWN ▶ ', 'BG_RED')
|
|
229
|
+
cust_print(random.choice([flip, chunga, ogre]), 'GREEN')
|
|
230
|
+
|
|
231
|
+
return RetScope.return_string
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def view_viz_gpu(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None):
|
|
235
|
+
# this is for hot reload
|
|
236
|
+
if not work:
|
|
237
|
+
return "UPDATE IN PROGRESS - PLZ W8 M8 B8"
|
|
238
|
+
|
|
239
|
+
# who is the current user?
|
|
240
|
+
if current_user is None:
|
|
241
|
+
import os
|
|
242
|
+
current_user = os.path.basename(os.environ['HOME'])
|
|
243
|
+
|
|
244
|
+
nodes = infrastructure.get_sorted_nodes()
|
|
245
|
+
infrast_down = all([x.status == 'down' for x in nodes])
|
|
246
|
+
|
|
247
|
+
class RetScope:
|
|
248
|
+
return_string = ''
|
|
249
|
+
|
|
250
|
+
def cust_print(thing, style=None):
|
|
251
|
+
RetScope.return_string += (thing if style is None else stylefn(style, thing)) + '\n'
|
|
252
|
+
|
|
253
|
+
if not infrast_down:
|
|
254
|
+
highlighted_users = [current_user]
|
|
255
|
+
highlighted_users += pd.DataFrame([(j.user, sum([x.n_gpus for x in j.joblets])) for j in jobs if j.user != current_user and j.state in ('R', 'S')]
|
|
256
|
+
).groupby(0).sum()[1].sort_values(ascending=False).iloc[:3].index.to_list()
|
|
257
|
+
|
|
258
|
+
user_styles = dict(zip(highlighted_users, ['RED', 'YELLOW', 'GREEN', 'MAGENTA', 'BLUE']))
|
|
259
|
+
students = [j.user for j in jobs if is_student_viz(j)]
|
|
260
|
+
for s in students:
|
|
261
|
+
user_styles[s] = 'CYAN'
|
|
262
|
+
|
|
263
|
+
cvcs_students = [j.user for j in jobs if is_cvcs_viz(j)]
|
|
264
|
+
for s in cvcs_students:
|
|
265
|
+
user_styles[s] = 'BLUE'
|
|
266
|
+
|
|
267
|
+
stalled_jobs = sum([j.state == 'S' for j in jobs])
|
|
268
|
+
total_jobs_prod = 0
|
|
269
|
+
total_jobs_stud = 0
|
|
270
|
+
|
|
271
|
+
# print jobs
|
|
272
|
+
for n in nodes:
|
|
273
|
+
joblet_icons = []
|
|
274
|
+
occs = 0
|
|
275
|
+
for j in jobs:
|
|
276
|
+
for jj in j.joblets:
|
|
277
|
+
if jj.n_gpus == 0:
|
|
278
|
+
continue
|
|
279
|
+
if n.name == jj.node:
|
|
280
|
+
if j.is_student() and 'all_usr_prod' in j.partition:
|
|
281
|
+
total_jobs_stud += jj.n_gpus
|
|
282
|
+
elif 'all_usr_prod' in j.partition:
|
|
283
|
+
total_jobs_prod += jj.n_gpus
|
|
284
|
+
occs += jj.n_gpus
|
|
285
|
+
icon = gpu_paused if j.state == 'S' else gpu_occ
|
|
286
|
+
st = icon + (('+' if len(j.joblets) > 1 else '-') + icon) * (jj.n_gpus - 1)
|
|
287
|
+
joblet_icons.append((st, user_styles[j.user] if j.user in user_styles else None))
|
|
288
|
+
joblet_icons += [(gpu_drain if n.status == 'drain' else (gpu_down if n.status == 'down' else (gpu_pendr if n.reserved == 'pending' else gpu_avail)), None)] * (n.n_gpus - occs)
|
|
289
|
+
|
|
290
|
+
joblet_icons = [(ji[0] + (' ' if i != len(joblet_icons) - 1 else ''), ji[1]) for i, ji in enumerate(joblet_icons)]
|
|
291
|
+
|
|
292
|
+
jobsplit = [""]
|
|
293
|
+
count = 0
|
|
294
|
+
for ic, c in joblet_icons:
|
|
295
|
+
for i in ic:
|
|
296
|
+
if count == gpu_box_chars:
|
|
297
|
+
jobsplit.append("")
|
|
298
|
+
count = 0
|
|
299
|
+
jobsplit[-1] += stylefn(c, i) if c is not None else i
|
|
300
|
+
count += 1
|
|
301
|
+
|
|
302
|
+
for i, l in enumerate(jobsplit):
|
|
303
|
+
RetScope.return_string += f'{_format_to(n.name if i == 0 else "", gpu_name_chars, "right")}{"(" if n.reserved == "yes" and i == 0 else " "}{l}{")" if n.reserved == "yes" and i == (len(jobsplit) - 1) else ""}\n'
|
|
304
|
+
|
|
305
|
+
# verify maintenance status
|
|
306
|
+
onmain, waitString = maintenance_status(infrastructure)
|
|
307
|
+
|
|
308
|
+
# print banner
|
|
309
|
+
if onmain:
|
|
310
|
+
cust_print(' ◀ ONGOING MAINTENANCE ▶ ', 'BG_MAGENTA')
|
|
311
|
+
elif len(infrastructure.maintenances):
|
|
312
|
+
cust_print(' ◀ MAINTENANCE in %4s ▶ ' % waitString, 'BG_MAGENTA')
|
|
313
|
+
elif len(jobs) == 0:
|
|
314
|
+
cust_print(' ◀ NO JOBS ▶ ', 'BG_GREEN')
|
|
315
|
+
elif stalled_jobs / len(jobs) > 0.5:
|
|
316
|
+
cust_print(' ◀ JOBS ON HOLD ▶ ', 'BG_YELLOW')
|
|
317
|
+
else:
|
|
318
|
+
cust_print('')
|
|
319
|
+
|
|
320
|
+
# print summary
|
|
321
|
+
cust_print(''.join([' [' + gpu_occ + 'run', gpu_paused + 'hld', gpu_drain + 'drn', gpu_pendr + 'pnd', gpu_down + 'dwn', '()res]']))
|
|
322
|
+
gpuc = 'RED'
|
|
323
|
+
if infrastructure.gpu_limit_pu > 3:
|
|
324
|
+
gpuc = 'YELLOW'
|
|
325
|
+
if infrastructure.gpu_limit_pu > 6:
|
|
326
|
+
gpuc = 'GREEN'
|
|
327
|
+
cust_print(' '.join([" gpu:", stylefn(gpuc, ("%2d" % infrastructure.gpu_limit_pu) if not pd.isna(infrastructure.gpu_limit_pu) else " ∞"), " grp:",
|
|
328
|
+
stylefn(gpuc, "%2d/%s") % (total_jobs_prod, ("%2d" % infrastructure.gpu_limit_grp) if not pd.isna(infrastructure.gpu_limit_grp) else " ∞")]))
|
|
329
|
+
cust_print(' '.join([" Sgpu:", stylefn('CYAN', ("%2d" % infrastructure.gpu_limit_stu) if not pd.isna(infrastructure.gpu_limit_stu) else " ∞"), "Sgrp:",
|
|
330
|
+
stylefn('CYAN', "%2d/%s") % (total_jobs_stud, ("%2d" % infrastructure.gpu_limit_stugrp) if not pd.isna(infrastructure.gpu_limit_stugrp) else " ∞")]))
|
|
331
|
+
|
|
332
|
+
# print user list
|
|
333
|
+
for u, c in user_styles.items():
|
|
334
|
+
if c in ('CYAN', 'BLUE'):
|
|
335
|
+
continue
|
|
336
|
+
cust_print(
|
|
337
|
+
f" {stylefn(c, gpu_occ)} {stylefn('CYAN', u) if any(['stu' in j.partition for j in jobs if j.user == u]) else u} ({sum([sum([jj.n_gpus for jj in j.joblets if jj.node is not None]) for j in jobs if j.user == u])})")
|
|
338
|
+
cust_print(f" {stylefn('CYAN', gpu_occ)} {stylefn('CYAN', 'students')} ({sum([sum([jj.n_gpus for jj in j.joblets if jj.node is not None]) for j in jobs if is_student_viz(j)])})")
|
|
339
|
+
cust_print(f" {stylefn('BLUE', gpu_occ)} {stylefn('BLUE', 'cvcs/ai4a')} ({sum([sum([jj.n_gpus for jj in j.joblets if jj.node is not None]) for j in jobs if is_cvcs_viz(j)])})")
|
|
340
|
+
|
|
341
|
+
else: # if infrastrcture_down
|
|
342
|
+
# print emergency screen
|
|
343
|
+
cust_print(' ◀ INFRASTRUCTURE IS DOWN ▶ ', 'BG_RED')
|
|
344
|
+
cust_print(random.choice([flip, chunga, ogre]), 'GREEN')
|
|
345
|
+
|
|
346
|
+
return RetScope.return_string
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def get_cpu_icon(stat):
|
|
350
|
+
return {
|
|
351
|
+
'drain': cpu_drain,
|
|
352
|
+
'down': cpu_down,
|
|
353
|
+
'pending': cpu_pendr,
|
|
354
|
+
}.get(stat, cpu_avail)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def view_viz_cpu(infrastructure, jobs, work=True, stylefn=cmdstyle, current_user=None):
|
|
358
|
+
# this is for hot reload
|
|
359
|
+
if not work:
|
|
360
|
+
return "UPDATE IN PROGRESS - PLZ W8 M8 B8"
|
|
361
|
+
|
|
362
|
+
# who is the current user?
|
|
363
|
+
if current_user is None:
|
|
364
|
+
import os
|
|
365
|
+
current_user = os.path.basename(os.environ['HOME'])
|
|
366
|
+
|
|
367
|
+
nodes = infrastructure.get_sorted_nodes()
|
|
368
|
+
infrast_down = all([x.status == 'down' for x in nodes])
|
|
369
|
+
|
|
370
|
+
class RetScope:
|
|
371
|
+
return_string = ''
|
|
372
|
+
|
|
373
|
+
def cust_print(thing, style=None):
|
|
374
|
+
RetScope.return_string += (thing if style is None else stylefn(style, thing)) + '\n'
|
|
375
|
+
|
|
376
|
+
if not infrast_down:
|
|
377
|
+
highlighted_users = [current_user]
|
|
378
|
+
highlighted_users += pd.DataFrame([(j.user, sum([x.cpus for x in j.joblets])) for j in jobs if j.user != current_user and j.state in ('R', 'S')]
|
|
379
|
+
).groupby(0).sum()[1].sort_values(ascending=False).iloc[:3].index.to_list()
|
|
380
|
+
|
|
381
|
+
user_styles = dict(zip(highlighted_users, ['RED', 'YELLOW', 'GREEN', 'MAGENTA', 'BLUE']))
|
|
382
|
+
students = [j.user for j in jobs if is_student_viz(j)]
|
|
383
|
+
for s in students:
|
|
384
|
+
user_styles[s] = 'CYAN'
|
|
385
|
+
|
|
386
|
+
cvcs_students = [j.user for j in jobs if is_cvcs_viz(j)]
|
|
387
|
+
for s in cvcs_students:
|
|
388
|
+
user_styles[s] = 'BLUE'
|
|
389
|
+
|
|
390
|
+
stalled_jobs = sum([j.state == 'S' for j in jobs])
|
|
391
|
+
total_jobs_prod = 0
|
|
392
|
+
total_jobs_stud = 0
|
|
393
|
+
|
|
394
|
+
# print jobs
|
|
395
|
+
for n in nodes:
|
|
396
|
+
joblet_icons = []
|
|
397
|
+
occs = 0
|
|
398
|
+
none_st = 0
|
|
399
|
+
for j in sorted(jobs, key=lambda x: (x.partition, x.user)):
|
|
400
|
+
for jj in j.joblets:
|
|
401
|
+
if n.name == jj.node:
|
|
402
|
+
if j.is_student() and 'all_usr_prod' in j.partition:
|
|
403
|
+
total_jobs_stud += jj.cpus
|
|
404
|
+
elif 'all_usr_prod' in j.partition:
|
|
405
|
+
total_jobs_prod += jj.cpus
|
|
406
|
+
occs += jj.cpus
|
|
407
|
+
icon = cpu_paused if j.state == 'S' else cpu_occ
|
|
408
|
+
st = icon * get_cpu_block(jj.cpus)
|
|
409
|
+
if st == '':
|
|
410
|
+
none_st += jj.cpus
|
|
411
|
+
joblet_icons.append((st, user_styles[j.user] if j.user in user_styles else None))
|
|
412
|
+
if none_st > 0:
|
|
413
|
+
joblet_icons += [(cpu_occ, None)] * get_cpu_block(none_st)
|
|
414
|
+
if none_st % cpu_size != 0:
|
|
415
|
+
joblet_icons.append((cpu_occ_alt, None))
|
|
416
|
+
joblet_icons += [(get_cpu_icon(n.status), None)] * get_cpu_block(n.cpus - occs)
|
|
417
|
+
|
|
418
|
+
jobsplit = [""]
|
|
419
|
+
count = 0
|
|
420
|
+
for ic, c in joblet_icons:
|
|
421
|
+
for i in ic:
|
|
422
|
+
if count == gpu_box_chars - 3:
|
|
423
|
+
jobsplit.append("")
|
|
424
|
+
count = 0
|
|
425
|
+
bb = cpu_occ_alt if len(jobsplit) > 1 and i == cpu_occ else i
|
|
426
|
+
jobsplit[-1] += stylefn(c, bb) if c is not None else bb
|
|
427
|
+
count += 1
|
|
428
|
+
# if count < gpu_box_chars:
|
|
429
|
+
jobsplit[-1] += f'{to_font(n.cpus-occs)}/{to_font(n.cpus)}'
|
|
430
|
+
|
|
431
|
+
for i, l in enumerate(jobsplit):
|
|
432
|
+
RetScope.return_string += f'{_format_to(n.name if i == 0 else "", gpu_name_chars, "right")}{"(" if n.reserved == "yes" and i == 0 else " "}{l}{")" if n.reserved == "yes" and i == (len(jobsplit) - 1) else ""}\n'
|
|
433
|
+
|
|
434
|
+
# verify maintenance status
|
|
435
|
+
onmain, waitString = maintenance_status(infrastructure)
|
|
436
|
+
|
|
437
|
+
# print banner
|
|
438
|
+
if onmain:
|
|
439
|
+
cust_print(' ◀ ONGOING MAINTENANCE ▶ ', 'BG_MAGENTA')
|
|
440
|
+
elif len(infrastructure.maintenances):
|
|
441
|
+
cust_print(' ◀ MAINTENANCE in %4s ▶ ' % waitString, 'BG_MAGENTA')
|
|
442
|
+
elif len(jobs) == 0:
|
|
443
|
+
cust_print(' ◀ NO JOBS ▶ ', 'BG_GREEN')
|
|
444
|
+
elif stalled_jobs / len(jobs) > 0.5:
|
|
445
|
+
cust_print(' ◀ JOBS ON HOLD ▶ ', 'BG_YELLOW')
|
|
446
|
+
else:
|
|
447
|
+
cust_print('')
|
|
448
|
+
|
|
449
|
+
# print summary
|
|
450
|
+
# cust_print(''.join([' ['+ ram_occ + 'run', paused + 'hld', drain + 'drn', down + 'dwn', '()res]']))
|
|
451
|
+
cust_print(''.join(['[' + ram_occ + f'{cpu_size}{cpu_unit}', cpu_paused + 'hld', cpu_drain + 'drn', cpu_pendr + 'pnd', cpu_down + 'dwn', '()res]']))
|
|
452
|
+
gpuc = 'GREEN'
|
|
453
|
+
# if infrastructure.gpu_limit_pu > 3:
|
|
454
|
+
# gpuc = 'YELLOW'
|
|
455
|
+
# if infrastructure.gpu_limit_pu > 6:
|
|
456
|
+
# gpuc = 'GREEN'
|
|
457
|
+
cust_print(' '.join([" cpu:", stylefn(gpuc, (f"{int(round(infrastructure.cpu_limit_pu)):4d}{cpu_size}")
|
|
458
|
+
if not pd.isna(infrastructure.cpu_limit_pu) else " ∞"),
|
|
459
|
+
" grp:", stylefn(gpuc, f"{total_jobs_prod:4d}{cpu_size}/{int(round(infrastructure.cpu_limit_grp))}{cpu_size}"
|
|
460
|
+
if not pd.isna(infrastructure.cpu_limit_grp) else " ∞ ")]))
|
|
461
|
+
cust_print(' '.join([" Scpu:", stylefn('CYAN', (f"{int(round(infrastructure.cpu_limit_stu)):4d}{cpu_size}")
|
|
462
|
+
if not pd.isna(infrastructure.cpu_limit_stu) else " ∞"),
|
|
463
|
+
"Sgrp:", stylefn('CYAN', f"{total_jobs_stud:4d}{cpu_size}/{int(round(infrastructure.cpu_limit_stugrp))}{cpu_size}"
|
|
464
|
+
if not pd.isna(infrastructure.cpu_limit_stugrp) else " ∞ ")]))
|
|
465
|
+
|
|
466
|
+
# print user list
|
|
467
|
+
for u, c in user_styles.items():
|
|
468
|
+
if c in ('CYAN', 'BLUE'):
|
|
469
|
+
continue
|
|
470
|
+
cust_print(
|
|
471
|
+
f" {stylefn(c, gpu_occ)} {stylefn('CYAN', u) if any(['stu' in j.partition for j in jobs if j.user == u]) else u} ({sum([sum([jj.cpus for jj in j.joblets if jj.node is not None]) for j in jobs if j.user == u])}{cpu_unit})")
|
|
472
|
+
cust_print(f" {stylefn('CYAN', gpu_occ)} {stylefn('CYAN', 'students')}")
|
|
473
|
+
cust_print(f" {stylefn('BLUE', gpu_occ)} {stylefn('BLUE', 'cvcs/ai4a')}")
|
|
474
|
+
|
|
475
|
+
else: # if infrastrcture_down
|
|
476
|
+
# print emergency screen
|
|
477
|
+
cust_print(' ◀ INFRASTRUCTURE IS DOWN ▶ ', 'BG_RED')
|
|
478
|
+
cust_print(random.choice([flip, chunga, ogre]), 'GREEN')
|
|
479
|
+
|
|
480
|
+
return RetScope.return_string
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
if __name__ == '__main__':
|
|
484
|
+
import sys
|
|
485
|
+
|
|
486
|
+
from readers.slurmreader import read_infrastructure, read_jobs
|
|
487
|
+
infr = read_infrastructure()
|
|
488
|
+
jobs, _ = read_jobs()
|
|
489
|
+
if len(sys.argv) > 1 and sys.argv[1] == 'work':
|
|
490
|
+
print(view_viz_gpu(infr, jobs, work=True))
|
|
491
|
+
print(view_viz_ram(infr, jobs, work=True))
|
|
492
|
+
else:
|
|
493
|
+
print(view_viz_gpu(infr, jobs))
|
|
494
|
+
print(view_viz_ram(infr, jobs))
|