diskimage-builder/diskimage_builder/lib/img-functions
Yolanda Robla 81f495ad00 Increase timeout for removal
Under certain environments, this timeout was causing failures
because it was too short. Increasing to 10, to give time to
perform the specified tasks.

Change-Id: I01dd3553f38e1137b2fcb04b4ee12202be3ad1a8
2017-08-11 16:29:26 +02:00

224 lines
9.0 KiB
Bash

#!/bin/bash
# Copyright 2012 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
function unmount_image () {
# Calling sync before helps ensure the mount isn't busy when you unmount it.
# Previously observing having disk corruption issues; one possibility is
# qemu-nbd not flushing dirty pages on disconnect?
# https://bugs.launchpad.net/diskimage-builder/+bug/1214388
sync
# unmount from the chroot
# Don't use TMP_MOUNT_PATH here, it might not have been set.
unmount_dir "$TMP_BUILD_DIR/mnt"
if [ -n "$EXTRA_DETACH" ]; then
$EXTRA_DETACH
fi
if [ -n "$EXTRA_UNMOUNT" ]; then
$EXTRA_UNMOUNT
fi
}
function fstrim_image () {
# A race condition can occur when trying to fstrim immediately after
# deleting a file resulting in that free space not being reclaimed.
# Calling sync before fstrim is a workaround for this behaviour.
# https://lists.gnu.org/archive/html/qemu-devel/2014-03/msg02978.html
sync
# Discard all unused bytes
sudo fstrim "${TMP_BUILD_DIR}/mnt"
}
function trap_cleanup() {
exitval=$?
cleanup
exit $exitval
}
function cleanup () {
dib-block-device umount
unmount_image
cleanup_build_dir
cleanup_image_dir
}
# Helper function to run a command inside the chroot
function run_in_target () {
cmd="$@"
# -E to preserve http_proxy
ORIG_HOME=$HOME
export HOME=/root
# Force an empty TMPDIR inside the chroot. There is no need to use an user
# defined tmp dir which may not exist in the chroot.
# Bug: #1330290
# Force the inclusion of a typical set of dirs in PATH, this is needed for guest
# distros that have path elements not in the host PATH.
sudo -E chroot $TMP_MOUNT_PATH env -u TMPDIR -u VIRTUAL_ENV PATH="\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" sh -c "$cmd"
export HOME=$ORIG_HOME
}
# Helper function to run a directory of scripts inside the chroot
function run_d_in_target () {
check_element
# If we can find a directory of hooks to run in the target filesystem, bind
# mount it into the target and then execute run-parts in a chroot
if [ -d ${TMP_HOOKS_PATH}/$1.d ] ; then
sudo mkdir $TMP_MOUNT_PATH/tmp/in_target.d
sudo mount --bind ${TMP_HOOKS_PATH} $TMP_MOUNT_PATH/tmp/in_target.d
# Copy in dib-run-parts to run inside chroot. Note, in the
# future, we might like to use a diffrent dib-run-parts for
# running inside the chroot that doesn't rely on bash. For now
# they're the same. Note also this gets cleaned up with the dir
# delete below.
sudo cp ${DIB_RUN_PARTS} ${TMP_MOUNT_PATH}/tmp/in_target.d
sudo mount -o remount,ro,bind ${TMP_HOOKS_PATH} $TMP_MOUNT_PATH/tmp/in_target.d
check_break before-$1 run_in_target bash
[ -z "$break_outside_target" ] && in_target_arg="run_in_target" || in_target_arg=
trap "check_break after-error $in_target_arg ${break_cmd:-bash}" ERR
# NOTE: this is the dib-run-parts copied into the chroot by the
# dib-run-parts element.
run_in_target /tmp/in_target.d/dib-run-parts /tmp/in_target.d/$1.d
trap - ERR
check_break after-$1 run_in_target bash
sudo umount -f $TMP_MOUNT_PATH/tmp/in_target.d
if ! timeout 10 sh -c " while ! sudo rmdir $TMP_MOUNT_PATH/tmp/in_target.d; do sleep 1; done"; then
echo "ERROR: unable to cleanly remove $TMP_MOUNT_PATH/tmp/in_target.d"
exit 1
fi
fi
}
function finalise_base () {
TARGET_ROOT=$TMP_MOUNT_PATH run_d cleanup
# In create_base() we replaced/created the initial resolv.conf
# inside the image with a copy of the "outside" version so that
# resolving during the build will work.
#
# If that file has been replace with a symlink (resolvconf package
# can do this), or marked immutable, then don't restore the
# original version, just leave it alone.
if [ -L $TMP_MOUNT_PATH/etc/resolv.conf ] || \
lsattr $TMP_MOUNT_PATH/etc/resolv.conf | grep '^....i' >/dev/null ; then
# We're keeping the contents of resolv.conf set in the elements,
# so remove the old saved file
sudo rm -f $TMP_MOUNT_PATH/etc/resolv.conf.ORIG
else
# Remove the resolv.conf we created above
sudo rm -f $TMP_MOUNT_PATH/etc/resolv.conf
# Move the original back
if [ -L $TMP_MOUNT_PATH/etc/resolv.conf.ORIG ] || [ -f $TMP_MOUNT_PATH/etc/resolv.conf.ORIG ] ; then
sudo mv $TMP_MOUNT_PATH/etc/resolv.conf.ORIG $TMP_MOUNT_PATH/etc/resolv.conf
fi
fi
# Cleanup /tmp in the guest, so there is less cruft left there
unmount_dir $TMP_MOUNT_PATH/tmp
find $TMP_MOUNT_PATH/tmp -maxdepth 1 -mindepth 1 | xargs sudo rm -rf --one-file-system
# Truncate /var/log files in preparation for first boot
sudo find ${TMP_MOUNT_PATH}/var/log -type f -exec cp /dev/null '{}' \;
# also /root logs
sudo find ${TMP_MOUNT_PATH}/root -name \*.log -type f -delete
}
function compress_and_save_image () {
# Recreate our image to throw away unnecessary data
test $IMAGE_TYPE != qcow2 && COMPRESS_IMAGE=""
if [ -n "$QEMU_IMG_OPTIONS" ]; then
EXTRA_OPTIONS="-o $QEMU_IMG_OPTIONS"
else
EXTRA_OPTIONS=""
fi
if [ "$IMAGE_TYPE" = "raw" ]; then
mv $TMP_IMAGE_PATH $1-new
elif [ "$IMAGE_TYPE" == "tgz" ]; then
gzip -9 < $IMAGE_NAME.tar > $1-new
rm $IMAGE_NAME.tar
elif [ "$IMAGE_TYPE" == "vhd" ]; then
cp $TMP_IMAGE_PATH $1-intermediate
vhd-util convert -s 0 -t 1 -i $1-intermediate -o $1-intermediate
vhd-util convert -s 1 -t 2 -i $1-intermediate -o $1-new
# The previous command creates a .bak file
rm $1-intermediate.bak
OUT_IMAGE_PATH=$1-new
else
echo "Converting image using qemu-img convert"
qemu-img convert ${COMPRESS_IMAGE:+-c} -f raw -O $IMAGE_TYPE $EXTRA_OPTIONS $TMP_IMAGE_PATH $1-new
fi
OUT_IMAGE_PATH=$1-new
finish_image $1
}
function do_extra_package_install () {
# Install any packages that were requested with the -p command line option
if [ "$INSTALL_PACKAGES" != "" ]; then
run_in_target install-packages ${INSTALL_PACKAGES[@]}
fi
}
function copy_elements_lib () {
sudo mkdir -p $TMP_MOUNT_PATH/lib/diskimage-builder
sudo cp -t $TMP_MOUNT_PATH/lib/diskimage-builder $_LIB/elements-functions
}
# Dig up the initrd and kernel.
function select_boot_kernel_initrd () {
TARGET_ROOT=$1
BOOTDIR=$TARGET_ROOT/boot
if [ -n "${DIB_BAREMETAL_KERNEL_PATTERN:-}" -a -n "${DIB_BAREMETAL_INITRD_PATTERN:-}" ]; then
KERNEL=$(basename $(eval ls -1rv "$BOOTDIR/${DIB_BAREMETAL_KERNEL_PATTERN}" | head -1))
RAMDISK=$(basename $(eval ls -1rv "$BOOTDIR/${DIB_BAREMETAL_INITRD_PATTERN}" | head -1))
elif [ -f $TARGET_ROOT/etc/redhat-release ]; then
# Prioritize PAE if present
KERNEL=$(ls -1rv $BOOTDIR/vmlinuz* | grep PAE | grep -v debug | head -1 || echo "")
KERNEL=${KERNEL:-$(ls -1rv $BOOTDIR/vmlinuz* | grep -v debug | head -1 || echo "")}
if [ ! $KERNEL ]; then
echo "No suitable kernel found."
exit 1
fi
KERNEL=$(basename $KERNEL)
KERNEL_VERSION=${KERNEL#vmlinuz-}
RAMDISK=$(basename $(ls $BOOTDIR/initramfs-$KERNEL_VERSION.img) || echo "")
if [ ! $RAMDISK ]; then
echo "Can't find an initramfs for the $KERNEL_VERSION version of the kernel."
exit 1
fi
elif [ -f $TARGET_ROOT/etc/debian_version ]; then
KERNEL=$(basename $(ls -1rv $BOOTDIR/vmlinu*generic 2>/dev/null || ls -1rv $BOOTDIR/vmlinu* | head -1))
RAMDISK=$(basename $(ls -1rv $BOOTDIR/initrd*generic 2>/dev/null || ls -1rv $BOOTDIR/initrd* | head -1))
if [ -f $TARGET_ROOT/dib-signed-kernel-version ] ; then
. $TARGET_ROOT/dib-signed-kernel-version
fi
if [ -n "${DIB_SIGNED_KERNEL_VERSION:-}" ]; then
echo "Using signed kernel $DIB_SIGNED_KERNEL_VERSION"
KERNEL=$(basename $(ls -1rv $BOOTDIR/vmlinu*generic.efi.signed 2>/dev/null))
fi
elif [ -f $TARGET_ROOT/etc/SuSE-release ]; then
KERNEL=$(basename $(readlink -e $BOOTDIR/vmlinuz))
RAMDISK=$(basename $(readlink -e $BOOTDIR/initrd))
elif [[ -f "${TARGET_ROOT}"/etc/gentoo-release ]]; then
KERNEL="$(basename $(ls -1rv $BOOTDIR/kernel-*-openstack | head -n 1))"
RAMDISK="$(basename $(ls -1rv $BOOTDIR/initramfs-*-openstack | head -n 1))"
else
echo "ERROR: Unable to detect operating system"
exit 1
fi
}