Allow local_dash reports to be regenerated from the ui.
For simply keeping an eye on local test activity, it's
helpful to have a ui based regenerate click to avoid dropping
into the chroot to update after running tests.
BUG=chromium-os:34919
TEST=result_viewer, then run_remote_tests.sh, then click regenerate.
Change-Id: I8465edee83f91d205401781ab9c5f127becd9979
Reviewed-on: https://gerrit.chromium.org/gerrit/38996
Reviewed-by: Yusuf Mohsinally <mohsinally@google.com>
Reviewed-by: Yusuf Mohsinally <mohsinally@chromium.org>
Commit-Ready: Mike Truty <truty@chromium.org>
Tested-by: Mike Truty <truty@chromium.org>
diff --git a/utils_py/local_dash/dash_template/result_viewer b/utils_py/local_dash/dash_template/result_viewer
index 2b14cb3..f0f90bf 100755
--- a/utils_py/local_dash/dash_template/result_viewer
+++ b/utils_py/local_dash/dash_template/result_viewer
@@ -9,7 +9,8 @@
By default pages are shown
"""
-import glob, json, operator, optparse, os, socket, sys, time
+import glob, json, operator, optparse, os, socket, subprocess, sys
+import datetime, time
# Bottle is a fast, simple and lightweight WSGI micro web-framework for Python.
# It enables simple webpage rendering from a single file (bottle.py) with no
@@ -152,6 +153,23 @@
"""Render a view that shows possible urls for help."""
return bottle.template('urlhelp')
+@app.route('/regenerate')
+def regenerate_results():
+ """Regenerate all reports from test results folder"""
+ test_results = read_test_results()
+ cmd = test_results.get('cmd')
+ if cmd:
+ print '%s: Regenerating report from test results.' % datetime.datetime.now()
+ cmd = [cmd]
+ config = test_results.get('config')
+ args = test_results.get('args')
+ if config:
+ cmd.append('-c')
+ cmd.append(config)
+ if args:
+ cmd.append(args)
+ subprocess.check_call(cmd)
+ bottle.redirect('/')
@app.route('/logs/<filepath:path>')
def server_result_file(filepath):
diff --git a/utils_py/local_dash/dash_template/views/header.tpl b/utils_py/local_dash/dash_template/views/header.tpl
index a914f86..4cf31a2 100644
--- a/utils_py/local_dash/dash_template/views/header.tpl
+++ b/utils_py/local_dash/dash_template/views/header.tpl
@@ -11,5 +11,6 @@
target="_blank">External buildbot</a> |
<a href="http://chromegw/i/chromeos/console"
target="_blank">Internal buildbot</a> |
+ <a href="/regenerate">Regenerate</a> |
<a href="/help">Help</a>
</div>
diff --git a/utils_py/local_dash/local_dash b/utils_py/local_dash/local_dash
index f014487..2e44df1 100755
--- a/utils_py/local_dash/local_dash
+++ b/utils_py/local_dash/local_dash
@@ -76,6 +76,9 @@
0: Shows ERROR logged messages.
1: Shows ERROR, INFO logged messages.
2: Shows ERROR, INFO and DEBUG logged messages.
+
+ Returns:
+ Tuple of (options, args) parsed.
"""
parser = optparse.OptionParser()
parser.add_option('-c', '--config-file',
@@ -87,7 +90,7 @@
parser.add_option('-v', '--verbosity-level',
help='1=debug, 2=most verbose [default: %default]',
dest='verbosity', type='int', default=0)
- options = parser.parse_args()[0]
+ options, args = parser.parse_args()
logging_level = logging.ERROR
if options.verbosity == 1:
@@ -96,7 +99,7 @@
logging_level = logging.DEBUG
LOG.setLevel(logging_level)
- return options
+ return options, args
def get_json_config(current_dir, json_file):
@@ -152,6 +155,10 @@
result dashboard. Each run_remote_tests.XXX folder will be an
individual dictionary entry in the list.
+ The result model is made up of actual _results, some hardware details,
+ a list of tests executed (for building report headers) and the
+ details of the command line execution for aiding re-runs of local_dash.
+
The _results data structure is organized as follows.
[{'path': path1 # path to the result folder,
@@ -215,20 +222,30 @@
suite_path = '/'.join(suite_parts[:2])
return path_, suite_path, is_suite
- def get_model(self):
+ def get_model(self, cmd=None, config=None, args=None):
"""Some final post-processing before the data is returned.
The model will commonly be viewed in date-descending order.
+
+ Args:
+ cmd: if present, added to the model to aid re-runs.
+ config: if present, added to the model to aid re-runs.
+ args: if present, added to the model to aid re-runs.
+
Returns:
A dictionary with 3 elements: the test-result-list-of-dictionaries, a
list of unique hardware on which the tests were attempted and a list of
unique tests that were attempted. These 3 things allow the recipient to
format some organized tables by hardware and test.
"""
- return {'results': sorted(self._results, key=itemgetter('timestamp'),
- reverse=True),
- 'hardware': sorted(self._hardware_set),
- 'tests': sorted(self._test_set)}
+ model = {'results': sorted(self._results, key=itemgetter('timestamp'),
+ reverse=True),
+ 'hardware': sorted(self._hardware_set),
+ 'tests': sorted(self._test_set)}
+ for k, var in [('cmd', cmd), ('config', config), ('args', args)]:
+ if var:
+ model[k] = var
+ return model
def print_result_model(self):
"""For diagnostic purposes allow the model to be reviewed."""
@@ -435,7 +452,7 @@
base_dir = os.path.dirname(os.path.abspath(argv[0]))
# Parse options
- options = parse_args()
+ options, args = parse_args()
try:
config_dash = get_json_config(base_dir, options.config_file)
@@ -451,7 +468,11 @@
if test_results:
if options.print_model:
test_results.print_result_model()
- file_name = write_json_file(test_results.get_model())
+ result_model = test_results.get_model(os.path.abspath(argv[0]),
+ options.config_file, args)
+ # To enable re-running this command from a web-ui, stash the
+ # details of this command invocation in the results.
+ file_name = write_json_file(result_model)
print 'Wrote %s.' % file_name
viewer_path = os.path.join(base_dir, 'dash_template', 'result_viewer')
# Touch forces the bottle web server to refresh.