Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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")
Exemplo n.º 4
0
    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