#!/bin/bash
#
# Copyright (c) 2006 Mellanox Technologies. All rights reserved.
#
# This Software is licensed under one of the following licenses:
#
# 1) under the terms of the "Common Public License 1.0" a copy of which is
#    available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/cpl.php.
#
# 2) under the terms of the "The BSD License" a copy of which is
#    available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/bsd-license.php.
#
# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
#    copy of which is available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/gpl-license.php.
#
# Licensee has the right to choose one of the above licenses.
#
# Redistributions of source code must retain the above copyright
# notice and one of the license notices.
#
# Redistributions in binary form must reproduce both the above copyright
# notice, one of the license notices in the documentation
# and/or other materials provided with the distribution.
#
#  $Id: build.sh 9602 2006-09-21 12:27:03Z vlad $
#
# Description: OFED RPMs build script

usage()
{
cat << EOF

    `basename $0` [ -c <config_file> ]

EOF
}

unalias -a

cd ${0%*/*}
CWD=`pwd`

INTERACTIVE=1

if [ ! -e ./build_env.sh ]; then
    echo "ERROR: $CWD/build_env.sh is missing"
    exit 1
fi

while [ $# -gt 0 ]
do
    case $1 in
            -c)
                shift
                CONFIG=$1
                INTERACTIVE=0
            ;;
            *)
                usage
                exit 1
            ;;
    esac
    shift
done

. $CWD/build_env.sh


# Set default values
SELECTED_PACKAGES=""
OPENIB_PACKAGES=""
EXTRA_PACKAGES=""
IB_EXTRA_PACKAGES=""
WITH_PACKAGES=""
WITH_PACKAGES32=""
WITH_KERNEL_PACKAGES=""
WITH_BIN_PACKAGES=""
WITH_BIN_PACKAGES32=""
MEMTRACK=0
MADEYE=0

build_kernel_ib=0
build_kernel_ib_devel=0
modprobe_update=1
include_ipoib_conf=1
apply_hpage_patch=1
build_32bit=0

# Environment variables definition
BUILD_COUNTER=0
EXISTING_RPMS=0


# Create selected from openib RPM packages (ib-verbs, ib-ipoib, ...)
openib()
{
#        if ! check_build_req openib err; then
#            exit 2
#        fi    
        cd $BUILD_TMP
        local OPENIB_SRCDIR=$BUILD_TMP/`echo ${OPENIB_SOURCE##*/} | sed -e 's/.tgz//' | tr -d '[:space:]'`
        echo
        echo "Building ${OPENIB_NAME} RPMs. Please wait..."
        echo

        for package in ${OPENIB_PACKAGES}
        do
            case ${package} in
                kernel-ib)
                    build_kernel_ib=1
                ;;
                kernel-ib-devel)
                    build_kernel_ib_devel=1
                ;;
                libo*sm*|opensm)
                    if ! ( echo "${WITH_PACKAGES}" | grep "with-opensm" > $NULL 2>&1 ); then
                        WITH_PACKAGES="${WITH_PACKAGES} --with-opensm"
                    fi
                ;;
                *-devel|*-utils)
                ;;
                mstflint|tvflash)
                    case $ARCH in
                        ppc64)
                        WITH_BIN_PACKAGES32="${WITH_BIN_PACKAGES32} --with-${package}"
                        ;;
                        *)
                        WITH_BIN_PACKAGES="${WITH_BIN_PACKAGES} --with-${package}"
                        ;;
                    esac
                ;;
                perftest)
                    WITH_BIN_PACKAGES="${WITH_BIN_PACKAGES} --with-${package}"
                ;;
                *)
                WITH_PACKAGES="${WITH_PACKAGES} --with-${package}"
                ;;
            esac
        done

        if [ $build_32bit -eq 1 ]; then
            WITH_PACKAGES32="${WITH_PACKAGES} ${WITH_PACKAGES32} ${WITH_BIN_PACKAGES32}"
        fi

        if [ -n "${WITH_BIN_PACKAGES32}" ] && [ $build_32bit -eq 0 ]; then
            build_32bit=1
            WITH_PACKAGES32="${WITH_BIN_PACKAGES32}"
        fi

        if [ ! -n "$OPENIB_KERNEL_PACKAGES" ]; then
            # OPENIB_KERNEL_PACKAGES="$BASIC_IB_KERNEL_PACKAGES"
            OPENIB_KERNEL_PACKAGES=""
        fi

        for package in ${OPENIB_KERNEL_PACKAGES}
        do
            case ${package} in
                ib_verbs)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-core-mod --with-user_mad-mod --with-user_access-mod --with-addr_trans-mod"
                ;;
                ib_mthca)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-mthca-mod"
                ;;
                ib_ipath)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-ipath_inf-mod"
                ;;
                ib_ehca)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-ehca-mod"
                ;;
                ib_ipoib)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-ipoib-mod"
                ;;
                ib_sdp)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-sdp-mod"
                ;;
                ib_srp)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-srp-mod"
                ;;
                ib_iser)
                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-iser-mod"
                ;;
#                ib_rds)
#                    WITH_KERNEL_PACKAGES="${WITH_KERNEL_PACKAGES} --with-rds-mod"
#                ;;
                *)
                    warn_echo "Unknown package ${package}"
                ;;
            esac
        done

        for param in ${OPENIB_PARAMS}
        do
            case ${param} in
                --with-modprobe)
                    modprobe_update=1
                ;;
                --without-modprobe)
                    modprobe_update=0
                ;;
                --memtrack|--with-memtrack)
                    MEMTRACK=1
                ;;
                --without-memtrack)
                    MEMTRACK=0
                ;;
                --with-madeye|--with-madeye-mod)
                    MADEYE=1
                ;;
                --without-madeye|--without-madeye-mod)
                    MADEYE=0
                ;;
                --with-ipoibconf)
                    include_ipoib_conf=1
                ;;
                --without-ipoibconf)
                    include_ipoib_conf=0
                ;;
                --with-hpage-patch)
                    apply_hpage_patch=1
                ;;
                --without-hpage-patch)
                    apply_hpage_patch=0
                ;;
            esac
        done

        # ex "${BUILDENV} ${OPENIB_SRCDIR}/build_rpm.sh --topdir ${RPM_DIR} --prefix ${STACK_PREFIX} --build_root ${BUILD_ROOT} --packages ${OPENIB_KERNEL_PACKAGES} -- ${WITH_PACKAGES} -kver ${K_VER} --ksrc ${K_SRC} ${OPENIB_PARAMS}"

    # Create openib src.rpm if not exist
    srcrpm=$(ls -1 ${SRPMS}/openib-*.src.rpm 2> $NULL)
    if [ ! -n "${srcrpm}" ]; then
	tar xzf  ${OPENIB_SOURCE} openib-1.1/ofed_scripts/openib.spec
	tar xzf  ${OPENIB_SOURCE} openib-1.1/openib.spec
	chown root:root openib-1.1/ofed_scripts/openib.spec openib-1.1/openib.spec
	cp ${OPENIB_SOURCE} ${RPM_DIR}/SOURCES
	rpmbuild -bs --define "_topdir ${RPM_DIR}" openib-1.1/openib.spec
        srcrpm=$(ls -1 ${RPM_DIR}/SRPMS/openib-*.src.rpm 2> $NULL)
        ex "$MV -f ${srcrpm} $SRPMS"
    fi

    if [ ! -n "${WITH_PACKAGES32}" ]; then
        configure_options32="%{nil}"
    else
        configure_options32="${WITH_PACKAGES32}"
    fi

    if [ ! -n "${WITH_PACKAGES}" ] && [ ! -n "${WITH_KERNEL_PACKAGES}" ] && [ ! -n "${WITH_BIN_PACKAGES}" ]; then
        configure_options="%{nil}"
    else
        configure_options="${WITH_PACKAGES} ${WITH_BIN_PACKAGES} ${WITH_KERNEL_PACKAGES}"
    fi

    if [ $MEMTRACK -eq 1 ]; then
        configure_options="$configure_options --with-memtrack"
    fi

    if [ $MADEYE -eq 1 ]; then
        configure_options="$configure_options --with-madeye-mod"
    fi

    if [ ${apply_hpage_patch} -eq 0 ]; then
        configure_options="$configure_options --without-hpage-patch"
    fi

        srcrpm=$(ls -1 ${SRPMS}/openib-*.src.rpm 2> $NULL)
        ex  rpmbuild --rebuild --define \'_topdir ${RPM_DIR}\' \
                --define \'_prefix ${STACK_PREFIX}\' \
                --define \'build_root  ${BUILD_ROOT}\' \
                --define \'configure_options ${configure_options}\' \
                --define \'configure_options32 ${configure_options32}\' \
                --define \'KVERSION ${K_VER}\' \
                --define \'KSRC ${K_SRC}\' \
                --define \'build_kernel_ib ${build_kernel_ib}\' \
                --define \'build_kernel_ib_devel ${build_kernel_ib_devel}\' \
                --define \'NETWORK_CONF_DIR ${NETWORK_CONF_DIR}\' \
                --define \'modprobe_update ${modprobe_update}\' \
                --define \'include_ipoib_conf ${include_ipoib_conf}\' \
                --define \'build_32bit ${build_32bit}\' \
                ${srcrpm}
        rpms=""
        for package in ${OPENIB_PACKAGES}
        do
            rpm=""
            if ( ls -1 ${RPM_DIR}/RPMS/$build_arch/${package}-*.${build_arch}.rpm > $NULL 2>&1 ); then
                rpm=$(ls -1 ${RPM_DIR}/RPMS/$build_arch/${package}-*.${build_arch}.rpm 2> $NULL)
                rpms="$rpms $rpm"
                let BUILD_COUNTER++
            fi
        done
        rpms=$(echo $rpms | tr -s ' ' '\n' | sort -n | uniq | tr -s '\n' ' ')
        ex "$MV -f ${rpms} $RPMS"
        
        return 0
}

oiscsi-iser()
{
        if ! check_build_req oiscsi_iser err; then
            return 2
        fi    

        echo
        echo "Building oiscsi-iser RPM. Please wait..."
        echo

        if [[ -z $OISCSI_ISER_NAME || -z $OISCSI_ISER_VERSION ]]; then
            err_echo "Failed to define OISCSI_ISER RPM version"
            return 1
        fi
        ex rpmbuild --rebuild --define \'_topdir ${RPM_DIR}\' ${OISCSI_ISER_SRC_RPM}

        ex "$MV -f ${RPM_DIR}/RPMS/$build_arch/${OISCSI_ISER_NAME}-${OISCSI_ISER_VERSION}.${build_arch}.rpm $RPMS"
        let BUILD_COUNTER++
        
        return 0
}

ofed-docs()
{
        if [[ -z $DOCS_NAME || -z $DOCS_VERSION ]]; then
            err_echo "Failed to define DOCS RPM version"
            return 1
        fi
        ex rpmbuild --rebuild --target=noarch --define \'_topdir ${RPM_DIR}\' --define \'_prefix ${STACK_PREFIX}\' ${DOCS_SRC_RPM}

        ex "$MV -f ${RPM_DIR}/RPMS/noarch/${DOCS_NAME}-${DOCS_VERSION}.noarch.rpm $RPMS"
        let BUILD_COUNTER++
        return 0
}

ofed-scripts()
{
        if [[ -z $SCRIPTS_NAME || -z $SCRIPTS_VERSION ]]; then
            err_echo "Failed to define SCRIPTS RPM version"
            return 1
        fi
        ex rpmbuild --rebuild --target=noarch --define \'_topdir ${RPM_DIR}\' --define \'_prefix ${STACK_PREFIX}\' ${SCRIPTS_SRC_RPM}

        ex "$MV -f ${RPM_DIR}/RPMS/noarch/${SCRIPTS_NAME}-${SCRIPTS_VERSION}.noarch.rpm $RPMS"
        let BUILD_COUNTER++
        return 0
}

ibutils()
{
#        if ! check_build_req ibutils err; then
#            return 2
#        fi    

        echo
        echo "Building ibutils RPM. Please wait..."
        echo

        if [[ -z $IBUTILS_NAME || -z $IBUTILS_VERSION ]]; then
            err_echo "Failed to define IBUTILS RPM version"
            return 1
        fi

        local libdir
        case ${ARCH} in
            i?86|ia64)
            libdir=${STACK_PREFIX}/lib
            ;;
            *)
            libdir=${STACK_PREFIX}/lib64
            ;;
        esac

        ex rpmbuild --rebuild \
        --define \'_topdir ${RPM_DIR}\' \
        --define \'configure_options --prefix=${STACK_PREFIX} --mandir=${STACK_PREFIX}/man --cache-file=${BUILD_ROOT}/ibutils.cache --with-osm=${BUILD_ROOT}${STACK_PREFIX}\' \
        --define \'_prefix ${STACK_PREFIX}\' \
        --define \'_libdir ${libdir}\' \
        --define \'_mandir %{_prefix}/man\' \
        --define \'build_root ${BUILD_ROOT}\' \
        ${IBUTILS_SRC_RPM}

        ex "$MV -f ${RPM_DIR}/RPMS/$build_arch/${IBUTILS_NAME}-${IBUTILS_VERSION}.${build_arch}.rpm $RPMS"
        let BUILD_COUNTER++
        
        return 0

}

# OSU MPI installation
mpi_osu()
{
#        if ! check_build_req mpi_osu err; then
#            return 2
#        fi    

        echo
        echo "Building OSU RPM. Please wait..."
        echo

        for mpi_comp in ${MPI_COMPILER_mpi_osu}
        do
            echo "Using ${mpi_comp} compiler"
            OSU_RPM=${MPI_OSU_MPICH_NAME}_${mpi_comp}-${MPI_OSU_MPICH_VER}-${MPI_OSU_MPICH_REL}.${build_arch}.rpm
            cd $BUILD_TMP
            local OSU_SRCDIR=$BUILD_TMP/`echo ${OSU_SOURCE##*/} | sed -e 's/.tgz//' | tr -d '[:space:]'`
            ex_silent "$RM -f ${OSU_SOURCE##*/}"
            ex_silent "$RM -rf ${OSU_SRCDIR}"
            ex_silent "tar xzvf ${OSU_SOURCE}"

            ex "${OSU_SRCDIR}/build_rpm.sh --topdir ${RPM_DIR} --install_root ${BUILD_ROOT} --prefix ${STACK_PREFIX} --driver_home ${BUILD_ROOT}/${STACK_PREFIX} --comp ${mpi_comp}"
            ex "$MV -f ${RPM_DIR}/RPMS/$build_arch/${OSU_RPM} $RPMS"
            ex_silent "$RM -rf ${OSU_SRCDIR}"
            ex_silent cd -
            let BUILD_COUNTER++
        if [ "$mpitests" == "y" ]; then
            echo
            echo "Building mpitests RPM over OSU MPI using ${mpi_comp} compiler. Please wait..."
            echo
            MPITESTS_RPM=${MPITESTS_NAME}_${MPI_OSU_MPICH_NAME}_${mpi_comp}-${MPITESTS_VERSION}.${build_arch}.rpm
            ex rpmbuild --rebuild \
            --define \'_topdir ${RPM_DIR}\' \
            --define \'_name ${MPITESTS_NAME}_${MPI_OSU_MPICH_NAME}_${mpi_comp}\' \
            --define \'path_to_mpihome ${STACK_PREFIX}/mpi/${mpi_comp}/mvapich-${MPI_OSU_VER}\' \
            --define \'buildroot ${BUILD_ROOT}\' \
            --define \'stack_prefix ${STACK_PREFIX}\' \
            $MPITESTS_SRC_RPM
            ex "$MV -f ${RPM_DIR}/RPMS/$build_arch/${MPITESTS_RPM} $RPMS"
            let BUILD_COUNTER++
        fi

        done        
        return 0
}

openmpi()
{
    echo
    echo "Open MPI RPM will be created during the installation process"
    echo
    return 0
}


build_packages()
{
    # # Install packages required for ${PACKAGE} operation
    # # Like ( swig1.1p5, tcl8.3.2 )
    # install_packages

    echo   
    echo "Building InfiniBand Software RPMs. Please wait..."
    echo
    
    if [[ -n "$OPENIB_PACKAGES" ]]; then
            # Build openib
            openib
    fi        
    
    for package in $EXTRA_PACKAGES
    do
        case $package in
            mpitests)
            # Nothing to be done: RPM created/installed from OSU/Open MPI
            ;;
            *)
            $package
            ;;
        esac
    done

    return 0
}

# Set configuration parameters and perform basic checks
pre_build()
{
        # Check that user is root
        check_user
        
#        # Check for InfiniBand software of other vendors
#        local vendors="topspin|iview_fm|ibhost-hpc"
#        local vrpms=""
#        
#        vrpms=$($RPM -qa | grep -E "${vendors}")
#        if [ -n "$vrpms" ]; then
#            echo
#            err_echo "You must remove the following InfiniBand software before continuing:"
#            echo
#            echo "$vrpms"
#            echo
#            exit 9
#        fi

}

# Run Build in interactive mode
interactive()
{
           show_menu "build_menu"
        	
                read ans_build
                case $ans_build in
                        1)
                                view_readme
                        ;;    
                        2)
                                if ! select_packages; then
                                   interactive
                                fi    
                                set_package_deps
                                check_build_dependencies
                                
                                include_ifcfg

                                echo
                                echo "Going to build ${PACKAGE} RPMs"
                                echo "The RPM build process requires a temporary directory"
                                echo
                                read -p "Please enter the temporary directory [${BUILD_ROOT}]:"
                                BUILD_ROOT=${REPLY:-$BUILD_ROOT}
                                
                                if [ "${BUILD_ROOT}" != "${BUILD_ROOT_DFT}" ]; then
                                       BUILD_ROOT=${BUILD_ROOT}/${PACKAGE}
                                fi
                                
                                [ -d $BUILD_ROOT ] && $RM -rf $BUILD_ROOT
                                
                                check_space_req "$BUILD_SPACE_REQ" "$BUILD_ROOT"
                                
                                echo
                                echo "The build process requires the target installation directory."
                                echo
                                echo "   Note: The build process does not create nor touch the target installation directory."
                                echo "         The directory will only be created when you actually install the ${PACKAGE} RPMs."
                                echo
                                read -p "Please enter the ${PACKAGE} installation directory [${STACK_PREFIX}]:"
                                STACK_PREFIX=${REPLY:-$STACK_PREFIX}
                                echo   
                                # Set  parameters with new values
                                . $CWD/build_env.sh
                                echo
                                pass_echo "Chosen temporary directory for ${PACKAGE} RPMs is: $BUILD_ROOT"
                                pass_echo "RPM packages will be stored under: $PKG_SOURCE_DIR/RPMS"
                                pass_echo "${PACKAGE} Software is configured to be installed under: ${STACK_PREFIX}"
                                echo
                                read -p "Do you want to continue? [Y/n]:" ans_r
                                if ! [[ "$ans_r" == "" || "$ans_r" == "y" || "$ans_r" == "Y" || "$ans_r" == "yes" ]]; then
                                    return 1
                                fi
                                
                                # Update CONFIG file
                                perl -ni -e "s@(BUILD_ROOT=).*@\$1${BUILD_ROOT}@; print" $CONFIG
                                perl -ni -e "s@(STACK_PREFIX=).*@\$1${STACK_PREFIX}@; print" $CONFIG

                                if [ ! -d "$BUILD_TMP" ]; then
                                   ex_silent "$MKDIR -p $BUILD_TMP"
                                fi
                                
                                echo
                                pass_echo "It may take up to 40 minutes to complete the installation process"
                                echo   
        
                                
                                if build_packages; then
                                    echo
                                    if [ $BUILD_COUNTER -gt 0 ]; then
                                       pass_echo "$BUILD_COUNTER packages were built"
                                    fi
                                    echo
                                    pass_echo "Build process finished ..."
                                
                                    echo
                                    read -p  "Do you want to remove the temporary build directory ${BUILD_ROOT}? [Y/n]:" ans_r
                                    if [[ "$ans_r" == "" || "$ans_r" == "y" || "$ans_r" == "Y" || "$ans_r" == "yes" ]]; then
                                        ex_silent "$RM -rf $BUILD_ROOT"
                                    fi
                                    
                                    getch
                                fi

                        ;;
                        Q|q)
                                close_log    
                                exit 0
                        ;;
                        *)
                                return 1
                        ;;
                esac
}

