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