Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-job @ e7d6946c

History | View | Annotate | Download (10.7 kB)

1 7a1ecaed Iustin Pop
#!/usr/bin/python
2 7a1ecaed Iustin Pop
#
3 7a1ecaed Iustin Pop
4 7a1ecaed Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 7a1ecaed Iustin Pop
#
6 7a1ecaed Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 7a1ecaed Iustin Pop
# it under the terms of the GNU General Public License as published by
8 7a1ecaed Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 7a1ecaed Iustin Pop
# (at your option) any later version.
10 7a1ecaed Iustin Pop
#
11 7a1ecaed Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 7a1ecaed Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 7a1ecaed Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 7a1ecaed Iustin Pop
# General Public License for more details.
15 7a1ecaed Iustin Pop
#
16 7a1ecaed Iustin Pop
# You should have received a copy of the GNU General Public License
17 7a1ecaed Iustin Pop
# along with this program; if not, write to the Free Software
18 7a1ecaed Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 7a1ecaed Iustin Pop
# 02110-1301, USA.
20 7a1ecaed Iustin Pop
21 7a1ecaed Iustin Pop
22 2f79bd34 Iustin Pop
# pylint: disable-msg=W0401,W0614
23 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
24 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
25 2f79bd34 Iustin Pop
26 7a1ecaed Iustin Pop
import sys
27 7a1ecaed Iustin Pop
28 7a1ecaed Iustin Pop
from ganeti.cli import *
29 7a1ecaed Iustin Pop
from ganeti import constants
30 7a1ecaed Iustin Pop
from ganeti import errors
31 26f15862 Iustin Pop
from ganeti import utils
32 e7d6946c Michael Hanselmann
from ganeti import cli
33 7a1ecaed Iustin Pop
34 7a1ecaed Iustin Pop
35 917b4e56 Iustin Pop
#: default list of fields for L{ListJobs}
36 60dd1473 Iustin Pop
_LIST_DEF_FIELDS = ["id", "status", "summary"]
37 7a5d3bbd Iustin Pop
38 917b4e56 Iustin Pop
#: map converting the job status contants to user-visible
39 917b4e56 Iustin Pop
#: names
40 af30b2fd Michael Hanselmann
_USER_JOB_STATUS = {
41 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_QUEUED: "queued",
42 e92376d7 Iustin Pop
  constants.JOB_STATUS_WAITLOCK: "waiting",
43 fbf0262f Michael Hanselmann
  constants.JOB_STATUS_CANCELING: "canceling",
44 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_RUNNING: "running",
45 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_CANCELED: "canceled",
46 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_SUCCESS: "success",
47 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_ERROR: "error",
48 af30b2fd Michael Hanselmann
  }
49 af30b2fd Michael Hanselmann
50 0ad64cf8 Michael Hanselmann
51 7a1ecaed Iustin Pop
def ListJobs(opts, args):
52 7a1ecaed Iustin Pop
  """List the jobs
53 7a1ecaed Iustin Pop
54 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
55 917b4e56 Iustin Pop
  @type args: list
56 917b4e56 Iustin Pop
  @param args: should be an empty list
57 917b4e56 Iustin Pop
  @rtype: int
58 917b4e56 Iustin Pop
  @return: the desired exit code
59 917b4e56 Iustin Pop
60 7a1ecaed Iustin Pop
  """
61 7a1ecaed Iustin Pop
  if opts.output is None:
62 7a5d3bbd Iustin Pop
    selected_fields = _LIST_DEF_FIELDS
63 7a5d3bbd Iustin Pop
  elif opts.output.startswith("+"):
64 7a5d3bbd Iustin Pop
    selected_fields = _LIST_DEF_FIELDS + opts.output[1:].split(",")
65 7a1ecaed Iustin Pop
  else:
66 7a1ecaed Iustin Pop
    selected_fields = opts.output.split(",")
67 7a1ecaed Iustin Pop
68 f1de3563 Iustin Pop
  output = GetClient().QueryJobs(args, selected_fields)
69 7a1ecaed Iustin Pop
  if not opts.no_headers:
70 af30b2fd Michael Hanselmann
    # TODO: Implement more fields