# Run Build in unattended mode
unattended()
{

    select_packages
    set_package_deps
    check_build_dependencies
    
    
    if [ ! -d  "$BUILD_ROOT" ]; then
        ex_silent "$MKDIR -p $BUILD_ROOT"
    fi
    
    check_space_req "$BUILD_SPACE_REQ" "$BUILD_ROOT"
    
    if [ ! -d "$BUILD_TMP" ]; then
       ex_silent "$MKDIR -p $BUILD_TMP"
    fi
    
    if build_packages; then
         echo
         if [ $BUILD_COUNTER -gt 0 ]; then
            pass_echo "$BUILD_COUNTER packages were built"
         fi
         if [ $EXISTING_RPMS -gt 0 ]; then
            pass_echo "$EXISTING_RPMS RPMs already exist"
         fi
         echo
         
         pass_echo "Build process finished ..."
    fi
        
    # Remove BUILD_TMP directory
    if [ "$BUILD_ROOT" == "${BUILD_ROOT_DFT}" ]; then
        ex_silent "$RM -rf $BUILD_ROOT"
    fi
    #     if [ $NEED_REBOOT -ne 0 ]; then
    #         echo
    #         echo    "Please reboot the system"
    #         echo
    #     fi
}

###
### Main
###

main()
{

        pre_build
         
        if [ $INTERACTIVE -eq 1 ]; then
            interactive
            if [ "$RPM_DIR" == "$RPM_DIR_DFT" ]; then
                ex_silent "$RM -rf $RPM_DIR"
            fi
       else
            unattended
        fi

        return 0
}

open_log
while true
do
    main
    if [ $INTERACTIVE -eq 0 ]; then
        exit 0
    fi    
done
