Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Unified Diff: ct/py/trigger_wait_ct_task.py

Issue 1370523002: Add script that triggers a task on CTFE and then waits for its completion or times out (Closed) Base URL: https://skia.googlesource.com/buildbot@master
Patch Set: Add patchset option Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ct/py/trigger_wait_ct_task.py
diff --git a/ct/py/trigger_wait_ct_task.py b/ct/py/trigger_wait_ct_task.py
new file mode 100644
index 0000000000000000000000000000000000000000..fec4e2249d742ebbf0fbe04e36ce4843d69b5012
--- /dev/null
+++ b/ct/py/trigger_wait_ct_task.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Python utility that triggers and waits for tasks to complete on CTFE."""
+
+import base64
+import hashlib
+import json
+import optparse
+import requests
+import sys
+import time
+
+
+CTFE_HOST = "http://ct.skia.org"
+CTFE_QUEUE = CTFE_HOST + '/queue/'
+CHROMIUM_PERF_TASK_POST_URI = CTFE_HOST + "/_/webhook_add_chromium_perf_task"
+GET_CHROMIUM_PERF_RUN_STATUS_URI = CTFE_HOST + "/get_chromium_perf_run_status"
+CHROMIUM_PERF_RUNS_HISTORY = CTFE_HOST + "/chromium_perf_runs/"
+GCE_WEBHOOK_SALT_METADATA_URI = (
+ "http://metadata/computeMetadata/v1/project/attributes/"
+ "webhook_request_salt")
+
+
+POLLING_FREQUENCY_SECS = 60 # 1 minute.
+TRYBOT_DEADLINE_SECS = 24 * 60 * 60 # 24 hours.
+
+
+class CtTrybotException(Exception):
+ pass
+
+
+def _CreateTaskJSON(options):
+ """Creates a JSON representation of the requested task."""
+ task_params = {}
+ task_params["username"] = options.requester
+ task_params["benchmark"] = options.benchmark
+ task_params["platform"] = "Linux"
+ task_params["page_sets"] = "10k"
+ task_params["repeat_runs"] = "3"
+ task_params["benchmark_args"] = "--output-format=csv-pivot-table"
+ task_params["browser_args_nopatch"] = (
+ "--disable-setuid-sandbox --enable-threaded-compositing "
+ "--enable-impl-side-painting")
+ task_params["browser_args_withpatch"] = (
+ "--disable-setuid-sandbox --enable-threaded-compositing "
+ "--enable-impl-side-painting")
+
+ trybot_params = {}
+ trybot_params["issue"] = options.issue
+ trybot_params["patchset"] = options.patchset
+ trybot_params["task"] = task_params
+ return json.dumps(trybot_params)
+
+
+def _GetWebhookSaltFromMetadata():
+ """Gets webhook_request_salt from GCE's metadata server."""
+ headers = {"Metadata-Flavor": "Google"}
+ resp = requests.get(GCE_WEBHOOK_SALT_METADATA_URI, headers=headers)
+ if resp.status_code != 200:
+ raise CtTrybotException(
+ 'Return code from %s was %s' % (GCE_WEBHOOK_SALT_METADATA_URI,
+ resp.status_code))
+ return resp.text
+
+
+def _TriggerTask(options):
+ """Triggers the requested task on CTFE and returns the new task's ID."""
+ task = _CreateTaskJSON(options)
+ m = hashlib.sha512()
+ m.update(task)
+ m.update('notverysecret' if options.local else _GetWebhookSaltFromMetadata())
+ encoded = base64.standard_b64encode(m.digest())
+
+ headers = {
+ "Content-type": "application/x-www-form-urlencoded",
+ "Accept": "application/json",
+ "X-Webhook-Auth-Hash": encoded}
+ resp = requests.post(CHROMIUM_PERF_TASK_POST_URI, task, headers=headers)
+
+ if resp.status_code != 200:
+ raise CtTrybotException(
+ 'Return code from %s was %s' % (CHROMIUM_PERF_TASK_POST_URI,
+ resp.status_code))
+ try:
+ ret = json.loads(resp.text)
+ except ValueError, e:
+ raise CtTrybotException(
+ 'Did not get a JSON response from %s: %s' % (
+ CHROMIUM_PERF_TASK_POST_URI, e))
+ return ret["taskID"]
+
+
+def TriggerAndWait(options):
+ task_id = _TriggerTask(options)
+
+ print
+ print 'Task %s has been successfull scheduled on CTFE (%s).' % (
+ task_id, CHROMIUM_PERF_RUNS_HISTORY)
+ print 'You will get an email once the task has been picked up by the server.'
+ print
+ print
+
+ # Now poll CTFE till the task completes or till deadline is hit.
+ time_started_polling = time.time()
+ while True:
+ if (time.time() - time_started_polling) > TRYBOT_DEADLINE_SECS:
+ raise CtTrybotException(
+ 'Task did not complete in the deadline of %s seconds.' % (
+ TRYBOT_DEADLINE_SECS))
+
+ # Get the status of the task the trybot added.
+ get_url = '%s?task_id=%s' % (GET_CHROMIUM_PERF_RUN_STATUS_URI, task_id)
+ resp = requests.get(get_url)
+ if resp.status_code != 200:
+ raise CtTrybotException(
+ 'Return code from %s was %s' % (GET_CHROMIUM_PERF_RUN_STATUS_URI,
+ resp.status_code))
+ try:
+ ret = json.loads(resp.text)
+ except ValueError, e:
+ raise CtTrybotException(
+ 'Did not get a JSON response from %s: %s' % (get_url, e))
+ # Assert that the status is for the task we asked for.
+ assert int(ret["taskID"]) == int(task_id)
+
+ status = ret["status"]
+ if status == "Completed":
+ print
+ print ('Your run was successfully completed. Please check your email for '
+ 'results of the run.')
+ print
+ return 0
+ elif status == "Completed with failures":
+ print
+ raise CtTrybotException(
+ 'Your run was completed with failures. Please check your email for '
+ 'links to logs of the run.')
+
+ print ('The current status of the task %s is "%s". You can view the size '
+ 'of the queue here: %s' % (task_id, status, CTFE_QUEUE))
+ print 'Checking again after %s seconds' % POLLING_FREQUENCY_SECS
+ print
+ time.sleep(POLLING_FREQUENCY_SECS)
+
+
+if '__main__' == __name__:
+ option_parser = optparse.OptionParser()
+ option_parser.add_option(
+ '', '--issue',
+ help='The Rietveld CL number to get the patch from.')
+ option_parser.add_option(
+ '', '--patchset',
+ help='The Rietveld CL patchset to use.')
+ option_parser.add_option(
+ '', '--requester',
+ help='Email address of the user who requested this run.')
+ option_parser.add_option(
+ '', '--benchmark',
+ help='The CT benchmark to run on the patch.')
+ option_parser.add_option(
+ '', '--local', default=False, action='store_true',
+ help='Uses a dummy metadata salt if this flag is true else it tries to '
+ 'get the salt from GCE metadata.')
+ options, unused_args = option_parser.parse_args()
+ if (not options.issue or not options.patchset or not options.requester
+ or not options.benchmark):
+ option_parser.error('Must specify issue, patchset, requester and benchmark')
+
+ sys.exit(TriggerAndWait(options))
+
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698