3 # Purpose: build process script for generating a (grml based) Linux Live-ISO
4 # Authors: grml-team (grml.org),
5 # (c) Michael Prokop <mika@grml.org>,
6 # (c) Thorsten Glaser <tg@mirbsd.org>
7 # Bug-Reports: see http://grml.org/bugs/
8 # License: This file is licensed under the GPL v2 or any later version.
9 ################################################################################
11 # some misc and global stuff {{{
15 # avoid leaking into chroots
18 # define function getfilesize before "set -e"
19 if stat --help >/dev/null 2>&1; then
20 getfilesize='stat -c %s' # GNU stat
22 getfilesize='stat -f %z' # BSD stat
26 # disable for now since it seems to cause some problems
29 # The line following this line is patched by debian/rules.
30 GRML_LIVE_VERSION='***UNRELEASED***'
35 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
38 # usage information {{{
42 $PN - build process script for generating a (grml based) Linux Live-ISO
44 Usage: $PN [options, see as follows]
46 -a <architecture> architecture; available values: i386 and amd64
47 -A clean build directories before and after running
48 -b build the ISO without updating the chroot via FAI
49 -B build the ISO without touching the chroot (skips cleanup)
50 -c <classe[s]> classes to be used for building the ISO via FAI
51 -C <configfile> configuration file for grml-live
52 -d <date> use specified date instead of build time as date of release
53 -D <configdir> use specified configuration directory instead of /etc/grml/fai
54 -e <iso_name> extract ISO and squashfs contents from iso_name
55 -F force execution without prompting
56 -g <grml_name> set the grml flavour name
57 -h display short usage information and exit
58 -i <iso_name> name of ISO
59 -I <src_directory> directory which provides files that should become
60 part of the chroot/ISO
61 -n skip generation of ISO
62 -N bootstrap (build chroot) only, do not create files for ISO
63 -o <output_directory> main output directory of the build process
65 -Q skip netboot package build
66 -r <release_name> release name
67 -s <suite> Debian suite/release, like: stable, testing, unstable
68 -t <template_directory> place of the templates
69 -u update existing chroot instead of rebuilding it from scratch
70 -U <username> arrange output to be owned by specified username
71 -v <version_number> specify version number of the release
72 -V increase verbosity in the build process
73 -z use ZLIB instead of LZMA/XZ compression
78 $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
79 $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
80 $PN -c GRMLBASE,GRML_FULL,AMD64 -s stable -V -r 'grml-ftw'
82 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
83 http://grml.org/grml-live/
85 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
87 [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
90 # make sure it's possible to get usage information without being
91 # root or actually executing the script
92 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
98 # some runtime checks {{{
99 # we need root permissions for the build-process:
100 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
101 echo "Error: please run this script with uid 0 (root)." >&2
105 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
106 echo "/usr/sbin/fai already running or was aborted before.">&2
107 echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
112 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
113 echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
114 echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
119 # lsb-functions and configuration stuff {{{
120 # make sure they are not set by default
131 # don't use colors/escape sequences
132 if [ -r /lib/lsb/init-functions ] ; then
133 . /lib/lsb/init-functions
134 ! log_use_fancy_output && NOCOLORS=true
137 if [ -r /etc/grml/lsb-functions ] ; then
138 . /etc/grml/lsb-functions
140 einfo() { echo " [*] $*" ;}
141 eerror() { echo " [!] $*">&2 ;}
142 ewarn() { echo " [x] $*" ;}
144 eindent() { return 0 ;}
145 eoutdent() { return 0 ;}
148 # source main configuration file:
149 LIVE_CONF=/etc/grml/grml-live.conf
150 if ! [ -r "$LIVE_CONF" ] ; then
151 ewarn "Configuration file $LIVE_CONF can not be read, ignoring"
153 einfo "Sourcing configuration file $LIVE_CONF"
159 # umount all directories {{{
161 # make sure we don't leave any mounts - FAI doesn't remove them always
162 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
163 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
164 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
165 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
166 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
167 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
169 if [ -n "$EXTRACT_ISO_NAME" ] ; then
170 umount "$EXTRACT_ISO_NAME" 2>/dev/null || /bin/true
173 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
174 if [ -x /usr/lib/fai/mkramdisk ] ; then
175 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
178 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
179 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
185 rm -f /var/run/fai/fai_softupdate_is_running \
186 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
187 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
188 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
190 [ -n "$1" ] && EXIT="$1" || EXIT="1"
191 [ -n "$2" ] && eerror "$2">&2
192 if [ -n "$CLEAN_ARTIFACTS" ]; then
195 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
196 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
200 # get rid of automatically generated conffiles
201 rm -f ${GRML_FAI_CONFIG}/nfsroot.conf
202 rm -f ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf
204 if [ -n "$CHOWN_USER" ]; then
205 log "Setting ownership"
206 einfo "Setting ownership"
207 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
208 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
209 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
210 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
211 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
212 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
215 log "------------------------------------------------------------------------------"
218 trap bailout 1 2 3 3 6 9 14 15
222 # some important functions {{{
225 # usage: log "string to log"
226 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
228 # cut string at character number int = $1
229 # usage: cut_string 5 "1234567890" will output "12345"
231 [ -n "$2" ] || return 1
232 echo "$2" | head -c "$1"; echo -ne "\n"
235 # prepend int = $1 spaces before string = $2
236 # usage: extend_string_begin 5 "123" will output " 123"
237 extend_string_begin() {
238 [ -n "$2" ] || return 1
239 local COUNT="$(echo $2 | wc -c)"
240 local FILL="$(expr $COUNT - $1)"
241 while [ "$FILL" -gt 1 ] ; do
243 local FILL=$(expr $FILL - 1)
245 while [ "$FILL" -lt 1 ] ; do
247 local FILL=$(expr $FILL + 1)
249 echo "$2" | head -c "$1"; echo -ne "\n"
252 # append int = $1 spaces to string = $2
253 # usage: extend_string_begin 5 "123" will output "123 "
254 extend_string_end() {
255 [ -n "$2" ] || return 1
256 echo -n "$2" | head -c "$1"
257 local COUNT="$(echo $2 | wc -c)"
258 local FILL="$(expr $COUNT - $1)"
259 while [ "$FILL" -gt 1 ] ; do
261 local FILL=$(expr $FILL - 1)
263 while [ "$FILL" -lt 1 ] ; do
265 local FILL=$(expr $FILL + 1)
270 # Copy addonfile $1 from either
271 # * the chroot (via $2, the system path),
272 # * or from TEMPLATE_DIRECTORY/compat (if exists),
273 # * or from the host system (again, using $2),
274 # or warn about the missing file.
277 # * We assume that the chroot always has a "good" version of
278 # the file. Also it makes sources handling easier.
279 # * On unstable, we Recommend the Debian packages containing
280 # these files. The user can override them by putting his
281 # "better" version into the chroot.
282 # * On stable, the Debian packages are probably not available,
283 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
284 # our grml-live-compat package installs current file versions.
286 DEST="${BUILD_OUTPUT}/boot/$3"
287 if [ ! -d "${DEST}/" ]; then
290 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
291 log "Copying $1 from chroot"
292 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
295 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
296 log "Copying $1 from grml-live-compat"
297 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
300 if [ -e "$2/$1" ]; then
301 log "Copying $1 from system"
302 cp "$2/$1" "${DEST}/"
306 msg="Missing addon file: \"$1\""
307 ewarn "$msg" ; eend 1
308 log "copy_addon_file: $msg"
312 # command line parsing {{{
313 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
316 A) CLEAN_ARTIFACTS=1 ;;
319 c) CLASSES="$OPTARG" ;;
320 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
322 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
323 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
324 g) GRML_NAME="$OPTARG" ;;
325 h) usage ; bailout 0 ;;
326 i) ISO_NAME="$OPTARG" ;;
327 I) CHROOT_INSTALL="$OPTARG" ;;
329 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
330 o) OUTPUT="$(readlink -f $OPTARG)" ;;
331 q) SKIP_MKSQUASHFS=1 ;;
333 r) RELEASENAME="$OPTARG" ;;
334 s) SUITE="$OPTARG" ;;
335 t) TEMPLATE_DIRECTORY="$OPTARG";;
336 v) VERSION="$OPTARG" ;;
339 U) CHOWN_USER="$OPTARG" ;;
341 z) SQUASHFS_ZLIB=1 ;;
342 ?) echo "invalid option -$OPTARG" >&2; usage; bailout 1 ;;
345 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
347 if [ -n "$1" ] ; then
348 echo "Error: unknown argument '$1' in options. Exiting to avoid possible data loss." >&2
353 # read local (non-packaged) configuration {{{
354 if [ -z "$LOCAL_CONFIG" ]; then
355 if [ -r "/etc/grml/grml-live.local" ]; then
356 LOCAL_CONFIG="/etc/grml/grml-live.local"
359 if [ -n "$LOCAL_CONFIG" ]; then
360 if [ -r "$LOCAL_CONFIG" ]; then
363 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
366 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
371 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
372 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
373 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
378 # assume sane defaults (if not set already) {{{
379 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
380 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
381 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
382 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
383 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
384 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
385 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
386 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
387 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
388 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
389 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
390 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='isohybrid'
391 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
392 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
393 [ -n "$SUITE" ] || SUITE='testing'
394 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
395 [ -n "$USERNAME" ] || USERNAME='grml'
396 [ -n "$VERSION" ] || VERSION='0.0.1'
398 # output specific stuff, depends on $OUTPUT (iff not set):
399 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
400 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
401 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
402 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
403 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
404 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
405 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
408 # some misc checks before executing FAI {{{
409 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
410 specify it on the command line using the -c option."
411 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
412 specify it on the command line using the -o option."
414 # trim characters that are known to cause problems inside $GRML_NAME;
415 # for example isolinux does not like '-' inside the directory name
416 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
418 # export variables to have them available in fai scripts:
419 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
420 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
423 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
424 # this was default behaviour until grml-live 0.9.34:
425 if [ -n "$ZERO_LOGFILE" ] ; then
426 PRESERVE_LOGFILE='' # make sure it's cleaned then
427 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
428 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
433 # ask user whether the setup is ok {{{
434 if [ -z "$FORCE" ] ; then
436 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
438 echo " FAI classes: $CLASSES"
439 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
440 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
441 echo " main directory: $OUTPUT"
442 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
443 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
444 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
445 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
446 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
447 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
448 [ -n "$DATE" ] && echo " Build date: $DATE"
449 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
450 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
451 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
452 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
453 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
454 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
455 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
456 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
457 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
458 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
459 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
460 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
461 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
462 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
463 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
464 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
465 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
466 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
467 if [ -n "$BOOTSTRAP_ONLY" ] ; then
468 echo " Bootstrapping only and not building (files for) ISO."
470 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
471 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
472 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
473 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
474 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
477 echo -n "Is this ok for you? [y/N] "
479 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
481 echo "Exiting as requested."
488 # clean up before start {{{
489 if [ -n "${CLEAN_ARTIFACTS}" ]; then
490 echo "Wiping old artifacts"
491 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
492 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
493 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
494 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
495 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
499 # create log file {{{
500 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
501 mkdir -p $(dirname "${LOGFILE}")
503 chown root:adm $LOGFILE
507 # clean/zero/remove logfiles {{{
509 if [ -n "$PRESERVE_LOGFILE" ] ; then
510 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
512 # make sure it is empty (as it is e.g. appended to grml-live-db)
516 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
517 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
518 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
519 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
520 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
521 rm -f /var/log/fai/"$HOSTNAME"/last \
522 /var/log/fai/"$HOSTNAME"/last-dirinstall \
523 /var/log/fai/"$HOSTNAME"/last-softupdate
528 # source config and startup {{{
529 if [ -n "$CONFIG" ] ; then
530 if ! [ -f "$CONFIG" ] ; then
531 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
532 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
535 log "Sourcing $CONFIG"
540 start_seconds=$(cut -d . -f 1 /proc/uptime)
541 log "------------------------------------------------------------------------------"
542 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
543 log "Using local config file: $LOCAL_CONFIG"
544 log "Executed grml-live command line:"
547 einfo "Logging actions to logfile $LOGFILE"
550 # dump config variables into file, for script access {{{
553 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
557 # unpack iso/squashfs {{{
559 if [ -n "$EXTRACT_ISO_NAME" ]; then
560 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
561 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
562 local mountpoint=$(mktemp -d)
564 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
565 if [ "$rc" != 0 ]; then
568 eerror "mount failed"
573 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
574 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
575 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
576 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
577 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
578 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
580 log "Error: Could not find any *.squashfs files on the ISO"
581 eerror "Error: Could not find any *.squashfs files on the ISO"
588 if [ "$rc" != 0 ]; then
589 log "unsquashfs failed"
590 eerror "unsquashfs failed"
599 # on-the-fly configuration {{{
601 # does this suck? YES!
602 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
604 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
605 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
607 export SUITE # make sure it's available in FAI scripts
609 # validate whether the specified architecture class matches the
610 # architecture (option), otherwise installation of kernel will fail
611 if echo $CLASSES | grep -qw I386 ; then
612 if ! [[ "$ARCH" == "i386" ]] ; then
613 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
614 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
615 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
619 elif echo $CLASSES | grep -qi amd64 ; then
620 if ! [[ "$ARCH" == "amd64" ]] ; then
621 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
622 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
623 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
629 # generate nfsroot configuration for FAI on the fly
630 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
631 FAI_DEBOOTSTRAP="$SUITE http://http.debian.net/debian"
634 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
635 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --arch $ARCH"
638 # create backup of old (not yet automatically generated) config file
639 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
640 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
641 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
642 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
647 echo "# This is an automatically generated file by grml-live.
648 # Do NOT edit this file, your changes will be lost.
649 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
650 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
651 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
652 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
653 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
656 # CHROOT_OUTPUT - execute FAI {{{
657 if [ -n "$BUILD_DIRTY" ]; then
658 log "Skipping stage 'fai' as requested via option -B"
659 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
661 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
663 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
664 FAI_ACTION=softupdate
666 FAI_ACTION=dirinstall
669 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
670 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
671 log "Error: does not look like you have a working chroot. Updating/building not possible."
672 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
678 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
679 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
680 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
682 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
684 if [ -n "${MIRROR_DIRECTORY}" ] ; then
685 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
686 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
689 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
690 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
692 log "Executed FAI command line:"
693 log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY GRML_LIVE_CONFIG=$CONFIGDUMP fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
694 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
695 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
696 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
697 RC="$PIPESTATUS" # notice: bash-only
699 if [ "$RC" != 0 ] ; then
700 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
701 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
705 # provide inform fai about the ISO we build, needs to be provided
706 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
707 # there is not BASEFILE (as it checks for presence of /etc) :(
708 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
709 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
710 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
712 FORCE_ISO_REBUILD=true
714 # move fai logs into grml_logs directory
715 mkdir -p "$LOG_OUTPUT"/fai/
716 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
717 rm -rf "$CHROOT_OUTPUT"/var/log/fai
719 # store copy of autogenerated configuration file
720 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
722 # copy fai package list
723 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
725 chown root:adm "$LOG_OUTPUT"/fai/*
726 chmod 664 "$LOG_OUTPUT"/fai/*
730 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
732 CHECKLOG="$LOG_OUTPUT"/fai/
733 if [ -r "$CHECKLOG/software.log" ] ; then
734 # 1 errors during executing of commands
735 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
736 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
737 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
738 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
739 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
742 if [ -r "$CHECKLOG/shell.log" ] ; then
743 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
746 if [ -n "$ERROR" ] ; then
747 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
748 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
749 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
753 log "Finished execution of stage 'fai dirinstall' [$(date)]"
754 einfo "Finished execution of stage 'fai dirinstall'"
760 # package validator {{{
761 CHECKLOG=/var/log/fai/$HOSTNAME/last
762 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
763 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
765 package_count="unknown"
769 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
771 # check for missing packages
772 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
773 einfo "No missing packages found, generating empty junit report."
775 cat > "${REPORT_MISSING_PACKAGES}" << EOF
776 <?xml version="1.0" encoding="UTF-8"?>
777 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
778 <testcase name="test_missing_packages" time="0" assertions="0">
788 einfo "Missing packages found, generating junit report."
790 if [ -r "$CHECKLOG/package_errors.log" ] ; then
791 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
793 package_errors="unknown"
797 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
799 cat > "${REPORT_MISSING_PACKAGES}" << EOF
800 <?xml version="1.0" encoding="UTF-8"?>
801 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
804 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
805 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
806 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
807 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
808 <failure type="${failure_reason}" message="Package ${package} is missing">
809 Package $package is missing in chroot (${failure_reason})
815 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
824 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
825 eerror "The following packages were requested for installation but could not be processed:"
826 cat "$CHECKLOG/package_errors.log"
827 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
831 ewarn "The following packages were requested for installation but could not be processed:"
832 cat "$CHECKLOG/package_errors.log"
838 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
839 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
840 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
843 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
844 if [ -n "$BOOTSTRAP_ONLY" ] ; then
845 log "Skipping stage 'boot' as building with bootstrap only."
846 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
848 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
849 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
850 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
853 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
854 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
856 # if we don't have an initrd we a) can't boot and b) there was an error
857 # during build, so check for the file:
858 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
859 if [ -n "$INITRD" ] ; then
860 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
861 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
863 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
864 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
868 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
869 if [ -n "$KERNEL_IMAGE" ] ; then
870 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
872 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
873 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
878 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
879 einfo "Moving EFI boot files into ISO path."
880 log "Moving EFI boot files into ISO path."
882 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
883 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
884 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
888 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
889 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
890 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
891 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
895 # copy _required_ isolinux files
896 if [ -d "${CHROOT_OUTPUT}/usr/lib/ISOLINUX" ] ; then
897 copy_addon_file isolinux.bin /usr/lib/ISOLINUX isolinux
898 copy_addon_file ifcpu64.c32 /usr/lib/syslinux/modules/bios/ isolinux
899 copy_addon_file ldlinux.c32 /usr/lib/syslinux/modules/bios/ isolinux
900 copy_addon_file libcom32.c32 /usr/lib/syslinux/modules/bios/ isolinux
901 copy_addon_file libutil.c32 /usr/lib/syslinux/modules/bios/ isolinux
902 copy_addon_file vesamenu.c32 /usr/lib/syslinux/modules/bios/ isolinux
903 else # syslinux versions <= 3:4.05+dfsg-6+deb8u1
904 copy_addon_file isolinux.bin /usr/lib/syslinux isolinux
905 copy_addon_file ifcpu64.c32 /usr/lib/syslinux isolinux
906 copy_addon_file vesamenu.c32 /usr/lib/syslinux isolinux
909 # *always* copy files to output directory so the variables
910 # get adjusted according to the build.
911 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
913 if [ -n "$NO_ADDONS" ] ; then
914 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
915 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
917 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
918 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
919 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
921 # copy addons from system packages or grml-live-compat
922 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
923 copy_addon_file pci.ids /usr/share/misc addons
924 copy_addon_file memtest86+.bin /boot addons
926 # since syslinux(-common) v3:6.03~pre1+dfsg-4 the files are in a
927 # different directory :(
928 if [ -d "${CHROOT_OUTPUT}/usr/lib/syslinux/modules/bios/" ] ; then
929 syslinux_modules_dir=/usr/lib/syslinux/modules/bios/
931 syslinux_modules_dir=/usr/lib/syslinux
933 for file in memdisk chain.c32 hdt.c32 mboot.c32 menu.c32; do
934 copy_addon_file "${file}" "${syslinux_modules_dir}" addons
937 # make memtest filename FAT16/8.3 compatible
938 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
939 "${BUILD_OUTPUT}/boot/addons/memtest"
941 # copy only files so we can handle bsd4grml on its own
942 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
943 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
946 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
947 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
948 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
950 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
951 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
953 log "Missing addon file: bsd4grml"
954 ewarn "Missing addon file: bsd4grml" ; eend 0
958 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
961 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
962 mkdir -p "${BUILD_OUTPUT}/boot/grub"
964 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
966 # generate loopback.cfg config file without depending on grub's regexp module
967 # which isn't available in Debian/squeeze
968 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
969 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
970 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
971 [ -r "$config" ] || continue
972 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
974 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
975 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
977 # copy grub files from target
978 mkdir -p "${BUILD_OUTPUT}"/boot/grub/i386-pc/
979 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/i386-pc/
980 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/i386-pc/
981 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/i386-pc/
982 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
983 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
984 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
986 # copy modules for UEFI grub
987 mkdir -p "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
988 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/x86_64-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
990 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
991 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
992 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
996 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
997 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
999 # adjust boot splash information:
1000 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
1001 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
1002 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
1004 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
1005 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
1006 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
1009 # make sure the squashfs filename is set accordingly:
1010 SQUASHFS_NAME="$GRML_NAME.squashfs"
1012 if [ -n "$NO_BOOTID" ] ; then
1013 log 'Skipping bootid feature as requested via $NO_BOOTID.'
1014 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
1016 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
1017 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
1018 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
1019 log "Generating /conf/bootid.txt with entry ${BOOTID}."
1020 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
1024 # adjust all variables in the templates with the according distribution information
1025 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
1026 "${BUILD_OUTPUT}"/boot/grub/* ; do
1027 if [ -r "${file}" ] && [ -f "${file}" ] ; then
1028 sed -i "s/%ARCH%/$ARCH/g" "${file}"
1029 sed -i "s/%DATE%/$DATE/g" "${file}"
1030 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
1031 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
1032 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
1033 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
1034 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
1035 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
1036 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1037 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1039 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1041 if [ -n "$NO_BOOTID" ] ; then
1042 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1044 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1049 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1050 RELEASE_INFO SHORT_NAME VERSION ; do
1051 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1052 value="$(eval echo '$'"$param")"
1053 mv ${file} ${file/\%${param}\%/$value}
1057 # adjust bootsplash accordingly but make sure the string has the according lenght
1058 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1059 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1060 for file in f4 f5 ; do
1061 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1062 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1063 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1067 # generate addon list
1068 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1069 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1070 include_name=$(basename "$name")
1071 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1074 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1075 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1076 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1077 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1078 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1079 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1081 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1082 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1085 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1086 if [ ! -n "$NO_ADDONS" ] ; then
1087 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1089 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1090 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1091 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1092 else # assume we are building a custom distribution:
1093 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1094 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1095 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1096 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1098 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1102 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1103 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1104 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1108 # use old style console based isolinux method only if requested:
1109 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1110 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1111 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1112 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1113 einfo "include for console.cfg already found, nothing to do."
1116 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1117 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1118 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1122 log 'Using graphical boot menu.'
1123 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1124 log "include for vesamenu.cfg already found, nothing to do."
1126 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1127 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1131 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1132 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1135 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1136 if ! [ -r "$DPKG_LIST" ] ; then
1137 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1139 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1140 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1144 # autostart for Windows:
1145 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1146 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1149 FORCE_ISO_REBUILD=true
1150 einfo "Finished execution of stage 'boot'" ; eend 0
1154 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1155 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1159 # support installation of local files into the chroot/ISO
1160 if [ -n "$CHROOT_INSTALL" ] ; then
1161 if ! [ -d "$CHROOT_INSTALL" ] ; then
1162 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1163 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1165 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1166 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1167 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1169 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1170 FORCE_ISO_REBUILD=true
1174 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1175 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1176 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1177 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1178 log "Skipping stage 'squashfs' as requested via option -q or -N"
1179 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1181 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1182 # make sure we don't leave (even an empty) base.tgz:
1183 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1185 # if unconfigured default to squashfs-tools' mksquashfs binary
1186 if [ -z "$SQUASHFS_BINARY" ] ; then
1187 SQUASHFS_BINARY='mksquashfs'
1190 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1191 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1192 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1194 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1195 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1199 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1200 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1201 # use blocksize 256k as this gives best result with regards to time + compression
1202 SQUASHFS_OPTIONS="-b 256k"
1204 # set lzma/xz compression by default, unless -z option has been specified on command line
1205 if [ -z "$SQUASHFS_ZLIB" ] ; then
1206 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1208 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1212 # support exclusion of files via exclude-file:
1213 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1214 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1217 # get rid of unnecessary files when building grml-small for final release:
1218 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1219 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1223 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1225 # informational stuff
1226 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1227 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1228 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1230 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1232 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1233 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1234 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1235 log "Finished execution of stage 'squashfs' [$(date)]"
1236 einfo "Finished execution of stage 'squashfs'" ; eend 0
1238 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1239 log "$(cat $SQUASHFS_STDERR)"
1240 eerror "Error: there was a critical error executing stage 'squashfs':"
1241 cat "${SQUASHFS_STDERR}"
1246 FORCE_ISO_REBUILD=true
1249 # create md5sum file:
1250 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1251 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1252 find ../.. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1256 # ISO_OUTPUT - mkisofs {{{
1257 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1258 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1260 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1261 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1262 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1263 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1266 # Work around http://bts.grml.org/grml/issue945
1267 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1268 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1269 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1270 HYBRID_METHOD='grub2'
1274 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1275 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1276 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1277 elif [ -n "$SKIP_MKISOFS" ] ; then
1278 log "Skipping stage 'iso build' as requested via option -n or -N"
1279 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1281 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1283 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1284 log "Forcing rebuild of ISO because files on ISO have been modified."
1285 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1288 # support xorriso as well mkisofs and genisoimage
1289 if which xorriso >/dev/null 2>&1 ; then
1290 MKISOFS='xorriso -as mkisofs'
1291 elif which mkisofs >/dev/null 2>&1; then
1293 elif which genisoimage >/dev/null 2>&1; then
1294 MKISOFS='genisoimage'
1296 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1297 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1301 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1302 case "${ARCH}-${MKISOFS}" in
1303 # using -eltorito-alt-boot is limited to xorriso for now
1307 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1308 log "Disabling (U)EFI boot support because xorriso version is too old."
1309 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1311 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1312 einfo "Enabling (U)EFI boot."
1313 log "Enabling (U)EFI boot."
1314 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1317 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1318 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1327 if cd "$BUILD_OUTPUT" ; then
1328 if [ "$BOOT_METHOD" = "grub2" ]; then
1329 # make a 2048-byte bootsector for El Torito
1330 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1331 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1332 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1333 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1335 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1336 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1337 -l -r -J $BOOT_ARGS -no-pad \
1338 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1339 # both of these need core.img there, so it’s easier to write it here
1340 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1341 # must be <= 30720 bytes
1342 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1343 conv=notrunc bs=512 seek=4 2>/dev/null
1346 # pad the output ISO to multiples of 256 KiB for partition table support
1347 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1348 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1349 siz=$((cyls * 16 * 32 * 512)) # size after padding
1350 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1351 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1353 # support disabling hybrid ISO image
1354 if [ "$HYBRID_METHOD" = "disable" ] ; then
1355 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1356 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1358 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1359 # isoinfo is part of both mkisofs and genisoimage so we're good
1360 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1361 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1363 if ! [ -r boot/grub/core.img ] ; then
1364 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1365 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1366 elif [ "${bootoff:-0}" -lt 1 ] ; then
1367 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1368 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1370 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1371 log "Creating hybrid ISO file with manifold/grub2 method"
1372 einfo "Creating hybrid ISO file with manifold/grub2 method"
1373 # 512 bytes: MBR, partition table, load GRUB 2
1374 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1376 log "Creating hybrid ISO file with manifold method"
1377 einfo "Creating hybrid ISO file with manifold method"
1378 # read only one but 2048-byte sized (scale: << 2) sector
1379 echo $bootoff $bootoff | \
1380 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1381 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1384 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1385 if ! which isohybrid >/dev/null 2>&1 ; then
1386 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1388 log "Creating hybrid ISO file with isohybrid method"
1389 einfo "Creating hybrid ISO file with isohybrid method"
1390 # Notes for consideration:
1391 # "-entry 4 -type 1c"
1392 # * using 4 as the partition number is supposed to help with BIOSes
1393 # that only support USB-Zip boot
1394 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1395 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1396 # to get the BIOS even look at the partition created by isohybrid
1397 if isohybrid --help | grep -q -- --uefi ; then
1398 if echo $CLASSES | grep -qw I386 ; then
1399 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1400 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1402 log "Detected uefi support for isohybrid, enabling"
1403 einfo "Detected uefi support for isohybrid, enabling"
1404 ISOHYBRID_OPTIONS=--uefi
1408 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1409 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1413 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1416 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1417 case $CLASSES in *RELEASE*)
1420 if cd $ISO_OUTPUT ; then
1421 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1422 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1423 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1424 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1433 if [ "$RC" = 0 ] ; then
1434 log "Finished execution of stage 'iso build' [$(date)]"
1435 einfo "Finished execution of stage 'iso build'" ; eend 0
1437 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1438 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1444 # netboot package {{{
1445 create_netbootpackage() {
1446 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1448 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1449 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1450 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1452 elif [ -n "$SKIP_NETBOOT" ] ; then
1453 log "Skipping stage 'netboot' as requested via option -Q"
1454 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1460 # since syslinux v3:6.03~pre1+dfsg-4 the pxelinux.0 has been split into a
1461 # separate pxelinux package
1462 if [ -d "${CHROOT_OUTPUT}/usr/lib/PXELINUX/" ] ; then
1463 local pxelinux_dir=/usr/lib/PXELINUX
1465 local pxelinux_dir=/usr/lib/syslinux
1468 if ! [ -r "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" ] ; then
1469 ewarn "File ${pxelinux_dir}/pxelinux.0 not found in build chroot." ; eend 0
1471 einfo "Install syslinux[-common]/pxelinux package in chroot to get a netboot package."
1476 local OUTPUTDIR="${NETBOOT}/build_tmp"
1477 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1479 mkdir -p "$WORKING_DIR"
1481 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1482 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1483 cp "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" "${WORKING_DIR}/pxelinux.0"
1485 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1486 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1487 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1489 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1490 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1492 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1493 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1497 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1499 cd $(dirname "${OUTPUT_FILE}")
1500 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1502 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1503 rm -rf "${OUTPUTDIR}"
1505 rm -rf "${OUTPUTDIR}"
1506 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1511 create_netbootpackage
1514 # log build information to database if grml-live-db is installed and enabled {{{
1516 if [ -d /usr/share/grml-live-db ] ; then
1519 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1520 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1521 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1522 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1524 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1525 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1526 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1530 # disable by default for now, not sure whether really everyone is using a local db file
1531 #if ! touch "$DPKG_DATABASE" ; then
1532 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1536 if ! [ -r "$DPKG_LIST" ] ; then
1537 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1538 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1540 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1541 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1542 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1545 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1561 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1562 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1564 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1566 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1570 ## END OF FILE #################################################################
1571 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2