From 35049ff2adcd6b5b1b64efb2db58b3b0322975b7 Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Thu, 10 Apr 2008 15:36:29 +0000 Subject: [PATCH] Add per-opcode results to job processing This patch changes the definition of a job and introduces per-opcode results. First, the result and status fields of a job are condensed into a single 'status' attribute. Then, we introduce an opcode status and one result list, that allow jobs to return values. The gnt-job script is also modified to allow these new fields to be queried. Note that the patch changes the opcode field to op_list, and it changes its return value from string to a list of (serialized) opcodes. Reviewed-by: ultrotter --- daemons/ganeti-masterd | 17 ++++++++++++++--- lib/jqueue.py | 10 ++++++++-- lib/opcodes.py | 28 ++++++++++++++++++++++------ scripts/gnt-job | 13 ++++++++++--- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/daemons/ganeti-masterd b/daemons/ganeti-masterd index 24fec0ead..d67b6fd4d 100644 --- a/daemons/ganeti-masterd +++ b/daemons/ganeti-masterd @@ -236,9 +236,20 @@ def JobRunner(proc, job): """ job.SetStatus(opcodes.Job.STATUS_RUNNING) - for op in job.data.op_list: - proc.ExecOpCode(op) - job.SetStatus(opcodes.Job.STATUS_FINISHED, result=opcodes.Job.RESULT_OK) + fail = False + for idx, op in enumerate(job.data.op_list): + job.data.op_status[idx] = opcodes.Job.STATUS_RUNNING + try: + job.data.op_result[idx] = proc.ExecOpCode(op) + job.data.op_status[idx] = opcodes.Job.STATUS_SUCCESS + except (errors.OpPrereqError, errors.OpExecError), err: + fail = True + job.data.op_result[idx] = str(err) + job.data.op_status[idx] = opcodes.Job.STATUS_FAIL + if fail: + job.SetStatus(opcodes.Job.STATUS_FAIL) + else: + job.SetStatus(opcodes.Job.STATUS_SUCCESS) def PoolWorker(worker_id, incoming_queue): diff --git a/lib/jqueue.py b/lib/jqueue.py index b0b8916d7..783c597de 100644 --- a/lib/jqueue.py +++ b/lib/jqueue.py @@ -38,6 +38,8 @@ class JobObject: self.data = jdesc jdesc.status = opcodes.Job.STATUS_PENDING jdesc.job_id = jid + jdesc.op_status = [opcodes.Job.STATUS_PENDING for i in jdesc.op_list] + jdesc.op_result = [None for i in jdesc.op_list] self.lock = threading.Lock() def SetStatus(self, status, result=None): @@ -114,8 +116,12 @@ class QueueManager: row.append(jdata.job_id) elif fname == "status": row.append(jdata.status) - elif fname == "opcodes": - row.append(",".join([op.OP_ID for op in jdata.op_list])) + elif fname == "op_list": + row.append([op.__getstate__() for op in jdata.op_list]) + elif fname == "op_status": + row.append(jdata.op_status) + elif fname == "op_result": + row.append(jdata.op_result) else: raise errors.OpExecError("Invalid job query field '%s'" % fname) diff --git a/lib/opcodes.py b/lib/opcodes.py index a5e41dee3..a5d8dedfe 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -74,15 +74,31 @@ class BaseJO(object): class Job(BaseJO): - """Job definition structure""" + """Job definition structure + + The Job definitions has two sets of parameters: + - the parameters of the job itself (all filled by server): + - job_id, + - status: pending, running, successfull, failed, aborted + - opcode parameters: + - op_list, list of opcodes, clients creates this + - op_status, status for each opcode, server fills in + - op_result, result for each opcode, server fills in + + """ STATUS_PENDING = 1 STATUS_RUNNING = 2 - STATUS_FINISHED = 3 - RESULT_OK = 1 - RESULT_FAIL = 2 - RESULT_ABORT = 3 + STATUS_SUCCESS = 3 + STATUS_FAIL = 4 + STATUS_ABORT = 5 - __slots__ = ["job_id", "op_list", "status", "result"] + __slots__ = [ + "job_id", + "status", + "op_list", + "op_status", + "op_result", + ] def __getstate__(self): """Specialized getstate for jobs diff --git a/scripts/gnt-job b/scripts/gnt-job index e438f5aed..e98f6373a 100644 --- a/scripts/gnt-job +++ b/scripts/gnt-job @@ -53,7 +53,9 @@ def ListJobs(opts, args): headers = { "id": "ID", "status": "Status", - "opcodes": "OpCodes", + "op_list": "OpCodes", + "op_status": "OpStatus", + "op_result": "OpResult", } else: headers = None @@ -71,8 +73,12 @@ def ListJobs(opts, args): val = "pending" elif val == opcodes.Job.STATUS_RUNNING: val = "running" - elif val == opcodes.Job.STATUS_FINISHED: + elif val == opcodes.Job.STATUS_SUCCESS: val = "finished" + elif val == opcodes.Job.STATUS_FAIL: + val = "failed" + elif val == opcodes.Job.STATUS_ABORT: + val = "aborted" else: raise errors.ProgrammerError("Unknown job status code '%s'" % val) @@ -91,7 +97,8 @@ commands = { 'list': (ListJobs, ARGS_NONE, [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT], "", "List the jobs and their status. The available fields are" - " (see the man page for details): id, status, opcodes." + " (see the man page for details): id, status, op_list," + " op_status, op_result." " The default field" " list is (in order): id, status."), } -- GitLab