71 7a1ecaed Iustin Pop
    headers = {
72 7a1ecaed Iustin Pop
      "id": "ID",
73 7a1ecaed Iustin Pop
      "status": "Status",
74 af30b2fd Michael Hanselmann
      "ops": "OpCodes",
75 af30b2fd Michael Hanselmann
      "opresult": "OpCode_result",
76 af30b2fd Michael Hanselmann
      "opstatus": "OpCode_status",
77 5b23c34c Iustin Pop
      "oplog": "OpCode_log",
78 60dd1473 Iustin Pop
      "summary": "Summary",
79 aad81f98 Iustin Pop
      "opstart": "OpCode_start",
80 aad81f98 Iustin Pop
      "opend": "OpCode_end",
81 aad81f98 Iustin Pop
      "start_ts": "Start",
82 aad81f98 Iustin Pop
      "end_ts": "End",
83 aad81f98 Iustin Pop
      "received_ts": "Received",
84 7a1ecaed Iustin Pop
      }
85 7a1ecaed Iustin Pop
  else:
86 7a1ecaed Iustin Pop
    headers = None
87 7a1ecaed Iustin Pop
88 7a1ecaed Iustin Pop
  # change raw values to nicer strings
89 dcbd6288 Guido Trotter
  for row_id, row in enumerate(output):
90 dcbd6288 Guido Trotter
    if row is None:
91 dcbd6288 Guido Trotter
      ToStderr("No such job: %s" % args[row_id])
92 dcbd6288 Guido Trotter
      continue
93 dcbd6288 Guido Trotter
94 7a1ecaed Iustin Pop
    for idx, field in enumerate(selected_fields):
95 7a1ecaed Iustin Pop
      val = row[idx]
96 7a1ecaed Iustin Pop
      if field == "status":
97 af30b2fd Michael Hanselmann
        if val in _USER_JOB_STATUS:
98 af30b2fd Michael Hanselmann
          val = _USER_JOB_STATUS[val]
99 7a1ecaed Iustin Pop
        else:
100 7a1ecaed Iustin Pop
          raise errors.ProgrammerError("Unknown job status code '%s'" % val)
101 60dd1473 Iustin Pop
      elif field == "summary":
102 60dd1473 Iustin Pop
        val = ",".join(val)
103 aad81f98 Iustin Pop
      elif field in ("start_ts", "end_ts", "received_ts"):
104 aad81f98 Iustin Pop
        val = FormatTimestamp(val)
105 aad81f98 Iustin Pop
      elif field in ("opstart", "opend"):
106 aad81f98 Iustin Pop
        val = [FormatTimestamp(entry) for entry in val]
107 7a1ecaed Iustin Pop
108 7a1ecaed Iustin Pop
      row[idx] = str(val)
109 7a1ecaed Iustin Pop
110 7a1ecaed Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
111 f1de3563 Iustin Pop
                       fields=selected_fields, data=output)
112 7a1ecaed Iustin Pop
  for line in data:
113 3a24c527 Iustin Pop
    ToStdout(line)
114 7a1ecaed Iustin Pop
115 7a1ecaed Iustin Pop
  return 0
116 7a1ecaed Iustin Pop
117 7a1ecaed Iustin Pop
118 0ad64cf8 Michael Hanselmann
def ArchiveJobs(opts, args):
119 917b4e56 Iustin Pop
  """Archive jobs.
120 917b4e56 Iustin Pop
121 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
122 917b4e56 Iustin Pop
  @type args: list
123 917b4e56 Iustin Pop
  @param args: should contain the job IDs to be archived
124 917b4e56 Iustin Pop
  @rtype: int
125 917b4e56 Iustin Pop
  @return: the desired exit code
126 917b4e56 Iustin Pop
127 917b4e56 Iustin Pop
  """
128 0ad64cf8 Michael Hanselmann
  client = GetClient()
129 0ad64cf8 Michael Hanselmann
130 0ad64cf8 Michael Hanselmann
  for job_id in args:
131 0ad64cf8 Michael Hanselmann
    client.ArchiveJob(job_id)
132 0ad64cf8 Michael Hanselmann
133 0ad64cf8 Michael Hanselmann
  return 0
