Whamcloud - gitweb
b=24090 distro and target autodetection
[fs/lustre-release.git] / build / lbuild
1 #!/bin/bash
2
3 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 # this is an alternative FD for stdout, to be used especially when we are
6 # taking stdout from a function as it's return value.  i.e. foo=$(bar)
7 # this is a workaround until a version of bash where we can put xtrace
8 # on a specific FD
9 exec 3>&1; STDOUT=3
10
11 #set -x
12 xtrace="+x"
13 if [[ $SHELLOPTS = *xtrace* ]]; then
14     xtrace="-x"
15 fi
16 shopt -s extdebug
17
18 # include the exit_traps library
19 . ${0%/lbuild}/exit_traps.sh
20
21 # our children should die when we do
22 push_exit_trap "kill -INT -$$ || true" kill_children
23
24 # increment this if you have made a change that should force a new kernel
25 # to build built
26 #BUILD_GEN=1
27 #BUILD_GEN=2    # bz19952: remove -lustre tag from kernel RPM names
28 #BUILD_GEN=3    # bz19975: enable the building of src.rpms by default
29 BUILD_GEN=4     # bz22281: use the git hash in the kernel extra version
30
31 TOPDIR=$PWD
32
33 # CVSROOT is inherited from the environment
34 KERNELDIR=
35 LINUX=
36 LUSTRE=
37 RELEASE=false
38 # XXX - some recent hacking has pretty much neutered this option.
39 #       search through this file (and lbuild.old_school -- but that will
40 #       be going away soon) for "-bb" and see how many places
41 #       simply don't account for this option
42 DO_SRC=true
43 DOWNLOAD=true
44 TAG=
45 CANONICAL_TARGET=
46 TARGET=
47 TARGET_ARCH="$(uname -m)"
48 # change default behavior to only build for the current arch
49 TARGET_ARCHS="$TARGET_ARCH"
50 TARGET_ARCHS_ALL="$TARGET_ARCH"
51 [ "$TARGET_ARCH" = "i686" ] && TARGET_ARCHS_ALL="i686 i586 i386"
52 CONFIGURE_FLAGS=
53 EXTERNAL_PATCHES=
54 EXTRA_VERSION=
55 STAGEDIR=
56 TMPDIR=${TMPDIR:-"/var/tmp"}
57 TIMESTAMP=
58 # this is a dir to try reuse old kernel RPMs in (although, it seems to be
59 # unused in any real manner
60 REUSERPM=
61 # this is the dir that should be used to store reuse products
62 REUSEBUILD=
63 # should cached products be used or force rebuilding?
64 USE_BUILD_CACHE=true
65 # what does this do exactly?  does it imply no kernel build?
66 NORPM=false
67 LDISKFSRPM=true
68 SKIPLDISKFSRPM="v1_4_* b1_4"
69 SMPTYPES="smp bigsmp default ''"
70 PATCHLESS=false
71 XEN=false
72 LINUXOBJ=
73 DISTRO=
74 KERNELTREE=
75 # default to not adding -lustre- into the kernel RPM package names
76 KERNEL_LUSTRE_NAMING=false
77
78 # patchless build
79 KERNELRPMSBASE=
80 RPMSMPTYPE=
81
82 # from target file
83 SERIES=
84 BASE_ARCHS=
85 BIGMEM_ARCHS=
86 BOOT_ARCHS=
87 JENSEN_ARCHS=
88 SMP_ARCHS=
89 BIGSMP_ARCHS=
90 PSERIES64_ARCHS=
91 UP_ARCHS=
92
93 # not in the target file any more
94 CONFIG=
95
96 # build the lustre-tests rpm?
97 LUSTRE_TESTS=true
98
99 DATE=$(date)
100
101 USE_DATESTAMP=1
102 RPMBUILD=
103
104 OLD_SCHOOL=false
105
106 export CC=${CC:-gcc}
107
108 # Readlink is not present on some older distributions: emulate it.
109 readlink() {
110     local path=$1 ll
111
112     if [ -L "$path" ]; then
113         ll="$(LC_ALL=C ls -l "$path" 2> /dev/null)" &&
114         echo "${ll/* -> }"
115     else
116         return 1
117     fi
118 }
119
120 cleanup() {
121
122     true
123 }
124
125 error() {
126     local msg="$1"
127
128     [ -n "$msg" ] && echo -e "\n${0##*/}: $msg" >&3
129
130 }
131
132 fatal() {
133
134     cleanup
135     error "$2"
136     exit $1
137
138 }
139
140 usage() {
141     cat <<EOF
142 Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
143
144   -d CVSROOT
145     Specifies the CVS Root to use when pulling files from CVS.  The
146     environment variable \$CVSROOT is used if this option is not
147     present.
148
149   --external-patches=EXTERNAL_PATCHES
150     Directory similar to lustre/lustre/kernel_patches/ that lbuild should
151     look for seres and config files in before looking in the lustre
152     tree.
153
154   --extraversion=EXTRAVERSION
155     Text to use for the rpm release and kernel extraversion.
156
157   --timestamp=TIMESTAMP
158     Date of building lustre in format YYYYMMDDhhmmss
159
160   --reuserpm=DIR
161     Try to reuse old kernel RPMs from DIR
162
163   --reusebuild=DIR
164     Try to reuse old kernel builds from DIR
165
166   --kernelrpm=DIR
167     Path to distro kernel RPM collection
168
169   --ccache
170     Use ccache
171
172   --norpm
173     Do not build RPMs (compile only mode)
174
175   --patchless
176     Build lustre client only
177
178   --distro=DISTRO
179     Which distro using. Autodetect by default
180
181   --kerneldir=KERNELDIR
182     Directory containing Linux source tarballs referenced by target
183     files.
184
185   --kerneltree=KERNELTREE
186     Directory containing dirs with Linux source tarballs referenced by target
187     files. Dir names in format kernel version ('2.6.9', etc.)
188
189   --linux=LINUX --with-linux=LINUX
190     Directory of Linux kernel sources.  When this option is used, only
191     Lustre modules and userspace are built.
192
193   --lustre=LUSTRE
194     Path to an existing lustre source tarball to use instead of
195     pulling from CVS.
196
197   --nodownload
198     Do not try to download a kernel from downloads.lustre.org
199
200   --nosrc
201     Do not build a .src.rpm, a full kernel patch, or a patched kernel
202     tarball.
203
204   --ldiskfs
205     Do ldiskfs RPM. Now true by default
206
207   --publish
208     Unused.
209
210   --release
211     Specifies that the files generated do not include timestamps, and
212     that this is an official release.
213
214   --src
215     Build a .src.rpm, a full kernel patch, and a patched kernel tarball.
216
217   --stage=DIR
218     Directory used to stage packages for release.  RPMs will be placed
219     more or less in DIR/<target>-<arch>, and the tarball will be
220     placed in DIR.
221
222   --tag=TAG
223     A CVS branch/tag name to build from when pulling from CVS.
224
225   --target=TARGET
226     The name of the target to build.  The available targets are listed
227     below.
228
229   --target-archs=TARGET_ARCHS
230     A (space delimited) list of architectures to build.  By default,
231     all of the archs supported by the TARGET will be built, in
232     addition to a .src.rpm.  This option can limit those, for machines
233     that can only build certain archs or if you only want a certain
234     arch built (for testing, or a one-off kernel).
235
236     Also note that by using a non-"base" arch (eg, i386) only kernels
237     will be built - there will be no lustre-lite-utils package.
238
239   --disable-datestamp
240     Prevents the datestamp flag (-D) from being passed to cvs for
241     checkouts. This is a workaround for a problem encountered when
242     using lbuild with tinderbox.
243
244   --xen
245     Builds a Xen domX kernel.
246
247   --set-value
248     Set's a variable to a given value.
249
250 EOF
251
252 #   list_targets
253
254     fatal "$1" "$2"
255 }
256
257 # canonicalize a relative path to a file
258 canon_filepath() {
259     local PATH="$1"
260
261     if [ ! -f "$PATH" ]; then
262         return 1
263     fi
264
265     local FILE=${PATH##*/}
266     local DIR=${PATH%/*}
267
268     echo $(canon_path "$DIR")/$FILE
269     return 0
270 }
271
272 # canonicalize a relative path to a dir
273 canon_path() {
274     local PATH="$1"
275
276     if [ ! -d "$PATH" ]; then
277         return 1
278     fi
279
280     pushd "$PATH" >/dev/null || return 1
281     local CANONPATH=$PWD
282     popd >/dev/null
283
284     echo "$CANONPATH"
285     return 0
286 }
287
288 check_options() {
289
290     if [ "$LUSTRE" ]; then
291         [ -r "$LUSTRE" ] || \
292             usage 1 "Could not find Lustre source tarball '$LUSTRE'."
293     else
294         [ "$CVSROOT" ] || \
295             usage 1 "Either specify a CVS Root with -d, or a Lustre source tarball with --lustre."
296         [ "$TAG" ] || \
297             usage 1 "A branch/tag name must be specified with --tag when not building from a tarball."
298     fi
299
300     [ -z "$DISTRO" ] && DISTRO=$(autodetect_distro)
301
302     if [ -z "$LINUX" ]; then
303         [ "$KERNELDIR" -o "$KERNELTREE" ] || \
304             usage 1 "A kernel directory must be specified with --kerneldir or --kerneltree."
305
306         [ -d "$KERNELDIR" -o -d "$KERNELTREE" ] || \
307             usage 1 "$KERNELDIR and $KERNELTREE are not a directory."
308
309         if ! $RELEASE; then
310             [ "$TAG" ] || \
311                 usage 1 "When building a snapshot, a tag name must be used."
312         fi
313
314         [ "$TARGET" ] || TARGET=$(autodetect_target "$DISTRO")
315 #       TARGET_FILE="$TOPDIR/lustre/kernel_patches/targets/$TARGET.target"
316 #       [ -r "$TARGET_FILE" ] || \
317 #               usage 1 "Target '$TARGET' was not found."
318     fi
319
320     case $TARGET in
321         2.6-rhel5)
322             CANONICAL_TARGET="rhel5"
323             ;;
324         2.6-rhel4)
325             CANONICAL_TARGET="rhel-2.6"
326             ;;
327         2.6-suse)
328             CANONICAL_TARGET="sles-2.6"
329             ;;
330         2.6-sles10)
331             CANONICAL_TARGET="sles10-2.6"
332             ;;
333         2.6-sles11)
334             CANONICAL_TARGET="sles11"
335             ;;
336         2.6-oel5)
337             CANONICAL_TARGET="oel5"
338             ;;
339         hp_pnnl-2.4)
340             CANONICAL_TARGET="hp-pnnl-2.4"
341             ;;
342         2.6-vanilla \
343             | suse-2.4.21-2 \
344             | rh-2.4 \
345             | rhel-2.4 \
346             | sles-2.4 \
347             | 2.6-patchless)
348                 CANONICAL_TARGET="$TARGET"
349                 ;;
350     esac
351
352     local timestampnodig=$(echo $TIMESTAMP | sed -e s/[0-9]*//g)
353     [ "$timestampnodig" = "" ] || TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
354     local timestamplength="${#TIMESTAMP}"
355     if [ $timestamplength -eq 12 ]; then
356         TIMESTAMP="${TIMESTAMP}00"
357     elif [ $timestamplength -ne 14 ]; then
358         TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
359     fi
360
361     RPMBUILD=$(which rpmbuild 2>/dev/null | head -1)
362     if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
363         RPMBUILD=$(which rpm 2>/dev/null | head -1)
364         if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
365             usage 1 "Could not find binary for making rpms (tried rpmbuild and rpm)."
366         fi
367     fi
368
369     if [ -n "$CCACHE" ]; then
370         which "$DISTCC" &>/dev/null && export DISTCC RPM_BUILD_NCPUS
371
372         if which "$CCACHE" &>/dev/null; then
373             local ccache=$(which "$CCACHE")
374             local bindir="$TOPDIR/bin"
375
376             if [ ! -d $bindir ]; then
377                 mkdir -p $bindir || fatal 1 "error trying to create $bindir"
378             else
379                 rm ${bindir}/* > /dev/null 2>&1 || true
380             fi
381             ln -s "$ccache" ${bindir}/ccache
382             ln -s "$ccache" ${bindir}/cc
383             ln -s "$ccache" ${bindir}/$CC
384             export PATH=$bindir:$PATH
385             export CCACHE && export CC="ccache $CC"
386             # zero the cache so we can see how effective we are being with it
387             echo -n "ccache "
388             ccache -z
389
390             # get some ccache stats when we are done
391             push_exit_trap '[ -n "$CCACHE" ] && ccache -s' "ccache_summary"
392             # should remove the ccache trap if lbuild is interrupted
393             trap 'echo "Received an INT TERM or HUP signal, terminating."; delete_exit_trap "ccache_summary"; exit 1' INT TERM HUP
394         fi
395     fi
396
397     return 0
398
399 }
400
401 # autodetect target
402 autodetect_target() {
403     local distro="$1"
404
405     local target=""
406     case ${distro} in
407           oel5) target="2.6-oel5";;
408          rhel5) target="2.6-rhel5";;
409         sles10) target="2.6-sles10";;
410             *) fatal 1 "I don't know what distro $distro is.\nEither update autodetect_target() or use the --target argument.";;
411     esac
412
413     echo ${target}
414     return 0
415
416 }
417
418 # autodetect used Distro
419 autodetect_distro() {
420
421     local name
422     local version
423
424     if which lsb_release >/dev/null 2>&1; then
425         name="$(lsb_release -s -i)"
426         version="$(lsb_release -s -r)"
427         case "$name" in
428             "EnterpriseEnterpriseServer" | "ScientificSL")
429                 name="oel"
430                 version="${version%%.*}"
431                 ;;
432             "RedHatEnterpriseServer")
433                 name="rhel"
434                 version="${version%%.*}"
435                 ;;
436             "SUSE LINUX")
437                 name="sles"
438                 ;;
439             *)
440                 fatal 1 "I don't know what distro name $name and version $version is.\nEither update autodetect_distro() or use the --distro argument."
441                 ;;
442         esac
443     else
444         echo "You really ought to install lsb_release for accurate distro identification"
445         # try some heuristics
446         if [ -f /etc/SuSE-release ]; then
447             name=sles
448             version=$(grep ^VERSION /etc/SuSE-release)
449             version=${version#*= }
450         elif [ -f /etc/redhat-release ]; then
451             #name=$(head -1 /etc/redhat-release)
452             name=rhel
453             version=$(echo "$distroname" |
454                       sed -e 's/^[^0-9.]*//g' | sed -e 's/[ \.].*//')
455         fi
456         if [ -z "$name" -o -z "$version" ]; then
457             fatal 1 "I don't know how to determine distro type/version.\nEither update autodetect_distro() or use the --distro argument."
458         fi
459     fi
460
461     echo ${name}${version}
462     return 0
463
464 }
465
466 uniqify() {
467
468     echo $(echo "$*" | xargs -n 1 | sort -u)
469
470 }
471
472 download_srpm() {
473     local target=$1
474     local srpm=$2
475     local force="${3:-false}"
476
477     if $force || [ ! -r "$KERNELDIR/$srpm" ] ||
478        [ ! -s "$KERNELDIR/$srpm" ]; then
479         if $DOWNLOAD; then
480             local location="http://downloads.lustre.org/public/kernels/$target/old"
481             echo "Downloading $location/$srpm..."
482             if ! wget -nv "$location/$srpm" -O "$KERNELDIR/$srpm" 2>&1 ||
483                [ ! -s "$KERNELDIR/$srpm" ]; then
484                 rm -f $KERNELDIR/$srpm
485                 fatal 1 "Could not download target $target's kernel SRPM $srpm from $location."
486             fi
487         else
488             fatal 1 "$srpm not found in directory $KERNELDIR."
489         fi
490     fi
491
492 }
493
494 download_file() {
495     local from="$1"
496     local to="$2"
497     local force="$3"
498
499     local file=${from##*/}
500
501     if [ -d $to ]; then
502         to="$to/$file"
503     fi
504
505     local semaphore="$to-downloading"
506
507     is_downloading() {
508         if [ ! -f $semaphore ]; then
509             return 1
510         fi
511
512         # make sure the download has not been aborted
513         local now=$(date +%s)
514         local file_mtime=$(stat -c %Y "$to")
515         local staleness=$((now - file_mtime))
516         # let's assume an active download will write at least once a minute
517         if [ $staleness -gt 60 ]; then
518             return 1
519         fi
520
521         return 0
522     }
523
524     is_downloaded() {
525         # if the semaphore file exists, the file is either still downloading
526         # or a download was aborted and we cannot trust the target file
527         if [ -f $semaphore ]; then
528             return 1
529         fi
530
531         if ! is_downloading && [ -r "$to" ] && [ -s "$to" ]; then
532             return 0
533         fi
534
535         return 1
536     }
537
538     if $force || ! is_downloaded; then
539         if is_downloading; then
540             echo "Somebody else is downloading $from..."
541             while is_downloading; do
542                 echo "Waiting for $to to finish downloading"
543                 sleep 60
544             done
545             if is_downloaded; then
546                 return 0
547             else
548                 echo "The download we were waiting for seems to have been aborted"
549             fi
550
551         fi
552
553         if $DOWNLOAD; then
554             echo "Downloading $from..."
555             # flag others so they don't try to download also
556             push_exit_trap "rm -f $to $semaphore" "download"
557             touch $semaphore
558             if ! wget -nv "$from" -O "$to" || [ ! -s "$to" ]; then
559                 # the trap will remove the files via the fatal below
560                 fatal 1 "Could not download ${to##*/} from ${from%/*}/."
561             fi
562             rm -f $semaphore
563             delete_exit_trap "download"
564         else
565             fatal 1 "${to##*/} not found in directory ${to%/*}."
566         fi
567     fi
568
569     return 0
570
571 }
572
573 download_ofed() {
574     local force="${1:-false}"
575
576     if [ -z "$OFED_VERSION" -o "$OFED_VERSION" = "inkernel" ]; then
577         return 0
578     fi
579
580     local location="http://www.openfabrics.org/downloads/OFED/ofed-${OFED_VERSION}/"
581
582     if [[ $OFED_VERSION = daily-* ]]; then
583         local Mmv daily
584         OFED_VERSION=${OFED_VERSION/daily-/}
585         Mmv=${OFED_VERSION%%-*}
586         daily=${OFED_VERSION##$Mmv-}
587         location="http://www.openfabrics.org/downloads/OFED/ofed-${Mmv}-daily/"
588         # find the filename for the version for the date specified
589         OFED_VERSION=$(curl -s "$location" | sed -nre "/${daily}-/s/.*href=\"OFED-(${Mmv//./\\.}-${daily}-[0-9]{4,4}).tgz.*$/\1/p" | tail -1)
590         if [ -z "$OFED_VERSION" ]; then
591             fatal 1 "Could not determine the filename of the OFED snapshot for ${daily}"
592         fi
593     fi
594
595     local file="OFED-${OFED_VERSION}.tgz"
596     download_file "$location/$file" "$KERNELTREE" "$force"
597
598 }
599
600 load_target() {
601
602     EXTRA_VERSION_save="$EXTRA_VERSION"
603     for patchesdir in "$EXTERNAL_PATCHES" \
604                       "$TOPDIR/lustre/lustre/kernel_patches"; do
605         TARGET_FILE="$patchesdir/targets/$TARGET.target"
606         [ -r "$TARGET_FILE" ] && break
607     done
608     [ -r "$TARGET_FILE" ] || fatal 1 "Target $TARGET was not found."
609
610     echo "Loading target config file $TARGET.target..."
611
612     # if the caller specified an OFED_VERSION it should override whatever
613     # the target file specifies
614     local env_OFED_VERSION="$OFED_VERSION"
615
616     . "$TARGET_FILE"
617
618     if [ -n "$env_OFED_VERSION" ]; then
619         OFED_VERSION="$env_OFED_VERSION"
620     fi
621
622     # doesn't make any sense to build OFED for xen domX's
623     if $XEN; then
624         OFED_VERSION=""
625     fi
626
627     # XXX - set_rpm_smp_type is an ugly undeterministic hack.  it needs to
628     #       go away and the target just specify the $RPMSMPTYPE
629     [ -z "$RPMSMPTYPE" ] && set_rpm_smp_type
630
631     # CC might have been overwriten in TARGET_FILE
632     if [[ $CC != ccache\ * ]] && which "$CCACHE" &>/dev/null; then
633         export CCACHE && export CC="ccache $CC"
634     fi
635
636     if [ ! "$KERNELTREE" = "" ] && [ -d "$KERNELTREE" ]; then
637         KERNELDIR="$KERNELTREE/${lnxmaj}"
638         [ -d "$KERNELDIR" ] || mkdir "$KERNELDIR"
639     fi
640
641     # verify the series is available
642     if [ "$SERIES" ]; then
643         for series in $SERIES; do
644             for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
645                 [ -r "$patchesdir/series/$series" ] && continue 2
646             done
647             fatal 1 "Target $TARGET's series $SERIES could not be found.\nSearched:\n\t$EXTERNAL_PATCHES/series\n\t$TOPDIR/lustre/lustre/kernel_patches/series."
648         done
649     fi
650
651     # set the location of the .config file
652     local XENPOSTFIX=""
653     if $XEN; then
654         XENPOSTFIX="-xen"
655     fi
656
657     if [ -f $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET-$TARGET_ARCH.config ]; then
658         CONFIG_FILE="$TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET$XENPOSTFIX-$TARGET_ARCH${RPMSMPTYPE:+-}${RPMSMPTYPE}.config"
659     fi
660
661     local lnxrelnew=${lnxrel//-/_}
662
663     # remember the EXTRA_VERSION before we diddle it here
664     # XXX - we really should not diddle with any values read in from the
665     #       target file.  if we want to modify a value, we should create
666     #       a new variable.
667     PRISTINE_EXTRA_VERSION=$EXTRA_VERSION
668
669     if ! $PATCHLESS && [ ! -f "$CONFIG_FILE" ]; then
670         fatal 1 "Config file for target $TARGET missing from $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/."
671     fi
672
673     if [ "$EXTRA_VERSION_save" ]; then
674         EXTRA_VERSION="$EXTRA_VERSION_save"
675     elif ! $RELEASE; then
676         # if there is no patch series, then this is not a lustre specific
677         # kernel.  don't make it look like one
678         if $PATCHLESS || [ -n "$SERIES" ]; then
679             EXTRA_VERSION=$(echo $EXTRA_VERSION | sed -e "s/\(.*_lustre\)\..*/\1/")
680 #            EXTRA_VERSION="${EXTRA_VERSION}-${TAG}.${TIMESTAMP}"
681             if ! $PATCHLESS && [ -n "$BUILDID" ]; then
682                 EXTRA_VERSION="${EXTRA_VERSION}.${BUILDID}"
683             fi
684         fi
685     fi
686     # EXTRA_VERSION=${EXTRA_VERSION//-/_}
687
688     ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $BIGSMP_ARCHS $PSERIES64_ARCHS $UP_ARCHS"
689
690     BUILD_ARCHS=
691     for arch in $(uniqify "$ALL_ARCHS"); do
692         if [ -z "$TARGET_ARCHS" ] ||
693            [[ \ $TARGET_ARCHS\  = *\ $arch\ * ]]; then
694             BUILD_ARCHS="$BUILD_ARCHS $arch"
695         fi
696     done
697     [ "$BUILD_ARCHS" ] || usage 1 "No available target archs to build."
698     echo "Building for: $BUILD_ARCHS"
699 }
700
701 tarflags() {
702     local file="$1"
703
704     case "$file" in
705         '')
706             fatal 1 "tarflags(): File name argument missing."
707             ;;
708         *.tar.gz | *.tgz)
709             echo 'zxf'
710             ;;
711         *.tar.bz2)
712             echo 'jxf'
713             ;;
714         *.tar)
715             echo 'xf'
716             ;;
717         *)
718             fatal 1 "tarflags(): Unrecognized tar extension in file: $1"
719             ;;
720     esac
721
722 }
723
724 untar() {
725     local tarfile="$1"
726     shift
727     local extractfile="$@"
728
729     echo "Untarring ${tarfile##*/}..."
730     tar $(tarflags "$tarfile") "$tarfile" $extractfile
731
732 }
733
734 unpack_ofed() {
735
736     if ! untar "$KERNELTREE/OFED-${OFED_VERSION}.tgz"; then
737         return 1
738     fi
739     [ -d OFED ] || ln -sf OFED-[0-9].[0-9]* OFED
740
741 }
742
743 unpack_lustre() {
744
745     if [ -z "$LUSTRE" ]; then
746         local DATESTAMP=""
747
748         if [ -n "$USE_DATESTAMP" ]; then
749             DATESTAMP="-D '$DATE'"
750         fi
751
752         local DIRNAME="lustre-$TAG-$TIMESTAMP"
753
754         cvs -d "$CVSROOT" -qz3 co $DATESTAMP -d "$DIRNAME" lustre || \
755             fatal 1 "There was an error checking out toplevel Lustre from CVS."
756         pushd "$DIRNAME" > /dev/null
757         ./lustrecvs "$TAG" || \
758             fatal 1 "There was an error checking out Lustre/Portals/Build from CVS."
759         echo "Creating lustre tarball..."
760         sh autogen.sh || fatal 1 "There was an error running autogen.sh."
761         ./configure --enable-dist || \
762             fatal 1 "There was an error running ./configure to create makefiles."
763         make dist || fatal 1 "There was an error running 'make dist'."
764         LUSTRE=$PWD/lustre-*.tar.gz
765         popd > /dev/null
766     fi
767
768     untar "$LUSTRE" || fatal 1 "Error unpacking Lustre tarball"
769     [ -d lustre ] || ln -sf lustre-[0-9].[0-9]* lustre
770
771 }
772
773 do_patch_linux() {
774
775     local do_patch=${1:-true}
776
777     FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
778     [ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
779     $do_patch && pushd linux >/dev/null
780     for series in $SERIES; do
781         echo -n "Applying series $series:"
782         for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
783             [ -r "$patchesdir/series/$series" ] || continue
784             SERIES_FILE="$patchesdir/series/$series"
785             for patch in $(<"$SERIES_FILE"); do
786                 echo -n " $patch"
787                 PATCH_FILE="$patchesdir/patches/$patch"
788                 [ -r "$PATCH_FILE" ] || \
789                     fatal 1 "Patch $patch does not exist in Lustre tree."
790                 cat "$PATCH_FILE" >> "$FULL_PATCH" || {
791                     rm -f $FULL_PATCH
792                     fatal 1 "Error adding patch $patch to full patch."
793                 }
794                 if $do_patch; then
795                     patch -s -p1 < "$PATCH_FILE" 2>&1 || {
796                         rm -f $FULL_PATCH
797                         fatal 1 "Error applying patch $patch."
798                     }
799                 fi
800             done
801             break
802         done
803         echo
804     done
805     $do_patch && popd >/dev/null
806     echo "Full patch has been saved in ${FULL_PATCH##*/}."
807
808 }
809
810 build_lustre() {
811     local linux="$1"
812     local linuxobj="$2"
813
814     cp "$LUSTRE" SOURCES
815
816     pushd lustre >/dev/null
817
818     echo "Building Lustre RPMs for: $BUILD_ARCHS..."
819     local targets arch
820     for arch in $BUILD_ARCHS; do
821         targets="--target $arch $targets"
822     done
823
824     local confoptions=""
825
826     if $PATCHLESS; then
827         confoptions="$confoptions --disable-server"
828     fi
829
830     local rpmbuildopt='-tb'
831     if $NORPM; then
832         rpmbuildopt='-tc'
833         echo NORPM mode. Only compiling.
834     fi
835
836     ( $(skeep_ldiskfs_rpm $TAG) ) || {
837
838         pushd ldiskfs > /dev/null || return 255
839
840         if !  ./configure --enable-dist; then
841             echo "failed to configure in ldiskfs"
842             popd >/dev/null # pushd ldiskfs
843             popd >/dev/null # pushd lustre
844             return 255
845         fi
846
847         if ! make dist 2>&1; then
848             popd >/dev/null # pushd ldiskfs
849             popd >/dev/null # pushd lustre
850             return 255
851         fi
852
853         #cp lustre-ldiskfs*.tar.gz $TOPDIR/SOURCES || \
854         #    fatal 1 "Could not copy lustre-ldiskfs*.tar.gz to $TOPDIR/SOURCES"
855
856         if ! $RPMBUILD $targets $rpmbuildopt lustre-ldiskfs*.tar.gz \
857             --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
858             --define "kdir $linux" \
859             ${linuxobj:+--define "kobjdir $linuxobj"} \
860             --define "_tmppath /var/tmp" \
861             --define "_topdir $TOPDIR" 2>&1; then
862             popd >/dev/null # pushd ldiskfs
863             popd >/dev/null # pushd lustre
864             return 255
865         fi
866
867         if $DO_SRC; then
868             if ! $RPMBUILD -ts lustre-ldiskfs*.tar.gz \
869                 --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
870                 --define "kdir $linux" \
871                 ${linuxobj:+--define "kobjdir $linuxobj"} \
872                 --define "_tmppath /var/tmp" \
873                 --define "_topdir $TOPDIR" 2>&1; then
874                 popd >/dev/null # pushd ldiskfs
875                 popd >/dev/null # pushd lustre
876                 return 255
877             fi
878         fi
879         popd >/dev/null # pushd ldiskfs
880
881         # tell lustre where ldiskfs is
882         # XXX - pointing to the RPM BUILD dir is a hack.  we need to flesh
883         #       out the ldiskfs RPM build so that it builds a
884         #       lustre-ldiskfs-devel RPM and install that and point lustre
885         #       to that instead
886         confoptions="$confoptions --with-ldiskfs=$(ls -d $TOPDIR/BUILD/lustre-ldiskfs-*)"
887     }
888
889     # convert the $PATCHLESS boolean to an empty/not-empty boolean
890     # as silly as this seems, it makes the syntax of the rpmbuild command
891     # simpler and not need an eval to deal with the quotes in the quotes
892     local is_patchless=""
893     if $PATCHLESS; then
894         is_patchless="yes"
895     fi
896
897     # ditto for the lustre-tests boolean
898     local lustre_tests=""
899     if ! $LUSTRE_TESTS; then
900         lustre_tests="no"
901     fi
902
903     $RPMBUILD $targets $rpmbuildopt "$LUSTRE" \
904         ${is_patchless:+--define "lustre_name lustre-client"} \
905         ${lustre_tests:+--define "build_lustre_tests 0"} \
906         ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
907         --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
908         --define "kdir $linux" \
909         ${linuxobj:+--define "kobjdir $linuxobj"} \
910         --define "_tmppath $TMPDIR" \
911         --define "_topdir $TOPDIR" 2>&1 || \
912         fatal 1 "Error building rpms for $BUILD_ARCHS."
913
914     if $DO_SRC; then
915         if ! $RPMBUILD -ts "$LUSTRE" \
916                  ${is_patchless:+--define "lustre_name lustre-client"} \
917                  ${lustre_tests:+--define "build_lustre_tests 0"} \
918                  ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
919                  --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
920                  --define "kdir $linux" \
921                  ${linuxobj:+--define "kobjdir $linuxobj"} \
922                  --define "_tmppath $TMPDIR" \
923                  --define "_topdir $TOPDIR" 2>&1; then
924             popd
925             return 255
926         fi
927     fi
928     popd >/dev/null
929
930 }
931
932 stage() {
933
934     [ "$STAGEDIR" ] || return 0
935
936     for arch in $BUILD_ARCHS; do
937         rpmdir="${STAGEDIR}/${CANONICAL_TARGET}-${arch}"
938         echo "${0##*/}: Copying RPMs into ${rpmdir}"
939         mkdir -p "${rpmdir}"
940         cp -v RPMS/${arch}/*.rpm "${rpmdir}"
941         if [ -d RPMS/noarch ]; then
942             cp -v RPMS/noarch/*.rpm "${rpmdir}"
943         fi
944     done
945
946     cp -v "$LUSTRE" "$STAGEDIR"
947
948 }
949
950 #check if we need to build separate ldiskfs RPM
951 skeep_ldiskfs_rpm() {
952     local tag="$1"
953
954     local skip=false
955
956     if ! $LDISKFSRPM; then
957         skip=true
958     elif $PATCHLESS; then
959         skip=true
960     else
961         for skiptag in $SKIPLDISKFSRPM; do
962             [[ $tag == $skiptag ]] && skip=true && break
963         done
964     fi
965
966     echo $skip
967
968 }
969
970 set_rpm_smp_type() {
971
972     local infact_arch="${TARGET_ARCH}"
973
974     RPMSMPTYPE=""
975     [ "$infact_arch" == "i586" ] && infact_arch="i686"
976
977     local smp_type
978     for smp_type in $SMP_ARCHS; do
979         [ $infact_arch == $smp_type ] && RPMSMPTYPE=smp && break
980     done
981
982     for smp_type in $BIGSMP_ARCHS; do
983         [ $infact_arch == $smp_type ] && RPMSMPTYPE=bigsmp && break
984     done
985
986     for smp_type in $PPC64_ARCHS; do
987         [ $infact_arch == $smp_type ] && RPMSMPTYPE=ppc64 && break
988     done
989
990     for smp_type in $DEFAULT_ARCHS; do
991         [ $infact_arch == $smp_type ] && RPMSMPTYPE=default && break
992     done
993
994 }
995
996 # This function takes a linux source pool and digs out the linux release
997 # from it
998 find_linux_release() {
999     local SRCDIR="$1"
1000
1001     local LINUXRELEASEHEADER=$SRCDIR/include/linux/version.h
1002     if [ -s $SRCDIR/include/linux/utsrelease.h ]; then
1003         LINUXRELEASEHEADER=$SRCDIR/include/linux/utsrelease.h
1004     fi
1005
1006     sed -ne 's/#define UTS_RELEASE "\(.*\)"$/\1/p' $LINUXRELEASEHEADER
1007
1008 }
1009
1010 # XXX this needs to be re-written as a wrapper around find_rpm
1011 #     or just gotten rid of.  :-)
1012 find_linux_rpm() {
1013     local prefix="$1"
1014
1015     local pathtorpms="${KERNELRPMSBASE}/${lnxmaj}/${DISTRO}"
1016     [ -d $pathtorpms ] || return 255
1017
1018     local kernelbinaryrpm rpmfile
1019     local wanted_kernel="${lnxmaj}${lnxmin}-${lnxrel}"
1020
1021     local arch ret=1
1022     for arch in $TARGET_ARCHS_ALL; do
1023         local found_rpm="" rpm
1024         for rpm in ${pathtorpms}/${arch}/*.rpm; do
1025             if rpm -q --provides -p "$rpm" 2>&3 | grep -q "kernel${prefix} = $wanted_kernel" 2>&3; then
1026
1027                 found_rpm="$rpm"
1028                 ret=0
1029                 break
1030             fi
1031         done
1032         [ -f "$found_rpm" ] && break
1033     done
1034
1035     echo "$found_rpm"
1036     return $ret
1037
1038 }
1039
1040 # unpack kernel(/source/devel) RPM
1041 #
1042 # This function and it's setting of $LINUX and $LINUXOBJ is a total hack that
1043 # needs to completely refactored.  It completely ingores that $BUILD_ARCHS may
1044 # contain a list of arches for which rpmbuild commands (including the one for
1045 # lustre itself)
1046 unpack_linux_devel_rpm() {
1047     local kernelrpm="${1}"
1048
1049     [ -f "$kernelrpm" ] || return 255
1050     [ -d $TOPDIR/reused ] || mkdir $TOPDIR/reused || return 255
1051
1052     pushd $TOPDIR/reused &>/dev/null || return 255
1053
1054     if ! rpm2cpio < "$kernelrpm" | cpio -id > /dev/null 2>&1; then
1055         return 255
1056     fi
1057
1058     # call a distro specific hook, if available
1059     if type -p unpack_linux_devel_rpm-$DISTRO; then
1060         if ! unpack_linux_devel_rpm-$DISTRO "$kernelrpm"; then
1061             return 255
1062         fi
1063     fi
1064
1065     popd &>/dev/null
1066
1067     find_linux_devel_paths $TOPDIR/reused
1068
1069     return 0
1070
1071 }
1072
1073 build_kernel_ib() {
1074     local linux="$1"
1075
1076     # build kernel-ib{,-devel}
1077     local K_SRC="K_SRC"
1078     # ofed 1.3 had a bug in the rpm spec
1079     if [ "$OFED_VERSION" = "1.3" ]; then
1080         K_SRC="KSRC"
1081     fi
1082
1083     local OFED_CORE="--with-core-mod --with-ipoib-mod --with-sdp-mod --with-user_mad-mod --with-user_access-mod --with-addr_trans-mod --with-rds-mod --with-qlgc_vnic-mod --with-madeye-mod"
1084     local OFED_HARDWARE="--with-mthca-mod --with-mlx4-mod --with-mlx4_en-mod --with-cxgb3-mod --with-nes-mod"
1085     # some I/B drivers are architecture dependent and kernel-ib's configure
1086     # does not figure it out for us ~sigh~
1087     case "$TARGET_ARCH" in
1088         ppc64)
1089             OFED_HARDWARE="$OFED_HARDWARE --with-ehca-mod"
1090             ;;
1091     esac
1092     # we're no longer shipping the OFED iSCSI
1093     #OFED_ISCSI="--with-srp-mod --with-srp-target-mod"
1094     ## ISER module has no backport support as of OFED 1.5 (i.e. only builds on
1095     ##kernels >= 2.6.30)
1096     #if [[ $OFED_VERSION = 1.[0-4]* ]]; then
1097     #   OFED_ISCSI="$OFED_ISCSI --with-iser-mod"
1098     #fi
1099
1100     # assume we are just rebuilding the SRPM
1101     local BUILD_TYPE=${BUILD_TYPE:-"--rebuild"}
1102     local SOURCE="${TOPDIR}/OFED/SRPMS/ofa_kernel-*.src.rpm"
1103
1104     # but switch to building from the SPEC if we need to apply patches
1105     if ls ${TOPDIR}/lustre/build/patches/ofed/* >/dev/null; then
1106         BUILD_TYPE="-bb"
1107         rpm --define "_topdir ${TOPDIR}" -ivh $SOURCE
1108         SOURCE="${TOPDIR}/SPECS/ofa_kernel.spec"
1109         local file ed_fragment1 ed_fragment2 n=1
1110         for file in $(ls ${TOPDIR}/lustre/build/patches/ofed/*); do
1111             ed_fragment1="$ed_fragment1
1112 Patch$n: ${file%%*/}"
1113             ed_fragment2="$ed_fragment2
1114 %patch$n -p0"
1115             cp $file ${TOPDIR}/SOURCES
1116             let n=$n+1
1117         done
1118
1119         if [ $n -gt 1 ]; then
1120             ed $SOURCE <<EOF
1121 /^Source: /a
1122 $ed_fragment1
1123 .
1124 /^%setup /a
1125 $ed_fragment2
1126 .
1127 wq
1128 EOF
1129         fi
1130     fi
1131
1132     local linuxrelease=$(find_linux_release "$linux")
1133     if ! $RPMBUILD $BUILD_TYPE --define 'build_kernel_ib 1' --define 'build_kernel_ib_devel 1' \
1134                   ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
1135                   --define "_topdir ${TOPDIR}" --target ${TARGET_ARCH} \
1136                   --define "KVERSION ${linuxrelease}" \
1137                   --define "$K_SRC ${linux}" \
1138                   --define "LIB_MOD_DIR /lib/modules/${linuxrelease}/updates" \
1139                   ${OFA_KERNEL_RELEASE:+--define "_release $OFA_KERNEL_RELEASE"} \
1140                   --define "configure_options --without-quilt $OFED_CORE $OFED_HARDWARE $OFED_ISCSI" \
1141                   ${SOURCE} 2>&1; then
1142         fatal 1 "Error building kernel-ib"
1143     fi
1144
1145 }
1146
1147 store_for_reuse() {
1148     local articles="$1"
1149     local module="$2"
1150     local location="$3"
1151     local signature="$4"
1152     local use_links="$5"
1153
1154     local linkflag=""
1155     if $use_links; then
1156         linkflag="l"
1157     fi
1158
1159     local default_iface=$(/sbin/ip route get 192.1.1.1 | sed -ne 's/.* dev \(.*\)  * src .*/\1/p')
1160     if [ -z "$default_iface" ]; then
1161         fatal 1 "Failed to determine the default route interface"
1162     fi
1163     local unique_id=$(/sbin/ip addr show dev $default_iface | sed -ne '/ inet /s/ *inet \(.*\)\/.*/\1/p' | head -1)
1164     if [ -z "$unique_id" ]; then
1165         fatal 1 "Failed to determine a unique id from interface $default_interface"
1166     fi
1167
1168     local finallocation="$location"/"$signature"/"$module"
1169     location="$location"/"$signature-${unique_id}"/"$module"
1170     mkdir -p "$location"
1171     # the cleanup script removes any directory that doesn't have a
1172     # .lastused, so let's try to prevent that as soon as we can
1173     # this solution still slightly racy with the cleanup script
1174     # but the race is a lot tighter now
1175     touch -t 197001010000 "$location/.lastused"
1176     ## use eval/echo here to make sure shell expansions are performed
1177     #if ! cp -a${linkflag} $(eval echo $articles) "$location"; then
1178     local article
1179     for article in $(eval echo $articles); do
1180         if ! cp -a${linkflag} "$article" "$location"; then
1181             error "Failed to copy \"$article\" to \"$location\" in store_for_reuse()"
1182             # rename the cache location so that it's not cached
1183             # product, but is around for analysis
1184             mv "$location"{,-bad-$(date +%s)} ||
1185                 error "failed to clean up a failed cache attempt" \
1186                       "in \"$location\" -- manual cleanup will be" \
1187                       "necessary"
1188             return 1
1189         fi
1190     done
1191
1192     # flag the cache as complete (i.e. in case lbuild was previously
1193     # interrupted while caching)
1194     touch "$location/.lastused"
1195
1196     # put the temporary location into the final location
1197     # (last one wins)
1198     mkdir -p "${finallocation%/*}"
1199     mv "$location" "$finallocation"
1200     rmdir "${location%/*}"
1201     return 0
1202
1203 }
1204
1205 reuse() {
1206     local module="$1"
1207     local dest="$2"
1208     local use_links="${3:-false}"
1209     local signature="$4"
1210
1211     if [ -n "$REUSEBUILD" ] && [ -d "$REUSEBUILD/$signature/$module" ]; then
1212         if [ ! -f "$REUSEBUILD/$signature/$module/.lastused" ]; then
1213             # the .lastused flag is populated at the end of the caching to
1214             # signal that the caching was completed.  if that flag is not
1215             # there, then the cache is invalid (and should be removed in fact)
1216             mv "$REUSEBUILD/$signature/$module"{,-bad-$(date +%s)} ||
1217                 fatal 1 "failed to clean up a bad cache in location $REUSEBUILD/$signature/$module\" -- manual cleanup will be necessary"
1218             return 1
1219         fi
1220
1221         # so that we know how stale this entry is
1222         touch $REUSEBUILD/$signature/$module/.lastused
1223
1224         if $use_links; then
1225             if ls $REUSEBUILD/$signature/$module/* >/dev/null 2>&1; then
1226                 cp -al $REUSEBUILD/$signature/$module/* $dest/
1227             fi
1228         else
1229             # copying is pretty heavy
1230             # cp -a $REUSEBUILD/$signature/$module/* $dest/
1231             # do some creative symlinking instead
1232             local dir
1233             for dir in BUILD SRPMS SPECS; do
1234                 if ls $REUSEBUILD/$signature/$module/$dir/* >/dev/null 2>&1; then
1235                     ln -s $REUSEBUILD/$signature/$module/$dir/* $dest/$dir
1236                 fi
1237             done
1238             # sources have to be copied by file because we need SOURCES to
1239             # be a dir we can write into
1240 # could overrun ls's arg list here
1241             #ls $REUSEBUILD/$signature/$module/SOURCES/* |
1242             find $REUSEBUILD/$signature/$module/SOURCES/ -type f |
1243                 xargs ln -t $dest/SOURCES -s
1244
1245             # same for RPMS/* dirs
1246 # could overrun ls's arg list here
1247             #ls $REUSEBUILD/$signature/$module/RPMS/$TARGET_ARCH/* |
1248             local dir
1249             for dir in $REUSEBUILD/$signature/$module/RPMS/*; do
1250                 mkdir -p $dest/RPMS/${dir##*/}
1251                 find $dir -type f |
1252                   xargs ln -t $dest/RPMS/${dir##*/} -s
1253             done
1254         fi
1255         return 0
1256     else
1257         return 1
1258     fi
1259 }
1260
1261 basearch() {
1262     local arch="$1"
1263
1264     if [[ $arch = i[3456]86 ]]; then
1265         echo "i386"
1266     else
1267         echo "$arch"
1268     fi
1269
1270 }
1271
1272 #
1273 # in a given directory, find the first rpm matching given requirements
1274 #
1275 find_rpm() {
1276     local dir="$1"
1277     local match_type="$2"
1278     local match="$3"
1279
1280     pushd "$dir" > /dev/null || \
1281         fatal 1 "Unable to chdir to directory \"$dir\" in find_rpm()"
1282
1283     local file
1284     for file in $(ls *.rpm); do
1285         if [ ! -f "$file" ]; then
1286             continue
1287         fi
1288         case "$match_type" in
1289             provides)
1290                 # match is any valid ERE (i.e. given to egrep) match
1291                 if rpm -q --provides -p "$file" 2>&3 | egrep -q "$match"; then
1292                     echo "$file"
1293                     popd >/dev/null
1294                     return 0
1295                 fi
1296                 ;;
1297             *)
1298                 popd >/dev/null
1299                 fatal 1 "Unknown match type \"$match_type\" given to find_rpm()"
1300                 ;;
1301         esac
1302     done
1303
1304     popd >/dev/null
1305     return 1
1306 }
1307
1308 build_kernel_with_srpm() {
1309     local outfd=$1
1310
1311     if [ -z "$outfd" ] || [ $outfd = 1 ]; then
1312         fatal 1 "You must supply a file descriptor to ${FUNCNAME[0]} and it cannot be 1"
1313     fi
1314
1315     # need to generate the patch for this target
1316     do_patch_linux false >&${outfd}    # sets global $FULL_PATCH (yeah, yuck)
1317
1318     # get an md5sum of the kernel patch + config for reuse check
1319     # XXX really, there needs to be a signature and a CONFIG_FILE per arch
1320     #     in BUILD_ARCHS
1321     local release_str
1322     if $RELEASE; then
1323         local release_str="RELEASE=$RELEASE\n"
1324     fi
1325
1326     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1327         local REUSE_SIGNATURE=$({ echo -en $release_str;
1328                                   echo $BUILD_GEN;
1329                                   cat $CONFIG_FILE $TARGET_FILE $FULL_PATCH; } |
1330                                 md5sum | cut -d" " -f1)
1331         # see if we can link to the reuse pool
1332         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1333         #       "library"
1334         local CAN_LINK_FOR_REUSE=false
1335         touch $REUSEBUILD/$$
1336         if cp -al $REUSEBUILD/$$ $TOPDIR/ 2>/dev/null; then
1337             CAN_LINK_FOR_REUSE=true
1338         fi
1339         rm $REUSEBUILD/$$
1340     fi
1341
1342     # the extra version string to use for the kernel (which might be a reused
1343     # kernel, remember)
1344     local kernel_extra_version=""
1345     if ! $USE_BUILD_CACHE || ! reuse kernel "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1346                                    "$REUSE_SIGNATURE"; then
1347         # nothing cached, build from scratch
1348         if [ ! -r "$KERNELDIR/$KERNEL_SRPM" ]; then
1349             echo "Downloading kernel SRPM"
1350             download_srpm "$CANONICAL_TARGET" "$KERNEL_SRPM" >&${outfd}
1351         fi
1352
1353         if ! rpm -ivh $KERNELDIR/$KERNEL_SRPM \
1354                   --define "_topdir $TOPDIR" >&${outfd} 2>&1; then
1355             # should we clean this up or leave it for analysis?
1356             #rm -rf $RPMTOPDIR
1357             fatal 1 "Error installing kernel SRPM."
1358         fi
1359
1360         # put the Lustre kernel patch into the RPM build tree
1361         cp $FULL_PATCH $TOPDIR/SOURCES/linux-${lnxmaj}-lustre.patch
1362         prepare_and_build_srpm >&${outfd} ||
1363             fatal 1 "failed to prepare_and_build_srpm"
1364
1365         if [ -z "$REUSE_SIGNATURE" ]; then
1366             echo "No reuse signature was caculated so not storing the built kernel" >&${outfd}
1367         else
1368             # store the resulting kernel RPM build tree for future use
1369             echo "Storing the built kernel for future reuse" >&${outfd}
1370             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
1371                                  "kernel" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1372                                  "$CAN_LINK_FOR_REUSE"; then
1373                 error "Failed to store kernel RPMS for reuse"
1374                 echo "unknown"
1375                 return 1
1376             fi
1377         fi
1378     fi  # build reuse
1379
1380     # figure out the EXTRA_VERSION of the kernel we built or are re-using
1381     local KERNEL_RPM
1382     if ! KERNEL_RPM=$(find_rpm "$TOPDIR/RPMS/$TARGET_ARCH/" provides "^kernel ="); then
1383         fatal 1 "Failed to find a kernel RPM in $TOPDIR/RPMS/$TARGET_ARCH/"
1384     fi
1385     kernel_extra_version=$(rpm -q --queryformat "%{RELEASE}" -p $TOPDIR/RPMS/$TARGET_ARCH/$KERNEL_RPM)
1386
1387     # should now have the following RPMs
1388     # $TOPDIR/RPMS/$arch/kernel-lustre-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1389     # $TOPDIR/RPMS/$arch/kernel-lustre-devel-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1390     # $TOPDIR/RPMS/$arch/kernel-lustre-headers-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1391     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-common-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1392     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1393
1394     echo $kernel_extra_version
1395     return 0
1396
1397 }
1398
1399 # build OFED
1400 # globals used:
1401 #    TOPDIR
1402 #    REUSEBUILD, USE_BUILD_CACHE
1403 #    CONFIGURE_FLAGS
1404
1405 build_ofed() {
1406     local linux="$1"
1407     local ofed_version="$2"
1408
1409     # if an ofed version is given, then it means use OFED proper,
1410     # not any vendor specific "inkernel" version
1411     if [ -z "$ofed_version" ]; then
1412         return 0
1413     fi
1414
1415     if [ "$ofed_version" = "inkernel" ]; then
1416         # see if there is a distro specific override for this and use
1417         # that if it exists
1418         # XXX we need to better integrate a distro specific override with
1419         #     the rest of this function so that all of the reuse cache
1420         #     stuff is leveraged given that 80% of this function is reuse
1421         if type -p build_ofed-${DISTRO}; then
1422             local ofed_location
1423             ofed_location=$(build_ofed-${DISTRO} ${STDOUT})
1424             local rc=${PIPESTATUS[0]}
1425             CONFIGURE_FLAGS="--with-o2ib=${ofed_location} ${CONFIGURE_FLAGS}"
1426             return $rc
1427         else
1428             return 0
1429         fi
1430     fi
1431
1432     # build kernel-ib
1433     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1434         local REUSE_SIGNATURE=$({ echo "$ofed_version";
1435                                   echo "$(find_linux_release ${linux})";
1436                                   cat "${linux}/include/linux/autoconf.h"; } |
1437                                 md5sum | cut -d" " -f1)
1438         # see if we can link to the reuse pool
1439         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1440         #       "library"
1441         local CAN_LINK_FOR_REUSE=false
1442         touch $REUSEBUILD/$$
1443         if cp -al $REUSEBUILD/$$ $TOPDIR/; then
1444             CAN_LINK_FOR_REUSE=true
1445         fi
1446         rm $REUSEBUILD/$$
1447     fi
1448
1449     if ! $USE_BUILD_CACHE || ! reuse ofed "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1450                                    "$REUSE_SIGNATURE"; then
1451         if [ -n "$REUSE_SIGNATURE" ]; then
1452             # stash away the existing built articles for a moment
1453             mkdir bak
1454             mv {BUILD,{S,}RPMS,S{OURCE,PEC}S} bak
1455             function mv_back {
1456                 pushd bak
1457                 find . | cpio -pudlm ..
1458                 popd
1459                 rm -rf bak
1460             }
1461             create_rpmbuild_dirs
1462         fi
1463         # build it
1464         build_kernel_ib "${linux}"
1465
1466         if [ -z "$REUSE_SIGNATURE" ]; then
1467             echo "No reuse signature was caculated so not storing the built ofed"
1468         else
1469             # store the resulting RPM build tree for future use
1470             echo "Storing the built ofed for future reuse"
1471             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
1472                                  "ofed" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1473                                  "$CAN_LINK_FOR_REUSE"; then
1474                 error "Failed to store OFED RPMS for reuse"
1475                 mv_back
1476                 return 1
1477             fi
1478             # put the stuff we stashed away back
1479             mv_back
1480         fi
1481     fi
1482
1483     pushd "$TOPDIR" >/dev/null
1484     rm -rf kernel-ib-devel
1485     mkdir kernel-ib-devel
1486     cd kernel-ib-devel
1487     # the actual ofed RPMs don't have the -rc$n or -$date string appened that
1488     # might be present on the file
1489     local linuxrelease=$(find_linux_release "$linux")
1490     ofed_version=$(echo $ofed_version |
1491                    sed -re 's/-(20[0-9]{6,6}-[0-9]{4,4}|rc[0-9]*)$//')
1492     local rpm=$(ls $TOPDIR/RPMS/*/kernel-ib-devel-${ofed_version}-${linuxrelease//-/_}.*.rpm)
1493     if ! rpm2cpio < $rpm | cpio -id; then
1494         fatal 1 "could not unpack the kernel-ib-devel rpm."
1495     fi
1496     CONFIGURE_FLAGS="--with-o2ib=$(pwd)/usr/src/ofa_kernel ${CONFIGURE_FLAGS}"
1497     popd >/dev/null
1498
1499 }
1500
1501 build_with_srpm() {
1502
1503     if ! $PATCHLESS; then
1504         local kernel_extra_version
1505         if ! kernel_extra_version=$(build_kernel_with_srpm ${STDOUT}); then
1506             fatal 1 "Failed to build the kernel from it's SRPM"
1507         fi
1508
1509         for arch in $BUILD_ARCHS; do
1510             local kernel_devel_rpm
1511             if ! kernel_devel_rpm=$(find_rpm "$TOPDIR/RPMS/$arch/" provides "^$(devel_kernel_name $KERNEL_LUSTRE_NAMING) ="); then
1512                 fatal 1 "Failed to find a kernel development RPM in $TOPDIR/RPMS/$arch/"
1513             fi
1514
1515             # install the -devel RPM in preparation for modules builds
1516             if ! lnxrel="$kernel_extra_version" unpack_linux_devel_rpm \
1517                            "$TOPDIR/RPMS/$arch/$kernel_devel_rpm"; then
1518                 fatal 1 "Could not find the Linux tree in $TOPDIR/RPMS/$arch/$kernel_devel_rpm"
1519             fi
1520         done
1521     else
1522         # need to find and unpack the vendor's own kernel-devel for patchless
1523         # client build
1524         local kernelrpm
1525         if ! kernelrpm=$(find_linux_rpm "-$DEVEL_KERNEL_TYPE"); then
1526             fatal 1 "Could not find the kernel-$DEVEL_KERNEL_TYPE RPM in ${KERNELRPMSBASE}/${lnxmaj}/${DISTRO}"
1527         fi
1528         if ! lnxrel="$lnxrel" unpack_linux_devel_rpm "$kernelrpm" "-"; then
1529             fatal 1 "Could not find the Linux tree in $kernelrpm"
1530         fi
1531     fi
1532
1533     # ~sigh~  have to make copies of and modify some of the rpm
1534     # infrastructure files so that find-requires can find our unpacked
1535     # kernel-devel artifacts
1536     cp $RPM_HELPERS_DIR/{symset-table,find-requires{,.ksyms}} .
1537     FIND_REQUIRES="$(pwd)/find-requires"
1538     chmod 755 {symset-table,find-requires{,.ksyms}}
1539     local tmp="$(pwd)"
1540     tmp="${tmp//\//\\/}"
1541     ed find-requires <<EOF
1542 1a
1543 set -x
1544 .
1545 /|.*find-requires.ksyms/s/|/| bash -x/
1546 g/ [^ ]*\/\(find-requires\.ksyms\)/s// $tmp\/\1/g
1547 wq
1548 EOF
1549     ed find-requires.ksyms <<EOF
1550 1a
1551 set -x
1552 .
1553 g/\/.*\/\(symset-table\)/s//$tmp\/\1/g
1554 wq
1555 EOF
1556     ed symset-table <<EOF
1557 1a
1558 set -x
1559 .
1560 g/\(\/boot\/\)/s//$tmp\/reused\1/g
1561 g/\(\/usr\/src\/kernels\/\)/s//$tmp\/reused\1/g
1562 wq
1563 EOF
1564
1565     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1566         fatal 1 "error building OFED"
1567
1568     # now build Lustre
1569     if build_lustre "$LINUX" "$LINUXOBJ"; then
1570         # the build worked.  resolve any symlinked files (i.e. from reuse)
1571         # in RPMS/$arch to real files so that that that huge mess of
1572         # complication known as LTS can copy them yet somewhere else.
1573         # is it any wonder this whole process is so damn so?  anyone ever
1574         # heard of hardlinks?  it's this cool new thing that allows you save
1575         # tons of time and space by creating... well you can go read about
1576         # them if you have not heard about them yet.
1577         # can i say how much the implemenation of all of this really impedes
1578         # RPM reuse?
1579         local dir
1580         for dir in RPMS/*; do
1581             pushd $dir
1582             for file in $(ls); do
1583                 if [ -h $file ]; then
1584                     cp $file foo
1585                     mv foo $file
1586                 fi
1587             done
1588             popd
1589         done
1590         # also, for i?86, make sure all of the RPMs are in RPMS/$TARGET_ARCH
1591         # as that's where LTS expects to find them
1592         for dir in RPMS/*; do
1593             if [ $dir = RPMS/$TARGET_ARCH ]; then
1594                 continue
1595             fi
1596             pushd $dir
1597             local files=$(ls)
1598             if [ -n "$files" ]; then
1599                 cp -al $files ../$TARGET_ARCH
1600             fi
1601             popd
1602         done
1603     else
1604         return 1
1605     fi
1606
1607 }
1608
1609 create_rpmbuild_dirs() {
1610
1611     [ -d RPMS ] || mkdir RPMS
1612     for arch in $BUILD_ARCHS; do
1613         if [[ $arch = i?86 ]]; then
1614             # some stupidity in the sles11 kernel spec requires an RPMS/i386
1615             # even if the target arch is i686
1616             [ -d RPMS/i386 ] || mkdir RPMS/i386
1617         fi
1618         [ -d RPMS/$arch ] || mkdir RPMS/$arch
1619     done
1620     [ -d BUILD ] || mkdir BUILD
1621     [ -d SOURCES ] || mkdir SOURCES
1622     [ -d SPECS ] || mkdir SPECS
1623     [ -d SRPMS ] || mkdir SRPMS
1624
1625 }
1626
1627 new_list() {
1628
1629     echo ""
1630
1631 }
1632
1633 add_list() {
1634     local list="$1"
1635     local item="$2"
1636
1637     echo "$list $item"
1638
1639 }
1640
1641 is_list_member() {
1642     local list="$1"
1643     local item="$2"
1644
1645     [[ $list\  == *\ $item\ * ]]
1646
1647 }
1648
1649 #########################################################################
1650 # Generate a backtrace through the call stack.
1651 #
1652 # Input: None
1653 # Output: None
1654 #########################################################################
1655 backtrace() {
1656     local strip=${1:-1}
1657
1658     local funcname="" sourcefile="" lineno="" n
1659
1660     echo "Call stack: (most recent first)"
1661     for (( n = $strip ; n < ${#FUNCNAME[@]} ; ++n )) ; do
1662         funcname=${FUNCNAME[$n - 1]}
1663         sourcefile=$(basename ${BASH_SOURCE[$n]})
1664         lineno=${BASH_LINENO[$n - 1]}
1665         if [ $n = 1 ]; then
1666             let lineno-=11
1667         fi
1668         # Display function arguments
1669         if [[ ! -z "${BASH_ARGV[@]}" ]]; then
1670             local args newarg j p=0
1671             for (( j = ${BASH_ARGC[$n - 1]}; j > 0; j-- )); do
1672                 newarg=${BASH_ARGV[$j + $p - 1]}
1673                 args="${args:+${args} }'${newarg}'"
1674             done
1675             let p+=${BASH_ARGC[$n - 1]}
1676         fi
1677         echo "  ${funcname} ${args:+${args} }at ${sourcefile}:${lineno}"
1678     done
1679
1680     echo
1681     echo "BEGIN BACKTRACE"
1682
1683     #echo ${BASH_LINENO[*]}
1684     #echo ${BASH_SOURCE[*]}
1685     #echo ${FUNCNAME[*]}
1686     local i=$((${#FUNCNAME[@]} - 1))
1687     while [ $i -ge 0 ]; do
1688         local lineno=${BASH_LINENO[$i]}
1689         if [ $i = 0 ]; then
1690             let lineno-=11
1691         fi
1692         local SOURCELINE="${BASH_SOURCE[$i + 1]}:${lineno}"
1693         # Can't figure out how to get function args from other frames...
1694         local FUNCTION="${FUNCNAME[$i]}()"
1695         echo "$SOURCELINE:$FUNCTION"
1696         i=$((i - 1))
1697     done
1698
1699     echo "END BACKTRACE"
1700
1701     echo $BACKTRACE
1702
1703 }
1704
1705 seen_list=$(new_list)
1706 trap 'set +x;
1707 echo "An unexpected error has occurred at ${BASH_SOURCE[0]##*/}:$((LINENO-1)).
1708 Unfortunately the above line number in the message may or may not be correct,
1709 but details have been send to the lbuild maintainer.  Attempting to continue."; (echo "Untrapped error"
1710 echo
1711 # have we seen this one
1712 echo "checking seen list for ${BASH_SOURCE[0]}:${BASH_LINENO[0]}"
1713
1714 if is_list_member "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}"; then
1715   echo "seen this one already"
1716 else
1717   seen_list=$(add_list "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}")
1718 fi
1719 backtrace
1720 echo
1721 echo "Environment:"
1722 set
1723 ) | mail -s "Untrapped error at ${BASH_SOURCE[0]##*/}:$((LINENO-15)) on $HOSTNAME" brian@sun.com >&2; set $xtrace' ERR
1724 set -E
1725
1726 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
1727
1728 options=$(getopt -o d:D:h -l kerneltree:,distro:,kernelrpm:,reusebuild:,patchless,ldiskfs,ccache,reuse:,norpm,disable-datestamp,external-patches:,timestamp:,extraversion:,kerneldir:,linux:,lustre:,nodownload,nosrc,ofed-version:,publish,release,set-value:,src,stage:,tag:,target:,target-archs:,with-linux:,xen -- "$@")
1729
1730 if [ $? != 0 ]; then
1731     usage 1
1732 fi
1733
1734 eval set -- "$options"
1735
1736 while [ "$1" ]; do
1737     case "$1" in
1738         '')
1739             usage 1
1740             ;;
1741         --ccache)
1742             CCACHE='ccache'
1743             shift
1744             ;;
1745         -d)
1746             CVSROOT=$2
1747             shift 2
1748             ;;
1749         -D)
1750             DATE=$2
1751             shift 2
1752             ;;
1753         --external-patches)
1754             EXTERNAL_PATCHES=$2
1755             shift 2
1756             ;;
1757         --extraversion)
1758             EXTRA_VERSION=$2
1759             shift 2
1760             ;;
1761         --help | -h)
1762             usage 0
1763             ;;
1764         --kerneldir)
1765             KERNELDIR=$2
1766             shift 2
1767             ;;
1768         --kerneltree)
1769             if ! KERNELTREE=$(canon_path "$2"); then
1770                 fatal 1 "Could not determine the canonical location of $2"
1771             fi
1772             shift 2
1773             ;;
1774         --linux | --with-linux)
1775             if ! LINUX=$(canon_path "$2"); then
1776                 fatal 1 "Could not determine the canonical location of $2"
1777             fi
1778             shift 2
1779             ;;
1780         --distro)
1781             DISTRO=$2
1782             shift 2
1783             ;;
1784         --reuserpm)
1785             REUSERPM=$2
1786             shift 2
1787             ;;
1788         --reusebuild)
1789             if ! REUSEBUILD=$(canon_path "$2"); then
1790                 fatal 1 "Could not determine the canonical location of $2"
1791             fi
1792             shift 2
1793             ;;
1794         --norpm)
1795             NORPM=true
1796             shift
1797             ;;
1798         --ldiskfs)
1799             LDISKFSRPM=true
1800             shift
1801             ;;
1802         --patchless)
1803             PATCHLESS=true
1804             shift
1805             ;;
1806         --kernelrpm)
1807             if ! KERNELRPMSBASE=$(canon_path "$2"); then
1808                 fatal 1 "Could not determine the canonical location of $2"
1809             fi
1810             shift 2
1811             ;;
1812         --timestamp)
1813             TIMESTAMP=$2
1814             shift 2
1815             ;;
1816         --lustre)
1817             if ! LUSTRE=$(canon_filepath "$2"); then
1818                 fatal 1 "Could not determine the canonical location of $2"
1819             fi
1820             shift 2
1821             ;;
1822         --nodownload)
1823             DOWNLOAD=false
1824             shift 1
1825             ;;
1826         --nosrc)
1827             DO_SRC=false
1828             shift 1
1829             ;;
1830         --ofed-version)
1831             OFED_VERSION="$2"
1832             shift 2
1833             ;;
1834         --publish)
1835             shift
1836             ;;
1837         --release)
1838             RELEASE=true
1839             shift
1840             ;;
1841         --src)
1842             DO_SRC=true
1843             shift 1
1844             ;;
1845         --stage)
1846             STAGEDIR=$2
1847             shift 2
1848             ;;
1849         --tag)
1850             TAG=$2
1851             shift 2
1852             ;;
1853         --target)
1854             TARGET=$2
1855             shift 2
1856             ;;
1857         --target-archs)
1858             TARGET_ARCHS=$2
1859             shift 2
1860             ;;
1861         --disable-datestamp)
1862             USE_DATESTAMP=
1863             shift
1864             ;;
1865         --xen)
1866             XEN=true
1867             shift
1868             ;;
1869         --set-value)
1870             eval $2
1871             shift 2
1872             ;;
1873         --)
1874             shift
1875             # there are actually some lustre configure flags that we need to
1876             # handle ourselves (but we still give them to configure)
1877             if [[ \ $@\  == *\ --disable-tests\ * ]]; then
1878                 LUSTRE_TESTS=false
1879             fi
1880             CONFIGURE_FLAGS=$@
1881             CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-liblustre --enable-liblustre-tests"
1882             break
1883             ;;
1884         *)
1885             usage 1 "Unrecognized option: $1"
1886             ;;
1887     esac
1888 done
1889
1890 check_options
1891
1892 unpack_lustre
1893
1894 # XXX - should we _always_ get the buildid from the META file?  what are the
1895 # other (i.e. non-lustre-tarball use cases of lbuild)?
1896 BUILDID=$(sed -ne '/^BUILDID =/s/.*= *//p' lustre/META)
1897
1898 load_target
1899
1900 if [ -n "$OFED_VERSION" -a "$OFED_VERSION" != "inkernel" ]; then
1901     download_ofed
1902     unpack_ofed || fatal 1 "Error unpacking OFED tarball"
1903 fi
1904
1905 # make sure the RPM build environment is set up
1906 create_rpmbuild_dirs
1907
1908 # if an unpacked kernel source tree was given on the command line
1909 # just build lustre with it (nothing distro kernel specific here)
1910 if [ -n "$LINUX" ]; then
1911     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1912         fatal 1 "error building OFED"
1913     build_lustre "$LINUX" "$LINUXOBJ"
1914 else
1915     if [ -f "${0%/*}/lbuild-$DISTRO" ]; then
1916         source ${0%/*}/lbuild-$DISTRO
1917
1918         build_with_srpm || fatal 1 "Failed to build_with_srpm"
1919     else
1920         EXTRA_VERSION_DELIMITER=${EXTRA_VERSION_DELIMITER:-"-"}
1921         source ${0%/*}/lbuild.old_school
1922
1923         old_school_download_kernel
1924
1925         build_success=false
1926         if $PATCHLESS; then
1927             patchless_build_sequence && build_success=true
1928         else
1929             [ "$DISTRO" = "sles9" ] && build_sequence_rpm_reuse && build_success=true
1930             if ! $build_success; then
1931                 build_sequence_reuse && build_success=true
1932                 if ! $build_success; then
1933                     build_sequence && build_success=true
1934                     if $build_success; then
1935                         store_for_reuse || echo "Cannot store for future reuse"
1936                     fi
1937                 fi
1938             fi
1939         fi
1940         ( $build_success ) || fatal 1 "Cannot build lustre"
1941     fi
1942 fi
1943
1944 stage