Commit 3895ae24 by Enrico Pozzobon

allow user to cancel scheduled or running tests

parent 72e9cc76
...@@ -219,9 +219,11 @@ function showJobMenu(event, jobId) { ...@@ -219,9 +219,11 @@ function showJobMenu(event, jobId) {
const st = schedule[jobId].state; const st = schedule[jobId].state;
if (st == 'SUCCESSFUL' || st == 'FAILED') { if (st == 'SUCCESSFUL' || st == 'FAILED') {
menuView.appendChild(makeEntry('↺ Retry', () => restartJob(jobId))); menuView.appendChild(makeEntry('↺ Retry', () => restartJob(jobId)));
}
if (st == 'SUCCESSFUL' || st == 'FAILED' || st == 'SCHEDULED') {
menuView.appendChild(makeEntry('🗑️ Delete', () => deleteJob(jobId))); menuView.appendChild(makeEntry('🗑️ Delete', () => deleteJob(jobId)));
} }
if (st == 'RUNNING' || st == 'SCHEDULED') { if (st == 'RUNNING') {
menuView.appendChild(makeEntry('🗴 Cancel', () => cancelJob(jobId))); menuView.appendChild(makeEntry('🗴 Cancel', () => cancelJob(jobId)));
} }
menuView.appendChild(makeEntry('🗎 View Logs', () => viewJobLogs(jobId))); menuView.appendChild(makeEntry('🗎 View Logs', () => viewJobLogs(jobId)));
......
...@@ -64,6 +64,8 @@ class ScheduledTest: ...@@ -64,6 +64,8 @@ class ScheduledTest:
if k not in ScheduledTest._unserialized_slots: if k not in ScheduledTest._unserialized_slots:
if k != 'id': if k != 'id':
setattr(a, k, dict[k]) setattr(a, k, dict[k])
if a.state == 'RUNNING':
a.state = 'SCHEDULED'
return a return a
...@@ -81,8 +83,13 @@ class Runner(threading.Thread): ...@@ -81,8 +83,13 @@ class Runner(threading.Thread):
self.program = program self.program = program
self.process = None self.process = None
self.job = None self.job = None
# Event used for stopping the runner
self.stop_event = threading.Event() self.stop_event = threading.Event()
# Event used to abort only the current job
self.abort_event = threading.Event()
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.name += "-%s" % template self.name += "-%s" % template
self.start() self.start()
...@@ -96,8 +103,12 @@ class Runner(threading.Thread): ...@@ -96,8 +103,12 @@ class Runner(threading.Thread):
} }
def stop(self): def stop(self):
self.abort_event.set()
self.stop_event.set() self.stop_event.set()
def abort_current_job(self):
self.abort_event.set()
def lock_new_job(self): def lock_new_job(self):
my_queue = [ my_queue = [
s for s in schedule s for s in schedule
...@@ -124,6 +135,7 @@ class Runner(threading.Thread): ...@@ -124,6 +135,7 @@ class Runner(threading.Thread):
def do_job(self): def do_job(self):
self.job.time_started = int(time.time()) self.job.time_started = int(time.time())
self.abort_event.clear()
cmd = [] cmd = []
cmd += self.program cmd += self.program
...@@ -139,7 +151,7 @@ class Runner(threading.Thread): ...@@ -139,7 +151,7 @@ class Runner(threading.Thread):
stderr=err_fd stderr=err_fd
) )
while self.process.poll() is None: while self.process.poll() is None:
if self.stop_event.wait(timeout=1): if self.abort_event.wait(timeout=1):
self.process.send_signal(signal.SIGINT) self.process.send_signal(signal.SIGINT)
try: try:
self.process.wait(timeout=1) self.process.wait(timeout=1)
...@@ -201,6 +213,27 @@ class DeleteJob(Resource): ...@@ -201,6 +213,27 @@ class DeleteJob(Resource):
return 'Job is already running', 400 return 'Job is already running', 400
class CancelJob(Resource):
def get(self, job_id):
job = [job for job in schedule if job.id == job_id]
job = job[0] if len(job) > 0 else None
if job is None:
return 'Job not found', 404
with job.lock:
if job.state == 'RUNNING':
r = [r for r in runners if r if r.job == job]
if len(r) == 0:
return 'Job runner not found', 404
process = r[0].process
if process is None:
return 'Job runner process not found', 404
process.send_signal(signal.SIGINT)
return jsonify({'success': True})
else:
return 'Job is not running', 400
class RestartJob(Resource): class RestartJob(Resource):
def get(self, job_id): def get(self, job_id):
job = [job for job in schedule if job.id == job_id] job = [job for job in schedule if job.id == job_id]
...@@ -238,6 +271,7 @@ class ScheduleJob(Resource): ...@@ -238,6 +271,7 @@ class ScheduleJob(Resource):
api.add_resource(Status, '/status') api.add_resource(Status, '/status')
api.add_resource(ScheduleJob, '/schedule_test') api.add_resource(ScheduleJob, '/schedule_test')
api.add_resource(CancelJob, '/cancel_test/<string:job_id>')
api.add_resource(RestartJob, '/restart_test/<string:job_id>') api.add_resource(RestartJob, '/restart_test/<string:job_id>')
api.add_resource(DeleteJob, '/delete_test/<string:job_id>') api.add_resource(DeleteJob, '/delete_test/<string:job_id>')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment