Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_job.py @ 3086220e

History | View | Annotate | Download (11 kB)

1 a09b9e3d Michael Hanselmann
#
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 7260cfbe Iustin Pop
"""Job related commands"""
22 7a1ecaed Iustin Pop
23 b459a848 Andrea Spadaccini
# pylint: disable=W0401,W0613,W0614,C0103
24 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
25 2d54e29c Iustin Pop
# W0613: Unused argument, since all functions follow the same API
26 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
27 7260cfbe Iustin Pop
# C0103: Invalid name gnt-job
28 2f79bd34 Iustin Pop
29 7a1ecaed Iustin Pop
from ganeti.cli import *
30 7a1ecaed Iustin Pop
from ganeti import constants
31 7a1ecaed Iustin Pop
from ganeti import errors
32 26f15862 Iustin Pop
from ganeti import utils
33 e7d6946c Michael Hanselmann
from ganeti import cli
34 3086220e Michael Hanselmann
from ganeti import qlang
35 7a1ecaed Iustin Pop
36 7a1ecaed Iustin Pop
37 917b4e56 Iustin Pop
#: default list of fields for L{ListJobs}
38 60dd1473 Iustin Pop
_LIST_DEF_FIELDS = ["id", "status", "summary"]
39 7a5d3bbd Iustin Pop
40 917b4e56 Iustin Pop
#: map converting the job status contants to user-visible
41 917b4e56 Iustin Pop
#: names
42 af30b2fd Michael Hanselmann
_USER_JOB_STATUS = {
43 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_QUEUED: "queued",
44 47099cd1 Michael Hanselmann
  constants.JOB_STATUS_WAITING: "waiting",
45 fbf0262f Michael Hanselmann
  constants.JOB_STATUS_CANCELING: "canceling",
46 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_RUNNING: "running",
47 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_CANCELED: "canceled",
48 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_SUCCESS: "success",
49 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_ERROR: "error",
50 af30b2fd Michael Hanselmann
  }
51 af30b2fd Michael Hanselmann
52 0ad64cf8 Michael Hanselmann
53 3086220e Michael Hanselmann
def _FormatStatus(value):
54 3086220e Michael Hanselmann
  """Formats a job status.
55 3086220e Michael Hanselmann

56 3086220e Michael Hanselmann
  """
57 3086220e Michael Hanselmann
  try:
58 3086220e Michael Hanselmann
    return _USER_JOB_STATUS[value]
59 3086220e Michael Hanselmann
  except KeyError:
60 3086220e Michael Hanselmann
    raise errors.ProgrammerError("Unknown job status code '%s'" % value)
61 3086220e Michael Hanselmann
62 3086220e Michael Hanselmann
63 7a1ecaed Iustin Pop
def ListJobs(opts, args):
64 7a1ecaed Iustin Pop
  """List the jobs
65 7a1ecaed Iustin Pop

66 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
67 917b4e56 Iustin Pop
  @type args: list
68 917b4e56 Iustin Pop
  @param args: should be an empty list
69 917b4e56 Iustin Pop
  @rtype: int
70 917b4e56 Iustin Pop
  @return: the desired exit code
71 917b4e56 Iustin Pop

72 7a1ecaed Iustin Pop
  """
73 a4ebd726 Michael Hanselmann
  selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
74 7a1ecaed Iustin Pop
75 3086220e Michael Hanselmann
  fmtoverride = {
76 3086220e Michael Hanselmann
    "status": (_FormatStatus, False),
77 3086220e Michael Hanselmann
    "summary": (lambda value: ",".join(str(item) for item in value), False),
78 3086220e Michael Hanselmann
    }
79 3086220e Michael Hanselmann
  fmtoverride.update(dict.fromkeys(["opstart", "opexec", "opend"],
80 3086220e Michael Hanselmann
    (lambda value: map(FormatTimestamp, value), None)))
81 7a1ecaed Iustin Pop
82 3086220e Michael Hanselmann
  return GenericList(constants.QR_JOB, selected_fields, args, None,
83 3086220e Michael Hanselmann
                     opts.separator, not opts.no_headers,
84 3086220e Michael Hanselmann
                     format_override=fmtoverride, verbose=opts.verbose,
85 3086220e Michael Hanselmann
                     force_filter=opts.force_filter, namefield="id")
