Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-job @ 3ccafd0e

History | View | Annotate | Download (8.5 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 7a1ecaed Iustin Pop
import sys
23 7a1ecaed Iustin Pop
import os
24 7a1ecaed Iustin Pop
import itertools
25 5b23c34c Iustin Pop
import time
26 7a1ecaed Iustin Pop
from optparse import make_option
27 7a1ecaed Iustin Pop
from cStringIO import StringIO
28 7a1ecaed Iustin Pop
29 7a1ecaed Iustin Pop
from ganeti.cli import *
30 7a1ecaed Iustin Pop
from ganeti import opcodes
31 7a1ecaed Iustin Pop
from ganeti import logger
32 7a1ecaed Iustin Pop
from ganeti import constants
33 7a1ecaed Iustin Pop
from ganeti import utils
34 7a1ecaed Iustin Pop
from ganeti import errors
35 7a1ecaed Iustin Pop
36 7a1ecaed Iustin Pop
37 60dd1473 Iustin Pop
_LIST_DEF_FIELDS = ["id", "status", "summary"]
38 7a5d3bbd Iustin Pop
39 af30b2fd Michael Hanselmann
_USER_JOB_STATUS = {
40 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_QUEUED: "queued",
41 e92376d7 Iustin Pop
  constants.JOB_STATUS_WAITLOCK: "waiting",
42 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_RUNNING: "running",
43 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_CANCELED: "canceled",
44 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_SUCCESS: "success",
45 af30b2fd Michael Hanselmann
  constants.JOB_STATUS_ERROR: "error",
46 af30b2fd Michael Hanselmann
  }
47 af30b2fd Michael Hanselmann
48 0ad64cf8 Michael Hanselmann
49 7a1ecaed Iustin Pop
def ListJobs(opts, args):
50 7a1ecaed Iustin Pop
  """List the jobs
51 7a1ecaed Iustin Pop
52 7a1ecaed Iustin Pop
  """
53 7a1ecaed Iustin Pop
  if opts.output is None:
54 7a5d3bbd Iustin Pop
    selected_fields = _LIST_DEF_FIELDS
55 7a5d3bbd Iustin Pop
  elif opts.output.startswith("+"):
56 7a5d3bbd Iustin Pop
    selected_fields = _LIST_DEF_FIELDS + opts.output[1:].split(",")
57 7a1ecaed Iustin Pop
  else:
58 7a1ecaed Iustin Pop
    selected_fields = opts.output.split(",")
59 7a1ecaed Iustin Pop
60 af30b2fd Michael Hanselmann
  output = GetClient().QueryJobs(None, selected_fields)
61 7a1ecaed Iustin Pop
  if not opts.no_headers:
62 af30b2fd Michael Hanselmann
    # TODO: Implement more fields
63 7a1ecaed Iustin Pop
    headers = {
64 7a1ecaed Iustin Pop
      "id": "ID",
65 7a1ecaed Iustin Pop
      "status": "Status",
66 af30b2fd Michael Hanselmann
      "ops": "OpCodes",
67 af30b2fd Michael Hanselmann
      "opresult": "OpCode_result",
68 af30b2fd Michael Hanselmann
      "opstatus": "OpCode_status",
69 5b23c34c Iustin Pop
      "oplog": "OpCode_log",
70 60dd1473 Iustin Pop
      "summary": "Summary",
71 aad81f98 Iustin Pop
      "opstart": "OpCode_start",
72 aad81f98 Iustin Pop
      "opend": "OpCode_end",
73 aad81f98 Iustin Pop
      "start_ts": "Start",
74 aad81f98 Iustin Pop
      "end_ts": "End",
75 aad81f98 Iustin Pop
      "received_ts": "Received",
76 7a1ecaed Iustin Pop
      }
77 7a1ecaed Iustin Pop
  else:
78 7a1ecaed Iustin Pop
    headers = None
79 7a1ecaed Iustin Pop
80 7a1ecaed Iustin Pop
  # we don't have yet unitfields here
81 7a1ecaed Iustin Pop
  unitfields = None
82 5ce81b28 Michael Hanselmann
  numfields = None
83 7a1ecaed Iustin Pop
84 7a1ecaed Iustin Pop
  # change raw values to nicer strings
85 7a1ecaed Iustin Pop
  for row in output:
86 7a1ecaed Iustin Pop
    for idx, field in enumerate(selected_fields):
87 7a1ecaed Iustin Pop
      val = row[idx]
88 7a1ecaed Iustin Pop
      if field == "status":
89 af30b2fd Michael Hanselmann
        if val in _USER_JOB_STATUS:
90 af30b2fd Michael Hanselmann
          val = _USER_JOB_STATUS[val]
91 7a1ecaed Iustin Pop
        else:
92 7a1ecaed Iustin Pop
          raise errors.ProgrammerError("Unknown job status code '%s'" % val)
93 60dd1473 Iustin Pop
      elif field == "summary":
94 60dd1473 Iustin Pop
        val = ",".join(val)
95 aad81f98 Iustin Pop
      elif field in ("start_ts", "end_ts", "received_ts"):
96 aad81f98 Iustin Pop
        val = FormatTimestamp(val)
97 aad81f98 Iustin Pop
      elif field in ("opstart", "opend"):
98 aad81f98 Iustin Pop
        val = [FormatTimestamp(entry) for entry in val]
99 7a1ecaed Iustin Pop
100 7a1ecaed Iustin Pop
      row[idx] = str(val)
101 7a1ecaed Iustin Pop
102 7a1ecaed Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
103 7a1ecaed Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
104 7a1ecaed Iustin Pop
                       numfields=numfields, data=output)
