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