86 b8802cc4 Michael Hanselmann
87 dcbd6288 Guido Trotter
88 3086220e Michael Hanselmann
def ListJobFields(opts, args):
89 3086220e Michael Hanselmann
  """List job fields.
90 7a1ecaed Iustin Pop

91 3086220e Michael Hanselmann
  @param opts: the command line options selected by the user
92 3086220e Michael Hanselmann
  @type args: list
93 3086220e Michael Hanselmann
  @param args: fields to list, or empty for all
94 3086220e Michael Hanselmann
  @rtype: int
95 3086220e Michael Hanselmann
  @return: the desired exit code
96 3086220e Michael Hanselmann

97 3086220e Michael Hanselmann
  """
98 3086220e Michael Hanselmann
  return GenericListFields(constants.QR_JOB, args, opts.separator,
99 3086220e Michael Hanselmann
                           not opts.no_headers)
100 7a1ecaed Iustin Pop
101 7a1ecaed Iustin Pop
102 0ad64cf8 Michael Hanselmann
def ArchiveJobs(opts, args):
103 917b4e56 Iustin Pop
  """Archive jobs.
104 917b4e56 Iustin Pop

105 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
106 917b4e56 Iustin Pop
  @type args: list
107 917b4e56 Iustin Pop
  @param args: should contain the job IDs to be archived
108 917b4e56 Iustin Pop
  @rtype: int
109 917b4e56 Iustin Pop
  @return: the desired exit code
110 917b4e56 Iustin Pop

111 917b4e56 Iustin Pop
  """
112 0ad64cf8 Michael Hanselmann
  client = GetClient()
113 0ad64cf8 Michael Hanselmann
114 aa9f8167 Iustin Pop
  rcode = 0
115 0ad64cf8 Michael Hanselmann
  for job_id in args:
116 aa9f8167 Iustin Pop
    if not client.ArchiveJob(job_id):
117 aa9f8167 Iustin Pop
      ToStderr("Failed to archive job with ID '%s'", job_id)
118 aa9f8167 Iustin Pop
      rcode = 1
119 0ad64cf8 Michael Hanselmann
120 aa9f8167 Iustin Pop
  return rcode
121 0ad64cf8 Michael Hanselmann
122 0ad64cf8 Michael Hanselmann
123 07cd723a Iustin Pop
def AutoArchiveJobs(opts, args):
124 917b4e56 Iustin Pop
  """Archive jobs based on age.
125 917b4e56 Iustin Pop

126 917b4e56 Iustin Pop
  This will archive jobs based on their age, or all jobs if a 'all' is
127 917b4e56 Iustin Pop
  passed.
128 917b4e56 Iustin Pop

129 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
130 917b4e56 Iustin Pop
  @type args: list
131 917b4e56 Iustin Pop
  @param args: should contain only one element, the age as a time spec
132 c41eea6e Iustin Pop
      that can be parsed by L{ganeti.cli.ParseTimespec} or the
133 c41eea6e Iustin Pop
      keyword I{all}, which will cause all jobs to be archived
134 917b4e56 Iustin Pop
  @rtype: int
135 917b4e56 Iustin Pop
  @return: the desired exit code
136 917b4e56 Iustin Pop

137 917b4e56 Iustin Pop
  """
138 07cd723a Iustin Pop
  client = GetClient()
139 07cd723a Iustin Pop
140 07cd723a Iustin Pop
  age = args[0]
141 07cd723a Iustin Pop
142 d0c8c01d Iustin Pop
  if age == "all":
143 07cd723a Iustin Pop
    age = -1
144 07cd723a Iustin Pop
  else:
145 07cd723a Iustin Pop
    age = ParseTimespec(age)
146 07cd723a Iustin Pop
147 f8ad5591 Michael Hanselmann
  (archived_count, jobs_left) = client.AutoArchiveJobs(age)
148 f8ad5591 Michael Hanselmann
  ToStdout("Archived %s jobs, %s unchecked left", archived_count, jobs_left)
149 f8ad5591 Michael Hanselmann
150 07cd723a Iustin Pop
  return 0