134 0ad64cf8 Michael Hanselmann
135 0ad64cf8 Michael Hanselmann
136 07cd723a Iustin Pop
def AutoArchiveJobs(opts, args):
137 917b4e56 Iustin Pop
  """Archive jobs based on age.
138 917b4e56 Iustin Pop
139 917b4e56 Iustin Pop
  This will archive jobs based on their age, or all jobs if a 'all' is
140 917b4e56 Iustin Pop
  passed.
141 917b4e56 Iustin Pop
142 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
143 917b4e56 Iustin Pop
  @type args: list
144 917b4e56 Iustin Pop
  @param args: should contain only one element, the age as a time spec
145 c41eea6e Iustin Pop
      that can be parsed by L{ganeti.cli.ParseTimespec} or the
146 c41eea6e Iustin Pop
      keyword I{all}, which will cause all jobs to be archived
147 917b4e56 Iustin Pop
  @rtype: int
148 917b4e56 Iustin Pop
  @return: the desired exit code
149 917b4e56 Iustin Pop
150 917b4e56 Iustin Pop
  """
151 07cd723a Iustin Pop
  client = GetClient()
152 07cd723a Iustin Pop
153 07cd723a Iustin Pop
  age = args[0]
154 07cd723a Iustin Pop
155 07cd723a Iustin Pop
  if age == 'all':
156 07cd723a Iustin Pop
    age = -1
157 07cd723a Iustin Pop
  else:
158 07cd723a Iustin Pop
    age = ParseTimespec(age)
159 07cd723a Iustin Pop
160 f8ad5591 Michael Hanselmann
  (archived_count, jobs_left) = client.AutoArchiveJobs(age)
161 f8ad5591 Michael Hanselmann
  ToStdout("Archived %s jobs, %s unchecked left", archived_count, jobs_left)
162 f8ad5591 Michael Hanselmann
163 07cd723a Iustin Pop
  return 0
164 07cd723a Iustin Pop
165 07cd723a Iustin Pop
166 d2b92ffc Michael Hanselmann
def CancelJobs(opts, args):
167 917b4e56 Iustin Pop
  """Cancel not-yet-started jobs.
168 917b4e56 Iustin Pop
169 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
170 917b4e56 Iustin Pop
  @type args: list
171 917b4e56 Iustin Pop
  @param args: should contain the job IDs to be cancelled
172 917b4e56 Iustin Pop
  @rtype: int
173 917b4e56 Iustin Pop
  @return: the desired exit code
174 917b4e56 Iustin Pop
175 917b4e56 Iustin Pop
  """
176 d2b92ffc Michael Hanselmann
  client = GetClient()
177 d2b92ffc Michael Hanselmann
178 d2b92ffc Michael Hanselmann
  for job_id in args:
179 b28a3e8b Michael Hanselmann
    (success, msg) = client.CancelJob(job_id)
180 b28a3e8b Michael Hanselmann
    ToStdout(msg)
181 d2b92ffc Michael Hanselmann
182 b28a3e8b Michael Hanselmann
  # TODO: Different exit value if not all jobs were canceled?
183 d2b92ffc Michael Hanselmann
  return 0
184 d2b92ffc Michael Hanselmann
185 d2b92ffc Michael Hanselmann
186 191712c0 Iustin Pop
def ShowJobs(opts, args):
187 917b4e56 Iustin Pop
  """Show detailed information about jobs.
188 917b4e56 Iustin Pop
189 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
190 917b4e56 Iustin Pop
  @type args: list
191 917b4e56 Iustin Pop
  @param args: should contain the job IDs to be queried
192 917b4e56 Iustin Pop
  @rtype: int
193 917b4e56 Iustin Pop
  @return: the desired exit code
194 191712c0 Iustin Pop
195 191712c0 Iustin Pop
  """
196 191712c0 Iustin Pop
  def format(level, text):
197 191712c0 Iustin Pop
    """Display the text indented."""
198 3a24c527 Iustin Pop
    ToStdout("%s%s", "  " * level, text)
199 191712c0 Iustin Pop
200 191712c0 Iustin Pop
  def result_helper(value):
201 191712c0 Iustin Pop
    """Format a result field in a nice way."""
202 191712c0 Iustin Pop
    if isinstance(value, (tuple, list)):
203 191712c0 Iustin Pop
      return "[%s]" % (", ".join(str(elem) for elem in value))
204 191712c0 Iustin Pop
    else:
205 191712c0 Iustin Pop
      return str(value)
206 191712c0 Iustin Pop
207 aad81f98 Iustin Pop
  selected_fields = [
208 aad81f98 Iustin Pop
    "id", "status", "ops", "opresult", "opstatus", "oplog",
209 aad81f98 Iustin Pop
    "opstart", "opend", "received_ts", "start_ts", "end_ts",
210 aad81f98 Iustin Pop
    ]
211 191712c0 Iustin Pop
212 191712c0 Iustin Pop
  result = GetClient().QueryJobs(args, selected_fields)
213 191712c0 Iustin Pop
214 191712c0 Iustin Pop
  first = True
215 191712c0 Iustin Pop
216 b27b39b0 Iustin Pop
  for idx, entry in enumerate(result):
217 191712c0 Iustin Pop
    if not first:
218 191712c0 Iustin Pop
      format(0, "")
219 191712c0 Iustin Pop
    else:
220 191712c0 Iustin Pop
      first = False
221 aad81f98 Iustin Pop
222 aad81f98 Iustin Pop
    if entry is None:
223 b27b39b0 Iustin Pop
      if idx <= len(args):
224 b27b39b0 Iustin Pop
        format(0, "Job ID %s not found" % args[idx])
225 b27b39b0 Iustin Pop
      else:
226 b27b39b0 Iustin Pop
        # this should not happen, when we don't pass args it will be a
227 b27b39b0 Iustin Pop
        # valid job returned
228 b27b39b0 Iustin Pop
        format(0, "Job ID requested as argument %s not found" % (idx + 1))
229 aad81f98 Iustin Pop
      continue
230 aad81f98 Iustin Pop
231 aad81f98 Iustin Pop
    (job_id, status, ops, opresult, opstatus, oplog,
232 aad81f98 Iustin Pop
     opstart, opend, recv_ts, start_ts, end_ts) = entry
233 191712c0 Iustin Pop
    format(0, "Job ID: %s" % job_id)
234 191712c0 Iustin Pop
    if status in _USER_JOB_STATUS:
235 191712c0 Iustin Pop
      status = _USER_JOB_STATUS[status]
236 191712c0 Iustin Pop
    else:
237 2f79bd34 Iustin Pop
      raise errors.ProgrammerError("Unknown job status code '%s'" % status)
238 191712c0 Iustin Pop
239 191712c0 Iustin Pop
    format(1, "Status: %s" % status)
240 aad81f98 Iustin Pop
241 aad81f98 Iustin Pop
    if recv_ts is not None:
242 aad81f98 Iustin Pop
      format(1, "Received:         %s" % FormatTimestamp(recv_ts))
243 aad81f98 Iustin Pop
    else:
244 aad81f98 Iustin Pop
      format(1, "Missing received timestamp (%s)" % str(recv_ts))
245 aad81f98 Iustin Pop
246 aad81f98 Iustin Pop
    if start_ts is not None:
247 aad81f98 Iustin Pop
      if recv_ts is not None:
248 aad81f98 Iustin Pop
        d1 = start_ts[0] - recv_ts[0] + (start_ts[1] - recv_ts[1]) / 1000000.0
249 aad81f98 Iustin Pop
        delta = " (delta %.6fs)" % d1
250 aad81f98 Iustin Pop
      else:
251 aad81f98 Iustin Pop
        delta = ""
252 aad81f98 Iustin Pop
      format(1, "Processing start: %s%s" % (FormatTimestamp(start_ts), delta))
253 aad81f98 Iustin Pop
    else:
254 aad81f98 Iustin Pop
      format(1, "Processing start: unknown (%s)" % str(start_ts))
255 aad81f98 Iustin Pop
256 aad81f98 Iustin Pop
    if end_ts is not None:
257 aad81f98 Iustin Pop
      if start_ts is not None:
258 aad81f98 Iustin Pop
        d2 = end_ts[0] - start_ts[0] + (end_ts[1] - start_ts[1]) / 1000000.0
259 aad81f98 Iustin Pop
        delta = " (delta %.6fs)" % d2
260 aad81f98 Iustin Pop
      else:
261 aad81f98 Iustin Pop
        delta = ""
262 aad81f98 Iustin Pop
      format(1, "Processing end:   %s%s" % (FormatTimestamp(end_ts), delta))
