nodeocc 1.0.2__tar.gz → 1.0.4__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.
Files changed (23) hide show
  1. {nodeocc-1.0.2 → nodeocc-1.0.4}/PKG-INFO +1 -1
  2. {nodeocc-1.0.2 → nodeocc-1.0.4}/pyproject.toml +1 -1
  3. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/controller/controller.py +1 -0
  4. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/model/infrastructure.py +1 -1
  5. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/nodeocc.egg-info/PKG-INFO +1 -1
  6. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/readers/slurmreader.py +45 -27
  7. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/view/curses_multiwindow.py +1 -1
  8. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/view/slurm_list.py +1 -1
  9. {nodeocc-1.0.2 → nodeocc-1.0.4}/README.md +0 -0
  10. {nodeocc-1.0.2 → nodeocc-1.0.4}/setup.cfg +0 -0
  11. {nodeocc-1.0.2 → nodeocc-1.0.4}/setup.py +0 -0
  12. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/__init__.py +0 -0
  13. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/model/job.py +0 -0
  14. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/nodeocc.egg-info/SOURCES.txt +0 -0
  15. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/nodeocc.egg-info/dependency_links.txt +0 -0
  16. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/nodeocc.egg-info/entry_points.txt +0 -0
  17. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/nodeocc.egg-info/requires.txt +0 -0
  18. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/nodeocc.egg-info/top_level.txt +0 -0
  19. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/readers/compute_wait_time.py +0 -0
  20. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/view/__init__.py +0 -0
  21. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/view/slurm_viz.py +0 -0
  22. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/view/styles.py +0 -0
  23. {nodeocc-1.0.2 → nodeocc-1.0.4}/src/view/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nodeocc
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: TUI application for viewing the status of GPU allocations on a Slurm cluster
5
5
  Author: Matteo Boschini
6
6
  Maintainer: Lorenzo Bonicelli, Aniello Panariello
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nodeocc"
7
- version = "1.0.2"
7
+ version = "1.0.4"
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"
@@ -57,6 +57,7 @@ try:
57
57
  print(END, end='')
58
58
  except Exception as e:
59
59
  print(f"{BBLUE}Could not get newest version from pip, check if {program_name} is up to date{END}")
60
+ newest_version = '?.?.?'
60
61
  time.sleep(5)
61
62
 
62
63
 
@@ -67,7 +67,7 @@ class Infrastructure:
67
67
  self.cpu_limit_grp = cpu_limit_grp
68
68
  self.cpu_limit_stu = cpu_limit_stu
69
69
  self.cpu_limit_stugrp = cpu_limit_stugrp
70
- self.prior = ['n/a', None, 'RTXA5000', 'RTX6000', 'RTX5000', '2080', 'V100', '1080', 'P100', 'K80']
70
+ self.prior = ['n/a', None, 'A40', 'RTXA5000', 'RTX6000', 'RTX5000', '2080', 'V100', '1080', 'P100', 'K80']
71
71
 
72
72
  @staticmethod
73
73
  def from_dict(d):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nodeocc
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: TUI application for viewing the status of GPU allocations on a Slurm cluster
5
5
  Author: Matteo Boschini
6
6
  Maintainer: Lorenzo Bonicelli, Aniello Panariello
@@ -1,6 +1,5 @@
1
- import json
2
1
  import os
3
- import time
2
+ import re
4
3
  from io import StringIO
5
4
 
6
5
  import pandas as pd
@@ -152,27 +151,29 @@ def _load_joblet_meta(line):
152
151
 
153
152
 
154
153
  def _gpus_per_joblet(line):
155
- if pd.isna(line['gpus_per_job']) and pd.isna(line['gpus_per_node']) and pd.isna(line['gpus_per_task']):
154
+ try:
155
+ if 'node=1' in line['TRES_ALLOC']:
156
+ return line['TRES_ALLOC'].split('gpu=')[-1].split(',')[0] if 'gpu=' in line['TRES_ALLOC'] else 0
157
+ else:
158
+ node = line['NODELIST']
159
+ node_idx = line['ALL_JOB_NODES'].split(',').index(node)
160
+ return int(re.findall(r'gpu:(\d+)', line['TRES_PER_NODE'])[node_idx]) if 'gpu:' in line['TRES_PER_NODE'] else 0
161
+ except BaseException as e:
156
162
  return 0
157
- elif not pd.isna(line['gpus_per_node']):
158
- return line['gpus_per_node'] * (line['NODES'] if pd.isna(line['NODELIST']) else 1)
159
- else:
160
- if line['ST'] == 'PD':
161
- return line['gpus_per_job'] if not pd.isna(line['gpus_per_job']) else line['gpus_per_task']
162
- gpus_id = line['joblet_meta_str']
163
- gpus_id = sum([x.split('IDX:')[-1].split(')')[0].split(',') for x in gpus_id if 'gpu' in x], [])
164
- gpus_n = len(gpus_id) + sum([len(range(int(x.split('-')[1].split()[0]) - int(x.split('-')[0]))) for x in gpus_id if '-' in x])
165
- return gpus_n
166
163
 
167
164
 
168
165
  def _cpus_per_joblet(line):
