X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/1d2dcdfd59298fc8aad16d98ae59beaf8e05a4f6..8f9069e5a1c176a416e144b1e6fb8bfbb0fa85c0:/scripts/gnt-job diff --git a/scripts/gnt-job b/scripts/gnt-job index e6fcea5..2e71bae 100755 --- a/scripts/gnt-job +++ b/scripts/gnt-job @@ -18,10 +18,13 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. +"""Job related commands""" -# pylint: disable-msg=W0401,W0614 +# pylint: disable-msg=W0401,W0613,W0614,C0103 # W0401: Wildcard import ganeti.cli +# W0613: Unused argument, since all functions follow the same API # W0614: Unused import %s from wildcard import (since we need cli) +# C0103: Invalid name gnt-job import sys @@ -77,6 +80,7 @@ def ListJobs(opts, args): "oplog": "OpCode_log", "summary": "Summary", "opstart": "OpCode_start", + "opexec": "OpCode_exec", "opend": "OpCode_end", "start_ts": "Start", "end_ts": "End", @@ -103,7 +107,7 @@ def ListJobs(opts, args): val = ",".join(val) elif field in ("start_ts", "end_ts", "received_ts"): val = FormatTimestamp(val) - elif field in ("opstart", "opend"): + elif field in ("opstart", "opexec", "opend"): val = [FormatTimestamp(entry) for entry in val] elif field == "lock_status" and not val: val = "-" @@ -130,10 +134,13 @@ def ArchiveJobs(opts, args): """ client = GetClient() + rcode = 0 for job_id in args: - client.ArchiveJob(job_id) + if not client.ArchiveJob(job_id): + ToStderr("Failed to archive job with ID '%s'", job_id) + rcode = 1 - return 0 + return rcode def AutoArchiveJobs(opts, args): @@ -179,7 +186,7 @@ def CancelJobs(opts, args): client = GetClient() for job_id in args: - (success, msg) = client.CancelJob(job_id) + (_, msg) = client.CancelJob(job_id) ToStdout(msg) # TODO: Different exit value if not all jobs were canceled? @@ -196,20 +203,20 @@ def ShowJobs(opts, args): @return: the desired exit code """ - def format(level, text): + def format_msg(level, text): """Display the text indented.""" ToStdout("%s%s", " " * level, text) def result_helper(value): """Format a result field in a nice way.""" if isinstance(value, (tuple, list)): - return "[%s]" % (", ".join(str(elem) for elem in value)) + return "[%s]" % utils.CommaJoin(value) else: return str(value) selected_fields = [ "id", "status", "ops", "opresult", "opstatus", "oplog", - "opstart", "opend", "received_ts", "start_ts", "end_ts", + "opstart", "opexec", "opend", "received_ts", "start_ts", "end_ts", ] result = GetClient().QueryJobs(args, selected_fields) @@ -218,33 +225,33 @@ def ShowJobs(opts, args): for idx, entry in enumerate(result): if not first: - format(0, "") + format_msg(0, "") else: first = False if entry is None: if idx <= len(args): - format(0, "Job ID %s not found" % args[idx]) + format_msg(0, "Job ID %s not found" % args[idx]) else: # this should not happen, when we don't pass args it will be a # valid job returned - format(0, "Job ID requested as argument %s not found" % (idx + 1)) + format_msg(0, "Job ID requested as argument %s not found" % (idx + 1)) continue (job_id, status, ops, opresult, opstatus, oplog, - opstart, opend, recv_ts, start_ts, end_ts) = entry - format(0, "Job ID: %s" % job_id) + opstart, opexec, opend, recv_ts, start_ts, end_ts) = entry + format_msg(0, "Job ID: %s" % job_id) if status in _USER_JOB_STATUS: status = _USER_JOB_STATUS[status] else: raise errors.ProgrammerError("Unknown job status code '%s'" % status) - format(1, "Status: %s" % status) + format_msg(1, "Status: %s" % status) if recv_ts is not None: - format(1, "Received: %s" % FormatTimestamp(recv_ts)) + format_msg(1, "Received: %s" % FormatTimestamp(recv_ts)) else: - format(1, "Missing received timestamp (%s)" % str(recv_ts)) + format_msg(1, "Missing received timestamp (%s)" % str(recv_ts)) if start_ts is not None: if recv_ts is not None: @@ -252,9 +259,10 @@ def ShowJobs(opts, args): delta = " (delta %.6fs)" % d1 else: delta = "" - format(1, "Processing start: %s%s" % (FormatTimestamp(start_ts), delta)) + format_msg(1, "Processing start: %s%s" % + (FormatTimestamp(start_ts), delta)) else: - format(1, "Processing start: unknown (%s)" % str(start_ts)) + format_msg(1, "Processing start: unknown (%s)" % str(start_ts)) if end_ts is not None: if start_ts is not None: @@ -262,57 +270,62 @@ def ShowJobs(opts, args): delta = " (delta %.6fs)" % d2 else: delta = "" - format(1, "Processing end: %s%s" % (FormatTimestamp(end_ts), delta)) + format_msg(1, "Processing end: %s%s" % + (FormatTimestamp(end_ts), delta)) else: - format(1, "Processing end: unknown (%s)" % str(end_ts)) + format_msg(1, "Processing end: unknown (%s)" % str(end_ts)) if end_ts is not None and recv_ts is not None: d3 = end_ts[0] - recv_ts[0] + (end_ts[1] - recv_ts[1]) / 1000000.0 - format(1, "Total processing time: %.6f seconds" % d3) + format_msg(1, "Total processing time: %.6f seconds" % d3) else: - format(1, "Total processing time: N/A") - format(1, "Opcodes:") - for (opcode, result, status, log, s_ts, e_ts) in \ - zip(ops, opresult, opstatus, oplog, opstart, opend): - format(2, "%s" % opcode["OP_ID"]) - format(3, "Status: %s" % status) + format_msg(1, "Total processing time: N/A") + format_msg(1, "Opcodes:") + for (opcode, result, status, log, s_ts, x_ts, e_ts) in \ + zip(ops, opresult, opstatus, oplog, opstart, opexec, opend): + format_msg(2, "%s" % opcode["OP_ID"]) + format_msg(3, "Status: %s" % status) if isinstance(s_ts, (tuple, list)): - format(3, "Processing start: %s" % FormatTimestamp(s_ts)) + format_msg(3, "Processing start: %s" % FormatTimestamp(s_ts)) + else: + format_msg(3, "No processing start time") + if isinstance(x_ts, (tuple, list)): + format_msg(3, "Execution start: %s" % FormatTimestamp(x_ts)) else: - format(3, "No processing start time") + format_msg(3, "No execution start time") if isinstance(e_ts, (tuple, list)): - format(3, "Processing end: %s" % FormatTimestamp(e_ts)) + format_msg(3, "Processing end: %s" % FormatTimestamp(e_ts)) else: - format(3, "No processing end time") - format(3, "Input fields:") + format_msg(3, "No processing end time") + format_msg(3, "Input fields:") for key, val in opcode.iteritems(): if key == "OP_ID": continue if isinstance(val, (tuple, list)): val = ",".join([str(item) for item in val]) - format(4, "%s: %s" % (key, val)) + format_msg(4, "%s: %s" % (key, val)) if result is None: - format(3, "No output data") + format_msg(3, "No output data") elif isinstance(result, (tuple, list)): if not result: - format(3, "Result: empty sequence") + format_msg(3, "Result: empty sequence") else: - format(3, "Result:") + format_msg(3, "Result:") for elem in result: - format(4, result_helper(elem)) + format_msg(4, result_helper(elem)) elif isinstance(result, dict): if not result: - format(3, "Result: empty dictionary") + format_msg(3, "Result: empty dictionary") else: for key, val in result.iteritems(): - format(4, "%s: %s" % (key, result_helper(val))) + format_msg(4, "%s: %s" % (key, result_helper(val))) else: - format(3, "Result: %s" % result) - format(3, "Execution log:") + format_msg(3, "Result: %s" % result) + format_msg(3, "Execution log:") for serial, log_ts, log_type, log_msg in log: time_txt = FormatTimestamp(log_ts) - encoded = utils.SafeEncode(log_msg) - format(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded)) + encoded = FormatLogMessage(log_type, log_msg) + format_msg(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded)) return 0 @@ -343,31 +356,33 @@ def WatchJob(opts, args): commands = { - 'list': (ListJobs, [ArgJobId()], - [DEBUG_OPT, NOHDR_OPT, SEP_OPT, FIELDS_OPT], - "[job_id ...]", - "List the jobs and their status. The available fields are" - " (see the man page for details): id, status, op_list," - " op_status, op_result." - " The default field" - " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS)), - 'archive': (ArchiveJobs, [ArgJobId(min=1)], [DEBUG_OPT], - " [ ...]", - "Archive specified jobs"), - 'autoarchive': (AutoArchiveJobs, - [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w"])], - [DEBUG_OPT], - "", - "Auto archive jobs older than the given age"), - 'cancel': (CancelJobs, [ArgJobId(min=1)], [DEBUG_OPT], - " [ ...]", - "Cancel specified jobs"), - 'info': (ShowJobs, [ArgJobId(min=1)], [DEBUG_OPT], - " [ ...]", - "Show detailed information about the specified jobs"), - 'watch': (WatchJob, [ArgJobId(min=1, max=1)], [DEBUG_OPT], - "", - "Follows a job and prints its output as it arrives"), + 'list': ( + ListJobs, [ArgJobId()], + [NOHDR_OPT, SEP_OPT, FIELDS_OPT], + "[job_id ...]", + "List the jobs and their status. The available fields are" + " (see the man page for details): id, status, op_list," + " op_status, op_result." + " The default field" + " list is (in order): %s." % utils.CommaJoin(_LIST_DEF_FIELDS)), + 'archive': ( + ArchiveJobs, [ArgJobId(min=1)], [], + " [ ...]", "Archive specified jobs"), + 'autoarchive': ( + AutoArchiveJobs, + [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w", "all"])], + [], + "", "Auto archive jobs older than the given age"), + 'cancel': ( + CancelJobs, [ArgJobId(min=1)], [], + " [ ...]", "Cancel specified jobs"), + 'info': ( + ShowJobs, [ArgJobId(min=1)], [], + " [ ...]", + "Show detailed information about the specified jobs"), + 'watch': ( + WatchJob, [ArgJobId(min=1, max=1)], [], + "", "Follows a job and prints its output as it arrives"), }