gnt-debug: Extend job queue tests
[ganeti-local] / scripts / gnt-job
index 44ae4b2..2e71bae 100755 (executable)
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 
 # 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
 # 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)
 # W0614: Unused import %s from wildcard import (since we need cli)
+# C0103: Invalid name gnt-job
 
 import sys
 
 
 import sys
 
@@ -77,6 +80,7 @@ def ListJobs(opts, args):
       "oplog": "OpCode_log",
       "summary": "Summary",
       "opstart": "OpCode_start",
       "oplog": "OpCode_log",
       "summary": "Summary",
       "opstart": "OpCode_start",
+      "opexec": "OpCode_exec",
       "opend": "OpCode_end",
       "start_ts": "Start",
       "end_ts": "End",
       "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)
         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 = "-"
         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()
 
   """
   client = GetClient()
 
+  rcode = 0
   for job_id in args:
   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):
 
 
 def AutoArchiveJobs(opts, args):
@@ -179,7 +186,7 @@ def CancelJobs(opts, args):
   client = GetClient()
 
   for job_id in 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?
     ToStdout(msg)
 
   # TODO: Different exit value if not all jobs were canceled?
@@ -196,7 +203,7 @@ def ShowJobs(opts, args):
   @return: the desired exit code
 
   """
   @return: the desired exit code
 
   """
-  def format(level, text):
+  def format_msg(level, text):
     """Display the text indented."""
     ToStdout("%s%s", "  " * level, text)
 
     """Display the text indented."""
     ToStdout("%s%s", "  " * level, text)
 
@@ -209,7 +216,7 @@ def ShowJobs(opts, args):
 
   selected_fields = [
     "id", "status", "ops", "opresult", "opstatus", "oplog",
 
   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)
     ]
 
   result = GetClient().QueryJobs(args, selected_fields)
@@ -218,33 +225,33 @@ def ShowJobs(opts, args):
 
   for idx, entry in enumerate(result):
     if not first:
 
   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):
     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
       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,
       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)
 
     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:
 
     if recv_ts is not None:
-      format(1, "Received:         %s" % FormatTimestamp(recv_ts))
+      format_msg(1, "Received:         %s" % FormatTimestamp(recv_ts))
     else:
     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:
 
     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 = ""
         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:
     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:
 
     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 = ""
         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:
     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
 
     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:
     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)):
       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:
       else:
-        format(3, "No processing start time")
+        format_msg(3, "No execution start time")
       if isinstance(e_ts, (tuple, list)):
       if isinstance(e_ts, (tuple, list)):
-        format(3, "Processing end:   %s" % FormatTimestamp(e_ts))
+        format_msg(3, "Processing end:   %s" % FormatTimestamp(e_ts))
       else:
       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])
       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:
       if result is None:
-        format(3, "No output data")
+        format_msg(3, "No output data")
       elif isinstance(result, (tuple, list)):
         if not result:
       elif isinstance(result, (tuple, list)):
         if not result:
-          format(3, "Result: empty sequence")
+          format_msg(3, "Result: empty sequence")
         else:
         else:
-          format(3, "Result:")
+          format_msg(3, "Result:")
           for elem in result:
           for elem in result:
-            format(4, result_helper(elem))
+            format_msg(4, result_helper(elem))
       elif isinstance(result, dict):
         if not result:
       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():
         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:
       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)
       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
 
 
   return 0
 
 
@@ -357,7 +370,7 @@ commands = {
     "<job-id> [<job-id> ...]", "Archive specified jobs"),
   'autoarchive': (
     AutoArchiveJobs,
     "<job-id> [<job-id> ...]", "Archive specified jobs"),
   'autoarchive': (
     AutoArchiveJobs,
-    [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w"])],
+    [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w", "all"])],
     [],
     "<age>", "Auto archive jobs older than the given age"),
   'cancel': (
     [],
     "<age>", "Auto archive jobs older than the given age"),
   'cancel': (