151 07cd723a Iustin Pop
152 07cd723a Iustin Pop
153 d2b92ffc Michael Hanselmann
def CancelJobs(opts, args):
154 917b4e56 Iustin Pop
  """Cancel not-yet-started jobs.
155 917b4e56 Iustin Pop

156 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
157 917b4e56 Iustin Pop
  @type args: list
158 917b4e56 Iustin Pop
  @param args: should contain the job IDs to be cancelled
159 917b4e56 Iustin Pop
  @rtype: int
160 917b4e56 Iustin Pop
  @return: the desired exit code
161 917b4e56 Iustin Pop

162 917b4e56 Iustin Pop
  """
163 d2b92ffc Michael Hanselmann
  client = GetClient()
164 06fef5e0 Michael Hanselmann
  result = constants.EXIT_SUCCESS
165 d2b92ffc Michael Hanselmann
166 d2b92ffc Michael Hanselmann
  for job_id in args:
167 06fef5e0 Michael Hanselmann
    (success, msg) = client.CancelJob(job_id)
168 06fef5e0 Michael Hanselmann
169 06fef5e0 Michael Hanselmann
    if not success:
170 06fef5e0 Michael Hanselmann
      result = constants.EXIT_FAILURE
171 06fef5e0 Michael Hanselmann
172 b28a3e8b Michael Hanselmann
    ToStdout(msg)
173 d2b92ffc Michael Hanselmann
174 06fef5e0 Michael Hanselmann
  return result
175 d2b92ffc Michael Hanselmann
176 d2b92ffc Michael Hanselmann
177 191712c0 Iustin Pop
def ShowJobs(opts, args):
178 917b4e56 Iustin Pop
  """Show detailed information about jobs.
179 917b4e56 Iustin Pop

180 917b4e56 Iustin Pop
  @param opts: the command line options selected by the user
181 917b4e56 Iustin Pop
  @type args: list
182 917b4e56 Iustin Pop
  @param args: should contain the job IDs to be queried
183 917b4e56 Iustin Pop
  @rtype: int
184 917b4e56 Iustin Pop
  @return: the desired exit code
185 191712c0 Iustin Pop

186 191712c0 Iustin Pop
  """
187 c04bc777 Iustin Pop
  def format_msg(level, text):
188 191712c0 Iustin Pop
    """Display the text indented."""
189 3a24c527 Iustin Pop
    ToStdout("%s%s", "  " * level, text)
190 191712c0 Iustin Pop
191 191712c0 Iustin Pop
  def result_helper(value):
192 191712c0 Iustin Pop
    """Format a result field in a nice way."""
193 191712c0 Iustin Pop
    if isinstance(value, (tuple, list)):
194 1f864b60 Iustin Pop
      return "[%s]" % utils.CommaJoin(value)
195 191712c0 Iustin Pop
    else:
196 191712c0 Iustin Pop
      return str(value)
197 191712c0 Iustin Pop
198 aad81f98 Iustin Pop
  selected_fields = [
199 aad81f98 Iustin Pop
    "id", "status", "ops", "opresult", "opstatus", "oplog",
200 b9b5abcb Iustin Pop
    "opstart", "opexec", "opend", "received_ts", "start_ts", "end_ts",
201 aad81f98 Iustin Pop
    ]
202 191712c0 Iustin Pop
203 eba1aaad Michael Hanselmann
  result = GetClient().Query(constants.QR_JOB, selected_fields,
204 eba1aaad Michael Hanselmann
                             qlang.MakeSimpleFilter("id", args)).data
205 191712c0 Iustin Pop
206 191712c0 Iustin Pop
  first = True
207 191712c0 Iustin Pop
208 eba1aaad Michael Hanselmann
  for entry in result:
209 191712c0 Iustin Pop
    if not first:
210 c04bc777 Iustin Pop
      format_msg(0, "")
211 191712c0 Iustin Pop
    else:
212 191712c0 Iustin Pop
      first = False
213 aad81f98 Iustin Pop
214 eba1aaad Michael Hanselmann
    ((_, job_id), (rs_status, status), (_, ops), (_, opresult), (_, opstatus),
215 eba1aaad Michael Hanselmann
     (_, oplog), (_, opstart), (_, opexec), (_, opend), (_, recv_ts),
216 eba1aaad Michael Hanselmann
     (_, start_ts), (_, end_ts)) = entry
217 eba1aaad Michael Hanselmann
218 eba1aaad Michael Hanselmann
    # Detect non-normal results
