From 8dad50d97fff0142c4b45a62d3fe13263e08b5a0 Mon Sep 17 00:00:00 2001 From: Chris Sosa Date: Mon, 14 Feb 2011 15:29:32 -0800 Subject: [PATCH] Update test harness to take in optional public and private keys to sign payloads. In addition some refactoring to make this cleaner and easier. Change-Id: I1607700d065c71aff2b2833b10acbd3ebace68ce BUG=chromium-os:8212 TEST=Ran with Simple ... running now with full Review URL: http://codereview.chromium.org/6482017 --- bin/cros_au_test_harness.py | 429 ++++++++++++++++++++++-------------- bin/cros_run_vm_update | 6 +- bin/ctest.py | 41 ++-- image_to_vm.sh | 2 +- 4 files changed, 282 insertions(+), 196 deletions(-) diff --git a/bin/cros_au_test_harness.py b/bin/cros_au_test_harness.py index 67c0485ba0..2c2f8f8218 100755 --- a/bin/cros_au_test_harness.py +++ b/bin/cros_au_test_harness.py @@ -15,8 +15,10 @@ import optparse import os import re +import shutil import subprocess import sys +import tempfile import threading import time import unittest @@ -53,11 +55,74 @@ class AUTest(object): self.crosutils = os.path.join(os.path.dirname(__file__), '..') self.crosutilsbin = os.path.join(os.path.dirname(__file__)) self.download_folder = os.path.join(self.crosutils, 'latest_download') + self.vm_image_path = None if not os.path.exists(self.download_folder): os.makedirs(self.download_folder) # -------- Helper functions --------- + def _PrepareRealBase(self, image_path): + self.PerformUpdate(image_path) + + def _PrepareVMBase(self, image_path): + # VM Constants. + FULL_VDISK_SIZE = 6072 + FULL_STATEFULFS_SIZE = 3074 + # Needed for VM delta updates. We need to use the qemu image rather + # than the base image on a first update. By tracking the first_update + # we can set src_image to the qemu form of the base image when + # performing generating the delta payload. + self._first_update = True + self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( + image_path) + if not os.path.exists(self.vm_image_path): + Info('Creating %s' % self.vm_image_path) + RunCommand(['%s/image_to_vm.sh' % self.crosutils, + '--full', + '--from=%s' % ReinterpretPathForChroot( + os.path.dirname(image_path)), + '--vdisk_size=%s' % FULL_VDISK_SIZE, + '--statefulfs_size=%s' % FULL_STATEFULFS_SIZE, + '--board=%s' % self.board, + '--test_image'], enter_chroot=True) + + Info('Using %s as base' % self.vm_image_path) + self.assertTrue(os.path.exists(self.vm_image_path)) + + def AppendUpdateFlags(self, cmd, image_path, src_image_path, proxy_port, + private_key_path): + """Appends common args to an update cmd defined by an array. + + Modifies cmd in places by appending appropriate items given args. + """ + if proxy_port: cmd.append('--proxy_port=%s' % proxy_port) + + # Get pregenerated update if we have one. + update_id = _GenerateUpdateId(target=image_path, src=src_image_path, + key=private_key_path) + cache_path = dev_server_cache[update_id] + if cache_path: + update_url = DevServerWrapper.GetDevServerURL(proxy_port, cache_path) + cmd.append('--update_url=%s' % update_url) + else: + cmd.append('--image=%s' % image_path) + if src_image_path: cmd.append('--src_image=%s' % src_image_path) + + def RunUpdateCmd(self, cmd): + """Runs the given update cmd given verbose options. + + Raises an UpdateException if the update fails. + """ + if self.verbose: + try: + RunCommand(cmd) + except Exception, e: + raise UpdateException(1, e.message) + else: + (code, stdout, stderr) = RunCommandCaptureOutput(cmd) + if code != 0: + raise UpdateException(code, stdout) + def GetStatefulChangeFlag(self, stateful_change): """Returns the flag to pass to image_to_vm for the stateful change.""" stateful_change_flag = '' @@ -101,7 +166,7 @@ class AUTest(object): return percent_passed def PerformUpdate(self, image_path, src_image_path='', stateful_change='old', - proxy_port=None): + proxy_port=None, private_key_path=None): """Performs an update using _UpdateImage and reports any error. Subclasses should not override this method but override _UpdateImage @@ -121,10 +186,14 @@ class AUTest(object): Raises an UpdateException if _UpdateImage returns an error. """ try: - if not self.use_delta_updates: - src_image_path = '' + if not self.use_delta_updates: src_image_path = '' + if private_key_path: + key_to_use = private_key_path + else: + key_to_use = self.private_key - self._UpdateImage(image_path, src_image_path, stateful_change, proxy_port) + self._UpdateImage(image_path, src_image_path, stateful_change, proxy_port, + key_to_use) except UpdateException as err: # If the update fails, print it out Warning(err.stdout) @@ -178,6 +247,9 @@ class AUTest(object): cls.base_image_path = options.base_image cls.target_image_path = options.target_image cls.use_delta_updates = options.delta + cls.board = options.board + cls.private_key = options.private_key + cls.clean = options.clean if options.quick_test: cls.verify_suite = 'build_RootFilesystemSize' else: @@ -199,7 +271,7 @@ class AUTest(object): pass def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', - proxy_port=None): + proxy_port=None, private_key_path=None): """Implementation of an actual update. See PerformUpdate for description of args. Subclasses must override this @@ -410,32 +482,20 @@ class RealAUTest(unittest.TestCase, AUTest): def PrepareBase(self, image_path): """Auto-update to base image to prepare for test.""" - self.PerformUpdate(image_path) + _PrepareRealBase(image_path) def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', - proxy_port=None): + proxy_port=None, private_key_path=None): """Updates a remote image using image_to_live.sh.""" stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) cmd = ['%s/image_to_live.sh' % self.crosutils, - '--image=%s' % image_path, '--remote=%s' % self.remote, stateful_change_flag, '--verify', - '--src_image=%s' % src_image_path ] - - if proxy_port: - cmd.append('--proxy_port=%s' % proxy_port) - - if self.verbose: - try: - RunCommand(cmd) - except Exception, e: - raise UpdateException(1, e.message) - else: - (code, stdout, stderr) = RunCommandCaptureOutput(cmd) - if code != 0: - raise UpdateException(code, stdout) + self.AppendUpdateFlags(cmd, image_path, src_image_path, proxy_port, + private_key_path) + self.RunUpdateCmd(cmd) def _UpdateUsingPayload(self, update_path, stateful_change='old', proxy_port=None): @@ -447,19 +507,8 @@ class RealAUTest(unittest.TestCase, AUTest): stateful_change_flag, '--verify', ] - - if proxy_port: - cmd.append('--proxy_port=%s' % proxy_port) - - if self.verbose: - try: - RunCommand(cmd) - except Exception, e: - raise UpdateException(1, e.message) - else: - (code, stdout, stderr) = RunCommandCaptureOutput(cmd) - if code != 0: - raise UpdateException(code, stdout) + if proxy_port: cmd.append('--proxy_port=%s' % proxy_port) + self.RunUpdateCmd(cmd) def VerifyImage(self, percent_required_to_pass): """Verifies an image using run_remote_tests.sh with verification suite.""" @@ -474,10 +523,6 @@ class RealAUTest(unittest.TestCase, AUTest): class VirtualAUTest(unittest.TestCase, AUTest): """Test harness for updating virtual machines.""" - # VM Constants. - _FULL_VDISK_SIZE = 6072 - _FULL_STATEFULFS_SIZE = 3074 - # Class variables used to acquire individual VM variables per test. _vm_lock = threading.Lock() _next_port = 9222 @@ -501,7 +546,6 @@ class VirtualAUTest(unittest.TestCase, AUTest): def setUp(self): """Unit test overriden method. Is called before every test.""" AUTest.setUp(self) - self.vm_image_path = None self._AcquireUniquePortAndPidFile() self._KillExistingVM(self._kvm_pid_file) @@ -512,85 +556,37 @@ class VirtualAUTest(unittest.TestCase, AUTest): def ProcessOptions(cls, parser, options): """Processes vm-specific options.""" AUTest.ProcessOptions(parser, options) - cls.board = options.board # Communicate flags to tests. cls.graphics_flag = '' if options.no_graphics: cls.graphics_flag = '--no_graphics' - - if not cls.board: - parser.error('Need board to convert base image to vm.') + if not cls.board: parser.error('Need board to convert base image to vm.') def PrepareBase(self, image_path): """Creates an update-able VM based on base image.""" - # Needed for VM delta updates. We need to use the qemu image rather - # than the base image on a first update. By tracking the first_update - # we can set src_image to the qemu form of the base image when - # performing generating the delta payload. - self._first_update = True - self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( - image_path) - if not os.path.exists(self.vm_image_path): - Info('Creating %s' % vm_image_path) - RunCommand(['%s/image_to_vm.sh' % self.crosutils, - '--full', - '--from=%s' % ReinterpretPathForChroot( - os.path.dirname(image_path)), - '--vdisk_size=%s' % self._FULL_VDISK_SIZE, - '--statefulfs_size=%s' % self._FULL_STATEFULFS_SIZE, - '--board=%s' % self.board, - '--test_image'], enter_chroot=True) - - Info('Using %s as base' % self.vm_image_path) - self.assertTrue(os.path.exists(self.vm_image_path)) + self._PrepareVMBase(image_path) def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', - proxy_port=''): + proxy_port='', private_key_path=None): """Updates VM image with image_path.""" stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) if src_image_path and self._first_update: src_image_path = self.vm_image_path self._first_update = False - # Check image payload cache first. - update_id = _GenerateUpdateId(target=image_path, src=src_image_path) - cache_path = dev_server_cache[update_id] - if cache_path: - Info('Using cache %s' % cache_path) - update_url = DevServerWrapper.GetDevServerURL(proxy_port, cache_path) - cmd = ['%s/cros_run_vm_update' % self.crosutilsbin, - '--vm_image_path=%s' % self.vm_image_path, - '--snapshot', - self.graphics_flag, - '--persist', - '--kvm_pid=%s' % self._kvm_pid_file, - '--ssh_port=%s' % self._ssh_port, - stateful_change_flag, - '--update_url=%s' % update_url, - ] - else: - cmd = ['%s/cros_run_vm_update' % self.crosutilsbin, - '--update_image_path=%s' % image_path, - '--vm_image_path=%s' % self.vm_image_path, - '--snapshot', - self.graphics_flag, - '--persist', - '--kvm_pid=%s' % self._kvm_pid_file, - '--ssh_port=%s' % self._ssh_port, - stateful_change_flag, - '--src_image=%s' % src_image_path, - '--proxy_port=%s' % proxy_port - ] + cmd = ['%s/cros_run_vm_update' % self.crosutilsbin, + '--vm_image_path=%s' % self.vm_image_path, + '--snapshot', + self.graphics_flag, + '--persist', + '--kvm_pid=%s' % self._kvm_pid_file, + '--ssh_port=%s' % self._ssh_port, + stateful_change_flag, + ] - if self.verbose: - try: - RunCommand(cmd) - except Exception, e: - raise UpdateException(1, e.message) - else: - (code, stdout, stderr) = RunCommandCaptureOutput(cmd) - if code != 0: - raise UpdateException(code, stdout) + self.AppendUpdateFlags(cmd, image_path, src_image_path, proxy_port, + private_key_path) + self.RunUpdateCmd(cmd) def _UpdateUsingPayload(self, update_path, stateful_change='old', proxy_port=None): @@ -606,19 +602,8 @@ class VirtualAUTest(unittest.TestCase, AUTest): '--ssh_port=%s' % self._ssh_port, stateful_change_flag, ] - - if proxy_port: - cmd.append('--proxy_port=%s' % proxy_port) - - if self.verbose: - try: - RunCommand(cmd) - except Exception, e: - raise UpdateException(1, e.message) - else: - (code, stdout, stderr) = RunCommandCaptureOutput(cmd) - if code != 0: - raise UpdateException(code, stdout) + if proxy_port: cmd.append('--proxy_port=%s' % proxy_port) + self.RunUpdateCmd(cmd) def VerifyImage(self, percent_required_to_pass): """Runs vm smoke suite to verify image.""" @@ -642,8 +627,12 @@ class VirtualAUTest(unittest.TestCase, AUTest): return self.AssertEnoughTestsPassed(self, output, percent_required_to_pass) -class GenerateVirtualAUDeltasTest(VirtualAUTest): - """Class the overrides VirtualAUTest and stores deltas we will generate.""" +class PregenerateAUDeltas(unittest.TestCase, AUTest): + """Magical class that emulates an AUTest to store deltas we will generate. + + This class emulates an AUTest such that when it runs as a TestCase it runs + through the exact up + """ delta_list = {} def setUp(self): @@ -652,16 +641,29 @@ class GenerateVirtualAUDeltasTest(VirtualAUTest): def tearDown(self): pass + @classmethod + def ProcessOptions(cls, parser, options): + AUTest.ProcessOptions(parser, options) + cls.au_type = options.type + + def PrepareBase(self, image_path): + if self.au_type == 'vm': + self._PrepareVMBase(image_path) + else: + self._PrepareRealBase(image_path) + def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', - proxy_port=None): - if src_image_path and self._first_update: + proxy_port=None, private_key_path=None): + if self.au_type == 'vm' and src_image_path and self._first_update: src_image_path = self.vm_image_path self._first_update = False + # Generate a value that combines delta with private key path. + val = '%s+%s' % (src_image_path, private_key_path) if not self.delta_list.has_key(image_path): - self.delta_list[image_path] = set([src_image_path]) + self.delta_list[image_path] = set([val]) else: - self.delta_list[image_path].add(src_image_path) + self.delta_list[image_path].add(val) def AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): pass @@ -756,15 +758,16 @@ class DevServerWrapper(threading.Thread): return url -def _GenerateUpdateId(target, src): +def _GenerateUpdateId(target, src, key): """Returns a simple representation id of target and src paths.""" - if src: - return '%s->%s' % (target, src) - else: - return target + update_id = target + if src: update_id = '->'.join([update_id, src]) + if key: update_id = '+'.join([update_id, key]) + return update_id -def _RunParallelJobs(number_of_sumultaneous_jobs, jobs, jobs_args, print_status): +def _RunParallelJobs(number_of_sumultaneous_jobs, jobs, jobs_args, + print_status): """Runs set number of specified jobs in parallel. @@ -834,40 +837,47 @@ def _PregenerateUpdates(parser, options): Raises: UpdateException if we fail to generate an update. """ - def _GenerateVMUpdate(target, src): + def _GenerateVMUpdate(target, src, private_key_path): """Generates an update using the devserver.""" - target = ReinterpretPathForChroot(target) - if src: - src = ReinterpretPathForChroot(src) + command = ['./enter_chroot.sh', + '--nogit_config', + '--', + 'sudo', + './start_devserver', + '--pregenerate_update', + '--exit', + ] + # Add actual args to command. + command.append('--image=%s' % ReinterpretPathForChroot(target)) + if src: command.append('--src_image=%s' % ReinterpretPathForChroot(src)) + if options.type == 'vm': command.append('--for_vm') + if private_key_path: + command.append('--private_key=%s' % + ReinterpretPathForChroot(private_key_path)) - return RunCommandCaptureOutput(['./enter_chroot.sh', - '--nogit_config', - '--', - 'sudo', - './start_devserver', - '--pregenerate_update', - '--exit', - '--image=%s' % target, - '--src_image=%s' % src, - '--for_vm', - ], combine_stdout_stderr=True, - print_cmd=False) + return RunCommandCaptureOutput(command, combine_stdout_stderr=True, + print_cmd=True) # Get the list of deltas by mocking out update method in test class. - test_suite = _PrepareTestSuite(parser, options, GenerateVirtualAUDeltasTest) + test_suite = _PrepareTestSuite(parser, options, PregenerateAUDeltas) test_result = unittest.TextTestRunner(verbosity=0).run(test_suite) + if not test_result.wasSuccessful(): + raise UpdateException(1, 'Error finding updates to generate.') Info('The following delta updates are required.') update_ids = [] jobs = [] args = [] - for target, srcs in GenerateVirtualAUDeltasTest.delta_list.items(): - for src in srcs: - update_id = _GenerateUpdateId(target=target, src=src) + for target, srcs in PregenerateAUDeltas.delta_list.items(): + for src_key in srcs: + (src, key) = src_key.split('+') + # TODO(sosa): Add private key as part of caching name once devserver can + # handle it its own cache. + update_id = _GenerateUpdateId(target=target, src=src, key=key) print >> sys.stderr, 'AU: %s' % update_id update_ids.append(update_id) jobs.append(_GenerateVMUpdate) - args.append((target, src)) + args.append((target, src, key)) raw_results = _RunParallelJobs(options.jobs, jobs, args, print_status=True) results = [] @@ -919,12 +929,74 @@ def _RunTestsInParallel(parser, options, test_class): Die('Test harness was not successful') +def InsertPublicKeyIntoImage(image_path, key_path): + """Inserts public key into image @ static update_engine location.""" + from_dir = os.path.dirname(image_path) + image = os.path.basename(image_path) + crosutils_dir = os.path.abspath(__file__).rsplit('/', 2)[0] + target_key_path = 'usr/share/update_engine/update-payload-key.pub.pem' + + # Temporary directories for this function. + rootfs_dir = tempfile.mkdtemp(suffix='rootfs', prefix='tmp') + stateful_dir = tempfile.mkdtemp(suffix='stateful', prefix='tmp') + + Info('Copying %s into %s' % (key_path, image_path)) + try: + RunCommand(['./mount_gpt_image.sh', + '--from=%s' % from_dir, + '--image=%s' % image, + '--rootfs_mountpt=%s' % rootfs_dir, + '--stateful_mountpt=%s' % stateful_dir, + ], print_cmd=False, redirect_stdout=True, + redirect_stderr=True, cwd=crosutils_dir) + path = os.path.join(rootfs_dir, target_key_path) + dir_path = os.path.dirname(path) + RunCommand(['sudo', 'mkdir', '--parents', dir_path], print_cmd=False) + RunCommand(['sudo', 'cp', '--force', '-p', key_path, path], + print_cmd=False) + finally: + # Unmount best effort regardless. + RunCommand(['./mount_gpt_image.sh', + '--unmount', + '--rootfs_mountpt=%s' % rootfs_dir, + '--stateful_mountpt=%s' % stateful_dir, + ], print_cmd=False, redirect_stdout=True, redirect_stderr=True, + cwd=crosutils_dir) + # Clean up our directories. + os.rmdir(rootfs_dir) + os.rmdir(stateful_dir) + + RunCommand(['bin/cros_make_image_bootable', from_dir, image, ], + print_cmd=False, redirect_stdout=True, redirect_stderr=True, + enter_chroot=True, cwd=crosutils_dir) + + +def CleanPreviousWork(options): + """Cleans up previous work from the devserver cache and local image cache.""" + Info('Cleaning up previous work.') + # Wipe devserver cache. + RunCommandCaptureOutput( + ['sudo', './start_devserver', '--clear_cache', '--exit', ], + enter_chroot=True, print_cmd=False, combine_stdout_stderr=True) + + # Clean previous vm images if they exist. + if options.type == 'vm': + target_vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( + options.target_image) + base_vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( + options.base_image) + if os.path.exists(target_vm_image_path): os.remove(target_vm_image_path) + if os.path.exists(base_vm_image_path): os.remove(base_vm_image_path) + + def main(): parser = optparse.OptionParser() parser.add_option('-b', '--base_image', help='path to the base image.') parser.add_option('-r', '--board', help='board for the images.') + parser.add_option('--clean', default=False, dest='clean', action='store_true', + help='Clean all previous state') parser.add_option('--no_delta', action='store_false', default=True, dest='delta', help='Disable using delta updates.') @@ -932,6 +1004,10 @@ def main(): help='Disable graphics for the vm test.') parser.add_option('-j', '--jobs', default=8, type=int, help='Number of simultaneous jobs') + parser.add_option('--public_key', default=None, + help='Public key to use on images and updates.') + parser.add_option('--private_key', default=None, + help='Private key to use on images and updates.') parser.add_option('-q', '--quick_test', default=False, action='store_true', help='Use a basic test to verify image.') parser.add_option('-m', '--remote', @@ -948,31 +1024,52 @@ def main(): 'possible.') (options, leftover_args) = parser.parse_args() - if leftover_args: - parser.error('Found extra options we do not support: %s' % leftover_args) + if leftover_args: parser.error('Found unsupported flags: %s' % leftover_args) + + assert options.target_image and os.path.exists(options.target_image), \ + 'Target image path does not exist' + if not options.base_image: + Info('Base image not specified. Using target image as base image.') + options.base_image = options.target_image + + # Sanity checks on keys and insert them onto the image. The caches must be + # cleaned so we know that the vm images and payloads match the possibly new + # key. + if options.private_key or options.public_key: + error_msg = ('Could not find %s key. Both private and public keys must be ' + 'specified if either is specified.') + assert options.private_key and os.path.exists(options.private_key), \ + error_msg % 'private' + assert options.public_key and os.path.exists(options.public_key), \ + error_msg % 'public' + InsertPublicKeyIntoImage(options.target_image, options.public_key) + InsertPublicKeyIntoImage(options.base_image, options.public_key) + options.clean = True + + # Clean up previous work if requested. + if options.clean: CleanPreviousWork(options) # Figure out the test_class. if options.type == 'vm': test_class = VirtualAUTest elif options.type == 'real': test_class = RealAUTest else: parser.error('Could not parse harness type %s.' % options.type) - # TODO(sosa): Caching doesn't really make sense on non-vm images (yet). + # Generate cache of updates to use during test harness. global dev_server_cache - if options.type == 'vm' and options.jobs > 1: - dev_server_cache = _PregenerateUpdates(parser, options) - my_server = DevServerWrapper() - my_server.start() - try: + dev_server_cache = _PregenerateUpdates(parser, options) + my_server = DevServerWrapper() + my_server.start() + try: + if options.type == 'vm': _RunTestsInParallel(parser, options, test_class) - finally: - my_server.Stop() - - else: - dev_server_cache = None - test_suite = _PrepareTestSuite(parser, options, test_class) - test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) - if not test_result.wasSuccessful(): - Die('Test harness was not successful.') + else: + # TODO(sosa) - Take in a machine pool for a real test. + # Can't run in parallel with only one remote device. + test_suite = _PrepareTestSuite(parser, options, test_class) + test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) + if not test_result.wasSuccessful(): Die('Test harness failed.') + finally: + my_server.Stop() if __name__ == '__main__': diff --git a/bin/cros_run_vm_update b/bin/cros_run_vm_update index 05a1d44afb..c87e25d625 100755 --- a/bin/cros_run_vm_update +++ b/bin/cros_run_vm_update @@ -35,7 +35,7 @@ DEFINE_string proxy_port "" \ DEFINE_string src_image "" \ "Create a delta update by passing in the image on the remote machine." DEFINE_string stateful_update_flag "" "Flags to pass to stateful update." s -DEFINE_string update_image_path "" "Path of the image to update to." u +DEFINE_string image "" "Path of the image to update to." u DEFINE_string update_url "" "Full url of an update image." DEFINE_string vm_image_path "" "Path of the VM image to update from." v @@ -52,8 +52,8 @@ trap stop_kvm EXIT start_kvm "${FLAGS_vm_image_path}" retry_until_ssh -if [ -n "${FLAGS_update_image_path}" ]; then - IMAGE_ARGS="--image=$(readlink -f ${FLAGS_update_image_path})" +if [ -n "${FLAGS_image}" ]; then + IMAGE_ARGS="--image=$(readlink -f ${FLAGS_image})" fi if [ -n "${FLAGS_payload}" ]; then diff --git a/bin/ctest.py b/bin/ctest.py index 9388eaa225..95f9377e42 100755 --- a/bin/ctest.py +++ b/bin/ctest.py @@ -225,17 +225,8 @@ def GrabZipAndExtractImage(zip_url, download_folder, image_name) : fh.close() -def WipeDevServerCache(): - """Wipes the cache of the dev server.""" - RunCommand(['sudo', - './start_devserver', - '--clear_cache', - '--exit', - ], enter_chroot=True) - - def RunAUTestHarness(board, channel, latest_url_base, zip_server_base, - no_graphics, type, remote): + no_graphics, type, remote, clean): """Runs the auto update test harness. The auto update test harness encapsulates testing the auto-update mechanism @@ -251,6 +242,7 @@ def RunAUTestHarness(board, channel, latest_url_base, zip_server_base, no_graphics: boolean - If True, disable graphics during vm test. type: which test harness to run. Possible values: real, vm. remote: ip address for real test harness run. + clean: Clean the state of test harness before running. """ crosutils_root = os.path.join(os.path.dirname(__file__), '..') download_folder = os.path.abspath('latest_download') @@ -262,6 +254,9 @@ def RunAUTestHarness(board, channel, latest_url_base, zip_server_base, cwd=crosutils_root, redirect_stdout=True, print_cmd=True).strip() + update_engine_path = os.path.join(crosutils_root, '..', 'platform', + 'update_engine') + cmd = ['bin/cros_au_test_harness', '--base_image=%s' % os.path.join(download_folder, _IMAGE_TO_EXTRACT), @@ -270,8 +265,13 @@ def RunAUTestHarness(board, channel, latest_url_base, zip_server_base, '--board=%s' % board, '--type=%s' % type, '--remote=%s' % remote, + '--private_key=%s' % os.path.join(update_engine_path, + 'unittest_key.pem'), + '--public_key=%s' % os.path.join(update_engine_path, + 'unittest_key.pub.pem'), ] if no_graphics: cmd.append('--no_graphics') + if clean: cmd.append('--clean') RunCommand(cmd, cwd=crosutils_root) @@ -299,25 +299,14 @@ def main(): parser.set_usage(parser.format_help()) (options, args) = parser.parse_args() - if args: - parser.error('Extra args found %s.' % args) - - if not options.board: - parser.error('Need board for image to compare against.') - - if not options.channel: - parser.error('Need channel for image to compare against.') - - if not options.zipbase: - parser.error('Need zip url base to get images.') - - if not options.cache: - Info('Wiping dev server cache.') - WipeDevServerCache() + if args: parser.error('Extra args found %s.' % args) + if not options.board: parser.error('Need board for image to compare against.') + if not options.channel: parser.error('Need channel e.g. dev-channel.') + if not options.zipbase: parser.error('Need zip url base to get images.') RunAUTestHarness(options.board, options.channel, options.latestbase, options.zipbase, options.no_graphics, options.type, - options.remote) + options.remote, not options.cache) if __name__ == '__main__': diff --git a/image_to_vm.sh b/image_to_vm.sh index b517bc102c..dbc30eea0e 100755 --- a/image_to_vm.sh +++ b/image_to_vm.sh @@ -50,7 +50,7 @@ DEFINE_boolean factory_install $FLAGS_FALSE \ # We default to TRUE so the buildbot gets its image. Note this is different # behavior from image_to_usb.sh -DEFINE_boolean force_copy ${FLAGS_TRUE} "Always rebuild test image" +DEFINE_boolean force_copy ${FLAGS_FALSE} "Always rebuild test image" DEFINE_string format "qemu" \ "Output format, either qemu, vmware or virtualbox" DEFINE_string from "" \