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