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