-#!/bin/sh
-# Filename: grml-bootstrap
-# Purpose: wrapper around debootstrap for installing plain Debian via grml
+#!/bin/bash
+# Filename: grml-debootstrap
+# Purpose: wrapper around debootstrap for installing plain Debian via Grml
# Authors: grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
# Bug-Reports: see http://grml.org/bugs/
-# License: This file is licensed under the GPL v2.
+# License: This file is licensed under the GPL v2+
################################################################################
# http://www.debian.org/releases/stable/i386/index.html.en
# variables {{{
PN="$(basename $0)"
-VERSION='0.34'
+VERSION="$(dpkg --list $PN 2>/dev/null| awk '/^i/ {print $3}')"
+VERSION="${VERSION:-unknown}"
MNTPOINT="/mnt/debootstrap.$$"
+# defaults
+VMSIZE="2G"
+
# inside the chroot system locales might not be available, so use minimum:
export LANG=C
export LC_ALL=C
-m, --mirror <URL> Mirror which should be used for apt-get/aptitude.
-i, --iso <mnt> Mountpoint where a Debian ISO is mounted to, for use
- instead of fetching packages from a mirror.
- -r, --release <name> Release of new Debian system (default: lenny).
+ instead of fetching packages from a mirror.
+ -r, --release <name> Release of new Debian system (default: squeeze).
-t, --target <target> Target partition (/dev/...) or directory where the
system should be installed to.
-p, --mntpoint <mnt> Mountpoint used for mounting the target system,
--nodebootstrap Skip debootstrap, only do configuration to the target.
--grub <device> Target for grub installation. Usage example: /dev/sda
--arch <arch> Architecture to use. Currently only i386 is supported.
+ --filesystem <fs> Filesystem that should be used when target is a partition
+ or Virtual Machine (see --vmfile).
--insecure Do not download and check Release file signatures.
+Options for Virtual Machine deployment:
+
+ --vmfile Set up a Virtual Machine instead of installing to
+ a partition or directory, to be combined with --target,
+ like: --vmfile --target /mnt/sda1/qemu.img
+ --vmsize <size> Use specified size for size of VM file (default: 2G).
+ Syntax as supported by qemu-img, like: --vmsize 3G
+
Configuration options:
-c, --config <file> Use specified configuration file, defaults to
-d, --confdir <path> Place of config files for debootstrap, defaults
to /etc/debootstrap
--packages <file> Install packages defined in specified list file.
+ --nopackages Skip installation of packages defined in
+ /etc/debootstrap/packages
--debconf <file> Pre-seed packages using specified pre-seed db file.
--keep_src_list Do not overwrite user provided apt sources.list.
--hostname <name> Hostname of Debian system.
"
}
-if [ "$1" = '-h' ] || [ "$1" = '-help' ] ; then
+if [ "$1" = '-h' ] || [ "$1" = '-help' ] || [ "$1" = "--help" ] ; then
usage
echo 'Please notice that this script requires root permissions!'
exit 0
# make sure we have what we need {{{
check4progs debootstrap dialog || exit 1
-check4root || exit 1
# }}}
-# source configuration file {{{
+# source main configuration file {{{
if [ -r /etc/debootstrap/config ] ; then
- if [ -n "$CONFIGFILE" ] ; then
- einfo "Using config file $CONFIGFILE."
- if ! . "$CONFIGFILE" ; then
- eerror "Error reading config file $CONFIGFILE" ; eend 1 ; exit 1
- fi
- else
- . /etc/debootstrap/config
- fi
+ . /etc/debootstrap/config
fi
# }}}
[ "$_opt_iso" ] && ISO=$_opt_iso
[ "$_opt_release" ] && RELEASE=$_opt_release
[ "$_opt_target" ] && TARGET=$_opt_target
+[ "$_opt_vmfile" ] && VIRTUAL=1
+[ "$_opt_vmsize" ] && VMSIZE=$_opt_vmsize
[ "$_opt_mntpoint" ] && MNTPOINT=$_opt_mntpoint
[ "$_opt_debopt" ] && DEBOOTSTRAP_OPT=$_opt_debopt
[ "$_opt_interactive" ] && INTERACTIVE=1
[ "$_opt_config" ] && CONFIGFILE=$_opt_config
+[ "$_opt_filesystem" ] && MKFS="mkfs.$_opt_filesystem"
[ "$_opt_packages_set" ] && PACKAGES='yes'
+[ "$_opt_nopackages" ] && PACKAGES=''
[ "$_opt_debconf_set" ] && DEBCONF='yes'
[ "$_opt_scripts_set" ] && SCRIPTS='yes'
[ "$_opt_pre_scripts_set" ] && PRE_SCRIPTS='yes'
}
# }}}
+# check for root permissions {{{
+if ! check4root ; then
+ echo "For usage instructions please execute '$PN --help'."
+ exit 1
+fi
+# }}}
+
+# make sure we have what we need {{{
+if [ -n "$VIRTUAL" ] ; then
+ check4progs kpartx mksh qemu-img || exit 1
+fi
+# }}}
+
+# source specified configuration file {{{
+if [ -n "$CONFIGFILE" ] ; then
+ einfo "Reading specified config file $CONFIGFILE."
+ if ! . "$CONFIGFILE" ; then
+ eerror "Error reading config file $CONFIGFILE" ; eend 1 ; exit 1
+ fi
+fi
+# }}}
+
# backwards compability checks {{{
if [ -n "$GROOT" ] ; then
echo "Error: you seem to have \$GROOT configured." >&2
fi
PARTITION_LIST=$(for i in $(echo $AVAILABLE_PARTITIONS) ; do
- echo "$i $(vol_id --type $i 2>/dev/null || echo [no_filesystem_yet])"
+ echo "$i $(blkid -s TYPE -o value $i 2>/dev/null || echo [no_filesystem_yet])"
done)
TARGET=$(dialog --title "$PN" --single-quoted --stdout \
# ask for Debian release {{{
prompt_for_release()
{
- [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='lenny'
+ [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='squeeze'
RELEASE="$(dialog --stdout --title "${PN}" --default-item $DEFAULT_RELEASE --menu \
"Please enter the Debian release you would like to use for installation:" \
- 0 50 3 \
- lenny Debian/stable \
- squeeze Debian/testing \
+ 0 50 4 \
+ lenny Debian/old-stable \
+ squeeze Debian/stable \
+ wheezy Debian/testing \
sid Debian/unstable)"
}
# }}}
MIRROR="$(dialog --stdout --title "${PN}" --inputbox \
"Please enter Debian mirror you would like to use for installing packages." \
0 0 $MIRROR)"
- else # CHROOT_VARIABLES == local
+ else # CHOOSE_MIRROR == local
[ -n "$ISO" ] || ISO='/mnt/mirror'
ISO="$(dialog --stdout --title "${PN}" --inputbox \
"Please enter directory name you would like to use for installing packages." \
gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}')
[ -n "$AVAILABLE_PARTITIONS" ] || echo "FIXME: no partitions available?"
PARTITION_LIST=$(for i in $(echo $AVAILABLE_PARTITIONS) ; do
- echo "$i $(vol_id --type $i 2>/dev/null || echo [no_filesystem_yet]) off"
+ echo "$i $(blkid -s TYPE -o value $i 2>/dev/null || echo [no_filesystem_yet]) off"
done)
dialog --title "$PN" --separate-output \
NUM_PARTITIONS=$((${NUM_PARTITIONS}+1))
done
+# force metadata version 0.90 for lenny so old grub can boot from this array.
+METADATA_VERSION=""
+if [ $RELEASE = "lenny" ]; then
+ METADATA_VERSION="-e0"
+fi
+
ERRORFILE=$(mktemp)
set +e
# TODO: better error handling?
yes | mdadm --create "${TARGET}" --level="${RAIDLEVEL}" \
- --raid-devices="${NUM_PARTITIONS}" ${SELECTED_PARTITIONS} 1>/dev/null 2>$ERRORFILE
+ --raid-devices="${NUM_PARTITIONS}" ${METADATA_VERSION} ${SELECTED_PARTITIONS} >/dev/null 2>$ERRORFILE
RC=$?
set -e
# do not display if MNTPOINT is the default one
case "$MNTPOINT" in /mnt/debootstrap*) ;; *) echo " Mount point: $MNTPOINT" ;; esac
- [ -n "$GRUB" ] && echo " Install grub: $GRUB" || echo " Install grub: no"
+ if [ -n "$VIRTUAL" ] ; then
+ echo " Install grub: yes"
+ else
+ [ -n "$GRUB" ] && echo " Install grub: $GRUB" || echo " Install grub: no"
+ fi
+
[ -n "$RELEASE" ] && echo " Using release: $RELEASE"
[ -n "$MIRROR" ] && echo " Using mirror: $MIRROR"
[ -n "$HOSTNAME" ] && echo " Using hostname: $HOSTNAME"
[ -n "$ISO" ] && echo " Using ISO: $ISO"
+ if [ -n "$VIRTUAL" ] ; then
+ echo " Deploying as Virtual Machine."
+ [ -n "$VMSIZE" ] && echo " Using Virtual Disk file with size of ${VMSIZE}."
+ fi
+ echo
echo " Important! Continuing will delete all data from ${TARGET}!"
echo
{
welcome_dialog
+ prompt_for_release
+
prompt_for_swraid
prompt_for_target
prompt_for_bootmanager
- prompt_for_release
-
prompt_for_hostname
prompt_for_password
TARGET="$(readlink -f $TARGET)"
}
-if [ -b "$TARGET" ] ; then
+if [ -b "$TARGET" ] || [ -n "$VIRTUAL" ] ; then
PARTITION=1
else
set_target_directory
# make sure nothing is left inside chroot so we can unmount it
[ -x "$MNTPOINT"/etc/init.d/ssh ] && "$MNTPOINT"/etc/init.d/ssh stop
[ -x "$MNTPOINT"/etc/init.d/mdadm ] && "$MNTPOINT"/etc/init.d/mdadm stop
- # ugly, but make sure we really don't leav anything (/proc /proc is intended)
- for ARG in /sys -a /proc /proc ; do
- [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount $ARG 1>/dev/null 2>&1 || true
+ # ugly, but make sure we really don't leave anything (/proc /proc is intended)
+ for ARG in /sys /proc /proc ; do
+ [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount $ARG >/dev/null 2>&1 || true
done
- umount "$MNTPOINT"/dev 1>/dev/null 2>&1 || true
+ umount "$MNTPOINT"/dev >/dev/null 2>&1 || true
- [ -d "$MNTPOINT/$ISODIR" ] && umount "$MNTPOINT/$ISODIR" 1>/dev/null 2>&1 || true
+ [ -d "$MNTPOINT/$ISODIR" ] && umount "$MNTPOINT/$ISODIR" >/dev/null 2>&1 || true
if [ -n "$DIRECTORY" ] ; then
einfo "Not unmounting $MNTPOINT as you requested me to install into a directory of your own choice." ; eend 0
else
- einfo "Unmounting $MNTPOINT" ; umount "$MNTPOINT" ; eend $?
+ einfo "Unmounting $MNTPOINT" ; umount "$MNTPOINT" ; eend $?
fi
if [ -n "$STAGES" ] ; then
fi
fi
+ if [ -n "${ORIG_TARGET}" ] ; then
+ einfo "Removing loopback mount of file ${ORIG_TARGET}."
+ kpartx -d "${ORIG_TARGET}" ; eend $?
+ fi
+
[ -n "$1" ] && EXIT="$1" || EXIT="1"
[ -n "$3" ] && einfo "Notice: just remove $STAGES/$3 to reexecute the stage"
# make sure /dev/disk/by-uuid/... is up2date, otherwise grub
# will fail to detect the uuid in the chroot
- blockdev --rereadpt "${TARGET%%[0-9]*}"
+ if echo "$TARGET" | grep -q "/dev/md" ; then
+ blockdev --rereadpt "${TARGET}"
+ elif ! [ -n "$VIRTUAL" ] ; then
+ blockdev --rereadpt "${TARGET%%[0-9]*}"
+ fi
# give the system 2 seconds, otherwise we might run into
# race conditions :-/
sleep 2
# modify filesystem settings {{{
tunefs() {
- if [ -n "$TUNE2FS" ] ; then
+ if [ -n "$TUNE2FS" ] && echo "$MKFS" | grep -q "mkfs.ext" ; then
einfo "Disabling automatic filesystem check on $TARGET via tune2fs"
$TUNE2FS $TARGET
eend $?
if grep -q $TARGET /proc/mounts ; then
ewarn "$TARGET already mounted, continuing anyway." ; eend 0
else
- [ -d "$MNTPOINT" ] || mkdir -p "$MNTPOINT"
+ if ! [ -d "${MNTPOINT}" ] ; then
+ [ -n "$VIRTUAL" ] || mkdir -p "${MNTPOINT}"
+ fi
einfo "Mounting $TARGET to $MNTPOINT"
+ mkdir -p "$MNTPOINT"
mount -o rw,suid,dev $TARGET $MNTPOINT
eend $?
fi
}
# }}}
+# prepare VM image for usage with debootstrap {{{
+prepare_vm() {
+ if [ -z "$VIRTUAL" ] ; then
+ return 0 # be quite by intention
+ fi
+
+ if [ -b "$TARGET" ] ; then
+ eerror "Error: specified virtual disk target ($TARGET) is an existing block device."
+ eend 1
+ exit 1
+ fi
+
+ ORIG_TARGET="$TARGET" # store for later reuse
+
+ qemu-img create -f raw "${TARGET}" "${VMSIZE}"
+ echo 4 66 | mksh /usr/share/grml-debootstrap/bootgrub.mksh -A | dd of="$TARGET" conv=notrunc
+ dd if=/dev/zero bs=1 conv=notrunc count=64 seek=446 of="$TARGET"
+ parted -s "${TARGET}" 'mkpart primary ext3 2M -1'
+
+ DEVINFO=$(kpartx -av $TARGET) # 'add map loop1p1 (253:0): 0 6289408 linear /dev/loop1 2048'
+ if [ -z "${DEVINFO}" ] ; then
+ echo Error setting up loopback device >&2
+ exit 1
+ fi
+
+ # hopefully this always works as expected
+ LOOP=$(echo ${DEVINFO} | sed 's/.* linear //; s/ [[:digit:]]*//') # '/dev/loop1'
+ BLOCKDEV=$(echo "${DEVINFO}" | sed -e 's/.* (\(.*:.*\)).*/\1/') # '253:0'
+ LOOP_PART="$(echo ${DEVINFO##add map } | sed 's/ .*//')" # '/dev/loop1p1'
+ export TARGET="/dev/mapper/$LOOP_PART" # '/dev/mapper/loop1p1'
+
+ blockdev --rereadpt "${LOOP}"
+
+ if [ -z "$TARGET" ] ; then
+ echo "Error: target could not be set to according /dev/mapper/* device." >&2
+ exit 1
+ fi
+}
+# }}}
+
+# make VM image bootable and unmount it {{{
+finalize_vm() {
+ if [ -z "${VIRTUAL}" ] ; then
+ return 0
+ fi
+
+ if ! mount "${TARGET}" "${MNTPOINT}" ; then
+ eerror "Error: Mounting ${TARGET} failed, can not continue." ; eend 1
+ exit 1
+ fi
+
+ einfo "Installing Grub as bootloader."
+ mount -t proc none "${MNTPOINT}"/proc
+ mount -t sysfs none "${MNTPOINT}"/sys
+ mount --bind /dev "${MNTPOINT}"/dev
+
+ mkdir -p "${MNTPOINT}/boot/grub"
+ if ! [ -d "${MNTPOINT}"/usr/lib/grub/i386-pc/ ] ; then
+ eerror "Error: grub not installed inside Virtual Machine. Can not install bootloader." ; eend 1
+ exit 1
+ fi
+
+ cp "${MNTPOINT}"/usr/lib/grub/i386-pc/* "${MNTPOINT}/boot/grub/"
+ chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos ext2
+ dd if="${MNTPOINT}/tmp/core.img" of="${ORIG_TARGET}" conv=notrunc seek=4
+ rm -f "${MNTPOINT}/tmp/core.img"
+
+ einfo "Updating grub configuration file."
+ chroot "${MNTPOINT}" update-grub
+
+ umount "${MNTPOINT}"/proc
+ umount "${MNTPOINT}"/sys
+ umount "${MNTPOINT}"/dev
+
+ einfo "Adjusting grub.cfg for successful boot sequence."
+ # ugly but needed to boot grub acordingly
+ sed -i "s;set root=.*;set root='(hd0,msdos1)';" "${MNTPOINT}"/boot/grub/grub.cfg
+ sed -i "s; root=/dev/.*; root=/dev/sda1;" "${MNTPOINT}"/boot/grub/grub.cfg
+
+ umount "${MNTPOINT}"
+ kpartx -d "${ORIG_TARGET}" >/dev/null
+}
+# }}}
+
# install main chroot {{{
debootstrap_system() {
if [ "$_opt_nodebootstrap" ]; then
[ -n "$INSTALL_NOTES" ] && echo "INSTALL_NOTES=$INSTALL_NOTES" >> $CHROOT_VARIABLES
[ -n "$ISODIR" ] && echo "ISODIR=$ISO" >> $CHROOT_VARIABLES
[ -n "$ISO" ] && echo "ISO=$ISO" >> $CHROOT_VARIABLES
- [ -n "$MIRROR" ] && echo "MIRROR=$MIRROR" >> $CHROOT_VARIABLES
[ -n "$KEEP_SRC_LIST" ] && echo "KEEP_SRC_LIST=$KEEP_SRC_LIST" >> $CHROOT_VARIABLES
+ [ -n "$MIRROR" ] && echo "MIRROR=$MIRROR" >> $CHROOT_VARIABLES
[ -n "$PACKAGES" ] && echo "PACKAGES=$PACKAGES" >> $CHROOT_VARIABLES
+ [ -n "$RM_APTCACHE" ] && echo "RM_APTCACHE=$RM_APTCACHE" >> $CHROOT_VARIABLES
[ -n "$ROOTPASSWORD" ] && echo "ROOTPASSWORD=$ROOTPASSWORD" >> $CHROOT_VARIABLES
+ [ -n "$SELECTED_PARTITIONS" ] && echo "SELECTED_PARTITIONS=$SELECTED_PARTITIONS" >> $CHROOT_VARIABLES
[ -n "$TARGET" ] && echo "TARGET=$TARGET" >> $CHROOT_VARIABLES
[ -n "$TARGET_UUID" ] && echo "TARGET_UUID=$TARGET_UUID" >> $CHROOT_VARIABLES
cp $VERBOSE /etc/network/interfaces $MNTPOINT/etc/network/interfaces
fi
+ # install config file providing some example entries
+ if [ -r /etc/network/interfaces.examples -a ! -r "$MNTPOINT/etc/network/interfaces.examples" ] ; then
+ cp /etc/network/interfaces.examples "$MNTPOINT/etc/network/interfaces.examples"
+ fi
+
eend 0
}
# }}}
}
# }}}
-# install booloader grub {{{
-grub_install() {
- if [ -z "$GRUB" ] ; then
- echo "Notice: \$GRUB not defined, will not install grub therefore."
- return 0
- fi
-
- if ! [ -x "$(which grub-install)" ] ; then
- echo "Error: grub-install not available. (Error while installing grub package?)"
- return 1
- fi
-
- if [ -n "$SELECTED_PARTITIONS" ] ; then # using sw-raid
- for device in $SELECTED_PARTITIONS ; do
- GRUB="${device%%[0-9]}"
- einfo "Installing grub on ${GRUB}:"
- grub-install --no-floppy --root-directory="$MNTPOINT" "$GRUB"
- eend $?
- done
- else
- einfo "Installing grub on ${GRUB}:"
- grub-install --no-floppy --root-directory="$MNTPOINT" "$GRUB"
- eend $?
- fi
-}
-# }}}
-
# unmount $MNTPOINT {{{
umount_chroot() {
# }}}
# now execute all the functions {{{
-for i in mkfs tunefs mount_target debootstrap_system preparechroot \
- execute_pre_scripts chrootscript execute_scripts grub_install umount_chroot \
- fscktool ; do
+for i in prepare_vm mkfs tunefs mount_target debootstrap_system \
+ preparechroot execute_pre_scripts chrootscript execute_scripts \
+ umount_chroot finalize_vm fscktool ; do
if stage "${i}" ; then
$i && ( stage "${i}" done && rm -f "${STAGES}/${i}" ) || bailout 2 "i"
fi
# end dialog of autoinstallation {{{
if [ -n "$AUTOINSTALL" ] ; then
- dialog --title "$PN" --msgbox \
- "Finished execution of ${PN}. Enjoy your Debian system." 0 0
+ if dialog --title "${PN}" --pause "Finished execution of ${PN}.
+Automatically rebooting in 10 seconds.
+
+Choose Cancel to skip rebooting." 10 60 10 ; then
+ noeject noprompt reboot
+ fi
else
einfo "Finished execution of ${PN}. Enjoy your Debian system." ; eend 0
fi