105 7a1ecaed Iustin Pop
  for line in data:
106 7a1ecaed Iustin Pop
    print line
107 7a1ecaed Iustin Pop
108 7a1ecaed Iustin Pop
  return 0
109 7a1ecaed Iustin Pop
110 7a1ecaed Iustin Pop
111 0ad64cf8 Michael Hanselmann
def ArchiveJobs(opts, args):
112 0ad64cf8 Michael Hanselmann
  client = GetClient()
113 0ad64cf8 Michael Hanselmann
114 0ad64cf8 Michael Hanselmann
  for job_id in args:
115 0ad64cf8 Michael Hanselmann
    client.ArchiveJob(job_id)
116 0ad64cf8 Michael Hanselmann
117 0ad64cf8 Michael Hanselmann
  return 0
118 0ad64cf8 Michael Hanselmann
119 0ad64cf8 Michael Hanselmann
120 07cd723a Iustin Pop
def AutoArchiveJobs(opts, args):
121 07cd723a Iustin Pop
  client = GetClient()
122 07cd723a Iustin Pop
123 07cd723a Iustin Pop
  age = args[0]
124 07cd723a Iustin Pop
125 07cd723a Iustin Pop
  if age == 'all':
126 07cd723a Iustin Pop
    age = -1
127 07cd723a Iustin Pop
  else:
128 07cd723a Iustin Pop
    age = ParseTimespec(age)
129 07cd723a Iustin Pop
130 07cd723a Iustin Pop
  client.AutoArchiveJobs(age)
131 07cd723a Iustin Pop
  return 0
132 07cd723a Iustin Pop
133 07cd723a Iustin Pop
134 d2b92ffc Michael Hanselmann
def CancelJobs(opts, args):
135 d2b92ffc Michael Hanselmann
  client = GetClient()
136 d2b92ffc Michael Hanselmann
137 d2b92ffc Michael Hanselmann
  for job_id in args:
138 d2b92ffc Michael Hanselmann
    client.CancelJob(job_id)
139 d2b92ffc Michael Hanselmann
140 d2b92ffc Michael Hanselmann
  return 0
141 d2b92ffc Michael Hanselmann
142 d2b92ffc Michael Hanselmann
143 191712c0 Iustin Pop
def ShowJobs(opts, args):
144 191712c0 Iustin Pop
  """List the jobs
145 191712c0 Iustin Pop
146 191712c0 Iustin Pop
  """
147 191712c0 Iustin Pop
  def format(level, text):
148 191712c0 Iustin Pop
    """Display the text indented."""
149 191712c0 Iustin Pop
    print "%s%s" % ("  " * level, text)
150 191712c0 Iustin Pop
151 191712c0 Iustin Pop
  def result_helper(value):
152 191712c0 Iustin Pop
    """Format a result field in a nice way."""
153 191712c0 Iustin Pop
    if isinstance(value, (tuple, list)):
154 191712c0 Iustin Pop
      return "[%s]" % (", ".join(str(elem) for elem in value))
155 191712c0 Iustin Pop
    else:
156 191712c0 Iustin Pop
      return str(value)
157 191712c0 Iustin Pop
158 aad81f98 Iustin Pop
  selected_fields = [
159 aad81f98 Iustin Pop
    "id", "status", "ops", "opresult", "opstatus", "oplog",
160 aad81f98 Iustin Pop
    "opstart", "opend", "received_ts", "start_ts", "end_ts",
161 aad81f98 Iustin Pop
    ]
162 191712c0 Iustin Pop
163 191712c0 Iustin Pop
  result = GetClient().QueryJobs(args, selected_fields)
164 191712c0 Iustin Pop
165 191712c0 Iustin Pop
  first = True
166 191712c0 Iustin Pop
167 b27b39b0 Iustin Pop
  for idx, entry in enumerate(result):
168 191712c0 Iustin Pop
    if not first:
169 191712c0 Iustin Pop
      format(0, "")
