Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 1 | # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Dale Curtis | 386eea7 | 2011-09-21 18:43:04 -0700 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 5 | import logging |
Eric Li | a11a045 | 2010-01-07 22:01:58 -0800 | [diff] [blame] | 6 | import os |
Chris Sosa | 3ee5d5c | 2012-02-23 11:18:41 -0800 | [diff] [blame^] | 7 | from autotest_lib.client.common_lib import error, global_config |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 8 | from autotest_lib.server import installable_object, autoserv_parser |
Eric Li | 2eb800f | 2011-04-21 16:52:58 -0700 | [diff] [blame] | 9 | |
| 10 | |
| 11 | config = global_config.global_config |
| 12 | parser = autoserv_parser.autoserv_parser |
| 13 | |
Eric Li | a11a045 | 2010-01-07 22:01:58 -0800 | [diff] [blame] | 14 | |
| 15 | class SiteAutotest(installable_object.InstallableObject): |
| 16 | |
Chris Sosa | 3ee5d5c | 2012-02-23 11:18:41 -0800 | [diff] [blame^] | 17 | def get(self, location=None): |
Eric Li | a11a045 | 2010-01-07 22:01:58 -0800 | [diff] [blame] | 18 | if not location: |
| 19 | location = os.path.join(self.serverdir, '../client') |
| 20 | location = os.path.abspath(location) |
| 21 | installable_object.InstallableObject.get(self, location) |
| 22 | self.got = True |
| 23 | |
Eric Li | c7444bd | 2011-02-15 17:12:10 -0800 | [diff] [blame] | 24 | |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 25 | def _get_fetch_location_from_host_attribute(self): |
| 26 | """Get repo to use for packages from host attribute, if possible. |
| 27 | |
| 28 | Hosts are tagged with an attribute containing the URL |
| 29 | from which to source packages when running a test on that host. |
| 30 | If self.host is set, attempt to look this attribute up by calling out |
| 31 | to the AFE. |
| 32 | |
| 33 | @returns value of the 'job_repo_url' host attribute, if present. |
| 34 | """ |
| 35 | try: |
| 36 | from autotest_lib.server import frontend |
| 37 | if self.host: |
| 38 | afe = frontend.AFE(debug=False) |
| 39 | hosts = afe.get_hosts(hostname=self.host.hostname) |
| 40 | if 'job_repo_url' in hosts[0].attributes: |
| 41 | return hosts[0].attributes['job_repo_url'] |
Chris Masone | 2e20498 | 2012-02-13 13:26:13 -0800 | [diff] [blame] | 42 | logging.warning("No job_repo_url for %s", self.host) |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 43 | except ImportError: |
Chris Masone | 2e20498 | 2012-02-13 13:26:13 -0800 | [diff] [blame] | 44 | logging.warning('Not attempting to look for job_repo_url') |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 45 | pass |
| 46 | return None |
| 47 | |
| 48 | |
Eric Li | 2eb800f | 2011-04-21 16:52:58 -0700 | [diff] [blame] | 49 | def get_fetch_location(self): |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 50 | """Generate list of locations where autotest can look for packages. |
| 51 | |
| 52 | Old n' busted: Autotest packages are always stored at a URL that can |
| 53 | be derived from the one passed via the voodoo magic --image argument. |
| 54 | New hotness: Hosts are tagged with an attribute containing the URL |
| 55 | from which to source packages when running a test on that host. |
| 56 | |
| 57 | @returns the list of candidate locations to check for packages. |
| 58 | """ |
Dale Curtis | 386eea7 | 2011-09-21 18:43:04 -0700 | [diff] [blame] | 59 | repos = super(SiteAutotest, self).get_fetch_location() |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 60 | |
Dale Curtis | 386eea7 | 2011-09-21 18:43:04 -0700 | [diff] [blame] | 61 | if parser.options.image: |
Chris Masone | be78eb0 | 2012-02-23 14:28:19 -0800 | [diff] [blame] | 62 | # The old way. |
Dale Curtis | 386eea7 | 2011-09-21 18:43:04 -0700 | [diff] [blame] | 63 | # Add our new repo to the end, the package manager will later |
| 64 | # reverse the list of repositories resulting in ours being first. |
| 65 | repos.append(parser.options.image.replace( |
| 66 | 'update', 'static/archive').rstrip('/') + '/autotest') |
Chris Masone | be78eb0 | 2012-02-23 14:28:19 -0800 | [diff] [blame] | 67 | else: |
| 68 | # The new way. |
| 69 | found_repo = self._get_fetch_location_from_host_attribute() |
| 70 | if found_repo is not None: |
| 71 | # Add our new repo to the end, the package manager will |
| 72 | # later reverse the list of repositories resulting in ours |
| 73 | # being first |
| 74 | repos.append(found_repo) |
Eric Li | 2eb800f | 2011-04-21 16:52:58 -0700 | [diff] [blame] | 75 | |
Dale Curtis | 386eea7 | 2011-09-21 18:43:04 -0700 | [diff] [blame] | 76 | return repos |
Eric Li | 2eb800f | 2011-04-21 16:52:58 -0700 | [diff] [blame] | 77 | |
| 78 | |
Chris Masone | 8abb6fc | 2012-01-31 09:27:36 -0800 | [diff] [blame] | 79 | def install(self, host=None, autodir=None): |
| 80 | """Install autotest. If |host| is not None, stores it in |self.host|. |
| 81 | |
| 82 | @param host A Host instance on which autotest will be installed |
| 83 | @param autodir Location on the remote host to install to |
| 84 | """ |
| 85 | if host: |
| 86 | self.host = host |
| 87 | |
| 88 | super(SiteAutotest, self).install(host=host, autodir=autodir) |
| 89 | |
| 90 | |
Chris Sosa | 3ee5d5c | 2012-02-23 11:18:41 -0800 | [diff] [blame^] | 91 | class SiteClientLogger(object): |
| 92 | """Overrides default client logger to allow for using a local package cache. |
| 93 | """ |
| 94 | |
| 95 | def _process_line(self, line): |
| 96 | """Returns the package checksum file if it exists.""" |
| 97 | logging.debug(line) |
| 98 | fetch_package_match = self.fetch_package_parser.search(line) |
| 99 | if fetch_package_match: |
| 100 | pkg_name, dest_path, fifo_path = fetch_package_match.groups() |
| 101 | serve_packages = global_config.global_config.get_config_value( |
| 102 | "PACKAGES", "serve_packages_from_autoserv", type=bool) |
| 103 | if serve_packages and pkg_name == 'packages.checksum': |
| 104 | package_served = False |
| 105 | try: |
| 106 | checksum_file = os.path.join( |
| 107 | self.job.pkgmgr.pkgmgr_dir, 'packages', pkg_name) |
| 108 | if os.path.exists(checksum_file): |
| 109 | self.host.send_file(checksum_file, dest_path) |
| 110 | package_served = True |
| 111 | except error.AutoservRunError: |
| 112 | msg = "Package checksum file not found, continuing anyway" |
| 113 | logging.exception(msg) |
| 114 | |
| 115 | if package_served: |
| 116 | try: |
| 117 | # When fetching a package, the client expects to be |
| 118 | # notified when the fetching is complete. Autotest |
| 119 | # does this pushing a B to a fifo queue to the client. |
| 120 | self.host.run("echo B > %s" % fifo_path) |
| 121 | except error.AutoservRunError: |
| 122 | msg = "Checksum installation failed, continuing anyway" |
| 123 | logging.exception(msg) |
| 124 | finally: |
| 125 | return |
| 126 | |
| 127 | # Fall through to process the line using the default method. |
| 128 | super(SiteClientLogger, self)._process_line(line) |
| 129 | |
| 130 | |
| 131 | def _send_tarball(self, pkg_name, remote_dest): |
| 132 | """Uses tarballs in package manager by default.""" |
| 133 | try: |
| 134 | server_package = os.path.join(self.job.pkgmgr.pkgmgr_dir, |
| 135 | 'packages', pkg_name) |
| 136 | if os.path.exists(server_package): |
| 137 | self.host.send_file(server_package, remote_dest) |
| 138 | return |
| 139 | |
| 140 | except error.AutoservRunError: |
| 141 | msg = ("Package %s could not be sent from the package cache." % |
| 142 | pkg_name) |
| 143 | logging.exception(msg) |
| 144 | |
| 145 | # Fall through to send tarball the default method. |
| 146 | super(SiteClientLogger, self)._send_tarball(pkg_name, remote_dest) |
| 147 | |
| 148 | |
Eric Li | c7444bd | 2011-02-15 17:12:10 -0800 | [diff] [blame] | 149 | class _SiteRun(object): |
| 150 | pass |