set -e
+CLEANUP=( )
+
+cleanup() {
+ if [ ${#CLEANUP[*]} -gt 0 ]; then
+ LAST_ELEMENT=$((${#CLEANUP[*]}-1))
+ REVERSE_INDEXES=$(seq ${LAST_ELEMENT} -1 0)
+ for i in $REVERSE_INDEXES; do
+ ${CLEANUP[$i]}
+ done
+ fi
+}
+
+trap cleanup EXIT
+
DEFAULT_FILE="@sysconfdir@/default/ganeti-instance-debootstrap"
if [ -f "$DEFAULT_FILE" ]; then
. "$DEFAULT_FILE"
: ${SUITE:="lenny"}
: ${ARCH:=""}
: ${EXTRA_PKGS:=""}
+: ${CUSTOMIZE_DIR:="@sysconfdir@/ganeti/instance-debootstrap.d"}
: ${GENERATE_CACHE:="yes"}
: ${CLEAN_CACHE:="14"} # number of days to keep a cache file
+: ${PARTITION_STYLE:="none"} # disk partition style
CACHE_DIR="@localstatedir@/cache/ganeti-instance-debootstrap"
DPKG_ARCH=${ARCH:-`dpkg --print-architecture`}
CACHE_FILE="$CACHE_DIR/cache-${SUITE}-${DPKG_ARCH}.tar"
-TEMP=`getopt -o i:b:s: -n '$0' -- "$@"`
-
-if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
-
-# Note the quotes around `$TEMP': they are essential!
-eval set -- "$TEMP"
-
-while true; do
- case "$1" in
- -i) instance=$2; shift 2;;
+. common.sh
- -b) blockdev=$2; shift 2;;
+# If the target device is not a real block device we'll first losetup it.
+# This is needed for file disks.
+if [ ! -b $blockdev ]; then
+ ORIGINAL_BLOCKDEV=$blockdev
+ blockdev=$(losetup -sf $blockdev)
+ CLEANUP+=("losetup -d $blockdev")
+fi
- -s) swapdev=$2; shift 2;;
+if [ "$PARTITION_STYLE" = "none" ]; then
+ filesystem_dev=$blockdev
+elif [ "$PARTITION_STYLE" = "msdos" ]; then
+ # Create one big partition, and make it bootable
+ sfdisk --quiet --Linux $blockdev <<EOF
+0,,L,*
+EOF
+ block_base=`basename $blockdev`
+ filesystem_dev_base=`kpartx -l -p- $blockdev | \
+ grep -m 1 "^$block_base.*$blockdev" | \
+ awk '{print $1}'`
+ kpartx -a -p- $blockdev
+ CLEANUP+=("kpartx -d -p- $blockdev")
+ filesystem_dev="/dev/mapper/$filesystem_dev_base"
+else
+ echo "Unknown partition style $PARTITION_STYLE"
+ exit 1
+fi
- --) shift; break;;
+mke2fs -Fjq $filesystem_dev
+root_uuid=$($VOL_ID -u $filesystem_dev )
- *) echo "Internal error!"; exit 1;;
- esac
-done
-if [ -z "$instance" -o -z "$blockdev" -o -z "$swapdev" ]; then
- echo "Missing -i or -b or -s argument!"
- exit 1
+if [ -n "$swapdev" ]; then
+ mkswap $swapdev
+ swap_uuid=$($VOL_ID -u $swapdev )
fi
-mkswap $swapdev
-mke2fs -Fjq $blockdev
TMPDIR=`mktemp -d` || exit 1
-trap "umount $TMPDIR; rmdir $TMPDIR" EXIT
+CLEANUP+=("rmdir $TMPDIR")
-# If it's not a block device try to mount it via loopback device.
-# This is needed for file disks.
-MOUNT_OPTIONS=""
-if [ ! -b $blockdev ]; then
- MOUNT_OPTIONS="$MOUNT_OPTIONS -o loop"
-fi
-mount $MOUNT_OPTIONS $blockdev $TMPDIR
+mount $filesystem_dev $TMPDIR
+CLEANUP+=("umount $TMPDIR")
# remove the cache file if it's old (> 2 weeks) and writable by the owner (the
# default due to the standard umask)
cat > $TMPDIR/etc/fstab <<EOF
# /etc/fstab: static file system information.
#
-# <file system> <mount point> <type> <options> <dump> <pass>
-/dev/sda / ext3 defaults 0 1
-/dev/sdb swap swap defaults 0 0
-proc /proc proc defaults 0 0
+# <file system> <mount point> <type> <options> <dump> <pass>
+UUID=$root_uuid / ext3 defaults 0 1
+proc /proc proc defaults 0 0
+EOF
+
+[ -n "$swapdev" ] && cat >> $TMPDIR/etc/fstab <<EOF
+UUID=$swap_uuid swap swap defaults 0 0
EOF
cat > $TMPDIR/etc/network/interfaces <<EOF
iface lo inet loopback
EOF
-umount $TMPDIR
-rmdir $TMPDIR
+if [ -e $TMPDIR/etc/inittab ]; then
+ cat $TMPDIR/etc/inittab | sed -re 's/\stty1$/ console/' \
+ > $TMPDIR/etc/inittab.new
+ mv $TMPDIR/etc/inittab.new $TMPDIR/etc/inittab
+elif [ -e $TMPDIR/etc/event.d/tty1 ]; then
+ cat $TMPDIR/etc/event.d/tty1 | sed -re 's/tty1/console/' \
+ > $TMPDIR/etc/event.d/console
+ rm $TMPDIR/etc/event.d/tty1
+fi
+
+RUN_PARTS=`which run-parts`
+
+if [ -n "$RUN_PARTS" -a -n "$CUSTOMIZE_DIR" -a -d "$CUSTOMIZE_DIR" ]; then
+ TARGET=$TMPDIR
+ BLOCKDEV=$blockdev
+ FSYSDEV=$filesystem_dev
+ export TARGET SUITE ARCH PARTITION_STYLE EXTRA_PKGS BLOCKDEV FSYSDEV
+ $RUN_PARTS $CUSTOMIZE_DIR
+fi
+
+# execute cleanups
+cleanup
trap - EXIT
exit 0