#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
[ -n "${DEBUG:-}" ] && set -o xtrace
readonly IMAGE_TOPDIR="/var/cache/kata-containers"
readonly KERNEL_SYMLINK="${IMAGE_TOPDIR}/vmlinuz.container"
readonly KVERSION=`uname -r`
readonly SCRIPTNAME="$0"
readonly DRACUT_ROOTFS=`mktemp --directory -t kata-dracut-rootfs-XXXXXX`
readonly DRACUT_IMAGES=`mktemp --directory -t kata-dracut-images-XXXXXX`
trap exit_handler EXIT
readonly GENERATED_IMAGE="${DRACUT_IMAGES}/kata-containers.img"
readonly GENERATED_INITRD="${DRACUT_IMAGES}/kata-containers-initrd.img"
KERNEL_PATH=""
COMMAND=""
OSBUILDER_DIR="/usr/libexec/kata-containers/osbuilder"
die()
{
error "$*"
exit 1
}
error()
{
echo "ERROR: ${SCRIPTNAME}: $*" >&2
}
info()
{
echo "${SCRIPTNAME}: $*"
}
exit_handler()
{
rm -rf "${DRACUT_ROOTFS}" "${DRACUT_IMAGES}"
}
usage()
{
cat <<EOT
Usage: ${SCRIPTNAME} [options]
This script builds the kata appliance initrd and image and adds
stable symlink paths in ${IMAGE_TOPDIR}
This script is called at kata-osbuilder at RPM install %post time and
via kata-osbuilder-generate.service
Options:
-h Show this help message
-c Check if an initrd is already generated for the current
kernel, and if so, simply exit
-o DIRNAME Use the passed directory for osbuilder code. Point
To a git checkout if you want to use upstream osbuilder.
Default: ${OSBUILDER_DIR}
EOT
exit $1
}
parse_args()
{
while getopts "cho:" opt
do
case $opt in
c) COMMAND="check" ;;
h) usage 0 ;;
o) OSBUILDER_DIR="${OPTARG}" ;;
*) usage 1 ;;
esac
done
shift $(($OPTIND - 1))
if [ -n "$*" ]; then
error "Unhandled options: '$*'"
usage 1
fi
}
find_host_kernel_path()
{
local vmname
for vmname in vmlinuz vmlinux; do
local trypath="/lib/modules/$KVERSION/$vmname"
if [ -e "$trypath" ] ; then
KERNEL_PATH="$trypath"
break
fi
done
[ -z "$KERNEL_PATH" ] && die "Didn't find kernel path for version=$KVERSION"
if [ "$COMMAND" = "check" ]; then
local linked_kernel=$(readlink -n "${KERNEL_SYMLINK}" || :)
if [ "${KERNEL_PATH}" = "${linked_kernel}" ] ; then
info "symlink=${KERNEL_SYMLINK} already points to host kernel=${KERNEL_PATH}"
info "Nothing to generate. Exiting."
exit 0
fi
fi
}
generate_rootfs()
{
# To generate the rootfs, we build an initrd with dracut, extract
# the initrd content, and then discard the initrd. We then rebuild
# the initrd using the osbuilder native scripts.
#
# This is a bit wasteful, but it's the easiest way to work around
# obuilder script inflexibility for now, which expect that some rootfs.sh
# code is called on a fully populated distro root.
local agent_source_bin="/usr/libexec/kata-containers/osbuilder/agent/kata-agent"
local osbuilder_version="fedora-osbuilder-version-unknown"
local dracut_conf_dir="./dracut/dracut.conf.d"
local dracut_kmodules=`source ${dracut_conf_dir}/10-drivers.conf; echo "$drivers"`
local tmp_initrd=`mktemp --tmpdir=${DRACUT_IMAGES}`
unlink "$tmp_initrd"
# Build the initrd
echo -e "+ Building dracut initrd"
dracut \
--confdir "${dracut_conf_dir}" \
--no-compress \
--conf /dev/null \
${tmp_initrd} ${KVERSION}
# Extract the generated rootfs
echo "+ Extracting dracut initrd rootfs"
cat ${tmp_initrd} | \
cpio --extract --preserve-modification-time --make-directories --directory=${DRACUT_ROOTFS}
# Using the busybox dracut module sets /sbin/init -> busybox
# We don't want that. Reset it to systemd
ln -sf ../lib/systemd/systemd ${DRACUT_ROOTFS}/usr/sbin/init
# Make kata specific adjustments to our rootfs
echo "Calling osbuilder rootfs.sh on extracted rootfs"
AGENT_SOURCE_BIN="${agent_source_bin}" \
./rootfs-builder/rootfs.sh \
-o ${osbuilder_version} \
-r ${DRACUT_ROOTFS}
# Add modules-load.d file for all our manually specified drivers
mkdir -p ${DRACUT_ROOTFS}/etc/modules-load.d
echo ${dracut_kmodules} | tr " " "\n" > ${DRACUT_ROOTFS}/etc/modules-load.d/kata-modules.conf
}
move_images()
{
# Move images into place
local image_osbuilder_dir="${IMAGE_TOPDIR}/osbuilder-images"
local image_dir="${image_osbuilder_dir}/$KVERSION"
local initrd_dest_path="${image_dir}/fedora-kata-${KVERSION}.initrd"
local image_dest_path="${image_dir}/fedora-kata-${KVERSION}.img"
# This blows away the entire osbuilder-images/ dir, deleting any
# previously cached content
rm -rf "${image_osbuilder_dir}"
mkdir -p "${image_dir}"
ln -sf ${KERNEL_PATH} ${KERNEL_SYMLINK}
mv ${GENERATED_INITRD} ${initrd_dest_path}
ln -sf ${initrd_dest_path} ${IMAGE_TOPDIR}/kata-containers-initrd.img
mv ${GENERATED_IMAGE} ${image_dest_path}
ln -sf ${image_dest_path} ${IMAGE_TOPDIR}/kata-containers.img
}
main()
{
parse_args $*
[ "$(id -u)" -eq 0 ] || die "$0: must be run as root"
find_host_kernel_path
cd "${OSBUILDER_DIR}"
# Generate the rootfs using dracut
generate_rootfs
# Build the initrd
echo "+ Calling osbuilder initrd_builder.sh"
./initrd-builder/initrd_builder.sh -o ${GENERATED_INITRD} ${DRACUT_ROOTFS}
# Build the FS image
echo "+ Calling osbuilder image_builder.sh"
./image-builder/image_builder.sh -o ${GENERATED_IMAGE} ${DRACUT_ROOTFS}
# This is a workaround till issue[0] is fixed, released and packaged.
# [0]: https://github.com/kata-containers/osbuilder/issues/394
rm -f image-builder/nsdax
move_images
}
main $*