Skip to content

Commit ceeed14

Browse files
committed
flux-jobs: support inactive_reason output field
Problem: There are a number of fields in flux-jobs that are available to help users get details about how or why their job exited / finished / ended. However, it is scattered across several fields. It would be convenient if there were just one field that collated that information. Solution: Support a new "inactive_reason" output field. It will output if a job was canceled, signaled, timedout, or exited normally. Other contextual information will be output when available. Fixes #4946
1 parent 144b94e commit ceeed14

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

src/bindings/python/flux/compat36.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import signal
1212

13+
1314
# strsignal() is only available on Python 3.8 and up
1415
def strsignal(signum):
1516
if signum == signal.SIGHUP:

src/bindings/python/flux/job/info.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929
except ImportError:
3030
SchedResourceList = None
3131

32+
# strsignal() is only available in Python 3.8 and up.
33+
# flux-core's minimum is 3.6. Use compat library if not available.
34+
try:
35+
from signal import strsignal # novermin
36+
except ImportError:
37+
from flux.compat36 import strsignal
38+
3239

3340
def statetostr(stateid, fmt="L"):
3441
return raw.flux_job_statetostr(stateid, fmt).decode("utf-8")
@@ -541,6 +548,55 @@ def zero_remove(key):
541548

542549
return result
543550

551+
@memoized_property
552+
def inactive_reason(self):
553+
"""
554+
Generate contextual exit reason based on how the job ended
555+
"""
556+
state = str(self.state)
557+
if state != "INACTIVE":
558+
return ""
559+
result = str(self.result)
560+
if result == "CANCELED":
561+
if (
562+
self.exception.occurred
563+
and self.exception.type == "cancel"
564+
and self.exception.note
565+
):
566+
return f"Canceled: {self.exception.note}"
567+
else:
568+
return "Canceled"
569+
elif result == "FAILED":
570+
# exception.type == "exec" is special case, handled by returncode
571+
if (
572+
self.exception.occurred
573+
and self.exception.type != "exec"
574+
and self.exception.severity == 0
575+
):
576+
note = None
577+
if self.exception.note:
578+
note = f" note={self.exception.note}"
579+
return f'Exception: type={self.exception.type}{note or ""}'
580+
elif self.returncode > 128:
581+
signum = self.returncode - 128
582+
try:
583+
sigdesc = strsignal(signum)
584+
except ValueError:
585+
sigdesc = f"Signaled {signum}"
586+
return sigdesc
587+
elif self.returncode == 126:
588+
return "Command invoked cannot execute"
589+
elif self.returncode == 127:
590+
return "command not found"
591+
elif self.returncode == 128:
592+
return "Invalid argument to exit"
593+
else:
594+
return f"Exit {self.returncode}"
595+
elif result == "TIMEOUT":
596+
return "Timeout"
597+
else:
598+
return f"Exit {self.returncode}"
599+
544600

545601
def job_fields_to_attrs(fields):
546602
# Note there is no attr for "id", it is always returned
@@ -593,6 +649,15 @@ def job_fields_to_attrs(fields):
593649
"dependencies": ("dependencies",),
594650
"contextual_info": ("state", "dependencies", "annotations", "nodelist"),
595651
"contextual_time": ("state", "t_run", "t_cleanup", "duration"),
652+
"inactive_reason": (
653+
"state",
654+
"result",
655+
"waitstatus",
656+
"exception_occurred",
657+
"exception_severity",
658+
"exception_type",
659+
"exception_note",
660+
),
596661
# Special cases, pointers to sub-dicts in annotations
597662
"sched": ("annotations",),
598663
"user": ("annotations",),
@@ -676,6 +741,7 @@ class JobInfoFormat(flux.util.OutputFormat):
676741
"dependencies": "DEPENDENCIES",
677742
"contextual_info": "INFO",
678743
"contextual_time": "TIME",
744+
"inactive_reason": "INACTIVE-REASON",
679745
# The following are special pre-defined cases per RFC27
680746
"annotations.sched.t_estimate": "T_ESTIMATE",
681747
"annotations.sched.reason_pending": "REASON",

0 commit comments

Comments
 (0)