Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: bin/au_test_harness/cros_au_test_harness.py

Issue 6698017: Remove test keys from images we test with in the test harness. (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: Refactored public key logic into its own module Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2011 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 """This module runs a suite of Auto Update tests. 7 """This module runs a suite of Auto Update tests.
8 8
9 The tests can be run on either a virtual machine or actual device depending 9 The tests can be run on either a virtual machine or actual device depending
10 on parameters given. Specific tests can be run by invoking --test_prefix. 10 on parameters given. Specific tests can be run by invoking --test_prefix.
11 Verbose is useful for many of the tests if you want to see individual commands 11 Verbose is useful for many of the tests if you want to see individual commands
12 being run during the update process. 12 being run during the update process.
13 """ 13 """
14 14
15 import optparse 15 import optparse
16 import os 16 import os
17 import re 17 import re
18 import sys 18 import sys
19 import tempfile
20 import unittest 19 import unittest
21 20
22 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) 21 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
23 import cros_build_lib as cros_lib 22 import cros_build_lib as cros_lib
24 23
25 import au_test 24 import au_test
26 import au_worker 25 import au_worker
27 import dummy_au_worker 26 import dummy_au_worker
28 import dev_server_wrapper 27 import dev_server_wrapper
29 import parallel_test_job 28 import parallel_test_job
29 import public_key_manager
30 import update_exception 30 import update_exception
31 31
32
33 def _PrepareTestSuite(options, use_dummy_worker=False): 32 def _PrepareTestSuite(options, use_dummy_worker=False):
34 """Returns a prepared test suite given by the options and test class.""" 33 """Returns a prepared test suite given by the options and test class."""
35 au_test.AUTest.ProcessOptions(options, use_dummy_worker) 34 au_test.AUTest.ProcessOptions(options, use_dummy_worker)
36 test_loader = unittest.TestLoader() 35 test_loader = unittest.TestLoader()
37 test_loader.testMethodPrefix = options.test_prefix 36 test_loader.testMethodPrefix = options.test_prefix
38 return test_loader.loadTestsFromTestCase(au_test.AUTest) 37 return test_loader.loadTestsFromTestCase(au_test.AUTest)
39 38
40 39
41 def _PregenerateUpdates(options): 40 def _PregenerateUpdates(options):
42 """Determines all deltas that will be generated and generates them. 41 """Determines all deltas that will be generated and generates them.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite) 75 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite)
77 if not test_result.wasSuccessful(): 76 if not test_result.wasSuccessful():
78 raise update_exception.UpdateException(1, 77 raise update_exception.UpdateException(1,
79 'Error finding updates to generate.') 78 'Error finding updates to generate.')
80 79
81 cros_lib.Info('The following delta updates are required.') 80 cros_lib.Info('The following delta updates are required.')
82 update_ids = [] 81 update_ids = []
83 jobs = [] 82 jobs = []
84 args = [] 83 args = []
85 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items(): 84 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items():
85 # We only need to add the target if we are doing a full update.
86 if not options.delta: au_test.AUTest.modified_images.add(target)
petkov 2011/03/16 22:03:48 can you make modified_images local to this routine
sosa 2011/03/16 22:47:02 Done.
86 for src_key in srcs: 87 for src_key in srcs:
87 (src, _ , key) = src_key.partition('+') 88 (src, _ , key) = src_key.partition('+')
89 if src: au_test.AUTest.modified_images.add(src)
88 # TODO(sosa): Add private key as part of caching name once devserver can 90 # TODO(sosa): Add private key as part of caching name once devserver can
89 # handle it its own cache. 91 # handle it its own cache.
90 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key) 92 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key)
91 print >> sys.stderr, 'AU: %s' % update_id 93 print >> sys.stderr, 'AU: %s' % update_id
92 update_ids.append(update_id) 94 update_ids.append(update_id)
93 jobs.append(_GenerateVMUpdate) 95 jobs.append(_GenerateVMUpdate)
94 args.append((target, src, key)) 96 args.append((target, src, key))
95 97
98 # Always add the base image path. This is only useful for non-delta updates.
99 au_test.AUTest.modified_images.add(options.base_image)
100
101 # Add public key to all images we are using.
102 if options.public_key:
103 for image in au_test.AUTest.modified_images:
104 manager = public_key_manager.PublicKeyManager(image, options.public_key)
105 manager.AddKeyToImage()
106 au_test.AUTest.public_key_managers.append(manager)
107
96 raw_results = parallel_test_job.RunParallelJobs(options.jobs, jobs, args, 108 raw_results = parallel_test_job.RunParallelJobs(options.jobs, jobs, args,
97 print_status=True) 109 print_status=True)
98 results = [] 110 results = []
99 111
100 # Looking for this line in the output. 112 # Looking for this line in the output.
101 key_line_re = re.compile('^PREGENERATED_UPDATE=([\w/.]+)') 113 key_line_re = re.compile('^PREGENERATED_UPDATE=([\w/.]+)')
102 for result in raw_results: 114 for result in raw_results:
103 (return_code, output, _) = result 115 (return_code, output, _) = result
104 if return_code != 0: 116 if return_code != 0:
105 cros_lib.Warning(output) 117 cros_lib.Warning(output)
(...skipping 24 matching lines...) Expand all
130 142
131 143
132 def _RunTestsInParallel(options): 144 def _RunTestsInParallel(options):
133 """Runs the tests given by the options in parallel.""" 145 """Runs the tests given by the options in parallel."""
134 threads = [] 146 threads = []
135 args = [] 147 args = []
136 test_suite = _PrepareTestSuite(options) 148 test_suite = _PrepareTestSuite(options)
137 for test in test_suite: 149 for test in test_suite:
138 test_name = test.id() 150 test_name = test.id()
139 test_case = unittest.TestLoader().loadTestsFromName(test_name) 151 test_case = unittest.TestLoader().loadTestsFromName(test_name)
140 threads.append(unittest.TextTestRunner().run) 152 threads.append(unittest.TextTestRunner(verbosity=2).run)
141 args.append(test_case) 153 args.append(test_case)
142 154
143 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args, 155 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args,
144 print_status=False) 156 print_status=False)
145 for test_result in results: 157 for test_result in results:
146 if not test_result.wasSuccessful(): 158 if not test_result.wasSuccessful():
147 cros_lib.Die('Test harness was not successful') 159 cros_lib.Die('Test harness was not successful')
148 160
149 161
150 def _InsertPublicKeyIntoImage(image_path, key_path):
151 """Inserts public key into image @ static update_engine location."""
152 from_dir = os.path.dirname(image_path)
153 image = os.path.basename(image_path)
154 crosutils_dir = os.path.abspath(__file__).rsplit('/', 2)[0]
155 target_key_path = 'usr/share/update_engine/update-payload-key.pub.pem'
156
157 # Temporary directories for this function.
158 rootfs_dir = tempfile.mkdtemp(suffix='rootfs', prefix='tmp')
159 stateful_dir = tempfile.mkdtemp(suffix='stateful', prefix='tmp')
160
161 cros_lib.Info('Copying %s into %s' % (key_path, image_path))
162 try:
163 cros_lib.RunCommand(['./mount_gpt_image.sh',
164 '--from=%s' % from_dir,
165 '--image=%s' % image,
166 '--rootfs_mountpt=%s' % rootfs_dir,
167 '--stateful_mountpt=%s' % stateful_dir,
168 ], print_cmd=False, redirect_stdout=True,
169 redirect_stderr=True, cwd=crosutils_dir)
170 path = os.path.join(rootfs_dir, target_key_path)
171 dir_path = os.path.dirname(path)
172 cros_lib.RunCommand(['sudo', 'mkdir', '--parents', dir_path],
173 print_cmd=False)
174 cros_lib.RunCommand(['sudo', 'cp', '--force', '-p', key_path, path],
175 print_cmd=False)
176 finally:
177 # Unmount best effort regardless.
178 cros_lib.RunCommand(['./mount_gpt_image.sh',
179 '--unmount',
180 '--rootfs_mountpt=%s' % rootfs_dir,
181 '--stateful_mountpt=%s' % stateful_dir,
182 ], print_cmd=False, redirect_stdout=True,
183 redirect_stderr=True, cwd=crosutils_dir)
184 # Clean up our directories.
185 os.rmdir(rootfs_dir)
186 os.rmdir(stateful_dir)
187
188 cros_lib.RunCommand(['bin/cros_make_image_bootable',
189 cros_lib.ReinterpretPathForChroot(from_dir),
190 image],
191 print_cmd=False, redirect_stdout=True,
192 redirect_stderr=True, enter_chroot=True,
193 cwd=crosutils_dir)
194
195
196 def _CleanPreviousWork(options): 162 def _CleanPreviousWork(options):
197 """Cleans up previous work from the devserver cache and local image cache.""" 163 """Cleans up previous work from the devserver cache and local image cache."""
198 cros_lib.Info('Cleaning up previous work.') 164 cros_lib.Info('Cleaning up previous work.')
199 # Wipe devserver cache. 165 # Wipe devserver cache.
200 cros_lib.RunCommandCaptureOutput( 166 cros_lib.RunCommandCaptureOutput(
201 ['sudo', 'start_devserver', '--clear_cache', '--exit', ], 167 ['sudo', 'start_devserver', '--clear_cache', '--exit', ],
202 enter_chroot=True, print_cmd=False, combine_stdout_stderr=True) 168 enter_chroot=True, print_cmd=False, combine_stdout_stderr=True)
203 169
204 # Clean previous vm images if they exist. 170 # Clean previous vm images if they exist.
205 if options.type == 'vm': 171 if options.type == 'vm':
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 (options, leftover_args) = parser.parse_args() 216 (options, leftover_args) = parser.parse_args()
251 217
252 if leftover_args: parser.error('Found unsupported flags: %s' % leftover_args) 218 if leftover_args: parser.error('Found unsupported flags: %s' % leftover_args)
253 219
254 assert options.target_image and os.path.exists(options.target_image), \ 220 assert options.target_image and os.path.exists(options.target_image), \
255 'Target image path does not exist' 221 'Target image path does not exist'
256 if not options.base_image: 222 if not options.base_image:
257 cros_lib.Info('Base image not specified. Using target as base image.') 223 cros_lib.Info('Base image not specified. Using target as base image.')
258 options.base_image = options.target_image 224 options.base_image = options.target_image
259 225
260 # Sanity checks on keys and insert them onto the image. The caches must be
261 # cleaned so we know that the vm images and payloads match the possibly new
262 # key.
263 if options.private_key or options.public_key: 226 if options.private_key or options.public_key:
264 error_msg = ('Could not find %s key. Both private and public keys must be ' 227 error_msg = ('Could not find %s key. Both private and public keys must be '
265 'specified if either is specified.') 228 'specified if either is specified.')
266 assert options.private_key and os.path.exists(options.private_key), \ 229 assert options.private_key and os.path.exists(options.private_key), \
267 error_msg % 'private' 230 error_msg % 'private'
268 assert options.public_key and os.path.exists(options.public_key), \ 231 assert options.public_key and os.path.exists(options.public_key), \
269 error_msg % 'public' 232 error_msg % 'public'
270 _InsertPublicKeyIntoImage(options.target_image, options.public_key)
271 if options.target_image != options.base_image:
272 _InsertPublicKeyIntoImage(options.base_image, options.public_key)
273 options.clean = True
274 233
275 # Clean up previous work if requested. 234 # Clean up previous work if requested.
276 if options.clean: _CleanPreviousWork(options) 235 if options.clean: _CleanPreviousWork(options)
277 236
278 # Make sure we have a log directory. 237 # Make sure we have a log directory.
279 if not os.path.exists(options.test_results_root): 238 if not os.path.exists(options.test_results_root):
280 os.makedirs(options.test_results_root) 239 os.makedirs(options.test_results_root)
281 240
282 # Generate cache of updates to use during test harness. 241 # Pre-generate update modifies images by adding public keys to them.
283 update_cache = _PregenerateUpdates(options) 242 # Wrap try to make sure we clean this up before we're done.
284 au_worker.AUWorker.SetUpdateCache(update_cache) 243 try:
244 # Generate cache of updates to use during test harness.
245 update_cache = _PregenerateUpdates(options)
246 au_worker.AUWorker.SetUpdateCache(update_cache)
285 247
286 my_server = dev_server_wrapper.DevServerWrapper( 248 my_server = dev_server_wrapper.DevServerWrapper(
287 au_test.AUTest.test_results_root) 249 au_test.AUTest.test_results_root)
288 my_server.start() 250 my_server.start()
289 try: 251 try:
290 if options.type == 'vm': 252 if options.type == 'vm':
291 _RunTestsInParallel(options) 253 _RunTestsInParallel(options)
292 else: 254 else:
293 # TODO(sosa) - Take in a machine pool for a real test. 255 # TODO(sosa) - Take in a machine pool for a real test.
294 # Can't run in parallel with only one remote device. 256 # Can't run in parallel with only one remote device.
295 test_suite = _PrepareTestSuite(options) 257 test_suite = _PrepareTestSuite(options)
296 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) 258 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite)
297 if not test_result.wasSuccessful(): cros_lib.Die('Test harness failed.') 259 if not test_result.wasSuccessful(): cros_lib.Die('Test harness failed.')
260
261 finally:
262 my_server.Stop()
263
298 finally: 264 finally:
299 my_server.Stop() 265 # Un-modify any target images we modified. We don't need to de-modify
petkov 2011/03/16 22:03:48 Un-modify or de-modify? Pick on non-word and stick
sosa 2011/03/16 22:47:02 I enjoy making up words. Done. On 2011/03/16 22:0
266 # non-targets because they aren't important for archival steps.
267 cros_lib.Info('Cleaning up. Removing keys added as part of testing.')
268 target_directory = os.path.dirname(options.target_image)
269 for key_manager in au_test.AUTest.public_key_managers:
270 if key_manager.image_path.startswith(target_directory):
271 key_manager.RemoveKeyFromImage()
300 272
301 273
302 if __name__ == '__main__': 274 if __name__ == '__main__':
303 main() 275 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698