from ganeti import constants
from ganeti import errors
from ganeti import utils
+from ganeti import cli
#: default list of fields for L{ListJobs}
else:
selected_fields = opts.output.split(",")
- output = GetClient().QueryJobs(None, selected_fields)
+ output = GetClient().QueryJobs(args, selected_fields)
if not opts.no_headers:
# TODO: Implement more fields
headers = {
"start_ts": "Start",
"end_ts": "End",
"received_ts": "Received",
+ "lock_status": "LockStatus",
}
else:
headers = None
- # we don't have yet unitfields here
- unitfields = None
- numfields = None
-
# change raw values to nicer strings
- for row in output:
+ for row_id, row in enumerate(output):
+ if row is None:
+ ToStderr("No such job: %s" % args[row_id])
+ continue
+
for idx, field in enumerate(selected_fields):
val = row[idx]
if field == "status":
val = FormatTimestamp(val)
elif field in ("opstart", "opend"):
val = [FormatTimestamp(entry) for entry in val]
+ elif field == "lock_status" and not val:
+ val = "-"
row[idx] = str(val)
data = GenerateTable(separator=opts.separator, headers=headers,
- fields=selected_fields, unitfields=unitfields,
- numfields=numfields, data=output, units=opts.units)
+ fields=selected_fields, data=output)
for line in data:
ToStdout(line)
return 0
+def WatchJob(opts, args):
+ """Follow a job and print its output as it arrives.
+
+ @param opts: the command line options selected by the user
+ @type args: list
+ @param args: Contains the job ID
+ @rtype: int
+ @return: the desired exit code
+
+ """
+ job_id = args[0]
+
+ msg = ("Output from job %s follows" % job_id)
+ ToStdout(msg)
+ ToStdout("-" * len(msg))
+
+ retcode = 0
+ try:
+ cli.PollJob(job_id)
+ except errors.GenericError, err:
+ (retcode, job_result) = cli.FormatError(err)
+ ToStderr("Job %s failed: %s", job_id, job_result)
+
+ return retcode
+
+
commands = {
- 'list': (ListJobs, ARGS_NONE,
- [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
- "", "List the jobs and their status. The available fields are"
+ 'list': (ListJobs, [ArgJobId()],
+ [DEBUG_OPT, NOHDR_OPT, SEP_OPT, FIELDS_OPT],
+ "[job_id ...]",
+ "List the jobs and their status. The available fields are"
" (see the man page for details): id, status, op_list,"
" op_status, op_result."
" The default field"
" list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS)),
- 'archive': (ArchiveJobs, ARGS_ANY,
- [DEBUG_OPT],
+ 'archive': (ArchiveJobs, [ArgJobId(min=1)], [DEBUG_OPT],
"<job-id> [<job-id> ...]",
"Archive specified jobs"),
- 'autoarchive': (AutoArchiveJobs, ARGS_ONE,
- [DEBUG_OPT],
- "<age>",
- "Auto archive jobs older than the given age"),
- 'cancel': (CancelJobs, ARGS_ANY,
- [DEBUG_OPT],
+ 'autoarchive': (AutoArchiveJobs,
+ [ArgSuggest(min=1, max=1, choices=["1d", "1w", "4w"])],
+ [DEBUG_OPT],
+ "<age>",
+ "Auto archive jobs older than the given age"),
+ 'cancel': (CancelJobs, [ArgJobId(min=1)], [DEBUG_OPT],
"<job-id> [<job-id> ...]",
"Cancel specified jobs"),
- 'info': (ShowJobs, ARGS_ANY, [DEBUG_OPT],
+ 'info': (ShowJobs, [ArgJobId(min=1)], [DEBUG_OPT],
"<job-id> [<job-id> ...]",
"Show detailed information about the specified jobs"),
+ 'watch': (WatchJob, [ArgJobId(min=1, max=1)], [DEBUG_OPT],
+ "<job-id>",
+ "Follows a job and prints its output as it arrives"),
}