| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Wrapper for tests that are run on builders.""" | 7 """Wrapper for tests that are run on builders.""" |
| 8 | 8 |
| 9 import fileinput | 9 import fileinput |
| 10 import optparse | 10 import optparse |
| 11 import os | 11 import os |
| 12 import re |
| 12 import sys | 13 import sys |
| 13 import traceback | 14 import traceback |
| 14 import urllib | 15 import urllib |
| 16 import HTMLParser |
| 15 | 17 |
| 16 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 18 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
| 17 from cros_build_lib import Info, RunCommand, ReinterpretPathForChroot | 19 from cros_build_lib import Info |
| 20 from cros_build_lib import ReinterpretPathForChroot |
| 21 from cros_build_lib import RunCommand |
| 22 from cros_build_lib import Warning |
| 18 | 23 |
| 19 _IMAGE_TO_EXTRACT = 'chromiumos_test_image.bin' | 24 _IMAGE_TO_EXTRACT = 'chromiumos_test_image.bin' |
| 20 | 25 |
| 26 class HTMLDirectoryParser(HTMLParser.HTMLParser): |
| 27 """HTMLParser for parsing the default apache file index.""" |
| 28 |
| 29 def __init__(self, regex): |
| 30 HTMLParser.HTMLParser.__init__(self) |
| 31 self.regex_object = re.compile(regex) |
| 32 self.link_list = [] |
| 33 |
| 34 def handle_starttag(self, tag, attrs): |
| 35 """Overrides from HTMLParser and is called at the start of every tag. |
| 36 |
| 37 This implementation grabs attributes from links (i.e. <a ... > </a> |
| 38 and adds the target from href=<target> if the <target> matches the |
| 39 regex given at the start. |
| 40 """ |
| 41 if not tag.lower() == 'a': |
| 42 return |
| 43 |
| 44 for attr in attrs: |
| 45 if not attr[0].lower() == 'href': |
| 46 continue |
| 47 |
| 48 match = self.regex_object.match(attr[1]) |
| 49 if match: |
| 50 self.link_list.append(match.group(0).rstrip('/')) |
| 51 |
| 21 | 52 |
| 22 def ModifyBootDesc(download_folder, redirect_file=None): | 53 def ModifyBootDesc(download_folder, redirect_file=None): |
| 23 """Modifies the boot description of a downloaded image to work with path. | 54 """Modifies the boot description of a downloaded image to work with path. |
| 24 | 55 |
| 25 The default boot.desc from another system is specific to the directory | 56 The default boot.desc from another system is specific to the directory |
| 26 it was created in. This modifies the boot description to be compatiable | 57 it was created in. This modifies the boot description to be compatiable |
| 27 with the download folder. | 58 with the download folder. |
| 28 | 59 |
| 29 Args: | 60 Args: |
| 30 download_folder: Absoulte path to the download folder. | 61 download_folder: Absoulte path to the download folder. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 55 Info('Replacing line %s with %s' % (line, new_line)) | 86 Info('Replacing line %s with %s' % (line, new_line)) |
| 56 redirect_file.write('%s\n' % new_line) | 87 redirect_file.write('%s\n' % new_line) |
| 57 continue | 88 continue |
| 58 | 89 |
| 59 # Line does not need to be modified. | 90 # Line does not need to be modified. |
| 60 redirect_file.write(line) | 91 redirect_file.write(line) |
| 61 | 92 |
| 62 fileinput.close() | 93 fileinput.close() |
| 63 | 94 |
| 64 | 95 |
| 96 def GetLatestLinkFromPage(url, regex): |
| 97 """Returns the latest link from the given url that matches regex. |
| 98 |
| 99 Args: |
| 100 url: Url to download and parse. |
| 101 regex: Regular expression to match links against. |
| 102 """ |
| 103 url_file = urllib.urlopen(url) |
| 104 url_html = url_file.read() |
| 105 url_file.close() |
| 106 |
| 107 # Parses links with versions embedded. |
| 108 url_parser = HTMLDirectoryParser(regex=regex) |
| 109 url_parser.feed(url_html) |
| 110 return max(url_parser.link_list) |
| 111 |
| 112 |
| 113 def GetNewestLinkFromZipBase(board, channel, zip_server_base): |
| 114 """Returns the url to the newest image from the zip server. |
| 115 |
| 116 Args: |
| 117 board: board for the image zip. |
| 118 channel: channel for the image zip. |
| 119 zip_server_base: base url for zipped images. |
| 120 """ |
| 121 zip_base = os.path.join(zip_server_base, channel, board) |
| 122 latest_version = GetLatestLinkFromPage(zip_base, '\d+\.\d+\.\d+\.\d+/') |
| 123 |
| 124 zip_dir = os.path.join(zip_base, latest_version) |
| 125 zip_name = GetLatestLinkFromPage(zip_dir, |
| 126 'ChromeOS-\d+\.\d+\.\d+\.\d+-.*\.zip') |
| 127 return os.path.join(zip_dir, zip_name) |
| 128 |
| 129 |
| 65 def GetLatestZipUrl(board, channel, latest_url_base, zip_server_base): | 130 def GetLatestZipUrl(board, channel, latest_url_base, zip_server_base): |
| 66 """Returns the url of the latest image zip for the given arguments. | 131 """Returns the url of the latest image zip for the given arguments. |
| 67 | 132 |
| 68 Args: | 133 Args: |
| 69 board: board for the image zip. | 134 board: board for the image zip. |
| 70 channel: channel for the image zip. | 135 channel: channel for the image zip. |
| 71 latest_url_base: base url for latest links. | 136 latest_url_base: base url for latest links. |
| 72 zip_server_base: base url for zipped images. | 137 zip_server_base: base url for zipped images. |
| 73 """ | 138 """ |
| 74 # Grab the latest image info. | 139 if latest_url_base: |
| 75 latest_file_url = os.path.join(latest_url_base, channel, | 140 try: |
| 76 'LATEST-%s' % board) | 141 # Grab the latest image info. |
| 77 latest_image_file = urllib.urlopen(latest_file_url) | 142 latest_file_url = os.path.join(latest_url_base, channel, |
| 78 latest_image = latest_image_file.read() | 143 'LATEST-%s' % board) |
| 79 latest_image_file.close() | 144 latest_image_file = urllib.urlopen(latest_file_url) |
| 145 latest_image = latest_image_file.read() |
| 146 latest_image_file.close() |
| 147 # Convert bin.gz into zip. |
| 148 latest_image = latest_image.replace('.bin.gz', '.zip') |
| 149 version = latest_image.split('-')[1] |
| 150 zip_base = os.path.join(zip_server_base, channel, board) |
| 151 return os.path.join(zip_base, version, latest_image) |
| 152 except IOError: |
| 153 Warning(('Could not use latest link provided, defaulting to parsing' |
| 154 ' latest from zip url base.')) |
| 80 | 155 |
| 81 # Convert bin.gz into zip. | 156 return GetNewestLinkFromZipBase(board, channel, zip_server_base) |
| 82 latest_image = latest_image.replace('.bin.gz', '.zip') | |
| 83 version = latest_image.split('-')[1] | |
| 84 zip_base = os.path.join(zip_server_base, channel, board) | |
| 85 return os.path.join(zip_base, version, latest_image) | |
| 86 | 157 |
| 87 | 158 |
| 88 def GrabZipAndExtractImage(zip_url, download_folder, image_name) : | 159 def GrabZipAndExtractImage(zip_url, download_folder, image_name) : |
| 89 """Downloads the zip and extracts the given image. | 160 """Downloads the zip and extracts the given image. |
| 90 | 161 |
| 91 Doesn't re-download if matching version found already in download folder. | 162 Doesn't re-download if matching version found already in download folder. |
| 92 Args: | 163 Args: |
| 93 zip_url - url for the image. | 164 zip_url - url for the image. |
| 94 download_folder - download folder to store zip file and extracted images. | 165 download_folder - download folder to store zip file and extracted images. |
| 95 image_name - name of the image to extract from the zip file. | 166 image_name - name of the image to extract from the zip file. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 | 265 |
| 195 if args: | 266 if args: |
| 196 parser.error('Extra args found %s.' % args) | 267 parser.error('Extra args found %s.' % args) |
| 197 | 268 |
| 198 if not options.board: | 269 if not options.board: |
| 199 parser.error('Need board for image to compare against.') | 270 parser.error('Need board for image to compare against.') |
| 200 | 271 |
| 201 if not options.channel: | 272 if not options.channel: |
| 202 parser.error('Need channel for image to compare against.') | 273 parser.error('Need channel for image to compare against.') |
| 203 | 274 |
| 204 if not options.latestbase: | |
| 205 parser.error('Need latest url base to get images.') | |
| 206 | |
| 207 if not options.zipbase: | 275 if not options.zipbase: |
| 208 parser.error('Need zip url base to get images.') | 276 parser.error('Need zip url base to get images.') |
| 209 | 277 |
| 210 RunAUTestHarness(options.board, options.channel, options.latestbase, | 278 RunAUTestHarness(options.board, options.channel, options.latestbase, |
| 211 options.zipbase, options.no_graphics, options.type, | 279 options.zipbase, options.no_graphics, options.type, |
| 212 options.remote) | 280 options.remote) |
| 213 | 281 |
| 214 | 282 |
| 215 if __name__ == '__main__': | 283 if __name__ == '__main__': |
| 216 try: | 284 try: |
| 217 main() | 285 main() |
| 218 except Exception: | 286 except Exception: |
| 219 print "Got exception." | 287 print "Got exception." |
| 220 traceback.print_exc(file=sys.stdout) | 288 traceback.print_exc(file=sys.stdout) |
| 221 | 289 |
| OLD | NEW |