219 eba1aaad Michael Hanselmann
    if rs_status != constants.RS_NORMAL:
220 eba1aaad Michael Hanselmann
      format_msg(0, "Job ID %s not found" % job_id)
221 aad81f98 Iustin Pop
      continue
222 aad81f98 Iustin Pop
223 c04bc777 Iustin Pop
    format_msg(0, "Job ID: %s" % job_id)
224 191712c0 Iustin Pop
    if status in _USER_JOB_STATUS:
225 191712c0 Iustin Pop
      status = _USER_JOB_STATUS[status]
226 191712c0 Iustin Pop
    else:
227 2f79bd34 Iustin Pop
      raise errors.ProgrammerError("Unknown job status code '%s'" % status)
228 191712c0 Iustin Pop
229 c04bc777 Iustin Pop
    format_msg(1, "Status: %s" % status)
230 aad81f98 Iustin Pop
231 aad81f98 Iustin Pop
    if recv_ts is not None:
232 c04bc777 Iustin Pop
      format_msg(1, "Received:         %s" % FormatTimestamp(recv_ts))
233 aad81f98 Iustin Pop
    else:
234 c04bc777 Iustin Pop
      format_msg(1, "Missing received timestamp (%s)" % str(recv_ts))
235 aad81f98 Iustin Pop
236 aad81f98 Iustin Pop
    if start_ts is not None:
237 aad81f98 Iustin Pop
      if recv_ts is not None:
238 aad81f98 Iustin Pop
        d1 = start_ts[0] - recv_ts[0] + (start_ts[1] - recv_ts[1]) / 1000000.0
239 aad81f98 Iustin Pop
        delta = " (delta %.6fs)" % d1
240 aad81f98 Iustin Pop
      else:
241 aad81f98 Iustin Pop
        delta = ""
242 c04bc777 Iustin Pop
      format_msg(1, "Processing start: %s%s" %
243 c04bc777 Iustin Pop
                 (FormatTimestamp(start_ts), delta))
244 aad81f98 Iustin Pop
    else:
245 c04bc777 Iustin Pop
      format_msg(1, "Processing start: unknown (%s)" % str(start_ts))
246 aad81f98 Iustin Pop
247 aad81f98 Iustin Pop
    if end_ts is not None:
248 aad81f98 Iustin Pop
      if start_ts is not None:
249 aad81f98 Iustin Pop
        d2 = end_ts[0] - start_ts[0] + (end_ts[1] - start_ts[1]) / 1000000.0
250 aad81f98 Iustin Pop
        delta = " (delta %.6fs)" % d2
251 aad81f98 Iustin Pop
      else:
252 aad81f98 Iustin Pop
        delta = ""
253 c04bc777 Iustin Pop
      format_msg(1, "Processing end:   %s%s" %
254 c04bc777 Iustin Pop
                 (FormatTimestamp(end_ts), delta))
255 aad81f98 Iustin Pop
    else:
256 c04bc777 Iustin Pop
      format_msg(1, "Processing end:   unknown (%s)" % str(end_ts))
257 aad81f98 Iustin Pop
258 aad81f98 Iustin Pop
    if end_ts is not None and recv_ts is not None:
259 aad81f98 Iustin Pop
      d3 = end_ts[0] - recv_ts[0] + (end_ts[1] - recv_ts[1]) / 1000000.0
260 c04bc777 Iustin Pop
      format_msg(1, "Total processing time: %.6f seconds" % d3)
261 aad81f98 Iustin Pop
    else:
262 c04bc777 Iustin Pop
      format_msg(1, "Total processing time: N/A")
263 c04bc777 Iustin Pop
    format_msg(1, "Opcodes:")
264 b9b5abcb Iustin Pop
    for (opcode, result, status, log, s_ts, x_ts, e_ts) in \
265 b9b5abcb Iustin Pop
            zip(ops, opresult, opstatus, oplog, opstart, opexec, opend):
266 c04bc777 Iustin Pop
      format_msg(2, "%s" % opcode["OP_ID"])
267 c04bc777 Iustin Pop
      format_msg(3, "Status: %s" % status)
268 aad81f98 Iustin Pop
      if isinstance(s_ts, (tuple, list)):
