2015-08-28 04:49:04 +00:00
|
|
|
#!/bin/bash
|
2012-11-15 03:20:32 +00:00
|
|
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
|
|
|
# All Rights Reserved.
|
2013-01-25 22:23:56 +00:00
|
|
|
#
|
2012-11-15 03:20:32 +00:00
|
|
|
# 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
|
2013-01-25 22:23:56 +00:00
|
|
|
#
|
2012-11-15 03:20:32 +00:00
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
2013-01-25 22:23:56 +00:00
|
|
|
#
|
2012-11-15 03:20:32 +00:00
|
|
|
# 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.
|
|
|
|
|
2012-11-09 11:04:13 +00:00
|
|
|
function unmount_image () {
|
2013-08-15 16:45:31 +00:00
|
|
|
# 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
|
|
|
|
|
2012-11-09 11:04:13 +00:00
|
|
|
# unmount from the chroot
|
|
|
|
# Don't use TMP_MOUNT_PATH here, it might not have been set.
|
2013-12-31 09:44:48 +00:00
|
|
|
unmount_dir "$TMP_BUILD_DIR/mnt"
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
if [ -n "$EXTRA_DETACH" ]; then
|
|
|
|
$EXTRA_DETACH
|
|
|
|
fi
|
2012-11-09 11:04:13 +00:00
|
|
|
if [ -n "$EXTRA_UNMOUNT" ]; then
|
|
|
|
$EXTRA_UNMOUNT
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2016-03-09 22:43:27 +00:00
|
|
|
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"
|
|
|
|
}
|
|
|
|
|
2014-10-11 00:01:37 +00:00
|
|
|
function trap_cleanup() {
|
|
|
|
exitval=$?
|
|
|
|
cleanup
|
|
|
|
exit $exitval
|
|
|
|
}
|
|
|
|
|
2012-11-09 11:04:13 +00:00
|
|
|
function cleanup () {
|
2017-05-01 10:17:21 +00:00
|
|
|
dib-block-device --phase=umount \
|
|
|
|
--params="${DIB_BLOCK_DEVICE_PARAMS_YAML}"
|
2012-11-09 11:04:13 +00:00
|
|
|
unmount_image
|
2015-06-04 08:46:18 +00:00
|
|
|
cleanup_build_dir
|
|
|
|
cleanup_image_dir
|
2013-04-02 00:25:25 +00:00
|
|
|
}
|
|
|
|
|
2012-11-09 11:04:13 +00:00
|
|
|
# Helper function to run a command inside the chroot
|
2013-05-06 16:11:49 +00:00
|
|
|
function run_in_target () {
|
2015-04-28 00:02:15 +00:00
|
|
|
cmd="$@"
|
2013-05-07 12:20:35 +00:00
|
|
|
# -E to preserve http_proxy
|
2013-08-09 13:15:18 +00:00
|
|
|
ORIG_HOME=$HOME
|
|
|
|
export HOME=/root
|
2014-10-15 15:58:47 +00:00
|
|
|
# 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
|
2015-04-28 00:02:15 +00:00
|
|
|
# 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.
|
2016-12-21 08:17:40 +00:00
|
|
|
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"
|
2013-08-09 13:15:18 +00:00
|
|
|
export HOME=$ORIG_HOME
|
2012-11-09 11:04:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Helper function to run a directory of scripts inside the chroot
|
2013-05-06 16:11:49 +00:00
|
|
|
function run_d_in_target () {
|
2012-11-30 20:47:57 +00:00
|
|
|
check_element
|
2012-11-09 11:04:13 +00:00
|
|
|
# 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
|
2017-03-16 22:43:45 +00:00
|
|
|
# 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
|
2012-11-09 11:04:13 +00:00
|
|
|
sudo mount -o remount,ro,bind ${TMP_HOOKS_PATH} $TMP_MOUNT_PATH/tmp/in_target.d
|
2012-12-14 07:17:00 +00:00
|
|
|
check_break before-$1 run_in_target bash
|
2015-04-17 02:36:46 +00:00
|
|
|
[ -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
|
2017-03-16 02:58:31 +00:00
|
|
|
# NOTE: this is the dib-run-parts copied into the chroot by the
|
|
|
|
# dib-run-parts element.
|
2017-03-16 22:43:45 +00:00
|
|
|
run_in_target /tmp/in_target.d/dib-run-parts /tmp/in_target.d/$1.d
|
2013-08-01 14:50:17 +00:00
|
|
|
trap - ERR
|
2012-12-14 07:17:00 +00:00
|
|
|
check_break after-$1 run_in_target bash
|
2012-11-09 11:04:13 +00:00
|
|
|
sudo umount -f $TMP_MOUNT_PATH/tmp/in_target.d
|
2015-03-23 08:35:41 +00:00
|
|
|
if ! timeout 5 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
|
2012-11-09 11:04:13 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function finalise_base () {
|
2013-02-13 22:16:00 +00:00
|
|
|
TARGET_ROOT=$TMP_MOUNT_PATH run_d cleanup
|
2014-04-25 23:24:04 +00:00
|
|
|
# If the file has been set immutable, we probably want to keep it
|
|
|
|
if 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
|
2013-06-14 13:32:14 +00:00
|
|
|
fi
|
2015-05-20 09:24:17 +00:00
|
|
|
# Cleanup /tmp in the guest, so there is less cruft left there
|
2017-03-16 16:31:23 +00:00
|
|
|
unmount_dir $TMP_MOUNT_PATH/tmp
|
2015-05-20 09:24:17 +00:00
|
|
|
find $TMP_MOUNT_PATH/tmp -maxdepth 1 -mindepth 1 | xargs sudo rm -rf --one-file-system
|
2017-01-14 09:35:24 +00:00
|
|
|
# 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
|
2012-11-09 11:04:13 +00:00
|
|
|
}
|
|
|
|
|
2013-08-26 09:59:41 +00:00
|
|
|
function compress_and_save_image () {
|
2012-11-09 11:04:13 +00:00
|
|
|
# Recreate our image to throw away unnecessary data
|
2013-02-20 12:07:23 +00:00
|
|
|
test $IMAGE_TYPE != qcow2 && COMPRESS_IMAGE=""
|
2014-06-13 12:20:17 +00:00
|
|
|
if [ -n "$QEMU_IMG_OPTIONS" ]; then
|
|
|
|
EXTRA_OPTIONS="-o $QEMU_IMG_OPTIONS"
|
|
|
|
else
|
|
|
|
EXTRA_OPTIONS=""
|
|
|
|
fi
|
2015-03-25 21:34:13 +00:00
|
|
|
if [ "$IMAGE_TYPE" = "raw" ]; then
|
|
|
|
mv $TMP_IMAGE_PATH $1-new
|
2016-12-17 21:41:14 +00:00
|
|
|
elif [ "$IMAGE_TYPE" == "tgz" ]; then
|
|
|
|
gzip -9 < $IMAGE_NAME.tar > $1-new
|
|
|
|
rm $IMAGE_NAME.tar
|
2015-02-17 01:20:01 +00:00
|
|
|
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
|
2015-03-25 21:34:13 +00:00
|
|
|
else
|
|
|
|
echo "Converting image using qemu-img convert"
|
2016-05-12 15:44:04 +00:00
|
|
|
qemu-img convert ${COMPRESS_IMAGE:+-c} -f raw -O $IMAGE_TYPE $EXTRA_OPTIONS $TMP_IMAGE_PATH $1-new
|
2015-03-25 21:34:13 +00:00
|
|
|
fi
|
2013-08-26 09:59:41 +00:00
|
|
|
|
2014-10-01 19:34:21 +00:00
|
|
|
OUT_IMAGE_PATH=$1-new
|
2014-03-25 01:16:06 +00:00
|
|
|
finish_image $1
|
2013-07-01 16:20:15 +00:00
|
|
|
}
|
|
|
|
|
2012-12-18 20:45:02 +00:00
|
|
|
function do_extra_package_install () {
|
|
|
|
# Install any packages that were requested with the -p command line option
|
|
|
|
if [ "$INSTALL_PACKAGES" != "" ]; then
|
2013-01-28 05:41:54 +00:00
|
|
|
run_in_target install-packages ${INSTALL_PACKAGES[@]}
|
2012-12-18 20:45:02 +00:00
|
|
|
fi
|
|
|
|
}
|
2013-01-28 05:41:54 +00:00
|
|
|
|
|
|
|
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
|
2013-02-11 04:01:36 +00:00
|
|
|
}
|
2014-03-12 07:23:00 +00:00
|
|
|
|
|
|
|
# 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
|
2014-09-05 17:00:06 +00:00
|
|
|
KERNEL=$(basename $(eval ls -1rv "$BOOTDIR/${DIB_BAREMETAL_KERNEL_PATTERN}" | head -1))
|
|
|
|
RAMDISK=$(basename $(eval ls -1rv "$BOOTDIR/${DIB_BAREMETAL_INITRD_PATTERN}" | head -1))
|
2014-03-12 07:23:00 +00:00
|
|
|
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-}
|
2014-09-05 17:00:06 +00:00
|
|
|
RAMDISK=$(basename $(ls $BOOTDIR/initramfs-$KERNEL_VERSION.img) || echo "")
|
2014-03-12 07:23:00 +00:00
|
|
|
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
|
2015-01-21 20:40:39 +00:00
|
|
|
KERNEL=$(basename $(ls -1rv $BOOTDIR/vmlinu*generic 2>/dev/null || ls -1rv $BOOTDIR/vmlinu* | head -1))
|
2014-06-27 09:11:16 +00:00
|
|
|
RAMDISK=$(basename $(ls -1rv $BOOTDIR/initrd*generic 2>/dev/null || ls -1rv $BOOTDIR/initrd* | head -1))
|
2015-04-10 08:58:19 +00:00
|
|
|
|
|
|
|
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
|
2014-03-12 07:23:00 +00:00
|
|
|
elif [ -f $TARGET_ROOT/etc/SuSE-release ]; then
|
2014-08-31 15:25:04 +00:00
|
|
|
KERNEL=$(basename $(readlink -e $BOOTDIR/vmlinuz))
|
|
|
|
RAMDISK=$(basename $(readlink -e $BOOTDIR/initrd))
|
2016-01-04 17:00:28 +00:00
|
|
|
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))"
|
2014-03-12 07:23:00 +00:00
|
|
|
else
|
|
|
|
echo "ERROR: Unable to detect operating system"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|