function unmount_image () { # unmount from the chroot # Don't use TMP_MOUNT_PATH here, it might not have been set. sudo umount -f $TMP_BUILD_DIR/mnt/sys || true sudo umount -f $TMP_BUILD_DIR/mnt/proc || true sudo umount -f $TMP_BUILD_DIR/mnt/dev || true sudo umount -f $TMP_BUILD_DIR/mnt/tmp/in_target.d || true # give it a second (ok really 5) to umount XXX - why? should instead track # the mount data / lsof etc. sleep 5 # oh ya don't want to forget to unmount the image sudo umount -f $TMP_BUILD_DIR/mnt || true # having disk corruption issues; one possibility is qemu-nbd not flush dirty # pages on disconnect? sync if [ -n "$EXTRA_UNMOUNT" ]; then $EXTRA_UNMOUNT fi } function cleanup () { unmount_image rm -rf $TMP_BUILD_DIR } function mk_build_dir () { export TMP_BUILD_DIR=$(mktemp -t -d image.XXXXXXXX) [ $? -eq 0 ] || die "Failed to create tmp directory" trap cleanup EXIT echo Building in $TMP_BUILD_DIR export TMP_IMAGE_PATH=$TMP_BUILD_DIR/image export TMP_HOOKS_PATH=$TMP_BUILD_DIR/hooks } function ensure_nbd () { NBD=`which qemu-nbd` if [ -z "$NBD" ]; then echo "Need qemu-nbd to build qcow2 files." sudo apt-get install qemu-utils fi # prep nbd for mounting (lsmod | grep '^nbd ') || sudo modprobe nbd max_part=16 } function ensure_base_available () { # TODO: don't cache -current forever. if [ ! -f $IMG_PATH/$BASE_IMAGE_FILE ] ; then echo "Fetching Base Image" wget $CLOUD_IMAGES/$RELEASE/current/$BASE_IMAGE_FILE -O $IMG_PATH/$BASE_IMAGE_FILE.tmp mv $IMG_PATH/$BASE_IMAGE_FILE.tmp $IMG_PATH/$BASE_IMAGE_FILE fi } function ensure_sudo () { sudo echo "Ensuring sudo is available" } function mount_tmp_image () { mkdir $TMP_BUILD_DIR/mnt sudo mount $@ $TMP_BUILD_DIR/mnt [ $? -eq 0 ] || die "Failed to mount image" export TMP_MOUNT_PATH=$TMP_BUILD_DIR/mnt } function create_base () { # Extract the base image sudo tar -C $TMP_MOUNT_PATH -xzf $IMG_PATH/$BASE_IMAGE_FILE # Configure Image # Setup resolv.conf so we can chroot to install some packages # XXXX: Should store the old state rather than unlink; then restore later. if [ -L $TMP_MOUNT_PATH/etc/resolv.conf ] ; then sudo unlink $TMP_MOUNT_PATH/etc/resolv.conf fi if [ -f $TMP_MOUNT_PATH/etc/resolv.conf ] ; then sudo rm -f $TMP_MOUNT_PATH/etc/resolv.conf fi # Recreate resolv.conf sudo touch $TMP_MOUNT_PATH/etc/resolv.conf sudo chmod 777 $TMP_MOUNT_PATH/etc/resolv.conf echo nameserver 8.8.8.8 > $TMP_MOUNT_PATH/etc/resolv.conf # supporting kernel file systems sudo mount -t proc none $TMP_MOUNT_PATH/proc sudo mount --bind /dev $TMP_MOUNT_PATH/dev sudo mount -t sysfs none $TMP_MOUNT_PATH/sys # If we have a network proxy, use it. if [ -n "$http_proxy" ] ; then sudo dd of=$TMP_MOUNT_PATH/etc/apt/apt.conf.d/60img-build-proxy << _EOF_ Acquire::http::Proxy "$http_proxy"; _EOF_ fi } # Helper function to run a command inside the chroot function run_in_target() { # -E to preserve http_proxy sudo -E chroot $TMP_MOUNT_PATH "$@" } function generate_hooks () { mkdir -p $TMP_HOOKS_PATH for _FLAVOUR in $IMAGE_FLAVOUR ; do [ -d $FLAVOURS_DIR/$_FLAVOUR ] || die "The flavour does not exist." ; cp -t $TMP_HOOKS_PATH -a $FLAVOURS_DIR/$_FLAVOUR/* ; done } # Check that a real flavour has been chosen (prevents foot-guns) function check_flavour () { [ -d $TMP_HOOKS_PATH ] || generate_hooks } # Helper function to run a directory of scripts inside the chroot function run_d_in_target() { check_flavour # 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 sudo mount -o remount,ro,bind ${TMP_HOOKS_PATH} $TMP_MOUNT_PATH/tmp/in_target.d run_in_target run-parts -v /tmp/in_target.d/$1.d sudo umount -f $TMP_MOUNT_PATH/tmp/in_target.d sudo rmdir $TMP_MOUNT_PATH/tmp/in_target.d fi } # Run a directory of hooks outside the target. function run_d() { check_flavour if [ -d ${TMP_HOOKS_PATH}/$1.d ] ; then run-parts ${TMP_HOOKS_PATH}/$1.d fi } function prepare_first_boot () { if [ -d ${TMP_HOOKS_PATH}/first-boot.d ] ; then sudo cp -t $TMP_MOUNT_PATH/etc/ -a $TMP_HOOKS_PATH/first-boot.d run_in_target mv /etc/rc.local /etc/rc.local.REAL sudo dd of=$TMP_MOUNT_PATH/etc/rc.local <