18abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2386eea7066cbd9a35599e76eee56b2c98ecec9a1Dale Curtis# Use of this source code is governed by a BSD-style license that can be
3386eea7066cbd9a35599e76eee56b2c98ecec9a1Dale Curtis# found in the LICENSE file.
4386eea7066cbd9a35599e76eee56b2c98ecec9a1Dale Curtis
58abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masoneimport logging
6a11a045e56301bea09f54581c5ec5e08d328d03eEric Liimport os
7809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wileyimport tempfile
84f34170dbb70080a56de88dc13859b3a7ffffb0aAlex Millerimport urllib2
9809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley
103ee5d5c574d4e6d397aff36136101c657664c26bChris Sosafrom autotest_lib.client.common_lib import error, global_config
11eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalskifrom autotest_lib.client.common_lib.cros import dev_server
128abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masonefrom autotest_lib.server import installable_object, autoserv_parser
1382997b9a9791105d81c9db14e75ed14946f78f94Dan Shifrom autotest_lib.server import utils as server_utils
14eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalskifrom autotest_lib.server.cros.dynamic_suite import tools
1544e4d6ce5a7c38451c25d35b307b35338606091fChris Masonefrom autotest_lib.server.cros.dynamic_suite.constants import JOB_REPO_URL
162eb800f7b1895983bbbd66b231101a5ade6bffabEric Li
172eb800f7b1895983bbbd66b231101a5ade6bffabEric Li
1844e4d6ce5a7c38451c25d35b307b35338606091fChris Masone_CONFIG = global_config.global_config
1944e4d6ce5a7c38451c25d35b307b35338606091fChris Masone_PARSER = autoserv_parser.autoserv_parser
202eb800f7b1895983bbbd66b231101a5ade6bffabEric Li
21a11a045e56301bea09f54581c5ec5e08d328d03eEric Li
22a11a045e56301bea09f54581c5ec5e08d328d03eEric Liclass SiteAutotest(installable_object.InstallableObject):
23b669cbdea7f4bfc9cbfcea48d9cf9ce62f0deff5Dan Shi    """Site implementation of Autotest."""
24a11a045e56301bea09f54581c5ec5e08d328d03eEric Li
253ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa    def get(self, location=None):
26a11a045e56301bea09f54581c5ec5e08d328d03eEric Li        if not location:
27a11a045e56301bea09f54581c5ec5e08d328d03eEric Li            location = os.path.join(self.serverdir, '../client')
28a11a045e56301bea09f54581c5ec5e08d328d03eEric Li            location = os.path.abspath(location)
29a11a045e56301bea09f54581c5ec5e08d328d03eEric Li        installable_object.InstallableObject.get(self, location)
30a11a045e56301bea09f54581c5ec5e08d328d03eEric Li        self.got = True
31a11a045e56301bea09f54581c5ec5e08d328d03eEric Li
32c7444bd374d25cdcef5f7abaf61d6406ab3a95bfEric Li
338abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone    def _get_fetch_location_from_host_attribute(self):
348abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        """Get repo to use for packages from host attribute, if possible.
358abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
368abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        Hosts are tagged with an attribute containing the URL
378abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        from which to source packages when running a test on that host.
388abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        If self.host is set, attempt to look this attribute up by calling out
398abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        to the AFE.
408abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
418abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        @returns value of the 'job_repo_url' host attribute, if present.
428abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        """
438abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        try:
448abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone            from autotest_lib.server import frontend
458abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone            if self.host:
468abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone                afe = frontend.AFE(debug=False)
478abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone                hosts = afe.get_hosts(hostname=self.host.hostname)
4844e4d6ce5a7c38451c25d35b307b35338606091fChris Masone                if hosts and JOB_REPO_URL in hosts[0].attributes:
4944e4d6ce5a7c38451c25d35b307b35338606091fChris Masone                    return hosts[0].attributes[JOB_REPO_URL]
5044e4d6ce5a7c38451c25d35b307b35338606091fChris Masone                logging.warning("No %s for %s", JOB_REPO_URL, self.host)
514f34170dbb70080a56de88dc13859b3a7ffffb0aAlex Miller        except (ImportError, urllib2.URLError):
5244e4d6ce5a7c38451c25d35b307b35338606091fChris Masone            logging.warning('Not attempting to look for %s', JOB_REPO_URL)
538abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone            pass
548abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        return None
558abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
568abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
572eb800f7b1895983bbbd66b231101a5ade6bffabEric Li    def get_fetch_location(self):
588abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        """Generate list of locations where autotest can look for packages.
598abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
608abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        Old n' busted: Autotest packages are always stored at a URL that can
618abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        be derived from the one passed via the voodoo magic --image argument.
628abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        New hotness: Hosts are tagged with an attribute containing the URL
638abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        from which to source packages when running a test on that host.
648abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
658abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        @returns the list of candidate locations to check for packages.
668abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        """
67386eea7066cbd9a35599e76eee56b2c98ecec9a1Dale Curtis        repos = super(SiteAutotest, self).get_fetch_location()
688abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
6944e4d6ce5a7c38451c25d35b307b35338606091fChris Masone        if _PARSER.options.image:
70eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            image_opt = _PARSER.options.image
71eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            if image_opt.startswith('http://'):
72eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # A devserver HTTP url was specified, set that as the repo_url.
73eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                repos.append(image_opt.replace(
7403eaad90a2fabae6f3253e9acde8859681237610joychen                    'update', 'static').rstrip('/') + '/autotest')
75eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            else:
76eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # An image_name like stumpy-release/R27-3437.0.0 was specified,
77eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # set this as the repo_url for the host. If an AFE is not being
78eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # run, this will ensure that the installed build uses the
79eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # associated artifacts for the test specified when running
80eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # autoserv with --image. However, any subsequent tests run on
81eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # the host will no longer have the context of the image option
82eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # and will revert back to utilizing test code/artifacts that are
83eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                # currently present in the users source checkout.
84eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                devserver_url = dev_server.ImageServer.resolve(image_opt).url()
85eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                repo_url = tools.get_package_url(devserver_url, image_opt)
86eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski                repos.append(repo_url)
8782997b9a9791105d81c9db14e75ed14946f78f94Dan Shi        elif not server_utils.is_inside_chroot():
8882997b9a9791105d81c9db14e75ed14946f78f94Dan Shi            # Only try to get fetch location from host attribute if the test
8982997b9a9791105d81c9db14e75ed14946f78f94Dan Shi            # is not running inside chroot.
90eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            # No --image option was specified, look for the repo url via
91eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            # the host attribute. If we are not running with a full AFE
92eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            # autoserv will fall back to serving packages itself from whatever
93eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            # source version it is sync'd to rather than using the proper
94eadbf7098c7cf810aaaf88791b1d59b786407e9fScott Zawalski            # artifacts for the build on the host.
95be78eb08bef7768cd9e2883f454760d96f60a704Chris Masone            found_repo = self._get_fetch_location_from_host_attribute()
96be78eb08bef7768cd9e2883f454760d96f60a704Chris Masone            if found_repo is not None:
97be78eb08bef7768cd9e2883f454760d96f60a704Chris Masone                # Add our new repo to the end, the package manager will
98be78eb08bef7768cd9e2883f454760d96f60a704Chris Masone                # later reverse the list of repositories resulting in ours
99be78eb08bef7768cd9e2883f454760d96f60a704Chris Masone                # being first
100be78eb08bef7768cd9e2883f454760d96f60a704Chris Masone                repos.append(found_repo)
101386eea7066cbd9a35599e76eee56b2c98ecec9a1Dale Curtis
102386eea7066cbd9a35599e76eee56b2c98ecec9a1Dale Curtis        return repos
1032eb800f7b1895983bbbd66b231101a5ade6bffabEric Li
1042eb800f7b1895983bbbd66b231101a5ade6bffabEric Li
105b669cbdea7f4bfc9cbfcea48d9cf9ce62f0deff5Dan Shi    def install(self, host=None, autodir=None, use_packaging=True):
1068abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        """Install autotest.  If |host| is not None, stores it in |self.host|.
1078abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
1088abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        @param host A Host instance on which autotest will be installed
1098abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        @param autodir Location on the remote host to install to
110b669cbdea7f4bfc9cbfcea48d9cf9ce62f0deff5Dan Shi        @param use_packaging Enable install modes that use the packaging system.
111b669cbdea7f4bfc9cbfcea48d9cf9ce62f0deff5Dan Shi
1128abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        """
1138abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone        if host:
1148abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone            self.host = host
1158abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
116b669cbdea7f4bfc9cbfcea48d9cf9ce62f0deff5Dan Shi        super(SiteAutotest, self).install(host=host, autodir=autodir,
117b669cbdea7f4bfc9cbfcea48d9cf9ce62f0deff5Dan Shi                                          use_packaging=use_packaging)
1188abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
1198abb6fcf1768a1e6181c74ba384edcdd0620591fChris Masone
120809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley    def _install(self, host=None, autodir=None, use_autoserv=True,
121809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                 use_packaging=True):
122809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        """
123809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        Install autotest.  If get() was not called previously, an
124809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        attempt will be made to install from the autotest svn
125809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        repository.
126809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley
127809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        @param host A Host instance on which autotest will be installed
128809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        @param autodir Location on the remote host to install to
129809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        @param use_autoserv Enable install modes that depend on the client
130809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley            running with the autoserv harness
131809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        @param use_packaging Enable install modes that use the packaging system
132809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley
133809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        @exception AutoservError if a tarball was not specified and
134809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley            the target host does not have svn installed in its path
135809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        """
136809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        # TODO(milleral): http://crbug.com/258161
137809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        super(SiteAutotest, self)._install(host, autodir, use_autoserv,
138809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                                           use_packaging)
139809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        # Send over the most recent global_config.ini after installation if one
140809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        # is available.
141809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        # This code is a bit duplicated from
142809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        # _BaseRun._create_client_config_file, but oh well.
143809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley        if self.installed and self.source_material:
144809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley            logging.info('Installing updated global_config.ini.')
145809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley            destination = os.path.join(self.host.get_autodir(),
146809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                                       'global_config.ini')
147809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley            with tempfile.NamedTemporaryFile() as client_config:
148809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                config = global_config.global_config
149809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                client_section = config.get_section_values('CLIENT')
150809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                client_section.write(client_config)
151809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                client_config.flush()
152809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley                self.host.send_file(client_config.name, destination)
153809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley
154809301c57ccea919f37c067cb261d8dc0e89ed3dChristopher Wiley
155f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa    def run_static_method(self, module, method, results_dir='.', host=None,
156f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa                          *args):
157f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        """Runs a non-instance method with |args| from |module| on the client.
158f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa
159f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        This method runs a static/class/module autotest method on the client.
160f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        For example:
161f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa          run_static_method("autotest_lib.client.cros.cros_ui", "reboot")
162f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa
163f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        Will run autotest_lib.client.cros.cros_ui.reboot() on the client.
164f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa
165f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        @param module: module name as you would refer to it when importing in a
166f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa            control file. e.g. autotest_lib.client.common_lib.module_name.
167f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        @param method: the method you want to call.
168f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        @param results_dir: A str path where the results should be stored
169f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa            on the local filesystem.
170f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        @param host: A Host instance on which the control file should
171f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa            be run.
172f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        @param args: args to pass to the method.
173f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        """
174f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        control = "\n".join(["import %s" % module,
175f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa                             "%s.%s(%s)\n" % (module, method,
176f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa                                              ','.join(map(repr, args)))])
177f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa        self.run(control, results_dir=results_dir, host=host)
178f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa
179f4d43ff1254ac68ebc54442da8ad2821bd16d6cbChris Sosa
1803ee5d5c574d4e6d397aff36136101c657664c26bChris Sosaclass SiteClientLogger(object):
1813ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa    """Overrides default client logger to allow for using a local package cache.
1823ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa    """
1833ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
1843ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa    def _process_line(self, line):
1853ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        """Returns the package checksum file if it exists."""
1863ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        logging.debug(line)
1873ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        fetch_package_match = self.fetch_package_parser.search(line)
1883ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        if fetch_package_match:
1893ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa            pkg_name, dest_path, fifo_path = fetch_package_match.groups()
19044e4d6ce5a7c38451c25d35b307b35338606091fChris Masone            serve_packages = _CONFIG.get_config_value(
1913ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                "PACKAGES", "serve_packages_from_autoserv", type=bool)
1923ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa            if serve_packages and pkg_name == 'packages.checksum':
1933ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                try:
1943ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                    checksum_file = os.path.join(
1953ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                        self.job.pkgmgr.pkgmgr_dir, 'packages', pkg_name)
1963ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                    if os.path.exists(checksum_file):
1973ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                        self.host.send_file(checksum_file, dest_path)
1983ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                except error.AutoservRunError:
1993ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                    msg = "Package checksum file not found, continuing anyway"
2003ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                    logging.exception(msg)
2013ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2022cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                try:
2032cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    # When fetching a package, the client expects to be
2042cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    # notified when the fetching is complete. Autotest
2052cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    # does this pushing a B to a fifo queue to the client.
2062cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    self.host.run("echo B > %s" % fifo_path)
2072cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                except error.AutoservRunError:
2082cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    msg = "Checksum installation failed, continuing anyway"
2092cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    logging.exception(msg)
2102cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                finally:
2112cc4da09caabc67f97e8038f7bc7e124bf468230Chris Sosa                    return
2123ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2133ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        # Fall through to process the line using the default method.
2143ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        super(SiteClientLogger, self)._process_line(line)
2153ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2163ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2173ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa    def _send_tarball(self, pkg_name, remote_dest):
2183ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        """Uses tarballs in package manager by default."""
2193ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        try:
2203ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa            server_package = os.path.join(self.job.pkgmgr.pkgmgr_dir,
2213ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                                          'packages', pkg_name)
2223ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa            if os.path.exists(server_package):
2233ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa              self.host.send_file(server_package, remote_dest)
2243ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa              return
2253ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2263ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        except error.AutoservRunError:
2273ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa            msg = ("Package %s could not be sent from the package cache." %
2283ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa                   pkg_name)
2293ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa            logging.exception(msg)
2303ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2313ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        # Fall through to send tarball the default method.
2323ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa        super(SiteClientLogger, self)._send_tarball(pkg_name, remote_dest)
2333ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
2343ee5d5c574d4e6d397aff36136101c657664c26bChris Sosa
235c7444bd374d25cdcef5f7abaf61d6406ab3a95bfEric Liclass _SiteRun(object):
236c7444bd374d25cdcef5f7abaf61d6406ab3a95bfEric Li    pass
237