experiment_factory.py revision b47bff4d3336c5fe5593a95963c0f3dc20a02f68
1#!/usr/bin/python
2
3# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""A module to generate experments."""
8
9import os
10import re
11import socket
12
13from benchmark import Benchmark
14import config
15from experiment import Experiment
16from label import Label
17from label import MockLabel
18from results_cache import CacheConditions
19import test_flag
20
21
22class ExperimentFactory(object):
23  """Factory class for building an Experiment, given an ExperimentFile as input.
24
25  This factory is currently hardcoded to produce an experiment for running
26  ChromeOS benchmarks, but the idea is that in the future, other types
27  of experiments could be produced.
28  """
29
30  def GetExperiment(self, experiment_file, working_directory, log_dir):
31    """Construct an experiment from an experiment file."""
32    global_settings = experiment_file.GetGlobalSettings()
33    experiment_name = global_settings.GetField("name")
34    remote = global_settings.GetField("remote")
35    # This is used to remove the ",' from the remote if user
36    # add them to the remote string.
37    new_remote = []
38    for i in remote:
39      c = re.sub('["\']', '', i)
40      new_remote.append(c)
41    remote = new_remote
42    chromeos_root = global_settings.GetField("chromeos_root")
43    rm_chroot_tmp = global_settings.GetField("rm_chroot_tmp")
44    key_results_only = global_settings.GetField("key_results_only")
45    acquire_timeout= global_settings.GetField("acquire_timeout")
46    cache_dir = global_settings.GetField("cache_dir")
47    config.AddConfig("no_email", global_settings.GetField("no_email"))
48    share_users = global_settings.GetField("share_users")
49    results_dir = global_settings.GetField("results_dir")
50    chrome_src = global_settings.GetField("chrome_src")
51    use_test_that = global_settings.GetField("use_test_that")
52    # Default cache hit conditions. The image checksum in the cache and the
53    # computed checksum of the image must match. Also a cache file must exist.
54    cache_conditions = [CacheConditions.CACHE_FILE_EXISTS,
55                        CacheConditions.CHECKSUMS_MATCH]
56    if global_settings.GetField("rerun_if_failed"):
57      cache_conditions.append(CacheConditions.RUN_SUCCEEDED)
58    if global_settings.GetField("rerun"):
59      cache_conditions.append(CacheConditions.FALSE)
60    if global_settings.GetField("same_machine"):
61      cache_conditions.append(CacheConditions.SAME_MACHINE_MATCH)
62    if global_settings.GetField("same_specs"):
63      cache_conditions.append(CacheConditions.MACHINES_MATCH)
64
65    # Construct benchmarks.
66    benchmarks = []
67    all_benchmark_settings = experiment_file.GetSettings("benchmark")
68    for benchmark_settings in all_benchmark_settings:
69      benchmark_name = benchmark_settings.name
70      test_name = benchmark_settings.GetField("test_name")
71      if not test_name:
72        test_name = benchmark_name
73      test_args = benchmark_settings.GetField("test_args")
74      iterations = benchmark_settings.GetField("iterations")
75      outlier_range = benchmark_settings.GetField("outlier_range")
76      perf_args = benchmark_settings.GetField("perf_args")
77      rm_chroot_tmp = benchmark_settings.GetField("rm_chroot_tmp")
78      key_results_only = benchmark_settings.GetField("key_results_only")
79      suite = benchmark_settings.GetField("suite")
80      use_test_that = benchmark_settings.GetField("use_test_that")
81
82      benchmark = Benchmark(benchmark_name, test_name, test_args,
83                            iterations, outlier_range,
84                            key_results_only, rm_chroot_tmp,
85                            perf_args, suite, use_test_that)
86      benchmarks.append(benchmark)
87
88    # Construct labels.
89    labels = []
90    all_label_settings = experiment_file.GetSettings("label")
91    all_remote = list(remote)
92    for label_settings in all_label_settings:
93      label_name = label_settings.name
94      image = label_settings.GetField("chromeos_image")
95      chromeos_root = label_settings.GetField("chromeos_root")
96      board = label_settings.GetField("board")
97      my_remote = label_settings.GetField("remote")
98      new_remote = []
99      for i in my_remote:
100        c = re.sub('["\']', '', i)
101        new_remote.append(c)
102      my_remote = new_remote
103
104      image_md5sum = label_settings.GetField("md5sum")
105      cache_dir = label_settings.GetField("cache_dir")
106      chrome_src = label_settings.GetField("chrome_src")
107
108    # TODO(yunlian): We should consolidate code in machine_manager.py
109    # to derermine whether we are running from within google or not
110      if ("corp.google.com" in socket.gethostname() and
111          (not my_remote
112           or my_remote == remote
113           and global_settings.GetField("board") != board)):
114        my_remote = self.GetDefaultRemotes(board)
115      if global_settings.GetField("same_machine") and len(my_remote) > 1:
116        raise Exception("Only one remote is allowed when same_machine "
117                        "is turned on")
118      all_remote += my_remote
119      image_args = label_settings.GetField("image_args")
120      if test_flag.GetTestMode():
121        label = MockLabel(label_name, image, chromeos_root, board, my_remote,
122                          image_args, image_md5sum, cache_dir, chrome_src)
123      else:
124        label = Label(label_name, image, chromeos_root, board, my_remote,
125                      image_args, image_md5sum, cache_dir, chrome_src)
126      labels.append(label)
127
128    email = global_settings.GetField("email")
129    all_remote = list(set(all_remote))
130    experiment = Experiment(experiment_name, all_remote,
131                            working_directory, chromeos_root,
132                            cache_conditions, labels, benchmarks,
133                            experiment_file.Canonicalize(),
134                            email, acquire_timeout, log_dir, share_users,
135                            results_dir)
136
137    return experiment
138
139  def GetDefaultRemotes(self, board):
140    default_remotes_file = os.path.join(os.path.dirname(__file__),
141                                        "default_remotes")
142    try:
143      with open(default_remotes_file) as f:
144        for line in f:
145          key, v = line.split(":")
146          if key.strip() == board:
147            remotes = v.strip().split(" ")
148            if remotes:
149              return remotes
150            else:
151              raise Exception("There is not remote for {0}".format(board))
152    except IOError:
153      raise Exception("IOError while reading file {0}"
154                      .format(default_remotes_file))
155    else:
156      raise Exception("There is not remote for {0}".format(board))
157
158
159
160