170 191712c0 Iustin Pop
    else:
171 191712c0 Iustin Pop
      first = False
172 aad81f98 Iustin Pop
173 aad81f98 Iustin Pop
    if entry is None:
174 b27b39b0 Iustin Pop
      if idx <= len(args):
175 b27b39b0 Iustin Pop
        format(0, "Job ID %s not found" % args[idx])
176 b27b39b0 Iustin Pop
      else:
177 b27b39b0 Iustin Pop
        # this should not happen, when we don't pass args it will be a
178 b27b39b0 Iustin Pop
        # valid job returned
179 b27b39b0 Iustin Pop
        format(0, "Job ID requested as argument %s not found" % (idx + 1))
180 aad81f98 Iustin Pop
      continue
181 aad81f98 Iustin Pop
182 aad81f98 Iustin Pop
    (job_id, status, ops, opresult, opstatus, oplog,
183 aad81f98 Iustin Pop
     opstart, opend, recv_ts, start_ts, end_ts) = entry
184 191712c0 Iustin Pop
    format(0, "Job ID: %s" % job_id)
185 191712c0 Iustin Pop
    if status in _USER_JOB_STATUS:
186 191712c0 Iustin Pop
      status = _USER_JOB_STATUS[status]
187 191712c0 Iustin Pop
    else:
188 191712c0 Iustin Pop
      raise errors.ProgrammerError("Unknown job status code '%s'" % val)
189 191712c0 Iustin Pop
190 191712c0 Iustin Pop
    format(1, "Status: %s" % status)
191 aad81f98 Iustin Pop
192 aad81f98 Iustin Pop
    if recv_ts is not None:
193 aad81f98 Iustin Pop
      format(1, "Received:         %s" % FormatTimestamp(recv_ts))
194 aad81f98 Iustin Pop
    else:
195 aad81f98 Iustin Pop
      format(1, "Missing received timestamp (%s)" % str(recv_ts))
196 aad81f98 Iustin Pop
197 aad81f98 Iustin Pop
    if start_ts is not None:
198 aad81f98 Iustin Pop
      if recv_ts is not None:
199 aad81f98 Iustin Pop
        d1 = start_ts[0] - recv_ts[0] + (start_ts[1] - recv_ts[1]) / 1000000.0
200 aad81f98 Iustin Pop
        delta = " (delta %.6fs)" % d1
201 aad81f98 Iustin Pop
      else:
202 aad81f98 Iustin Pop
        delta = ""
203 aad81f98 Iustin Pop
      format(1, "Processing start: %s%s" % (FormatTimestamp(start_ts), delta))
204 aad81f98 Iustin Pop
    else:
205 aad81f98 Iustin Pop
      format(1, "Processing start: unknown (%s)" % str(start_ts))
206 aad81f98 Iustin Pop
207 aad81f98 Iustin Pop
    if end_ts is not None:
208 aad81f98 Iustin Pop
      if start_ts is not None:
209 aad81f98 Iustin Pop
        d2 = end_ts[0] - start_ts[0] + (end_ts[1] - start_ts[1]) / 1000000.0
210 aad81f98 Iustin Pop
        delta = " (delta %.6fs)" % d2
211 aad81f98 Iustin Pop
      else:
212 aad81f98 Iustin Pop
        delta = ""
213 aad81f98 Iustin Pop
      format(1, "Processing end:   %s%s" % (FormatTimestamp(end_ts), delta))
214 aad81f98 Iustin Pop
    else:
215 aad81f98 Iustin Pop
      format(1, "Processing end:   unknown (%s)" % str(end_ts))
216 aad81f98 Iustin Pop
217 aad81f98 Iustin Pop
    if end_ts is not None and recv_ts is not None:
218 aad81f98 Iustin Pop
      d3 = end_ts[0] - recv_ts[0] + (end_ts[1] - recv_ts[1]) / 1000000.0
219 aad81f98 Iustin Pop
      format(1, "Total processing time: %.6f seconds" % d3)
220 aad81f98 Iustin Pop
    else:
221 aad81f98 Iustin Pop
      format(1, "Total processing time: N/A")
222 191712c0 Iustin Pop
    format(1, "Opcodes:")
223 aad81f98 Iustin Pop
    for (opcode, result, status, log, s_ts, e_ts) in \
224 aad81f98 Iustin Pop
            zip(ops, opresult, opstatus, oplog, opstart, opend):
225 191712c0 Iustin Pop
      format(2, "%s" % opcode["OP_ID"])
226 191712c0 Iustin Pop
      format(3, "Status: %s" % status)
227 aad81f98 Iustin Pop
      if isinstance(s_ts, (tuple, list)):
228 aad81f98 Iustin Pop
        format(3, "Processing start: %s" % FormatTimestamp(s_ts))
229 aad81f98 Iustin Pop
      else:
