diff options
-rw-r--r-- | .SRCINFO | 25 | ||||
-rw-r--r-- | PKGBUILD | 73 | ||||
-rwxr-xr-x | image_builder.sh | 521 | ||||
-rw-r--r-- | install_kata-agent.tpl | 5 | ||||
-rw-r--r-- | install_sd-kata-agent.tpl | 7 | ||||
-rw-r--r-- | kata-agent.service.in | 24 | ||||
-rw-r--r-- | kata-containers.target | 16 | ||||
-rw-r--r-- | kata-runtime.install | 44 | ||||
-rw-r--r-- | mkinitcpio-agent.conf | 6 |
9 files changed, 641 insertions, 80 deletions
@@ -1,40 +1,47 @@ pkgbase = kata-containers-guest pkgdesc = Lightweight virtual machines for containers (guest components) pkgver = 1.11.4 - pkgrel = 3 + pkgrel = 4 url = https://katacontainers.io/ arch = x86_64 license = Apache makedepends = go<2:1.15 makedepends = yq2-bin makedepends = mkinitcpio + makedepends = pacman makedepends = udisks2 - noextract = archlinux-bootstrap-2020.11.01-x86_64.tar.gz source = agent-1.11.4.tar.gz::https://github.com/kata-containers/agent/archive/1.11.4.tar.gz source = osbuilder-1.11.4.tar.gz::https://github.com/kata-containers/osbuilder/archive/1.11.4.tar.gz source = packaging-1.11.4.tar.gz::https://github.com/kata-containers/packaging/archive/1.11.4.tar.gz source = https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.32.tar.xz source = https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.32.tar.sign - source = http://mirrors.evowise.com/archlinux/iso/2020.11.01/archlinux-bootstrap-2020.11.01-x86_64.tar.gz - source = http://mirrors.evowise.com/archlinux/iso/2020.11.01/archlinux-bootstrap-2020.11.01-x86_64.tar.gz.sig + source = mkinitcpio-agent.conf + source = install_kata-agent.tpl + source = image_builder.sh + source = install_sd-kata-agent.tpl validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E - validpgpkeys = 4AA4767BBC9C4B1D18AE28B77F2D434B9741E8AC sha512sums = e0af374e279899a010ab66ed4fd4caff33c91d2cc19711f5e51302041cd49e69a71909d71092042bf0c4070acbbc5421f5c6cca49c55a4c332c060e745cf5a0c sha512sums = b8f8998229e2f12491cf6f9262cf8889353e83c58e93010ca3f328f77b61f89fb33d9209b21a1babae406f60b915011edb0832b803dd31b32115dfffa1b2edb1 sha512sums = 867f8fbf9c589535a10696a14c26aa6b9b3c6344690105489d55ed1287bdbd56909eb8052a22b4be98e8eb697fc57021212780ff41e478438c71a5c20d7446ad sha512sums = 197f292fa541031071b8ed64880a3d4251fa65059747cbdf3900b8f934d17f681b506ca5f70132899bdef343d2d249a7902215d2ea04af5410599f1e50d6cbac sha512sums = SKIP - sha512sums = 91a3f0a1cbc7addb1941bc583b364b411e28223580980063ddc950cf4a0d247b0c40dbac6462f39d4d2f20102a8ff643b02179fa7dba685ae588962ea778c5d3 - sha512sums = SKIP + sha512sums = 182a249aecbab33b8704e9567e96d33b535ee59e6d2f52f0c30fbc3d12813f60192886539cc745933caaf59268925d78db9e0b6b427321e2bac932ebde77d62e + sha512sums = 0250e52251986f36cfb9e378d848f755caaf5253daa8ff7d87172f2622754c1eb4180b338a497e3fbeb880e232eef19d5e512f5a8e610e7a6eb468f210849a08 + sha512sums = 6f476297d9001eef9a0665689f752cf5124907522cfc87240df16488379a5c7c9820a6e33a576dbf7f75c4fdfa7cab7a0e395b05c9339069dedbdaac42fb6c04 + sha512sums = 65d368df7fe4546d5c825e30c5c831cb4b4f759fb1352b7715d40b750968b3ba54139f64cd1133a3b599d179d88d8181bd61eb34b1f5868b5606e53de6552c41 b2sums = 94e996c463f0c5517bc6d97af2cb0f1dbadccd7e5f2ef5c45ea15d1deb5af65770371f25a0b9421ba70fa50a0b8c22c7d5a443173515ad4c5db30c1fa72cd395 b2sums = 6c30855fc7d5298dbe8c6b7e294edbf840e123083fecfa3d73d91e741dcca70af6ca0c10672eb6fa24dd886b3ebddccefcff943b4c816ce65c2f05588947660e b2sums = 6194835f2526a7b16e5b8ca97fb831fdfb78a951dec51c8640c8cff6efd5186ed051e717ff748af7913bdf339f5a69e1b5c9aff2d70c732a4876481ac6fb59ea b2sums = 0ac78d1eb97ce4689ccdab01fb1475d07f29a90251b44b05fcf030d2f9aa644ac9dbb1315c7fe1eb991ef1435b7f17669e2b4f66187e3404599a0f136d2b1a50 b2sums = SKIP - b2sums = ce8bfce07a121780e6a09f2b652b0be3fb3c728cd0cccedaad4add394784a6ded18c5163d2a999fc8043cdc9eb6fc347aa6a26a990b31f1f4a445f83460eccc3 - b2sums = SKIP + b2sums = 43c81141a65fd14b60ae72c5b98168bec531990903cc7c8b224b416c71d1d05c1cf3f73891954604e0b0c6f48c52a3a41a8e9e78874a79e72b14282373108e8b + b2sums = 9abf2208af353019ba177d8a48ba613401742cd21258a79c5d9cb8518a51f4f22a41dc386b71f2d6521d03f6ff65d8710dc59d1ca9c7c1dc5f94061c7374286c + b2sums = 1745aa5d5df0af2452381de163e3964511172e045c13736a062bb2c932e3306250d24992b2bdbc534ced188b35d3b1f4958a5680c99356afd3097d11c84aee31 + b2sums = c9d90683b134dcbf656adcb5bebad02a9a02ec68a1497bbab16cdec7d626ab020f56a40f00bfddf06000452e20d5a58d53ed59d0be49451daf9019fe1f203a58 pkgname = kata-agent pkgname = kata-linux-container +pkgname = kata-containers-image + @@ -5,11 +5,11 @@ pkgbase=kata-containers-guest pkgname=( kata-agent kata-linux-container - #kata-containers-image + kata-containers-image ) pkgver=1.11.4 _pkgver=${pkgver/\~/-} -pkgrel=3 +pkgrel=4 pkgdesc="Lightweight virtual machines for containers (guest components)" arch=('x86_64') url="https://katacontainers.io/" @@ -18,12 +18,11 @@ makedepends=( 'go<2:1.15' # thanks Intel, love you big time: https://github.com/kata-containers/runtime/issues/2982 'yq2-bin' # quietly pulled by Kata's codebase to read versions.yaml from repo 'mkinitcpio' # initrd build - 'udisks2' # rootless image build + 'pacman' 'udisks2' # rootless image build ) _gh_org="github.com/kata-containers" _kata_kernel_ver="${KATA_KERNEL_VER:-5.4.32}" -_arch_bootstrap_ver="${ARCH_BOOTSTRAP_VER:-2020.11.01}" source=( "agent-${_pkgver}.tar.gz::https://${_gh_org}/agent/archive/${_pkgver}.tar.gz" @@ -33,8 +32,13 @@ source=( "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${_kata_kernel_ver}.tar.xz" "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${_kata_kernel_ver}.tar.sign" - "http://mirrors.evowise.com/archlinux/iso/${_arch_bootstrap_ver}/archlinux-bootstrap-${_arch_bootstrap_ver}-x86_64.tar.gz" - "http://mirrors.evowise.com/archlinux/iso/${_arch_bootstrap_ver}/archlinux-bootstrap-${_arch_bootstrap_ver}-x86_64.tar.gz.sig" + # mknitcpio-busybox + "mkinitcpio-agent.conf" + "install_kata-agent.tpl" + "image_builder.sh" # image build + + # mknitpcio-systemd + "install_sd-kata-agent.tpl" ) sha512sums=( "e0af374e279899a010ab66ed4fd4caff33c91d2cc19711f5e51302041cd49e69a71909d71092042bf0c4070acbbc5421f5c6cca49c55a4c332c060e745cf5a0c" @@ -44,8 +48,11 @@ sha512sums=( "${KATA_KERNEL_SUM_SHA512:-197f292fa541031071b8ed64880a3d4251fa65059747cbdf3900b8f934d17f681b506ca5f70132899bdef343d2d249a7902215d2ea04af5410599f1e50d6cbac}" "SKIP" - "${ARCH_BOOTSTRAP_SUM_SHA512:-91a3f0a1cbc7addb1941bc583b364b411e28223580980063ddc950cf4a0d247b0c40dbac6462f39d4d2f20102a8ff643b02179fa7dba685ae588962ea778c5d3}" - "SKIP" + "182a249aecbab33b8704e9567e96d33b535ee59e6d2f52f0c30fbc3d12813f60192886539cc745933caaf59268925d78db9e0b6b427321e2bac932ebde77d62e" + "0250e52251986f36cfb9e378d848f755caaf5253daa8ff7d87172f2622754c1eb4180b338a497e3fbeb880e232eef19d5e512f5a8e610e7a6eb468f210849a08" + "6f476297d9001eef9a0665689f752cf5124907522cfc87240df16488379a5c7c9820a6e33a576dbf7f75c4fdfa7cab7a0e395b05c9339069dedbdaac42fb6c04" + + "65d368df7fe4546d5c825e30c5c831cb4b4f759fb1352b7715d40b750968b3ba54139f64cd1133a3b599d179d88d8181bd61eb34b1f5868b5606e53de6552c41" ) b2sums=( "94e996c463f0c5517bc6d97af2cb0f1dbadccd7e5f2ef5c45ea15d1deb5af65770371f25a0b9421ba70fa50a0b8c22c7d5a443173515ad4c5db30c1fa72cd395" @@ -55,13 +62,14 @@ b2sums=( "${KATA_KERNEL_SUM_B2:-0ac78d1eb97ce4689ccdab01fb1475d07f29a90251b44b05fcf030d2f9aa644ac9dbb1315c7fe1eb991ef1435b7f17669e2b4f66187e3404599a0f136d2b1a50}" "SKIP" - "${ARCH_BOOTSTRAP_SUM_B2:-ce8bfce07a121780e6a09f2b652b0be3fb3c728cd0cccedaad4add394784a6ded18c5163d2a999fc8043cdc9eb6fc347aa6a26a990b31f1f4a445f83460eccc3}" - "SKIP" + "43c81141a65fd14b60ae72c5b98168bec531990903cc7c8b224b416c71d1d05c1cf3f73891954604e0b0c6f48c52a3a41a8e9e78874a79e72b14282373108e8b" + "9abf2208af353019ba177d8a48ba613401742cd21258a79c5d9cb8518a51f4f22a41dc386b71f2d6521d03f6ff65d8710dc59d1ca9c7c1dc5f94061c7374286c" + "1745aa5d5df0af2452381de163e3964511172e045c13736a062bb2c932e3306250d24992b2bdbc534ced188b35d3b1f4958a5680c99356afd3097d11c84aee31" + + "c9d90683b134dcbf656adcb5bebad02a9a02ec68a1497bbab16cdec7d626ab020f56a40f00bfddf06000452e20d5a58d53ed59d0be49451daf9019fe1f203a58" ) -noextract=("archlinux-bootstrap-${_arch_bootstrap_ver}-x86_64.tar.gz") validpgpkeys=( 647F28654894E3BD457199BE38DBBDC86092693E # kernel - 4AA4767BBC9C4B1D18AE28B77F2D434B9741E8AC # arch ) case "${CARCH}" in @@ -99,33 +107,44 @@ prepare(){ install -dm0755 "${srcdir}/src/${_gh_org}" mv "${srcdir}/agent-${_pkgver}" "${srcdir}/src/${_gh_org}/agent" + + # agent-based initrd + BINSRC="${srcdir}/src/${_gh_org}/agent/kata-agent" envsubst <"${srcdir}/install_kata-agent.tpl" >"${srcdir}/install_kata-agent" + install -Dm0644 "${srcdir}/install_kata-agent" "${srcdir}/initcpio-agent/install/kata-agent" + + # systemd-based initrd + SRCDIR="${srcdir}/src/${_gh_org}/agent" envsubst <"${srcdir}/install_sd-kata-agent.tpl" >"${srcdir}/install_sd-kata-agent" + install -Dm0644 "${srcdir}/install_sd-kata-agent" "${srcdir}/initcpio-systemd/install/sd-kata-agent" + + install -m0755 "${srcdir}/image_builder.sh" "${srcdir}/osbuilder-${_pkgver}/image-builder/image_builder.sh" } _kata_image_build(){ - # rootfs and initrd build (it's horrid, but somewhat works) - local -r _ROOTFS_DIR="${srcdir}/osbuilder-${_pkgver}/rootfs-builder/rootfs" - - # build rootfs - install -D -m 0644 "${srcdir}/rootfs-builder-config.sh" "${srcdir}/osbuilder-${_pkgver}/rootfs-builder/archlinux/config.sh" - install -D -m 0644 "${srcdir}/rootfs-builder-lib.sh" "${srcdir}/osbuilder-${_pkgver}/rootfs-builder/archlinux/rootfs_lib.sh" + install -dm0755 "${srcdir}/pkgcache" "${srcdir}/alpmdb" "${srcdir}/rootfs" + fakeroot -- pacman -r "${srcdir}/rootfs" -b "${srcdir}/alpmdb" --cachedir "${srcdir}/pkgcache" --noconfirm -Sy systemd chrony iptables kmod libseccomp + pushd "${srcdir}/rootfs/sbin" + ln -sf ../lib/systemd/systemd init + popd - cd "${srcdir}/osbuilder-${_pkgver}/rootfs-builder" - GOPATH="${srcdir}" AGENT_SOURCE_BIN="${srcdir}/src/${_gh_org}/agent/kata-agent" ROOTFS_DIR="${_ROOTFS_DIR}" ./rootfs.sh archlinux + install -Dm0755 "${srcdir}/src/${_gh_org}/agent/kata-agent" "${srcdir}/rootfs/usr/bin/kata-agent" + install -Dm0644 "${srcdir}/src/${_gh_org}/agent/kata-containers.target" "${srcdir}/rootfs/usr/lib/systemd/system/kata-containers.target" + sed -e 's#@bindir@#/usr/bin#' -e 's#@kata-agent@#kata-agent#' "${srcdir}/src/${_gh_org}/agent/kata-agent.service.in" >"${srcdir}/rootfs/usr/lib/systemd/system/kata-agent.service" - # rootfs image (need to bypass root requirement somehow) + # rootfs image (builds filesystem with uid:gid of building system user! beware!) cd "${srcdir}/osbuilder-${_pkgver}/image-builder" - ./image_builder.sh "${_ROOTFS_DIR}" + ./image_builder.sh -f ext4 "${srcdir}/rootfs" } build(){ cd "${srcdir}/src/${_gh_org}/agent" GOPATH="${srcdir}" LDFLAGS="" make - # kernel build cd "${srcdir}/linux-${_kata_kernel_ver}" make -s ARCH="${_KARCH}" - #_kata_image_build + mkinitcpio -c "${srcdir}/mkinitcpio-agent.conf" -g "${srcdir}/initrd-arch-agent.img" -D "${srcdir}/initcpio-agent" + #mkinitcpio -c "${srcdir}/mkinitcpio-systemd.conf" -g "${srcdir}/initrd-arch-systemd.img" -D "${srcdir}/initcpio-systemd" + _kata_image_build } package_kata-agent(){ @@ -135,10 +154,10 @@ package_kata-agent(){ package_kata-containers-image(){ local -r _img_filename="kata-containers-${_pkgver%%~*}-arch-systemd-image.img" _initrd_filename="kata-containers-${_pkgver%%~*}-arch-agent-initrd.img" - #install -D -m 0644 "${srcdir}/osbuilder-${_pkgver}/image-builder/kata-containers.img" "${pkgdir}/usr/share/kata-containers/${_img_filename}" - install -D -m 0644 "${srcdir}/osbuilder-${_pkgver}/initrd-builder/kata-containers-initrd.img" "${pkgdir}/usr/share/kata-containers/${_initrd_filename}" + install -Dm 0644 "${srcdir}/osbuilder-${_pkgver}/image-builder/kata-containers.img" "${pkgdir}/usr/share/kata-containers/${_img_filename}" + install -Dm 0644 "${srcdir}/initrd-arch-agent.img" "${pkgdir}/usr/share/kata-containers/${_initrd_filename}" pushd "${pkgdir}/usr/share/kata-containers" - #ln -sf "${_img_filename}" "kata-containers-arch.img" + ln -sf "${_img_filename}" "kata-containers-arch.img" ln -sf "${_initrd_filename}" "kata-containers-arch-initrd.img" popd } diff --git a/image_builder.sh b/image_builder.sh new file mode 100755 index 000000000000..51d5dc420b8d --- /dev/null +++ b/image_builder.sh @@ -0,0 +1,521 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2017-2019 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +[ -n "${DEBUG}" ] && set -x + +DOCKER_RUNTIME=${DOCKER_RUNTIME:-runc} + +readonly script_name="${0##*/}" +readonly script_dir=$(dirname "$(readlink -f "$0")") +readonly lib_file="${script_dir}/../scripts/lib.sh" + +readonly ext4_format="ext4" +readonly xfs_format="xfs" + +# ext4: percentage of the filesystem which may only be allocated by privileged processes. +readonly reserved_blocks_percentage=3 + +# Where the rootfs starts in MB +readonly rootfs_start=1 + +# Where the rootfs ends in MB +readonly rootfs_end=-1 + +# DAX header size +# * NVDIMM driver reads the device namespace information from nvdimm namespace (4K offset). +# The MBR #1 + DAX metadata are saved in the first 2MB of the image. +readonly dax_header_sz=2 + +# DAX aligment +# * DAX huge pages [2]: 2MB alignment +# [2] - https://nvdimm.wiki.kernel.org/2mib_fs_dax +readonly dax_alignment=2 + +# The list of systemd units and files that are not needed in Kata Containers +readonly -a systemd_units=( + "systemd-coredump@" + "systemd-journald" + "systemd-journald-dev-log" + "systemd-journal-flush" + "systemd-random-seed" + "systemd-timesyncd" + "systemd-tmpfiles-setup" + "systemd-udevd" + "systemd-udevd-control" + "systemd-udevd-kernel" + "systemd-udev-trigger" + "systemd-update-utmp" +) + +readonly -a systemd_files=( + "systemd-bless-boot-generator" + "systemd-fstab-generator" + "systemd-getty-generator" + "systemd-gpt-auto-generator" + "systemd-tmpfiles-cleanup.timer" +) + +# Set a default value +AGENT_INIT=${AGENT_INIT:-no} + +# Align image to (size in MB) according to different architecture. +case "$(uname -m)" in + aarch64) readonly mem_boundary_mb=16 ;; + *) readonly mem_boundary_mb=128 ;; +esac + +# shellcheck source=../scripts/lib.sh +source "${lib_file}" + +usage() { + cat <<EOT +Usage: ${script_name} [options] <rootfs-dir> + This script will create a Kata Containers image file of + an adequate size based on the <rootfs-dir> directory. + +Options: + -h Show this help + -o path to generate image file ENV: IMAGE + -r Free space of the root partition in MB ENV: ROOT_FREE_SPACE + +Extra environment variables: + AGENT_BIN: Use it to change the expected agent binary name + AGENT_INIT: Use kata agent as init process + NSDAX_BIN: Use to specify path to pre-compiled 'nsdax' tool. + FS_TYPE: Filesystem type to use. Only xfs and ext4 are supported. + USE_DOCKER: If set will build image in a Docker Container (requries docker) + DEFAULT: not set + USE_PODMAN: If set and USE_DOCKER not set, will build image in a Podman Container (requries podman) + DEFAULT: not set + + +Following diagram shows how the resulting image will look like + + .-----------.----------.---------------.-----------. + | 0 - 512 B | 4 - 8 Kb | 2M - 2M+512B | 3M | + |-----------+----------+---------------+-----------+ + | MBR #1 | DAX | MBR #2 | Rootfs | + '-----------'----------'---------------'-----------+ + | | ^ | ^ + | '-data-' '--------' + | | + '--------rootfs-partition---------' + + +MBR: Master boot record. +DAX: Metadata required by the NVDIMM driver to enable DAX in the guest [1][2] (struct nd_pfn_sb). +Rootfs: partition that contains the root filesystem (/usr, /bin, ect). + +Kernels and hypervisors that support DAX/NVDIMM read the MBR #2, otherwise MBR #1 is read. + +[1] - https://github.com/kata-containers/osbuilder/blob/master/image-builder/nsdax.gpl.c +[2] - https://github.com/torvalds/linux/blob/master/drivers/nvdimm/pfn.h + +EOT +} + + +# build the image using container engine +build_with_container() { + local rootfs="$1" + local image="$2" + local fs_type="$3" + local block_size="$4" + local root_free_space="$5" + local agent_bin="$6" + local agent_init="$7" + local container_engine="$8" + local nsdax_bin="$9" + local container_image_name="image-builder-osbuilder" + local shared_files="" + + image_dir=$(readlink -f "$(dirname "${image}")") + image_name=$(basename "${image}") + + "${container_engine}" build \ + --build-arg http_proxy="${http_proxy}" \ + --build-arg https_proxy="${https_proxy}" \ + -t "${container_image_name}" "${script_dir}" + + readonly mke2fs_conf="/etc/mke2fs.conf" + if [ -f "${mke2fs_conf}" ]; then + shared_files+="-v ${mke2fs_conf}:${mke2fs_conf}:ro " + fi + + #Make sure we use a compatible runtime to build rootfs + # In case Clear Containers Runtime is installed we dont want to hit issue: + #https://github.com/clearcontainers/runtime/issues/828 + "${container_engine}" run \ + --rm \ + --runtime "${DOCKER_RUNTIME}" \ + --privileged \ + --env AGENT_BIN="${agent_bin}" \ + --env AGENT_INIT="${agent_init}" \ + --env FS_TYPE="${fs_type}" \ + --env BLOCK_SIZE="${block_size}" \ + --env ROOT_FREE_SPACE="${root_free_space}" \ + --env NSDAX_BIN="${nsdax_bin}" \ + --env DEBUG="${DEBUG}" \ + -v /dev:/dev \ + -v "${script_dir}":"/osbuilder" \ + -v "${script_dir}/../scripts":"/scripts" \ + -v "${rootfs}":"/rootfs" \ + -v "${image_dir}":"/image" \ + ${shared_files} \ + ${container_image_name} \ + bash "/osbuilder/${script_name}" -o "/image/${image_name}" /rootfs +} + +check_rootfs() { + local rootfs="${1}" + + [ -d "${rootfs}" ] || die "${rootfs} is not a directory" + + # The kata rootfs image expect init and kata-agent to be installed + init_path="/sbin/init" + init="${rootfs}${init_path}" + if [ ! -x "${init}" ] && [ ! -L "${init}" ]; then + error "${init_path} is not installed in ${rootfs}" + return 1 + fi + OK "init is installed" + + + candidate_systemd_paths="/usr/lib/systemd/systemd /lib/systemd/systemd" + + # check agent or systemd + case "${AGENT_INIT}" in + "no") + for systemd_path in $candidate_systemd_paths; do + systemd="${rootfs}${systemd_path}" + if [ -x "${systemd}" ] || [ -L "${systemd}" ]; then + found="yes" + break + fi + done + if [ ! $found ]; then + error "None of ${candidate_systemd_paths} is installed in ${rootfs}" + return 1 + fi + OK "init is systemd" + ;; + + "yes") + agent_path="/sbin/init" + agent="${rootfs}${agent_path}" + if [ ! -x "${agent}" ]; then + error "${agent_path} is not installed in ${rootfs}. Use AGENT_BIN env variable to change the expected agent binary name" + return 1 + fi + # checksum must be different to system + for systemd_path in $candidate_systemd_paths; do + systemd="${rootfs}${systemd_path}" + if [ -f "${systemd}" ] && cmp -s "${systemd}" "${agent}"; then + error "The agent is not the init process. ${agent_path} is systemd" + return 1 + fi + done + + OK "Agent installed" + ;; + + *) + error "Invalid value for AGENT_INIT: '${AGENT_INIT}'. Use to 'yes' or 'no'" + return 1 + ;; + esac + + return 0 +} + +calculate_required_disk_size() { + local rootfs="$1" + local fs_type="$2" + local block_size="$3" + + readonly rootfs_size_mb=$(du -B 1MB -s "${rootfs}" | awk '{print $1}') + readonly image="$(mktemp)" + readonly max_tries=20 + readonly increment=10 + + for i in $(seq 1 $max_tries); do + local img_size="$((rootfs_size_mb + (i * increment)))" + create_disk "${image}" "${img_size}" "${fs_type}" "${rootfs_start}" > /dev/null 2>&1 + if ! device="$(setup_loop_device "${image}")"; then + continue + fi + + if ! format_loop "${device}" "${block_size}" "${fs_type}" > /dev/null 2>&1 ; then + die "Could not format loop device: ${device}" + fi + local mount_dir + while [ -z "${mount_dir}" ]; do mount_dir="$(udisksctl mount -b ${device}p1)" || sleep 3; done + mount_dir="${mount_dir##* }" + avail="$(df -BM --output=avail "${mount_dir}" | tail -n1 | sed 's/[M ]//g')" + udisksctl unmount -b "${device}p1" &>/dev/null + udisksctl loop-delete -b "${device}" &>/dev/null + unset mount_dir + + if [ "${avail}" -gt "${rootfs_size_mb}" ]; then + #rmdir "${mount_dir}" + rm -f "${image}" + echo "${img_size}" + return + fi + done + + + #rmdir "${mount_dir}" + rm -f "${image}" + error "Could not calculate the required disk size" +} + +# Calculate image size based on the rootfs and free space +calculate_img_size() { + local rootfs="$1" + local root_free_space_mb="$2" + local fs_type="$3" + local block_size="$4" + + # rootfs start + DAX header size + rootfs end + local reserved_size_mb=$((rootfs_start + dax_header_sz + rootfs_end)) + + disk_size="$(calculate_required_disk_size "${rootfs}" "${fs_type}" "${block_size}")" + + img_size="$((disk_size + reserved_size_mb))" + if [ -n "${root_free_space_mb}" ]; then + img_size="$((img_size + root_free_space_mb))" + fi + + remaining="$((img_size % mem_boundary_mb))" + if [ "${remaining}" != "0" ]; then + img_size=$((img_size + mem_boundary_mb - remaining)) + fi + + echo "${img_size}" +} + +setup_loop_device() { + local image="$1" + + # Get the loop device bound to the image file (requires /dev mounted in the + # image build system and root privileges) + local device="$(udisksctl loop-setup -f ${image})" + device="${device##* }" + device="${device%.*}" + echo "${device}" + return 0 +} + +format_loop() { + local device="$1" + local block_size="$2" + local fs_type="$3" + + case "${fs_type}" in + "${ext4_format}") + mkfs.ext4 -q -F -E root_owner -b "${block_size}" "${device}p1" + info "Set filesystem reserved blocks percentage to ${reserved_blocks_percentage}%" + tune2fs -m "${reserved_blocks_percentage}" "${device}p1" + ;; + + "${xfs_format}") + # DAX and reflink cannot be used together! + # Explicitly disable reflink, if it fails then reflink + # is not supported and '-m reflink=0' is not needed. + if mkfs.xfs -m reflink=0 -q -f -b size="${block_size}" "${device}p1" 2>&1 | grep -q "unknown option"; then + mkfs.xfs -q -f -b size="${block_size}" "${device}p1" + fi + ;; + + *) + error "Unsupported fs type: ${fs_type}" + return 1 + ;; + esac +} + +create_disk() { + local image="$1" + local img_size="$2" + local fs_type="$3" + local part_start="$4" + + info "Creating raw disk with size ${img_size}M" + qemu-img create -q -f raw "${image}" "${img_size}M" + OK "Image file created" + + # Kata runtime expect an image with just one partition + # The partition is the rootfs content + info "Creating partitions" + parted -s -a optimal "${image}" -- \ + mklabel msdos \ + mkpart primary "${fs_type}" "${part_start}"M "${rootfs_end}"M + + OK "Partitions created" +} + +create_rootfs_image() { + local rootfs="$1" + local image="$2" + local img_size="$3" + local fs_type="$4" + local block_size="$5" + + create_disk "${image}" "${img_size}" "${fs_type}" "${rootfs_start}" + + if ! device="$(setup_loop_device "${image}")"; then + die "Could not setup loop device" + fi + + if ! format_loop "${device}" "${block_size}" "${fs_type}"; then + die "Could not format loop device: ${device}" + fi + + info "Mounting root partition" + local mount_dir + while [ -z "${mount_dir}" ]; do mount_dir="$(udisksctl mount -b ${device}p1)" || sleep 3; done + mount_dir="${mount_dir##* }" + OK "root partition mounted" + + info "Copying content from rootfs to root partition" + cp -a "${rootfs}"/* "${mount_dir}" + sync + OK "rootfs copied" + + info "Removing unneeded systemd services and sockets" + for u in "${systemd_units[@]}"; do + find "${mount_dir}" \ + -path "${mount_dir}/lost+found" -prune -o -type f \( \ + -name "${u}.service" -o \ + -name "${u}.socket" \) \ + -exec rm -f {} \; + done + + info "Removing unneeded systemd files" + for u in "${systemd_files[@]}"; do + find "${mount_dir}" \ + -path "${mount_dir}/lost+found" -prune -o \ + -type f -name "${u}" -exec rm -f {} \; + done + + info "Creating empty machine-id to allow systemd to bind-mount it" + touch "${mount_dir}/etc/machine-id" + + info "Unmounting root partition" + udisksctl unmount -b "${device}p1" + OK "Root partition unmounted" + + if [ "${fs_type}" = "${ext4_format}" ]; then + fsck.ext4 -D -y "${device}p1" + fi + + udisksctl loop-delete -b "${device}" + #rmdir "${mount_dir}" +} + +set_dax_header() { + local image="$1" + local img_size="$2" + local fs_type="$3" + local nsdax_bin="$4" + + # rootfs start + DAX header size + local rootfs_offset=$((rootfs_start + dax_header_sz)) + local header_image="${image}.header" + local dax_image="${image}.dax" + rm -f "${dax_image}" "${header_image}" + + create_disk "${header_image}" "${img_size}" "${fs_type}" "${rootfs_offset}" + + dax_header_bytes=$((dax_header_sz * 1024 * 1024)) + dax_alignment_bytes=$((dax_alignment * 1024 * 1024)) + info "Set DAX metadata" + # Set metadata header + # Issue: https://github.com/kata-containers/osbuilder/issues/240 + if [ -z "${nsdax_bin}" ] ; then + nsdax_bin="${script_dir}/nsdax" + gcc -O2 "${script_dir}/nsdax.gpl.c" -o "${nsdax_bin}" + trap "rm ${nsdax_bin}" EXIT + fi + "${nsdax_bin}" "${header_image}" "${dax_header_bytes}" "${dax_alignment_bytes}" + sync + + touch "${dax_image}" + # Copy MBR #1 + DAX metadata + dd if="${header_image}" of="${dax_image}" bs="${dax_header_sz}M" count=1 + # Copy MBR #2 + Rootfs + dd if="${image}" of="${dax_image}" oflag=append conv=notrunc + # final image + mv "${dax_image}" "${image}" + sync + + rm -f "${dax_image}" "${header_image}" +} + +main() { + # variables that can be overwritten by environment variables + local agent_bin="${AGENT_BIN:-kata-agent}" + local agent_init="${AGENT_INIT:-no}" + local fs_type="${FS_TYPE:-${ext4_format}}" + local image="${IMAGE:-kata-containers.img}" + local block_size="${BLOCK_SIZE:-4096}" + local root_free_space="${ROOT_FREE_SPACE:-}" + local nsdax_bin="${NSDAX_BIN:-}" + + while getopts "ho:r:f:" opt + do + case "$opt" in + h) usage; return 0;; + o) image="${OPTARG}" ;; + r) root_free_space="${OPTARG}" ;; + f) fs_type="${OPTARG}" ;; + *) break ;; + esac + done + + shift $(( OPTIND - 1 )) + rootfs="$(readlink -f "$1")" + if [ -z "${rootfs}" ]; then + usage + exit 0 + fi + + local container_engine + if [ -n "${USE_DOCKER}" ]; then + container_engine="docker" + elif [ -n "${USE_PODMAN}" ]; then + container_engine="podman" + fi + + if [ -n "$container_engine" ]; then + build_with_container "${rootfs}" \ + "${image}" "${fs_type}" "${block_size}" \ + "${root_free_space}" "${agent_bin}" \ + "${agent_init}" "${container_engine}" \ + "${nsdax_bin}" + exit $? + fi + + if ! check_rootfs "${rootfs}" ; then + die "Invalid rootfs" + fi + + img_size=$(calculate_img_size "${rootfs}" "${root_free_space}" "${fs_type}" "${block_size}") + + # the first 2M are for the first MBR + NVDIMM metadata and were already + # consider in calculate_img_size + rootfs_img_size=$((img_size - dax_header_sz)) + create_rootfs_image "${rootfs}" "${image}" "${rootfs_img_size}" \ + "${fs_type}" "${block_size}" + + # insert at the beginning of the image the MBR + DAX header + set_dax_header "${image}" "${img_size}" "${fs_type}" "${nsdax_bin}" +} + +main "$@" diff --git a/install_kata-agent.tpl b/install_kata-agent.tpl new file mode 100644 index 000000000000..6873c78824a4 --- /dev/null +++ b/install_kata-agent.tpl @@ -0,0 +1,5 @@ +#!/bin/bash + +build(){ + add_binary "${BINSRC}" "/init" +} diff --git a/install_sd-kata-agent.tpl b/install_sd-kata-agent.tpl new file mode 100644 index 000000000000..4edb4493f365 --- /dev/null +++ b/install_sd-kata-agent.tpl @@ -0,0 +1,7 @@ +#!/bin/bash + +build(){ + add_systemd_unit "${SRCDIR}/kata-containers.target" + add_systemd_unit "${SRCDIR}/kata-agent.service" + add_binary "${SRCDIR}/kata-agent" +} diff --git a/kata-agent.service.in b/kata-agent.service.in new file mode 100644 index 000000000000..0340bdbbbd54 --- /dev/null +++ b/kata-agent.service.in @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018-2019 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +[Unit] +Description=Kata Containers Agent +Documentation=https://github.com/kata-containers/kata-containers +Wants=kata-containers.target +#ConditionPathExists=/etc/initrd-release +#DefaultDependencies=no + +[Service] +# Send agent output to tty to allow capture debug logs +# from a VM vsock port +StandardOutput=tty +Type=simple +ExecStart=@BINDIR@/@AGENT_NAME@ +LimitNOFILE=infinity +# ExecStop is required for static agent tracing; in all other scenarios +# the runtime handles shutting down the VM. +ExecStop=/bin/sync ; /usr/bin/systemctl --force poweroff +FailureAction=poweroff diff --git a/kata-containers.target b/kata-containers.target new file mode 100644 index 000000000000..03f370075ee5 --- /dev/null +++ b/kata-containers.target @@ -0,0 +1,16 @@ +# +# Copyright (c) 2018-2019 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +[Unit] +Description=Kata Containers Agent Target +Requires=basic.target +Requires=tmp.mount +Wants=chronyd.service +Requires=kata-agent.service +Conflicts=rescue.service rescue.target +After=basic.target rescue.service rescue.target +AllowIsolate=yes +#ConditionPathExists=/etc/initrd-release diff --git a/kata-runtime.install b/kata-runtime.install deleted file mode 100644 index bf29b5a97eae..000000000000 --- a/kata-runtime.install +++ /dev/null @@ -1,44 +0,0 @@ -post_install() { - cat <<EOF - -To use kata-runtime with docker, -- add the following config to /etc/docker/daemon.json -""" -{ - "runtimes": { - "kata": { - "path": "/usr/bin/kata-runtime" - } - } -} -""" - and restart the docker daemon - -- run containers with the "--runtime=kata" options to use kata-runtime -""" -$ docker run --runtime=kata --rm busybox date -""" - -- to set Kata as the default runtime, add '"default-runtime": "kata"' to /etc/docker/daemon.json and restart the docker daemon -""" -{ - "default-runtime": "kata", - "runtimes": { - "kata": { - "path": "/usr/bin/kata-runtime" - }, - } -} - -""" - -- to run Kata with Firecracker, due to Firecracker's limitations, you have to set your Docker storage driver (ref: https://docs.docker.com/storage/storagedriver/select-storage-driver/ ) to 'devicemapper' in /etc/docker/daemon.json -""" -{ - "storage-driver": "devicemapper" -} -""" - -EOF - -} diff --git a/mkinitcpio-agent.conf b/mkinitcpio-agent.conf new file mode 100644 index 000000000000..1a36f26aab64 --- /dev/null +++ b/mkinitcpio-agent.conf @@ -0,0 +1,6 @@ +MODULES=() +BINARIES=() +FILES=() +HOOKS=(kata-agent) +#COMPRESSION="gzip" +#COMPRESSION_OPTIONS=() |