root / lib / client / gnt_job.py @ 25bd815c
History | View | Annotate | Download (11.2 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 | 2d54e29c | Iustin Pop | # pylint: disable-msg=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 | 7a1ecaed | Iustin Pop | |
35 | 7a1ecaed | Iustin Pop | |
36 | 917b4e56 | Iustin Pop | #: default list of fields for L{ListJobs}
|
37 | 60dd1473 | Iustin Pop | _LIST_DEF_FIELDS = ["id", "status", "summary"] |
38 | 7a5d3bbd | Iustin Pop | |
39 | 917b4e56 | Iustin Pop | #: map converting the job status contants to user-visible
|
40 | 917b4e56 | Iustin Pop | #: names
|
41 | af30b2fd | Michael Hanselmann | _USER_JOB_STATUS = { |
42 | af30b2fd | Michael Hanselmann | constants.JOB_STATUS_QUEUED: "queued",
|
43 | e92376d7 | Iustin Pop | constants.JOB_STATUS_WAITLOCK: "waiting",
|
44 | fbf0262f | Michael Hanselmann | constants.JOB_STATUS_CANCELING: "canceling",
|
45 | af30b2fd | Michael Hanselmann | constants.JOB_STATUS_RUNNING: "running",
|
46 | af30b2fd | Michael Hanselmann | constants.JOB_STATUS_CANCELED: "canceled",
|
47 | af30b2fd | Michael Hanselmann | constants.JOB_STATUS_SUCCESS: "success",
|
48 | af30b2fd | Michael Hanselmann | constants.JOB_STATUS_ERROR: "error",
|
49 | af30b2fd | Michael Hanselmann | } |
50 | af30b2fd | Michael Hanselmann | |
51 | 0ad64cf8 | Michael Hanselmann | |
52 | 7a1ecaed | Iustin Pop | def ListJobs(opts, args): |
53 | 7a1ecaed | Iustin Pop | """List the jobs
|
54 | 7a1ecaed | Iustin Pop |
|
55 | 917b4e56 | Iustin Pop | @param opts: the command line options selected by the user
|
56 | 917b4e56 | Iustin Pop | @type args: list
|
57 | 917b4e56 | Iustin Pop | @param args: should be an empty list
|
58 | 917b4e56 | Iustin Pop | @rtype: int
|
59 | 917b4e56 | Iustin Pop | @return: the desired exit code
|
60 | 917b4e56 | Iustin Pop |
|
61 | 7a1ecaed | Iustin Pop | """
|
62 | a4ebd726 | Michael Hanselmann | selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS) |
63 | 7a1ecaed | Iustin Pop | |
64 | f1de3563 | Iustin Pop | output = GetClient().QueryJobs(args, selected_fields) |
65 | 7a1ecaed | Iustin Pop | if not opts.no_headers: |
66 | af30b2fd | Michael Hanselmann | # TODO: Implement more fields
|
67 | 7a1ecaed | Iustin Pop | headers = { |
68 | 7a1ecaed | Iustin Pop | "id": "ID", |
69 | 7a1ecaed | Iustin Pop | "status": "Status", |
70 | b8802cc4 | Michael Hanselmann | "priority": "Prio", |
71 | af30b2fd | Michael Hanselmann | "ops": "OpCodes", |
72 | af30b2fd | Michael Hanselmann | "opresult": "OpCode_result", |
73 | af30b2fd | Michael Hanselmann | "opstatus": "OpCode_status", |
74 | 5b23c34c | Iustin Pop | "oplog": "OpCode_log", |
75 | 60dd1473 | Iustin Pop | "summary": "Summary", |
76 | aad81f98 | Iustin Pop | "opstart": "OpCode_start", |
77 | b9b5abcb | Iustin Pop | "opexec": "OpCode_exec", |
78 | aad81f98 | Iustin Pop | "opend": "OpCode_end", |
79 | b8802cc4 | Michael Hanselmann | "oppriority": "OpCode_prio", |
80 | aad81f98 | Iustin Pop | "start_ts": "Start", |
81 | aad81f98 | Iustin Pop | "end_ts": "End", |
82 | aad81f98 | Iustin Pop | "received_ts": "Received", |
83 | 7a1ecaed | Iustin Pop | } |
84 | 7a1ecaed | Iustin Pop | else:
|
85 | 7a1ecaed | Iustin Pop | headers = None
|
86 | 7a1ecaed | Iustin Pop | |
87 | b8802cc4 | Michael Hanselmann | numfields = ["priority"]
|
88 | b8802cc4 | Michael Hanselmann | |
89 | 7a1ecaed | Iustin Pop | # change raw values to nicer strings
|
90 | dcbd6288 | Guido Trotter | for row_id, row in enumerate(output): |
91 | dcbd6288 | Guido Trotter | if row is None: |
92 | dcbd6288 | Guido Trotter | ToStderr("No such job: %s" % args[row_id])
|
93 | dcbd6288 | Guido Trotter | continue
|
94 | dcbd6288 | Guido Trotter | |
95 | 7a1ecaed | Iustin Pop | for idx, field in enumerate(selected_fields): |
96 | 7a1ecaed | Iustin Pop | val = row[idx] |
97 | 7a1ecaed | Iustin Pop | if field == "status": |
98 | af30b2fd | Michael Hanselmann | if val in _USER_JOB_STATUS: |
99 | af30b2fd | Michael Hanselmann | val = _USER_JOB_STATUS[val] |
100 | 7a1ecaed | Iustin Pop | else:
|
101 | 7a1ecaed | Iustin Pop | raise errors.ProgrammerError("Unknown job status code '%s'" % val) |
102 | 60dd1473 | Iustin Pop | elif field == "summary": |
103 | 60dd1473 | Iustin Pop | val = ",".join(val)
|
104 | aad81f98 | Iustin Pop | elif field in ("start_ts", "end_ts", "received_ts"): |
105 | aad81f98 | Iustin Pop | val = FormatTimestamp(val) |
106 | b9b5abcb | Iustin Pop | elif field in ("opstart", "opexec", "opend"): |
107 | aad81f98 | Iustin Pop | val = [FormatTimestamp(entry) for entry in val] |
108 | 7a1ecaed | Iustin Pop | |
109 | 7a1ecaed | Iustin Pop | row[idx] = str(val)
|
110 | 7a1ecaed | Iustin Pop | |
111 | 7a1ecaed | Iustin Pop | data = GenerateTable(separator=opts.separator, headers=headers, |
112 | b8802cc4 | Michael Hanselmann | fields=selected_fields, data=output, |
113 | b8802cc4 | Michael Hanselmann | numfields=numfields) |
114 | 7a1ecaed | Iustin Pop | for line in data: |
115 | 3a24c527 | Iustin Pop | ToStdout(line) |
116 | 7a1ecaed | Iustin Pop | |
117 | 7a1ecaed | Iustin Pop | return 0 |
118 | 7a1ecaed | Iustin Pop | |
119 | 7a1ecaed | Iustin Pop | |
120 | 0ad64cf8 | Michael Hanselmann | def ArchiveJobs(opts, args): |
121 | 917b4e56 | Iustin Pop | """Archive jobs.
|
122 | 917b4e56 | Iustin Pop |
|
123 | 917b4e56 | Iustin Pop | @param opts: the command line options selected by the user
|
124 | 917b4e56 | Iustin Pop | @type args: list
|
125 | 917b4e56 | Iustin Pop | @param args: should contain the job IDs to be archived
|
126 | 917b4e56 | Iustin Pop | @rtype: int
|
127 | 917b4e56 | Iustin Pop | @return: the desired exit code
|
128 | 917b4e56 | Iustin Pop |
|
129 | 917b4e56 | Iustin Pop | """
|
130 | 0ad64cf8 | Michael Hanselmann | client = GetClient() |
131 | 0ad64cf8 | Michael Hanselmann | |
132 | aa9f8167 | Iustin Pop | rcode = 0
|
133 | 0ad64cf8 | Michael Hanselmann | for job_id in args: |
134 | aa9f8167 | Iustin Pop | if not client.ArchiveJob(job_id): |
135 | aa9f8167 | Iustin Pop | ToStderr("Failed to archive job with ID '%s'", job_id)
|
136 | aa9f8167 | Iustin Pop | rcode = 1
|
137 | 0ad64cf8 | Michael Hanselmann | |
138 | aa9f8167 | Iustin Pop | return rcode
|
139 | 0ad64cf8 | Michael Hanselmann | |
140 | 0ad64cf8 | Michael Hanselmann | |
141 | 07cd723a | Iustin Pop | def AutoArchiveJobs(opts, args): |
142 | 917b4e56 | Iustin Pop | """Archive jobs based on age.
|
143 | 917b4e56 | Iustin Pop |
|
144 | 917b4e56 | Iustin Pop | This will archive jobs based on their age, or all jobs if a 'all' is
|
145 | 917b4e56 | Iustin Pop | passed.
|
146 | 917b4e56 | Iustin Pop |
|
147 | 917b4e56 | Iustin Pop | @param opts: the command line options selected by the user
|
148 | 917b4e56 | Iustin Pop | @type args: list
|
149 | 917b4e56 | Iustin Pop | @param args: should contain only one element, the age as a time spec
|
150 | c41eea6e | Iustin Pop | that can be parsed by L{ganeti.cli.ParseTimespec} or the
|
151 | c41eea6e | Iustin Pop | keyword I{all}, which will cause all jobs to be archived
|
152 | 917b4e56 | Iustin Pop | @rtype: int
|
153 | 917b4e56 | Iustin Pop | @return: the desired exit code
|
154 | 917b4e56 | Iustin Pop |
|
155 | 917b4e56 | Iustin Pop | """
|
156 | 07cd723a | Iustin Pop | client = GetClient() |
157 | 07cd723a | Iustin Pop | |
158 | 07cd723a | Iustin Pop | age = args[0]
|
159 | 07cd723a | Iustin Pop | |
160 | 07cd723a | Iustin Pop | if age == 'all': |
161 | 07cd723a | Iustin Pop | age = -1
|
162 | 07cd723a | Iustin Pop | else:
|
163 | 07cd723a | Iustin Pop | age = ParseTimespec(age) |
164 | 07cd723a | Iustin Pop | |
165 | f8ad5591 | Michael Hanselmann | (archived_count, jobs_left) = client.AutoArchiveJobs(age) |
166 | f8ad5591 | Michael Hanselmann | ToStdout("Archived %s jobs, %s unchecked left", archived_count, jobs_left)
|
167 | f8ad5591 | Michael Hanselmann | |
168 | 07cd723a | Iustin Pop | return 0 |
169 | 07cd723a | Iustin Pop | |
170 | 07cd723a | Iustin Pop | |
171 | d2b92ffc | Michael Hanselmann | def CancelJobs(opts, args): |
172 | 917b4e56 | Iustin Pop | """Cancel not-yet-started jobs.
|
173 | 917b4e56 | Iustin Pop |
|
174 | 917b4e56 | Iustin Pop | @param opts: the command line options selected by the user
|
175 | 917b4e56 | Iustin Pop | @type args: list
|
176 | 917b4e56 | Iustin Pop | @param args: should contain the job IDs to be cancelled
|
177 | 917b4e56 | Iustin Pop | @rtype: int
|
178 | 917b4e56 | Iustin Pop | @return: the desired exit code
|
179 | 917b4e56 | Iustin Pop |
|
180 | 917b4e56 | Iustin Pop | """
|
181 | d2b92ffc | Michael Hanselmann | client = GetClient() |
182 | 06fef5e0 | Michael Hanselmann | result = constants.EXIT_SUCCESS |
183 | d2b92ffc | Michael Hanselmann | |
184 | d2b92ffc | Michael Hanselmann | for job_id in args: |
185 | 06fef5e0 | Michael Hanselmann | (success, msg) = client.CancelJob(job_id) |
186 | 06fef5e0 | Michael Hanselmann | |
187 | 06fef5e0 | Michael Hanselmann | if not success: |
188 | 06fef5e0 | Michael Hanselmann | result = constants.EXIT_FAILURE |
189 | 06fef5e0 | Michael Hanselmann | |
190 | b28a3e8b | Michael Hanselmann | ToStdout(msg) |
191 | d2b92ffc | Michael Hanselmann | |
192 | 06fef5e0 | Michael Hanselmann | return result
|
193 | d2b92ffc | Michael Hanselmann | |
194 | d2b92ffc | Michael Hanselmann | |
195 | 191712c0 | Iustin Pop | def ShowJobs(opts, args): |
196 | 917b4e56 | Iustin Pop | """Show detailed information about jobs.
|
197 | 917b4e56 | Iustin Pop |
|
198 | 917b4e56 | Iustin Pop | @param opts: the command line options selected by the user
|
199 | 917b4e56 | Iustin Pop | @type args: list
|
200 | 917b4e56 | Iustin Pop | @param args: should contain the job IDs to be queried
|
201 | 917b4e56 | Iustin Pop | @rtype: int
|
202 | 917b4e56 | Iustin Pop | @return: the desired exit code
|
203 | 191712c0 | Iustin Pop |
|
204 | 191712c0 | Iustin Pop | """
|
205 | c04bc777 | Iustin Pop | def format_msg(level, text): |
206 | 191712c0 | Iustin Pop | """Display the text indented."""
|
207 | 3a24c527 | Iustin Pop | ToStdout("%s%s", " " * level, text) |
208 | 191712c0 | Iustin Pop | |
209 | 191712c0 | Iustin Pop | def result_helper(value): |
210 | 191712c0 | Iustin Pop | """Format a result field in a nice way."""
|
211 | 191712c0 | Iustin Pop | if isinstance(value, (tuple, list)): |
212 | 1f864b60 | Iustin Pop | return "[%s]" % utils.CommaJoin(value) |
213 | 191712c0 | Iustin Pop | else:
|
214 | 191712c0 | Iustin Pop | return str(value) |
215 | 191712c0 | Iustin Pop | |
216 | aad81f98 | Iustin Pop | selected_fields = [ |
217 | aad81f98 | Iustin Pop | "id", "status", "ops", "opresult", "opstatus", "oplog", |
218 | b9b5abcb | Iustin Pop | "opstart", "opexec", "opend", "received_ts", "start_ts", "end_ts", |
219 | aad81f98 | Iustin Pop | ] |
220 | 191712c0 | Iustin Pop | |
221 | 191712c0 | Iustin Pop | result = GetClient().QueryJobs(args, selected_fields) |
222 | 191712c0 | Iustin Pop | |
223 | 191712c0 | Iustin Pop | first = True
|
224 | 191712c0 | Iustin Pop | |
225 | b27b39b0 | Iustin Pop | for idx, entry in enumerate(result): |
226 | 191712c0 | Iustin Pop | if not first: |
227 | c04bc777 | Iustin Pop | format_msg(0, "") |
228 | 191712c0 | Iustin Pop | else:
|
229 | 191712c0 | Iustin Pop | first = False
|
230 | aad81f98 | Iustin Pop | |
231 | aad81f98 | Iustin Pop | if entry is None: |
232 | b27b39b0 | Iustin Pop | if idx <= len(args): |
233 | c04bc777 | Iustin Pop | format_msg(0, "Job ID %s not found" % args[idx]) |
234 | b27b39b0 | Iustin Pop | else:
|
235 | b27b39b0 | Iustin Pop | # this should not happen, when we don't pass args it will be a
|
236 | b27b39b0 | Iustin Pop | # valid job returned
|
237 | c04bc777 | Iustin Pop | format_msg(0, "Job ID requested as argument %s not found" % (idx + 1)) |
238 | aad81f98 | Iustin Pop | continue
|
239 | aad81f98 | Iustin Pop | |
240 | aad81f98 | Iustin Pop | (job_id, status, ops, opresult, opstatus, oplog, |
241 | b9b5abcb | Iustin Pop | opstart, opexec, opend, recv_ts, start_ts, end_ts) = entry |
242 | c04bc777 | Iustin Pop | format_msg(0, "Job ID: %s" % job_id) |
243 | 191712c0 | Iustin Pop | if status in _USER_JOB_STATUS: |
244 | 191712c0 | Iustin Pop | status = _USER_JOB_STATUS[status] |
245 | 191712c0 | Iustin Pop | else:
|
246 | 2f79bd34 | Iustin Pop | raise errors.ProgrammerError("Unknown job status code '%s'" % status) |
247 | 191712c0 | Iustin Pop | |
248 | c04bc777 | Iustin Pop | format_msg(1, "Status: %s" % status) |
249 | aad81f98 | Iustin Pop | |
250 | aad81f98 | Iustin Pop | if recv_ts is not None: |
251 | c04bc777 | Iustin Pop | format_msg(1, "Received: %s" % FormatTimestamp(recv_ts)) |
252 | aad81f98 | Iustin Pop | else:
|
253 | c04bc777 | Iustin Pop | format_msg(1, "Missing received timestamp (%s)" % str(recv_ts)) |
254 | aad81f98 | Iustin Pop | |
255 | aad81f98 | Iustin Pop | if start_ts is not None: |
256 | aad81f98 | Iustin Pop | if recv_ts is not None: |
257 | aad81f98 | Iustin Pop | d1 = start_ts[0] - recv_ts[0] + (start_ts[1] - recv_ts[1]) / 1000000.0 |
258 | aad81f98 | Iustin Pop | delta = " (delta %.6fs)" % d1
|
259 | aad81f98 | Iustin Pop | else:
|
260 | aad81f98 | Iustin Pop | delta = ""
|
261 | c04bc777 | Iustin Pop | format_msg(1, "Processing start: %s%s" % |
262 | c04bc777 | Iustin Pop | (FormatTimestamp(start_ts), delta)) |
263 | aad81f98 | Iustin Pop | else:
|
264 | c04bc777 | Iustin Pop | format_msg(1, "Processing start: unknown (%s)" % str(start_ts)) |
265 | aad81f98 | Iustin Pop | |
266 | aad81f98 | Iustin Pop | if end_ts is not None: |
267 | aad81f98 | Iustin Pop | if start_ts is not None: |
268 | aad81f98 | Iustin Pop | d2 = end_ts[0] - start_ts[0] + (end_ts[1] - start_ts[1]) / 1000000.0 |
269 | aad81f98 | Iustin Pop | delta = " (delta %.6fs)" % d2
|
270 | aad81f98 | Iustin Pop | else:
|
271 | aad81f98 | Iustin Pop | delta = ""
|
272 | c04bc777 | Iustin Pop | format_msg(1, "Processing end: %s%s" % |
273 | c04bc777 | Iustin Pop | (FormatTimestamp(end_ts), delta)) |
274 | aad81f98 | Iustin Pop | else:
|
275 | c04bc777 | Iustin Pop | format_msg(1, "Processing end: unknown (%s)" % str(end_ts)) |
276 | aad81f98 | Iustin Pop | |
277 | aad81f98 | Iustin Pop | if end_ts is not None and recv_ts is not None: |
278 | aad81f98 | Iustin Pop | d3 = end_ts[0] - recv_ts[0] + (end_ts[1] - recv_ts[1]) / 1000000.0 |
279 | c04bc777 | Iustin Pop | format_msg(1, "Total processing time: %.6f seconds" % d3) |
280 | aad81f98 | Iustin Pop | else:
|
281 | c04bc777 | Iustin Pop | format_msg(1, "Total processing time: N/A") |
282 | c04bc777 | Iustin Pop | format_msg(1, "Opcodes:") |
283 | b9b5abcb | Iustin Pop | for (opcode, result, status, log, s_ts, x_ts, e_ts) in \ |
284 | b9b5abcb | Iustin Pop | zip(ops, opresult, opstatus, oplog, opstart, opexec, opend):
|
285 | c04bc777 | Iustin Pop | format_msg(2, "%s" % opcode["OP_ID"]) |
286 | c04bc777 | Iustin Pop | format_msg(3, "Status: %s" % status) |
287 | aad81f98 | Iustin Pop | if isinstance(s_ts, (tuple, list)): |
288 | c04bc777 | Iustin Pop | format_msg(3, "Processing start: %s" % FormatTimestamp(s_ts)) |
289 | aad81f98 | Iustin Pop | else:
|
290 | c04bc777 | Iustin Pop | format_msg(3, "No processing start time") |
291 | b9b5abcb | Iustin Pop | if isinstance(x_ts, (tuple, list)): |
292 | c04bc777 | Iustin Pop | format_msg(3, "Execution start: %s" % FormatTimestamp(x_ts)) |
293 | b9b5abcb | Iustin Pop | else:
|
294 | c04bc777 | Iustin Pop | format_msg(3, "No execution start time") |
295 | aad81f98 | Iustin Pop | if isinstance(e_ts, (tuple, list)): |
296 | c04bc777 | Iustin Pop | format_msg(3, "Processing end: %s" % FormatTimestamp(e_ts)) |
297 | aad81f98 | Iustin Pop | else:
|
298 | c04bc777 | Iustin Pop | format_msg(3, "No processing end time") |
299 | c04bc777 | Iustin Pop | format_msg(3, "Input fields:") |
300 | 598b5255 | Michael Hanselmann | for key in utils.NiceSort(opcode.keys()): |
301 | 191712c0 | Iustin Pop | if key == "OP_ID": |
302 | 191712c0 | Iustin Pop | continue
|
303 | 598b5255 | Michael Hanselmann | val = opcode[key] |
304 | 191712c0 | Iustin Pop | if isinstance(val, (tuple, list)): |
305 | 08db7c5c | Iustin Pop | val = ",".join([str(item) for item in val]) |
306 | c04bc777 | Iustin Pop | format_msg(4, "%s: %s" % (key, val)) |
307 | 191712c0 | Iustin Pop | if result is None: |
308 | c04bc777 | Iustin Pop | format_msg(3, "No output data") |
309 | 191712c0 | Iustin Pop | elif isinstance(result, (tuple, list)): |
310 | 191712c0 | Iustin Pop | if not result: |
311 | c04bc777 | Iustin Pop | format_msg(3, "Result: empty sequence") |
312 | 191712c0 | Iustin Pop | else:
|
313 | c04bc777 | Iustin Pop | format_msg(3, "Result:") |
314 | 191712c0 | Iustin Pop | for elem in result: |
315 | c04bc777 | Iustin Pop | format_msg(4, result_helper(elem))
|
316 | 191712c0 | Iustin Pop | elif isinstance(result, dict): |
317 | 191712c0 | Iustin Pop | if not result: |
318 | c04bc777 | Iustin Pop | format_msg(3, "Result: empty dictionary") |
319 | 191712c0 | Iustin Pop | else:
|
320 | 191712c0 | Iustin Pop | for key, val in result.iteritems(): |
321 | c04bc777 | Iustin Pop | format_msg(4, "%s: %s" % (key, result_helper(val))) |
322 | 191712c0 | Iustin Pop | else:
|
323 | c04bc777 | Iustin Pop | format_msg(3, "Result: %s" % result) |
324 | c04bc777 | Iustin Pop | format_msg(3, "Execution log:") |
325 | 3386e7a9 | Iustin Pop | for serial, log_ts, log_type, log_msg in log: |
326 | 3386e7a9 | Iustin Pop | time_txt = FormatTimestamp(log_ts) |
327 | 8a7f1c61 | Michael Hanselmann | encoded = FormatLogMessage(log_type, log_msg) |
328 | c04bc777 | Iustin Pop | format_msg(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded)) |
329 | 191712c0 | Iustin Pop | return 0 |
330 | 191712c0 | Iustin Pop | |
331 | 191712c0 | Iustin Pop | |
332 | e7d6946c | Michael Hanselmann | def WatchJob(opts, args): |
333 | e7d6946c | Michael Hanselmann | """Follow a job and print its output as it arrives.
|
334 | e7d6946c | Michael Hanselmann |
|
335 | e7d6946c | Michael Hanselmann | @param opts: the command line options selected by the user
|
336 | e7d6946c | Michael Hanselmann | @type args: list
|
337 | e7d6946c | Michael Hanselmann | @param args: Contains the job ID
|
338 | e7d6946c | Michael Hanselmann | @rtype: int
|
339 | e7d6946c | Michael Hanselmann | @return: the desired exit code
|
340 | e7d6946c | Michael Hanselmann |
|
341 | e7d6946c | Michael Hanselmann | """
|
342 | e7d6946c | Michael Hanselmann | job_id = args[0]
|
343 | e7d6946c | Michael Hanselmann | |
344 | e7d6946c | Michael Hanselmann | msg = ("Output from job %s follows" % job_id)
|
345 | e7d6946c | Michael Hanselmann | ToStdout(msg) |
346 | e7d6946c | Michael Hanselmann | ToStdout("-" * len(msg)) |
347 | e7d6946c | Michael Hanselmann | |
348 | e7d6946c | Michael Hanselmann | retcode = 0
|
349 | e7d6946c | Michael Hanselmann | try:
|
350 | e7d6946c | Michael Hanselmann | cli.PollJob(job_id) |
351 | e7d6946c | Michael Hanselmann | except errors.GenericError, err:
|
352 | e7d6946c | Michael Hanselmann | (retcode, job_result) = cli.FormatError(err) |
353 | e7d6946c | Michael Hanselmann | ToStderr("Job %s failed: %s", job_id, job_result)
|
354 | e7d6946c | Michael Hanselmann | |
355 | e7d6946c | Michael Hanselmann | return retcode
|
356 | e7d6946c | Michael Hanselmann | |
357 | e7d6946c | Michael Hanselmann | |
358 | 7a1ecaed | Iustin Pop | commands = { |
359 | 6ea815cf | Iustin Pop | 'list': (
|
360 | 6ea815cf | Iustin Pop | ListJobs, [ArgJobId()], |
361 | 064c21f8 | Iustin Pop | [NOHDR_OPT, SEP_OPT, FIELDS_OPT], |
362 | 6ea815cf | Iustin Pop | "[job_id ...]",
|
363 | 6ea815cf | Iustin Pop | "List the jobs and their status. The available fields are"
|
364 | 6ea815cf | Iustin Pop | " (see the man page for details): id, status, op_list,"
|
365 | 6ea815cf | Iustin Pop | " op_status, op_result."
|
366 | 6ea815cf | Iustin Pop | " The default field"
|
367 | 1f864b60 | Iustin Pop | " list is (in order): %s." % utils.CommaJoin(_LIST_DEF_FIELDS)),
|
368 | 6ea815cf | Iustin Pop | 'archive': (
|
369 | 064c21f8 | Iustin Pop | ArchiveJobs, [ArgJobId(min=1)], [],
|
370 | 6ea815cf | Iustin Pop | "<job-id> [<job-id> ...]", "Archive specified jobs"), |
371 | 6ea815cf | Iustin Pop | 'autoarchive': (
|
372 | 6ea815cf | Iustin Pop | AutoArchiveJobs, |
373 | 94182b63 | Iustin Pop | [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w", "all"])], |
374 | 064c21f8 | Iustin Pop | [], |
375 | 6ea815cf | Iustin Pop | "<age>", "Auto archive jobs older than the given age"), |
376 | 6ea815cf | Iustin Pop | 'cancel': (
|
377 | 064c21f8 | Iustin Pop | CancelJobs, [ArgJobId(min=1)], [],
|
378 | 6ea815cf | Iustin Pop | "<job-id> [<job-id> ...]", "Cancel specified jobs"), |
379 | 6ea815cf | Iustin Pop | 'info': (
|
380 | 064c21f8 | Iustin Pop | ShowJobs, [ArgJobId(min=1)], [],
|
381 | 6ea815cf | Iustin Pop | "<job-id> [<job-id> ...]",
|
382 | 6ea815cf | Iustin Pop | "Show detailed information about the specified jobs"),
|
383 | 6ea815cf | Iustin Pop | 'watch': (
|
384 | 064c21f8 | Iustin Pop | WatchJob, [ArgJobId(min=1, max=1)], [], |
385 | 6ea815cf | Iustin Pop | "<job-id>", "Follows a job and prints its output as it arrives"), |
386 | 7a1ecaed | Iustin Pop | } |
387 | 7a1ecaed | Iustin Pop | |
388 | 7a1ecaed | Iustin Pop | |
389 | a09b9e3d | Michael Hanselmann | def Main(): |
390 | a09b9e3d | Michael Hanselmann | return GenericMain(commands) |