From 72f7e9e3002db2540d605af3249ae87316711fd5 Mon Sep 17 00:00:00 2001 From: Jakob Naucke Date: Tue, 15 Feb 2022 19:12:41 +0100 Subject: [PATCH] osbuilder: Multistrap Ubuntu Use `multistrap` for building Ubuntu rootfs. Adds support for building for foreign architectures using the `ARCH` environment variable. In the process, the Ubuntu rootfs workflow is vastly simplified. Signed-off-by: Jakob Naucke --- tools/osbuilder/rootfs-builder/rootfs.sh | 18 ++-- .../rootfs-builder/ubuntu/Dockerfile.in | 42 +++------ .../osbuilder/rootfs-builder/ubuntu/config.sh | 48 +++++----- .../rootfs-builder/ubuntu/rootfs_lib.sh | 93 +++++-------------- tools/osbuilder/scripts/lib.sh | 5 +- 5 files changed, 71 insertions(+), 135 deletions(-) diff --git a/tools/osbuilder/rootfs-builder/rootfs.sh b/tools/osbuilder/rootfs-builder/rootfs.sh index 6bc0f8b7d..9bd485fe4 100755 --- a/tools/osbuilder/rootfs-builder/rootfs.sh +++ b/tools/osbuilder/rootfs-builder/rootfs.sh @@ -39,7 +39,11 @@ handle_error() { trap 'handle_error $LINENO' ERR # Default architecture -ARCH=$(uname -m) +export ARCH=${ARCH:-$(uname -m)} +if [ "$ARCH" == "ppc64le" ] || [ "$ARCH" == "s390x" ]; then + LIBC=gnu + echo "WARNING: Forcing LIBC=gnu because $ARCH has no musl Rust target" +fi # distro-specific config file typeset -r CONFIG_SH="config.sh" @@ -103,6 +107,11 @@ AGENT_SOURCE_BIN Path to the directory of agent binary. AGENT_VERSION Version of the agent to include in the rootfs. Default value: ${AGENT_VERSION:-} +ARCH Target architecture (according to \`uname -m\`). + Foreign bootstraps are currently only supported for Ubuntu + and glibc agents. + Default value: $(uname -m) + DISTRO_REPO Use host repositories to install guest packages. Default value: @@ -408,6 +417,7 @@ build_rootfs_distro() --env ROOTFS_DIR="/rootfs" \ --env AGENT_BIN="${AGENT_BIN}" \ --env AGENT_INIT="${AGENT_INIT}" \ + --env ARCH="${ARCH}" \ --env CI="${CI}" \ --env KERNEL_MODULES_DIR="${KERNEL_MODULES_DIR}" \ --env LIBC="${LIBC}" \ @@ -538,10 +548,6 @@ EOT AGENT_DEST="${AGENT_DIR}/${AGENT_BIN}" if [ -z "${AGENT_SOURCE_BIN}" ] ; then - if [ "$ARCH" == "ppc64le" ] || [ "$ARCH" == "s390x" ]; then - LIBC=gnu - echo "WARNING: Forcing LIBC=gnu because $ARCH has no musl Rust target" - fi test -r "${HOME}/.cargo/env" && source "${HOME}/.cargo/env" # rust agent needs ${arch}-unknown-linux-${LIBC} if ! (rustup show | grep -v linux-${LIBC} > /dev/null); then @@ -559,7 +565,7 @@ EOT info "Set up libseccomp" libseccomp_install_dir=$(mktemp -d -t libseccomp.XXXXXXXXXX) gperf_install_dir=$(mktemp -d -t gperf.XXXXXXXXXX) - bash ${script_dir}/../../../ci/install_libseccomp.sh "${libseccomp_install_dir}" "${gperf_install_dir}" + ${script_dir}/../../../ci/install_libseccomp.sh "${libseccomp_install_dir}" "${gperf_install_dir}" echo "Set environment variables for the libseccomp crate to link the libseccomp library statically" export LIBSECCOMP_LINK_TYPE=static export LIBSECCOMP_LIB_PATH="${libseccomp_install_dir}/lib" diff --git a/tools/osbuilder/rootfs-builder/ubuntu/Dockerfile.in b/tools/osbuilder/rootfs-builder/ubuntu/Dockerfile.in index edc921641..de3c31ed9 100644 --- a/tools/osbuilder/rootfs-builder/ubuntu/Dockerfile.in +++ b/tools/osbuilder/rootfs-builder/ubuntu/Dockerfile.in @@ -1,45 +1,29 @@ -# -# Copyright (c) 2018 Yash Jain +# Copyright (c) 2018 Yash Jain, 2022 IBM Corp. # # SPDX-License-Identifier: Apache-2.0 ARG IMAGE_REGISTRY=docker.io -#ubuntu: docker image to be used to create a rootfs -#@OS_VERSION@: Docker image version to build this dockerfile FROM ${IMAGE_REGISTRY}/ubuntu:@OS_VERSION@ +@SET_PROXY@ -# This dockerfile needs to provide all the componets need to build a rootfs -# Install any package need to create a rootfs (package manager, extra tools) - -# RUN commands -RUN apt-get update && apt-get --no-install-recommends install -y \ - apt-utils \ - autoconf \ - automake \ - binutils \ - build-essential \ +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive \ + apt-get --no-install-recommends -y install \ ca-certificates \ - chrony \ - coreutils \ curl \ - debianutils \ - debootstrap \ g++ \ - gcc \ + $(gcc_arch="@ARCH@" && [ "$(uname -m)" != "$gcc_arch" ] && ( \ + libc_arch="$gcc_arch" && \ + [ "$gcc_arch" = aarch64 ] && libc_arch=arm64; \ + [ "$gcc_arch" = ppc64le ] && gcc_arch=powerpc64le && libc_arch=ppc64el; \ + [ "$gcc_arch" = x86_64 ] && gcc_arch=x86-64 && libc_arch=amd64; \ + echo "gcc-$gcc_arch-linux-gnu libc6-dev-$libc_arch-cross")) \ git \ - libc6-dev \ - libstdc++-8-dev \ - m4 \ make \ + multistrap \ musl-tools \ - protobuf-compiler \ - sed \ - systemd \ - tar \ - vim \ - wget + protobuf-compiler # aarch64 requires this name -- link for all RUN ln -s /usr/bin/musl-gcc "/usr/bin/$(uname -m)-linux-musl-gcc" -# This will install the proper packages to build Kata components @INSTALL_RUST@ diff --git a/tools/osbuilder/rootfs-builder/ubuntu/config.sh b/tools/osbuilder/rootfs-builder/ubuntu/config.sh index 14ae93ece..8afc34804 100644 --- a/tools/osbuilder/rootfs-builder/ubuntu/config.sh +++ b/tools/osbuilder/rootfs-builder/ubuntu/config.sh @@ -1,34 +1,28 @@ -# This is a configuration file add extra variables to -# -# Copyright (c) 2018 Yash Jain +# Copyright (c) 2018 Yash Jain, 2022 IBM Corp. # # SPDX-License-Identifier: Apache-2.0 -# be used by build_rootfs() from rootfs_lib.sh the variables will be -# loaded just before call the function. For more information see the -# rootfs-builder/README.md file. -OS_VERSION=${OS_VERSION:-20.04} +OS_NAME=ubuntu # This should be Ubuntu's code name, e.g. "focal" (Focal Fossa) for 20.04 -OS_NAME=${OS_NAME:-"focal"} +OS_VERSION=${OS_VERSION:-focal} +PACKAGES=chrony +[ "$AGENT_INIT" = no ] && PACKAGES+=" init" +[ "$SECCOMP" = yes ] && PACKAGES+=" libseccomp2" +REPO_URL=http://ports.ubuntu.com -# packages to be installed by default -PACKAGES="systemd coreutils init kmod" -EXTRA_PKGS+=" chrony" - -DEBOOTSTRAP=${PACKAGE_MANAGER:-"debootstrap"} - -case $(uname -m) in - x86_64) ARCHITECTURE="amd64";; - ppc64le) ARCHITECTURE="ppc64el";; - aarch64) ARCHITECTURE="arm64";; - s390x) ARCHITECTURE="s390x";; - (*) die "$(uname -m) not supported " +case "$ARCH" in + aarch64) DEB_ARCH=arm64;; + ppc64le) DEB_ARCH=ppc64el;; + s390x) DEB_ARCH="$ARCH";; + x86_64) DEB_ARCH=amd64; REPO_URL=http://archive.ubuntu.com/ubuntu;; + *) die "$ARCH not supported" esac -# Init process must be one of {systemd,kata-agent} -INIT_PROCESS=systemd -# List of zero or more architectures to exclude from build, -# as reported by `uname -m` -ARCH_EXCLUDE_LIST=() - -[ "$SECCOMP" = "yes" ] && PACKAGES+=" libseccomp2" || true +if [ "$(uname -m)" != "$ARCH" ]; then + case "$ARCH" in + ppc64le) cc_arch=powerpc64le;; + x86_64) cc_arch=x86-64;; + *) cc_arch="$ARCH" + esac + export CC="$cc_arch-linux-gnu-gcc" +fi diff --git a/tools/osbuilder/rootfs-builder/ubuntu/rootfs_lib.sh b/tools/osbuilder/rootfs-builder/ubuntu/rootfs_lib.sh index e94df355d..4261c7ff0 100644 --- a/tools/osbuilder/rootfs-builder/ubuntu/rootfs_lib.sh +++ b/tools/osbuilder/rootfs-builder/ubuntu/rootfs_lib.sh @@ -1,78 +1,29 @@ -# - Arguments -# -# Copyright (c) 2018 Yash Jain +# Copyright (c) 2018 Yash Jain, 2022 IBM Corp. # # SPDX-License-Identifier: Apache-2.0 -# -# -# rootfs_dir=$1 -# -# - Optional environment variables -# -# EXTRA_PKGS: Variable to add extra PKGS provided by the user -# -# BIN_AGENT: Name of the Kata-Agent binary -# -# REPO_URL: URL to distribution repository ( should be configured in -# config.sh file) -# -# Any other configuration variable for a specific distro must be added -# and documented on its own config.sh -# -# - Expected result -# -# rootfs_dir populated with rootfs pkgs -# It must provide a binary in /sbin/init -# + build_rootfs() { - # Mandatory - local ROOTFS_DIR=$1 + local rootfs_dir=$1 + local multistrap_conf=multistrap.conf - # Name of the Kata-Agent binary - local BIN_AGENT=${BIN_AGENT} + # For simplicity's sake, use multistrap for foreign and native bootstraps. + cat > "$multistrap_conf" << EOF +[General] +cleanup=true +aptsources=Ubuntu +bootstrap=Ubuntu - # In case of support EXTRA packages, use it to allow - # users to add more packages to the base rootfs - local EXTRA_PKGS=${EXTRA_PKGS:-} +[Ubuntu] +source=$REPO_URL +keyring=ubuntu-keyring +suite=focal +packages=$PACKAGES $EXTRA_PKGS +EOF + multistrap -a "$DEB_ARCH" -d "$rootfs_dir" -f "$multistrap_conf" + rm -rf "$rootfs_dir/var/run" + ln -s /run "$rootfs_dir/var/run" + cp --remove-destination /etc/resolv.conf "$rootfs_dir/etc" - # In case rootfs is created using repositories allow user to modify - # the default URL - local REPO_URL=${REPO_URL:-YOUR_REPO} - - # PATH where files this script is placed - # Use it to refer to files in the same directory - # Example: ${CONFIG_DIR}/foo - local CONFIG_DIR=${CONFIG_DIR} - - - # Populate ROOTFS_DIR - # Must provide /sbin/init and /bin/${BIN_AGENT} - DEBOOTSTRAP="debootstrap" - check_root - mkdir -p "${ROOTFS_DIR}" - if [ -n "${PKG_MANAGER}" ]; then - info "debootstrap path provided by user: ${PKG_MANAGER}" - elif check_program $DEBOOTSTRAP ; then - PKG_MANAGER=$DEBOOTSTRAP - else - die "$DEBOOTSTRAP is not installed" - fi - # trim whitespace - PACKAGES=$(echo $PACKAGES |xargs ) - # add comma as debootstrap needs , separated package names. - # Don't change $PACKAGES in config.sh to include ',' - # This is done to maintain consistency - PACKAGES=$(echo $PACKAGES | sed -e 's/ /,/g' ) - - ${PKG_MANAGER} --variant=minbase \ - --arch=${ARCHITECTURE}\ - --include="$PACKAGES" \ - ${OS_NAME} \ - ${ROOTFS_DIR} - - [ -n "${EXTRA_PKGS}" ] && chroot $ROOTFS_DIR apt-get install -y ${EXTRA_PKGS} - - # Reduce image size and memory footprint - # removing not needed files and directories. - chroot $ROOTFS_DIR rm -rf /usr/share/{bash-completion,bug,doc,info,lintian,locale,man,menu,misc,pixmaps,terminfo,zoneinfo,zsh} + # Reduce image size and memory footprint by removing unnecessary files and directories. + rm -rf $rootfs_dir/usr/share/{bash-completion,bug,doc,info,lintian,locale,man,menu,misc,pixmaps,terminfo,zsh} } diff --git a/tools/osbuilder/scripts/lib.sh b/tools/osbuilder/scripts/lib.sh index 9db989900..5a6a1be1e 100644 --- a/tools/osbuilder/scripts/lib.sh +++ b/tools/osbuilder/scripts/lib.sh @@ -203,8 +203,8 @@ generate_dockerfile() dir="$1" [ -d "${dir}" ] || die "${dir}: not a directory" - local rustarch=$(uname -m) - [ "$rustarch" = ppc64le ] && rustarch=powerpc64le + local rustarch="$ARCH" + [ "$ARCH" = ppc64le ] && rustarch=powerpc64le [ -n "${http_proxy:-}" ] && readonly set_proxy="RUN sed -i '$ a proxy="${http_proxy:-}"' /etc/dnf/dnf.conf /etc/yum.conf; true" @@ -220,6 +220,7 @@ RUN . /root/.cargo/env; cargo install cargo-when sed \ -e "s#@OS_VERSION@#${OS_VERSION:-}#g" \ + -e "s#@ARCH@#$ARCH#g" \ -e "s#@INSTALL_RUST@#${install_rust//$'\n'/\\n}#g" \ -e "s#@SET_PROXY@#${set_proxy:-}#g" \ Dockerfile.in > Dockerfile