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