diff --git a/bin/disk-image-create b/bin/disk-image-create index 7ea65c4dc..c38a20055 100755 --- a/bin/disk-image-create +++ b/bin/disk-image-create @@ -63,6 +63,7 @@ function show_options () { echo " --qemu-img-options -- option flags to be passed directly to qemu-img." echo " Options need to be comma separated, and follow the key=value pattern." echo " --root-label label -- label for the root filesystem. Defaults to 'cloudimg-rootfs'." + echo " --ramdisk-element -- specify the main element to be used for building ramdisks." if [ "$IS_RAMDISK" == "0" ]; then echo " -n skip the default inclusion of the 'base' element" echo " -p package[,package,package] -- list of packages to install in the image" @@ -87,7 +88,7 @@ function show_options () { INSTALL_PACKAGES="" COMPRESS_IMAGE="true" DIB_ROOT_LABEL="" -TEMP=`getopt -o a:ho:t:xucnp: -l no-tmpfs,offline,help,min-tmpfs:,image-size:,image-cache:,max-online-resize:,qemu-img-options:,root-label: -n $SCRIPTNAME -- "$@"` +TEMP=`getopt -o a:ho:t:xucnp: -l no-tmpfs,offline,help,min-tmpfs:,image-size:,image-cache:,max-online-resize:,qemu-img-options:,ramdisk-element:,root-label: -n $SCRIPTNAME -- "$@"` if [ $? -ne 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP': they are essential! @@ -112,6 +113,7 @@ while true ; do --offline) shift; export DIB_OFFLINE=1;; --qemu-img-options) QEMU_IMG_OPTIONS=$2; shift 2;; --root-label) export DIB_ROOT_LABEL=$2; shift 2;; + --ramdisk-element) RAMDISK_ELEMENT=$2; shift 2;; --) shift ; break ;; *) echo "Internal error!" ; exit 1 ;; esac diff --git a/elements/deploy-ironic/init.d/80-deploy-ironic b/elements/deploy-ironic/init.d/80-deploy-ironic index f0ba49bc7..d52ccdedc 100644 --- a/elements/deploy-ironic/init.d/80-deploy-ironic +++ b/elements/deploy-ironic/init.d/80-deploy-ironic @@ -35,9 +35,11 @@ if [ "$BOOT_METHOD" = "$VMEDIA_BOOT_TAG" ]; then else TOKEN_FILE=token-$DEPLOYMENT_ID - if tftp -r $TOKEN_FILE -g $BOOT_SERVER - then TOKEN_HEADER="-H 'X-Auth-Token: $(cat $TOKEN_FILE)'" - else TOKEN_HEADER="" + # Allow multiple versions of the tftp client + if tftp -r $TOKEN_FILE -g $BOOT_SERVER || tftp $BOOT_SERVER -c get $TOKEN_FILE; then + TOKEN_HEADER="-H 'X-Auth-Token: $(cat $TOKEN_FILE)'" + else + TOKEN_HEADER="" fi fi diff --git a/elements/dracut-ramdisk/README.md b/elements/dracut-ramdisk/README.md new file mode 100644 index 000000000..c3f19185d --- /dev/null +++ b/elements/dracut-ramdisk/README.md @@ -0,0 +1,5 @@ +Build Dracut-based ramdisks + +This is an alternative to the `ramdisk` element that uses +Dracut to provide the base system functionality instead of +Busybox. diff --git a/elements/dracut-ramdisk/element-deps b/elements/dracut-ramdisk/element-deps new file mode 100644 index 000000000..c07f41335 --- /dev/null +++ b/elements/dracut-ramdisk/element-deps @@ -0,0 +1,3 @@ +pkg-map +ramdisk-base +source-repositories diff --git a/elements/dracut-ramdisk/environment.d/10-dracut-version.bash b/elements/dracut-ramdisk/environment.d/10-dracut-version.bash new file mode 100644 index 000000000..5b752b629 --- /dev/null +++ b/elements/dracut-ramdisk/environment.d/10-dracut-version.bash @@ -0,0 +1,2 @@ +# Using 037 because that matches the current Fedora package +export DRACUT_VERSION=037 diff --git a/elements/dracut-ramdisk/extra-data.d/scripts/module/deploy-cmdline.sh b/elements/dracut-ramdisk/extra-data.d/scripts/module/deploy-cmdline.sh new file mode 100755 index 000000000..7cd143281 --- /dev/null +++ b/elements/dracut-ramdisk/extra-data.d/scripts/module/deploy-cmdline.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# NOTE(bnemec): Dracut doesn't like it if we enable these +# dib-lint: disable=setu sete setpipefail + +source /init-func + +find_target() { + local DISK=$(getarg disk) + local target_disk= + t=0 + while ! target_disk=$(find_disk "$DISK"); do + if [ $t -eq 10 ]; then + break + fi + t=$(($t + 1)) + sleep 1 + done + echo $target_disk +} +root=$(find_target) + +if [ -n "$root" ]; then + rootok=1 +fi + +# Dracut doesn't correctly parse the ip argument passed to us. +# Override /proc/cmdline to rewrite it in a way dracut can grok. +sed 's/\(ip=\S\+\)/\1:::off/' /proc/cmdline > /run/cmdline +# Map the existing "troubleshoot" kernel param to the Dracut equivalent. +sed -i 's/troubleshoot=/rd.shell=/' /run/cmdline +mount -n --bind -o ro /run/cmdline /proc/cmdline +# Force Dracut to re-read the cmdline args +CMDLINE= diff --git a/elements/dracut-ramdisk/extra-data.d/scripts/module/module-setup.sh b/elements/dracut-ramdisk/extra-data.d/scripts/module/module-setup.sh new file mode 100755 index 000000000..694e8d427 --- /dev/null +++ b/elements/dracut-ramdisk/extra-data.d/scripts/module/module-setup.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Dracut is bash too, and it doesn't play nicely with our usual sets +# dib-lint: disable=setu sete setpipefail + +check() { + return 0 +} + +depends() { + return 0 +} + +install() { + inst_hook cmdline 80 "$moddir/deploy-cmdline.sh" + inst_hook pre-mount 50 "$moddir/init.sh" +} diff --git a/elements/dracut-ramdisk/install.d/20-install-dracut-deps b/elements/dracut-ramdisk/install.d/20-install-dracut-deps new file mode 100755 index 000000000..8621d893f --- /dev/null +++ b/elements/dracut-ramdisk/install.d/20-install-dracut-deps @@ -0,0 +1,24 @@ +#!/bin/bash + +set -eux +set -o pipefail + +DRACUT_NETWORK="dracut-network" +if [ 'ubuntu' = "$DISTRO_NAME" ]; then + DRACUT_NETWORK= + # Install Dracut from source because the packaged version is + # broken and old. For Dracut builds we throw away the chroot + # anyway so it won't matter if we've installed some build deps. + install-packages build-essential arping + pushd /tmp + tar xJvf dracut.tar.xz + pushd dracut-$DRACUT_VERSION + ./configure + make + make install + popd + popd +fi + +PACKAGES=$(pkg-map --element dracut-ramdisk ncat tftp) +install-packages $DRACUT_NETWORK wget $PACKAGES diff --git a/elements/dracut-ramdisk/pkg-map b/elements/dracut-ramdisk/pkg-map new file mode 100644 index 000000000..e3f831639 --- /dev/null +++ b/elements/dracut-ramdisk/pkg-map @@ -0,0 +1,15 @@ +{ + "family":{ + "debian":{ + "ncat":"netcat-traditional", + "tftp":"tftp-hpa" + }, + "redhat":{ + "ncat":"nmap-ncat" + } + }, + "default":{ + "ncat":"ncat", + "tftp":"tftp" + } +} \ No newline at end of file diff --git a/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk b/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk new file mode 100755 index 000000000..0c5e3fca2 --- /dev/null +++ b/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk @@ -0,0 +1,63 @@ +#!/bin/bash + +set -eux +set -o pipefail + +_LIB="/tmp/ramdisk-build" + +source "$_LIB/common-defaults" +source "$_LIB/img-defaults" +source "$_LIB/ramdisk-defaults" + +source "$_LIB/common-functions" +source "$_LIB/img-functions" +source "$_LIB/ramdisk-functions" + +KERNEL_VERSION="${DIB_KERNEL_VERSION:-$(find_kernel_version)}" +MODULE_DIR="$MODULE_ROOT/lib/modules/$KERNEL_VERSION" +FIRMWARE_DIR="$MODULE_ROOT/lib/firmware" +LIB_UDEV="$LIB_UDEV_ROOT/lib/udev" +INIT="$_LIB/scripts/init" +FUNCTIONS_D="$_LIB/scripts/d" +MODULE="$_LIB/scripts/module" +# NOTE(bnemec): IMAGE_ELEMENT is normally set in disk-image-create, but we're +# not using that to build the image here. +IMAGE_ELEMENT= + +mk_build_dir +mkdir -p "$TMP_BUILD_DIR/mnt" +export TMP_HOOKS_PATH=/tmp +export TMP_MOUNT_PATH="$TMP_BUILD_DIR/mnt" + +echo "building ramdisk in $TMP_MOUNT_PATH" + +populate_init +SCRIPT_HOME=/tmp/in_target.d/bin TMP_HOOKS_PATH=/tmp/in_target.d run_d ramdisk-install +MODULE_PATH="/usr/lib/dracut/modules.d" +cp -r "$MODULE" "$MODULE_PATH/80deploy-ramdisk" +cp "$TMP_MOUNT_PATH/init" "$MODULE_PATH/80deploy-ramdisk/init.sh" + +# Notes on the options passed to Dracut: +# -N: Do not build a host-specific ramdisk. We want to be able to run this ramdisk +# on as many different machines as possible. +# --install: A list of the binaries needed by our ramdisk script fragments. +# --kernel-cmdline: Kernel parameters to pass to the ramdisk. rd.neednet is required +# to force Dracut to bring up networking even if it isn't passed a +# network target root. Pre-loading the ahci module is necessary +# on some systems to ensure that SATA disks are recognized. +# --include: Files from the chroot to include in the ramdisk. +# --kver: The kernel version to use, as determined above. +# --add-drivers: Extra kernel modules to include in the ramdisk. +# -o: Force omission of these dracut modules. Our scripts are written for bash, +# so dash is not desirable, and plymouth was causing some issues on Ubuntu. +dracut -N \ + --install 'tail head awk ifconfig cut expr route ping tgtd tgtadm nc wget curl tftp grep' \ + --kernel-cmdline "rd.shell rd.debug rd.neednet=1 rd.driver.pre=ahci" \ + --include "$TMP_MOUNT_PATH/init-func" /init-func \ + --kver "${KERNEL_VERSION}" \ + --add-drivers "virtio virtio_net virtio_blk" \ + -o "dash plymouth" \ + /tmp/ramdisk + +cp "/boot/vmlinuz-${KERNEL_VERSION}" /tmp/kernel +chmod o+r /tmp/kernel diff --git a/elements/dracut-ramdisk/source-repository-dracut b/elements/dracut-ramdisk/source-repository-dracut new file mode 100644 index 000000000..d7c1bdc79 --- /dev/null +++ b/elements/dracut-ramdisk/source-repository-dracut @@ -0,0 +1 @@ +dracut file /tmp/dracut.tar.xz https://www.kernel.org/pub/linux/utils/boot/dracut/dracut-$DRACUT_VERSION.tar.xz diff --git a/lib/common-functions b/lib/common-functions index 6bd1f9750..0260d34d2 100644 --- a/lib/common-functions +++ b/lib/common-functions @@ -233,7 +233,7 @@ function arg_to_elements() { IMAGE_ELEMENT="base $IMAGE_ELEMENT" fi if [ "$IS_RAMDISK" == "1" ]; then - IMAGE_ELEMENT="ramdisk $IMAGE_ELEMENT" + IMAGE_ELEMENT="$RAMDISK_ELEMENT $IMAGE_ELEMENT" fi echo "Building elements: $IMAGE_ELEMENT" diff --git a/lib/ramdisk-defaults b/lib/ramdisk-defaults index 893826b13..13120f1df 100644 --- a/lib/ramdisk-defaults +++ b/lib/ramdisk-defaults @@ -18,6 +18,7 @@ # options for ramdisk-image-create export DIB_NO_TMPFS=${DIB_NO_TMPFS:-1} export DIB_MIN_TMPFS=${DIB_MIN_TMPFS:-1} +export RAMDISK_ELEMENT=${RAMDISK_ELEMENT:-ramdisk} source $_LIB/common-defaults MODULE_ROOT=${DIB_MODULE_ROOT:-""} LIB_UDEV_ROOT=${DIB_LIB_UDEV_ROOT:-""} diff --git a/lib/ramdisk-functions b/lib/ramdisk-functions index e41691afc..b34e93abb 100644 --- a/lib/ramdisk-functions +++ b/lib/ramdisk-functions @@ -25,7 +25,9 @@ function fullpath() { } function cleanup () { - unmount_dir "$TMP_BUILD_DIR/mnt" + if [ "$RAMDISK_ELEMENT" != "dracut-ramdisk" ]; then + unmount_dir "$TMP_BUILD_DIR/mnt" + fi if [ -f "$TMP_IMAGE_PATH" ]; then loopdev=`sudo losetup -j "$TMP_IMAGE_PATH" | cut -d: -f1` if [ -n "$loopdev" ]; then