230 aad81f98 Iustin Pop
        format(3, "No processing start time")
231 aad81f98 Iustin Pop
      if isinstance(e_ts, (tuple, list)):
232 aad81f98 Iustin Pop
        format(3, "Processing end:   %s" % FormatTimestamp(e_ts))
233 aad81f98 Iustin Pop
      else:
234 aad81f98 Iustin Pop
        format(3, "No processing end time")
235 191712c0 Iustin Pop
      format(3, "Input fields:")
236 191712c0 Iustin Pop
      for key, val in opcode.iteritems():
237 191712c0 Iustin Pop
        if key == "OP_ID":
238 191712c0 Iustin Pop
          continue
239 191712c0 Iustin Pop
        if isinstance(val, (tuple, list)):
240 191712c0 Iustin Pop
          val = ",".join(val)
241 191712c0 Iustin Pop
        format(4, "%s: %s" % (key, val))
242 191712c0 Iustin Pop
      if result is None:
243 191712c0 Iustin Pop
        format(3, "No output data")
244 191712c0 Iustin Pop
      elif isinstance(result, (tuple, list)):
245 191712c0 Iustin Pop
        if not result:
246 191712c0 Iustin Pop
          format(3, "Result: empty sequence")
247 191712c0 Iustin Pop
        else:
248 191712c0 Iustin Pop
          format(3, "Result:")
249 191712c0 Iustin Pop
          for elem in result:
250 191712c0 Iustin Pop
            format(4, result_helper(elem))
251 191712c0 Iustin Pop
      elif isinstance(result, dict):
252 191712c0 Iustin Pop
        if not result:
253 191712c0 Iustin Pop
          format(3, "Result: empty dictionary")
254 191712c0 Iustin Pop
        else:
255 191712c0 Iustin Pop
          for key, val in result.iteritems():
256 191712c0 Iustin Pop
            format(4, "%s: %s" % (key, result_helper(val)))
257 191712c0 Iustin Pop
      else:
258 191712c0 Iustin Pop
        format(3, "Result: %s" % result)
259 5b23c34c Iustin Pop
      format(3, "Execution log:")
260 3386e7a9 Iustin Pop
      for serial, log_ts, log_type, log_msg in log:
261 3386e7a9 Iustin Pop
        time_txt = FormatTimestamp(log_ts)
262 5b23c34c Iustin Pop
        encoded = str(log_msg).encode('string_escape')
263 5b23c34c Iustin Pop
        format(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded))
264 191712c0 Iustin Pop
  return 0
265 191712c0 Iustin Pop
266 191712c0 Iustin Pop
267 7a1ecaed Iustin Pop
commands = {
268 7a1ecaed Iustin Pop
  'list': (ListJobs, ARGS_NONE,
269 9a033156 Iustin Pop
            [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
270 9a033156 Iustin Pop
            "", "List the jobs and their status. The available fields are"
271 35049ff2 Iustin Pop
           " (see the man page for details): id, status, op_list,"
272 35049ff2 Iustin Pop
           " op_status, op_result."
273 7a1ecaed Iustin Pop
           " The default field"
274 0ad64cf8 Michael Hanselmann
           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS)),
275 0ad64cf8 Michael Hanselmann
  'archive': (ArchiveJobs, ARGS_ANY,
276 0ad64cf8 Michael Hanselmann
              [DEBUG_OPT],
277 0ad64cf8 Michael Hanselmann
              "<job-id> [<job-id> ...]",
278 0ad64cf8 Michael Hanselmann
              "Archive specified jobs"),
279 07cd723a Iustin Pop
  'autoarchive': (AutoArchiveJobs, ARGS_ONE,
280 07cd723a Iustin Pop
              [DEBUG_OPT],
281 07cd723a Iustin Pop
              "<age>",
282 07cd723a Iustin Pop
              "Auto archive jobs older than the given age"),
283 d2b92ffc Michael Hanselmann
  'cancel': (CancelJobs, ARGS_ANY,
284 d2b92ffc Michael Hanselmann
             [DEBUG_OPT],
285 d2b92ffc Michael Hanselmann
             "<job-id> [<job-id> ...]",
286 d2b92ffc Michael Hanselmann
             "Cancel specified jobs"),
287 191712c0 Iustin Pop
  'info': (ShowJobs, ARGS_ANY, [DEBUG_OPT],
288 191712c0 Iustin Pop
           "<job-id> [<job-id> ...]",
289 191712c0 Iustin Pop
           "Show detailed information about the specified jobs"),
290 7a1ecaed Iustin Pop
  }
291 7a1ecaed Iustin Pop
292 7a1ecaed Iustin Pop
293 7a1ecaed Iustin Pop
if __name__ == '__main__':
294 7a1ecaed Iustin Pop
  sys.exit(GenericMain(commands))