[autotest] Delete code for creating Android testbeds.

This deletes all factory code creating testbed.TestBed instances,
along with some related external references to the TestBed class.

BUG=chromium:834335
TEST=TBD

Change-Id: Ie400c0c6a1d13aa01130dd38b71b45b0809a2476
Reviewed-on: https://chromium-review.googlesource.com/1029353
Commit-Ready: Richard Barnette <jrbarnette@chromium.org>
Tested-by: Richard Barnette <jrbarnette@chromium.org>
Reviewed-by: Aviv Keshet <akeshet@chromium.org>
diff --git a/cli/host.py b/cli/host.py
index 3d8e161..05b152f 100644
--- a/cli/host.py
+++ b/cli/host.py
@@ -666,13 +666,9 @@
         try:
             if bin_utils.ping(host, tries=1, deadline=1) == 0:
                 serials = self.attributes.get('serials', '').split(',')
-                if serials and len(serials) > 1:
-                    host_dut = hosts.create_testbed(machine,
-                                                    adb_serials=serials)
-                else:
-                    adb_serial = self.attributes.get('serials')
-                    host_dut = hosts.create_host(machine,
-                                                 adb_serial=adb_serial)
+                adb_serial = self.attributes.get('serials')
+                host_dut = hosts.create_host(machine,
+                                             adb_serial=adb_serial)
 
                 info = HostInfo(host, host_dut.get_platform(),
                                 host_dut.get_labels())
diff --git a/global_config.ini b/global_config.ini
index 4bca337..19808f3 100644
--- a/global_config.ini
+++ b/global_config.ini
@@ -462,10 +462,6 @@
 # running inside the container can use the same user to make RPC.
 user:
 
-[ACTS]
-# Section for ACTS configuration.
-acts_config_folder:
-
 [ANDROID]
 image_url_pattern: %s/static/%s
 stable_version_dragonboard: git_mnc-brillo-dev/dragonboard-userdebug/2512766
diff --git a/server/control_segments/crashinfo b/server/control_segments/crashinfo
index 82f075f..4f45ee4 100644
--- a/server/control_segments/crashinfo
+++ b/server/control_segments/crashinfo
@@ -3,10 +3,6 @@
 
 
 def crashinfo(machine):
-    if utils.machine_is_testbed(machine):
-        logging.info('testbed does not need to get crash info.')
-        return
-
     host = hosts.create_host(machine)
     if has_failed_tests:
         crashcollect.get_crashinfo(host, test_start_time)
diff --git a/server/control_segments/provision b/server/control_segments/provision
index 2840688..33e22aa 100644
--- a/server/control_segments/provision
+++ b/server/control_segments/provision
@@ -68,10 +68,7 @@
         duration = (end_time - start_time).total_seconds()
 
         fields = {'success': label_update_success,
-                  # TODO(kevcheng): Need a better way of classifying testbeds.
-                  'board': (host.get_board()
-                            if not utils.machine_is_testbed(machine)
-                            else host.get_platform())}
+                  'board': host.get_board()}
         _LABEL_UPDATE_DURATION_METRIC.add(duration, fields=fields)
     except Exception:
         logging.exception('Provision failed due to Exception.')
diff --git a/server/control_segments/verify_job_repo_url b/server/control_segments/verify_job_repo_url
index 6f908ce..4f25039 100644
--- a/server/control_segments/verify_job_repo_url
+++ b/server/control_segments/verify_job_repo_url
@@ -2,10 +2,6 @@
 
 
 def install(machine):
-    if utils.machine_is_testbed(machine):
-        logging.info('testbed does not need to verify job repo url.')
-        return
-
     logging.info('Verifying job repo url for machine %s', machine)
     host = hosts.create_host(machine)
     host.verify_job_repo_url(job.tag)
diff --git a/server/hosts/__init__.py b/server/hosts/__init__.py
index ad3babb..b2f7f0a 100644
--- a/server/hosts/__init__.py
+++ b/server/hosts/__init__.py
@@ -19,11 +19,9 @@
 from cros_host import CrosHost
 from chameleon_host import ChameleonHost
 from servo_host import ServoHost
-from testbed import TestBed
 
 # factory function
 from factory import create_host
-from factory import create_testbed
 from factory import create_target_machine
 
 # Many host creation sites only import the package, so also provide useful
diff --git a/server/hosts/factory.py b/server/hosts/factory.py
index a541953..9b7dafc 100644
--- a/server/hosts/factory.py
+++ b/server/hosts/factory.py
@@ -21,7 +21,6 @@
 from autotest_lib.server.hosts import gce_host
 from autotest_lib.server.hosts import sonic_host
 from autotest_lib.server.hosts import ssh_host
-from autotest_lib.server.hosts import testbed
 
 
 CONFIG = global_config.global_config
@@ -208,29 +207,8 @@
     return host_instance
 
 
-def create_testbed(machine, **kwargs):
-    """Create the testbed object.
-
-    @param machine: A dict representing the test bed under test or a String
-                    representing the testbed hostname (for legacy caller
-                    support).
-                    If it is a machine dict, the 'hostname' key is required.
-                    Optional 'afe_host' key will pipe in afe_host from
-                    the afe_host object from the autoserv runtime or the AFE.
-    @param kwargs: Keyword args to pass to the testbed initialization.
-
-    @returns: The testbed object with all associated host objects instantiated.
-    """
-    detected_args = _get_host_arguments(machine)
-    hostname = detected_args.pop('hostname')
-    kwargs.update(detected_args)
-    host = testbed.TestBed(hostname, **kwargs)
-    base_classes.send_creation_metric(host, context='factory')
-    return host
-
-
 def create_target_machine(machine, **kwargs):
