Skip to content

Commit 9538493

Browse files
committed
wip: reservation api
1 parent db3663d commit 9538493

File tree

3 files changed

+123
-10
lines changed

3 files changed

+123
-10
lines changed

docs/reference/reservation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ title: Reservation
44

55
::: pyslurm.Reservation
66
::: pyslurm.Reservations
7+
::: pyslurm.ReservationFlags
8+
::: pyslurm.ReservationReoccurrence

pyslurm/core/reservation.pxd

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ from pyslurm.slurm cimport (
4545
from pyslurm.utils cimport cstr
4646
from pyslurm.utils cimport ctime
4747
from pyslurm.utils.ctime cimport time_t
48-
from pyslurm.utils.uint cimport u32_parse
48+
from pyslurm.utils.uint cimport (
49+
u32,
50+
u32_parse,
51+
u64_parse_bool_flag,
52+
u64_set_bool_flag,
53+
)
4954
from pyslurm.xcollections cimport MultiClusterMap
5055

5156
cdef extern void slurm_free_resv_desc_msg(resv_desc_msg_t *msg)
@@ -105,8 +110,14 @@ cdef class Reservation:
105110
Count of Nodes required.
106111
nodes (str):
107112
Nodes to be reserved.
113+
When creating or updating a Reservation, you can also pass the
114+
string `ALL`, when you want all nodes to be included in the
115+
Reservation.
108116
partition (str):
109117
Name of the partition to be used.
118+
purge_time (int):
119+
When the Reservation is idle for this amount of seconds, it will be
120+
removed.
110121
start_time (int):
111122
When the Reservation starts. This is a Unix timestamp.
112123
duration (int):
@@ -127,10 +138,27 @@ cdef class Reservation:
127138
TRES for the Reservation.
128139
users (list[str]):
129140
List of user names permitted to use the Reservation.
141+
flags (pyslurm.ReservationFlags):
142+
Optional Flags for the Reservation.
143+
For convenience, instead of using [pyslurm.ReservationFlags][] in
144+
combination with the logical Operators, you can set this attribute
145+
via a [list][] of [str][]:
146+
147+
flags = ["MAINTENANCE", "FLEX", "MAGNETIC"]
148+
149+
When setting like this, the strings must match the names of members
150+
in [pyslurm.ReservationFlags][].
151+
reoccurrence (pyslurm.ReservationReoccurrence):
152+
Describes if and when this Reservation reoccurs.
153+
Since [pyslurm.ReservationReoccurrence] members are also just
154+
strings, you can conveniently also set the attribute like this:
155+
156+
reoccurrence = "DAILY"
130157
"""
131158
cdef:
132159
reserve_info_t *info
133160
resv_desc_msg_t *umsg
161+
_reoccurrence
134162

135163
cdef readonly cluster
136164

pyslurm/core/reservation.pyx

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ from pyslurm.core.slurmctld.config import _get_memory
3030
from datetime import datetime
3131
from pyslurm import xcollections
3232
from pyslurm.utils.helpers import instance_to_dict
33+
from pyslurm.utils.enums import SlurmEnum, SlurmFlag
34+
from enum import auto, StrEnum
3335
from pyslurm.utils.ctime import (
3436
_raw_time,
3537
timestr_to_mins,
38+
timestr_to_secs,
3639
date_to_timestamp,
3740
)
3841
from pyslurm.core.error import (
@@ -63,7 +66,8 @@ cdef class Reservations(MultiClusterMap):
6366
"""Load all Reservations in the system.
6467
6568
Returns:
66-
(pyslurm.Reservations): Collection of Reservation objects.
69+
(pyslurm.Reservations): Collection of [pyslurm.Reservation][]
70+
objects.
6771
6872
Raises:
6973
(pyslurm.RPCError): When getting all the Reservations from the
@@ -75,10 +79,7 @@ cdef class Reservations(MultiClusterMap):
7579

7680
verify_rpc(slurm_load_reservations(0, &reservations.info))
7781

78-
# prepare a dummy reserve_info_t struct.
7982
memset(&reservations.tmp_info, 0, sizeof(reserve_info_t))
80-
81-
# Put each pointer into its own instance.
8283
for cnt in range(reservations.info.record_count):
8384
reservation = Reservation.from_ptr(&reservations.info.reservation_array[cnt])
8485

@@ -96,7 +97,6 @@ cdef class Reservations(MultiClusterMap):
9697

9798
reservations.data[cluster][reservation.name] = reservation
9899

99-
# We have extracted all pointers
100100
reservations.info.record_count = 0
101101
return reservations
102102

@@ -110,6 +110,7 @@ cdef class Reservation:
110110
def __init__(self, name=None, **kwargs):
111111
self._alloc_impl()
112112
self.name = name
113+
self._reoccurrence = ReservationReoccurrence.NO
113114
self.cluster = settings.LOCAL_CLUSTER
114115
for k, v in kwargs.items():
115116
setattr(self, k, v)
@@ -130,6 +131,7 @@ cdef class Reservation:
130131
if not self.umsg:
131132
raise MemoryError("xmalloc failed for resv_desc_msg_t")
132133
slurm_init_resv_desc_msg(self.umsg)
134+
self.umsg.flags = 0
133135

134136
def _dealloc_umsg(self):
135137
slurm_free_resv_desc_msg(self.umsg)
@@ -162,6 +164,9 @@ cdef class Reservation:
162164
wrap._alloc_info()
163165
wrap.cluster = settings.LOCAL_CLUSTER
164166
memcpy(wrap.info, in_ptr, sizeof(reserve_info_t))
167+
wrap._reoccurrence = ReservationReoccurrence.from_flag(wrap.info.flags,
168+
default=ReservationReoccurrence.NO)
169+
wrap.info.flags &= ~wrap.reoccurrence._flag
165170
return wrap
166171

167172
def _error_or_name(self):
@@ -226,7 +231,16 @@ cdef class Reservation:
226231
227232
Examples:
228233
>>> import pyslurm
229-
>>> resv = pyslurm.Reservation("debug")
234+
>>> from pyslurm import ReservationFlags, ReservationReoccurrence
235+
>>> resv = pyslurm.Reservation(
236+
... name = "debug",
237+
... users = ["root"],
238+
... nodes = "node001",
239+
... duration = "1-00:00:00",
240+
... flags = ReservationFlags.MAINTENANCE,
241+
... reoccurrence = ReservationReoccurrence.DAILY,
242+
... )
243+
>>> resv.create()
230244
"""
231245
cdef char* new_name = NULL
232246

@@ -356,8 +370,6 @@ cdef class Reservation:
356370
def features(self, val):
357371
cstr.from_list2(&self.info.features, &self.umsg.features, val)
358372

359-
# TODO: flags
360-
361373
@property
362374
def groups(self):
363375
return cstr.to_list(self.info.groups)
@@ -414,7 +426,15 @@ cdef class Reservation:
414426
def partition(self, val):
415427
cstr.fmalloc2(&self.info.partition, &self.umsg.partition, val)
416428

417-
# TODO: purge_comp_time ?
429+
@property
430+
def purge_time(self):
431+
return u32_parse(self.info.purge_comp_time)
432+
433+
@purge_time.setter
434+
def purge_time(self, val):
435+
self.info.purge_comp_time = self.umsg.purge_comp_time = timestr_to_secs(val)
436+
if ReservationFlags.PURGE not in self.flags:
437+
self.flags |= ReservationFlags.PURGE
418438

419439
@property
420440
def start_time(self):
@@ -464,3 +484,66 @@ cdef class Reservation:
464484
@users.setter
465485
def users(self, val):
466486
cstr.from_list2(&self.info.users, &self.umsg.users, val)
487+
488+
@property
489+
def reoccurrence(self):
490+
return self._reoccurrence
491+
492+
@reoccurrence.setter
493+
def reoccurrence(self, val):
494+
v = ReservationReoccurrence(val)
495+
current = self._reoccurrence
496+
self._reoccurrence = v
497+
if v == ReservationReoccurrence.NO:
498+
self.umsg.flags |= current._clear_flag
499+
else:
500+
self.umsg.flags |= v._flag
501+
502+
@property
503+
def flags(self):
504+
return ReservationFlags(self.info.flags)
505+
506+
@flags.setter
507+
def flags(self, val):
508+
# TODO: What if I want to clear all flags?
509+
flag = val
510+
if isinstance(val, list):
511+
flag = ReservationFlags.from_list(val)
512+
513+
self.info.flags = flag.value
514+
self.umsg.flags = flag._get_flags_cleared()
515+
516+
# TODO: RESERVE_FLAG_SKIP ?
517+
518+
519+
class ReservationFlags(SlurmFlag):
520+
MAINTENANCE = slurm.RESERVE_FLAG_MAINT, slurm.RESERVE_FLAG_NO_MAINT
521+
MAGNETIC = slurm.RESERVE_FLAG_MAGNETIC, slurm.RESERVE_FLAG_NO_MAGNETIC
522+
FLEX = slurm.RESERVE_FLAG_FLEX, slurm.RESERVE_FLAG_NO_FLEX
523+
IGNORE_RUNNING_JOBS = slurm.RESERVE_FLAG_IGN_JOBS, slurm.RESERVE_FLAG_NO_IGN_JOB
524+
ANY_NODES = slurm.RESERVE_FLAG_ANY_NODES, slurm.RESERVE_FLAG_NO_ANY_NODES
525+
STATIC_NODES = slurm.RESERVE_FLAG_STATIC, slurm.RESERVE_FLAG_NO_STATIC
526+
PARTITION_NODES_ONLY = slurm.RESERVE_FLAG_PART_NODES, slurm.RESERVE_FLAG_NO_PART_NODES
527+
USER_DELETION = slurm.RESERVE_FLAG_USER_DEL, slurm.RESERVE_FLAG_NO_USER_DEL
528+
PURGE = slurm.RESERVE_FLAG_PURGE_COMP, slurm.RESERVE_FLAG_NO_PURGE_COMP
529+
SPECIFIC_NODES = slurm.RESERVE_FLAG_SPEC_NODES
530+
NO_JOB_HOLD_AFTER_END = slurm.RESERVE_FLAG_NO_HOLD_JOBS
531+
OVERLAP = slurm.RESERVE_FLAG_OVERLAP
532+
ALL_NODES = slurm.RESERVE_FLAG_ALL_NODES
533+
534+
535+
class ReservationReoccurrence(SlurmEnum):
536+
"""Different reocurrences for a Reservation
537+
538+
Args:
539+
NO:
540+
No reocurrence defined
541+
DAILY:
542+
Daily reocurrence.
543+
"""
544+
NO = auto()
545+
DAILY = auto(), slurm.RESERVE_FLAG_DAILY, slurm.RESERVE_FLAG_NO_DAILY
546+
HOURLY = auto(), slurm.RESERVE_FLAG_HOURLY, slurm.RESERVE_FLAG_NO_HOURLY
547+
WEEKLY = auto(), slurm.RESERVE_FLAG_WEEKLY, slurm.RESERVE_FLAG_NO_WEEKLY
548+
WEEKDAY = auto(), slurm.RESERVE_FLAG_WEEKDAY, slurm.RESERVE_FLAG_NO_WEEKDAY
549+
WEEKEND = auto(), slurm.RESERVE_FLAG_WEEKEND, slurm.RESERVE_FLAG_NO_WEEKEND

0 commit comments

Comments
 (0)