263 aad81f98 Iustin Pop
    else:
264 aad81f98 Iustin Pop
      format(1, "Processing end:   unknown (%s)" % str(end_ts))
265 aad81f98 Iustin Pop
266 aad81f98 Iustin Pop
    if end_ts is not None and recv_ts is not None:
267 aad81f98 Iustin Pop
      d3 = end_ts[0] - recv_ts[0] + (end_ts[1] - recv_ts[1]) / 1000000.0
268 aad81f98 Iustin Pop
      format(1, "Total processing time: %.6f seconds" % d3)
269 aad81f98 Iustin Pop
    else:
270 aad81f98 Iustin Pop
      format(1, "Total processing time: N/A")
271 191712c0 Iustin Pop
    format(1, "Opcodes:")
272 aad81f98 Iustin Pop
    for (opcode, result, status, log, s_ts, e_ts) in \
273 aad81f98 Iustin Pop
            zip(ops, opresult, opstatus, oplog, opstart, opend):
274 191712c0 Iustin Pop
      format(2, "%s" % opcode["OP_ID"])
275 191712c0 Iustin Pop
      format(3, "Status: %s" % status)
276 aad81f98 Iustin Pop
      if isinstance(s_ts, (tuple, list)):
277 aad81f98 Iustin Pop
        format(3, "Processing start: %s" % FormatTimestamp(s_ts))
278 aad81f98 Iustin Pop
      else:
279 aad81f98 Iustin Pop
        format(3, "No processing start time")
280 aad81f98 Iustin Pop
      if isinstance(e_ts, (tuple, list)):
281 aad81f98 Iustin Pop
        format(3, "Processing end:   %s" % FormatTimestamp(e_ts))
282 aad81f98 Iustin Pop
      else:
283 aad81f98 Iustin Pop
        format(3, "No processing end time")
284 191712c0 Iustin Pop
      format(3, "Input fields:")
285 191712c0 Iustin Pop
      for key, val in opcode.iteritems():
286 191712c0 Iustin Pop
        if key == "OP_ID":
287 191712c0 Iustin Pop
          continue
288 191712c0 Iustin Pop
        if isinstance(val, (tuple, list)):
289 08db7c5c Iustin Pop
          val = ",".join([str(item) for item in val])
290 191712c0 Iustin Pop
        format(4, "%s: %s" % (key, val))
291 191712c0 Iustin Pop
      if result is None:
292 191712c0 Iustin Pop
        format(3, "No output data")
293 191712c0 Iustin Pop
      elif isinstance(result, (tuple, list)):
294 191712c0 Iustin Pop
        if not result:
295 191712c0 Iustin Pop
          format(3, "Result: empty sequence")
296 191712c0 Iustin Pop
        else:
297 191712c0 Iustin Pop
          format(3, "Result:")
298 191712c0 Iustin Pop
          for elem in result:
299 191712c0 Iustin Pop
            format(4, result_helper(elem))
300 191712c0 Iustin Pop
      elif isinstance(result, dict):
301 191712c0 Iustin Pop
        if not result:
302 191712c0 Iustin Pop
          format(3, "Result: empty dictionary")
303 191712c0 Iustin Pop
        else:
304 191712c0 Iustin Pop
          for key, val in result.iteritems():
305 191712c0 Iustin Pop
            format(4, "%s: %s" % (key, result_helper(val)))
306 191712c0 Iustin Pop
      else:
307 191712c0 Iustin Pop
        format(3, "Result: %s" % result)
308 5b23c34c Iustin Pop
      format(3, "Execution log:")
309 3386e7a9 Iustin Pop
      for serial, log_ts, log_type, log_msg in log:
310 3386e7a9 Iustin Pop
        time_txt = FormatTimestamp(log_ts)
311 26f15862 Iustin Pop
        encoded = utils.SafeEncode(log_msg)
312 5b23c34c Iustin Pop
        format(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded))
313 191712c0 Iustin Pop
  return 0
