for Issue555
[grml-debootstrap.git] / grml-debootstrap
1 #!/bin/sh
2 # Filename:      grml-bootstrap
3 # Purpose:       wrapper around debootstrap for installing plain Debian via grml
4 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 ################################################################################
8 # http://www.debian.org/releases/stable/i386/index.html.en
9
10 set -e # exit on any error
11
12 # variables {{{
13 PN="$(basename $0)"
14 prog_real=`readlink -f -- $0`
15 VERSION='0.23'
16 MNTPOINT="/mnt/debootstrap.$$"
17
18 # inside the chroot system locales might not be available, so use minimum:
19 export LANG=C
20 export LC_ALL=C
21
22 # make sure interactive mode is only executed when
23 # using an empty configuration file or option --interactive
24 INTERACTIVE=''
25 # }}}
26
27 # source core functions {{{
28 . /etc/grml/lsb-functions
29 . /etc/grml/script-functions
30 # }}}
31
32 # help text {{{
33 usage() {
34   echo "$PN - wrapper around debootstrap for installing Debian
35
36 Usage: $PN [options]
37
38 Bootstrap options:
39
40   -m, --mirror=URL       Mirror which should be used for apt-get/aptitude.
41   -i, --iso=mnt          Mountpoint where a Debian ISO is mounted to, for use
42                            instead of fetching packages from a mirror.
43   -r, --release=name     Release of new Debian system (default: stable).
44   -t, --target=target    Target partition (/dev/...) or directory.
45   -p, --mntpoint=mnt     Mountpoint used for mounting the target system.
46       --debopt=params    Extra parameters passed to the debootstrap.
47       --interactive      Use interactive mode (frontend).
48
49 Configuration options:
50
51
52   -d, --confdir=path     Place of config files for debootstrap, defaults to
53                            /etc/debootstrap
54   -c, --config=file      Use specified configuration file, defaults to
55                            <confdir>/config
56       --packages[=f]     Install packages defined in <confdir>/packages. Option
57                            arg: alternative package list file.
58       --debconf[=f]      Pre-seed packages using <confdir>/debconf-selections.
59                            Option arg: alternative pre-seed db file.
60       --keep_src_list    Do not overwrite user provided apt sources.list.
61       --hostname=name    Hostname of Debian system.
62       --password=pwd     Use specified password as password for user root.
63
64       --bootappend=line  Add specified appendline to kernel whilst booting.
65       --groot=device     Root device for usage in grub, corresponds with
66                            $TARGET in grub syntax, like hd0,0 for /dev/sda1.
67       --grub=device      Target for grub installation. Use grub syntax for
68                            specifying, like hd0 for /dev/sda.
69
70 Other options:
71
72   -h, --help             Print this usage information and exit.
73   -v, --version          Show summary of options and exit.
74
75 Send bugreports to the grml-team: bugs@grml.org || http://grml.org/bugs/
76 "
77 }
78
79 if [ "$1" = '-h' ] || [ "$1" = '-help' ] ; then
80    usage
81    echo 'Please notice that this script requires root permissions!'
82    exit 0
83 fi
84 # }}}
85
86 # make sure we have what we need {{{
87 check4progs debootstrap dialog || exit 1
88 check4root || exit 1
89 # }}}
90
91 # source configuration file {{{
92 if [ -r /etc/debootstrap/config ] ; then
93    if [ -n "$CONFIGFILE" ] ; then
94       if ! . "$CONFIGFILE" ; then
95          eerror "Error reading config file $CONFIGFILE" ; eend 1 ; exit 1
96       fi
97    else
98       . /etc/debootstrap/config
99    fi
100 fi
101 # }}}
102
103 # cmdline handling {{{
104 # source external command line parameter-processing script
105 . $prog_real.clp
106
107 # business-logic of command line parameter-processing
108 [ "$_opt_mirror" ]              && MIRROR=$_opt_mirror
109 [ "$_opt_iso" ]                 && ISO=$_opt_iso
110 [ "$_opt_release" ]             && RELEASE=$_opt_release
111 [ "$_opt_target" ]              && TARGET=$_opt_target
112 [ "$_opt_mntpoint" ]            && MNTPOINT=$_opt_mntpoint
113 [ "$_opt_debopt" ]              && DEBOOTSTRAP_OPT=$_opt_debopt
114 [ "$_opt_interactive" ]         && INTERACTIVE=1
115 [ "$_opt_confdir" ]             && CONFFILES=$_opt_confdir
116 [ "$_opt_config" ]              && CONFIGFILE=$_opt_config
117 [ "$_opt_packages_set" ]        && PACKAGES='yes'
118 [ "$_opt_debconf_set" ]         && DEBCONF='yes'
119 [ "$_opt_keep_src_list" ]       && KEEP_SRC_LIST='yes'
120 [ "$_opt_hostname" ]            && HOSTNAME=$_opt_hostname
121 [ "$_opt_password" ]            && ROOTPASSWORD=$_opt_password
122 [ "$_opt_bootappend" ]          && BOOT_APPEND=$_opt_bootappend
123 [ "$_opt_groot" ]               && GROOT=$_opt_groot
124 [ "$_opt_grub" ]                && GRUB=$_opt_grub
125
126 [ "$_opt_help" ] && {
127   usage ; eend 0
128   eend 0
129   exit 0
130 }
131
132 [ "$_opt_version" ] && {
133   einfo "$PN - version $VERSION"
134   einfo "Send bug reports to bugs@grml.org or http://grml.org/bugs/"
135   eend 0
136   exit 0
137 }
138 # }}}
139
140 # welcome screen {{{
141 welcome_dialog()
142 {
143    dialog --title "$PN" --yesno "Welcome to the interactive configuration of ${PN}.
144 Do you want to continue installing Debian using this frontend?" 0 0
145 }
146 # }}}
147
148 # ask for target {{{
149 prompt_for_target()
150 {
151   AVAILABLE_PARTITIONS=$(LANG=C fdisk -l 2>/dev/null | \
152                sed 's/*//' | \
153                grep -v 'Extended$' | \
154                gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}')
155
156   if [ -z "$AVAILABLE_PARTITIONS" ] ; then
157      dialog --title "$PN" --trim \
158      --msgbox "Sorry, no partitions found. Please configure your
159      harddisks (see /proc/partitions) using a tool like fdisk,
160      cfdisk, gpart, gparted,..." 0 0
161      exit 0
162   fi
163
164   PARTITION_LIST=$(for i in $(echo $AVAILABLE_PARTITIONS) ; do
165                        echo "$i $(vol_id --type $i 2>/dev/null || echo [no_filesystem_yet])"
166                    done)
167
168   TARGET=$(dialog --title "$PN" --single-quoted --stdout \
169          --menu "Please select the target partition:" 0 0 0 \
170          $PARTITION_LIST)
171 }
172 # }}}
173
174 # ask for bootmanager {{{
175 prompt_for_bootmanager()
176 {
177   ADDITIONAL_PARAMS=""
178   for device in sda hda; do
179     if [ /dev/$device != ${TARGET%[0-9]} ]; then
180       grep -q $device /proc/partitions && \
181       ADDITIONAL_PARAMS=:$device:"install bootmanager grub into MBR of /dev/${device}"
182     fi
183   done
184   ADDITIONAL_PARAMS=${ADDITIONAL_PARAMS#:}
185
186   OIFS="$IFS"; IFS=:
187
188   if echo $TARGET | grep -q "/dev/md" ; then
189      MBRPART="all disks of Software RAID $TARGET"
190   else
191      MBRPART="MBR of ${TARGET%[0-9]}"
192   fi
193
194   GETMBR=$(dialog --stdout --title "$PN" --default-item mbr \
195           --menu "Where do you want to install the bootmanager grub?" 0 0 0 \
196             mbr       "install bootmanager into $MBRPART" \
197             partition "install bootmanager into partition $TARGET" \
198             nowhere   "do not install bootmanager at all" \
199           ${ADDITIONAL_PARAMS})
200   [ $? -eq 0 ] || bailout 3
201   IFS="$OIFS"
202
203   case "$GETMBR" in
204     mbr)
205       # /dev/md0: has to be installed in MBR of /dev/md0 and not in /dev/md:
206       if echo $TARGET | grep -q "*md*" ; then
207          BOOT_PARTITION="${TARGET}"
208       else
209          BOOT_PARTITION="${TARGET%[0-9]}"
210       fi
211       ;;
212     partition)
213       BOOT_PARTITION="$TARGET"
214       ;;
215     hda)
216       BOOT_PARTITION="/dev/hda"
217       ;;
218     sda)
219       BOOT_PARTITION="/dev/sda"
220       ;;
221     nowhere)
222       BOOT_PARTITION=''
223       ;;
224   esac
225 }
226 # }}}
227
228 # ask for Debian release {{{
229 prompt_for_release()
230 {
231   RELEASE="$(dialog --stdout --title "${PN}" --default-item etch --menu \
232             "Please enter the Debian release you would like to use for installation:" \
233             0 50 3 \
234             etch   Debian/stable \
235             lenny  Debian/testing \
236             sid    Debian/unstable)"
237 }
238 # }}}
239
240 # ask for hostname {{{
241 prompt_for_hostname()
242 {
243   HOSTNAME="$(dialog --stdout --title "${PN}" --inputbox \
244             "Please enter the hostname you would like to use for installation:" \
245             0 0 grml)"
246 }
247 # }}}
248
249 # ask for password {{{
250 prompt_for_password()
251 {
252      ROOTPW1='PW1'
253      ROOTPW2='PW2'
254      while [ "$ROOTPW1" != "$ROOTPW2" ]; do
255        ROOTPW1=$(dialog --insecure --stdout --title "${PN}" --passwordbox \
256        "Please enter the password for the root account:" 10 60)
257        ROOTPW2=$(dialog --insecure --stdout --title "${PN}" --passwordbox \
258        "Please enter the password for the root account again for \
259        confirmation:" 10 60)
260
261        if [ "$ROOTPW1" != "$ROOTPW2" ]; then
262          $(dialog --stdout --title "${PN}" --ok-label \
263          "Retry" --msgbox "Passwords do not match!" 10 60)
264        fi
265      done
266      ROOTPASSWORD="$ROOTPW1"
267 }
268 # }}}
269
270 # ask for Debian mirror {{{
271 prompt_for_mirror()
272 {
273   MIRROR="$(dialog --stdout --title "${PN}" --inputbox \
274             "Please enter Debian mirror you would like to use for installing packages." \
275             0 0 http://ftp.de.debian.org/debian)"
276 }
277 # }}}
278
279 # get grub's syntax for /dev/ice {{{
280 # usage example: 'grubdevice /dev/sda2' returns 'hd0,1'
281 grubdevice() {
282   if [ -z "$1" ] ; then
283      echo "Usage: grubdevice <device>">&2
284      return 1
285   fi
286
287   device="$1"
288   device_map=/boot/grub/device.map
289
290   # create device.map
291   if ! [ -f "$device_map" ] ; then
292      echo 'quit' | grub --device-map="$device_map" 1>/dev/null 2>&1
293   fi
294
295   # based on code from d-i's trunk/packages/arch/i386/grub-installer/grub-installer:
296   tmp_disk=`echo "$device" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
297                     -e 's%\(fd[0-9]*\)$%\1%' \
298                     -e 's%/part[0-9]*$%/disc%' \
299                     -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
300   tmp_part=`echo "$device" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
301                     -e 's%.*/fd[0-9]*$%%' \
302                     -e 's%.*/floppy/[0-9]*$%%' \
303                     -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
304                     -e 's%.*c[0-7]d[0-9]*p*%%'`
305   tmp_drive=$(grep -v '^#' $device_map | grep "$tmp_disk *$" | sed 's%.*\([hf]d[0-9][a-g0-9,]*\).*%\1%')
306
307   case $1 in
308      /dev/[sh]d[a-z]) # we expect something like 'hd0'
309         echo "$tmp_drive"
310         ;;
311       *) # we expect something like 'hd0,0'
312         echo "$tmp_drive" | sed "s%$%,`expr $tmp_part - 1`%" # FIXME => md0
313         ;;
314   esac
315 }
316 # }}}
317
318 # software raid setup {{{
319 config_swraid_setup()
320 {
321 TMPFILE=$(mktemp)
322
323 # Currently we support only raid1:
324 RAIDLEVEL='raid1'
325
326 #RAIDLEVEL=$(dialog --stdout --title "$PN" --default-item raid1 \
327 #                   --menu "Which RAID level do you want to use?" 0 0 0 \
328 #                     raid1 "Software RAID level 1" \
329 #                     raid5 "Software RAID level 5")
330 #[ $? -eq 0 ] || bailout 20
331
332 MD_LIST=$(for i in $(seq 0 9) ; do
333             awk '{print $4}' /proc/partitions | grep -q md$i || \
334             echo "/dev/md$i /dev/md$i"
335           done)
336
337 TARGET=$(dialog --stdout --title "$PN" --default-item /dev/md0 \
338 --menu "Which device do you want to use for ${RAIDLEVEL}?
339
340 Notice: activated devices will not be listed for security reasons. Anyway, please make sure the selected device is not in use already!" 0 0 0 \
341 $MD_LIST)
342 [ $? -eq 0 ] || bailout 20
343
344 AVAILABLE_PARTITIONS=$(LANG=C fdisk -l 2>/dev/null | \
345              sed 's/*//' | \
346              grep -v 'Extended$' | \
347              gawk -v num=0 -v ORS=' ' '/^\/dev\// {print $1}')
348 [ -n "$AVAILABLE_PARTITIONS" ] || echo "FIXME: no partitions available?"
349 PARTITION_LIST=$(for i in $(echo $AVAILABLE_PARTITIONS) ; do
350                      echo "$i $(vol_id --type $i 2>/dev/null || echo [no_filesystem_yet]) off"
351                  done)
352
353 dialog --title "$PN" --separate-output \
354        --checklist "Please select the partitions you would like to use for your $RAIDLEVEL on ${TARGET}:" 0 0 0 \
355        $PARTITION_LIST 2>$TMPFILE
356 RETVAL=$?
357 SELECTED_PARTITIONS="$(cat $TMPFILE)"
358
359 NUM_PARTITIONS=0
360 for i in $(cat $TMPFILE) ; do
361    NUM_PARTITIONS=$((${NUM_PARTITIONS}+1))
362 done
363
364 ERRORFILE=$(mktemp)
365 set +e
366 # TODO: better error handling?
367 yes | mdadm --create "${TARGET}" --level="${RAIDLEVEL}" \
368       --raid-devices="${NUM_PARTITIONS}" ${SELECTED_PARTITIONS} 1>/dev/null 2>$ERRORFILE
369 RC=$?
370 set -e
371
372 if [ "$RC" = 0 ] ; then
373    dialog --title "$PN" --msgbox \
374    "Creating $TARGET was successful." 0 0
375    rm -f "$TMPFILE" "$ERRORFILE"
376 else
377    dialog --title "$PN" --msgbox \
378    "There was an error setting up $TARGET:
379
380 $(cat $ERRORFILE)
381
382 Exiting." 0 0
383    rm -f "$TMPFILE" "$ERRORFILE"
384    exit 1
385 fi
386
387 }
388
389 prompt_for_swraid()
390 {
391 if dialog --stdout --title "$PN" \
392           --defaultno --yesno "Do you want to configure Software RAID?
393
394 Please notice that only RAID level 1 is supported by ${PN} currently. Configuration will take place using mdadm." 0 0 ; then
395   config_swraid_setup
396 fi
397 }
398 # }}}
399
400 # make sure the user is aware of the used configuration {{{
401 checkconfiguration()
402 {
403 if [ -n "$AUTOINSTALL" ] ; then
404    if checkforrun ; then
405       eerror "Exiting as requested" ; eend 0
406       exit 1
407    fi
408 elif [ -n "$INTERACTIVE" ] ; then
409
410    INFOTEXT="Please recheck configuration before execution:
411    "
412    [ -n "$TARGET" ]  && INFOTEXT="$INFOTEXT
413    Target:          $TARGET"
414    [ -n "$GRUB" ]    && INFOTEXT="$INFOTEXT
415    Install grub:    $GRUB"
416    [ -n "$RELEASE" ] && INFOTEXT="$INFOTEXT
417    Using release:   $RELEASE"
418    [ -n "$HOSTNAME" ] && INFOTEXT="$INFOTEXT
419    Using hostname   $HOSTNAME"
420    [ -n "$MIRROR" ]  && INFOTEXT="$INFOTEXT
421    Using mirror:    $MIRROR"
422
423    INFOTEXT="$INFOTEXT
424
425 Is this ok for you? Notice: selecting 'No' will exit ${PN}."
426
427    dialog --title "$PN" --no-collapse \
428           --yesno "$INFOTEXT" 0 0
429
430 else # if not running automatic installation display configuration and prompt for execution:
431    einfo "$PN - Please recheck configuration before execution:"
432    echo
433    echo "   Target:          $TARGET"
434       case "$MNTPOINT" in "$TARGET") ;; *) echo "   Mount point:     $MNTPOINT" ;; esac
435       [ -n "$GRUB" ]    && echo "   Install grub:    $GRUB" || echo "   Install grub:    no"
436       [ -n "$RELEASE" ] && echo "   Using release:   $RELEASE"
437       [ -n "$MIRROR" ]  && echo "   Using mirror:    $MIRROR"
438       [ -n "$ISO" ]     && echo "   Using iso:       $ISO"
439       case "$MNTPOINT" in "$TARGET") ;; *) echo "   Important! Continuing will delete all data from ${TARGET}!" ;; esac
440       echo
441    einfon "Is this ok for you? [y/N] "
442    read a
443    if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
444       eerror "Exiting as requested." ; eend 1
445       exit 1
446    fi
447 fi
448 }
449 # }}}
450
451 # interactive mode {{{
452 interactive_mode()
453 {
454   welcome_dialog
455
456   prompt_for_swraid
457
458   # do not prompt for partition dialog if swraid has been configured already
459   [ -n "$TARGET" ] || prompt_for_target
460
461   prompt_for_bootmanager
462
463   prompt_for_release
464
465   prompt_for_hostname
466
467   prompt_for_password
468
469   # use first disk of sw-raid for grub by default, install grub on
470   # all involved disks later on
471   if echo "$TARGET" | grep -q '/dev/md' ; then
472      if [ -n "$SELECTED_PARTITIONS" ] ; then # using sw-raid
473         # use hdX and not hdX,Y for $GRUB
474         TMPDEVICE=$(echo ${SELECTED_PARTITIONS} | awk '{print $1}') # use first disk only
475         GRUB="$(grubdevice ${TMPDEVICE%%[0-9]})" # like: hd0
476         GROOT="$(grubdevice ${TMPDEVICE})"       # like: hd0,0
477         echo "debug: GRUB = $GRUB - GROOT = $GROOT" >/tmp/debug # FIXME
478      fi
479   else
480      [ -n "$BOOT_PARTITION" ] && GRUB="$(grubdevice $BOOT_PARTITION)"
481      [ -n "$TARGET" ]         && GROOT="$(grubdevice $TARGET)"
482   fi
483
484   prompt_for_mirror
485
486   checkconfiguration
487 }
488
489 # run interactive mode if we didn't get the according configuration yet
490 if [ -z "$TARGET" -o -n "$INTERACTIVE" ] ; then
491    # only target might be unset, so make sure the INTERACTIVE flag is set as well
492    INTERACTIVE=1
493    interactive_mode
494 fi
495 # }}}
496
497 # finally make sure at least $TARGET is set [the partition for the new system] {{{
498 if [ -n "$TARGET" ] ; then
499    SHORT_TARGET="${TARGET##*/}"
500 else
501    eerror "Please adjust /etc/debootstrap/config or..."
502    eerror "... use the interactive version for configuration before running ${0}" ; eend 1
503    exit 1
504 fi
505 # }}}
506
507 # stages setup {{{
508 if [ -z "$STAGES" ] ; then
509    STAGES="/var/cache/grml-debootstrap/stages_${SHORT_TARGET}"
510    [ -d "$STAGES" ] || mkdir -p "$STAGES"
511 fi
512
513 if [ -r "$STAGES"/grml-debootstrap ] ; then
514    if grep -q done $STAGES/grml-debootstrap ; then
515       eerror "Error: grml-debootstrap has been executed already, won't continue therefore."
516       eerror "If you want to re-execute grml-debootstrap just manually remove ${STAGES}" ; eend 1
517    fi
518 fi
519 # }}}
520
521 # partition handling {{{
522 PARTITION=''
523 DIRECTORY=''
524
525 case $TARGET in
526   /dev/*)
527     PARTITION=1
528     ;;
529   *)
530     # assume we are installing into a directory, don't run mkfs and grub related stuff therefore
531     DIRECTORY=1
532     MNTPOINT="$TARGET"
533     MKFS=''
534     TUNE2FS=''
535     FSCK=''
536     GRUB=''
537     GROOT=''
538     ;;
539 esac
540 # }}}
541
542 # architecture setup {{{
543 if [ -n "$ARCH" ] ; then
544    ARCHCMD="--arch $ARCH"
545    ARCHINFO=" (${ARCH})"
546 else
547    ARCH="$(dpkg --print-architecture)"
548    ARCHCMD="--arch $ARCH"
549    ARCHINFO=" (${ARCH})"
550 fi
551 # }}}
552
553 # make sure we have the right syntax when using an iso image {{{
554 if [ -n "$ISO" ] ; then
555    case $ISO in
556       file*) # do nothing
557       ;;
558       *)
559       ISO=file:$1
560       ;;
561    esac
562 fi
563 ISODIR=${ISO##file:}
564 ISODIR=${ISODIR%%/}
565 # }}}
566
567 # helper functions {{{
568 # we want to exit smoothly and clean:
569 bailout(){
570   # make sure $TARGET is not mounted when exiting grml-debootstrap
571   if [ -n "$MNTPOINT" ] ; then
572      if grep -q $MNTPOINT /proc/mounts ; then
573         # make sure nothing is left inside chroot so we can unmount it
574         [ -x "$MNTPOINT"/etc/init.d/ssh   ] && "$MNTPOINT"/etc/init.d/ssh stop
575         [ -x "$MNTPOINT"/etc/init.d/mdadm ] && "$MNTPOINT"/etc/init.d/mdadm stop
576         # ugly, but make sure we really don't leav anything
577         [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount /sys  1>/dev/null 2>&1
578         [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount -a    1>/dev/null 2>&1
579         [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount /proc 1>/dev/null 2>&1
580         [ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount /proc 1>/dev/null 2>&1
581         [ -d "$MNTPOINT/$ISODIR" ]    && umount "$MNTPOINT/$ISODIR" 1>/dev/null 2>&1
582         einfo "Unmounting $MNTPOINT"   ; umount "$MNTPOINT" ; eend $?
583
584         if [ -n "$STAGES" ] ; then
585            echo -n "Removing stages directory ${STAGES}: "
586            rm -rf "$STAGES" && echo done
587         fi
588
589         # remove directory only if we used the default with process id inside the name
590         if echo "$MNTPOINT" | grep -q '/mnt/debootstrap\.' ; then
591            einfo "Removing directory ${MNTPOINT}" ; rmdir $MNTPOINT ; eend $?
592         fi
593      fi
594   fi
595
596   [ -n "$1" ] && EXIT="$1" || EXIT="1"
597   [ -n "$3" ] && einfo "Notice: just remove $STAGES/$3 to reexecute the stage"
598
599   exit "$EXIT"
600 }
601 trap bailout HUP INT QUIT TERM
602
603 # we want to execute all the functions only once, simple check for it:
604 stage() {
605   if [ -n "$2" ] ; then
606      echo "$2" > "${STAGES}/${1}"
607      return 0
608   elif grep -q done "${STAGES}/${1}" 2>/dev/null ; then
609      ewarn "Notice: stage $1 has been executed already, skipping execution therefore." ; eend 0
610      eindent
611        ewarn "To reexecute it clean up the according directory inside $STAGES" ; eend 0
612      eoutdent
613      return 1
614   fi
615 }
616 # }}}
617
618 # user should recheck his configuration {{{
619 # support full automatic installation:
620 checkforrun() {
621    dialog --timeout 10 --title "$PN" \
622           --yesno "Do you want to stop at this stage?
623
624 Notice: you are running ${PN} in non-interactive mode.
625 ${PN} will install Debian ${RELEASE} on ${TARGET}.
626 Last chance to quit. Timeout of 10 seconds running....
627
628 Do you want to stop now?" 0 0 2>/dev/null
629 }
630
631 # create filesystem {{{
632 mkfs() {
633   if [ -n "$MKFS" ] ; then
634      einfo "Running $MKFS on $TARGET"
635      $MKFS $TARGET
636      TARGET_UUID="$(vol_id -u $TARGET 2>/dev/null || echo '')"
637      eend $?
638   fi
639 }
640 # }}}
641
642 # modify filesystem settings {{{
643 tunefs() {
644   if [ -n "$TUNE2FS" ] ; then
645      einfo "Disabling automatic filesystem check on $TARGET via tune2fs"
646      $TUNE2FS $TARGET
647      eend $?
648   fi
649 }
650 # }}}
651
652 # mount the new partition or if it's a directory do nothing at all {{{
653 mount_target() {
654   if [ -n "$DIRECTORY" ] ; then
655      einfo "Running grml-debootstrap on a directory, nothing to mount."
656   else
657      if grep -q $TARGET /proc/mounts ; then
658         eerror "$TARGET already mounted, exiting."
659      else
660        [ -d "$MNTPOINT" ] || mkdir -p "$MNTPOINT"
661        einfo "Mounting $TARGET to $MNTPOINT"
662        mount -o rw,suid,dev $TARGET $MNTPOINT
663        eend $?
664      fi
665   fi
666   if [ -n "$ISODIR" ] ; then
667      einfo "Mounting Debian image loopback to $MNTPOINT/$ISODIR."
668      mkdir -p "$MNTPOINT/$ISODIR"
669      mount --bind "$ISODIR" "$MNTPOINT/$ISODIR"
670      eend $?
671   fi
672 }
673 # }}}
674
675 # install main chroot {{{
676 debootstrap_system() {
677   if ! grep -q $MNTPOINT /proc/mounts ; then
678      mount_target
679   fi
680   if grep -q $MNTPOINT /proc/mounts || [ -n "$DIRECTORY" ] ; then
681      einfo "Running $DEBOOTSTRAP $DEBOOTSTRAP_OPT for release ${RELEASE}${ARCHINFO} using ${MIRROR}${ISO}"
682      [ -n "$MIRROR" ] && $DEBOOTSTRAP $ARCHCMD $DEBOOTSTRAP_OPT $RELEASE $MNTPOINT $MIRROR || \
683      $DEBOOTSTRAP $ARCHCMD $DEBOOTSTRAP_OPT $RELEASE $MNTPOINT $ISO
684      eend $?
685   else
686      eerror "Error: $MNTPOINT not mounted, can not continue."
687      eend 1
688   fi
689 }
690 # }}}
691
692 # prepare chroot via chroot-script {{{
693 preparechroot() {
694   einfo "Preparing chroot system"
695
696   # provide variables to chroot system
697   CHROOT_VARIABLES="/var/cache/grml-debootstrap/variables_${SHORT_TARGET}"
698   touch $CHROOT_VARIABLES
699   chmod 600 $CHROOT_VARIABLES # make sure nobody except root can read it
700   echo "# Configuration of ${PN}"                              > $CHROOT_VARIABLES
701   [ -n "$ARCH" ]         && echo "ARCH=$ARCH"                 >> $CHROOT_VARIABLES
702   [ -n "$GROOT" ]        && echo "GROOT=$GROOT"               >> $CHROOT_VARIABLES
703   [ -n "$GRUB" ]         && echo "GRUB=$GRUB"                 >> $CHROOT_VARIABLES
704   [ -n "$HOSTNAME" ]     && echo "HOSTNAME=$HOSTNAME"         >> $CHROOT_VARIABLES
705   [ -n "$ISODIR" ]       && echo "ISODIR=$ISO"                >> $CHROOT_VARIABLES
706   [ -n "$ISO" ]          && echo "ISO=$ISO"                   >> $CHROOT_VARIABLES
707   [ -n "$MIRROR" ]       && echo "CHROOTMIRROR=$MIRROR"       >> $CHROOT_VARIABLES
708   [ -n "$MIRROR" ]       && echo "MIRROR=$MIRROR"             >> $CHROOT_VARIABLES
709   [ -n "$KEEP_SRC_LIST" ] && echo "KEEP_SRC_LIST=$KEEP_SRC_LIST" >> $CHROOT_VARIABLES
710   [ -n "$ROOTPASSWORD" ] && echo "ROOTPASSWORD=$ROOTPASSWORD" >> $CHROOT_VARIABLES
711   [ -n "$TARGET" ]       && echo "TARGET=$TARGET"             >> $CHROOT_VARIABLES
712   [ -n "$TARGET_UUID" ]  && echo "TARGET_UUID=$TARGET_UUID"   >> $CHROOT_VARIABLES
713
714   cp $CONFFILES/chroot-script $MNTPOINT/bin/chroot-script
715   chmod 755 $MNTPOINT/bin/chroot-script
716   mkdir $MNTPOINT/etc/debootstrap/
717
718   # make sure we have our files for later use via chroot-script
719   cp /etc/debootstrap/config    $MNTPOINT/etc/debootstrap/
720   # make sure we adjust the configuration variables accordingly:
721   sed -i "s#RELEASE=.*#RELEASE=\"$RELEASE\"#" $MNTPOINT/etc/debootstrap/config
722   sed -i "s#TARGET=.*#TARGET=\"$TARGET\"#"    $MNTPOINT/etc/debootstrap/config
723   sed -i "s#GRUB=.*#GRUB=\"$GRUB\"#"          $MNTPOINT/etc/debootstrap/config
724   sed -i "s#GROOT=.*#GROOT=\"$GROOT\"#"       $MNTPOINT/etc/debootstrap/config
725
726   cp ${_opt_packages:-/etc/debootstrap/packages} \
727     $MNTPOINT/etc/debootstrap/packages
728   _opt_debconf=${_opt_debconf:-/etc/debootstrap/debconf-selections}
729   [ -f $_opt_debconf -a "$DEBCONF" = 'yes' ] && \
730     cp $_opt_debconf $MNTPOINT/etc/debootstrap/debconf-selections
731
732   # notice: do NOT use $CHROOT_VARIABLES inside chroot but statically file instead!
733   cp $CHROOT_VARIABLES          $MNTPOINT/etc/debootstrap/variables
734
735   cp -a -L /etc/debootstrap/extrapackages/ $MNTPOINT/etc/debootstrap/
736
737   # make sure we can access network [relevant for cdebootstrap]
738   [ -f "$MNTPOINT/etc/resolv.conf" ] || cp /etc/resolv.conf $MNTPOINT/etc/resolv.conf
739
740   # provide system's /etc/hosts to the target:
741   if ! [ -f "$MNTPOINT/etc/hosts" ] ; then
742      cp /etc/hosts $MNTPOINT/etc/hosts
743      sed -i "s#127.0.0.1 .*#127.0.0.1       localhost  $HOSTNAME#" /etc/hosts
744   fi
745
746   # setup default locales
747   [ -n "$LOCALES" ] && cp /etc/debootstrap/locale.gen  $MNTPOINT/etc/locale.gen
748
749   # MAKEDEV is just a forking bomb crap, let's do it on our own instead :)
750   ( cd $MNTPOINT/dev && tar zxf /etc/debootstrap/devices.tar.gz )
751
752   # copy any existing files to chroot
753   [ -d /etc/debootstrap/bin   ] && cp -a -L /etc/debootstrap/bin/*   $MNTPOINT/bin/
754   [ -d /etc/debootstrap/boot  ] && cp -a -L /etc/debootstrap/boot/*  $MNTPOINT/boot/
755   [ -d /etc/debootstrap/etc   ] && cp -a -L /etc/debootstrap/etc/*   $MNTPOINT/etc/
756   [ -d /etc/debootstrap/sbin  ] && cp -a -L /etc/debootstrap/sbin/*  $MNTPOINT/sbin/
757   [ -d /etc/debootstrap/share ] && cp -a -L /etc/debootstrap/share/* $MNTPOINT/share/
758   [ -d /etc/debootstrap/usr   ] && cp -a -L /etc/debootstrap/usr/*   $MNTPOINT/usr/
759   [ -d /etc/debootstrap/var   ] && cp -a -L /etc/debootstrap/var/*   $MNTPOINT/var/
760
761   # copy local network setup to chroot
762   if [ -r /etc/network/interfaces -a ! -r "${MNTPOINT}"/etc/network/interfaces ] ; then
763      [ -d $MNTPOINT/etc/network ] || mkdir $MNTPOINT/etc/network
764      cp /etc/network/interfaces $MNTPOINT/etc/network/interfaces
765   fi
766
767   eend 0
768 }
769 # }}}
770
771 # execute chroot-script {{{
772 chrootscript() {
773   if ! [ -r "$MNTPOINT/bin/chroot-script" ] ; then
774      mount_target
775   fi
776   if [ -x "$MNTPOINT/bin/chroot-script" ] ; then
777      einfo "Executing chroot-script now"
778      chroot "$MNTPOINT" /bin/chroot-script
779      eend $?
780   else
781      eerror "Fatal: $MNTPOINT/bin/chroot-script could not be found."
782      eend 1
783   fi
784 }
785 # }}}
786
787 # install booloader grub {{{
788 grub_install() {
789   if [ -z "$GRUB" -o -z "$GROOT" ] ; then
790      echo "Notice: \$GRUB or \$GROOT not defined, will not install grub therefor."
791   elif [ -n "$SELECTED_PARTITIONS" ] ; then # using sw-raid
792      for device in $SELECTED_PARTITIONS ; do
793         # TMPDEVICE=$(echo ${SELECTED_PARTITIONS} | awk '{print $1}')
794         # GRUB="$(grubdevice ${TMPDEVICE})"
795         # GRUB="$(grubdevice ${TMPDEVICE%%[0-9]})"
796         # GRUB=$(grubdevice $device)
797         GRUB="$(grubdevice ${device%%[0-9]})"
798         einfo "Installing grub on ${GRUB}:"
799         [ -x /usr/sbin/grub-install ] && GRUBINSTALL="/usr/sbin/grub-install --no-floppy" || GRUBINSTALL="/sbin/grub-install --no-floppy"
800         $GRUBINSTALL --root-directory="$MNTPOINT" "(${GRUB})"
801         eend $?
802      done
803   else
804      einfo "Installing grub on ${GRUB}:"
805      [ -x /usr/sbin/grub-install ] && GRUBINSTALL="/usr/sbin/grub-install --no-floppy" || GRUBINSTALL="/sbin/grub-install --no-floppy"
806      $GRUBINSTALL --root-directory="$MNTPOINT" "(${GRUB})"
807      eend $?
808   fi
809 }
810 # }}}
811
812 # unmount $MNTPOINRT {{{
813 umount_chroot() {
814   if [ -n "$ISODIR" ] ; then
815      if grep -q "$ISODIR" /proc/mounts ; then
816         einfo "Unmount $MNTPOINT/$ISODIR"
817         umount "$MNTPOINT/$ISODIR"
818         eend $?
819      fi
820   fi
821   if grep -q "$MNTPOINT" /proc/mounts ; then
822      if [ -n "$PARTITION" ] ; then
823         einfo "Unmount $MNTPOINT"
824         umount $MNTPOINT
825         eend $?
826      fi
827   fi
828 }
829 # }}}
830
831 # execute filesystem check {{{
832 fscktool() {
833   if [ "$FSCK" = 'yes' ] ; then
834      [ -n "$FSCKTOOL" ] || FSCKTOOL="fsck.${MKFS#mkfs.}"
835      einfo "Checking filesystem on $TARGET using $FSCKTOOL"
836      $FSCKTOOL $TARGET
837      eend $?
838   fi
839 }
840 # }}}
841
842 # now execute all the functions {{{
843 for i in mkfs tunefs mount_target debootstrap_system preparechroot \
844          chrootscript grub_install umount_chroot fscktool ; do
845     if stage "${i}" ; then
846        $i && ( stage "${i}" done && rm -f "${STAGES}/${i}" ) || bailout 2 "i"
847     fi
848 done
849 # }}}
850
851 # finalize {{{
852 einfo "Removing ${CHROOT_VARIABLES}" ; rm "$CHROOT_VARIABLES" ; eend $?
853 einfo "Removing ${STAGES}" ; rmdir "$STAGES" ; eend $?
854
855 # Remove temporary mountpoint again
856 if echo "$MNTPOINT" | grep -q '/mnt/debootstrap\.' ; then
857    einfo "Removing directory ${MNTPOINT}" ; rmdir "$MNTPOINT" ; eend $?
858 fi
859 # }}}
860
861 # end dialog of autoinstallation {{{
862 if [ -n "$AUTOINSTALL" ] ; then
863    dialog --title "$PN" --msgbox \
864           "Finished execution of ${PN}. Enjoy your Debian system." 0 0
865 else
866    einfo "Finished execution of ${PN}. Enjoy your Debian system." ; eend 0
867 fi
868 # }}}
869
870 ## END OF FILE #################################################################
871 # vim: ai tw=100 expandtab foldmethod=marker shiftwidth=3