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; values: etch, lenny, squeeze, sid
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 sid -V -r 'grml-live rocks'
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 log "Configuration file $LIVE_CONF can not be read, ignoring"
153 log "Sourcing configuration file $LIVE_CONF"
154 einfo "Sourcing configuration file $LIVE_CONF"
160 # umount all directories {{{
162 # make sure we don't leave any mounts - FAI doesn't remove them always
163 umount $CHROOT_OUTPUT/proc/sys/fs/binfmt_misc 2>/dev/null || /bin/true
164 umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
165 umount $CHROOT_OUTPUT/run 2>/dev/null || /bin/true
166 umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true
167 umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
168 umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
170 if [ -n "$EXTRACT_ISO_NAME" ] ; then
171 umount "$EXTRACT_ISO_NAME" 2>/dev/null || /bin/true
174 # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry
175 if [ -x /usr/lib/fai/mkramdisk ] ; then
176 /usr/lib/fai/mkramdisk -u "$(readlink -f ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true
179 umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true
180 [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
186 rm -f /var/run/fai/fai_softupdate_is_running \
187 /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
188 [ -n "$CONFIGDUMP" ] && rm -f "$CONFIGDUMP"
189 [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR"
191 [ -n "$1" ] && EXIT="$1" || EXIT="1"
192 [ -n "$2" ] && eerror "$2">&2
193 if [ -n "$CLEAN_ARTIFACTS" ]; then
196 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
197 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
201 # get rid of automatically generated conffiles
202 rm -f ${GRML_FAI_CONFIG}/nfsroot.conf
203 rm -f ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf
205 if [ -n "$CHOWN_USER" ]; then
206 log "Setting ownership"
207 einfo "Setting ownership"
208 [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}"
209 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}"
210 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}"
211 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}"
212 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}"
213 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && chown -R "${CHOWN_USER}:" "${NETBOOT}"
216 log "------------------------------------------------------------------------------"
219 trap bailout 1 2 3 3 6 9 14 15
223 # some important functions {{{
226 # usage: log "string to log"
227 log() { [ -n "$LOGFILE" ] && echo "$*" >> $LOGFILE ; }
229 # cut string at character number int = $1
230 # usage: cut_string 5 "1234567890" will output "12345"
232 [ -n "$2" ] || return 1
233 echo "$2" | head -c "$1"; echo -ne "\n"
236 # prepend int = $1 spaces before string = $2
237 # usage: extend_string_begin 5 "123" will output " 123"
238 extend_string_begin() {
239 [ -n "$2" ] || return 1
240 local COUNT="$(echo $2 | wc -c)"
241 local FILL="$(expr $COUNT - $1)"
242 while [ "$FILL" -gt 1 ] ; do
244 local FILL=$(expr $FILL - 1)
246 while [ "$FILL" -lt 1 ] ; do
248 local FILL=$(expr $FILL + 1)
250 echo "$2" | head -c "$1"; echo -ne "\n"
253 # append int = $1 spaces to string = $2
254 # usage: extend_string_begin 5 "123" will output "123 "
255 extend_string_end() {
256 [ -n "$2" ] || return 1
257 echo -n "$2" | head -c "$1"
258 local COUNT="$(echo $2 | wc -c)"
259 local FILL="$(expr $COUNT - $1)"
260 while [ "$FILL" -gt 1 ] ; do
262 local FILL=$(expr $FILL - 1)
264 while [ "$FILL" -lt 1 ] ; do
266 local FILL=$(expr $FILL + 1)
271 # Copy addonfile $1 from either
272 # * the chroot (via $2, the system path),
273 # * or from TEMPLATE_DIRECTORY/compat (if exists),
274 # * or from the host system (again, using $2),
275 # or warn about the missing file.
278 # * We assume that the chroot always has a "good" version of
279 # the file. Also it makes sources handling easier.
280 # * On unstable, we Recommend the Debian packages containing
281 # these files. The user can override them by putting his
282 # "better" version into the chroot.
283 # * On stable, the Debian packages are probably not available,
284 # or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
285 # our grml-live-compat package installs current file versions.
287 DEST="${BUILD_OUTPUT}/boot/$3"
288 if [ ! -d "${DEST}/" ]; then
291 if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then
292 log "Copying $1 from chroot"
293 cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/"
296 if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
297 log "Copying $1 from grml-live-compat"
298 cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
301 if [ -e "$2/$1" ]; then
302 log "Copying $1 from system"
303 cp "$2/$1" "${DEST}/"
307 msg="Missing addon file: \"$1\""
308 ewarn "$msg" ; eend 1
309 log "copy_addon_file: $msg"
313 # command line parsing {{{
314 while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
317 A) CLEAN_ARTIFACTS=1 ;;
320 c) CLASSES="$OPTARG" ;;
321 C) LOCAL_CONFIG="$(readlink -f $OPTARG)" ;;
323 D) GRML_FAI_CONFIG="$(readlink -f $OPTARG)" ;;
324 e) EXTRACT_ISO_NAME="$(readlink -f $OPTARG)" ;;
325 g) GRML_NAME="$OPTARG" ;;
326 h) usage ; bailout 0 ;;
327 i) ISO_NAME="$OPTARG" ;;
328 I) CHROOT_INSTALL="$OPTARG" ;;
330 N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;;
331 o) OUTPUT="$(readlink -f $OPTARG)" ;;
332 q) SKIP_MKSQUASHFS=1 ;;
334 r) RELEASENAME="$OPTARG" ;;
335 s) SUITE="$OPTARG" ;;
336 t) TEMPLATE_DIRECTORY="$OPTARG";;
337 v) VERSION="$OPTARG" ;;
340 U) CHOWN_USER="$OPTARG" ;;
342 z) SQUASHFS_ZLIB=1 ;;
343 ?) echo "invalid option -$OPTARG" >&2; usage; bailout 1 ;;
346 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
348 if [ -n "$1" ] ; then
349 echo "Error: unknown argument '$1' in options. Exiting to avoid possible data loss." >&2
354 # read local (non-packaged) configuration {{{
355 if [ -z "$LOCAL_CONFIG" ]; then
356 if [ -r "/etc/grml/grml-live.local" ]; then
357 LOCAL_CONFIG="/etc/grml/grml-live.local"
360 if [ -n "$LOCAL_CONFIG" ]; then
361 if [ -r "$LOCAL_CONFIG" ]; then
364 eerror "Could not read specified local configuration file \"$LOCAL_CONFIG\"."
367 LOCAL_CONFIG=$(readlink -f "$LOCAL_CONFIG")
372 if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then
373 eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated."
374 ewarn "Please set up \${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead."
379 # assume sane defaults (if not set already) {{{
380 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
381 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
382 [ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')"
383 [ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)"
384 [ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators'
385 [ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml"
386 [ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png'
387 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
388 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
389 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
390 [ -n "$HOSTNAME" ] || HOSTNAME='grml'
391 [ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='isohybrid'
392 [ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks'
393 [ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
394 [ -n "$SUITE" ] || SUITE='testing'
395 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
396 [ -n "$USERNAME" ] || USERNAME='grml'
397 [ -n "$VERSION" ] || VERSION='0.0.1'
399 # output specific stuff, depends on $OUTPUT (iff not set):
400 [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live'
401 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
402 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
403 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
404 [ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs"
405 [ -n "$REPORTS" ] || REPORTS="${LOG_OUTPUT}/reports/"
406 [ -n "$NETBOOT" ] || NETBOOT="${OUTPUT}/netboot/"
409 # some misc checks before executing FAI {{{
410 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
411 specify it on the command line using the -c option."
412 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
413 specify it on the command line using the -o option."
415 # trim characters that are known to cause problems inside $GRML_NAME;
416 # for example isolinux does not like '-' inside the directory name
417 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
419 # export variables to have them available in fai scripts:
420 [ -n "$GRML_NAME" ] && export GRML_NAME="$GRML_NAME"
421 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
424 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
425 # this was default behaviour until grml-live 0.9.34:
426 if [ -n "$ZERO_LOGFILE" ] ; then
427 PRESERVE_LOGFILE='' # make sure it's cleaned then
428 ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
429 ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
434 # ask user whether the setup is ok {{{
435 if [ -z "$FORCE" ] ; then
437 echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
439 echo " FAI classes: $CLASSES"
440 [ -n "$LOCAL_CONFIG" ] && echo " Configuration: $LOCAL_CONFIG"
441 [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG"
442 echo " main directory: $OUTPUT"
443 [ -n "$EXTRACT_ISO_NAME" ] && echo " Extract ISO: $EXTRACT_ISO_NAME"
444 [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT"
445 [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT"
446 [ -n "$ISO_OUTPUT" ] && echo " ISO target: $ISO_OUTPUT"
447 [ -n "$GRML_NAME" ] && echo " Grml name: $GRML_NAME"
448 [ -n "$RELEASENAME" ] && echo " Release name: $RELEASENAME"
449 [ -n "$DATE" ] && echo " Build date: $DATE"
450 [ -n "$VERSION" ] && echo " Grml version: $VERSION"
451 [ -n "$SUITE" ] && echo " Debian suite: $SUITE"
452 [ -n "$ARCH" ] && echo " Architecture: $ARCH"
453 [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD"
454 [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD"
455 [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY"
456 [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL"
457 [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID"
458 [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature."
459 [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER"
460 [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
461 [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS"
462 [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE"
463 [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression."
464 [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
465 [ -n "$VERBOSE" ] && echo " Using VERBOSE mode."
466 [ -n "$CLEAN_ARTIFACTS" ] && echo " Will clean output before and after running."
467 [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation."
468 if [ -n "$BOOTSTRAP_ONLY" ] ; then
469 echo " Bootstrapping only and not building (files for) ISO."
471 [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file."
472 [ -n "$SKIP_NETBOOT" ] && echo " Skipping creation of NETBOOT package."
473 [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file."
474 [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE."
475 [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched."
478 echo -n "Is this ok for you? [y/N] "
480 if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
482 echo "Exiting as requested."
489 # clean up before start {{{
490 if [ -n "${CLEAN_ARTIFACTS}" ]; then
491 echo "Wiping old artifacts"
492 [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}"
493 [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}"
494 [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}"
495 [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}"
496 [ -n "${NETBOOT}" -a -d "${NETBOOT}" ] && rm -r "${NETBOOT}"
500 # create log file {{{
501 [ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log
502 mkdir -p $(dirname "${LOGFILE}")
504 chown root:adm $LOGFILE
508 # clean/zero/remove logfiles {{{
510 if [ -n "$PRESERVE_LOGFILE" ] ; then
511 echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
513 # make sure it is empty (as it is e.g. appended to grml-live-db)
517 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
518 if [ -d /var/log/fai/"$HOSTNAME" ] ; then
519 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
520 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
521 rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
522 rm -f /var/log/fai/"$HOSTNAME"/last \
523 /var/log/fai/"$HOSTNAME"/last-dirinstall \
524 /var/log/fai/"$HOSTNAME"/last-softupdate
529 # source config and startup {{{
530 if [ -n "$CONFIG" ] ; then
531 if ! [ -f "$CONFIG" ] ; then
532 log "Error: $CONFIG could not be read. Exiting. [$(date)]"
533 eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
536 log "Sourcing $CONFIG"
541 start_seconds=$(cut -d . -f 1 /proc/uptime)
542 log "------------------------------------------------------------------------------"
543 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
544 log "Using local config file: $LOCAL_CONFIG"
545 log "Executed grml-live command line:"
548 einfo "Logging actions to logfile $LOGFILE"
551 # dump config variables into file, for script access {{{
554 '^(GRML_NAME|RELEASENAME|DATE|VERSION|SUITE|ARCH|DISTRI_NAME|USERNAME|HOSTNAME|APT_PROXY)=' \
558 # unpack iso/squashfs {{{
560 if [ -n "$EXTRACT_ISO_NAME" ]; then
561 log "Unpacking ISO from ${EXTRACT_ISO_NAME}"
562 einfo "Unpacking ISO from ${EXTRACT_ISO_NAME}"
563 local mountpoint=$(mktemp -d)
565 mount -o loop "${EXTRACT_ISO_NAME}" "$mountpoint" ; rc=$?
566 if [ "$rc" != 0 ]; then
569 eerror "mount failed"
574 if ls "${mountpoint}"/live/*/*.squashfs 2>/dev/null | grep -q . ; then # ISOs >=2011.12
575 log "Using ${mountpoint}/live/*/*.squashfs for unsquashfs"
576 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*/*.squashfs ; rc=$?
577 elif ls "${mountpoint}"/live/*.squashfs 2>/dev/null | grep -q . ; then # ISOs before 2011.12
578 log "Using ${mountpoint}/live/*.squashfs for unsquashfs"
579 unsquashfs -d "${CHROOT_OUTPUT}" "${mountpoint}"/live/*.squashfs ; rc=$?
581 log "Error: Could not find any *.squashfs files on the ISO"
582 eerror "Error: Could not find any *.squashfs files on the ISO"
589 if [ "$rc" != 0 ]; then
590 log "unsquashfs failed"
591 eerror "unsquashfs failed"
600 # on-the-fly configuration {{{
602 # does this suck? YES!
603 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
605 unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;;
606 *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";;
608 export SUITE # make sure it's available in FAI scripts
610 # validate whether the specified architecture class matches the
611 # architecture (option), otherwise installation of kernel will fail
612 if echo $CLASSES | grep -qw I386 ; then
613 if ! [[ "$ARCH" == "i386" ]] ; then
614 log "Error: You specified the I386 class but are trying to build something else (AMD64?)."
615 eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
616 eerror "Tip: Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
620 elif echo $CLASSES | grep -qi amd64 ; then
621 if ! [[ "$ARCH" == "amd64" ]] ; then
622 log "Error: You specified the AMD64 class but are trying to build something else (I386?)."
623 eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
624 eerror "Tip: Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
630 # generate nfsroot configuration for FAI on the fly
631 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
632 FAI_DEBOOTSTRAP="$SUITE http://cdn.debian.net/debian"
635 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
636 FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --arch $ARCH"
639 # create backup of old (not yet automatically generated) config file
640 if [ -f "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ] ; then
641 if ! grep -q 'This is an automatically generated file by grml-live' "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" ; then
642 ewarn "Found old ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf - moving to ${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
643 mv "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" "${GRML_FAI_CONFIG}/make-fai-nfsroot.conf.outdated"
648 echo "# This is an automatically generated file by grml-live.
649 # Do NOT edit this file, your changes will be lost.
650 FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"
651 FAI_DEBOOTSTRAP_OPTS=\"$FAI_DEBOOTSTRAP_OPTS\"
652 # EOF " > "${GRML_FAI_CONFIG}/nfsroot.conf"
653 # support FAI <=3.4.8, versions >=4.0 use nfsroot.conf
654 ( cd ${GRML_FAI_CONFIG} && ln -sf nfsroot.conf make-fai-nfsroot.conf )
657 # CHROOT_OUTPUT - execute FAI {{{
658 if [ -n "$BUILD_DIRTY" ]; then
659 log "Skipping stage 'fai' as requested via option -B"
660 ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
662 [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
664 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
665 FAI_ACTION=softupdate
667 FAI_ACTION=dirinstall
670 if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
671 if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
672 log "Error: does not look like you have a working chroot. Updating/building not possible."
673 eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
679 if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
680 log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
681 ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
683 mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
685 if [ -n "${MIRROR_DIRECTORY}" ] ; then
686 mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
687 mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
690 mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
691 mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
693 log "Executed FAI command line:"
694 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"
695 BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
696 -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
697 -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
698 RC="$PIPESTATUS" # notice: bash-only
700 # provide inform fai about the ISO we build, needs to be provided
701 # *after* FAI stage, otherwise FAI skips the debootstrap stage if
702 # there is not BASEFILE (as it checks for presence of /etc) :(
703 echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
704 [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
705 [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
707 FORCE_ISO_REBUILD=true
709 if [ "$RC" != 0 ] ; then
710 log "Error: critical error while executing fai [exit code ${RC}]. Exiting."
711 eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
715 # move fai logs into grml_logs directory
716 mkdir -p "$LOG_OUTPUT"/fai/
717 cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
718 rm -rf "$CHROOT_OUTPUT"/var/log/fai
720 # store copy of autogenerated configuration file
721 cp ${GRML_FAI_CONFIG}/nfsroot.conf "$LOG_OUTPUT"/fai/
723 # copy fai package list
724 cp "$CHROOT_OUTPUT"/var/log/install_packages.list "$LOG_OUTPUT"/fai/
726 chown root:adm "$LOG_OUTPUT"/fai/*
727 chmod 664 "$LOG_OUTPUT"/fai/*
731 # notice: 'fai dirinstall' does not seem to exit appropriate, so:
733 CHECKLOG="$LOG_OUTPUT"/fai/
734 if [ -r "$CHECKLOG/software.log" ] ; then
735 # 1 errors during executing of commands
736 grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
737 grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
738 grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
739 grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
740 grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
743 if [ -r "$CHECKLOG/shell.log" ] ; then
744 grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
747 if [ -n "$ERROR" ] ; then
748 log "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
749 eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
750 eerror "Note: check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
754 log "Finished execution of stage 'fai dirinstall' [$(date)]"
755 einfo "Finished execution of stage 'fai dirinstall'"
761 # package validator {{{
762 CHECKLOG=/var/log/fai/$HOSTNAME/last
763 if [ -r "$CHECKLOG/dpkg.selections" ] ; then
764 package_count=$(wc -l "$CHECKLOG/dpkg.selections" | awk '{print $1}')
766 package_count="unknown"
770 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
772 # check for missing packages
773 if ! [ -s "$CHECKLOG/package_errors.log" ] ; then
774 einfo "No missing packages found, generating empty junit report."
776 cat > "${REPORT_MISSING_PACKAGES}" << EOF
777 <?xml version="1.0" encoding="UTF-8"?>
778 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="0" errors="0" skipped="0" assertions="0">
779 <testcase name="test_missing_packages" time="0" assertions="0">
789 einfo "Missing packages found, generating junit report."
791 if [ -r "$CHECKLOG/package_errors.log" ] ; then
792 package_errors=$(wc -l "$CHECKLOG/package_errors.log" | awk '{print $1}')
794 package_errors="unknown"
798 REPORT_MISSING_PACKAGES="${REPORTS}/TEST-MissingPackages.xml"
800 cat > "${REPORT_MISSING_PACKAGES}" << EOF
801 <?xml version="1.0" encoding="UTF-8"?>
802 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
805 for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
806 failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
807 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
808 <testcase name="test_missing_packages_${package}" time="0" assertions="0">
809 <failure type="${failure_reason}" message="Package ${package} is missing">
810 Package $package is missing in chroot (${failure_reason})
816 cat >> "${REPORT_MISSING_PACKAGES}" << EOF
825 if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
826 eerror "The following packages were requested for installation but could not be processed:"
827 cat "$CHECKLOG/package_errors.log"
828 eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
832 ewarn "The following packages were requested for installation but could not be processed:"
833 cat "$CHECKLOG/package_errors.log"
839 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
840 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
841 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
844 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
845 if [ -n "$BOOTSTRAP_ONLY" ] ; then
846 log "Skipping stage 'boot' as building with bootstrap only."
847 ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
849 if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
850 log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
851 ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
854 [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
855 [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
857 # if we don't have an initrd we a) can't boot and b) there was an error
858 # during build, so check for the file:
859 INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
860 if [ -n "$INITRD" ] ; then
861 cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
862 find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
864 log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
865 eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
869 KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
870 if [ -n "$KERNEL_IMAGE" ] ; then
871 cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
873 log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
874 eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
879 if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
880 einfo "Moving EFI boot files into ISO path."
881 log "Moving EFI boot files into ISO path."
883 mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
884 mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
885 mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
889 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
890 if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
891 log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
892 eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
896 # copy _required_ isolinux files
897 for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
898 copy_addon_file "${file}" /usr/lib/syslinux isolinux
901 # *always* copy files to output directory so the variables
902 # get adjusted according to the build.
903 cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/
905 if [ -n "$NO_ADDONS" ] ; then
906 log "Skipping installation of boot addons as requested via \$NO_ADDONS."
907 einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
909 if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
910 log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
911 ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
913 # copy addons from system packages or grml-live-compat
914 copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
915 copy_addon_file pci.ids /usr/share/misc addons
916 copy_addon_file memtest86+.bin /boot addons
917 for file in memdisk chain.c32 hdt.c32 mboot.c32 menu.c32; do
918 copy_addon_file "${file}" /usr/lib/syslinux addons
921 # make memtest filename FAT16/8.3 compatible
922 mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
923 "${BUILD_OUTPUT}/boot/addons/memtest"
925 # copy only files so we can handle bsd4grml on its own
926 for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
927 test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
930 if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
931 log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
932 einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
934 if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
935 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
937 log "Missing addon file: bsd4grml"
938 ewarn "Missing addon file: bsd4grml" ; eend 0
942 fi # no "$TEMPLATE_DIRECTORY"/boot/addons
945 if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
946 mkdir -p "${BUILD_OUTPUT}/boot/grub"
948 cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
950 # generate loopback.cfg config file without depending on grub's regexp module
951 # which isn't available in Debian/squeeze
952 echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
953 echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
954 for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
955 [ -r "$config" ] || continue
956 echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
958 echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
959 echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
961 # copy grub files from target
962 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
963 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
964 cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
965 cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
966 cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
967 cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
969 if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
970 log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
971 eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
975 mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
976 cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
978 # adjust boot splash information:
979 RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
980 RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
981 RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
983 if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
984 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
985 sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
988 # make sure the squashfs filename is set accordingly:
989 SQUASHFS_NAME="$GRML_NAME.squashfs"
991 if [ -n "$NO_BOOTID" ] ; then
992 log 'Skipping bootid feature as requested via $NO_BOOTID.'
993 einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
995 [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
996 [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
997 einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
998 log "Generating /conf/bootid.txt with entry ${BOOTID}."
999 echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
1003 # adjust all variables in the templates with the according distribution information
1004 for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
1005 "${BUILD_OUTPUT}"/boot/grub/* ; do
1006 if [ -r "${file}" ] && [ -f "${file}" ] ; then
1007 sed -i "s/%ARCH%/$ARCH/g" "${file}"
1008 sed -i "s/%DATE%/$DATE/g" "${file}"
1009 sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}"
1010 sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}"
1011 sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}"
1012 sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}"
1013 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}"
1014 sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}"
1015 sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}"
1016 sed -i "s/%VERSION%/$VERSION/g" "${file}"
1018 [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;" "${file}"
1020 if [ -n "$NO_BOOTID" ] ; then
1021 sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
1023 sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
1028 for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
1029 RELEASE_INFO SHORT_NAME VERSION ; do
1030 for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
1031 value="$(eval echo '$'"$param")"
1032 mv ${file} ${file/\%${param}\%/$value}
1036 # adjust bootsplash accordingly but make sure the string has the according lenght
1037 SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
1038 SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
1039 for file in f4 f5 ; do
1040 if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
1041 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1042 sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
1046 # generate addon list
1047 rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1048 for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
1049 include_name=$(basename "$name")
1050 echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
1053 if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
1054 log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1055 echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1056 echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1057 echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1058 echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1060 for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
1061 echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1064 echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1065 if [ ! -n "$NO_ADDONS" ] ; then
1066 echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1068 echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1069 echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1070 echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
1071 else # assume we are building a custom distribution:
1072 log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1073 einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
1074 if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1075 log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1077 einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
1081 log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1082 echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1083 [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
1087 # use old style console based isolinux method only if requested:
1088 if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
1089 log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1090 einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
1091 if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
1092 einfo "include for console.cfg already found, nothing to do."
1095 log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1096 einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1097 echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1101 log 'Using graphical boot menu.'
1102 if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
1103 log "include for vesamenu.cfg already found, nothing to do."
1105 log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1106 echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
1110 if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
1111 sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
1114 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
1115 if ! [ -r "$DPKG_LIST" ] ; then
1116 ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
1118 einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
1119 cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
1123 # autostart for Windows:
1124 if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
1125 cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
1128 FORCE_ISO_REBUILD=true
1129 einfo "Finished execution of stage 'boot'" ; eend 0
1133 log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
1134 eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
1138 # support installation of local files into the chroot/ISO
1139 if [ -n "$CHROOT_INSTALL" ] ; then
1140 if ! [ -d "$CHROOT_INSTALL" ] ; then
1141 log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1142 ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
1144 log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1145 einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
1146 rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
1148 einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
1149 FORCE_ISO_REBUILD=true
1153 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1154 log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
1155 ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
1156 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
1157 log "Skipping stage 'squashfs' as requested via option -q or -N"
1158 ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0
1160 mkdir -p "$BUILD_OUTPUT"/live/"${GRML_NAME}"/
1161 # make sure we don't leave (even an empty) base.tgz:
1162 [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
1164 # if unconfigured default to squashfs-tools' mksquashfs binary
1165 if [ -z "$SQUASHFS_BINARY" ] ; then
1166 SQUASHFS_BINARY='mksquashfs'
1169 if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
1170 log "Using mksquashfs binary ${SQUASHFS_BINARY}"
1171 einfo "Using mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
1173 log "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
1174 eerror "Error: mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
1178 # use sane defaults if $SQUASHFS_OPTIONS isn't set
1179 if [ -z "$SQUASHFS_OPTIONS" ] ; then
1180 # use blocksize 256k as this gives best result with regards to time + compression
1181 SQUASHFS_OPTIONS="-b 256k"
1183 # set lzma/xz compression by default, unless -z option has been specified on command line
1184 if [ -z "$SQUASHFS_ZLIB" ] ; then
1185 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz"
1187 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip"
1191 # support exclusion of files via exclude-file:
1192 if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1193 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards"
1196 # get rid of unnecessary files when building grml-small for final release:
1197 if echo "$CLASSES" | grep -q GRML_SMALL ; then
1198 SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1202 SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1204 # informational stuff
1205 [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1206 [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1207 einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1209 log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS"
1211 if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}"/"${GRML_NAME}".squashfs \
1212 -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then
1213 echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/"${GRML_NAME}"/filesystem.module
1214 log "Finished execution of stage 'squashfs' [$(date)]"
1215 einfo "Finished execution of stage 'squashfs'" ; eend 0
1217 log "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1218 log "$(cat $SQUASHFS_STDERR)"
1219 eerror "Error: there was a critical error executing stage 'squashfs':"
1220 cat "${SQUASHFS_STDERR}"
1225 FORCE_ISO_REBUILD=true
1228 # create md5sum file:
1229 if [ -z "$BOOTSTRAP_ONLY" ] ; then
1230 ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
1231 find ../.. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1235 # ISO_OUTPUT - mkisofs {{{
1236 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1237 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1239 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1240 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1241 elif [ "$BOOT_METHOD" = "grub2" ] ; then
1242 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
1245 # Work around http://bts.grml.org/grml/issue945
1246 if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then
1247 log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1248 ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet."
1249 HYBRID_METHOD='grub2'
1253 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then
1254 log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1255 ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1256 elif [ -n "$SKIP_MKISOFS" ] ; then
1257 log "Skipping stage 'iso build' as requested via option -n or -N"
1258 ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0
1260 mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1262 if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1263 log "Forcing rebuild of ISO because files on ISO have been modified."
1264 einfo "Forcing rebuild of ISO because files on ISO have been modified."
1267 # support xorriso as well mkisofs and genisoimage
1268 if which xorriso >/dev/null 2>&1 ; then
1269 MKISOFS='xorriso -as mkisofs'
1270 elif which mkisofs >/dev/null 2>&1; then
1272 elif which genisoimage >/dev/null 2>&1; then
1273 MKISOFS='genisoimage'
1275 log "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO."
1276 eerror "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." ; eend 1
1280 einfo "Using ${MKISOFS} to build ISO." ; eend 0
1281 case "${ARCH}-${MKISOFS}" in
1282 # using -eltorito-alt-boot is limited to xorriso for now
1286 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
1287 log "Disabling (U)EFI boot support because xorriso version is too old."
1288 ewarn "Disabling (U)EFI boot support because xorriso version is too old." ; eend 0
1290 if [ -r "${BUILD_OUTPUT}"/boot/efi.img ] ; then
1291 einfo "Enabling (U)EFI boot."
1292 log "Enabling (U)EFI boot."
1293 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
1296 log "Disabling (U)EFI boot support because /boot/efi.img is missing."
1297 ewarn "Disabling (U)EFI boot support because /boot/efi.img is missing." ; eend 0
1306 if cd "$BUILD_OUTPUT" ; then
1307 if [ "$BOOT_METHOD" = "grub2" ]; then
1308 # make a 2048-byte bootsector for El Torito
1309 dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
1310 # those are in 2048-byte sectors, so 1 16 matches 4 63 below
1311 echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
1312 dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
1314 log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
1315 $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1316 -l -r -J $BOOT_ARGS -no-pad \
1317 -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1318 # both of these need core.img there, so it’s easier to write it here
1319 if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
1320 # must be <= 30720 bytes
1321 dd if=boot/grub/core.img of="${ISO_OUTPUT}/${ISO_NAME}" \
1322 conv=notrunc bs=512 seek=4 2>/dev/null
1325 # pad the output ISO to multiples of 256 KiB for partition table support
1326 siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1327 cyls=$((siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
1328 siz=$((cyls * 16 * 32 * 512)) # size after padding
1329 dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1330 of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1332 # support disabling hybrid ISO image
1333 if [ "$HYBRID_METHOD" = "disable" ] ; then
1334 log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1335 einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1337 elif [ "$HYBRID_METHOD" = "manifold" ] || [ "$HYBRID_METHOD" = "grub2" ] ; then
1338 # isoinfo is part of both mkisofs and genisoimage so we're good
1339 bootoff=$(isoinfo -l -i "${ISO_OUTPUT}/${ISO_NAME}" | \
1340 sed -n '/^.*\[ *\([0-9]*\)[] ].* ISOLINUX.BIN[;1]* *$/s//\1/p')
1342 if ! [ -r boot/grub/core.img ] ; then
1343 log "boot/grub/core.img not found, not creating manifold boot ISO file"
1344 ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1345 elif [ "${bootoff:-0}" -lt 1 ] ; then
1346 log "isolinux.bin not found on the ISO file, disabling manifold boot"
1347 ewarn "isolinux.bin not found on the ISO file, disabling manifold boot"
1349 if [ "$HYBRID_METHOD" = "grub2" ] ; then
1350 log "Creating hybrid ISO file with manifold/grub2 method"
1351 einfo "Creating hybrid ISO file with manifold/grub2 method"
1352 # 512 bytes: MBR, partition table, load GRUB 2
1353 echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1355 log "Creating hybrid ISO file with manifold method"
1356 einfo "Creating hybrid ISO file with manifold method"
1357 # read only one but 2048-byte sized (scale: << 2) sector
1358 echo $bootoff $bootoff | \
1359 mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
1360 fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1363 elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1364 if ! which isohybrid >/dev/null 2>&1 ; then
1365 bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1367 log "Creating hybrid ISO file with isohybrid method"
1368 einfo "Creating hybrid ISO file with isohybrid method"
1369 # Notes for consideration:
1370 # "-entry 4 -type 1c"
1371 # * using 4 as the partition number is supposed to help with BIOSes
1372 # that only support USB-Zip boot
1373 # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1374 # (hidden NTFS, IIRC), as the partition type is sometimes needed
1375 # to get the BIOS even look at the partition created by isohybrid
1376 if isohybrid --help | grep -q -- --uefi ; then
1377 if echo $CLASSES | grep -qw I386 ; then
1378 log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1379 einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
1381 log "Detected uefi support for isohybrid, enabling"
1382 einfo "Detected uefi support for isohybrid, enabling"
1383 ISOHYBRID_OPTIONS=--uefi
1387 log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
1388 isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
1392 bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
1395 # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1396 case $CLASSES in *RELEASE*)
1399 if cd $ISO_OUTPUT ; then
1400 md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1401 touch -r ${ISO_NAME} ${ISO_NAME}.md5
1402 sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1403 touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1412 if [ "$RC" = 0 ] ; then
1413 log "Finished execution of stage 'iso build' [$(date)]"
1414 einfo "Finished execution of stage 'iso build'" ; eend 0
1416 log "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1417 eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1423 # netboot package {{{
1424 create_netbootpackage() {
1425 local OUTPUT_FILE="${NETBOOT}/grml_netboot_package_${GRML_NAME}_${VERSION}.tar.bz2"
1427 if [ -f "${OUTPUT_FILE}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
1428 log "Skipping stage 'netboot' as $OUTPUT_FILE exists already."
1429 ewarn "Skipping stage 'netboot' as $OUTPUT_FILE exists already." ; eend 0
1431 elif [ -n "$SKIP_NETBOOT" ] ; then
1432 log "Skipping stage 'netboot' as requested via option -Q"
1433 ewarn "Skipping stage 'netboot' as requested via option -Q" ; eend 0
1439 if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
1440 ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
1442 einfo "Install syslinux[-common] package in chroot to get a netboot package."
1447 local OUTPUTDIR="${NETBOOT}/build_tmp"
1448 local WORKING_DIR="${OUTPUTDIR}/grml_netboot_package_${GRML_NAME}_${VERSION}/tftpboot/"
1450 mkdir -p "$WORKING_DIR"
1452 cp "${CHROOT_OUTPUT}"/boot/vmlinuz-* "$WORKING_DIR"/vmlinuz
1453 cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
1454 cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
1456 mkdir -p "${WORKING_DIR}/pxelinux.cfg"
1457 if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
1458 cp "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" "${WORKING_DIR}/pxelinux.cfg/default"
1460 log "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1461 ewarn "File ${BUILD_OUTPUT}/boot/isolinux/netboot.cfg not found."
1463 log "Hint: Are you using custom templates which do not provide netboot.cfg?"
1464 ewarn "Hint: Are you using custom templates which do not provide netboot.cfg?" ; eend 0
1468 if tar -C "$OUTPUTDIR" -jcf "${OUTPUT_FILE}" "grml_netboot_package_${GRML_NAME}_${VERSION}" ; then
1470 cd $(dirname "${OUTPUT_FILE}")
1471 sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
1473 einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
1474 rm -rf "${OUTPUTDIR}"
1476 rm -rf "${OUTPUTDIR}"
1477 eerror "Could not generate netboot package ${OUTPUT_FILE}" ; eend 1
1482 create_netbootpackage
1485 # log build information to database if grml-live-db is installed and enabled {{{
1487 if [ -d /usr/share/grml-live-db ] ; then
1490 DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1491 [ -n "$DPKG_DATABASE" ] || DPKG_DATABASE=/var/log/grml-live.db
1492 [ -n "$DPKG_DBSCRIPT" ] || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1493 [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1495 if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1496 log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1497 eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1501 # disable by default for now, not sure whether really everyone is using a local db file
1502 #if ! touch "$DPKG_DATABASE" ; then
1503 # eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1507 if ! [ -r "$DPKG_LIST" ] ; then
1508 log "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1509 ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1511 einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1512 log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1513 log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1516 if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1532 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1533 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1535 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1537 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1541 ## END OF FILE #################################################################
1542 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2