Skip to content

Commit fdcd0bd

Browse files
committed
Address PR comments
1 parent e574683 commit fdcd0bd

File tree

3 files changed

+61
-61
lines changed

3 files changed

+61
-61
lines changed

reframe/core/schedulers/__init__.py

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,57 @@ def filternodes(self, job, nodes):
100100
:meta private:
101101
'''
102102

103+
def filternodes_by_state(self, nodelist, state):
104+
'''Filter nodes by their state
105+
106+
:arg nodelist: List of :class:`Node` instances to filter.
107+
:arg state: The state of the nodes.
108+
If ``all``, the initial list is returned untouched.
109+
If ``avail``, only the available nodes will be returned.
110+
All other values are interpreted as a state string.
111+
The pipe character ``|`` can be used as to specify multiple
112+
alternative node states.
113+
State match is exclusive unless the ``*`` is added at the end of the
114+
state string.
115+
When defining multiple states using ``|``, ``*`` has to be added at
116+
the end of each alternative state for which a non-exclusive match is
117+
required.
118+
119+
:returns: the filtered node list
120+
121+
.. versionchanged:: 4.9
122+
123+
Support the ``|`` character to filter according to alternative states.
124+
125+
.. versionchanged:: 4.10
126+
127+
Moved inside the :class:`JobShceduler` class.
128+
'''
129+
if '|' in state:
130+
allowed_states = state.split('|')
131+
final_nodelist = set()
132+
for s in allowed_states:
133+
final_nodelist.update(
134+
self.filternodes_by_state(nodelist, s)
135+
)
136+
137+
nodelist = final_nodelist
138+
elif state == 'avail':
139+
nodelist = {n for n in nodelist if self.is_node_avail(n)}
140+
elif state != 'all':
141+
if state.endswith('*'):
142+
# non-exclusive state match
143+
state = state[:-1]
144+
nodelist = {
145+
n for n in nodelist if n.in_state(state)
146+
}
147+
else:
148+
nodelist = {
149+
n for n in nodelist if n.in_statex(state)
150+
}
151+
152+
return nodelist
153+
103154
@abc.abstractmethod
104155
def submit(self, job):
105156
'''Submit a job.
@@ -153,53 +204,6 @@ def log(self, message, level=DEBUG2):
153204
getlogger().log(level, f'[S] {self.registered_name}: {message}')
154205

155206

156-
def filter_nodes_by_state(nodelist, state, scheduler):
157-
'''Filter nodes by their state
158-
159-
:arg nodelist: List of :class:`Node` instances to filter.
160-
:arg state: The state of the nodes.
161-
If ``all``, the initial list is returned untouched.
162-
If ``avail``, only the available nodes will be returned.
163-
All other values are interpreted as a state string.
164-
The pipe character ``|`` can be used as to specify multiple
165-
alternative node states.
166-
State match is exclusive unless the ``*`` is added at the end of the
167-
state string.
168-
When defining multiple states using ``|``, ``*`` has to be added at
169-
the end of each alternative state for which a non-exclusive match is
170-
required.
171-
172-
:returns: the filtered node list
173-
174-
.. versionchanged:: 4.9
175-
Support the ``|`` character to filter according to alternative states.
176-
'''
177-
if '|' in state:
178-
allowed_states = state.split('|')
179-
final_nodelist = set()
180-
for s in allowed_states:
181-
final_nodelist.update(
182-
filter_nodes_by_state(nodelist, s, scheduler)
183-
)
184-
185-
nodelist = final_nodelist
186-
elif state == 'avail':
187-
nodelist = {n for n in nodelist if scheduler.is_node_avail(n)}
188-
elif state != 'all':
189-
if state.endswith('*'):
190-
# non-exclusive state match
191-
state = state[:-1]
192-
nodelist = {
193-
n for n in nodelist if n.in_state(state)
194-
}
195-
else:
196-
nodelist = {
197-
n for n in nodelist if n.in_statex(state)
198-
}
199-
200-
return nodelist
201-
202-
203207
class Job(jsonext.JSONSerializable, metaclass=JobMeta):
204208
'''A job descriptor.
205209
@@ -627,10 +631,9 @@ def guess_num_tasks(self):
627631
)
628632

629633
# Try to guess the number of tasks now
630-
available_nodes = filter_nodes_by_state(
634+
available_nodes = self.scheduler.filternodes_by_state(
631635
available_nodes,
632-
self.sched_flex_alloc_nodes.lower(),
633-
self.scheduler
636+
self.sched_flex_alloc_nodes.lower()
634637
)
635638
getlogger().debug(
636639
f'[F] Total available in state='

reframe/core/schedulers/slurm.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def __init__(self):
147147
self._sched_access_in_submit = self.get_option(
148148
'sched_access_in_submit'
149149
)
150-
self.node_available_states = {
150+
self._available_states = {
151151
'ALLOCATED',
152152
'COMPLETING',
153153
'IDLE',
@@ -436,6 +436,8 @@ def filternodes(self, job, nodes):
436436

437437
def _get_reservation_nodes(self, resv):
438438
completed = _run_strict(f'scontrol -a show -o reservations {resv}')
439+
self.log(f'reservation info:\n{completed.stdout}')
440+
439441
node_match = re.search(r'Nodes=(\S+)', completed.stdout)
440442
if node_match:
441443
reservation_nodes = node_match[1]
@@ -446,10 +448,7 @@ def _get_reservation_nodes(self, resv):
446448
flags_match = re.search(r'Flags=(\S+)', completed.stdout)
447449
if flags_match:
448450
if 'MAINT' in flags_match.group(1).split(','):
449-
self.node_available_states.add('MAINTENANCE')
450-
else:
451-
self.log('could not extract the reservation flags for '
452-
f'reservation {resv!r}')
451+
self._available_states.add('MAINTENANCE')
453452

454453
completed = _run_strict(
455454
f'scontrol -a show -o nodes {reservation_nodes}'
@@ -648,7 +647,7 @@ def finished(self, job):
648647
return slurm_state_completed(job.state)
649648

650649
def is_node_avail(self, node):
651-
return node.states <= self.node_available_states
650+
return node.states <= self._available_states
652651

653652
def is_node_down(self, node):
654653
return not self.is_node_avail(node)

reframe/frontend/testgenerators.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from reframe.core.fields import make_convertible
1515
from reframe.core.logging import getlogger, time_function
1616
from reframe.core.meta import make_test
17-
from reframe.core.schedulers import Job, filter_nodes_by_state
17+
from reframe.core.schedulers import Job
1818
from reframe.frontend.executors import generate_testcases
1919

2020

@@ -38,10 +38,8 @@ def getallnodes(state, jobs_cli_options=None):
3838
f'Total available nodes for {part.name}: {len(available_nodes)}'
3939
)
4040

41-
available_nodes = filter_nodes_by_state(
42-
available_nodes,
43-
state,
44-
part.scheduler
41+
available_nodes = part.scheduler.filternodes_by_state(
42+
available_nodes, state
4543
)
4644
nodes[part.fullname] = [n.name for n in available_nodes]
4745

0 commit comments

Comments
 (0)