Bug 2779938: Many client jobs fail from fsck-induced double reboots. Add 'touch /fastboot' to kernel rpm boot method used by client tests. Also, factor out shared boot method for kernels installed from source or from rpm, in client/bin/kernel and its unittest.
Note that this patch overlaps with prior patch CL 4132496, which has not yet been applied to SVN, so this patch seems to apply uncleanly by itself. Applying the former patch first should resolve that. Functionally, the second patch totally replaces and extends the effect of the first patch. Using fastboot for boots into the target test kernel has greatly reduced our rate of failed boots due to fsck's bringing back the default kernel. Signed-off-by: Duane Sand <[email protected]> --- autotest/client/bin/kernel.py 2010-07-12 16:31:48.000000000 -0700 +++ autotest/client/bin/kernel.py 2010-07-15 18:23:26.000000000 -0700 @@ -64,7 +64,49 @@ root=root) -class kernel(object): +class BootableKernel(object): + + def __init__(self, job): + self.job = job + self.installed_as = None # kernel choice in bootloader menu + self.image = None + self.initrd = '' + + + def _boot_kernel(self, args, ident_check, expected_ident, subdir, notes): + """ Boot a kernel, with post-boot kernel id check + + @param args: kernel cmdline arguments + @param ident_check: check kernel id after boot + @param expected_ident: + @param subdir: job-step qualifier in status log + @param notes: additional comment in status log + """ + + # If we can check the kernel identity do so. + if ident_check: + when = int(time.time()) + args += " IDENT=%d" % when + self.job.next_step_prepend(["job.end_reboot_and_verify", when, + expected_ident, subdir, notes]) + else: + self.job.next_step_prepend(["job.end_reboot", + subdir, expected_ident, notes]) + + # Point bootloader to the selected tag. + _add_kernel_to_bootloader(self.job.bootloader, + self.job.config_get('boot.default_args'), + self.installed_as, args, self.image, self.initrd) + + # defer fsck for next reboot, to avoid reboots back to default kernel + utils.system('touch /fastboot') # this file is removed automatically + + # Boot it. + self.job.start_reboot() + self.job.reboot(tag=self.installed_as) + + +class kernel(BootableKernel): """ Class for compiling kernels. Data for the object includes the src files @@ -109,7 +151,7 @@ leave Boolean, whether to leave existing tmpdir or not """ - self.job = job + super(kernel, self).__init__(job) self.autodir = job.autodir self.src_dir = os.path.join(tmp_dir, 'src') @@ -120,8 +162,6 @@ self.results_dir = os.path.join(subdir, 'results') self.subdir = os.path.basename(subdir) - self.installed_as = None - if not leave: if os.path.isdir(self.src_dir): utils.system('rm -rf ' + self.src_dir) @@ -450,16 +490,6 @@ self.system_map, self.initrd) - def add_to_bootloader(self, tag='autotest', args=''): - """ add this kernel to bootloader, taking an - optional parameter of space separated parameters - e.g.: kernel.add_to_bootloader('mykernel', 'ro acpi=off') - """ - _add_kernel_to_bootloader(self.job.bootloader, - self.job.config_get('boot.default_args'), - tag, args, self.image, self.initrd) - - def get_kernel_build_arch(self, arch=None): """ Work out the current kernel architecture (as a kernel arch) @@ -526,32 +556,14 @@ just make it happen. """ - # If we can check the kernel identity do so. - expected_ident = self.get_kernel_build_ident() - if ident: - when = int(time.time()) - args += " IDENT=%d" % (when) - self.job.next_step_prepend(["job.end_reboot_and_verify", when, - expected_ident, self.subdir, - self.applied_patches]) - else: - self.job.next_step_prepend(["job.end_reboot", self.subdir, - expected_ident, self.applied_patches]) - - # Check if the kernel has been installed, if not install - # as the default tag and boot that. + # If the kernel has not yet been installed, + # install it now as default tag. if not self.installed_as: self.install() - # Boot the selected tag. - self.add_to_bootloader(args=args, tag=self.installed_as) - - # defer fsck for next reboot, to avoid reboots back to default kernel - utils.system('touch /fastboot') # this file is removed automatically - - # Boot it. - self.job.start_reboot() - self.job.reboot(tag=self.installed_as) + expected_ident = self.get_kernel_build_ident() + self._boot_kernel(args, ident, expected_ident, + self.subdir, self.applied_patches) def get_kernel_build_ver(self): @@ -649,20 +661,19 @@ pickle.dump(temp, open(filename, 'w')) -class rpm_kernel(object): +class rpm_kernel(BootableKernel): """ Class for installing a binary rpm kernel package """ def __init__(self, job, rpm_package, subdir): - self.job = job + super(rpm_kernel, self).__init__(job) self.rpm_package = rpm_package self.log_dir = os.path.join(subdir, 'debug') self.subdir = os.path.basename(subdir) if os.path.exists(self.log_dir): utils.system('rm -rf ' + self.log_dir) os.mkdir(self.log_dir) - self.installed_as = None def build(self, *args, **dargs): @@ -728,44 +739,23 @@ % (vmlinux, rpm_pack)) - def add_to_bootloader(self, tag='autotest', args=''): - """ Add this kernel to bootloader - """ - _add_kernel_to_bootloader(self.job.bootloader, - self.job.config_get('boot.default_args'), - tag, args, self.image, self.initrd) - - def boot(self, args='', ident=True): """ install and boot this kernel """ - # Check if the kernel has been installed, if not install - # as the default tag and boot that. + # If the kernel has not yet been installed, + # install it now as default tag. if not self.installed_as: self.install() - # If we can check the kernel identity do so. expected_ident = self.full_version if not expected_ident: expected_ident = '-'.join([self.version, self.rpm_flavour, self.release]) - if ident: - when = int(time.time()) - args += " IDENT=%d" % (when) - self.job.next_step_prepend(["job.end_reboot_and_verify", - when, expected_ident, None, 'rpm']) - else: - self.job.next_step_prepend(["job.end_reboot", None, - expected_ident, []]) - - # Boot the selected tag. - self.add_to_bootloader(args=args, tag=self.installed_as) - # Boot it. - self.job.start_reboot() - self.job.reboot(tag=self.installed_as) + self._boot_kernel(args, ident, expected_ident, + None, 'rpm') class rpm_kernel_suse(rpm_kernel): --- autotest/client/bin/kernel_unittest.py 2010-07-12 16:31:48.000000000 -0700 +++ autotest/client/bin/kernel_unittest.py 2010-07-15 18:23:26.000000000 -0700 @@ -6,6 +6,99 @@ from autotest_lib.client.bin import kernel, job, utils, kernelexpand from autotest_lib.client.bin import kernel_config, boottool, os_dep + +class TestAddKernelToBootLoader(unittest.TestCase): + + def add_to_bootloader(self, base_args, args, + bootloader_args, bootloader_root, + tag='image', + image='image', initrd='initrd'): + god = mock.mock_god() + bootloader = god.create_mock_class( + boottool.boottool, "boottool") + + # record + bootloader.remove_kernel.expect_call(tag) + bootloader.add_kernel.expect_call( + image, tag, initrd=initrd, args=bootloader_args, + root=bootloader_root) + + # run and check + kernel._add_kernel_to_bootloader( + bootloader, base_args, tag, + args, image, initrd) + god.check_playback() + + + def test_add_kernel_to_bootloader(self): + self.add_to_bootloader(base_args='baseargs', + args='', + bootloader_args='baseargs', + bootloader_root=None) + self.add_to_bootloader(base_args='arg1 root=/dev/oldroot arg2', + args='root=/dev/newroot arg3', + bootloader_args='arg1 arg2 arg3', + bootloader_root='/dev/newroot') + + +class TestBootableKernel(unittest.TestCase): + + def setUp(self): + self.god = mock.mock_god() + self.god.stub_function(time, "time") + self.god.stub_function(utils, "system") + self.god.stub_function(kernel, "_add_kernel_to_bootloader") + job_ = self.god.create_mock_class(job.job, "job") + self.kernel = kernel.BootableKernel(job_) + self.kernel.job.bootloader = self.god.create_mock_class( + boottool.boottool, "boottool") + + + def tearDown(self): + # note: time.time() can only be unstubbed via tearDown() + self.god.unstub_all() + + + def boot_kernel(self, ident_check): + notes = "applied_patches" + when = 1 + args = '' + base_args = 'base_args' + tag = 'ident' + subdir = 'subdir' + self.kernel.image = 'image' + self.kernel.initrd = 'initrd' + self.kernel.installed_as = tag + + # record + args_ = args + if ident_check: + time.time.expect_call().and_return(when) + args_ += " IDENT=%d" % when + status = ["job.end_reboot_and_verify", when, tag, subdir, notes] + else: + status = ["job.end_reboot", subdir, tag, notes] + self.kernel.job.next_step_prepend.expect_call(status) + self.kernel.job.config_get.expect_call( + 'boot.default_args').and_return(base_args) + kernel._add_kernel_to_bootloader.expect_call( + self.kernel.job.bootloader, base_args, tag, + args_, self.kernel.image, self.kernel.initrd) + utils.system.expect_call('touch /fastboot') + self.kernel.job.start_reboot.expect_call() + self.kernel.job.reboot.expect_call(tag=tag) + + # run and check + self.kernel._boot_kernel(args=args, ident_check=ident_check, + expected_ident=tag, subdir=subdir, notes=notes) + self.god.check_playback() + + + def test_boot_kernel(self): + self.boot_kernel(ident_check=False) + self.boot_kernel(ident_check=True) + + class TestKernel(unittest.TestCase): def setUp(self): self.god = mock.mock_god() @@ -473,47 +566,6 @@ self.god.check_playback() - def _setup_add_to_bootloader(self, tag='autotest', args='', image='image', - initrd='initrd', base_args='baseargs', - bootloader_args='baseargs', - bootloader_root=None): - self.construct_kernel() - - # setup - self.kernel.image = image - self.kernel.initrd = initrd - - # record - self.job.config_get.expect_call( - 'boot.default_args').and_return(base_args) - self.job.bootloader.remove_kernel.expect_call(tag) - self.job.bootloader.add_kernel.expect_call( - image, tag, initrd=initrd, args=bootloader_args, - root=bootloader_root) - - - def test_add_to_bootloader(self): - # setup - self._setup_add_to_bootloader() - - # run and check - self.kernel.add_to_bootloader() - self.god.check_playback() - - - def test_add_to_bootloader_root_args(self): - # setup - args = 'root=/dev/newroot arg3' - self._setup_add_to_bootloader(args=args, - base_args='arg1 root=/dev/oldroot arg2', - bootloader_args='arg1 arg2 arg3', - bootloader_root='/dev/newroot') - - # run and check - self.kernel.add_to_bootloader(args=args) - self.god.check_playback() - - def test_get_kernel_build_arch1(self): self.construct_kernel() @@ -573,53 +625,23 @@ self.construct_kernel() self.god.stub_function(self.kernel, "get_kernel_build_ident") self.god.stub_function(self.kernel, "install") - self.god.stub_function(self.kernel, "add_to_bootloader") - self.kernel.applied_patches = "applied_patches" - when = 1 - args = '' - self.kernel.installed_as = False - - # record - self.kernel.get_kernel_build_ident.expect_call().and_return("ident") - time.time.expect_call().and_return(when) - args += " IDENT=%d" % (when) - self.job.next_step_prepend.expect_call(["job.end_reboot_and_verify", - when, "ident", self.subdir, self.kernel.applied_patches]) - self.kernel.install.expect_call() - self.kernel.add_to_bootloader.expect_call(args=args, - tag=False) - utils.system.expect_call('touch /fastboot') - self.job.start_reboot.expect_call() - self.job.reboot.expect_call(tag=False) - - # run and check - self.kernel.boot() - self.god.check_playback() - - - def test_boot_without_ident(self): - self.construct_kernel() - self.god.stub_function(self.kernel, "get_kernel_build_ident") - self.god.stub_function(self.kernel, "install") - self.god.stub_function(self.kernel, "add_to_bootloader") + self.god.stub_function(self.kernel, "_boot_kernel") self.kernel.applied_patches = "applied_patches" - when = 1 + self.kernel.installed_as = None args = '' - self.kernel.installed_as = False + expected_ident = 'ident' + ident = True # record - self.kernel.get_kernel_build_ident.expect_call().and_return("ident") - self.job.next_step_prepend.expect_call(["job.end_reboot", - self.subdir, "ident", self.kernel.applied_patches]) self.kernel.install.expect_call() - self.kernel.add_to_bootloader.expect_call(args=args, - tag=False) - utils.system.expect_call('touch /fastboot') - self.job.start_reboot.expect_call() - self.job.reboot.expect_call(tag=False) + self.kernel.get_kernel_build_ident.expect_call( + ).and_return(expected_ident) + self.kernel._boot_kernel.expect_call( + args, ident, expected_ident, + self.subdir, self.kernel.applied_patches) # run and check - self.kernel.boot(ident=False) + self.kernel.boot(args=args, ident=ident) self.god.check_playback() _______________________________________________ Autotest mailing list [email protected] http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
