J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright 2014 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 6 | """Report whether DUTs are working or broken. |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 7 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 8 | usage: dut_status [ <options> ] [hostname ...] |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 9 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 10 | Reports on the history and status of selected DUT hosts, to |
| 11 | determine whether they're "working" or "broken". For purposes of |
| 12 | the script, "broken" means "the DUT requires manual intervention |
| 13 | before it can be used for further testing", and "working" means "not |
| 14 | broken". The status determination is based on the history of |
| 15 | completed jobs for the DUT in a given time interval; still-running |
| 16 | jobs are not considered. |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 17 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 18 | Time Interval Selection |
| 19 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 20 | A DUT's reported status is based on the DUT's job history in a time |
| 21 | interval determined by command line options. The interval is |
| 22 | specified with up to two of three options: |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 23 | --until/-u DATE/TIME - Specifies an end time for the search |
| 24 | range. (default: now) |
| 25 | --since/-s DATE/TIME - Specifies a start time for the search |
| 26 | range. (no default) |
| 27 | --duration/-d HOURS - Specifies the length of the search interval |
Dan Shi | d243736 | 2014-12-29 09:42:10 -0800 | [diff] [blame] | 28 | in hours. (default: 24 hours) |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 29 | |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 30 | Any two time options completely specify the time interval. If only |
| 31 | one option is provided, these defaults are used: |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 32 | --until - Use the given end time with the default duration. |
| 33 | --since - Use the given start time with the default end time. |
| 34 | --duration - Use the given duration with the default end time. |
| 35 | |
| 36 | If no time options are given, use the default end time and duration. |
| 37 | |
| 38 | DATE/TIME values are of the form '2014-11-06 17:21:34'. |
| 39 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 40 | DUT Selection |
| 41 | ~~~~~~~~~~~~~ |
| 42 | By default, information is reported for DUTs named as command-line |
| 43 | arguments. Options are also available for selecting groups of |
| 44 | hosts: |
| 45 | --board/-b BOARD - Only include hosts with the given board. |
| 46 | --pool/-p POOL - Only include hosts in the given pool. |
| 47 | |
| 48 | The selected hosts may also be filtered based on status: |
| 49 | -w/--working - Only include hosts in a working state. |
| 50 | -n/--broken - Only include hosts in a non-working state. Hosts |
| 51 | with no job history are considered non-working. |
| 52 | |
| 53 | Output Formats |
| 54 | ~~~~~~~~~~~~~~ |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 55 | There are four available output formats: |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 56 | * A simple list of host names. |
| 57 | * A status summary showing one line per host. |
| 58 | * A detailed job history for all selected DUTs, sorted by |
| 59 | time of execution. |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 60 | * A job history for all selected DUTs showing only the history |
| 61 | surrounding the DUT's last change from working to broken, |
| 62 | or vice versa. |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 63 | |
| 64 | The default format depends on whether hosts are filtered by |
| 65 | status: |
| 66 | * With the --working or --broken options, the list of host names |
| 67 | is the default format. |
| 68 | * Without those options, the default format is the one-line status |
| 69 | summary. |
| 70 | |
| 71 | These options override the default formats: |
| 72 | -o/--oneline - Use the one-line summary with the --working or |
| 73 | --broken options. |
| 74 | -f/--full_history - Print detailed per-host job history. |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 75 | -g/--diagnosis - Print the job history surrounding a status |
| 76 | change. |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 77 | |
| 78 | Examples |
| 79 | ~~~~~~~~ |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 80 | $ dut_status chromeos2-row4-rack2-host12 |
| 81 | hostname S last checked URL |
| 82 | chromeos2-row4-rack2-host12 NO 2014-11-06 15:25:29 http://... |
| 83 | |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 84 | 'NO' means the DUT is broken. That diagnosis is based on a job that |
| 85 | failed: 'last checked' is the time of the failed job, and the URL |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 86 | points to the job's logs. |
| 87 | |
| 88 | $ dut_status.py -u '2014-11-06 15:30:00' -d 1 -f chromeos2-row4-rack2-host12 |
| 89 | chromeos2-row4-rack2-host12 |
| 90 | 2014-11-06 15:25:29 NO http://... |
| 91 | 2014-11-06 14:44:07 -- http://... |
| 92 | 2014-11-06 14:42:56 OK http://... |
| 93 | |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 94 | The times are the start times of the jobs; the URL points to the |
| 95 | job's logs. The status indicates the working or broken status after |
| 96 | the job: |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 97 | 'NO' Indicates that the DUT was believed broken after the job. |
| 98 | 'OK' Indicates that the DUT was believed working after the job. |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 99 | '--' Indicates that the job probably didn't change the DUT's |
| 100 | status. |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 101 | Typically, logs of the actual failure will be found at the last job |
| 102 | to report 'OK', or the first job to report '--'. |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 103 | |
| 104 | """ |
| 105 | |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 106 | import argparse |
| 107 | import sys |
| 108 | import time |
| 109 | |
| 110 | import common |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 111 | from autotest_lib.client.common_lib import time_utils |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 112 | from autotest_lib.server import frontend |
Aviv Keshet | 7ee9586 | 2016-08-30 15:18:27 -0700 | [diff] [blame^] | 113 | from autotest_lib.server.lib import status_history |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 114 | |
| 115 | |
J. Richard Barnette | fa27f5b | 2015-03-23 17:11:54 -0700 | [diff] [blame] | 116 | # The fully qualified name makes for lines that are too long, so |
| 117 | # shorten it locally. |
| 118 | HostJobHistory = status_history.HostJobHistory |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 119 | |
J. Richard Barnette | fa27f5b | 2015-03-23 17:11:54 -0700 | [diff] [blame] | 120 | # _DIAGNOSIS_IDS - |
| 121 | # Dictionary to map the known diagnosis codes to string values. |
| 122 | |
| 123 | _DIAGNOSIS_IDS = { |
| 124 | status_history.UNUSED: '??', |
| 125 | status_history.UNKNOWN: '--', |
| 126 | status_history.WORKING: 'OK', |
| 127 | status_history.BROKEN: 'NO' |
| 128 | } |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 129 | |
| 130 | |
| 131 | # Default time interval for the --duration option when a value isn't |
| 132 | # specified on the command line. |
Dan Shi | d243736 | 2014-12-29 09:42:10 -0800 | [diff] [blame] | 133 | _DEFAULT_DURATION = 24 |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 134 | |
| 135 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 136 | def _include_status(status, arguments): |
| 137 | """Determine whether the given status should be filtered. |
| 138 | |
| 139 | Checks the given `status` against the command line options in |
| 140 | `arguments`. Return whether a host with that status should be |
| 141 | printed based on the options. |
| 142 | |
| 143 | @param status Status of a host to be printed or skipped. |
| 144 | @param arguments Parsed arguments object as returned by |
| 145 | ArgumentParser.parse_args(). |
| 146 | |
| 147 | @return Returns `True` if the command-line options call for |
| 148 | printing hosts with the status, or `False` otherwise. |
| 149 | |
| 150 | """ |
J. Richard Barnette | fa27f5b | 2015-03-23 17:11:54 -0700 | [diff] [blame] | 151 | if status == status_history.WORKING: |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 152 | return arguments.working |
| 153 | else: |
| 154 | return arguments.broken |
| 155 | |
| 156 | |
| 157 | def _print_host_summaries(history_list, arguments): |
| 158 | """Print one-line summaries of host history. |
| 159 | |
| 160 | This function handles the output format of the --oneline option. |
| 161 | |
| 162 | @param history_list A list of HostHistory objects to be printed. |
| 163 | @param arguments Parsed arguments object as returned by |
| 164 | ArgumentParser.parse_args(). |
| 165 | |
| 166 | """ |
J. Richard Barnette | 390e865 | 2015-06-24 11:59:10 -0700 | [diff] [blame] | 167 | fmt = '%-30s %-2s %-19s %s' |
J. Richard Barnette | 36282cc | 2014-10-14 13:58:30 -0700 | [diff] [blame] | 168 | print fmt % ('hostname', 'S', 'last checked', 'URL') |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 169 | for history in history_list: |
| 170 | status, event = history.last_diagnosis() |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 171 | if not _include_status(status, arguments): |
| 172 | continue |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 173 | datestr = '---' |
| 174 | url = '---' |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 175 | if event is not None: |
| 176 | datestr = time_utils.epoch_time_to_date_string( |
| 177 | event.start_time) |
| 178 | url = event.job_url |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 179 | |
J. Richard Barnette | 36282cc | 2014-10-14 13:58:30 -0700 | [diff] [blame] | 180 | print fmt % (history.hostname, |
| 181 | _DIAGNOSIS_IDS[status], |
| 182 | datestr, |
| 183 | url) |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 184 | |
| 185 | |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 186 | def _print_event_summary(event): |
| 187 | """Print a one-line summary of a job or special task.""" |
| 188 | start_time = time_utils.epoch_time_to_date_string( |
| 189 | event.start_time) |
| 190 | print ' %s %s %s' % ( |
| 191 | start_time, |
| 192 | _DIAGNOSIS_IDS[event.diagnosis], |
| 193 | event.job_url) |
| 194 | |
| 195 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 196 | def _print_hosts(history_list, arguments): |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 197 | """Print hosts, optionally with a job history. |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 198 | |
| 199 | This function handles both the default format for --working |
| 200 | and --broken options, as well as the output for the |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 201 | --full_history and --diagnosis options. The `arguments` |
| 202 | parameter determines the format to use. |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 203 | |
| 204 | @param history_list A list of HostHistory objects to be printed. |
| 205 | @param arguments Parsed arguments object as returned by |
| 206 | ArgumentParser.parse_args(). |
| 207 | |
| 208 | """ |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 209 | for history in history_list: |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 210 | status, _ = history.last_diagnosis() |
| 211 | if not _include_status(status, arguments): |
| 212 | continue |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 213 | print history.hostname |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 214 | if arguments.full_history: |
| 215 | for event in history: |
| 216 | _print_event_summary(event) |
| 217 | elif arguments.diagnosis: |
| 218 | for event in history.diagnosis_interval(): |
| 219 | _print_event_summary(event) |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 220 | |
| 221 | |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 222 | def _validate_time_range(arguments): |
| 223 | """Validate the time range requested on the command line. |
| 224 | |
| 225 | Enforces the rules for the --until, --since, and --duration |
| 226 | options are followed, and calculates defaults: |
| 227 | * It isn't allowed to supply all three options. |
| 228 | * If only two options are supplied, they completely determine |
| 229 | the time interval. |
| 230 | * If only one option is supplied, or no options, then apply |
| 231 | specified defaults to the arguments object. |
| 232 | |
| 233 | @param arguments Parsed arguments object as returned by |
| 234 | ArgumentParser.parse_args(). |
| 235 | |
| 236 | """ |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 237 | if (arguments.duration is not None and |
| 238 | arguments.since is not None and arguments.until is not None): |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 239 | print >>sys.stderr, ('FATAL: Can specify at most two of ' |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 240 | '--since, --until, and --duration') |
| 241 | sys.exit(1) |
| 242 | if (arguments.until is None and (arguments.since is None or |
| 243 | arguments.duration is None)): |
| 244 | arguments.until = int(time.time()) |
| 245 | if arguments.since is None: |
| 246 | if arguments.duration is None: |
| 247 | arguments.duration = _DEFAULT_DURATION |
| 248 | arguments.since = (arguments.until - |
| 249 | arguments.duration * 60 * 60) |
| 250 | elif arguments.until is None: |
| 251 | arguments.until = (arguments.since + |
| 252 | arguments.duration * 60 * 60) |
| 253 | |
| 254 | |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 255 | def _get_host_histories(afe, arguments): |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 256 | """Return HostJobHistory objects for the requested hosts. |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 257 | |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 258 | Checks that individual hosts specified on the command line are |
| 259 | valid. Invalid hosts generate a warning message, and are |
| 260 | omitted from futher processing. |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 261 | |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 262 | The return value is a list of HostJobHistory objects for the |
| 263 | valid requested hostnames, using the time range supplied on the |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 264 | command line. |
| 265 | |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 266 | @param afe Autotest frontend |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 267 | @param arguments Parsed arguments object as returned by |
| 268 | ArgumentParser.parse_args(). |
| 269 | @return List of HostJobHistory objects for the hosts requested |
| 270 | on the command line. |
| 271 | |
| 272 | """ |
| 273 | histories = [] |
| 274 | saw_error = False |
| 275 | for hostname in arguments.hostnames: |
| 276 | try: |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 277 | h = HostJobHistory.get_host_history( |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 278 | afe, hostname, arguments.since, arguments.until) |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 279 | histories.append(h) |
| 280 | except: |
| 281 | print >>sys.stderr, ('WARNING: Ignoring unknown host %s' % |
| 282 | hostname) |
| 283 | saw_error = True |
| 284 | if saw_error: |
| 285 | # Create separation from the output that follows |
| 286 | print >>sys.stderr |
| 287 | return histories |
| 288 | |
| 289 | |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 290 | def _validate_host_list(afe, arguments): |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 291 | """Validate the user-specified list of hosts. |
| 292 | |
| 293 | Hosts may be specified implicitly with --board or --pool, or |
| 294 | explictly as command line arguments. This enforces these |
| 295 | rules: |
| 296 | * If --board or --pool, or both are specified, individual |
| 297 | hosts may not be specified. |
| 298 | * However specified, there must be at least one host. |
| 299 | |
| 300 | The return value is a list of HostJobHistory objects for the |
| 301 | requested hosts, using the time range supplied on the command |
| 302 | line. |
| 303 | |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 304 | @param afe Autotest frontend |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 305 | @param arguments Parsed arguments object as returned by |
| 306 | ArgumentParser.parse_args(). |
| 307 | @return List of HostJobHistory objects for the hosts requested |
| 308 | on the command line. |
| 309 | |
| 310 | """ |
| 311 | if arguments.board or arguments.pool: |
| 312 | if arguments.hostnames: |
| 313 | print >>sys.stderr, ('FATAL: Hostname arguments provided ' |
| 314 | 'with --board or --pool') |
| 315 | sys.exit(1) |
| 316 | histories = HostJobHistory.get_multiple_histories( |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 317 | afe, arguments.since, arguments.until, |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 318 | board=arguments.board, pool=arguments.pool) |
| 319 | else: |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 320 | histories = _get_host_histories(afe, arguments) |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 321 | if not histories: |
| 322 | print >>sys.stderr, 'FATAL: no valid hosts found' |
| 323 | sys.exit(1) |
| 324 | return histories |
| 325 | |
| 326 | |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 327 | def _validate_format_options(arguments): |
| 328 | """Check the options for what output format to use. |
| 329 | |
| 330 | Enforce these rules: |
| 331 | * If neither --broken nor --working was used, then --oneline |
| 332 | becomes the selected format. |
| 333 | * If neither --broken nor --working was used, included both |
| 334 | working and broken DUTs. |
| 335 | |
| 336 | @param arguments Parsed arguments object as returned by |
| 337 | ArgumentParser.parse_args(). |
| 338 | |
| 339 | """ |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 340 | if (not arguments.oneline and not arguments.diagnosis and |
| 341 | not arguments.full_history): |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 342 | arguments.oneline = (not arguments.working and |
| 343 | not arguments.broken) |
| 344 | if not arguments.working and not arguments.broken: |
| 345 | arguments.working = True |
| 346 | arguments.broken = True |
| 347 | |
| 348 | |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 349 | def _validate_command(afe, arguments): |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 350 | """Check that the command's arguments are valid. |
| 351 | |
| 352 | This performs command line checking to enforce command line |
| 353 | rules that ArgumentParser can't handle. Additionally, this |
| 354 | handles calculation of default arguments/options when a simple |
| 355 | constant default won't do. |
| 356 | |
| 357 | Areas checked: |
| 358 | * Check that a valid time range was provided, supplying |
| 359 | defaults as necessary. |
| 360 | * Identify invalid host names. |
| 361 | |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 362 | @param afe Autotest frontend |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 363 | @param arguments Parsed arguments object as returned by |
| 364 | ArgumentParser.parse_args(). |
| 365 | @return List of HostJobHistory objects for the hosts requested |
| 366 | on the command line. |
| 367 | |
| 368 | """ |
| 369 | _validate_time_range(arguments) |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 370 | _validate_format_options(arguments) |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 371 | return _validate_host_list(afe, arguments) |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 372 | |
| 373 | |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 374 | def _parse_command(argv): |
J. Richard Barnette | 784d1ba | 2014-11-18 14:52:43 -0800 | [diff] [blame] | 375 | """Parse the command line arguments. |
| 376 | |
| 377 | Create an argument parser for this command's syntax, parse the |
| 378 | command line, and return the result of the ArgumentParser |
| 379 | parse_args() method. |
| 380 | |
| 381 | @param argv Standard command line argument vector; argv[0] is |
| 382 | assumed to be the command name. |
| 383 | @return Result returned by ArgumentParser.parse_args(). |
| 384 | |
| 385 | """ |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 386 | parser = argparse.ArgumentParser( |
| 387 | prog=argv[0], |
J. Richard Barnette | e62fa2c | 2014-11-06 17:44:04 -0800 | [diff] [blame] | 388 | description='Report DUT status and execution history', |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 389 | epilog='You can specify one or two of --since, --until, ' |
| 390 | 'and --duration, but not all three.\n' |
| 391 | 'The date/time format is "YYYY-MM-DD HH:MM:SS".') |
J. Richard Barnette | fa27f5b | 2015-03-23 17:11:54 -0700 | [diff] [blame] | 392 | parser.add_argument('-s', '--since', type=status_history.parse_time, |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 393 | metavar='DATE/TIME', |
| 394 | help='starting time for history display') |
J. Richard Barnette | fa27f5b | 2015-03-23 17:11:54 -0700 | [diff] [blame] | 395 | parser.add_argument('-u', '--until', type=status_history.parse_time, |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 396 | metavar='DATE/TIME', |
| 397 | help='ending time for history display' |
| 398 | ' (default: now)') |
| 399 | parser.add_argument('-d', '--duration', type=int, |
| 400 | metavar='HOURS', |
| 401 | help='number of hours of history to display' |
| 402 | ' (default: %d)' % _DEFAULT_DURATION) |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 403 | |
| 404 | format_group = parser.add_mutually_exclusive_group() |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 405 | format_group.add_argument('-f', '--full_history', action='store_true', |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 406 | help='Display host history from most ' |
| 407 | 'to least recent for each DUT') |
J. Richard Barnette | 8abbfd6 | 2015-06-23 12:46:54 -0700 | [diff] [blame] | 408 | format_group.add_argument('-g', '--diagnosis', action='store_true', |
| 409 | help='Display host history for the ' |
| 410 | 'most recent DUT status change') |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 411 | format_group.add_argument('-o', '--oneline', action='store_true', |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 412 | help='Display host status summary') |
| 413 | |
| 414 | parser.add_argument('-w', '--working', action='store_true', |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 415 | help='List working devices by name only') |
| 416 | parser.add_argument('-n', '--broken', action='store_true', |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 417 | help='List non-working devices by name only') |
| 418 | |
J. Richard Barnette | 40ab60a | 2014-11-18 15:44:09 -0800 | [diff] [blame] | 419 | parser.add_argument('-b', '--board', |
| 420 | help='Display history for all DUTs ' |
| 421 | 'of the given board') |
| 422 | parser.add_argument('-p', '--pool', |
| 423 | help='Display history for all DUTs ' |
| 424 | 'in the given pool') |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 425 | parser.add_argument('hostnames', |
| 426 | nargs='*', |
| 427 | help='host names of DUTs to report on') |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 428 | parser.add_argument('--web', |
| 429 | help='Master autotest frontend hostname. If no value ' |
| 430 | 'is given, the one in global config will be used.', |
| 431 | default=None) |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 432 | arguments = parser.parse_args(argv[1:]) |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 433 | return arguments |
| 434 | |
| 435 | |
| 436 | def main(argv): |
| 437 | """Standard main() for command line processing. |
| 438 | |
| 439 | @param argv Command line arguments (normally sys.argv). |
| 440 | |
| 441 | """ |
| 442 | arguments = _parse_command(argv) |
MK Ryu | 1b2d7f9 | 2015-02-24 17:45:02 -0800 | [diff] [blame] | 443 | afe = frontend.AFE(server=arguments.web) |
| 444 | history_list = _validate_command(afe, arguments) |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 445 | if arguments.oneline: |
| 446 | _print_host_summaries(history_list, arguments) |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 447 | else: |
J. Richard Barnette | 048a628 | 2014-12-12 11:30:23 -0800 | [diff] [blame] | 448 | _print_hosts(history_list, arguments) |
J. Richard Barnette | c9b7933 | 2014-09-22 13:14:33 -0700 | [diff] [blame] | 449 | |
| 450 | |
| 451 | if __name__ == '__main__': |
| 452 | main(sys.argv) |