169
- if line['ST'] == 'PD':
170
- return line['MIN_CPUS']
171
- else:
172
- cpus_id = line['joblet_meta_str']
173
- cpus = sum([x.split('CPU_IDs=')[-1].split()[0].split(',') for x in cpus_id], [])
174
- cpus_n = len(cpus) + sum([len(range(int(x.split('-')[1].split()[0]) - int(x.split('-')[0]))) for x in cpus if '-' in x])
175
- return cpus_n
166
+ try:
167
+ if 'node=1' in line['TRES_ALLOC']:
168
+ return int(str(line['TRES_ALLOC']).split('cpu=')[-1].split(',')[0])
169
+ else:
170
+ nodes = line['NODES']
171
+ tot_gpu = int(str(line['TRES_ALLOC']).split('gpu=')[-1].split(',')[0]) if 'gpu=' in str(line['TRES_ALLOC']) else 0
172
+ tot_cpus = int(str(line['TRES_ALLOC']).split('cpu=')[-1].split(',')[0])
173
+ n_gpus = line['joblet_gpus']
174
+ return int(tot_cpus) // int(nodes) if tot_gpu == 0 else int(tot_cpus) // tot_gpu * n_gpus
175
+ except BaseException as e:
176
+ return 0
176
177
 
177
178
 
178
179
  memunits = {
@@ -193,12 +194,24 @@ def parse_mem(thing):
193
194
 
194
195
 
195
196
  def _mem_per_joblet(line):
196
- if line['ST'] == 'PD':
197
- return parse_mem(line['MIN_MEMORY'])
198
- else:
199
- mem_id = line['joblet_meta_str']
200
- mem = sum([int(x.split('Mem=')[-1].split()[0]) for x in mem_id])
197
+ try:
198
+ mem = line['TRES_ALLOC'].split('mem=')[-1].split(',')[0]
199
+ if 'G' in mem:
200
+ mem = int(mem.split('G')[0]) * 1024
201
+ elif 'M' in mem:
202
+ mem = int(mem.split('M')[0])
203
+ else:
204
+ mem = int(mem)
205
+ except BaseException:
206
+ return 0
207
+
208
+ if 'node=1' in line['TRES_ALLOC']:
201
209
  return mem
210
+ else:
211
+ nodes = line['NODES']
212
+ tot_gpu = int(str(line['TRES_ALLOC']).split('gpu=')[-1].split(',')[0]) if 'gpu=' in str(line['TRES_ALLOC']) else 0
213
+ n_gpus = line['joblet_gpus']
214
+ return int(mem) // int(nodes) if tot_gpu == 0 else int(mem) // tot_gpu * n_gpus
202
215
 
203
216
 
204
217
  def _true_jobid(line):
@@ -257,15 +270,20 @@ def read_jobs():
257
270
  instance.timeme(f"\t- squeue and dataframe creation")
258
271
 
259
272
  squeue_df['JOBID'] = squeue_df['JOBID'].apply(str)
273
+ squeue_df['ALL_JOB_NODES'] = squeue_df['NODELIST']
260
274
  squeue_df = _split_column(squeue_df, 'NODELIST')
275
+
261
276
  squeue_df['gpus_per_node'] = squeue_df['TRES_PER_NODE'].apply(lambda x: try_parse_gpu(x) if isinstance(x, str) else x)
262
277
  squeue_df['gpus_per_job'] = squeue_df['TRES_PER_JOB'].apply(lambda x: try_parse_gpu(x) if isinstance(x, str) else x)
263
278
  squeue_df['gpus_per_task'] = squeue_df['TRES_PER_TASK'].apply(lambda x: try_parse_gpu(x) if isinstance(x, str) else x)
264
279
 
265
280
  try:
266
- squeue_df['joblet_mem'] = squeue_df['TRES_ALLOC'].apply(get_mem_joblet)
267
- squeue_df['joblet_gpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: str(l).split('gpu=')[-1].split(',')[0] if 'gpu=' in str(l) else 0)
268
- squeue_df['joblet_cpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: int(str(l).split('cpu=')[-1].split(',')[0]))
281
+ # squeue_df['joblet_gpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: str(l).split('gpu=')[-1].split(',')[0] if 'gpu=' in str(l) else 0)
282
+ squeue_df['joblet_gpus'] = squeue_df.apply(_gpus_per_joblet, axis=1)
283
+ # squeue_df['joblet_cpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: int(str(l).split('cpu=')[-1].split(',')[0]))
284
+ squeue_df['joblet_cpus'] = squeue_df.apply(_cpus_per_joblet, axis=1)
285
+ # squeue_df['joblet_mem'] = squeue_df['TRES_ALLOC'].apply(get_mem_joblet)
286
+ squeue_df['joblet_mem'] = squeue_df.apply(_mem_per_joblet, axis=1)
269
287
  except Exception as e:
270
288
  instance.err(f"Exception PD: {e}")
271
289
 
@@ -89,7 +89,7 @@ class Singleton:
89
89
  self.basepath = self.args.basepath
90
90
 
91
91
  if self.args.daemon_only:
92
- handler = RotatingFileHandler(os.path.join(self.basepath, '.master_log_n.txt'), maxBytes=5 * 1024 * 1024, backupCount=2, mode='w')
92
+ handler = RotatingFileHandler(os.path.join(self.basepath, '.master_log.txt'), maxBytes=5 * 1024 * 1024, backupCount=2, mode='w')
93
93
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S',
94
94
  handlers=[handler])
95
95
  # set logging file
@@ -47,7 +47,7 @@ def _joblet_format(instance, job, width=74, jobid_type='agg'):
47
47
  if instance.view_mode in ('gpu', 'ram'):
48
48
  joblet_repr += _format_to((f'{joblet.n_gpus}gp' if joblet.n_gpus > 0 else " - "), 3, 'left')
49
49
  elif instance.view_mode == 'cpu':
50
- joblet_repr += _format_to((f'{joblet.cpus}cp' if joblet.cpus > 0 else "-"), 3, 'left')
50
+ joblet_repr += _format_to((f'{joblet.cpus}cp' if joblet.cpus > 0 else " - "), 3, 'left')
51
51
  joblet_repr += ' '
52
52
  joblet_repr += _format_to(joblet.node if joblet.node is not None else job.reason, 11)
53
53
  joblet_reprs.append(joblet_repr)
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