314 191712c0 Iustin Pop
315 191712c0 Iustin Pop
316 e7d6946c Michael Hanselmann
def WatchJob(opts, args):
317 e7d6946c Michael Hanselmann
  """Follow a job and print its output as it arrives.
318 e7d6946c Michael Hanselmann
319 e7d6946c Michael Hanselmann
  @param opts: the command line options selected by the user
320 e7d6946c Michael Hanselmann
  @type args: list
321 e7d6946c Michael Hanselmann
  @param args: Contains the job ID
322 e7d6946c Michael Hanselmann
  @rtype: int
323 e7d6946c Michael Hanselmann
  @return: the desired exit code
324 e7d6946c Michael Hanselmann
325 e7d6946c Michael Hanselmann
  """
326 e7d6946c Michael Hanselmann
  job_id = args[0]
327 e7d6946c Michael Hanselmann
328 e7d6946c Michael Hanselmann
  msg = ("Output from job %s follows" % job_id)
329 e7d6946c Michael Hanselmann
  ToStdout(msg)
330 e7d6946c Michael Hanselmann
  ToStdout("-" * len(msg))
331 e7d6946c Michael Hanselmann
332 e7d6946c Michael Hanselmann
  retcode = 0
333 e7d6946c Michael Hanselmann
  try:
334 e7d6946c Michael Hanselmann
    cli.PollJob(job_id)
335 e7d6946c Michael Hanselmann
  except errors.GenericError, err:
336 e7d6946c Michael Hanselmann
    (retcode, job_result) = cli.FormatError(err)
337 e7d6946c Michael Hanselmann
    ToStderr("Job %s failed: %s", job_id, job_result)
338 e7d6946c Michael Hanselmann
339 e7d6946c Michael Hanselmann
  return retcode
340 e7d6946c Michael Hanselmann
341 e7d6946c Michael Hanselmann
342 7a1ecaed Iustin Pop
commands = {
343 f1de3563 Iustin Pop
  'list': (ListJobs, ARGS_ANY,
344 f1de3563 Iustin Pop
            [DEBUG_OPT, NOHDR_OPT, SEP_OPT, FIELDS_OPT],
345 f1de3563 Iustin Pop
            "[job_id ...]",
346 f1de3563 Iustin Pop
           "List the jobs and their status. The available fields are"
347 35049ff2 Iustin Pop
           " (see the man page for details): id, status, op_list,"
348 35049ff2 Iustin Pop
           " op_status, op_result."
349 7a1ecaed Iustin Pop
           " The default field"
350 0ad64cf8 Michael Hanselmann
           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS)),
351 0ad64cf8 Michael Hanselmann
  'archive': (ArchiveJobs, ARGS_ANY,
352 0ad64cf8 Michael Hanselmann
              [DEBUG_OPT],
353 0ad64cf8 Michael Hanselmann
              "<job-id> [<job-id> ...]",
354 0ad64cf8 Michael Hanselmann
              "Archive specified jobs"),
355 07cd723a Iustin Pop
  'autoarchive': (AutoArchiveJobs, ARGS_ONE,
356 07cd723a Iustin Pop
              [DEBUG_OPT],
357 07cd723a Iustin Pop
              "<age>",
358 07cd723a Iustin Pop
              "Auto archive jobs older than the given age"),
359 d2b92ffc Michael Hanselmann
  'cancel': (CancelJobs, ARGS_ANY,
360 d2b92ffc Michael Hanselmann
             [DEBUG_OPT],
361 d2b92ffc Michael Hanselmann
             "<job-id> [<job-id> ...]",
362 d2b92ffc Michael Hanselmann
             "Cancel specified jobs"),
363 191712c0 Iustin Pop
  'info': (ShowJobs, ARGS_ANY, [DEBUG_OPT],
364 191712c0 Iustin Pop
           "<job-id> [<job-id> ...]",
365 191712c0 Iustin Pop
           "Show detailed information about the specified jobs"),
366 e7d6946c Michael Hanselmann
  'watch': (WatchJob, ARGS_ONE, [DEBUG_OPT],
367 e7d6946c Michael Hanselmann
           "<job-id>",
368 e7d6946c Michael Hanselmann
           "Follows a job and prints its output as it arrives"),
369 7a1ecaed Iustin Pop
  }
370 7a1ecaed Iustin Pop
371 7a1ecaed Iustin Pop
372 7a1ecaed Iustin Pop
if __name__ == '__main__':
373 7a1ecaed Iustin Pop
  sys.exit(GenericMain(commands))