+class JobSubmittedException(Exception):
+ """Job was submitted, client should exit.
+
+ This exception has one argument, the ID of the job that was
+ submitted. The handler should print this ID.
+
+ This is not an error, just a structured way to exit from clients.
+
+ """
+
+
+def SendJob(ops, cl=None):
+ """Function to submit an opcode without waiting for the results.
+
+ @type ops: list
+ @param ops: list of opcodes
+ @type cl: luxi.Client
+ @param cl: the luxi client to use for communicating with the master;
+ if None, a new client will be created
+
+ """
+ if cl is None:
+ cl = GetClient()
+
+ job_id = cl.SubmitJob(ops)
+
+ return job_id
+
+
+def PollJob(job_id, cl=None, feedback_fn=None):
+ """Function to poll for the result of a job.
+
+ @type job_id: job identified
+ @param job_id: the job to poll for results
+ @type cl: luxi.Client
+ @param cl: the luxi client to use for communicating with the master;
+ if None, a new client will be created
+
+ """
+ if cl is None:
+ cl = GetClient()
+
+ prev_job_info = None
+ prev_logmsg_serial = None
+
+ while True:
+ result = cl.WaitForJobChange(job_id, ["status"], prev_job_info,
+ prev_logmsg_serial)
+ if not result:
+ # job not found, go away!
+ raise errors.JobLost("Job with id %s lost" % job_id)
+
+ # Split result, a tuple of (field values, log entries)
+ (job_info, log_entries) = result
+ (status, ) = job_info
+
+ if log_entries:
+ for log_entry in log_entries:
+ (serial, timestamp, _, message) = log_entry
+ if callable(feedback_fn):
+ feedback_fn(log_entry[1:])
+ else:
+ print "%s %s" % (time.ctime(utils.MergeTime(timestamp)), message)
+ prev_logmsg_serial = max(prev_logmsg_serial, serial)
+
+ # TODO: Handle canceled and archived jobs
+ elif status in (constants.JOB_STATUS_SUCCESS, constants.JOB_STATUS_ERROR):
+ break
+
+ prev_job_info = job_info
+
+ jobs = cl.QueryJobs([job_id], ["status", "opresult"])
+ if not jobs:
+ raise errors.JobLost("Job with id %s lost" % job_id)
+
+ status, result = jobs[0]
+ if status == constants.JOB_STATUS_SUCCESS:
+ return result[0]
+ else:
+ raise errors.OpExecError(result)
+
+
+def SubmitOpCode(op, cl=None, feedback_fn=None):
+ """Legacy function to submit an opcode.