OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # |
| 3 # Copyright (c) 2010 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 """Wrapper for tests that are run on builders.""" |
| 8 |
| 9 import fileinput |
| 10 import optparse |
| 11 import os |
| 12 import sys |
| 13 import urllib |
| 14 |
| 15 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
| 16 from cros_build_lib import Info, RunCommand, ReinterpretPathForChroot |
| 17 |
| 18 _IMAGE_TO_EXTRACT = 'chromiumos_test_image.bin' |
| 19 |
| 20 |
| 21 def ModifyBootDesc(download_folder, redirect_file=None): |
| 22 """Modifies the boot description of a downloaded image to work with path. |
| 23 |
| 24 The default boot.desc from another system is specific to the directory |
| 25 it was created in. This modifies the boot description to be compatiable |
| 26 with the download folder. |
| 27 |
| 28 Args: |
| 29 download_folder: Absoulte path to the download folder. |
| 30 redirect_file: For testing. Where to copy new boot desc. |
| 31 """ |
| 32 boot_desc_path = os.path.join(download_folder, 'boot.desc') |
| 33 in_chroot_folder = ReinterpretPathForChroot(download_folder) |
| 34 |
| 35 for line in fileinput.input(boot_desc_path, inplace=1): |
| 36 # Has to be done here to get changes to sys.stdout from fileinput.input. |
| 37 if not redirect_file: |
| 38 redirect_file = sys.stdout |
| 39 split_line = line.split('=') |
| 40 if len(split_line) > 1: |
| 41 var_part = split_line[0] |
| 42 potential_path = split_line[1].replace('"', '').strip() |
| 43 |
| 44 if potential_path.startswith('/home') and not 'output_dir' in var_part: |
| 45 new_path = os.path.join(in_chroot_folder, |
| 46 os.path.basename(potential_path)) |
| 47 new_line = '%s="%s"' % (var_part, new_path) |
| 48 Info('Replacing line %s with %s' % (line, new_line)) |
| 49 redirect_file.write('%s\n' % new_line) |
| 50 continue |
| 51 elif 'output_dir' in var_part: |
| 52 # Special case for output_dir. |
| 53 new_line = '%s="%s"' % (var_part, in_chroot_folder) |
| 54 Info('Replacing line %s with %s' % (line, new_line)) |
| 55 redirect_file.write('%s\n' % new_line) |
| 56 continue |
| 57 |
| 58 # Line does not need to be modified. |
| 59 redirect_file.write(line) |
| 60 |
| 61 fileinput.close() |
| 62 |
| 63 |
| 64 def GetLatestZipUrl(board, channel, latest_url_base, zip_server_base): |
| 65 """Returns the url of the latest image zip for the given arguments. |
| 66 |
| 67 Args: |
| 68 board: board for the image zip. |
| 69 channel: channel for the image zip. |
| 70 latest_url_base: base url for latest links. |
| 71 zip_server_base: base url for zipped images. |
| 72 """ |
| 73 # Grab the latest image info. |
| 74 latest_file_url = os.path.join(latest_url_base, channel, |
| 75 'LATEST-%s' % board) |
| 76 latest_image_file = urllib.urlopen(latest_file_url) |
| 77 latest_image = latest_image_file.read() |
| 78 latest_image_file.close() |
| 79 |
| 80 # Convert bin.gz into zip. |
| 81 latest_image = latest_image.replace('.bin.gz', '.zip') |
| 82 version = latest_image.split('-')[1] |
| 83 zip_base = os.path.join(zip_server_base, channel, board) |
| 84 return os.path.join(zip_base, version, latest_image) |
| 85 |
| 86 |
| 87 def GrabZipAndExtractImage(zip_url, download_folder, image_name) : |
| 88 """Downloads the zip and extracts the given image. |
| 89 |
| 90 Doesn't re-download if matching version found already in download folder. |
| 91 Args: |
| 92 zip_url - url for the image. |
| 93 download_folder - download folder to store zip file and extracted images. |
| 94 image_name - name of the image to extract from the zip file. |
| 95 """ |
| 96 zip_path = os.path.join(download_folder, 'image.zip') |
| 97 versioned_url_path = os.path.join(download_folder, 'download_url') |
| 98 found_cached = False |
| 99 |
| 100 if os.path.exists(versioned_url_path): |
| 101 fh = open(versioned_url_path) |
| 102 version_url = fh.read() |
| 103 fh.close() |
| 104 |
| 105 if version_url == zip_url and os.path.exists(os.path.join(download_folder, |
| 106 image_name)): |
| 107 Info('Using cached %s' % image_name) |
| 108 found_cached = True |
| 109 |
| 110 if not found_cached: |
| 111 Info('Downloading %s' % zip_url) |
| 112 RunCommand(['rm', '-rf', download_folder], print_cmd=False) |
| 113 os.mkdir(download_folder) |
| 114 urllib.urlretrieve(zip_url, zip_path) |
| 115 |
| 116 # Using unzip because python implemented unzip in native python so |
| 117 # extraction is really slow. |
| 118 Info('Unzipping image %s' % image_name) |
| 119 RunCommand(['unzip', '-d', download_folder, zip_path], |
| 120 print_cmd=False, error_message='Failed to download %s' % zip_url) |
| 121 |
| 122 ModifyBootDesc(download_folder) |
| 123 |
| 124 # Put url in version file so we don't have to do this every time. |
| 125 fh = open(versioned_url_path, 'w+') |
| 126 fh.write(zip_url) |
| 127 fh.close() |
| 128 |
| 129 |
| 130 def RunAUTestHarness(board, channel, latest_url_base, zip_server_base): |
| 131 """Runs the auto update test harness. |
| 132 |
| 133 The auto update test harness encapsulates testing the auto-update mechanism |
| 134 for the latest image against the latest official image from the channel. This |
| 135 also tests images with suite_Smoke (built-in as part of its verification |
| 136 process). |
| 137 |
| 138 Args: |
| 139 board: the board for the latest image. |
| 140 channel: the channel to run the au test harness against. |
| 141 latest_url_base: base url for getting latest links. |
| 142 zip_server_base: base url for zipped images. |
| 143 """ |
| 144 crosutils_root = os.path.join(os.path.dirname(__file__), '..') |
| 145 download_folder = os.path.abspath('latest_download') |
| 146 zip_url = GetLatestZipUrl(board, channel, latest_url_base, zip_server_base) |
| 147 GrabZipAndExtractImage(zip_url, download_folder, _IMAGE_TO_EXTRACT) |
| 148 |
| 149 # Tests go here. |
| 150 latest_image = RunCommand(['./get_latest_image.sh', '--board=%s' % board], |
| 151 cwd=crosutils_root, redirect_stdout=True, |
| 152 print_cmd=True) |
| 153 |
| 154 RunCommand(['bin/cros_au_test_harness', |
| 155 '--base_image=%s' % os.path.join(download_folder, |
| 156 _IMAGE_TO_EXTRACT), |
| 157 '--target_image=%s' % latest_image, |
| 158 '--board=%s' % board], cwd=crosutils_root) |
| 159 |
| 160 |
| 161 def main(): |
| 162 parser = optparse.OptionParser() |
| 163 parser.add_option('-b', '--board', |
| 164 help='board for the image to compare against.') |
| 165 parser.add_option('-c', '--channel', |
| 166 help='channel for the image to compare against.') |
| 167 parser.add_option('-l', '--latestbase', |
| 168 help='Base url for latest links.') |
| 169 parser.add_option('-z', '--zipbase', |
| 170 help='Base url for hosted images.') |
| 171 # Set the usage to include flags. |
| 172 parser.set_usage(parser.format_help()) |
| 173 (options, args) = parser.parse_args() |
| 174 |
| 175 if args: |
| 176 parser.error('Extra args found %s.' % args) |
| 177 |
| 178 if not options.board: |
| 179 parser.error('Need board for image to compare against.') |
| 180 |
| 181 if not options.channel: |
| 182 parser.error('Need channel for image to compare against.') |
| 183 |
| 184 if not options.latestbase: |
| 185 parser.error('Need latest url base to get images.') |
| 186 |
| 187 if not options.zipbase: |
| 188 parser.error('Need zip url base to get images.') |
| 189 |
| 190 RunAUTestHarness(options.board, options.channel, options.latestbase, |
| 191 options.zipbase) |
| 192 |
| 193 |
| 194 if __name__ == '__main__': |
| 195 main() |
OLD | NEW |