Skip to content
Open
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
8 changes: 4 additions & 4 deletions .github/workflows/pyslurm.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: PySlurm

env:
SLURM_DOCKER_IMAGE: giovtorres/slurm-docker:25.11.4-rl10
SLURM_DOCKER_IMAGE: giovtorres/slurm-docker:26.05.3-rl10

on:
push:
Expand All @@ -18,11 +18,11 @@ jobs:
strategy:
matrix:
include:
- slurm-image: giovtorres/slurm-docker:25.11.4-rl10
- slurm-image: giovtorres/slurm-docker:26.05.3-rl10
python-version: "3.12"
- slurm-image: giovtorres/slurm-docker:25.11.4-rl9
- slurm-image: giovtorres/slurm-docker:26.05.3-rl9
python-version: "3.9"
- slurm-image: giovtorres/slurm-docker:25.11.4-rl8
- slurm-image: giovtorres/slurm-docker:26.05.3-rl8
python-version: "3.6"
fail-fast: false
env:
Expand Down
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,52 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased on the [26.05.x](https://github.com/PySlurm/pyslurm/tree/26.05.x) branch

### Added

- Support for Slurm 26.05.x
- New Enums, both available directly as `pyslurm.<name>`:
- `JobExclusive`
- `JobOversubscribe`
- New members added for the `pyslurm.Job` class:
- `container_type`
- `exclusive`
- `oversubscribe`
- `memory_update_delay`
- `memory_update_margin`
- New member added for the `pyslurm.JobStep` class:
- `container_type`
- New member added for the `pyslurm.JobSubmitDescription` class:
- `container_type` (also recognized as `--container-type` in batch scripts)
- New member added for the `pyslurm.Node` class:
- `suspend_time`
- New members added for the `pyslurm.slurmctld.Config` class:
- `health_check_timeout`
- `license_parameters`
- `metrics_auth`
- `metrics_auth_users`
- `metrics_parameters`
- `slurmctld_http_auth_parameters`
- `slurmd_http_auth_parameters`

### Fixed

- Fixed heap corruption in `pyslurm.Reservation.create()`. Slurm 26.05 changed
`slurm_create_reservation` to return an `xmalloc`-allocated name, which must
be released with `xfree` rather than `free`.
- Added the `node_ranks` member to the internal `job_resources` struct
definition. Its absence shifted every following member, corrupting
`pyslurm.Job.cpus`.

### Changed

- Slurm 26.05 changed a number of RPCs to take a `slurm_step_id_t` instead of a
plain `uint32_t` job id. This is handled internally and the PySlurm API is
unchanged.
- `ESLURM_ERROR_ON_DESC_TO_RECORD_COPY` was removed in Slurm 26.05 and is
replaced by `ESLURM_MAX_JOB_COUNT`.

## Unreleased on the [25.11.x](https://github.com/PySlurm/pyslurm/tree/25.11.x) branch

### Added
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pyslurm is the Python client library for the [Slurm Workload Manager](https://sl

## Requirements

* [Slurm](https://slurm.schedmd.com) 25.11.x — shared library and header files
* [Slurm](https://slurm.schedmd.com) 26.05.x — shared library and header files
* [Python](https://www.python.org) >= 3.6

## Versioning
Expand All @@ -15,6 +15,7 @@ major release.

| PySlurm | Slurm |
|---|---|
| 26.05.x | 26.05.x |
| 25.11.x | 25.11.x |
| 24.05.x | 24.05.x |
| 23.11.x | 23.11.x |
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
slurm:
image: ${SLURM_DOCKER_IMAGE:-giovtorres/slurm-docker:25.11.2}
image: ${SLURM_DOCKER_IMAGE:-giovtorres/slurm-docker:26.05.3}
hostname: slurmctl
container_name: slurmctl
privileged: true
Expand Down
9 changes: 6 additions & 3 deletions pyslurm.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: python-pyslurm
Version: 25.11.2
Version: 26.5.0
%define rel 1
Release: %{rel}%{?dist}
Summary: Python interface to Slurm
Expand All @@ -9,7 +9,7 @@ Source: pyslurm-%{version}.tar.gz

BuildRequires: python3-devel
BuildRequires: pyproject-rpm-macros
BuildRequires: slurm-devel >= 25.11.0
BuildRequires: slurm-devel >= 26.05.0

%description
pyslurm is a Python interface to Slurm
Expand Down Expand Up @@ -39,7 +39,10 @@ pyslurm is a Python interface to Slurm
%doc README.md

%changelog
* Sat Apr 12 2026 Giovanni Torres <giovtorres@users.noreply.github.com> - 25.11.2-1
* Thu Aug 20 2026 Giovanni Torres <giovtorres@users.noreply.github.com> - 26.5.0-1
- Support for Slurm 26.05.x

* Sat Apr 12 2026 Giovanni Torres <giovtorres@users.noreply.github.com> - 25.11.2-1
- Fix Python 3.6 package metadata (UNKNOWN-0.0.0) by reading version from setup.py

* Sun Mar 22 2026 Giovanni Torres <giovtorres@users.noreply.github.com> - 25.11.0-1
Expand Down
12 changes: 12 additions & 0 deletions pyslurm/core/job/job.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, int64_t
from libc.stdlib cimport free
from pyslurm.core.job.submission cimport JobSubmitDescription
from pyslurm.core.job.step cimport JobSteps, JobStep
from pyslurm.utils.helpers cimport init_job_step_id
from pyslurm.xcollections cimport MultiClusterMap
from pyslurm cimport slurm
from pyslurm.slurm cimport (
Expand Down Expand Up @@ -62,6 +63,7 @@ from pyslurm.slurm cimport (
slurm_update_job,
slurm_notify_job,
slurm_requeue,
slurm_step_id_t,
xfree,
try_xmalloc,
)
Expand Down Expand Up @@ -287,6 +289,10 @@ cdef class Job:
Name of the reservation this Job uses.
resource_sharing (str):
Mode controlling how a job shares resources with others.
exclusive (pyslurm.JobExclusive):
Exclusive resource allocation mode of the Job.
oversubscribe (pyslurm.JobOversubscribe):
Whether the Job is willing to oversubscribe resources.
requires_contiguous_nodes (bool):
Whether the Job has allocated a set of contiguous nodes.
licenses (list):
Expand All @@ -307,6 +313,12 @@ cdef class Job:
The container this Job uses.
container_id (str):
The OCI ID of the Container this Job uses.
container_type (str):
Container plugin type the Job uses.
memory_update_delay (int):
Delay in minutes before memory is auto-reduced.
memory_update_margin (int):
Margin in percent applied when memory is auto-reduced.
comment (str):
An arbitrary comment set for the Job.
standard_input (str):
Expand Down
47 changes: 39 additions & 8 deletions pyslurm/core/job/job.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ from pyslurm.core.error import (
verify_rpc,
slurm_errno,
)
from pyslurm.enums import JobExclusive, JobOversubscribe
from pyslurm.utils.ctime import _raw_time
from pyslurm.utils.helpers import (
uid_to_name,
Expand Down Expand Up @@ -286,9 +287,10 @@ cdef class Job:
cdef:
job_info_msg_t *info = NULL
Job wrap = None
slurm_step_id_t step_id = init_job_step_id(job_id)

try:
verify_rpc(slurm_load_job(&info, job_id, slurm.SHOW_DETAIL))
verify_rpc(slurm_load_job(&info, step_id, slurm.SHOW_DETAIL))

if info and info.record_count:
wrap = Job.from_ptr(&info.job_array[0])
Expand Down Expand Up @@ -373,7 +375,9 @@ cdef class Job:

>>> Job(9999).send_signal(9)
"""
cdef uint16_t flags = 0
cdef:
uint16_t flags = 0
slurm_step_id_t step_id = init_job_step_id(self.id)

if steps.casefold() == "all":
flags |= slurm.KILL_FULL_JOB
Expand All @@ -384,7 +388,7 @@ cdef class Job:
flags |= slurm.KILL_HURRY

sig = signal_to_num(signal)
slurm_kill_job(self.id, sig, flags)
slurm_kill_job(step_id, sig, flags)

# Ignore errors when the Job is already done or when SIGKILL was
# specified and the job id is already purged from slurmctlds memory.
Expand Down Expand Up @@ -426,7 +430,8 @@ cdef class Job:
# _slurm_rpc_suspend it should return ESLURM_INVALID_JOB_ID, but
# returns -1
# https://github.com/SchedMD/slurm/blob/master/src/slurmctld/proc_req.c#L4693
verify_rpc(slurm_suspend(self.id))
cdef slurm_step_id_t step_id = init_job_step_id(self.id)
verify_rpc(slurm_suspend(step_id))

def unsuspend(self):
"""Unsuspend a currently suspended Job.
Expand All @@ -441,7 +446,8 @@ cdef class Job:
>>> pyslurm.Job(9999).unsuspend()
"""
# Same problem as described in suspend()
verify_rpc(slurm_resume(self.id))
cdef slurm_step_id_t step_id = init_job_step_id(self.id)
verify_rpc(slurm_resume(step_id))

def modify(self, JobSubmitDescription changes):
"""Modify a Job.
Expand Down Expand Up @@ -532,12 +538,14 @@ cdef class Job:
>>> # Requeing a Job while putting it in a held state
>>> pyslurm.Job(9999).requeue(hold=True)
"""
cdef uint32_t flags = 0
cdef:
uint32_t flags = 0
slurm_step_id_t step_id = init_job_step_id(self.id)

if hold:
flags |= slurm.JOB_REQUEUE_HOLD

verify_rpc(slurm_requeue(self.id, flags))
verify_rpc(slurm_requeue(step_id, flags))

def notify(self, msg):
"""Sends a message to the Jobs stdout.
Expand All @@ -556,7 +564,8 @@ cdef class Job:
>>> import pyslurm
>>> pyslurm.Job(9999).notify("Hello Friends!")
"""
verify_rpc(slurm_notify_job(self.id, msg))
cdef slurm_step_id_t step_id = init_job_step_id(self.id)
verify_rpc(slurm_notify_job(step_id, msg))

def load_stats(self):
"""Load realtime statistics for a Job and its steps.
Expand Down Expand Up @@ -984,6 +993,16 @@ cdef class Job:
def resource_sharing(self):
return cstr.to_unicode(slurm_job_share_string(self.ptr.shared))

@property
def exclusive(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both exclusive and oversubscribe supersede the legacy self.ptr.shared value. I'd suggest deprecating the resource_sharing member, because it will be removed upstream in the future.

return JobExclusive.from_value(self.ptr.exclusive,
default=JobExclusive.NONE)

@property
def oversubscribe(self):
return JobOversubscribe.from_value(self.ptr.oversubscribe,
default=JobOversubscribe.NO)

@property
def requires_contiguous_nodes(self):
return u16_parse_bool(self.ptr.contiguous)
Expand Down Expand Up @@ -1024,6 +1043,18 @@ cdef class Job:
def container_id(self):
return cstr.to_unicode(self.ptr.container_id)

@property
def container_type(self):
return cstr.to_unicode(self.ptr.container_type)

@property
def memory_update_delay(self):
return u16_parse(self.ptr.mem_update_delay)

@property
def memory_update_margin(self):
return u16_parse(self.ptr.mem_update_margin)

@property
def comment(self):
return cstr.to_unicode(self.ptr.comment)
Expand Down
1 change: 1 addition & 0 deletions pyslurm/core/job/sbatch_opts.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ SBATCH_OPTIONS = [
SbatchOpt(None, "comment","comment"),
SbatchOpt("C", "constraint", "constraints"),
SbatchOpt(None, "container", "container"),
SbatchOpt(None, "container-type", "container_type"),
SbatchOpt(None, "contiguous", "requires_contiguous_nodes"),
SbatchOpt("S", "core-spec", "cores_reserved_for_system"),
SbatchOpt(None, "cores-per-socket", "cores_per_socket"),
Expand Down
2 changes: 2 additions & 0 deletions pyslurm/core/job/step.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ cdef class JobStep:
Path to the container OCI.
container_id (str):
The ID of the OCI Container.
container_type (str):
Container plugin type the Step uses.
allocated_nodes (str):
Nodes the Job is using.
start_time (int):
Expand Down
4 changes: 4 additions & 0 deletions pyslurm/core/job/step.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,10 @@ cdef class JobStep:
def container_id(self):
return cstr.to_unicode(self.ptr.container_id)

@property
def container_type(self):
return cstr.to_unicode(self.ptr.container_type)

def array_id(self):
return u32_parse(self.ptr.array_job_id)

Expand Down
4 changes: 4 additions & 0 deletions pyslurm/core/job/submission.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ cdef class JobSubmitDescription:
container_id (str):
Unique name for the Container
This is the same as --container-id from sbatch.
container_type (str):
Container plugin type to use.
This is the same as --container-type from sbatch.
cpus_per_task (int):
The amount of cpus required for each task.

Expand Down Expand Up @@ -624,6 +627,7 @@ cdef class JobSubmitDescription:
time_limit_min
container
container_id
container_type
cpus_per_task
cpus_per_gpu
sockets_per_node
Expand Down
1 change: 1 addition & 0 deletions pyslurm/core/job/submission.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ cdef class JobSubmitDescription:
cstr.fmalloc(&ptr.qos, self.qos)
cstr.fmalloc(&ptr.container, self.container)
cstr.fmalloc(&ptr.container_id, self.container_id)
cstr.fmalloc(&ptr.container_type, self.container_type)
cstr.fmalloc(&ptr.std_in, self.standard_in)
cstr.fmalloc(&ptr.std_out, self.standard_output)
cstr.fmalloc(&ptr.std_err, self.standard_error)
Expand Down
2 changes: 2 additions & 0 deletions pyslurm/core/node.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ cdef class Node:
Time this node was last busy, as unix timestamp.
reason_time (int):
Time the reason was set for the node, as unix timestamp.
suspend_time (int):
Time in seconds the node must be idle before power save kicks in.
allocated_tres (dict):
Currently allocated Trackable Resources
allocated_cpus (int):
Expand Down
4 changes: 4 additions & 0 deletions pyslurm/core/node.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,10 @@ cdef class Node:
def reason_time(self):
return _raw_time(self.info.reason_time)

@property
def suspend_time(self):
return u32_parse(self.info.suspend_time)

# @property
# def tres_configured(self):
# """dict: TRES that are configured on the node."""
Expand Down
1 change: 0 additions & 1 deletion pyslurm/core/reservation.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

from libc.string cimport memcpy, memset
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
from libc.stdlib cimport free
from pyslurm cimport slurm
from pyslurm.slurm cimport (
reserve_info_t,
Expand Down
4 changes: 3 additions & 1 deletion pyslurm/core/reservation.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ cdef class Reservation:

self.name = self._error_or_name()
new_name = slurm_create_reservation(self.umsg)
free(new_name)
# Since 26.05, the returned name is allocated with xmalloc, so it must
# be released with xfree instead of free.
xfree(new_name)
verify_rpc(slurm_errno())
return self

Expand Down
Loading