269 c04bc777 Iustin Pop
        format_msg(3, "Processing start: %s" % FormatTimestamp(s_ts))
270 aad81f98 Iustin Pop
      else:
271 c04bc777 Iustin Pop
        format_msg(3, "No processing start time")
272 b9b5abcb Iustin Pop
      if isinstance(x_ts, (tuple, list)):
273 c04bc777 Iustin Pop
        format_msg(3, "Execution start:  %s" % FormatTimestamp(x_ts))
274 b9b5abcb Iustin Pop
      else:
275 c04bc777 Iustin Pop
        format_msg(3, "No execution start time")
276 aad81f98 Iustin Pop
      if isinstance(e_ts, (tuple, list)):
277 c04bc777 Iustin Pop
        format_msg(3, "Processing end:   %s" % FormatTimestamp(e_ts))
278 aad81f98 Iustin Pop
      else:
279 c04bc777 Iustin Pop
        format_msg(3, "No processing end time")
280 c04bc777 Iustin Pop
      format_msg(3, "Input fields:")
281 598b5255 Michael Hanselmann
      for key in utils.NiceSort(opcode.keys()):
282 191712c0 Iustin Pop
        if key == "OP_ID":
283 191712c0 Iustin Pop
          continue
284 598b5255 Michael Hanselmann
        val = opcode[key]
285 191712c0 Iustin Pop
        if isinstance(val, (tuple, list)):
286 08db7c5c Iustin Pop
          val = ",".join([str(item) for item in val])
287 c04bc777 Iustin Pop
        format_msg(4, "%s: %s" % (key, val))
288 191712c0 Iustin Pop
      if result is None:
289 c04bc777 Iustin Pop
        format_msg(3, "No output data")
290 191712c0 Iustin Pop
      elif isinstance(result, (tuple, list)):
291 191712c0 Iustin Pop
        if not result:
292 c04bc777 Iustin Pop
          format_msg(3, "Result: empty sequence")
293 191712c0 Iustin Pop
        else:
294 c04bc777 Iustin Pop
          format_msg(3, "Result:")
295 191712c0 Iustin Pop
          for elem in result:
296 c04bc777 Iustin Pop
            format_msg(4, result_helper(elem))
297 191712c0 Iustin Pop
      elif isinstance(result, dict):
298 191712c0 Iustin Pop
        if not result:
299 c04bc777 Iustin Pop
          format_msg(3, "Result: empty dictionary")
300 191712c0 Iustin Pop
        else:
301 d1b47b16 Michael Hanselmann
          format_msg(3, "Result:")
302 191712c0 Iustin Pop
          for key, val in result.iteritems():
303 c04bc777 Iustin Pop
            format_msg(4, "%s: %s" % (key, result_helper(val)))
304 191712c0 Iustin Pop
      else:
305 c04bc777 Iustin Pop
        format_msg(3, "Result: %s" % result)
306 c04bc777 Iustin Pop
      format_msg(3, "Execution log:")
307 3386e7a9 Iustin Pop
      for serial, log_ts, log_type, log_msg in log:
308 3386e7a9 Iustin Pop
        time_txt = FormatTimestamp(log_ts)
309 8a7f1c61 Michael Hanselmann
        encoded = FormatLogMessage(log_type, log_msg)
310 c04bc777 Iustin Pop
        format_msg(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded))
311 191712c0 Iustin Pop
  return 0
312 191712c0 Iustin Pop
313 191712c0 Iustin Pop
314 e7d6946c Michael Hanselmann
def WatchJob(opts, args):
315 e7d6946c Michael Hanselmann
  """Follow a job and print its output as it arrives.
316 e7d6946c Michael Hanselmann

317 e7d6946c Michael Hanselmann
  @param opts: the command line options selected by the user
318 e7d6946c Michael Hanselmann
  @type args: list
319 e7d6946c Michael Hanselmann
  @param args: Contains the job ID
320 e7d6946c Michael Hanselmann
  @rtype: int
321 e7d6946c Michael Hanselmann
  @return: the desired exit code
322 e7d6946c Michael Hanselmann

323 e7d6946c Michael Hanselmann
  """
324 e7d6946c Michael Hanselmann
  job_id = args[0]
325 e7d6946c Michael Hanselmann
326 e7d6946c Michael Hanselmann
  msg = ("Output from job %s follows" % job_id)
