Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-job @ aad81f98

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