nodeocc 1.0.17__tar.gz → 1.0.19__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.17 → nodeocc-1.0.19}/PKG-INFO +1 -1
  2. {nodeocc-1.0.17 → nodeocc-1.0.19}/pyproject.toml +1 -1
  3. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/controller/controller.py +1 -2
  4. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/model/infrastructure.py +6 -1
  5. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/nodeocc.egg-info/PKG-INFO +1 -1
  6. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/view/__init__.py +0 -1
  7. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/view/curses_multiwindow.py +13 -7
  8. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/view/utils.py +7 -5
  9. {nodeocc-1.0.17 → nodeocc-1.0.19}/README.md +0 -0
  10. {nodeocc-1.0.17 → nodeocc-1.0.19}/setup.cfg +0 -0
  11. {nodeocc-1.0.17 → nodeocc-1.0.19}/setup.py +0 -0
  12. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/__init__.py +0 -0
  13. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/model/job.py +0 -0
  14. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/nodeocc.egg-info/SOURCES.txt +0 -0
  15. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/nodeocc.egg-info/dependency_links.txt +0 -0
  16. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/nodeocc.egg-info/entry_points.txt +0 -0
  17. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/nodeocc.egg-info/requires.txt +0 -0
  18. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/nodeocc.egg-info/top_level.txt +0 -0
  19. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/readers/compute_wait_time.py +0 -0
  20. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/readers/slurmreader.py +0 -0
  21. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/view/slurm_list.py +0 -0
  22. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/view/slurm_viz.py +0 -0
  23. {nodeocc-1.0.17 → nodeocc-1.0.19}/src/view/styles.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nodeocc
3
- Version: 1.0.17
3
+ Version: 1.0.19
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.17"
7
+ version = "1.0.19"
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"
@@ -136,7 +136,6 @@ def update_data_master(instance: Singleton):
136
136
  queue_jobs = sorted(queue_jobs, key=lambda x: x['priority'], reverse=True)
137
137
  maxlen = min(JOB_LIMIT_PER_MSG, len(running_jobs) + len(queue_jobs))
138
138
 
139
-
140
139
  queue_jobs, extra_queue_jobs = queue_jobs[:maxlen - len(running_jobs)], queue_jobs[maxlen - len(running_jobs):]
141
140
  cur_timestamp = time.time()
142
141
  msg = json.dumps({'inf': inf.to_nested_dict(), 'jobs': running_jobs + queue_jobs, 'ts': str(cur_timestamp)})
@@ -195,7 +194,7 @@ async def get_data_slave(instance):
195
194
  # check if timestamp is the same
196
195
  if float(new_ts['ts']) != orig_timestamp:
197
196
  instance.timeme(f"Timestamp mismatch, skipping")
198
- return inf, jobs, avg_wait_time # return what we have
197
+ return inf, jobs, avg_wait_time # return what we have
199
198
 
200
199
  msg_store[msg_idx] += new_jobs
201
200
 
@@ -1,5 +1,7 @@
1
1
  from typing import List
2
2
 
3
+ from view.utils import to_datetime
4
+
3
5
 
4
6
  class Node:
5
7
  """
@@ -34,7 +36,7 @@ class Maintenance:
34
36
  self.end_time = end_time
35
37
 
36
38
  def __repr__(self):
37
- return f'RESERVATION {self.start_time} - {self.end_time} on {",".join(self.nodes)}'
39
+ return f'RESERVATION - From: {self.start_time} To: {self.end_time} on {",".join(self.nodes)}'
38
40
 
39
41
  @staticmethod
40
42
  def from_dict(d):
@@ -94,3 +96,6 @@ class Infrastructure:
94
96
  def get_sorted_nodes(self):
95
97
 
96
98
  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)
99
+
100
+ def get_next_maintenance(self):
101
+ return sorted(self.maintenances, key=lambda x: to_datetime(x.start_time))[0] if len(self.maintenances) else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nodeocc
3
- Version: 1.0.17
3
+ Version: 1.0.19
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,4 +1,3 @@
1
- import curses
2
1
  from . import slurm_list, slurm_viz, styles
3
2
 
4
3
 
@@ -92,16 +92,17 @@ class Singleton:
92
92
 
93
93
  def clean_port_files(self):
94
94
  nodename = socket.getfqdn().split('.')[0]
95
- for f in os.listdir(self.basepath):
96
- if nodename in f and 'master_' in f and f.endswith('.portfile') and is_file_writable_byall(os.path.join(self.basepath, f)):
95
+ bp = os.path.join(self.basepath, nodename)
96
+ for f in os.listdir(bp):
97
+ if 'master_' in f and f.endswith('.portfile') and is_file_writable_byall(os.path.join(bp, f)):
97
98
  # read pid from file
98
- pid = Path(os.path.join(self.basepath, f)).read_text()
99
+ pid = Path(os.path.join(bp, f)).read_text()
99
100
  # assert no process is running
100
101
  if psutil.pid_exists(int(pid)):
101
102
  self.log(f"Process {pid} is still running, killing self")
102
103
  return False
103
104
 
104
- os.system(f"rm {os.path.join(self.basepath, f)}")
105
+ os.system(f"rm {os.path.join(bp, f)}")
105
106
  return True
106
107
 
107
108
  def __init__(self, args=None):
@@ -165,8 +166,9 @@ class Singleton:
165
166
  Check if a port file exists in the basepath and the file has 666 permissions
166
167
  """
167
168
  nodename = socket.getfqdn().split('.')[0]
168
- portfiles = [os.path.join(self.basepath, f) for f in os.listdir(self.basepath)
169
- if f.endswith('.portfile') and 'master_' in f and nodename in f]
169
+ bp = os.path.join(self.basepath, nodename)
170
+ portfiles = [os.path.join(bp, f) for f in os.listdir(bp)
171
+ if f.endswith('.portfile') and 'master_' in f]
170
172
  portfiles = [f for f in portfiles if is_file_readable_byall(f) and is_file_writable_byall(f)]
171
173
  return portfiles
172
174
 
@@ -197,7 +199,11 @@ class Singleton:
197
199
 
198
200
  try:
199
201
  # create file to store port with 666 permissions to file
200
- filepath = Path(self.basepath, f'{nodename}_master_{self.port}.portfile')
202
+ # file is in folder basepath/nodename/master_{port}.portfile
203
+ bp = os.path.join(self.basepath, nodename)
204
+ if not os.path.exists(bp):
205
+ os.makedirs(bp, mode=0o777)
206
+ filepath = Path(os.path.join(bp, f"master_{self.port}.portfile"))
201
207
  filepath.write_text(str(self.pid))
202
208
  os.chmod(filepath, 0o666)
203
209
 
@@ -1,6 +1,8 @@
1
- import numpy as np
2
1
  import re
3
2
 
3
+ import numpy as np
4
+
5
+
4
6
 
5
7
  def is_student_viz(user):
6
8
  return user.user_group in ('studenti', 'tesisti') and not is_cvcs_viz(user)
@@ -22,7 +24,7 @@ def to_datetime(time_str):
22
24
  return np.datetime64(re.match(r'\d+\s+(.*)\n', str(time_str)).group(1))
23
25
 
24
26
 
25
- def to_datetime(time_str):
27
+ def to_datetime(time_str):
26
28
  try:
27
29
  dt = np.datetime64(re.match(r'\d+\s+(.*)\n', str(time_str)).group(1))
28
30
  except:
@@ -35,9 +37,9 @@ def maintenance_status(infrastructure):
35
37
  waitString = ''
36
38
  if len(infrastructure.maintenances):
37
39
  # time format: '0 2023-12-04 14:00:00\nName: StartTime, dtype: datetime64[ns]'
38
- next_maintenance = sorted(infrastructure.maintenances, key=lambda x: to_datetime(x['start_time']))[0]
39
- start_time = to_datetime(next_maintenance['start_time'])
40
- end_time = to_datetime(next_maintenance['end_time'])
40
+ next_maintenance = infrastructure.get_next_maintenance()
41
+ start_time = to_datetime(next_maintenance.start_time)
42
+ end_time = to_datetime(next_maintenance.end_time)
41
43
  time_to_maintenance = (start_time - np.datetime64('now')).astype(float)
42
44
  # TODO: fix timezone
43
45
  if time_to_maintenance < 0 and (end_time - np.datetime64('now')) > 0:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes