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 |