Skip to content

Few fixes and handle modification consistently #300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ The `pyslurm` package is a wrapper around the Slurm C-API
* Node API
* [pyslurm.Node][]
* [pyslurm.Nodes][]
* Partition API
* [pyslurm.Partition][]
* [pyslurm.Partitions][]
* New Exceptions
* [pyslurm.RPCError][]
* [pyslurm.PyslurmError][]
Expand Down
4 changes: 1 addition & 3 deletions pyslurm/core/job/job.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ cdef class Jobs(dict):

Raises:
RPCError: When getting all the Jobs from the slurmctld failed.
MemoryError: If malloc fails to allocate memory.
"""
cdef:
dict passwd = {}
Expand Down Expand Up @@ -188,7 +187,7 @@ cdef class Jobs(dict):
"""Format the information as list of Job objects.

Returns:
(list): List of Job objects
(list[pyslurm.Job]): List of Job objects
"""
return list(self.values())

Expand Down Expand Up @@ -258,7 +257,6 @@ cdef class Job:
Raises:
RPCError: If requesting the Job information from the slurmctld was
not successful.
MemoryError: If malloc failed to allocate memory.

Examples:
>>> import pyslurm
Expand Down
8 changes: 5 additions & 3 deletions pyslurm/core/job/step.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,17 @@ cdef class JobStep:
step_id = self.ptr.step_id.step_id
verify_rpc(slurm_kill_job_step(self.job_id, step_id, 9))

def modify(self, changes):
def modify(self, JobStep changes):
"""Modify a job step.

Implements the slurm_update_step RPC.

Args:
changes (pyslurm.JobStep):
Another JobStep object which contains all the changes that
should be applied to this instance.
Another JobStep object that contains all the changes to apply.
Check the `Other Parameters` of the JobStep class to see which
properties can be modified.

Raises:
RPCError: When updating the JobStep was not successful.

Expand Down
3 changes: 3 additions & 0 deletions pyslurm/core/node.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ cdef class Node:
Default CPU-Binding for the node
state (str):
State of the node
reason (str):
Reason for the Node, typically used along with updating the node
state

Attributes:
name (str):
Expand Down
90 changes: 75 additions & 15 deletions pyslurm/core/node.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ from pyslurm.utils.helpers import (
instance_to_dict,
_sum_prop,
nodelist_from_range_str,
nodelist_to_range_str,
)


Expand Down Expand Up @@ -157,10 +158,37 @@ cdef class Nodes(dict):
"""Format the information as list of Node objects.

Returns:
(list): List of Node objects
(list[pyslurm.Node]): List of Node objects
"""
return list(self.values())

def modify(self, Node changes):
"""Modify all Nodes in a collection.

Args:
changes (pyslurm.Node):
Another Node object that contains all the changes to apply.
Check the `Other Parameters` of the Node class to see which
properties can be modified.

Raises:
RPCError: When updating the Node was not successful.

Examples:
>>> import pyslurm
>>>
>>> nodes = pyslurm.Nodes.load()
>>> # Prepare the changes
>>> changes = pyslurm.Node(state="DRAIN", reason="DRAIN Reason")
>>> # Apply the changes to all the nodes
>>> nodes.modify(changes)
"""
cdef Node n = <Node>changes
node_str = nodelist_to_range_str(list(self.keys()))
n._alloc_umsg()
cstr.fmalloc(&n.umsg.node_names, node_str)
verify_rpc(slurm_update_node(n.umsg))

@property
def free_memory(self):
return _sum_prop(self, Node.free_memory)
Expand Down Expand Up @@ -340,25 +368,27 @@ cdef class Node:

return self

def modify(self, changes):
def modify(self, Node changes):
"""Modify a node.

Implements the slurm_update_node RPC.

Args:
changes (pyslurm.Node):
Another Node object which contains all the changes that
should be applied to this instance.
Another Node object that contains all the changes to apply.
Check the `Other Parameters` of the Node class to see which
properties can be modified.

Raises:
RPCError: When updating the Node was not successful.

Examples:
>>> import pyslurm
>>>
>>> mynode = pyslurm.Node("localhost")
>>> changes = pyslurm.Node(weight=100)
>>> # Setting the weight to 100 for the "localhost" node
>>> mynode = pyslurm.Node.load("localhost")
>>> # Prepare the changes
>>> changes = pyslurm.Node(state="DRAIN", reason="DRAIN Reason")
>>> # Modify it
>>> mynode.modify(changes)
"""
cdef Node n = <Node>changes
Expand Down Expand Up @@ -448,6 +478,10 @@ cdef class Node:
def reason(self):
return cstr.to_unicode(self.info.reason)

@reason.setter
def reason(self, val):
cstr.fmalloc2(&self.info.reason, &self.umsg.reason, val)

@property
def reason_user(self):
return uid_to_name(self.info.reason_uid, lookup=self.passwd)
Expand Down Expand Up @@ -667,6 +701,10 @@ cdef class Node:
xfree(state)
return state_str

@state.setter
def state(self, val):
self.umsg.node_state=self.info.node_state = _node_state_from_str(val)

