blob: 8a3d12a059b8a08f4342100885e5f6d930e02b4f [file]
#!/usr/bin/env python
# Copyright (c) 2013 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.
"""Module that polls the Cluster telemetry AppEngine WebApp.
All CT tasks are polled by this module. All new tasks are then triggered.
This module also periodically updates the Telemetry Information after
CHECK_WORKERS_HEALTH_AFTER_SECS have elapsed.
"""
import json
import os
import subprocess
import sys
import tempfile
import time
import traceback
import urllib
import appengine_constants
SLEEP_BETWEEN_POLLS_SECS = 30
CHECK_WORKERS_HEALTH_AFTER_SECS = 30*60
# The following dictionaries ensure that tasks which are being currently
# processed are not triggered again.
ADMIN_ENCOUNTERED_KEYS = {}
CHROMIUM_BUILD_ENCOUNTERED_KEYS = {}
CHROMIUM_TRY_ENCOUNTERED_KEYS = {}
LUA_ENCOUNTERED_KEYS = {}
TELEMETRY_ENCOUNTERED_KEYS = {}
SKIA_TRY_ENCOUNTERED_KEYS = {}
def update_local_checkout():
makefile_path = os.path.abspath(
os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
old_cwd = os.getcwd()
os.chdir(makefile_path)
os.system("git pull; make all;")
os.chdir(old_cwd)
def process_admin_task(task):
# Extract required parameters.
task_key = task['key']
if task_key in ADMIN_ENCOUNTERED_KEYS:
print '%s is already being processed' % task_key
return
ADMIN_ENCOUNTERED_KEYS[task_key] = 1
task_name = task['task_name']
username = task['username']
pagesets_type = task['pagesets_type']
run_id = '%s-%s' % (username.split('@')[0], time.time())
cmd = []
if task_name == appengine_constants.PAGESETS_ADMIN_TASK_NAME:
cmd = [
'create_pagesets_on_workers',
'--run_id=' + str(run_id),
'--emails=' + str(username),
'--gae_task_id=' + str(task_key),
'--pageset_type=' + str(pagesets_type),
'--log_dir=/b/storage/glog',
]
elif task_name == appengine_constants.WEBPAGE_ARCHIVES_ADMIN_TASK_NAME:
chromium_build_dir = get_chromium_build_dir(task['chromium_rev'],
task['skia_rev'])
cmd = [
'capture_archives_on_workers',
'--run_id=' + str(run_id),
'--emails=' + str(username),
'--gae_task_id=' + str(task_key),
'--pageset_type=' + str(pagesets_type),
'--chromium_build=' + str(chromium_build_dir),
'--log_dir=/b/storage/glog',
]
print 'Updating local checkout'
update_local_checkout()
print 'Running admin cmd: ' + ' '.join(cmd)
subprocess.Popen(cmd)
def process_chromium_build_task(task):
# Extract required parameters.
task_key = task['key']
if task_key in CHROMIUM_BUILD_ENCOUNTERED_KEYS:
print '%s is already being processed' % task_key
return
CHROMIUM_BUILD_ENCOUNTERED_KEYS[task_key] = 1
chromium_rev = task['chromium_rev']
skia_rev = task['skia_rev']
username = task['username']
run_id = '%s-%s' % (username.split('@')[0], time.time())
print 'Updating local checkout'
update_local_checkout()
cmd = [
'build_chromium',
'--emails=' + str(username),
'--gae_task_id=' + str(task_key),
'--run_id=' + str(run_id),
'--target_platform=Linux',
'--apply_patches=false',
'--chromium_hash=' + str(chromium_rev),
'--skia_hash=' + str(skia_rev),
'--log_dir=/b/storage/glog',
'--log_id=' + str(run_id),
]
print 'Running chromium build cmd: ' + ' '.join(cmd)
subprocess.Popen(cmd)
def fix_and_write_patch(patch, run_id):
"""Modifies the patch for consumption by slaves and writes to local file."""
# Remove all carriage returns, appengine adds them to blobs.
patch_txt = patch.replace('\r\n', '\n')
# Add an extra newline at the end because git sometimes rejects patches due to
# missing newlines.
patch_txt += '\n'
patch_file = os.path.join(tempfile.gettempdir(),
'%s.patch' % run_id)
f = open(patch_file, 'w')
f.write(patch_txt)
f.close()
return patch_file
def process_skia_try_task(task):
# Extract required parameters.
task_key = task['key']
if task_key in SKIA_TRY_ENCOUNTERED_KEYS:
print '%s is already being processed' % task_key
return
SKIA_TRY_ENCOUNTERED_KEYS[task_key] = 1
username = task['username']
run_id = '%s-%s' % (username.split('@')[0], time.time())
fix_and_write_patch(task['patch'], run_id)
pagesets_type = task['pagesets_type']
chromium_build_dir = get_chromium_build_dir(task['chromium_rev'],
task['skia_rev'])
render_pictures_args = task['render_pictures_args'].replace('"', r'\"')
gpu_nopatch_run = task['gpu_nopatch_run']
gpu_withpatch_run = task['gpu_withpatch_run']
print 'Updating local checkout'
update_local_checkout()
skia_try_cmd = [
'run_skia_correctness_on_workers',
'--emails=' + str(username),
'--gae_task_id=' + str(task_key),
'--pageset_type=' + str(pagesets_type),
'--chromium_build=' + str(chromium_build_dir),
'--render_pictures_args=' + str(render_pictures_args),
'--gpu_nopatch_run=' + str(gpu_nopatch_run),
'--gpu_withpatch_run=' + str(gpu_withpatch_run),
'--run_id=' + str(run_id),
'--log_dir=/b/storage/glog',
'--log_id=' + str(run_id),
]
print 'Running skia try cmd: ' + ' '.join(skia_try_cmd)
subprocess.Popen(skia_try_cmd)
def process_chromium_try_task(task):
# Extract required parameters.
task_key = task['key']
if task_key in CHROMIUM_TRY_ENCOUNTERED_KEYS:
print '%s is already being processed' % task_key
return
CHROMIUM_TRY_ENCOUNTERED_KEYS[task_key] = 1
username = task['username']
benchmark_name = task['benchmark_name']
benchmark_arguments = task['benchmark_arguments']
target_platform = task['target_platform']
# Escape any quotes in benchmark arguments.
benchmark_arguments = benchmark_arguments.replace('"', r'\"')
num_repeated_runs = task['num_repeated_runs']
variance_threshold = task['variance_threshold']
discard_outliers = task['discard_outliers']
pageset_type = task['pageset_type']
browser_args_1 = task['browser_args_1']
browser_args_2 = task['browser_args_2']
# Copy the patches to a local file.
run_id = '%s-%s' % (username.split('@')[0], time.time())
fix_and_write_patch(task['chromium_patch'], run_id + '.chromium')
fix_and_write_patch(task['blink_patch'], run_id + '.blink')
fix_and_write_patch(task['skia_patch'], run_id + '.skia')
print 'Updating local checkout'
update_local_checkout()
cmd = [
'run_chromium_perf_on_workers',
'--emails=' + str(username),
'--gae_task_id=' + str(task_key),
'--pageset_type=' + str(pageset_type),
'--benchmark_name=' + str(benchmark_name),
'--benchmark_extra_args=' + str(benchmark_arguments),
'--browser_extra_args_nopatch=' + str(browser_args_1),
'--browser_extra_args_withpatch=' + str(browser_args_2),
'--repeat_benchmark=' + str(num_repeated_runs),
'--target_platform=' + str(target_platform),
'--run_id=' + str(run_id),
'--variance_threshold=' + str(variance_threshold),
'--discard_outliers=' + str(discard_outliers),
'--log_dir=/b/storage/glog',
'--log_id=' + str(run_id),
]
print 'Running chromium try cmd: ' + ' '.join(cmd)
subprocess.Popen(cmd)
def process_lua_task(task):
task_key = task['key']
pagesets_type = task['pagesets_type']
if task_key in LUA_ENCOUNTERED_KEYS:
print '%s is already being processed' % task_key
return
LUA_ENCOUNTERED_KEYS[task_key] = 1
chromium_build_dir = get_chromium_build_dir(task['chromium_rev'],
task['skia_rev'])
# Create a run id.
run_id = '%s-%s' % (task['username'].split('@')[0], time.time())
lua_file = os.path.join(tempfile.gettempdir(), '%s.lua' % run_id)
f = open(lua_file, 'w')
f.write(task['lua_script'])
f.close()
if task.get('lua_aggregator'):
aggregator_file = os.path.join(tempfile.gettempdir(),
'%s.aggregator' % run_id)
f = open(aggregator_file, 'w')
f.write(task['lua_aggregator'])
f.close()
print 'Updating local checkout'
update_local_checkout()
cmd = [
'run_lua_on_workers',
'--emails=' + str(task['username']),
'--gae_task_id=' + str(task_key),
'--pageset_type=' + str(pagesets_type),
'--chromium_build=' + str(chromium_build_dir),
'--run_id=' + str(run_id),
'--log_dir=/b/storage/glog',
'--log_id=' + str(run_id),
]
print 'Running lua script cmd: ' + ' '.join(cmd)
subprocess.Popen(cmd)
def process_telemetry_task(task):
task_key = task['key']
if task_key in TELEMETRY_ENCOUNTERED_KEYS:
print '%s is already being processed' % task_key
return
TELEMETRY_ENCOUNTERED_KEYS[task_key] = 1
pagesets_type = task['pagesets_type']
chromium_build_dir = get_chromium_build_dir(task['chromium_rev'],
task['skia_rev'])
username = task['username']
# Create a run id.
run_id = '%s-%s' % (username.split('@')[0], time.time())
print 'Updating local checkout'
update_local_checkout()
cmd = [
'capture_skps_on_workers',
'--emails=' + str(username),
'--gae_task_id=' + str(task_key),
'--pageset_type=' + str(pagesets_type),
'--chromium_build=' + str(chromium_build_dir),
'--target_platform=Linux',
'--run_id=' + str(run_id),
'--log_dir=/b/storage/glog',
'--log_id=' + str(run_id),
]
print 'Running telemetry cmd: ' + ' '.join(cmd)
subprocess.Popen(cmd)
def get_chromium_build_dir(chromium_rev, skia_rev):
"""Construct the chromium build dir from chromium and skia revs."""
return '%s-%s' % (chromium_rev[0:7], skia_rev[0:7])
TASK_TYPE_TO_PROCESSING_METHOD = {
appengine_constants.ADMIN_TASK_NAME: process_admin_task,
appengine_constants.CHROMIUM_BUILD_TASK_NAME: process_chromium_build_task,
appengine_constants.CHROMIUM_TRY_TASK_NAME: process_chromium_try_task,
appengine_constants.LUA_TASK_NAME: process_lua_task,
appengine_constants.TELEMETRY_TASK_NAME: process_telemetry_task,
appengine_constants.SKIA_TRY_TASK_NAME: process_skia_try_task,
}
class Poller(object):
def Poll(self):
workers_health_check_run_on = 0
while True:
try:
if ((time.time() - workers_health_check_run_on) >=
CHECK_WORKERS_HEALTH_AFTER_SECS):
print 'Updating local checkout'
update_local_checkout()
cmd = [
'check_workers_health',
'--log_dir=/b/storage/glog',
]
print 'Running workers health check cmd: ' + ' '.join(cmd)
subprocess.Popen(cmd)
workers_health_check_run_on = time.time()
# pylint: disable=C0301
oldest_pending_task_page = urllib.urlopen(
appengine_constants.SKIA_TELEMETRY_WEBAPP +
appengine_constants.GET_OLDEST_PENDING_TASK_SUBPATH)
oldest_pending_task = json.loads(
oldest_pending_task_page.read().replace('\r\n', '\\r\\n'))
if oldest_pending_task:
task_type = oldest_pending_task.keys()[0]
processing_method = TASK_TYPE_TO_PROCESSING_METHOD[task_type]
processing_method(oldest_pending_task[task_type])
print 'Sleeping %s secs' % SLEEP_BETWEEN_POLLS_SECS
time.sleep(SLEEP_BETWEEN_POLLS_SECS)
except Exception:
# The poller should never crash, output the exception and move on.
print traceback.format_exc()
continue
if '__main__' == __name__:
sys.exit(Poller().Poll())