Brillo Tier 1 PTS: Initial Script.

Here is the starting point for the Brillo Tier 1 PTS.

Currently it does the following:

* Connects to a MobLab instance.
* Adds the ADB Host to the MobLab host list.
* Stages an update payload (not yet used).
* Launches the Brillo PTS Sequence.

Added the Brillo PTS Sequence. Currently is just runs the
whitelisted Gtests twice.

Updated sequences to support using the local control file
and not the template.

BUG=b:24774860
TEST=Ran against a local moblab, payload is staged and
whitelisted Gtests run twice.

Change-Id: I421d5d9c659ca654494e10cb37456de6fdd9752d
Reviewed-on: https://chromium-review.googlesource.com/304792
Commit-Ready: Simran Basi <[email protected]>
Tested-by: Simran Basi <[email protected]>
Reviewed-by: Simran Basi <[email protected]>
diff --git a/server/hosts/adb_host.py b/server/hosts/adb_host.py
index f87be04..717d8ae 100644
--- a/server/hosts/adb_host.py
+++ b/server/hosts/adb_host.py
@@ -35,6 +35,7 @@
 RELEASE_FILE = 'ro.build.version.release'
 BOARD_FILE = 'ro.product.device'
 TMP_DIR = '/data/local/tmp'
+ANDROID_TESTER_FILEFLAG = '/mnt/stateful_partition/.android_tester'
 
 
 class ADBHost(abstract_ssh.AbstractSSHHost):
@@ -63,7 +64,7 @@
         """
         try:
             result = host.run(
-                    'test -f /mnt/stateful_partition/.android_tester',
+                    'test -f %s' % ANDROID_TESTER_FILEFLAG,
                     timeout=timeout)
         except (error.AutoservRunError, error.AutoservSSHTimeout):
             return False
diff --git a/server/hosts/cros_host.py b/server/hosts/cros_host.py
index 244a1fc..6c5662c 100644
--- a/server/hosts/cros_host.py
+++ b/server/hosts/cros_host.py
@@ -37,6 +37,7 @@
 from autotest_lib.server.cros.dynamic_suite import tools, frontend_wrappers
 from autotest_lib.server.cros.faft.config.config import Config as FAFTConfig
 from autotest_lib.server.hosts import abstract_ssh
+from autotest_lib.server.hosts import adb_host
 from autotest_lib.server.hosts import chameleon_host
 from autotest_lib.server.hosts import servo_host
 from autotest_lib.site_utils.rpm_control_system import rpm_client
@@ -2872,3 +2873,8 @@
 
     def get_os_type(self):
         return 'cros'
+
+
+    def enable_adb_testing(self):
+        """Mark this host as an adb tester."""
+        self.run('touch %s' % adb_host.ANDROID_TESTER_FILEFLAG)
diff --git a/server/hosts/factory.py b/server/hosts/factory.py
index 8623c80..7503c47 100644
--- a/server/hosts/factory.py
+++ b/server/hosts/factory.py
@@ -86,7 +86,7 @@
 
 def create_host(
     hostname, auto_monitor=False, follow_paths=None, pattern_paths=None,
-    netconsole=False, **args):
+    netconsole=False, host_class=None, **args):
     """Create a host object.
 
     This method mixes host classes that are needed into a new subclass
@@ -103,6 +103,8 @@
                          remote paths to monitor.
     @param pattern_paths: A list, passed to LogfileMonitorMixin,
                           local paths to alert pattern definition files.
+    @param host_class: Host class to use, if None, will attempt to detect
+                       the correct class.
     @param netconsole: A boolean value, if True, will mix NetconsoleHost in.
     @param args: Args that will be passed to the constructor of
                  the new host class.
@@ -131,8 +133,11 @@
                                   "on autotest's global_config.ini file." %
                                   SSH_ENGINE)
 
-    classes = [_detect_host(connectivity_class, hostname, **args),
-               connectivity_class]
+    if not host_class:
+        classes = [_detect_host(connectivity_class, hostname, **args),
+                   connectivity_class]
+    else:
+        classes = [host_class, connectivity_class]
     # by default mix in run_test support
     classes.append(autotest.AutotestHostMixin)
 
diff --git a/server/hosts/moblab_host.py b/server/hosts/moblab_host.py
index eec9832..66af7f5 100644
--- a/server/hosts/moblab_host.py
+++ b/server/hosts/moblab_host.py
@@ -43,6 +43,7 @@
     def _initialize(self, *args, **dargs):
         super(MoblabHost, self)._initialize(*args, **dargs)
         self.afe = frontend_wrappers.RetryingAFE(timeout_min=1,
+                                                 user='moblab',
                                                  server=self.hostname)
         # Clear the Moblab Image Storage so that staging an image is properly
         # tested.
