#!/bin/bash # Copyright (c) 2023 by the Flatcar Maintainers. # Use of this source code is governed by the Apache 2.0 license. # Helper script for building OS images w/ sysexts included. # Called by build_image -> prod_image_util.sh. # This is a separate script mainly so we can trap EXIT and clean up our mounts # without interfering with traps set by build_image. # We're in build_library/, script root is one up SCRIPT_ROOT="$(cd "$(dirname "$(readlink -f "$0")")/../"; pwd)" . "${SCRIPT_ROOT}/common.sh" || exit 1 # Script must run inside the chroot assert_inside_chroot switch_to_strict_mode . "${BUILD_LIBRARY_DIR}/build_image_util.sh" || exit 1 # Create a sysext from a package and install it to the OS image. # Conventions: # - For each /, __pkginfo will be built. Can be used in subsequent calls # to build dependent sysexts. # - If ${BUILD_LIBRARY_DIR}/sysext_mangle__ exists it will be used as FS mangle script # when building the sysext. create_prod_sysext() { local BOARD="$1" local output_dir="$2" local workdir="$3" local base_sysext="$4" local install_root="$5" local name="$6" local grp_pkgs="$7" local pkginfo="${8:-}" local -a build_sysext_opts=() local -a grp_pkg mapfile -t grp_pkg <<<"${grp_pkgs//&/$'\n'}" local msg="Installing ${grp_pkg[*]} in sysext ${name}.raw" # Include previous sysexts' pkginfo if supplied if [[ -n "${pkginfo}" ]] ; then if [[ ! -f "${output_dir}/${pkginfo}" ]] ; then die "Sysext build '${name}': unable to find package info at '${output_dir}/${pkginfo}'." fi msg="${msg} w/ package info '${pkginfo}'" build_sysext_opts+=( "--base_pkginfo=${output_dir}/${pkginfo}" ) fi # Include FS mangle script if present if [[ -x "${BUILD_LIBRARY_DIR}/sysext_mangle_${name}" ]] ; then build_sysext_opts+=( "--manglefs_script=${BUILD_LIBRARY_DIR}/sysext_mangle_${name}" ) msg="${msg}, FS mangle script 'sysext_mangle_${name}'" fi info "${msg}." sudo "${SCRIPTS_DIR}/build_sysext" \ --board="${BOARD}" \ --image_builddir="${workdir}/sysext-build" \ --squashfs_base="${base_sysext}" \ --generate_pkginfo \ "${build_sysext_opts[@]}" \ "${name}" "${grp_pkg[@]}" sudo mv "${workdir}/sysext-build/${name}.raw" "${workdir}/sysext-build/${name}_pkginfo.raw" \ "${workdir}/sysext-build/${name}"_*.txt "${output_dir}" sudo mkdir -p "${install_root}"/usr/share/flatcar/sysext sudo install -m 0644 -D "${output_dir}/${name}.raw" "${install_root}"/usr/share/flatcar/sysext/ sudo mkdir -p "${install_root}"/etc/extensions/ sudo ln -sf "/usr/share/flatcar/sysext/${name}.raw" "${install_root}/etc/extensions/${name}.raw" } # -- BOARD="$1" BUILD_DIR="$2" root_fs_dir="$3" merged_rootfs_dir="$4" sysext_output_dir="$5" sysexts_list="$6" grp_pkg="" prev_pkginfo="" sysext_workdir="${BUILD_DIR}/prod-sysext-work" sysext_mountdir="${BUILD_DIR}/prod-sysext-work/mounts" sysext_base="${sysext_workdir}/base-os.squashfs" function cleanup() { sudo umount "${sysext_mountdir}"/* || true rm -rf "${sysext_workdir}" || true } # -- trap cleanup EXIT rm -rf "${sysext_workdir}" "${sysext_output_dir}" mkdir "${sysext_workdir}" "${sysext_output_dir}" info "creating temporary base OS squashfs" sudo mksquashfs "${root_fs_dir}" "${sysext_base}" -noappend # Build sysexts on top of root fs and mount sysexts' squashfs + pkginfo squashfs # for combined overlay later. prev_pkginfo="" sysext_lowerdirs="${sysext_mountdir}/rootfs-lower" for sysext in ${sysexts_list//,/ }; do # format is ":/" name="${sysext%:*}" grp_pkg="${sysext#*:}" create_prod_sysext "${BOARD}" \ "${sysext_output_dir}" \ "${sysext_workdir}" \ "${sysext_base}" \ "${root_fs_dir}"\ "${name}" \ "${grp_pkg}" \ "${prev_pkginfo}" mkdir -p "${sysext_mountdir}/${name}" \ "${sysext_mountdir}/${name}_pkginfo" sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}.raw" \ "${sysext_mountdir}/${name}" sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}_pkginfo.raw" \ "${sysext_mountdir}/${name}_pkginfo" sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}" sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}_pkginfo" prev_pkginfo="${name}_pkginfo.raw" done # Mount the combined overlay (base OS, sysexts, and syset pkginfos) and copy a snapshot # into the designated output dir for upper layers to process. mkdir -p "${sysext_mountdir}/rootfs-lower" sudo mount -rt squashfs -o loop,nodev "${sysext_base}" "${sysext_mountdir}/rootfs-lower" # Mount overlay for report generation mkdir -p "${sysext_workdir}/.work" mkdir -p "${sysext_mountdir}/rootfs-upper" sudo mount -t overlay overlay \ -o lowerdir="${sysext_lowerdirs}",upperdir="${sysext_mountdir}/rootfs-upper",workdir="${sysext_workdir}/.work" \ "${sysext_mountdir}/rootfs-upper" sudo rm -rf "${merged_rootfs_dir}" sudo cp -a "${sysext_mountdir}/rootfs-upper" "${merged_rootfs_dir}" cleanup trap -- EXIT