-    """Create the target machine which could be a testbed or a *Host.
+    """Create the target machine, accounting for containers.
 
     @param machine: A dict representing the test bed under test or a String
                     representing the testbed hostname (for legacy caller
@@ -259,9 +237,4 @@
             machine = hostname
         logging.debug('Hostname of machine is converted to %s for the test to '
                       'run inside a container.', hostname)
-
-    # TODO(kevcheng): We'll want to have a smarter way of figuring out which
-    # host to create (checking host labels).
-    if server_utils.machine_is_testbed(machine):
-        return create_testbed(machine, **kwargs)
     return create_host(machine, **kwargs)
diff --git a/server/hosts/factory_unittest.py b/server/hosts/factory_unittest.py
index f876e4d..8e1d68c 100755
--- a/server/hosts/factory_unittest.py
+++ b/server/hosts/factory_unittest.py
@@ -3,7 +3,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import mock
 import unittest
 
 import common
@@ -229,73 +228,6 @@
         self.assertEqual(host_obj._init_args['ssh_options'], 'options')
 
 
-class CreateTestbedUnittests(unittest.TestCase):
-    """Tests for create_testbed function."""
-
-    def setUp(self):
-        """Mock out TestBed class to eliminate side effects.
-        """
-        self._orig_testbed = factory.testbed.TestBed
-        factory.testbed.TestBed = _gen_mock_host('testbed')
-
-
-    def tearDown(self):
-        """Clean up mock.
-        """
-        factory.testbed.TestBed = self._orig_testbed
-
-
-    def test_argument_passthrough(self):
-        """Confirm that detected and specified arguments are passed through to
-        the testbed object.
-        """
-        machine = _gen_machine_dict(hostname='localhost')
-        testbed_obj = factory.create_testbed(machine, foo='bar')
-        self.assertEqual(testbed_obj._init_args['hostname'], 'localhost')
-        self.assertTrue('afe_host' in testbed_obj._init_args)
-        self.assertTrue('host_info_store' in testbed_obj._init_args)
-        self.assertEqual(testbed_obj._init_args['foo'], 'bar')
-
-
-    def test_global_ssh_params(self):
-        """Confirm passing of ssh parameters set as globals.
-        """
-        factory.ssh_user = 'foo'
-        factory.ssh_pass = 'bar'
-        factory.ssh_port = 1
-        factory.ssh_verbosity_flag = 'baz'
-        factory.ssh_options = 'zip'
-        machine = _gen_machine_dict()
-        try:
-            testbed_obj = factory.create_testbed(machine)
-            self.assertEqual(testbed_obj._init_args['user'], 'foo')
-            self.assertEqual(testbed_obj._init_args['password'], 'bar')
-            self.assertEqual(testbed_obj._init_args['port'], 1)
-            self.assertEqual(testbed_obj._init_args['ssh_verbosity_flag'],
-                             'baz')
-            self.assertEqual(testbed_obj._init_args['ssh_options'], 'zip')
-        finally:
-            del factory.ssh_user
-            del factory.ssh_pass
-            del factory.ssh_port
-            del factory.ssh_verbosity_flag
-            del factory.ssh_options
-
-
-    def test_host_attribute_ssh_params(self):
-        """Confirm passing of ssh parameters from host attributes.
-        """
-        machine = _gen_machine_dict(attributes={'ssh_user': 'somebody',
-                                                'ssh_port': 100,
-                                                'ssh_verbosity_flag': 'verb',
-                                                'ssh_options': 'options'})
-        testbed_obj = factory.create_testbed(machine)
-        self.assertEqual(testbed_obj._init_args['user'], 'somebody')
-        self.assertEqual(testbed_obj._init_args['port'], 100)
-        self.assertEqual(testbed_obj._init_args['ssh_verbosity_flag'], 'verb')
-        self.assertEqual(testbed_obj._init_args['ssh_options'], 'options')
-
-
 if __name__ == '__main__':
     unittest.main()
 
diff --git a/server/server_job.py b/server/server_job.py
index 9f3ec55..e9774b4 100644
--- a/server/server_job.py
+++ b/server/server_job.py
@@ -1287,7 +1287,6 @@
         namespace['autotest'].Autotest.job = self
         # server.hosts.base_classes.Host uses .job.
         namespace['hosts'].Host.job = self
-        namespace['hosts'].TestBed.job = self
         namespace['hosts'].factory.ssh_user = self._ssh_user
         namespace['hosts'].factory.ssh_port = self._ssh_port
         namespace['hosts'].factory.ssh_pass = self._ssh_pass
diff --git a/server/site_tests/android_EasySetup/android_EasySetup.py b/server/site_tests/android_EasySetup/android_EasySetup.py
deleted file mode 100644
index 0ba44bb..0000000
--- a/server/site_tests/android_EasySetup/android_EasySetup.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2016 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.
-import logging
-
-import common
-from autotest_lib.server import test
-from autotest_lib.site_utils import acts_lib
-from autotest_lib.server.cros import dnsname_mangler
-from autotest_lib.server.hosts import host_info
-
-
-class android_EasySetup(test.test):
-    """A test that does nothing except setup a phone.
-
-    This test will only setup a phone how a user wants and will perform no
-    tests.
-    """
-    version = 1
-
-    def run_once(self,
-                testbed=None,
-                install_sl4a=True,
-                additional_apks=[]):
-        """When run the testbed will be setup.
-
-        @param testbed: The testbed to setup.
-        @param install_sl4a: When true sl4a will be installed.
-        @param additional_apks: An array of apk info dictionaries.
-                                apk = Name of the apk (eg. sl4a.apk)
-                                package = Name of the package (eg. test.tools)
-                                artifact = Name of the artifact, if not given
-                                           package is used.
-        """
-        hostname = testbed.hostname
-        if dnsname_mangler.is_ip_address(hostname):
-            testbed_name = hostname
-        else:
-            testbed_name = hostname.split('.')[0]
-
-        valid_hosts = []
-        for v in testbed.get_adb_devices().values():
-            try:
-                info = v.host_info_store.get()
-            except host_info.StoreError:
-                pass
-            else:
-                if v.job_repo_url_attribute in info.attributes:
-                    valid_hosts.append(v)
-
-        if not valid_hosts:
-            logging.error('No valid devices.')
-            return
-
-        testbed_env = acts_lib.AndroidTestingEnvironment(
-                devices=valid_hosts,
-                testbed_name=testbed_name)
-
-        if install_sl4a:
-            testbed_env.install_sl4a_apk()
-
-        for apk in additional_apks:
-            testbed_env.install_apk(apk)
diff --git a/server/site_tests/android_EasySetup/control b/server/site_tests/android_EasySetup/control
deleted file mode 100644
index 8a88cf4..0000000
--- a/server/site_tests/android_EasySetup/control
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2016 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 = 'bpeake'
-NAME = 'android_EasySetup'
-TIME = 'SHORT'
-TEST_TYPE = 'Server'
-
-DOC = """
-Sets up a phone how the user wants.
-
-"""
-
-import common
-from autotest_lib.server import utils
-
-def run(machine):
-    job.run_test('android_EasySetup',
-                 testbed=hosts.create_testbed(machine))
-
-
-parallel_simple(run, machines)
diff --git a/server/site_utils.py b/server/site_utils.py
index 51cede7..95579d5 100644
--- a/server/site_utils.py
+++ b/server/site_utils.py
@@ -764,20 +764,6 @@
     return os.path.join(creds_dir, creds_file)
 
 
-def machine_is_testbed(machine):
-    """Checks if the machine is a testbed.
-
-    The signal we use to determine if the machine is a testbed
-    is if the host attributes contain more than 1 serial.
-
-    @param machine: is a list of dicts
-
-    @return: True if the machine is a testbed, False otherwise.
-    """
-    _, afe_host = get_host_info_from_machine(machine)
-    return len(afe_host.attributes.get('serials', '').split(',')) > 1
-
-
 def SetupTsMonGlobalState(*args, **kwargs):
     """Import-safe wrap around chromite.lib.ts_mon_config's setup function.
 
@@ -990,4 +976,4 @@
 
     _report_result_size_metrics(result_size_info)
 
-    return result_size_info
\ No newline at end of file
+    return result_size_info
diff --git a/site_utils/acts_lib.py b/site_utils/acts_lib.py
deleted file mode 100644
index e8642c9..0000000
--- a/site_utils/acts_lib.py
+++ /dev/null
@@ -1,610 +0,0 @@
-# Copyright 2016 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.
-
-import json
-import logging
-import os
-
-from autotest_lib.client.common_lib import error
-from autotest_lib.client.common_lib import global_config
-from autotest_lib.server import adb_utils
-from autotest_lib.server import constants
-from autotest_lib.server.hosts import adb_host
-
-DEFAULT_ACTS_INTERNAL_DIRECTORY = 'tools/test/connectivity/acts'
-
-CONFIG_FOLDER_LOCATION = global_config.global_config.get_config_value(
-    'ACTS', 'acts_config_folder', default='')
-
-TEST_DIR_NAME = 'tests'
-FRAMEWORK_DIR_NAME = 'framework'
-SETUP_FILE_NAME = 'setup.py'
-CONFIG_DIR_NAME = 'autotest_config'
-CAMPAIGN_DIR_NAME = 'autotest_campaign'
-LOG_DIR_NAME = 'logs'
-ACTS_EXECUTABLE_IN_FRAMEWORK = 'acts/bin/act.py'
-
-ACTS_TESTPATHS_ENV_KEY = 'ACTS_TESTPATHS'
-ACTS_LOGPATH_ENV_KEY = 'ACTS_LOGPATH'
-ACTS_PYTHONPATH_ENV_KEY = 'PYTHONPATH'
-
-
-def create_acts_package_from_current_artifact(test_station, job_repo_url,
-                                              target_zip_file):
-    """Creates an acts package from the build branch being used.
-
-    Creates an acts artifact from the build branch being used. This is
-    determined by the job_repo_url passed in.
-
-    @param test_station: The teststation that should be creating the package.
-    @param job_repo_url: The job_repo_url to get the build info from.
-    @param target_zip_file: The zip file to create form the artifact on the
-                            test_station.
-
-    @returns An ActsPackage containing all the information about the zipped
-             artifact.
-    """
-    build_info = adb_host.ADBHost.get_build_info_from_build_url(job_repo_url)
-
-    return create_acts_package_from_artifact(
-        test_station, build_info['branch'], build_info['target'],
-        build_info['build_id'], job_repo_url, target_zip_file)
-
-
-def create_acts_package_from_artifact(test_station, branch, target, build_id,
-                                      devserver, target_zip_file):
-    """Creates an acts package from a specified branch.
-
-    Grabs the packaged acts artifact from the branch and places it on the
-    test_station.
-
-    @param test_station: The teststation that should be creating the package.
-    @param branch: The name of the branch where the artifact is to be pulled.
-    @param target: The name of the target where the artifact is to be pulled.
-    @param build_id: The build id to pull the artifact from.
-    @param devserver: The devserver to use.
-    @param target_zip_file: The zip file to create on the teststation.
-
-    @returns An ActsPackage containing all the information about the zipped
-             artifact.
-    """
-    devserver.trigger_download(
-        target, build_id, branch, files='acts.zip', synchronous=True)
-
-    pull_base_url = devserver.get_pull_url(target, build_id, branch)
-    download_ulr = os.path.join(pull_base_url, 'acts.zip')
-
-    test_station.download_file(download_ulr, target_zip_file)
-
-    return ActsPackage(test_station, target_zip_file)
-
-
-def create_acts_package_from_zip(test_station, zip_location, target_zip_file):
-    """Creates an acts package from an existing zip.
-
-    Creates an acts package from a zip file that already sits on the drone.
-
-    @param test_station: The teststation to create the package on.
-    @param zip_location: The location of the zip on the drone.
-    @param target_zip_file: The zip file to create on the teststaiton.
-
-    @returns An ActsPackage containing all the information about the zipped
-             artifact.
-    """
-    if not os.path.isabs(zip_location):
-        zip_location = os.path.join(CONFIG_FOLDER_LOCATION, 'acts_artifacts',
-                                    zip_location)
-
-    test_station.send_file(zip_location, target_zip_file)
-
-    return ActsPackage(test_station, target_zip_file)
-
-
-class ActsPackage(object):
-    """A packaged version of acts on a teststation."""
-
-    def __init__(self, test_station, zip_file_path):
-        """
-        @param test_station: The teststation this package is on.
-        @param zip_file_path: The path to the zip file on the test station that
-                              holds the package on the teststation.
-        """
-        self.test_station = test_station
-        self.zip_file = zip_file_path
-
-    def create_container(self,
-                         container_directory,
-                         internal_acts_directory=None):
-        """Unpacks this package into a container.
-
-        Unpacks this acts package into a container to interact with acts.
-
-        @param container_directory: The directory on the teststation to hold
-                                    the container.
-        @param internal_acts_directory: The directory inside of the package
-                                        that holds acts.
-
-        @returns: An ActsContainer with info on the unpacked acts container.
-        """
-        self.test_station.run('unzip "%s" -x -d "%s"' %
-                              (self.zip_file, container_directory))
-
-        return ActsContainer(
-            self.test_station,
-            container_directory,
-            acts_directory=internal_acts_directory)
-
-    def create_environment(self,
-                           container_directory,
-                           devices,
-                           testbed_name,
-                           internal_acts_directory=None):
-        """Unpacks this package into an acts testing enviroment.
-
-        Unpacks this acts package into a test enviroment to test with acts.
-
-        @param container_directory: The directory on the teststation to hold
-                                    the test enviroment.
-        @param devices: The list of devices in the environment.
-        @param testbed_name: The name of the testbed.
-        @param internal_acts_directory: The directory inside of the package
-                                        that holds acts.
-
-        @returns: An ActsTestingEnvironment with info on the unpacked
-                  acts testing environment.
-        """
-        container = self.create_container(container_directory,
-                                          internal_acts_directory)
-
-        return ActsTestingEnviroment(
-            devices=devices,
-            container=container,
-            testbed_name=testbed_name)
-
-
-class AndroidTestingEnvironment(object):
-    """A container for testing android devices on a test station."""
-
-    def __init__(self, devices, testbed_name):
-        """Creates a new android testing environment.
-
-        @param devices: The devices on the testbed to use.
-        @param testbed_name: The name for the testbed.
-        """
-        self.devices = devices
-        self.testbed_name = testbed_name
-
-    def install_sl4a_apk(self, force_reinstall=True):
-        """Install sl4a to all provided devices..
-
-        @param force_reinstall: If true the apk will be force to reinstall.
-        """
-        for device in self.devices:
-            adb_utils.install_apk_from_build(
-                device,
-                constants.SL4A_APK,
-                constants.SL4A_ARTIFACT,
-                package_name=constants.SL4A_PACKAGE,
-                force_reinstall=force_reinstall)
-
-    def install_apk(self, apk_info, force_reinstall=True):
-        """Installs an additional apk on all adb devices.
-
-        @param apk_info: A dictionary containing the apk info. This dictionary
-                         should contain the keys:
-                            apk="Name of the apk",
-                            package="Name of the package".
-                            artifact="Name of the artifact", if missing
-                                      the package name is used."
-        @param force_reinstall: If true the apk will be forced to reinstall.
-        """
-        for device in self.devices:
-            adb_utils.install_apk_from_build(
-                device,
-                apk_info['apk'],
-                apk_info.get('artifact') or constants.SL4A_ARTIFACT,
-                package_name=apk_info['package'],
-                force_reinstall=force_reinstall)
-
-
-class ActsContainer(object):
-    """A container for working with acts."""
-
-    def __init__(self, test_station, container_directory, acts_directory=None):
-        """
-        @param test_station: The test station that the container is on.
-        @param container_directory: The directory on the teststation this
-                                    container operates out of.
-        @param acts_directory: The directory within the container that holds
-                               acts. If none then it defaults to
-                               DEFAULT_ACTS_INTERNAL_DIRECTORY.
-        """
-        self.test_station = test_station
-        self.container_directory = container_directory
-
-        if not acts_directory:
-            acts_directory = DEFAULT_ACTS_INTERNAL_DIRECTORY
-
-        if not os.path.isabs(acts_directory):
-            self.acts_directory = os.path.join(container_directory,
-                                               acts_directory)
-        else:
-            self.acts_directory = acts_directory
-
-        self.tests_directory = os.path.join(self.acts_directory, TEST_DIR_NAME)
-        self.framework_directory = os.path.join(self.acts_directory,
-                                                FRAMEWORK_DIR_NAME)
-
-        self.acts_file = os.path.join(self.framework_directory,
-                                      ACTS_EXECUTABLE_IN_FRAMEWORK)
-
-        self.setup_file = os.path.join(self.framework_directory,
-                                       SETUP_FILE_NAME)
-
-        self.log_directory = os.path.join(container_directory,
-                                          LOG_DIR_NAME)
-
-        self.config_location = os.path.join(container_directory,
-                                            CONFIG_DIR_NAME)
-
-        self.acts_file = os.path.join(self.framework_directory,
-                                      ACTS_EXECUTABLE_IN_FRAMEWORK)
-
-        self.working_directory = os.path.join(container_directory,
-                                              CONFIG_DIR_NAME)
-        test_station.run('mkdir %s' % self.working_directory,
-                         ignore_status=True)
-
-    def get_test_paths(self):
-        """Get all test paths within this container.
-
-        Gets all paths that hold tests within the container.
-
-        @returns: A list of paths on the teststation that hold tests.
-        """
-        get_test_paths_result = self.test_station.run('find %s -type d' %
-                                                      self.tests_directory)
-        test_search_dirs = get_test_paths_result.stdout.splitlines()
-        return test_search_dirs
-
-    def get_python_path(self):
-        """Get the python path being used.
-
-        Gets the python path that will be set in the enviroment for this
-        container.
-
-        @returns: A string of the PYTHONPATH enviroment variable to be used.
-        """
-        return '%s:$PYTHONPATH' % self.framework_directory
-
-    def get_enviroment(self):
-        """Gets the enviroment variables to be used for this container.
-
-        @returns: A dictionary of enviroment variables to be used by this
-                  container.
-        """
-        env = {
-            ACTS_TESTPATHS_ENV_KEY: ':'.join(self.get_test_paths()),
-            ACTS_LOGPATH_ENV_KEY: self.log_directory,
-            ACTS_PYTHONPATH_ENV_KEY: self.get_python_path()
-        }
-
-        return env
-
-    def upload_file(self, src, dst):
-        """Uploads a file to be used by the container.
-
-        Uploads a file from the drone to the test staiton to be used by the
-        test container.
-
-        @param src: The source file on the drone. If a relative path is given
-                    it is assumed to exist in CONFIG_FOLDER_LOCATION.
-        @param dst: The destination on the teststation. If a relative path is
-                    given it is assumed that it is within the container.
-
-        @returns: The full path on the teststation.
-        """
-        if not os.path.isabs(src):
-            src = os.path.join(CONFIG_FOLDER_LOCATION, src)
-
-        if not os.path.isabs(dst):
-            dst = os.path.join(self.container_directory, dst)
-
-        path = os.path.dirname(dst)
-        self.test_station.run('mkdir "%s"' % path, ignore_status=True)
-
-        original_dst = dst
-        if os.path.basename(src) == os.path.basename(dst):
-            dst = os.path.dirname(dst)
-
-        self.test_station.send_file(src, dst)
-
-        return original_dst
-
-
-class ActsTestingEnviroment(AndroidTestingEnvironment):
-    """A container for running acts tests with a contained version of acts."""
-
-    def __init__(self, container, devices, testbed_name):
-        """
-        @param container: The acts container to use.
-        @param devices: The list of devices to use.
-        @testbed_name: The name of the testbed being used.
-        """
-        super(ActsTestingEnviroment, self).__init__(devices=devices,
-                                                    testbed_name=testbed_name)
-
-        self.container = container
-
-        self.configs = {}
-        self.campaigns = {}
-
-    def upload_config(self, config_file):
-        """Uploads a config file to the container.
-
-        Uploads a config file to the config folder in the container.
-
-        @param config_file: The config file to upload. This must be a file
-                            within the autotest_config directory under the
-                            CONFIG_FOLDER_LOCATION.
-
-        @returns: The full path of the config on the test staiton.
-        """
-        full_name = os.path.join(CONFIG_DIR_NAME, config_file)
-
-        full_path = self.container.upload_file(full_name, full_name)
-        self.configs[config_file] = full_path
-
-        return full_path
-
-    def upload_campaign(self, campaign_file):
-        """Uploads a campaign file to the container.
-
-        Uploads a campaign file to the campaign folder in the container.
-
-        @param campaign_file: The campaign file to upload. This must be a file
-                              within the autotest_campaign directory under the
-                              CONFIG_FOLDER_LOCATION.
-
-        @returns: The full path of the campaign on the test staiton.
-        """
-        full_name = os.path.join(CAMPAIGN_DIR_NAME, campaign_file)
-
-        full_path = self.container.upload_file(full_name, full_name)
-        self.campaigns[campaign_file] = full_path
-
-        return full_path
-
-    def setup_enviroment(self, python_bin='python'):
-        """Sets up the teststation system enviroment so the container can run.
-
-        Prepares the remote system so that the container can run. This involves
-        uninstalling all versions of acts for the version of python being
-        used and installing all needed dependencies.
-
-        @param python_bin: The python binary to use.
-        """
-        uninstall_command = '%s %s uninstall' % (
-            python_bin, self.container.setup_file)
-        install_deps_command = '%s %s install_deps' % (
-            python_bin, self.container.setup_file)
-
-        self.container.test_station.run(uninstall_command)
-        self.container.test_station.run(install_deps_command)
-
-    def run_test(self,
-                 config,
-                 campaign=None,
-                 test_case=None,
-                 extra_env={},
-                 python_bin='python',
-                 timeout=7200,
-                 additional_cmd_line_params=None):
-        """Runs a test within the container.
-
-        Runs a test within a container using the given settings.
-
-        @param config: The name of the config file to use as the main config.
-                       This should have already been uploaded with
-                       upload_config. The string passed into upload_config
-                       should be used here.
-        @param campaign: The campaign file to use for this test. If none then
-                         test_case is assumed. This file should have already
-                         been uploaded with upload_campaign. The string passed
-                         into upload_campaign should be used here.
-        @param test_case: The test case to run the test with. If none then the
-                          campaign will be used. If multiple are given,
-                          multiple will be run.
-        @param extra_env: Extra enviroment variables to run the test with.
-        @param python_bin: The python binary to execute the test with.
-        @param timeout: How many seconds to wait before timing out.
-        @param additional_cmd_line_params: Adds the ability to add any string
-                                           to the end of the acts.py command
-                                           line string.  This is intended to
-                                           add acts command line flags however
-                                           this is unbounded so it could cause
-                                           errors if incorrectly set.
-
-        @returns: The results of the test run.
-        """
-        if not config in self.configs:
-            # Check if the config has been uploaded and upload if it hasn't
-            self.upload_config(config)
-
-        full_config = self.configs[config]
-
-        if campaign:
-            # When given a campaign check if it's upload.
-            if not campaign in self.campaigns:
-                self.upload_campaign(campaign)
-
-            full_campaign = self.campaigns[campaign]
-        else:
-            full_campaign = None
-
-        full_env = self.container.get_enviroment()
-
-        # Setup environment variables.
-        if extra_env:
-            for k, v in extra_env.items():
-                full_env[k] = extra_env
-
-        logging.info('Using env: %s', full_env)
-        exports = ('export %s=%s' % (k, v) for k, v in full_env.items())
-        env_command = ';'.join(exports)
-
-        # Make sure to execute in the working directory.
-        command_setup = 'cd %s' % self.container.working_directory
-
-        if additional_cmd_line_params:
-            act_base_cmd = '%s %s -c %s -tb %s %s ' % (
-                    python_bin, self.container.acts_file, full_config,
-                    self.testbed_name, additional_cmd_line_params)
-        else:
-            act_base_cmd = '%s %s -c %s -tb %s ' % (
-                    python_bin, self.container.acts_file, full_config,
-                    self.testbed_name)
-
-        # Format the acts command based on what type of test is being run.
-        if test_case and campaign:
-            raise error.TestError(
-                    'campaign and test_file cannot both have a value.')
-        elif test_case:
-            if isinstance(test_case, str):
-                test_case = [test_case]
-            if len(test_case) < 1:
-                raise error.TestError('At least one test case must be given.')
-
-            tc_str = ''
-            for tc in test_case:
-                tc_str = '%s %s' % (tc_str, tc)
-            tc_str = tc_str.strip()
-
-            act_cmd = '%s -tc %s' % (act_base_cmd, tc_str)
-        elif campaign:
-            act_cmd = '%s -tf %s' % (act_base_cmd, full_campaign)
-        else:
-            raise error.TestFail('No tests was specified!')
-
-        # Format all commands into a single command.
-        command_list = [command_setup, env_command, act_cmd]
-        full_command = '; '.join(command_list)
-
-        try:
-            # Run acts on the remote machine.
-            act_result = self.container.test_station.run(full_command,
-                                                         timeout=timeout)
-            excep = None
-        except Exception as e:
-            # Catch any error to store in the results.
-            act_result = None
-            excep = e
-
-        return ActsTestResults(str(test_case) or campaign,
-                               container=self.container,
-                               devices=self.devices,
-                               testbed_name=self.testbed_name,
-                               run_result=act_result,
-                               exception=excep)
-
-
-class ActsTestResults(object):
-    """The packaged results of a test run."""
-    acts_result_to_autotest = {
-        'PASS': 'GOOD',
-        'FAIL': 'FAIL',
-        'UNKNOWN': 'WARN',
-        'SKIP': 'ABORT'
-    }
-
-    def __init__(self,
-                 name,
-                 container,
-                 devices,
-                 testbed_name,
-                 run_result=None,
-                 exception=None):
-        """
-        @param name: A name to identify the test run.
-        @param testbed_name: The name the testbed was run with, if none the
-                             default name of the testbed is used.
-        @param run_result: The raw i/o result of the test run.
-        @param log_directory: The directory that acts logged to.
-        @param exception: An exception that was thrown while running the test.
-        """
-        self.name = name
-        self.run_result = run_result
-        self.exception = exception
-        self.log_directory = container.log_directory
-        self.test_station = container.test_station
-        self.testbed_name = testbed_name
-        self.devices = devices
-
-        self.reported_to = set()
-
-        self.json_results = {}
-        self.results_dir = None
-        if self.log_directory:
-            self.results_dir = os.path.join(self.log_directory,
-                                            self.testbed_name, 'latest')
-            results_file = os.path.join(self.results_dir,
-                                        'test_run_summary.json')
-            cat_log_result = self.test_station.run('cat %s' % results_file,
-                                                   ignore_status=True)
-            if not cat_log_result.exit_status:
-                self.json_results = json.loads(cat_log_result.stdout)
-
-    def log_output(self):
-        """Logs the output of the test."""
-        if self.run_result:
-            logging.debug('ACTS Output:\n%s', self.run_result.stdout)
-
-    def save_test_info(self, test):
-        """Save info about the test.
-
-        @param test: The test to save.
-        """
-        for device in self.devices:
-            device.save_info(test.resultsdir)
-
-    def rethrow_exception(self):
-        """Re-throws the exception thrown during the test."""
-        if self.exception:
-            raise self.exception
-
-    def upload_to_local(self, local_dir):
-        """Saves all acts results to a local directory.
-
-        @param local_dir: The directory on the local machine to save all results
-                          to.
-        """
-        if self.results_dir:
-            self.test_station.get_file(self.results_dir, local_dir)
-
-    def report_to_autotest(self, test):
-        """Reports the results to an autotest test object.
-
-        Reports the results to the test and saves all acts results under the
-        tests results directory.
-
-        @param test: The autotest test object to report to. If this test object
-                     has already recived our report then this call will be
-                     ignored.
-        """
-        if test in self.reported_to:
-            return
-
-        if self.results_dir:
-            self.upload_to_local(test.resultsdir)
-
-        if not 'Results' in self.json_results:
-            return
-
-        results = self.json_results['Results']
-        for result in results:
-            verdict = self.acts_result_to_autotest[result['Result']]
-            details = result['Details']
-            test.job.record(verdict, None, self.name, status=(details or ''))
-
-        self.reported_to.add(test)