@@ -156,6 +157,17 @@
                 self.run('ping %s -w 1' % ip, ignore_status=True)
 
 
+    def add_dut(self, hostname):
+        """Add a DUT hostname to the AFE.
+
+        @param hostname: DUT hostname to add.
+        """
+        result = self.run_as_moblab('%s host create %s' % (ATEST_PATH,
+                                                           hostname))
+        logging.debug('atest host create output for host %s:\n%s',
+                      hostname, result.stdout)
+
+
     def find_and_add_duts(self):
         """Discover DUTs on the testing subnet and add them to the AFE.
 
@@ -171,10 +183,7 @@
                 dut_hostname = match.group('ip')
                 if dut_hostname in existing_hosts:
                     break
-                result = self.run_as_moblab('%s host create %s' %
-                                            (ATEST_PATH, dut_hostname))
-                logging.debug('atest host create output for host %s:\n%s',
-                              dut_hostname, result.stdout)
+                self.add_dut(dut_hostname)
 
 
     def verify_software(self):
diff --git a/server/sequence.py b/server/sequence.py
index 365f683..5983af5 100644
--- a/server/sequence.py
+++ b/server/sequence.py
@@ -7,10 +7,12 @@
 """
 
 import logging
+import os
 
 import common
 from autotest_lib.client.common_lib import control_data
 from autotest_lib.server import utils
+from autotest_lib.server.cros.dynamic_suite import control_file_getter
 from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
 from autotest_lib.site_utils import job_directories
 
@@ -32,19 +34,24 @@
 parallel_simple(run, machines)
 """
 
-    def __init__(self, name, args=None, iteration=1, duration=None):
+    def __init__(self, name, args=None, iteration=1, duration=None,
+                 fetch_control_file=False):
         """
         Constructor
 
-        @param name: name of the sever test to run.
+        @param name: name of the server test to run.
         @param args: arguments needed by the server test.
         @param iteration: number of copy of this test to sechudle
         @param duration: expected duration of the test (in seconds).
+        @param fetch_control_file: If True, fetch the control file contents
+                                   from disk. Otherwise uses the template
+                                   control file.
         """
         self._name = name
         self._args = args or {}
         self._iteration = iteration
         self._duration = duration
+        self._fetch_control_file = fetch_control_file
 
 
     def child_job_name(self, machine, iteration_number):
@@ -81,16 +88,24 @@
 
     def child_control_file(self):
         """
-        Populate the template control file.
+        Generate the child job's control file.
 
-        Populate it with the test name and expand the arguments
-        list.
+        If not fetching the contents, use the template control file and
+        populate the template control file with the test name and expand the
+        arguments list.
 
         @param test: name of the test to run
         @param args: dictionary of argument for this test.
 
         @returns a fully built control file to be use for the child job.
         """
+        if self._fetch_control_file:
+            # TODO (sbasi): Add arg support.
+            cntl_file_getter = control_file_getter.FileSystemGetter(
+                    [os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                                  '..')])
+            return cntl_file_getter.get_control_file_contents_by_name(
+                    self._name)
         child_args = ['',]
         for arg, value in self._args.iteritems():
             child_args.append('%s=%s' % (arg, repr(value)))
diff --git a/server/site_tests/brillo_Gtests/control.whitelist b/server/site_tests/brillo_Gtests/control.brillo_GtestsWhitelist
similarity index 100%
rename from server/site_tests/brillo_Gtests/control.whitelist
rename to server/site_tests/brillo_Gtests/control.brillo_GtestsWhitelist
diff --git a/server/site_tests/sequences/control.brillo_pts b/server/site_tests/sequences/control.brillo_pts
new file mode 100644
index 0000000..10d7f2e
--- /dev/null
+++ b/server/site_tests/sequences/control.brillo_pts
@@ -0,0 +1,26 @@
+# Copyright 2015 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+AUTHOR = "sbasi"
+NAME = "BrilloPTS"
+TIME = "LONG"
+TEST_CATEGORY = "Stress"
+TEST_CLASS = "suite"
+TEST_TYPE = "server"
+
+DOC = """
+Sequence for kicking off the Brillo PTS tests.
+"""
+from autotest_lib.server import sequence
+
+
+# TODO (sbasi): Add the Autoupdate End to End Test.
+SERVER_SEQUENCES = [
+    sequence.SequenceJob('control.brillo_GtestsWhitelist', duration=2000,
+                         fetch_control_file=True),
+    sequence.SequenceJob('control.brillo_GtestsWhitelist', duration=2000,
+                         fetch_control_file=True),
+]
+
+sequence.sequence_schedule(job, machines, SERVER_SEQUENCES)