327 e7d6946c Michael Hanselmann
  ToStdout(msg)
328 e7d6946c Michael Hanselmann
  ToStdout("-" * len(msg))
329 e7d6946c Michael Hanselmann
330 e7d6946c Michael Hanselmann
  retcode = 0
331 e7d6946c Michael Hanselmann
  try:
332 e7d6946c Michael Hanselmann
    cli.PollJob(job_id)
333 e7d6946c Michael Hanselmann
  except errors.GenericError, err:
334 e7d6946c Michael Hanselmann
    (retcode, job_result) = cli.FormatError(err)
335 e7d6946c Michael Hanselmann
    ToStderr("Job %s failed: %s", job_id, job_result)
336 e7d6946c Michael Hanselmann
337 e7d6946c Michael Hanselmann
  return retcode
338 e7d6946c Michael Hanselmann
339 e7d6946c Michael Hanselmann
340 7a1ecaed Iustin Pop
commands = {
341 d0c8c01d Iustin Pop
  "list": (
342 6ea815cf Iustin Pop
    ListJobs, [ArgJobId()],
343 3086220e Michael Hanselmann
    [NOHDR_OPT, SEP_OPT, FIELDS_OPT, VERBOSE_OPT, FORCE_FILTER_OPT],
344 6ea815cf Iustin Pop
    "[job_id ...]",
345 3086220e Michael Hanselmann
    "Lists the jobs and their status. The available fields can be shown"
346 3086220e Michael Hanselmann
    " using the \"list-fields\" command (see the man page for details)."
347 3086220e Michael Hanselmann
    " The default field list is (in order): %s." %
348 3086220e Michael Hanselmann
    utils.CommaJoin(_LIST_DEF_FIELDS)),
349 3086220e Michael Hanselmann
  "list-fields": (
350 3086220e Michael Hanselmann
    ListJobFields, [ArgUnknown()],
351 3086220e Michael Hanselmann
    [NOHDR_OPT, SEP_OPT],
352 3086220e Michael Hanselmann
    "[fields...]",
353 3086220e Michael Hanselmann
    "Lists all available fields for jobs"),
354 d0c8c01d Iustin Pop
  "archive": (
355 064c21f8 Iustin Pop
    ArchiveJobs, [ArgJobId(min=1)], [],
356 6ea815cf Iustin Pop
    "<job-id> [<job-id> ...]", "Archive specified jobs"),
357 d0c8c01d Iustin Pop
  "autoarchive": (
358 6ea815cf Iustin Pop
    AutoArchiveJobs,
359 94182b63 Iustin Pop
    [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w", "all"])],
360 064c21f8 Iustin Pop
    [],
361 6ea815cf Iustin Pop
    "<age>", "Auto archive jobs older than the given age"),
362 d0c8c01d Iustin Pop
  "cancel": (
363 064c21f8 Iustin Pop
    CancelJobs, [ArgJobId(min=1)], [],
364 6ea815cf Iustin Pop
    "<job-id> [<job-id> ...]", "Cancel specified jobs"),
365 d0c8c01d Iustin Pop
  "info": (
366 064c21f8 Iustin Pop
    ShowJobs, [ArgJobId(min=1)], [],
367 6ea815cf Iustin Pop
    "<job-id> [<job-id> ...]",
368 6ea815cf Iustin Pop
    "Show detailed information about the specified jobs"),
369 d0c8c01d Iustin Pop
  "watch": (
370 064c21f8 Iustin Pop
    WatchJob, [ArgJobId(min=1, max=1)], [],
371 6ea815cf Iustin Pop
    "<job-id>", "Follows a job and prints its output as it arrives"),
372 7a1ecaed Iustin Pop
  }
373 7a1ecaed Iustin Pop
374 7a1ecaed Iustin Pop
375 029fe503 Guido Trotter
#: dictionary with aliases for commands
376 029fe503 Guido Trotter
aliases = {
377 029fe503 Guido Trotter
  "show": "info",
378 029fe503 Guido Trotter
  }
379 029fe503 Guido Trotter
380 029fe503 Guido Trotter
381 a09b9e3d Michael Hanselmann
def Main():
382 029fe503 Guido Trotter
  return GenericMain(commands, aliases=aliases)