From 35bccdbe2fb425671089164e4b8bebb73cf6fd23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20M=C3=BCller?= <mueller@kip.uni-heidelberg.de> Date: Thu, 1 Aug 2024 20:27:38 +0200 Subject: [PATCH] feat: use skopeo and proot to create base image sandbox [DO-NOT-MERGE] Change-Id: Id28e2d75c3e0cc7a399f4c7a01bf57b88b2e3e2d --- bin/yashchiki | 12 ++-- lib/yashchiki/build_base_sandbox.sh | 47 ++++++++++++- lib/yashchiki/build_image.sh | 7 +- lib/yashchiki/build_sandbox.sh | 104 +++++++++++++++++++++++++--- lib/yashchiki/update_build_cache.sh | 18 +++-- 5 files changed, 170 insertions(+), 18 deletions(-) diff --git a/bin/yashchiki b/bin/yashchiki index 2f24443c..77477526 100755 --- a/bin/yashchiki +++ b/bin/yashchiki @@ -348,10 +348,14 @@ env.update({"YASHCHIKI_META_DIR": meta_dir}) run("lib/yashchiki/create_caches.sh", env) run("lib/yashchiki/fetch.sh", env) if config.get("docker_base_image", False): - run("lib/yashchiki/build_base_sandbox.sh", env, [base_sandbox_recipe]) -run(str(pathlib.Path("share", "yashchiki", "styles", args.style, - "create_recipe.sh")), - env) + run("lib/yashchiki/build_base_sandbox.sh", env)# FIXME: , [base_sandbox_recipe]) +# FIXME: dispatch to apptainer-based build or proot via style config? +# (for proot we don't use a apptainer recipe) +create_recipe_script = pathlib.Path("share", "yashchiki", "styles", args.style, + "create_recipe.sh") +if create_recipe_script.exists(): + run(str(create_recipe_script), env) + run("lib/yashchiki/build_sandbox.sh", env) run("lib/yashchiki/build_image.sh", env) diff --git a/lib/yashchiki/build_base_sandbox.sh b/lib/yashchiki/build_base_sandbox.sh index 38c049e5..b6d79f00 100755 --- a/lib/yashchiki/build_base_sandbox.sh +++ b/lib/yashchiki/build_base_sandbox.sh @@ -23,4 +23,49 @@ TARGET_FOLDER="${YASHCHIKI_SANDBOXES}/${CONTAINER_STYLE}" mkdir -p ${YASHCHIKI_SANDBOXES} -apptainer build --fakeroot --force ${YASHCHIKI_BASEIMAGE_NAME} $1 +#apptainer -d build --fakeroot --force ${YASHCHIKI_BASEIMAGE_NAME} $1 + +set -x +skopeo copy docker://${DOCKER_BASE_IMAGE} docker-archive:archive-file.tar:${DOCKER_BASE_IMAGE} +ARCHIVE_FILE=$(realpath archive-file.tar) +mkdir -p ${YASHCHIKI_SANDBOXES}/tmp +pushd ${YASHCHIKI_SANDBOXES}/tmp >/dev/null +tar xf ${ARCHIVE_FILE} +ls +popd >/dev/null +rm -f ${ARCHIVE_FILE} + +mkdir -p ${YASHCHIKI_SANDBOXES}/base_image +pushd ${YASHCHIKI_SANDBOXES}/base_image >/dev/null +find ${YASHCHIKI_SANDBOXES}/tmp -name "*.tar" -exec tar xf {} \; +rm -rf ${YASHCHIKI_SANDBOXES}/tmp +ls +popd >/dev/null + +mkdir -p "${YASHCHIKI_SANDBOXES}/base_image/opt/spack_install_scripts" +rsync -aLv --chmod 0755 "${ROOT_DIR}"/share/yashchiki/styles/${CONTAINER_STYLE}/*.sh "${YASHCHIKI_SANDBOXES}/base_image/opt/spack_install_scripts" +rsync -aLv --chmod 0755 "${ROOT_DIR}"/lib/yashchiki/*.sh "${YASHCHIKI_SANDBOXES}/base_image/opt/spack_install_scripts" +rsync -aLv "${ROOT_DIR}"/lib/yashchiki/*.awk "${YASHCHIKI_SANDBOXES}/base_image/opt/spack_install_scripts" +rsync -aLv "${ROOT_DIR}"/share/yashchiki/patches "${YASHCHIKI_SANDBOXES}/base_image/opt/spack_install_scripts" + +# create a fingerprint by which we can identify the container from within +cat /proc/sys/kernel/random/uuid > "${YASHCHIKI_SANDBOXES}/base_image/opt/fingerprint" + +cat <<EOF > ${YASHCHIKI_SANDBOXES}/base_image/prepare.sh +# prerequisites +ls /opt/spack_install_scripts +RUNLEVEL=1 /opt/spack_install_scripts/install_prerequisites.sh || exit 1 +# cannot specify permissions in files-section +chmod 440 /etc/sudoers +chown root:root /etc/sudoers +# install locales +/usr/sbin/locale-gen +EOF + +pushd / +echo proot -S ${YASHCHIKI_SANDBOXES}/base_image -w /root /bin/dash ${YASHCHIKI_SANDBOXES}/base_image/prepare.sh +PROOT_NO_SECCOMP=1 TMPDIR=/tmp proot -S ${YASHCHIKI_SANDBOXES}/base_image -w /root /bin/dash ${YASHCHIKI_SANDBOXES}/base_image/prepare.sh +popd +echo apptainer -d build --fakeroot --force ${YASHCHIKI_BASEIMAGE_NAME} ${YASHCHIKI_SANDBOXES}/base_image +TMPDIR=/tmp apptainer -d build --fakeroot --force ${YASHCHIKI_BASEIMAGE_NAME} ${YASHCHIKI_SANDBOXES}/base_image +rm -rf ${YASHCHIKI_SANDBOXES}/base_image diff --git a/lib/yashchiki/build_image.sh b/lib/yashchiki/build_image.sh index 6b7578c4..a8251730 100755 --- a/lib/yashchiki/build_image.sh +++ b/lib/yashchiki/build_image.sh @@ -3,6 +3,10 @@ set -euo pipefail shopt -s inherit_errexit 2>/dev/null || true +# for env vars +SOURCE_DIR="$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")" +source "${SOURCE_DIR}/commons.sh" + if [ -z "${YASHCHIKI_ENABLE_STAGE_IMAGE:-}" ]; then echo "Skipping stage build-base-sandbox." exit 0 @@ -15,4 +19,5 @@ if test -f "${YASHCHIKI_IMAGE_NAME}"; then exit 1 fi -apptainer build --fakeroot ${YASHCHIKI_IMAGE_NAME} "${TARGET_FOLDER}" +set -x +TMPDIR=/tmp apptainer -d build --fakeroot --bind ${YASHCHIKI_SPACK_PATH}:/opt/spack,ro ${YASHCHIKI_IMAGE_NAME} "${TARGET_FOLDER}" diff --git a/lib/yashchiki/build_sandbox.sh b/lib/yashchiki/build_sandbox.sh index 17a80b5f..14723b1e 100755 --- a/lib/yashchiki/build_sandbox.sh +++ b/lib/yashchiki/build_sandbox.sh @@ -3,6 +3,10 @@ set -euo pipefail shopt -s inherit_errexit 2>/dev/null || true +# for env vars +SOURCE_DIR="$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")" +source "${SOURCE_DIR}/commons.sh" + if [ -z "${YASHCHIKI_ENABLE_STAGE_BUILD_BASE:-}" ]; then echo "Skipping stage build-base." exit 0 @@ -23,11 +27,95 @@ TARGET_FOLDER="${YASHCHIKI_SANDBOXES}/${CONTAINER_STYLE}" mkdir -p ${YASHCHIKI_SANDBOXES} -apptainer build \ - --bind ${YASHCHIKI_CACHES_ROOT}/download_cache:/opt/spack/var/spack/cache \ - --bind ${YASHCHIKI_CACHES_ROOT}/spack_ccache:/opt/ccache \ - --bind ${YASHCHIKI_CACHES_ROOT}/build_caches:/opt/build_cache \ - --bind ${YASHCHIKI_CACHES_ROOT}/preserved_packages:/opt/preserved_packages \ - --bind ${JOB_TMP_SPACK}:/tmp/spack \ - --bind ${YASHCHIKI_SPACK_CONFIG}:/tmp/spack_config \ - --fakeroot --sandbox "${TARGET_FOLDER}" "${YASHCHIKI_RECIPE_PATH}" | tee out_singularity_build_recipe.txt +set -x +skopeo copy sif:${YASHCHIKI_BASEIMAGE_NAME} docker-archive:archive-file.tar +ARCHIVE_FILE=$(realpath archive-file.tar) +mkdir -p ${YASHCHIKI_SANDBOXES}/tmp +pushd ${YASHCHIKI_SANDBOXES}/tmp >/dev/null +tar xf ${ARCHIVE_FILE} +ls +popd >/dev/null +rm -f ${ARCHIVE_FILE} + +mkdir -p ${TARGET_FOLDER} +pushd ${TARGET_FOLDER} >/dev/null +find ${YASHCHIKI_SANDBOXES}/tmp -name "*.tar" -exec tar xf {} \; +rm -rf ${YASHCHIKI_SANDBOXES}/tmp +ls +popd >/dev/null + +ls ${TARGET_FOLDER} + +# FIXME: from recipe +# location to bind-mount spack-folder +mkdir ${TARGET_FOLDER}/opt/spack +# location to bind-mount spack-source-cache-folder +mkdir -p ${TARGET_FOLDER}/opt/spack/var/spack/cache/ +# copy spack repo +rsync -a ${YASHCHIKI_SPACK_PATH}/ ${TARGET_FOLDER}/opt/spack +# location to bind-mount ccache +mkdir ${TARGET_FOLDER}/opt/ccache +# location to bind-mount build_cache +mkdir -p "${TARGET_FOLDER}${BUILD_CACHE_INSIDE}" +# # create buildcache directory if it does not exist +[ ! -d "${BUILD_CACHE_OUTSIDE}" ] && mkdir -p "${BUILD_CACHE_OUTSIDE}" +# location to mount the full build cache folder into container because some files might be symlinked to other buildcaches +# mount --no-mtab --bind "${BASE_BUILD_CACHE_OUTSIDE}" "\${APPTAINER_ROOTFS}${BASE_BUILD_CACHE_INSIDE}" +# location to bind-mount preserved packages in case the build fails +mkdir -p "${TARGET_FOLDER}${PRESERVED_PACKAGES_INSIDE}" +# location to bind-mount tmp-folder +mkdir -p "${TARGET_FOLDER}/tmp/spack" +# location to bind-mount spack config tmp-folder +mkdir -p "${TARGET_FOLDER}/tmp/spack_config" +# copy install scripts +#mkdir "\${APPTAINER_ROOTFS}/${SPACK_INSTALL_SCRIPTS}" +rsync -a --chmod 0755 "${ROOT_DIR}"/share/yashchiki/styles/${CONTAINER_STYLE}/*.sh "${TARGET_FOLDER}${SPACK_INSTALL_SCRIPTS}" +rsync -a --chmod 0755 "${ROOT_DIR}"/lib/yashchiki/*.sh "${TARGET_FOLDER}${SPACK_INSTALL_SCRIPTS}" +rsync -a "${ROOT_DIR}"/lib/yashchiki/*.awk "${TARGET_FOLDER}${SPACK_INSTALL_SCRIPTS}" +rsync -a "${ROOT_DIR}"/share/yashchiki/patches "${TARGET_FOLDER}/${SPACK_INSTALL_SCRIPTS}" +mkdir -p "${TARGET_FOLDER}/${META_DIR_INSIDE}" +rsync -a "${META_DIR_OUTSIDE}/" "${TARGET_FOLDER}/${META_DIR_INSIDE}" +# init scripts for user convenience +mkdir -p "${TARGET_FOLDER}/opt/init" +rsync -a "${ROOT_DIR}"/share/yashchiki/misc-files/init/*.sh "${TARGET_FOLDER}/opt/init" + +rsync -a ${ROOT_DIR}/share/yashchiki/misc-files/setup-spack.sh ${TARGET_FOLDER}/etc/profile.d/setup-spack.sh +rsync -a ${ROOT_DIR}/share/yashchiki/misc-files/locale.gen ${TARGET_FOLDER}/etc/locale.gen +rsync -a ${ROOT_DIR}/share/yashchiki/misc-files/locale.alias ${TARGET_FOLDER}/etc/locale.alias +#rsync -a ${ROOT_DIR}/share/yashchiki/misc-files/sudoers ${TARGET_FOLDER}/etc/sudoers # FIXME: permission denied? + + +cat <<EOF > ${TARGET_FOLDER}/build.sh +# propagate environment variables to container recipe +export DEPENDENCY_PYTHON="${DEPENDENCY_PYTHON}" +export YASHCHIKI_BUILD_SPACK_GCC="${YASHCHIKI_BUILD_SPACK_GCC}" +export YASHCHIKI_SPACK_GCC="${YASHCHIKI_SPACK_GCC}" +export YASHCHIKI_SPACK_GCC_VERSION="${YASHCHIKI_SPACK_GCC_VERSION}" +export YASHCHIKI_JOBS="${YASHCHIKI_JOBS}" +export YASHCHIKI_SPACK_CONFIG="/tmp/spack_config" +export YASHCHIKI_CACHES_ROOT="${YASHCHIKI_CACHES_ROOT}" +export YASHCHIKI_BUILD_CACHE_NAME="${YASHCHIKI_BUILD_CACHE_NAME}" +export YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME="${YASHCHIKI_BUILD_CACHE_ON_FAILURE_NAME:-}" +export YASHCHIKI_SPACK_VERBOSE="${YASHCHIKI_SPACK_VERBOSE}" +export YASHCHIKI_DEBUG=${YASHCHIKI_DEBUG} +export CONTAINER_STYLE="${CONTAINER_STYLE}" +"${SPACK_INSTALL_SCRIPTS}/complete_spack_install_routine_called_in_post.sh" +EOF + +PROOT_NO_SECCOMP=1 proot -w / -S ${TARGET_FOLDER} \ + --bind=${YASHCHIKI_CACHES_ROOT}/download_cache:/opt/spack/var/spack/cache \ + --bind=${YASHCHIKI_CACHES_ROOT}/spack_ccache:/opt/ccache \ + --bind=${YASHCHIKI_CACHES_ROOT}/build_caches:/opt/build_cache \ + --bind=${YASHCHIKI_CACHES_ROOT}/preserved_packages:/opt/preserved_packages \ + --bind=${JOB_TMP_SPACK}:/tmp/spack \ + --bind=${YASHCHIKI_SPACK_CONFIG}:/tmp/spack_config \ + /bin/dash /build.sh + +#apptainer -d build --fakeroot \ +# --bind ${YASHCHIKI_CACHES_ROOT}/download_cache:/opt/spack/var/spack/cache \ +# --bind ${YASHCHIKI_CACHES_ROOT}/spack_ccache:/opt/ccache \ +# --bind ${YASHCHIKI_CACHES_ROOT}/build_caches:/opt/build_cache \ +# --bind ${YASHCHIKI_CACHES_ROOT}/preserved_packages:/opt/preserved_packages \ +# --bind ${JOB_TMP_SPACK}:/tmp/spack \ +# --bind ${YASHCHIKI_SPACK_CONFIG}:/tmp/spack_config \ +# --sandbox "${TARGET_FOLDER}" "${YASHCHIKI_RECIPE_PATH}" | tee out_singularity_build_recipe.txt diff --git a/lib/yashchiki/update_build_cache.sh b/lib/yashchiki/update_build_cache.sh index 76d3bbc5..a0345e4b 100755 --- a/lib/yashchiki/update_build_cache.sh +++ b/lib/yashchiki/update_build_cache.sh @@ -3,6 +3,10 @@ set -euo pipefail shopt -s inherit_errexit 2>/dev/null || true +# for env vars +SOURCE_DIR="$(dirname "$(readlink -m "${BASH_SOURCE[0]}")")" +source "${SOURCE_DIR}/commons.sh" + usage() { echo "Usage: ${0} -c <container>" 1>&2; exit 1; } while getopts ":c:" opts; do @@ -29,10 +33,16 @@ source "${SOURCE_DIR}/commons.sh" # update script inside the container set +e # Arguments needed once we switch to singularity3: --writable-tmpfs -apptainer exec\ - -B "${BUILD_CACHE_OUTSIDE}:${BUILD_CACHE_INSIDE}:rw"\ - "${IMAGE_NAME}" \ - /opt/spack_install_scripts/update_build_cache_in_container.sh -j ${YASHCHIKI_JOBS} -q || exit 0 +#apptainer exec\ +# -B "${BUILD_CACHE_OUTSIDE}:${BUILD_CACHE_INSIDE}:rw"\ +# "${IMAGE_NAME}" \ +# /opt/spack_install_scripts/update_build_cache_in_container.sh -j ${YASHCHIKI_JOBS} -q || exit 0 + +TARGET_FOLDER="${YASHCHIKI_SANDBOXES}/${CONTAINER_STYLE}" + +proot -w / -S ${TARGET_FOLDER} \ + --bind="${BUILD_CACHE_OUTSIDE}:${BUILD_CACHE_INSIDE}" \ + /opt/spack_install_scripts/update_build_cache_in_container.sh -q || exit 0 if [ -n "${CACHE_BUILD_TYPE:-}" ]; then if [ ${CACHE_SOURCE_TYPE} != "oci" ]; then -- GitLab