Skip to content
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
16 changes: 14 additions & 2 deletions src/DIRAC/Interfaces/API/Dirac.py
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,10 @@ def deleteJob(self, jobID):
return ret
jobID = ret["Value"]

res = JobStatus.checkJobStateTransition(jobID, JobStatus.DELETED)
Copy link
Contributor

Choose a reason for hiding this comment

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

If running, these jobs will be first killed.

I don't think it will work as expected:

>>> JobsStateMachine('Running').getNextState('Deleted')
{'OK': True, 'Value': 'Running'}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added the checkJobStateTransition that would return {'OK': False} in this case.

if not res["OK"]:
return res

result = WMSClient(useCertificates=self.useCertificates).deleteJob(jobID)
if result["OK"]:
if self.jobRepo:
Expand Down Expand Up @@ -1705,6 +1709,10 @@ def rescheduleJob(self, jobID):
return ret
jobID = ret["Value"]

res = JobStatus.checkJobStateTransition(jobID, JobStatus.RESCHEDULED)
if not res["OK"]:
return res

result = WMSClient(useCertificates=self.useCertificates).rescheduleJob(jobID)
if result["OK"]:
if self.jobRepo:
Expand All @@ -1721,11 +1729,11 @@ def killJob(self, jobID):

Example Usage:

>>> print dirac.killJob(12345)
>>> print(dirac.killJob(12345))
{'OK': True, 'Value': [12345]}

:param jobID: JobID
:type jobID: int, str or python:list
:type jobID: int, str
:returns: S_OK,S_ERROR

"""
Expand All @@ -1734,6 +1742,10 @@ def killJob(self, jobID):
return ret
jobID = ret["Value"]

res = JobStatus.checkJobStateTransition(jobID, JobStatus.KILLED)
if not res["OK"]:
return res

result = WMSClient(useCertificates=self.useCertificates).killJob(jobID)
if result["OK"]:
if self.jobRepo:
Expand Down
31 changes: 31 additions & 0 deletions src/DIRAC/WorkloadManagementSystem/Client/JobStatus.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

__RCSID__ = "$Id$"

from DIRAC import gLogger, S_OK, S_ERROR
from DIRAC.Core.Utilities.StateMachine import State, StateMachine


Expand Down Expand Up @@ -96,3 +97,33 @@ def __init__(self, state):
RECEIVED: State(1, [CHECKING, WAITING, FAILED, DELETED], defState=RECEIVED),
SUBMITTING: State(0, [RECEIVED, CHECKING, DELETED], defState=SUBMITTING), # initial state
}


def checkJobStateTransition(jobID, candidateState, currentStatus=None, jobMonitoringClient=None):
"""Utility to check if a job state transition is allowed"""
if not currentStatus:
if not jobMonitoringClient:
from DIRAC.WorkloadManagementSystem.Client.JobMonitoringClient import JobMonitoringClient

jobMonitoringClient = JobMonitoringClient()

res = jobMonitoringClient.getJobsStatus(jobID)
if not res["OK"]:
return res
try:
currentStatus = res["Value"][jobID]["Status"]
except KeyError:
return S_ERROR("Job does not exist")

res = JobsStateMachine(currentStatus).getNextState(candidateState)
if not res["OK"]:
return res

# If the JobsStateMachine does not accept the candidate, return an ERROR
if candidateState != res["Value"]:
gLogger.error(
"Job Status Error",
"%s can't move from %s to %s" % (jobID, currentStatus, candidateState),
)
return S_ERROR("Job state transition not allowed")
return S_OK()
2 changes: 1 addition & 1 deletion src/DIRAC/WorkloadManagementSystem/DB/JobDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ def setJobsMajorStatus(self, jIDList, candidateStatus, force=False):
return res
nextState = res["Value"]

# If the JobsStateMachine does not accept the candidate, add it to separate dictionary
# The JobsStateMachine might force a different status
if candidateStatus != nextState:
self.log.error(
"Job Status Error",
Expand Down