X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/e92376d7b2085c6beeb01c4f159259cb396f4a91..cd098c41522469e462efeb1e157a8718ff7b7809:/scripts/gnt-job diff --git a/scripts/gnt-job b/scripts/gnt-job index d9a2253..2da75a3 100755 --- a/scripts/gnt-job +++ b/scripts/gnt-job @@ -19,26 +19,27 @@ # 02110-1301, USA. +# pylint: disable-msg=W0401,W0614 +# W0401: Wildcard import ganeti.cli +# W0614: Unused import %s from wildcard import (since we need cli) + import sys -import os -import itertools -import time -from optparse import make_option -from cStringIO import StringIO from ganeti.cli import * -from ganeti import opcodes -from ganeti import logger from ganeti import constants -from ganeti import utils from ganeti import errors +from ganeti import utils +#: default list of fields for L{ListJobs} _LIST_DEF_FIELDS = ["id", "status", "summary"] +#: map converting the job status contants to user-visible +#: names _USER_JOB_STATUS = { constants.JOB_STATUS_QUEUED: "queued", constants.JOB_STATUS_WAITLOCK: "waiting", + constants.JOB_STATUS_CANCELING: "canceling", constants.JOB_STATUS_RUNNING: "running", constants.JOB_STATUS_CANCELED: "canceled", constants.JOB_STATUS_SUCCESS: "success", @@ -49,6 +50,12 @@ _USER_JOB_STATUS = { def ListJobs(opts, args): """List the jobs + @param opts: the command line options selected by the user + @type args: list + @param args: should be an empty list + @rtype: int + @return: the desired exit code + """ if opts.output is None: selected_fields = _LIST_DEF_FIELDS @@ -57,7 +64,7 @@ def ListJobs(opts, args): 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 = { @@ -77,12 +84,12 @@ def ListJobs(opts, args): 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": @@ -100,15 +107,23 @@ def ListJobs(opts, args): row[idx] = str(val) data = GenerateTable(separator=opts.separator, headers=headers, - fields=selected_fields, unitfields=unitfields, - numfields=numfields, data=output) + fields=selected_fields, data=output) for line in data: - print line + ToStdout(line) return 0 def ArchiveJobs(opts, args): + """Archive jobs. + + @param opts: the command line options selected by the user + @type args: list + @param args: should contain the job IDs to be archived + @rtype: int + @return: the desired exit code + + """ client = GetClient() for job_id in args: @@ -118,6 +133,20 @@ def ArchiveJobs(opts, args): def AutoArchiveJobs(opts, args): + """Archive jobs based on age. + + This will archive jobs based on their age, or all jobs if a 'all' is + passed. + + @param opts: the command line options selected by the user + @type args: list + @param args: should contain only one element, the age as a time spec + that can be parsed by L{ganeti.cli.ParseTimespec} or the + keyword I{all}, which will cause all jobs to be archived + @rtype: int + @return: the desired exit code + + """ client = GetClient() age = args[0] @@ -127,26 +156,45 @@ def AutoArchiveJobs(opts, args): else: age = ParseTimespec(age) - client.AutoArchiveJobs(age) + (archived_count, jobs_left) = client.AutoArchiveJobs(age) + ToStdout("Archived %s jobs, %s unchecked left", archived_count, jobs_left) + return 0 def CancelJobs(opts, args): + """Cancel not-yet-started jobs. + + @param opts: the command line options selected by the user + @type args: list + @param args: should contain the job IDs to be cancelled + @rtype: int + @return: the desired exit code + + """ client = GetClient() for job_id in args: - client.CancelJob(job_id) + (success, msg) = client.CancelJob(job_id) + ToStdout(msg) + # TODO: Different exit value if not all jobs were canceled? return 0 def ShowJobs(opts, args): - """List the jobs + """Show detailed information about jobs. + + @param opts: the command line options selected by the user + @type args: list + @param args: should contain the job IDs to be queried + @rtype: int + @return: the desired exit code """ def format(level, text): """Display the text indented.""" - print "%s%s" % (" " * level, text) + ToStdout("%s%s", " " * level, text) def result_helper(value): """Format a result field in a nice way.""" @@ -185,7 +233,7 @@ def ShowJobs(opts, args): if status in _USER_JOB_STATUS: status = _USER_JOB_STATUS[status] else: - raise errors.ProgrammerError("Unknown job status code '%s'" % val) + raise errors.ProgrammerError("Unknown job status code '%s'" % status) format(1, "Status: %s" % status) @@ -237,7 +285,7 @@ def ShowJobs(opts, args): if key == "OP_ID": continue if isinstance(val, (tuple, list)): - val = ",".join(val) + val = ",".join([str(item) for item in val]) format(4, "%s: %s" % (key, val)) if result is None: format(3, "No output data") @@ -259,15 +307,16 @@ def ShowJobs(opts, args): format(3, "Execution log:") for serial, log_ts, log_type, log_msg in log: time_txt = FormatTimestamp(log_ts) - encoded = str(log_msg).encode('string_escape') + encoded = utils.SafeEncode(log_msg) format(4, "%s:%s:%s %s" % (serial, time_txt, log_type, encoded)) return 0 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, ARGS_ANY, + [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"