diff --git a/bin/cros_au_test_harness b/bin/cros_au_test_harness new file mode 120000 index 0000000000..7c4176f6cb --- /dev/null +++ b/bin/cros_au_test_harness @@ -0,0 +1 @@ +cros_au_test_harness.py \ No newline at end of file diff --git a/bin/cros_au_test_harness.py b/bin/cros_au_test_harness.py new file mode 100755 index 0000000000..eaed1ef2b9 --- /dev/null +++ b/bin/cros_au_test_harness.py @@ -0,0 +1,170 @@ +#!/usr/bin/python + +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import optparse +import os +import sys +import unittest + +sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) +from cros_build_lib import RunCommand, Info, Warning + +_KVM_PID_FILE = '/tmp/harness_pid' +_SCRIPTS_DIR = os.path.join(os.path.dirname(__file__), '..') +_FULL_VDISK_SIZE = 6072 +_FULL_STATEFULFS_SIZE = 2048 + +global base_image_path +global target_image_path + +_VERIFY_SUITE = 'suite_Smoke' + +class AUTest(object): + """Abstract interface that defines an Auto Update test.""" + + def PrepareBase(self): + """Prepares target with base_image_path.""" + pass + + def UpdateImage(self, image_path, stateful_change='old'): + """Updates target with the image given by the image_path. + + Args: + image_path: Path to the image to update with. This image must be a test + image. + stateful_change: How to modify the stateful partition. Values are: + 'old': Don't modify stateful partition. Just update normally. + 'clean': Uses clobber-state to wipe the stateful partition with the + exception of code needed for ssh. + """ + pass + + def VerifyImage(self): + """Verifies the image is correct.""" + pass + + def testFullUpdateKeepStateful(self): + # Prepare and verify the base image has been prepared correctly. + self.PrepareBase() + self.VerifyImage() + + # Update to. + Info('Updating from base image on vm to target image.') + self.UpdateImage(target_image_path) + self.VerifyImage() + + # Update from. + Info('Updating from updated image on vm back to base image.') + self.UpdateImage(base_image_path) + self.VerifyImage() + + def testFullUpdateWipeStateful(self): + # Prepare and verify the base image has been prepared correctly. + self.PrepareBase() + self.VerifyImage() + + # Update to. + Info('Updating from base image on vm to target image and wiping stateful.') + self.UpdateImage(target_image_path, 'clean') + self.VerifyImage() + + # Update from. + Info('Updating from updated image back to base image and wiping stateful.') + self.UpdateImage(base_image_path, 'clean') + self.VerifyImage() + + +class VirtualAUTest(unittest.TestCase, AUTest): + """Test harness for updating virtual machines.""" + vm_image_path = None + + def _KillExistingVM(self, pid_file): + if os.path.exists(pid_file): + Warning('Existing %s found. Deleting and killing process' % + pid_file) + pid = RunCommand(['sudo', 'cat', pid_file], redirect_stdout=True, + enter_chroot=False) + if pid: + RunCommand(['sudo', 'kill', pid.strip()], error_ok=True, + enter_chroot=False) + RunCommand(['sudo', 'rm', pid_file], enter_chroot=False) + + def setUp(self): + """Unit test overriden method. Is called before every test.""" + + self._KillExistingVM(_KVM_PID_FILE) + + def PrepareBase(self): + """Creates an update-able VM based on base image.""" + + self.vm_image_path = ('%s/chromiumos_qemu_image.bin' % os.path.dirname( + base_image_path)) + if not os.path.exists(self.vm_image_path): + Info('Qemu image not found, creating one.') + RunCommand(['%s/image_to_vm.sh' % _SCRIPTS_DIR, + '--full', + '--from %s' % os.path.dirname(base_image_path), + '--vdisk_size %s' % _FULL_VDISK_SIZE, + '--statefulfs_size %s' % _FULL_STATEFULFS_SIZE, + '--test_image'], enter_chroot=True) + else: + Info('Using existing VM image') + + self.assertTrue(os.path.exists(self.vm_image_path)) + + def UpdateImage(self, image_path, stateful_change='old'): + """Updates VM image with image_path.""" + + stateful_change_flag = '' + if stateful_change: + stateful_change_flag = '--stateful_flags=%s' % stateful_change + + RunCommand(['%s/cros_run_vm_update' % os.path.dirname(__file__), + '--update_image_path=%s' % image_path, + '--vm_image_path=%s' % self.vm_image_path, + '--snapshot', + '--persist', + '--kvm_pid=%s' % _KVM_PID_FILE, + stateful_change_flag, + ], enter_chroot=False) + + def VerifyImage(self): + """Runs vm smoke suite to verify image.""" + + # image_to_live already verifies lsb-release matching. This is just + # for additional steps. + + # TODO(sosa): Compare output with results of base image. + RunCommand(['%s/cros_run_vm_test' % os.path.dirname(__file__), + '--image_path=%s' % self.vm_image_path, + '--snapshot', + '--persist', + '--kvm_pid=%s' % _KVM_PID_FILE, + '--test_case=%s' % _VERIFY_SUITE, + ], error_ok=True, enter_chroot=False) + + +if __name__ == '__main__': + parser = optparse.OptionParser() + parser.add_option('-b', '--base_image', + help='path to the base image.') + parser.add_option('-t', '--target_image', + help='path to the target image') + # Set the usage to include flags. + parser.set_usage(parser.format_help()) + # Parse existing sys.argv so we can pass rest to unittest.main. + (options, sys.argv) = parser.parse_args(sys.argv) + + base_image_path = options.base_image + target_image_path = options.target_image + + if not base_image_path: + parser.error('Need path to base image for vm.') + + if not target_image_path: + parser.error('Need path to target image to update with.') + + unittest.main()