Updates docs for SR1 with final revision
[genesis.git] / fuel / ci / build.sh
old mode 100644 (file)
new mode 100755 (executable)
index e69de29..f8e164a
@@ -0,0 +1,473 @@
+#!/bin/bash
+set -e
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# stefan.k.berg@ericsson.com
+# jonas.bjurel@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+trap 'echo "Exiting ..."; \
+if [ -f ${LOCK_FILE} ]; then \
+   if [ $(cat ${LOCK_FILE}) -eq $$ ]; then \
+      rm -f ${LOCK_FILE}; \
+   fi; \
+fi;' EXIT
+
+############################################################################
+# BEGIN of usage description
+#
+usage ()
+{
+cat << EOF
+$0 Builds the Fuel@OPNFV stack
+
+usage: $0 [-s spec-file] [-c cache-URI] [-l log-file] [-f Flags] build-directory
+
+OPTIONS:
+  -s spec-file ($BUILD_SPEC), define the build-spec file, default ../build/config.mk
+  -c cache base URI ($BUILD_CACHE_URI), specifies the base URI to a build cache to be used/updated - the name is automatically generated from the md5sum of the spec-file, http://, ftp://, file://[absolute path] suported.
+
+  -l log-file ($BUILD_LOG), specifies the output log-file (stdout and stderr), if not specified logs are output to console as normal
+  -v version tag to be applied to the build result
+  -r alternative remote access method script/program. curl is default.
+  -t run small build-script unit test.
+  -T run large build-script unit test.
+  -f build flags ($BUILD_FLAGS):
+     o s: Do nothing, succeed
+     o f: Do nothing, fail
+     o t: run build unit tests
+     o i: run interactive (-t flag to docker run)
+     o P: Populate a new local cache and push it to the (-c cache-URI) cache artifactory if -c option is present, currently file://, http:// and ftp:// are supported
+     o d: Detatch - NOT YET SUPPORTED
+
+  build-directory ($BUILD_DIR), specifies the directory for the output artifacts (.iso file).
+
+  -h help, prints this help text
+
+Description:
+build.sh builds opnfv .iso artifact.
+To reduce build time it uses build cache on a local or remote location. The cache is rebuilt and uploaded if either of the below conditions are met:
+1) The P(opulate) flag is set and the -c cache-base-URI is provided, if -c is not provided the cache will stay local.
+2) If the cache is invalidated by one of the following conditions:
+   - The config spec md5sum does not compare to the md5sum for the spec which the cache was built.
+   - The git Commit-Id on the remote repos/HEAD defined in the spec file does not correspont with the Commit-Id for what the cache was built with.
+3) A valid cache does not exist on the specified -c cache-base-URI.
+
+The cache URI object name is fuel_cache-"md5sum(spec file)"
+
+Logging by default to console, but can be directed elsewhere with the -l option in which case both stdout and stderr is redirected to that destination.
+
+Built in unit testing of components is enabled by adding the t(est) flag.
+
+Return codes:
+ - 0 Success!
+ - 1-99 Unspecified build error
+ - 100-199 Build system internal error (not build it self)
+   o 101 Build system instance busy
+ - 200 Build failure
+
+Examples:
+build -c http://opnfv.org/artifactory/fuel/cache -d ~/jenkins/genesis/fuel/ci/output -f ti
+NOTE: At current the build scope is set to the git root of the repository, -d destination locations outside that scope will not work
+EOF
+}
+#
+# END of usage description
+############################################################################
+
+############################################################################
+# Begin of string xor function
+#
+function  xor()
+{
+      local res=(`echo "$1" | sed "s/../0x& /g"`)
+      shift 1
+      while [[ "$1" ]]; do
+            local one=(`echo "$1" | sed "s/../0x& /g"`)
+            local count1=${#res[@]}
+            if [ $count1 -lt ${#one[@]} ]
+            then
+                  count1=${#one[@]}
+            fi
+            for (( i = 0; i < $count1; i++ ))
+            do
+                  res[$i]=$((${one[$i]:-0} ^ ${res[$i]:-0}))
+            done
+            shift 1
+      done
+       printf "%02x" "${res[@]}"
+}
+#
+# END of string xor function
+############################################################################
+
+############################################################################
+# BEGIN of variables to customize
+#
+BUILD_BASE=$(readlink -e ../build/)
+RESULT_DIR="${BUILD_BASE}/release"
+BUILD_SPEC="${BUILD_BASE}/config.mk"
+CACHE_DIR="cache"
+LOCAL_CACHE_ARCH_NAME="fuel-cache"
+
+REMOTE_ACCESS_METHD=curl
+INCLUDE_DIR=../include
+#
+# END of variables to customize
+############################################################################
+
+############################################################################
+# BEGIN of script assigned variables
+#
+SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+LOCK_FILE="${SCRIPT_DIR}/.build.lck"
+CACHE_TMP="${SCRIPT_DIR}/tmp"
+TEST_SUCCEED=0
+TEST_FAIL=0
+UNIT_TEST=0
+UPDATE_CACHE=0
+POPULATE_CACHE=0
+RECURSIVE=0
+DETACH=0
+DEBUG=0
+INTEGRATION_TEST=0
+FULL_INTEGRATION_TEST=0
+INTERACTIVE=0
+BUILD_CACHE_URI=
+BUILD_SPEC=
+BUILD_DIR=
+BUILD_LOG=
+BUILD_VERSION=
+MAKE_ARGS=
+FUEL_GIT_SRC="$(make -f ../build/config.mk get-fuel-repo | cut -d " " -f1)"
+FUEL_GIT_BRANCH="$(make -f ../build/config.mk get-fuel-repo | cut -d " " -f2)"
+CACHE_MD5=$(md5sum ../build/cache.mk | cut -f1 -d " ")
+CONFIG_MD5=$(md5sum ../build/config.mk | cut -f1 -d " ")
+FUEL_COMMIT_ID=$(git ls-remote $FUEL_GIT_SRC -t $FUEL_GIT_BRANCH | cut -d $'\t' -f1)
+REMOTE_CACHE_ARCH_HASH_TMP="$(xor $CACHE_MD5 $CONFIG_MD5)"
+REMOTE_CACHE_ARCH_HASH="$(xor $REMOTE_CACHE_ARCH_HASH_TMP $FUEL_COMMIT_ID)"
+REMOTE_CACHE_ARCH_NAME="fuel_cache-$REMOTE_CACHE_ARCH_HASH"
+#
+# END of script assigned variables
+############################################################################
+
+############################################################################
+# BEGIN of include pragmas
+#
+source ${INCLUDE_DIR}/build.sh.debug
+#
+# END of include
+############################################################################
+
+############################################################################
+# BEGIN of main
+#
+while getopts "s:c:v:f:l:r:RtTh" OPTION
+do
+    case $OPTION in
+        h)
+            usage
+            rc=0
+            exit $rc
+            ;;
+
+        s)
+            BUILD_SPEC=${OPTARG}
+            ;;
+
+        c)
+            BUILD_CACHE_URI=${OPTARG}
+            ;;
+
+        l)
+            BUILD_LOG=${OPTARG}
+            ;;
+
+        v)
+            BUILD_VERSION=${OPTARG}
+            ;;
+
+        f)
+            BUILD_FLAGS=${OPTARG}
+            ;;
+
+        r)  REMOTE_ACCESS_METHD=${OPTARG}
+            ;;
+
+        R)
+            RECURSIVE=1
+            ;;
+
+        t)
+            INTEGRATION_TEST=1
+            ;;
+
+        T)
+            INTEGRATION_TEST=1
+            FULL_INTEGRATION_TEST=1
+            ;;
+
+        *)
+            echo "${OPTION} is not a valid argument"
+            rc=100
+            exit $rc
+            ;;
+    esac
+done
+
+if [ -z $BUILD_DIR ]; then
+    BUILD_DIR=$(echo $@ | cut -d ' ' -f ${OPTIND})
+fi
+
+for ((i=0; i<${#BUILD_FLAGS};i++)); do
+    case ${BUILD_FLAGS:$i:1} in
+        s)
+            rc=0
+            exit $rc
+            ;;
+
+        f)
+            rc=1
+            exit $rc
+            ;;
+
+        t)
+            UNIT_TEST=1
+            ;;
+
+        i)
+            INTERACTIVE=1
+            ;;
+
+        P)
+            POPULATE_CACHE=1
+            ;;
+
+        d)
+            DETACH=1
+            echo "Detach is not yet supported - exiting ...."
+            rc=100
+            exit $rc
+            ;;
+
+        D)
+            DEBUG=1
+            ;;
+
+        *)
+            echo "${BUILD_FLAGS:$i:1} is not a valid build flag - exiting ...."
+            rc=100
+            exit $rc
+            ;;
+    esac
+done
+
+if [ ${INTEGRATION_TEST} -eq 1 ]; then
+    integration-test
+    rc=0
+    exit $rc
+fi
+
+if [ ! -f ${BUILD_SPEC} ]; then
+    echo "spec file does not exist: $BUILD_SPEC - exiting ...."
+    rc=100
+    exit $rc
+fi
+
+if [ -z ${BUILD_DIR} ]; then
+    echo "Missing build directory - exiting ...."
+    rc=100
+    exit $rc
+fi
+
+if [ ! -z ${BUILD_LOG} ]; then
+    if [[ ${RECURSIVE} -ne 1 ]]; then
+        set +e
+        eval $0 -R $@ > ${BUILD_LOG} 2>&1
+        rc=$?
+        set -e
+        if [ $rc -ne 0]; then
+            exit $rc
+        fi
+    fi
+fi
+
+if [ ${TEST_SUCCEED} -eq 1 ]; then
+    sleep 1
+    rc=0
+    exit $rc
+fi
+
+if [ ${TEST_FAIL} -eq 1 ]; then
+    sleep 1
+    rc=1
+    exit $rc
+fi
+
+if [ -e ${LOCK_FILE} ]; then
+    echo "A build job is already running, exiting....."
+    rc=101
+    exit $rc
+fi
+
+echo $$ > ${LOCK_FILE}
+
+if [ ! -z ${BUILD_CACHE_URI} ]; then
+    if [ ${POPULATE_CACHE} -ne 1 ]; then
+        rm -rf ${CACHE_TMP}/cache
+        mkdir -p ${CACHE_TMP}/cache
+        echo "Downloading cache archive ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME} ..."
+        set +e
+        ${REMOTE_ACCESS_METHD} -o ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME}.tgz
+        rc=$?
+        set -e
+        if [ $rc -ne 0 ]; then
+            echo "Remote cache does not exist, or is not accessible - a new cache will be built ..."
+            POPULATE_CACHE=1
+        else
+            echo "Unpacking cache archive ..."
+            set +e
+            tar -C ${CACHE_TMP}/cache -xvf ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz
+            rc=$?
+            set -e
+            if [ $rc -ne 0 ]; then
+                echo "WARNING: The cache seems to be corrupt or has trailing garbage, will try to use brute force"
+                echo "Info about the cache below:"
+                set +e
+                file ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz
+                tar -C ${CACHE_TMP}/cache -tvf ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz
+                set -e
+                echo "Current time is: `date`"
+                set +e
+                pushd ${CACHE_TMP}/cache
+                gunzip -dcq ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz | tar -xvf -
+                rc=$?
+                set -e
+                popd
+                if [ $rc -ne 0 ]; then
+                    echo "ERROR: Not able to resolve the cache corruption"
+                    POPULATE_CACHE=1
+                else
+                    echo "The chache corruption was resolved"
+                    cp ${CACHE_TMP}/cache/cache/.versions ${BUILD_BASE}/.
+                    set +e
+                    make -C ${BUILD_BASE} validate-cache;
+                    rc=$?
+                    set -e
+                    if [ $rc -ne 0 ]; then
+                        echo "Cache invalid - a new cache will be built "
+                        POPULATE_CACHE=1
+                    else
+                        echo "Cache is up to date and will be used"
+                        cp -rf ${CACHE_TMP}/cache/cache/. ${BUILD_BASE}
+                    fi
+                fi
+            else
+                echo "Cache archive is intact"
+                cp ${CACHE_TMP}/cache/cache/.versions ${BUILD_BASE}/.
+                set +e
+                make -C ${BUILD_BASE} validate-cache;
+                rc=$?
+                set -e
+
+                if [ $rc -ne 0 ]; then
+                    echo "Cache invalid - a new cache will be built "
+                    POPULATE_CACHE=1
+                else
+                    echo "Cache is up to date and will be used"
+                    cp -rf ${CACHE_TMP}/cache/cache/. ${BUILD_BASE}
+                fi
+            fi
+            rm -rf ${CACHE_TMP}/cache
+        fi
+    fi
+fi
+
+if [ ${POPULATE_CACHE} -eq 1 ]; then
+    if [ ${DEBUG} -eq 0 ]; then
+        set +e
+        cd ${BUILD_BASE} && make clean
+        rc=$?
+        set -e
+        if [ $rc -ne 0 ]; then
+            echo "Build - make clean failed, exiting ..."
+            rc=100
+            exit $rc
+        fi
+    fi
+fi
+
+if [ ! -z ${BUILD_VERSION} ]; then
+    MAKE_ARGS+="REVSTATE=${BUILD_VERSION} "
+fi
+
+if [ ${UNIT_TEST} -eq 1 ]; then
+    MAKE_ARGS+="UNIT_TEST=TRUE "
+else
+    MAKE_ARGS+="UNIT_TEST=FALSE "
+fi
+
+if [ ${INTERACTIVE} -eq 1 ]; then
+    MAKE_ARGS+="INTERACTIVE=TRUE "
+else
+    MAKE_ARGS+="INTERACTIVE=FALSE "
+fi
+
+MAKE_ARGS+=all
+
+if [ ${DEBUG} -eq 0 ]; then
+    set +e
+    cd ${BUILD_BASE} && make ${MAKE_ARGS}
+    rc=$?
+    set -e
+    if [ $rc -gt 0 ]; then
+        echo "Build: make all failed, exiting ..."
+        rc=200
+        exit $rc
+    fi
+else
+    debug_make
+fi
+set +e
+make -C ${BUILD_BASE} prepare-cache
+rc=$?
+set -e
+
+if [ $rc -gt 0 ]; then
+    echo "Build: make prepare-cache failed - exiting ..."
+    rc=100
+    exit $rc
+fi
+echo "Copying built OPNFV .iso file to target directory ${BUILD_DIR} ..."
+rm -rf ${BUILD_DIR}
+mkdir -p ${BUILD_DIR}
+cp ${BUILD_BASE}/.versions ${BUILD_DIR}
+cp ${RESULT_DIR}/*.iso* ${BUILD_DIR}
+
+if [ $POPULATE_CACHE -eq 1 ]; then
+    if [ ! -z ${BUILD_CACHE_URI} ]; then
+        echo "Building cache ..."
+        tar --dereference -C ${BUILD_BASE} -caf ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz ${CACHE_DIR}
+        set +e
+        tar -C ${CACHE_TMP}/cache -tvf ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz
+        rc=$?
+        set -e
+        if [ $rc -ne 0 ]; then
+            echo "WARNING the cache archive generated seems to be corrupt, or containing trailing garbage"
+        else
+            echo "The Cache archive build is intact"
+        fi
+        echo "Uploading cache ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME}"
+        ${REMOTE_ACCESS_METHD} -T ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME}.tgz
+        rm ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz
+    fi
+fi
+echo "Success!!!"
+exit 0
+#
+# END of main
+############################################################################