Chromium Code Reviews| 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 import optparse | 7 import optparse |
| 8 import os | 8 import os |
| 9 import re | 9 import re |
| 10 import sys | 10 import sys |
| 11 import thread | |
| 12 import time | |
| 11 import unittest | 13 import unittest |
| 12 import urllib | 14 import urllib |
| 13 | 15 |
| 14 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 16 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
| 15 from cros_build_lib import Die | 17 from cros_build_lib import Die |
| 16 from cros_build_lib import Info | 18 from cros_build_lib import Info |
| 17 from cros_build_lib import ReinterpretPathForChroot | 19 from cros_build_lib import ReinterpretPathForChroot |
| 18 from cros_build_lib import RunCommand | 20 from cros_build_lib import RunCommand |
| 19 from cros_build_lib import RunCommandCaptureOutput | 21 from cros_build_lib import RunCommandCaptureOutput |
| 20 from cros_build_lib import Warning | 22 from cros_build_lib import Warning |
| 21 | 23 |
| 24 import cros_test_proxy | |
| 25 | |
| 22 # VM Constants. | 26 # VM Constants. |
| 23 _FULL_VDISK_SIZE = 6072 | 27 _FULL_VDISK_SIZE = 6072 |
| 24 _FULL_STATEFULFS_SIZE = 3074 | 28 _FULL_STATEFULFS_SIZE = 3074 |
| 25 _KVM_PID_FILE = '/tmp/harness_pid' | 29 _KVM_PID_FILE = '/tmp/harness_pid' |
| 26 _VERIFY_SUITE = 'suite_Smoke' | 30 _VERIFY_SUITE = 'suite_Smoke' |
| 27 | 31 |
| 28 # Globals to communicate options to unit tests. | 32 # Globals to communicate options to unit tests. |
| 29 global base_image_path | 33 global base_image_path |
| 30 global board | 34 global board |
| 31 global remote | 35 global remote |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 self.source_image = src_image | 86 self.source_image = src_image |
| 83 self.UpdateImage(image) | 87 self.UpdateImage(image) |
| 84 except: | 88 except: |
| 85 Warning('Delta update failed, disabling delta updates and retrying.') | 89 Warning('Delta update failed, disabling delta updates and retrying.') |
| 86 self.use_delta_updates = False | 90 self.use_delta_updates = False |
| 87 self.source_image = '' | 91 self.source_image = '' |
| 88 self._UpdateImageReportError(image) | 92 self._UpdateImageReportError(image) |
| 89 else: | 93 else: |
| 90 self._UpdateImageReportError(image) | 94 self._UpdateImageReportError(image) |
| 91 | 95 |
| 92 def _UpdateImageReportError(self, image_path, stateful_change='old'): | 96 def _UpdateImageReportError(self, image_path, stateful_change='old', |
| 97 proxy_port=None): | |
| 93 """Calls UpdateImage and reports any error to the console. | 98 """Calls UpdateImage and reports any error to the console. |
| 94 | 99 |
| 95 Still throws the exception. | 100 Still throws the exception. |
| 96 """ | 101 """ |
| 97 try: | 102 try: |
| 98 self.UpdateImage(image_path, stateful_change) | 103 self.UpdateImage(image_path, stateful_change, proxy_port) |
| 99 except UpdateException as err: | 104 except UpdateException as err: |
| 100 # If the update fails, print it out | 105 # If the update fails, print it out |
| 101 Warning(err.stdout) | 106 Warning(err.stdout) |
| 102 raise | 107 raise |
| 103 | 108 |
| 104 def _AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): | 109 def _AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): |
| 105 # This update is expected to fail... | 110 # This update is expected to fail... |
| 106 try: | 111 try: |
| 107 self.UpdateUsingPayload(payload) | 112 self.UpdateUsingPayload(payload) |
| 108 except UpdateException as err: | 113 except UpdateException as err: |
| 109 # Will raise ValueError if expected is not found. | 114 # Will raise ValueError if expected is not found. |
| 110 if re.search(re.escape(expected_msg), err.stdout, re.MULTILINE): | 115 if re.search(re.escape(expected_msg), err.stdout, re.MULTILINE): |
| 111 return | 116 return |
| 112 | 117 |
| 113 Warning("Didn't find '%s' in:" % expected_msg) | 118 Warning("Didn't find '%s' in:" % expected_msg) |
| 114 Warning(err.stdout) | 119 Warning(err.stdout) |
| 115 self.fail('We managed to update when failure was expected') | 120 self.fail('We managed to update when failure was expected') |
| 116 | 121 |
| 117 def PrepareBase(self, image_path): | 122 def PrepareBase(self, image_path): |
| 118 """Prepares target with base_image_path.""" | 123 """Prepares target with base_image_path.""" |
| 119 pass | 124 pass |
| 120 | 125 |
| 121 def UpdateImage(self, image_path, stateful_change='old'): | 126 def UpdateImage(self, image_path, stateful_change='old', proxy_port=None): |
| 122 """Updates target with the image given by the image_path. | 127 """Updates target with the image given by the image_path. |
| 123 | 128 |
| 124 Args: | 129 Args: |
| 125 image_path: Path to the image to update with. This image must be a test | 130 image_path: Path to the image to update with. This image must be a test |
| 126 image. | 131 image. |
| 127 stateful_change: How to modify the stateful partition. Values are: | 132 stateful_change: How to modify the stateful partition. Values are: |
| 128 'old': Don't modify stateful partition. Just update normally. | 133 'old': Don't modify stateful partition. Just update normally. |
| 129 'clean': Uses clobber-state to wipe the stateful partition with the | 134 'clean': Uses clobber-state to wipe the stateful partition with the |
| 130 exception of code needed for ssh. | 135 exception of code needed for ssh. |
| 136 proxy_port: Port to have the client connect to. For use with | |
| 137 CrosTestProxy. | |
| 131 """ | 138 """ |
| 132 pass | 139 pass |
| 133 | 140 |
| 134 def UpdateUsingPayload(self, update_path, stateful_change='old'): | 141 def UpdateUsingPayload(self, |
| 142 update_path, | |
| 143 stateful_change='old', | |
| 144 proxy_port=None): | |
| 135 """Updates target with the pre-generated update stored in update_path | 145 """Updates target with the pre-generated update stored in update_path |
| 136 | 146 |
| 137 Args: | 147 Args: |
| 138 update_path: Path to the image to update with. This directory should | 148 update_path: Path to the image to update with. This directory should |
| 139 contain both update.gz, and stateful.image.gz | 149 contain both update.gz, and stateful.image.gz |
| 150 proxy_port: Port to have the client connect to. For use with | |
| 151 CrosTestProxy. | |
| 140 """ | 152 """ |
| 141 pass | 153 pass |
| 142 | 154 |
| 143 def VerifyImage(self, percent_required_to_pass): | 155 def VerifyImage(self, percent_required_to_pass): |
| 144 """Verifies the image with tests. | 156 """Verifies the image with tests. |
| 145 | 157 |
| 146 Verifies that the test images passes the percent required. | 158 Verifies that the test images passes the percent required. |
| 147 | 159 |
| 148 Args: | 160 Args: |
| 149 percent_required_to_pass: percentage required to pass. This should be | 161 percent_required_to_pass: percentage required to pass. This should be |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 178 return percent_passed | 190 return percent_passed |
| 179 | 191 |
| 180 def testFullUpdateKeepStateful(self): | 192 def testFullUpdateKeepStateful(self): |
| 181 """Tests if we can update normally. | 193 """Tests if we can update normally. |
| 182 | 194 |
| 183 This test checks that we can update by updating the stateful partition | 195 This test checks that we can update by updating the stateful partition |
| 184 rather than wiping it. | 196 rather than wiping it. |
| 185 """ | 197 """ |
| 186 # Just make sure some tests pass on original image. Some old images | 198 # Just make sure some tests pass on original image. Some old images |
| 187 # don't pass many tests. | 199 # don't pass many tests. |
| 188 self.PrepareBase(image_path=base_image_path) | 200 self.PrepareBase(base_image_path) |
| 189 # TODO(sosa): move to 100% once we start testing using the autotest paired | 201 # TODO(sosa): move to 100% once we start testing using the autotest paired |
| 190 # with the dev channel. | 202 # with the dev channel. |
| 191 percent_passed = self.VerifyImage(10) | 203 percent_passed = self.VerifyImage(10) |
| 192 | 204 |
| 193 # Update to - all tests should pass on new image. | 205 # Update to - all tests should pass on new image. |
| 194 Info('Updating from base image on vm to target image.') | 206 Info('Updating from base image on vm to target image.') |
| 195 self.TryDeltaAndFallbackToFull(base_image_path, target_image_path) | 207 self.TryDeltaAndFallbackToFull(base_image_path, target_image_path) |
| 196 self.VerifyImage(100) | 208 self.VerifyImage(100) |
| 197 | 209 |
| 198 # Update from - same percentage should pass that originally passed. | 210 # Update from - same percentage should pass that originally passed. |
| 199 Info('Updating from updated image on vm back to base image.') | 211 Info('Updating from updated image on vm back to base image.') |
| 200 self.TryDeltaAndFallbackToFull(target_image_path, base_image_path) | 212 self.TryDeltaAndFallbackToFull(target_image_path, base_image_path) |
| 201 self.VerifyImage(percent_passed) | 213 self.VerifyImage(percent_passed) |
| 202 | 214 |
| 203 def testFullUpdateWipeStateful(self): | 215 def testFullUpdateWipeStateful(self): |
| 204 """Tests if we can update after cleaning the stateful partition. | 216 """Tests if we can update after cleaning the stateful partition. |
| 205 | 217 |
| 206 This test checks that we can update successfully after wiping the | 218 This test checks that we can update successfully after wiping the |
| 207 stateful partition. | 219 stateful partition. |
| 208 """ | 220 """ |
| 209 # Just make sure some tests pass on original image. Some old images | 221 # Just make sure some tests pass on original image. Some old images |
| 210 # don't pass many tests. | 222 # don't pass many tests. |
| 211 self.PrepareBase(image_path=base_image_path) | 223 self.PrepareBase(base_image_path) |
| 212 # TODO(sosa): move to 100% once we start testing using the autotest paired | 224 # TODO(sosa): move to 100% once we start testing using the autotest paired |
| 213 # with the dev channel. | 225 # with the dev channel. |
| 214 percent_passed = self.VerifyImage(10) | 226 percent_passed = self.VerifyImage(10) |
| 215 | 227 |
| 216 # Update to - all tests should pass on new image. | 228 # Update to - all tests should pass on new image. |
| 217 Info('Updating from base image on vm to target image and wiping stateful.') | 229 Info('Updating from base image on vm to target image and wiping stateful.') |
| 218 self.TryDeltaAndFallbackToFull(base_image_path, target_image_path, 'clean') | 230 self.TryDeltaAndFallbackToFull(base_image_path, target_image_path, 'clean') |
| 219 self.VerifyImage(100) | 231 self.VerifyImage(100) |
| 220 | 232 |
| 221 # Update from - same percentage should pass that originally passed. | 233 # Update from - same percentage should pass that originally passed. |
| 222 Info('Updating from updated image back to base image and wiping stateful.') | 234 Info('Updating from updated image back to base image and wiping stateful.') |
| 223 self.TryDeltaAndFallbackToFull(target_image_path, base_image_path, 'clean') | 235 self.TryDeltaAndFallbackToFull(target_image_path, base_image_path, 'clean') |
| 224 self.VerifyImage(percent_passed) | 236 self.VerifyImage(percent_passed) |
| 225 | 237 |
| 226 def testPartialUpdate(self): | 238 def testPartialUpdate(self): |
| 227 """Tests what happens if we attempt to update with a truncated payload.""" | 239 """Tests what happens if we attempt to update with a truncated payload.""" |
| 228 # Preload with the version we are trying to test. | 240 # Preload with the version we are trying to test. |
| 229 self.PrepareBase(image_path=target_image_path) | 241 self.PrepareBase(target_image_path) |
| 230 | 242 |
| 231 # Image can be updated at: | 243 # Image can be updated at: |
| 232 # ~chrome-eng/chromeos/localmirror/autest-images | 244 # ~chrome-eng/chromeos/localmirror/autest-images |
| 233 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \ | 245 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \ |
| 234 'autest-images/truncated_image.gz' | 246 'autest-images/truncated_image.gz' |
| 235 payload = os.path.join(self.download_folder, 'truncated_image.gz') | 247 payload = os.path.join(self.download_folder, 'truncated_image.gz') |
| 236 | 248 |
| 237 # Read from the URL and write to the local file | 249 # Read from the URL and write to the local file |
| 238 urllib.urlretrieve(url, payload) | 250 urllib.urlretrieve(url, payload) |
| 239 | 251 |
| 240 expected_msg='download_hash_data == update_check_response_hash failed' | 252 expected_msg='download_hash_data == update_check_response_hash failed' |
| 241 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg) | 253 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg) |
| 242 | 254 |
| 243 def testCorruptedUpdate(self): | 255 def testCorruptedUpdate(self): |
| 244 """Tests what happens if we attempt to update with a corrupted payload.""" | 256 """Tests what happens if we attempt to update with a corrupted payload.""" |
| 245 # Preload with the version we are trying to test. | 257 # Preload with the version we are trying to test. |
| 246 self.PrepareBase(image_path=target_image_path) | 258 self.PrepareBase(target_image_path) |
| 247 | 259 |
| 248 # Image can be updated at: | 260 # Image can be updated at: |
| 249 # ~chrome-eng/chromeos/localmirror/autest-images | 261 # ~chrome-eng/chromeos/localmirror/autest-images |
| 250 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \ | 262 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \ |
| 251 'autest-images/corrupted_image.gz' | 263 'autest-images/corrupted_image.gz' |
| 252 payload = os.path.join(self.download_folder, 'corrupted.gz') | 264 payload = os.path.join(self.download_folder, 'corrupted.gz') |
| 253 | 265 |
| 254 # Read from the URL and write to the local file | 266 # Read from the URL and write to the local file |
| 255 urllib.urlretrieve(url, payload) | 267 urllib.urlretrieve(url, payload) |
| 256 | 268 |
| 257 # This update is expected to fail... | 269 # This update is expected to fail... |
| 258 expected_msg='zlib inflate() error:-3' | 270 expected_msg='zlib inflate() error:-3' |
| 259 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg) | 271 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg) |
| 260 | 272 |
| 273 def testInterruptedUpdate(self): | |
| 274 """Tests what happens if we interrupt payload delivery 3 times.""" | |
| 275 | |
| 276 class InterruptionFilter(cros_test_proxy.Filter): | |
| 277 """This filter causes the proxy to interrupt the download 3 times | |
| 278 | |
| 279 It does this by closing the first three connections to transfer | |
| 280 2M total in the outbound connection after they transfer the | |
| 281 2M. | |
| 282 """ | |
| 283 def __init__(self): | |
| 284 """Defines variable shared across all connections""" | |
| 285 self.close_count = 0 | |
| 286 | |
| 287 def setup(self): | |
| 288 """Called once at the start of each connection.""" | |
| 289 self.data_size = 0 | |
| 290 | |
| 291 def OutBound(self, data): | |
| 292 """Called once per packet for outgoing data. | |
| 293 | |
| 294 The first three connections transferring more than 2M | |
| 295 outbound will be closed. | |
| 296 """ | |
| 297 if self.close_count < 3: | |
| 298 if self.data_size > (2 * 1024 * 1024): | |
| 299 self.close_count += 1 | |
| 300 return None | |
| 301 | |
| 302 self.data_size += len(data) | |
| 303 return data | |
| 304 | |
| 305 | |
| 306 self.PrepareBase(target_image_path) | |
| 307 | |
| 308 # The devserver runs at port 8080 by default. We assume that here, and | |
| 309 # start our proxy at 8081. We then tell our update tools to have the | |
| 310 # client connect to 8081 instead of 8080. | |
| 311 proxy_port = 8081 | |
| 312 proxy = cros_test_proxy.CrosTestProxy(port_in=proxy_port, | |
| 313 address_out='127.0.0.1', | |
| 314 port_out=8080, | |
| 315 filter=InterruptionFilter()) | |
| 316 proxy.serve_forever_in_thread() | |
| 317 | |
| 318 # This update is expected to fail... | |
| 319 try: | |
| 320 self._UpdateImageReportError(target_image_path, proxy_port=proxy_port) | |
| 321 finally: | |
| 322 proxy.shutdown() | |
| 323 | |
| 324 def testDelayedUpdate(self): | |
| 325 """Tests what happens if some data is delayed during update delivery""" | |
| 326 | |
| 327 class DelayedFilter(cros_test_proxy.Filter): | |
| 328 """Causes intermittent delays in data transmission. | |
| 329 | |
| 330 It does this by inserting 3 20 second delays when transmitting | |
| 331 data after 2M has been sent. | |
| 332 """ | |
| 333 def setup(self): | |
| 334 # These values are reset for each connection | |
|
sosa
2010/12/07 17:49:23
These two should be docstringed as well
dgarrett
2010/12/09 00:48:38
Done.
| |
| 335 self.data_size = 0 | |
| 336 self.delay_count = 0 | |
| 337 | |
| 338 def OutBound(self, data): | |
| 339 # The first three packets after we reach 2M transferred | |
| 340 # are delayed by 20 seconds | |
| 341 if self.delay_count < 3: | |
| 342 if self.data_size > (2 * 1024 * 1024): | |
| 343 self.delay_count += 1 | |
| 344 time.sleep(20) | |
| 345 | |
| 346 self.data_size += len(data) | |
| 347 return data | |
| 348 | |
| 349 | |
|
sosa
2010/12/07 17:49:23
All the code below is common to both functions ...
| |
| 350 self.PrepareBase(target_image_path) | |
| 351 | |
| 352 proxy_port = 8081 | |
| 353 proxy = cros_test_proxy.CrosTestProxy(port_in=proxy_port, | |
| 354 address_out='127.0.0.1', | |
| 355 port_out=8080, | |
| 356 filter=DelayedFilter()) | |
| 357 proxy.serve_forever_in_thread() | |
| 358 | |
| 359 # This update is expected to fail... | |
| 360 try: | |
| 361 self._UpdateImageReportError(target_image_path, proxy_port=proxy_port) | |
| 362 finally: | |
| 363 proxy.shutdown() | |
| 364 | |
| 261 class RealAUTest(unittest.TestCase, AUTest): | 365 class RealAUTest(unittest.TestCase, AUTest): |
| 262 """Test harness for updating real images.""" | 366 """Test harness for updating real images.""" |
| 263 | 367 |
| 264 def setUp(self): | 368 def setUp(self): |
| 265 AUTest.setUp(self) | 369 AUTest.setUp(self) |
| 266 | 370 |
| 267 def PrepareBase(self, image_path): | 371 def PrepareBase(self, image_path): |
| 268 """Auto-update to base image to prepare for test.""" | 372 """Auto-update to base image to prepare for test.""" |
| 269 self._UpdateImageReportError(image_path) | 373 self._UpdateImageReportError(image_path) |
| 270 | 374 |
| 271 def UpdateImage(self, image_path, stateful_change='old'): | 375 def UpdateImage(self, image_path, stateful_change='old', proxy_port=None): |
| 272 """Updates a remote image using image_to_live.sh.""" | 376 """Updates a remote image using image_to_live.sh.""" |
| 273 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) | 377 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) |
| 274 | 378 |
| 379 port_flags = [] | |
| 380 if proxy_port: | |
| 381 port_flags.append('--proxy_port=%s' % proxy_port) | |
| 382 | |
| 275 (code, stdout, stderr) = RunCommandCaptureOutput([ | 383 (code, stdout, stderr) = RunCommandCaptureOutput([ |
| 276 '%s/image_to_live.sh' % self.crosutils, | 384 '%s/image_to_live.sh' % self.crosutils, |
| 277 '--image=%s' % image_path, | 385 '--image=%s' % image_path, |
| 278 '--remote=%s' % remote, | 386 '--remote=%s' % remote, |
| 279 stateful_change_flag, | 387 stateful_change_flag, |
| 280 '--verify', | 388 '--verify', |
| 281 '--src_image=%s' % self.source_image | 389 '--src_image=%s' % self.source_image |
| 282 ]) | 390 ].extend(port_flags)) |
| 283 | 391 |
| 284 if code != 0: | 392 if code != 0: |
| 285 raise UpdateException(code, stdout) | 393 raise UpdateException(code, stdout) |
| 286 | 394 |
| 287 def UpdateUsingPayload(self, update_path, stateful_change='old'): | 395 def UpdateUsingPayload(self, |
| 396 update_path, | |
| 397 stateful_change='old', | |
| 398 proxy_port=None): | |
| 288 """Updates a remote image using image_to_live.sh.""" | 399 """Updates a remote image using image_to_live.sh.""" |
| 289 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) | 400 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) |
| 290 | 401 |
| 402 port_flags = [] | |
| 403 if proxy_port: | |
| 404 port_flags.append('--proxy_port=%s' % proxy_port) | |
| 405 | |
| 291 (code, stdout, stderr) = RunCommandCaptureOutput([ | 406 (code, stdout, stderr) = RunCommandCaptureOutput([ |
| 292 '%s/image_to_live.sh' % self.crosutils, | 407 '%s/image_to_live.sh' % self.crosutils, |
| 293 '--payload=%s' % update_path, | 408 '--payload=%s' % update_path, |
| 294 '--remote=%s' % remote, | 409 '--remote=%s' % remote, |
| 295 stateful_change_flag, | 410 stateful_change_flag, |
| 296 '--verify', | 411 '--verify', |
| 297 ]) | 412 ].extend(port_flags)) |
| 298 | 413 |
| 299 if code != 0: | 414 if code != 0: |
| 300 raise UpdateException(code, stdout) | 415 raise UpdateException(code, stdout) |
| 301 | 416 |
| 302 def VerifyImage(self, percent_required_to_pass): | 417 def VerifyImage(self, percent_required_to_pass): |
| 303 """Verifies an image using run_remote_tests.sh with verification suite.""" | 418 """Verifies an image using run_remote_tests.sh with verification suite.""" |
| 304 output = RunCommand([ | 419 output = RunCommand([ |
| 305 '%s/run_remote_tests.sh' % self.crosutils, | 420 '%s/run_remote_tests.sh' % self.crosutils, |
| 306 '--remote=%s' % remote, | 421 '--remote=%s' % remote, |
| 307 _VERIFY_SUITE, | 422 _VERIFY_SUITE, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 '--board=%s' % board, | 462 '--board=%s' % board, |
| 348 '--test_image'], enter_chroot=True) | 463 '--test_image'], enter_chroot=True) |
| 349 else: | 464 else: |
| 350 Info('Using existing VM image %s' % self.vm_image_path) | 465 Info('Using existing VM image %s' % self.vm_image_path) |
| 351 | 466 |
| 352 | 467 |
| 353 Info('Testing for %s' % self.vm_image_path) | 468 Info('Testing for %s' % self.vm_image_path) |
| 354 | 469 |
| 355 self.assertTrue(os.path.exists(self.vm_image_path)) | 470 self.assertTrue(os.path.exists(self.vm_image_path)) |
| 356 | 471 |
| 357 def UpdateImage(self, image_path, stateful_change='old'): | 472 def UpdateImage(self, image_path, stateful_change='old', proxy_port=None): |
| 358 """Updates VM image with image_path.""" | 473 """Updates VM image with image_path.""" |
| 359 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) | 474 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) |
| 360 if self.source_image == base_image_path: | 475 if self.source_image == base_image_path: |
| 361 self.source_image = self.vm_image_path | 476 self.source_image = self.vm_image_path |
| 362 | 477 |
| 478 port_flags = [] | |
| 479 if proxy_port: | |
| 480 port_flags.append('--proxy_port=%s' % proxy_port) | |
| 481 | |
| 363 (code, stdout, stderr) = RunCommandCaptureOutput([ | 482 (code, stdout, stderr) = RunCommandCaptureOutput([ |
| 364 '%s/cros_run_vm_update' % self.crosutilsbin, | 483 '%s/cros_run_vm_update' % self.crosutilsbin, |
| 365 '--update_image_path=%s' % image_path, | 484 '--update_image_path=%s' % image_path, |
| 366 '--vm_image_path=%s' % self.vm_image_path, | 485 '--vm_image_path=%s' % self.vm_image_path, |
| 367 '--snapshot', | 486 '--snapshot', |
| 368 vm_graphics_flag, | 487 vm_graphics_flag, |
| 369 '--persist', | 488 '--persist', |
| 370 '--kvm_pid=%s' % _KVM_PID_FILE, | 489 '--kvm_pid=%s' % _KVM_PID_FILE, |
| 371 stateful_change_flag, | 490 stateful_change_flag, |
| 372 '--src_image=%s' % self.source_image, | 491 '--src_image=%s' % self.source_image, |
| 373 ]) | 492 ].extend(port_flags)) |
| 374 | 493 |
| 375 if code != 0: | 494 if code != 0: |
| 376 raise UpdateException(code, stdout) | 495 raise UpdateException(code, stdout) |
| 377 | 496 |
| 378 def UpdateUsingPayload(self, update_path, stateful_change='old'): | 497 def UpdateUsingPayload(self, |
| 498 update_path, | |
| 499 stateful_change='old', | |
| 500 proxy_port=None): | |
| 379 """Updates a remote image using image_to_live.sh.""" | 501 """Updates a remote image using image_to_live.sh.""" |
| 380 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) | 502 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) |
| 381 if self.source_image == base_image_path: | 503 if self.source_image == base_image_path: |
| 382 self.source_image = self.vm_image_path | 504 self.source_image = self.vm_image_path |
| 383 | 505 |
| 506 port_flags = [] | |
| 507 if proxy_port: | |
| 508 port_flags.append('--proxy_port=%s' % proxy_port) | |
| 509 | |
| 384 (code, stdout, stderr) = RunCommandCaptureOutput([ | 510 (code, stdout, stderr) = RunCommandCaptureOutput([ |
| 385 '%s/cros_run_vm_update' % self.crosutilsbin, | 511 '%s/cros_run_vm_update' % self.crosutilsbin, |
| 386 '--payload=%s' % update_path, | 512 '--payload=%s' % update_path, |
| 387 '--vm_image_path=%s' % self.vm_image_path, | 513 '--vm_image_path=%s' % self.vm_image_path, |
| 388 '--snapshot', | 514 '--snapshot', |
| 389 vm_graphics_flag, | 515 vm_graphics_flag, |
| 390 '--persist', | 516 '--persist', |
| 391 '--kvm_pid=%s' % _KVM_PID_FILE, | 517 '--kvm_pid=%s' % _KVM_PID_FILE, |
| 392 stateful_change_flag, | 518 stateful_change_flag, |
| 393 '--src_image=%s' % self.source_image, | 519 '--src_image=%s' % self.source_image, |
| 394 ]) | 520 ].extend(port_flags)) |
| 395 | 521 |
| 396 if code != 0: | 522 if code != 0: |
| 397 raise UpdateException(code, stdout) | 523 raise UpdateException(code, stdout) |
| 398 | 524 |
| 399 def VerifyImage(self, percent_required_to_pass): | 525 def VerifyImage(self, percent_required_to_pass): |
| 400 """Runs vm smoke suite to verify image.""" | 526 """Runs vm smoke suite to verify image.""" |
| 401 # image_to_live already verifies lsb-release matching. This is just | 527 # image_to_live already verifies lsb-release matching. This is just |
| 402 # for additional steps. | 528 # for additional steps. |
| 403 | 529 |
| 404 commandWithArgs = ['%s/cros_run_vm_test' % self.crosutilsbin, | 530 commandWithArgs = ['%s/cros_run_vm_test' % self.crosutilsbin, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 474 else: | 600 else: |
| 475 remote = options.remote | 601 remote = options.remote |
| 476 | 602 |
| 477 suite = unittest.TestLoader().loadTestsFromTestCase(RealAUTest) | 603 suite = unittest.TestLoader().loadTestsFromTestCase(RealAUTest) |
| 478 test_result = unittest.TextTestRunner(verbosity=2).run(suite) | 604 test_result = unittest.TextTestRunner(verbosity=2).run(suite) |
| 479 else: | 605 else: |
| 480 parser.error('Could not parse harness type %s.' % options.type) | 606 parser.error('Could not parse harness type %s.' % options.type) |
| 481 | 607 |
| 482 if not test_result.wasSuccessful(): | 608 if not test_result.wasSuccessful(): |
| 483 Die('Test harness was not successful') | 609 Die('Test harness was not successful') |
| OLD | NEW |