X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/2f79bd34cf17210ba62ab6cad9cdd6a4bdcf1c3d..cd098c41522469e462efeb1e157a8718ff7b7809:/scripts/gnt-job diff --git a/scripts/gnt-job b/scripts/gnt-job index 88bf3ce..2da75a3 100755 --- a/scripts/gnt-job +++ b/scripts/gnt-job @@ -28,13 +28,18 @@ import sys from ganeti.cli import * from ganeti import constants 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", @@ -45,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 @@ -53,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 = { @@ -73,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": @@ -96,8 +107,7 @@ 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: ToStdout(line) @@ -105,6 +115,15 @@ def ListJobs(opts, args): 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: @@ -114,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] @@ -123,21 +156,40 @@ 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): @@ -233,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") @@ -255,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"