def test_image_update_broken_kernel( self, bitbake_variables, connection, latest_mender_image, http_server, board_type, use_s3, s3_address, ): """Test that an update with a broken kernel rolls back correctly. This is distinct from the test_broken_image_update test, which corrupts the filesystem. When grub.d integration is enabled, these two scenarios trigger very different code paths.""" file_flag = Helpers.get_file_flag(bitbake_variables) (active_before, passive_before) = determine_active_passive_part( bitbake_variables, connection) image_type = bitbake_variables["MENDER_DEVICE_TYPE"] temp_artifact = "temporary_artifact.mender" try: shutil.copyfile(latest_mender_image, temp_artifact) # Assume that artifact has the same kernel names as the currently # running image. kernels = connection.run( "find /boot/ -maxdepth 1 -name '*linu[xz]*' -o -name '*Image'" ).stdout.split() for kernel in kernels: # Inefficient, but there shouldn't be too many kernels. subprocess.check_call( ["mender-artifact", "rm", f"{temp_artifact}:{kernel}"]) Helpers.install_update( temp_artifact, connection, http_server, board_type, use_s3, s3_address, ) reboot(connection) # Now qemu is auto-rebooted twice; once to boot the dummy image, # where it fails, and the boot loader auto-reboots a second time # into the original partition. output = run_after_connect("mount", connection) # The update should have reverted to the original active partition, # since the kernel was missing. assert output.find(active_before) >= 0 assert output.find(passive_before) < 0 finally: os.remove(temp_artifact)
def do_install_mender_binary_delta( self, request, prepared_test_build, bitbake_variables, bitbake_image, connection, http_server, board_type, use_s3, s3_address, ): build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_INSTALL_append = " mender-binary-delta"'], [ 'BBLAYERS_append = " %s/../meta-mender-commercial"' % bitbake_variables["LAYERDIR_MENDER"] ], ) image = latest_build_artifact(request, prepared_test_build["build_dir"], "core-image*.mender") Helpers.install_update(image, connection, http_server, board_type, use_s3, s3_address) reboot(connection) run_after_connect("true", connection) connection.run("mender -commit") return image
def test_perform_update( self, request, setup_board, prepared_test_build, bitbake_variables, bitbake_image, connection, http_server, board_type, use_s3, s3_address, ): """Perform a delta update. """ if ("read-only-rootfs" not in bitbake_variables["IMAGE_FEATURES"].strip().split()): pytest.skip("Only works when using read-only-rootfs IMAGE_FEATURE") if distutils.spawn.find_executable( "mender-binary-delta-generator") is None: pytest.fail("mender-binary-delta-generator not found in PATH") built_artifact = self.do_install_mender_binary_delta( request, prepared_test_build, bitbake_variables, bitbake_image, connection, http_server, board_type, use_s3, s3_address, ) with make_tempdir() as tmpdir: # Copy previous build artifact_from = os.path.join(tmpdir, "artifact_from.mender") shutil.copyfile(built_artifact, artifact_from) # Create new image installing some extra software build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_INSTALL_append = " nano"'], ) built_artifact = latest_build_artifact( request, prepared_test_build["build_dir"], "core-image*.mender") artifact_to = os.path.join(tmpdir, "artifact_to.mender") shutil.copyfile(built_artifact, artifact_to) # Create delta Artifact using mender-binary-delta-generator artifact_delta = os.path.join(tmpdir, "artifact_delta.mender") subprocess.check_call( f"mender-binary-delta-generator -n v2.0-deltafrom-v1.0 {artifact_from} {artifact_to} -o {artifact_delta}", shell=True, ) # Verbose provides/depends of the different Artifacts and the client (when supported) connection.run("mender show-provides", warn=True) subprocess.check_call( "mender-artifact read %s" % artifact_from, shell=True, ) subprocess.check_call( "mender-artifact read %s" % artifact_to, shell=True, ) subprocess.check_call( "mender-artifact read %s" % artifact_delta, shell=True, ) # Install Artifact, verify partitions and commit (active, passive) = determine_active_passive_part(bitbake_variables, connection) Helpers.install_update(artifact_delta, connection, http_server, board_type, use_s3, s3_address) reboot(connection) run_after_connect("true", connection) (new_active, new_passive) = determine_active_passive_part( bitbake_variables, connection) assert new_active == passive assert new_passive == active connection.run("mender -commit")
def test_network_based_image_update( self, successful_image_update_mender, bitbake_variables, connection, http_server, board_type, use_s3, s3_address, ): (active_before, passive_before) = determine_active_passive_part( bitbake_variables, connection) Helpers.install_update( successful_image_update_mender, connection, http_server, board_type, use_s3, s3_address, ) bootenv_print, _ = bootenv_tools(connection) output = connection.run(f"{bootenv_print} bootcount").stdout assert output.rstrip("\n") == "bootcount=0" output = connection.run(f"{bootenv_print} upgrade_available").stdout assert output.rstrip("\n") == "upgrade_available=1" output = connection.run(f"{bootenv_print} mender_boot_part").stdout assert output.rstrip("\n") == "mender_boot_part=" + passive_before[-1:] # Delete kernel and associated files from currently running partition, # so that the boot will fail if U-Boot for any reason tries to grab the # kernel from the wrong place. connection.run("rm -f /boot/* || true") reboot(connection) run_after_connect("true", connection) (active_after, passive_after) = determine_active_passive_part( bitbake_variables, connection) # The OS should have moved to a new partition, since the image was fine. assert active_after == passive_before assert passive_after == active_before output = connection.run(f"{bootenv_print} bootcount").stdout assert output.rstrip("\n") == "bootcount=1" output = connection.run(f"{bootenv_print} upgrade_available").stdout assert output.rstrip("\n") == "upgrade_available=1" output = connection.run(f"{bootenv_print} mender_boot_part").stdout assert output.rstrip("\n") == "mender_boot_part=" + active_after[-1:] connection.run("mender commit") output = connection.run(f"{bootenv_print} upgrade_available").stdout assert output.rstrip("\n") == "upgrade_available=0" output = connection.run(f"{bootenv_print} mender_boot_part").stdout assert output.rstrip("\n") == "mender_boot_part=" + active_after[-1:] active_before = active_after passive_before = passive_after reboot(connection) run_after_connect("true", connection) (active_after, passive_after) = determine_active_passive_part( bitbake_variables, connection) # The OS should have stayed on the same partition, since we committed. assert active_after == active_before assert passive_after == passive_before