@property
def next_state(self):
if ((self.info.next_state != slurm.NO_VAL)
Expand All @@ -677,10 +715,6 @@ cdef class Node:
else:
return None

@state.setter
def state(self, val):
self.umsg.node_state=self.info.node_state = _node_state_from_str(val)

@property
def cpu_load(self):
load = u32_parse(self.info.cpu_load)
Expand All @@ -694,10 +728,36 @@ cdef class Node:
def _node_state_from_str(state, err_on_invalid=True):
if not state:
return slurm.NO_VAL

for i in range(slurm.NODE_STATE_END):
if state == slurm_node_state_string(i):
return i
ustate = state.upper()

# Following states are explicitly possible as per documentation
# https://slurm.schedmd.com/scontrol.html#OPT_State_1
if ustate == "CANCEL_REBOOT":
return slurm.NODE_STATE_CANCEL_REBOOT
elif ustate == "DOWN":
return slurm.NODE_STATE_DOWN
elif ustate == "DRAIN":
return slurm.NODE_STATE_DRAIN
elif ustate == "FAIL":
return slurm.NODE_STATE_FAIL
elif ustate == "FUTURE":
return slurm.NODE_STATE_FUTURE
elif ustate == "NORESP" or ustate == "NO_RESP":
return slurm.NODE_STATE_NO_RESPOND
elif ustate == "POWER_DOWN":
return slurm.NODE_STATE_POWER_DOWN
elif ustate == "POWER_DOWN_ASAP":
# Drain and mark for power down
return slurm.NODE_STATE_POWER_DOWN | slurm.NODE_STATE_POWER_DRAIN
elif ustate == "POWER_DOWN_FORCE":
# Kill all Jobs and power down
return slurm.NODE_STATE_POWER_DOWN | slurm.NODE_STATE_POWERED_DOWN
elif ustate == "POWER_UP":
return slurm.NODE_STATE_POWER_UP
elif ustate == "RESUME":
return slurm.NODE_RESUME
elif ustate == "UNDRAIN":
return slurm.NODE_STATE_UNDRAIN

if err_on_invalid:
raise ValueError(f"Invalid Node state: {state}")
Expand Down
5 changes: 1 addition & 4 deletions pyslurm/core/partition.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ cdef class Partition:
* total_cpus
* total_nodes
* select_type_parameters
* consumable_resource

Attributes:
name (str):
Expand All @@ -116,10 +115,8 @@ cdef class Partition:
List of QoS which are allowed to execute Jobs
alternate (str):
Name of the alternate Partition in case a Partition is down.
consumable_resource (str):
The type of consumable resource used in the Partition.
select_type_parameters (list[str]):
List of additional parameters passed to the select plugin used.
List of Select type parameters for the select plugin.
cpu_binding (str):
Default CPU-binding for Jobs that execute in a Partition.
default_memory_per_cpu (int):
Expand Down
63 changes: 30 additions & 33 deletions pyslurm/core/partition.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -143,18 +143,29 @@ cdef class Partitions(dict):

return self

def set_state(self, state):
"""Modify the State of all Partitions in this Collection.
def modify(self, changes):
"""Modify all Partitions in a Collection.

Args:
state (str):
Partition state to set
changes (pyslurm.Partition):
Another Partition object that contains all the changes to
apply. Check the `Other Parameters` of the Partition class to
see which properties can be modified.

Raises:
RPCError: When updating the state failed
RPCError: When updating at least one Partition failed.

Examples:
>>> import pyslurm
>>>
>>> parts = pyslurm.Partitions.load()
>>> # Prepare the changes
>>> changes = pyslurm.Partition(state="DRAIN")
>>> # Apply the changes to all the partitions
>>> parts.modify(changes)
"""
for part in self.values():
part.modify(state=state)
part.modify(changes)

def as_list(self):
"""Format the information as list of Partition objects.
Expand Down Expand Up @@ -270,40 +281,30 @@ cdef class Partition:
verify_rpc(slurm_create_partition(self.ptr))
return self

def modify(self, **changes):
def modify(self, Partition changes):
"""Modify a Partition.

Implements the slurm_update_partition RPC.

Args:
**changes (Any):
Changes for the Partition. Almost every Attribute from a
Partition can be modified, except for:

* total_cpus
* total_nodes
* select_type_parameters
* consumable_resource
changes (pyslurm.Partition):
Another Partition object that contains all the changes to
apply. Check the `Other Parameters` of the Partition class to
see which properties can be modified.

Raises:
ValueError: When no changes were specified or when a parsing error
occured.
RPCError: When updating the Partition was not successful.

Examples:
>>> import pyslurm
>>>
>>> # Modifying the maximum time limit
>>> mypart = pyslurm.Partition("normal")
>>> mypart.modify(max_time_limit="10-00:00:00")
>>>
>>> # Modifying the partition state
>>> mypart.modify(state="DRAIN")
>>> part = pyslurm.Partition.load("normal")
>>> # Prepare the changes
>>> changes = pyslurm.Partition(state="DRAIN")
>>> # Apply the changes to the "normal" Partition
>>> part.modify(changes)
"""
if not changes:
raise ValueError("No changes were specified")

cdef Partition part = Partition(**changes)
cdef Partition part = <Partition>changes
part.name = self._error_or_name()
verify_rpc(slurm_update_partition(part.ptr))

Expand Down Expand Up @@ -381,10 +382,6 @@ cdef class Partition:
def alternate(self, val):
cstr.fmalloc(&self.ptr.alternate, val)

@property
def consumable_resource(self):
return _select_type_int_to_cons_res(self.ptr.cr_type)

@property
def select_type_parameters(self):
return _select_type_int_to_list(self.ptr.cr_type)
Expand Down Expand Up @@ -757,7 +754,7 @@ def _split_oversubscribe_str(val):
def _select_type_int_to_list(stype):
# The rest of the CR_* stuff are just some extra parameters to the select
# plugin
out = []
out = _select_type_int_to_cons_res(stype)

if stype & slurm.CR_OTHER_CONS_RES:
out.append("OTHER_CONS_RES")
Expand Down Expand Up @@ -800,7 +797,7 @@ def _select_type_int_to_cons_res(stype):
elif stype & slurm.CR_MEMORY:
return "MEMORY"
else:
return None
return []


def _preempt_mode_str_to_int(mode):
Expand Down
Loading