Retries for certain wheel and image build commands

The wheel and image build tools hit intermittent issues such as:
* Network or server issues that cause file download failures
* Repo access failures due to repo updates or other issues

To avoid formal build failures on such issues, this update adds
retries around specific commands, like wget and docker build.

Change-Id: Ifafdc6201872f43b2dd77efd4dcb033456477c2e
Closes-Bug: 1823986
Signed-off-by: Don Penney <don.penney@windriver.com>
This commit is contained in:
Don Penney 2019-04-09 16:17:22 -04:00
parent 02fa17a6ba
commit 492b5b218d
6 changed files with 143 additions and 26 deletions

View File

@ -1,14 +1,16 @@
#!/bin/bash #!/bin/bash
# #
# Copyright (c) 2018 Wind River Systems, Inc. # Copyright (c) 2018-2019 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
# This utility builds the StarlingX wheel tarball # This utility builds the StarlingX base image
# #
MY_SCRIPT_DIR=$(dirname $(readlink -f $0)) MY_SCRIPT_DIR=$(dirname $(readlink -f $0))
source ${MY_SCRIPT_DIR}/../build-wheels/utils.sh
# Required env vars # Required env vars
if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then
echo "Environment not setup for builds" >&2 echo "Environment not setup for builds" >&2
@ -31,6 +33,7 @@ CLEAN=no
TAG_LATEST=no TAG_LATEST=no
LATEST_TAG=latest LATEST_TAG=latest
HOST=${HOSTNAME} HOST=${HOSTNAME}
declare -i MAX_ATTEMPTS=1
function usage { function usage {
cat >&2 <<EOF cat >&2 <<EOF
@ -52,11 +55,12 @@ Options:
--registry: Docker registry --registry: Docker registry
--clean: Remove image(s) from local registry --clean: Remove image(s) from local registry
--hostname: build repo host --hostname: build repo host
--attempts: Max attempts, in case of failure (default: 1)
EOF EOF
} }
OPTS=$(getopt -o h -l help,os:,os-version:,version:,stream:,release:,repo:,push,proxy:,latest,latest-tag:,user:,registry:,local,clean,hostname: -- "$@") OPTS=$(getopt -o h -l help,os:,os-version:,version:,stream:,release:,repo:,push,proxy:,latest,latest-tag:,user:,registry:,local,clean,hostname:,attempts: -- "$@")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
usage usage
exit 1 exit 1
@ -132,6 +136,10 @@ while true; do
HOST=$2 HOST=$2
shift 2 shift 2
;; ;;
--attempts)
MAX_ATTEMPTS=$2
shift 2
;;
-h | --help ) -h | --help )
usage usage
exit 1 exit 1
@ -223,6 +231,9 @@ done
docker images --format '{{.Repository}}:{{.Tag}}' ${OS}:${OS_VERSION} | grep -q "^${OS}:${OS_VERSION}$" docker images --format '{{.Repository}}:{{.Tag}}' ${OS}:${OS_VERSION} | grep -q "^${OS}:${OS_VERSION}$"
BASE_IMAGE_PRESENT=$? BASE_IMAGE_PRESENT=$?
# Pull the image anyway, to ensure it is up to date
docker pull ${OS}:${OS_VERSION}
# Build the image # Build the image
IMAGE_NAME=${DOCKER_REGISTRY}${DOCKER_USER}/stx-${OS}:${IMAGE_VERSION} IMAGE_NAME=${DOCKER_REGISTRY}${DOCKER_USER}/stx-${OS}:${IMAGE_VERSION}
IMAGE_NAME_LATEST=${DOCKER_REGISTRY}${DOCKER_USER}/stx-${OS}:${LATEST_TAG} IMAGE_NAME_LATEST=${DOCKER_REGISTRY}${DOCKER_USER}/stx-${OS}:${LATEST_TAG}
@ -238,7 +249,7 @@ fi
BUILD_ARGS+=(--tag ${IMAGE_NAME} ${BUILDDIR}) BUILD_ARGS+=(--tag ${IMAGE_NAME} ${BUILDDIR})
# Build base image # Build base image
docker build "${BUILD_ARGS[@]}" with_retries ${MAX_ATTEMPTS} docker build "${BUILD_ARGS[@]}"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failed running docker build command" >&2 echo "Failed running docker build command" >&2
exit 1 exit 1

View File

@ -1,14 +1,16 @@
#!/bin/bash #!/bin/bash
# #
# Copyright (c) 2018 Wind River Systems, Inc. # Copyright (c) 2018-2019 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
# This utility builds the StarlingX wheel tarball # This utility builds the StarlingX container images
# #
MY_SCRIPT_DIR=$(dirname $(readlink -f $0)) MY_SCRIPT_DIR=$(dirname $(readlink -f $0))
source ${MY_SCRIPT_DIR}/../build-wheels/utils.sh
# Required env vars # Required env vars
if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then
echo "Environment not setup for builds" >&2 echo "Environment not setup for builds" >&2
@ -35,6 +37,7 @@ TAG_LIST_FILE=
TAG_LIST_LATEST_FILE= TAG_LIST_LATEST_FILE=
declare -a ONLY declare -a ONLY
declare -a SKIP declare -a SKIP
declare -i MAX_ATTEMPTS=1
function usage { function usage {
cat >&2 <<EOF cat >&2 <<EOF
@ -61,6 +64,7 @@ Options:
--skip <image> : Skip building the specified image(s). Multiple images --skip <image> : Skip building the specified image(s). Multiple images
can be specified with a comma-separated list, or with can be specified with a comma-separated list, or with
multiple --skip arguments. multiple --skip arguments.
--attempts: Max attempts, in case of failure (default: 1)
EOF EOF
@ -276,7 +280,7 @@ function build_image_loci {
local build_image_name="${USER}/${LABEL}:${IMAGE_TAG_BUILD}" local build_image_name="${USER}/${LABEL}:${IMAGE_TAG_BUILD}"
docker build ${WORKDIR}/loci --no-cache \ with_retries ${MAX_ATTEMPTS} docker build ${WORKDIR}/loci --no-cache \
"${BUILD_ARGS[@]}" \ "${BUILD_ARGS[@]}" \
--tag ${build_image_name} 2>&1 | tee ${WORKDIR}/docker-${LABEL}-${OS}-${BUILD_STREAM}.log --tag ${build_image_name} 2>&1 | tee ${WORKDIR}/docker-${LABEL}-${OS}-${BUILD_STREAM}.log
if [ ${PIPESTATUS[0]} -ne 0 ]; then if [ ${PIPESTATUS[0]} -ne 0 ]; then
@ -361,7 +365,7 @@ function build_image_docker {
BASE_BUILD_ARGS+=(--build-arg http_proxy=$PROXY) BASE_BUILD_ARGS+=(--build-arg http_proxy=$PROXY)
fi fi
BASE_BUILD_ARGS+=(--tag ${build_image_name}) BASE_BUILD_ARGS+=(--tag ${build_image_name})
docker build ${BASE_BUILD_ARGS[@]} 2>&1 | tee ${WORKDIR}/docker-${LABEL}-${OS}-${BUILD_STREAM}.log with_retries ${MAX_ATTEMPTS} docker build ${BASE_BUILD_ARGS[@]} 2>&1 | tee ${WORKDIR}/docker-${LABEL}-${OS}-${BUILD_STREAM}.log
if [ ${PIPESTATUS[0]} -ne 0 ]; then if [ ${PIPESTATUS[0]} -ne 0 ]; then
echo "Failed to build ${LABEL}... Aborting" echo "Failed to build ${LABEL}... Aborting"
@ -395,7 +399,7 @@ function build_image {
esac esac
} }
OPTS=$(getopt -o h -l help,os:,version:,release:,stream:,push,proxy:,user:,registry:,base:,wheels:,only:,skip:,prefix:,latest,latest-prefix:,clean -- "$@") OPTS=$(getopt -o h -l help,os:,version:,release:,stream:,push,proxy:,user:,registry:,base:,wheels:,only:,skip:,prefix:,latest,latest-prefix:,clean,attempts: -- "$@")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
usage usage
exit 1 exit 1
@ -477,6 +481,10 @@ while true; do
TAG_LATEST=yes TAG_LATEST=yes
shift shift
;; ;;
--attempts)
MAX_ATTEMPTS=$2
shift 2
;;
-h | --help ) -h | --help )
usage usage
exit 1 exit 1
@ -555,6 +563,9 @@ fi
docker images --format '{{.Repository}}:{{.Tag}}' ${BASE} | grep -q "^${BASE}$" docker images --format '{{.Repository}}:{{.Tag}}' ${BASE} | grep -q "^${BASE}$"
BASE_IMAGE_PRESENT=$? BASE_IMAGE_PRESENT=$?
# Pull the image anyway, to ensure it's up to date
docker pull ${BASE}
# Download loci, if needed. # Download loci, if needed.
get_loci get_loci
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
@ -573,7 +584,7 @@ for image_build_inc_file in $(find ${GIT_LIST} -maxdepth 1 -name "${OS}_${BUILD_
done done
done done
if [ "${CLEAN}" = "yes" ]; then if [ "${CLEAN}" = "yes" -a ${#RESULTS_BUILT[@]} -gt 0 ]; then
# Delete the images # Delete the images
echo "Deleting images" echo "Deleting images"
docker image rm ${RESULTS_BUILT[@]} ${RESULTS_PUSHED[@]} docker image rm ${RESULTS_BUILT[@]} ${RESULTS_PUSHED[@]}

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# Copyright (c) 2018 Wind River Systems, Inc. # Copyright (c) 2018-2019 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -8,6 +8,10 @@
# for a set of upstream python modules. # for a set of upstream python modules.
# #
MY_SCRIPT_DIR=$(dirname $(readlink -f $0))
source ${MY_SCRIPT_DIR}/utils.sh
# Required env vars # Required env vars
if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then
echo "Environment not setup for builds" >&2 echo "Environment not setup for builds" >&2
@ -21,6 +25,7 @@ OS=centos
OS_VERSION=7.5.1804 OS_VERSION=7.5.1804
BUILD_STREAM=stable BUILD_STREAM=stable
PROXY="" PROXY=""
declare -i MAX_ATTEMPTS=1
function usage { function usage {
cat >&2 <<EOF cat >&2 <<EOF
@ -34,11 +39,12 @@ Options:
--keep-container: Skip deletion of container used for the build --keep-container: Skip deletion of container used for the build
--proxy: Set proxy <URL>:<PORT> --proxy: Set proxy <URL>:<PORT>
--stream: Build stream, stable or dev (default: stable) --stream: Build stream, stable or dev (default: stable)
--attempts: Max attempts, in case of failure (default: 1)
EOF EOF
} }
OPTS=$(getopt -o h -l help,os:,os-version:,keep-image,keep-container,release:,stream:,proxy: -- "$@") OPTS=$(getopt -o h -l help,os:,os-version:,keep-image,keep-container,release:,stream:,proxy:,attempts: -- "$@")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
usage usage
exit 1 exit 1
@ -81,6 +87,10 @@ while true; do
PROXY=$2 PROXY=$2
shift 2 shift 2
;; ;;
--attempts)
MAX_ATTEMPTS=$2
shift 2
;;
-h | --help ) -h | --help )
usage usage
exit 1 exit 1
@ -210,7 +220,7 @@ BUILD_ARGS+=(-t ${BUILD_IMAGE_NAME})
BUILD_ARGS+=(-f ${DOCKER_PATH}/${OS}-dockerfile ${DOCKER_PATH}) BUILD_ARGS+=(-f ${DOCKER_PATH}/${OS}-dockerfile ${DOCKER_PATH})
# Build image # Build image
docker build "${BUILD_ARGS[@]}" with_retries ${MAX_ATTEMPTS} docker build "${BUILD_ARGS[@]}"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failed to create build image in docker" >&2 echo "Failed to create build image in docker" >&2
exit 1 exit 1
@ -230,7 +240,7 @@ fi
RUN_ARGS+=(${RM_OPT} -v ${BUILD_OUTPUT_PATH}:/wheels ${BUILD_IMAGE_NAME} /docker-build-wheel.sh) RUN_ARGS+=(${RM_OPT} -v ${BUILD_OUTPUT_PATH}:/wheels ${BUILD_IMAGE_NAME} /docker-build-wheel.sh)
# Run container to build wheels # Run container to build wheels
docker run ${RUN_ARGS[@]} with_retries ${MAX_ATTEMPTS} docker run ${RUN_ARGS[@]}
if [ "${KEEP_IMAGE}" = "no" ]; then if [ "${KEEP_IMAGE}" = "no" ]; then
# Delete the builder image # Delete the builder image

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# Copyright (c) 2018 Wind River Systems, Inc. # Copyright (c) 2018-2019 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -9,6 +9,8 @@
MY_SCRIPT_DIR=$(dirname $(readlink -f $0)) MY_SCRIPT_DIR=$(dirname $(readlink -f $0))
source ${MY_SCRIPT_DIR}/utils.sh
# Required env vars # Required env vars
if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then
echo "Environment not setup for builds" >&2 echo "Environment not setup for builds" >&2
@ -25,6 +27,7 @@ PUSH=no
PROXY="" PROXY=""
CLEAN=no CLEAN=no
DOCKER_USER=${USER} DOCKER_USER=${USER}
declare -i MAX_ATTEMPTS=1
# List of top-level services for images, which should not be listed in upper-constraints.txt # List of top-level services for images, which should not be listed in upper-constraints.txt
SKIP_CONSTRAINTS=( SKIP_CONSTRAINTS=(
@ -56,11 +59,12 @@ Options:
--proxy: Set proxy <URL>:<PORT> --proxy: Set proxy <URL>:<PORT>
--user: Docker repo userid --user: Docker repo userid
--version: Version for pushed image (if used with --push) --version: Version for pushed image (if used with --push)
--attempts: Max attempts, in case of failure (default: 1)
EOF EOF
} }
OPTS=$(getopt -o h -l help,os:,os-version:,push,clean,user:,release:,stream:,proxy:,version: -- "$@") OPTS=$(getopt -o h -l help,os:,os-version:,push,clean,user:,release:,stream:,proxy:,version:,attempts: -- "$@")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
usage usage
exit 1 exit 1
@ -111,6 +115,10 @@ while true; do
VERSION=$2 VERSION=$2
shift 2 shift 2
;; ;;
--attempts)
MAX_ATTEMPTS=$2
shift 2
;;
-h | --help ) -h | --help )
usage usage
exit 1 exit 1
@ -143,7 +151,7 @@ if [ ! -z "$PROXY" ]; then
BUILD_BASE_WL_ARGS+=(--proxy ${PROXY}) BUILD_BASE_WL_ARGS+=(--proxy ${PROXY})
fi fi
${MY_SCRIPT_DIR}/build-base-wheels.sh ${BUILD_BASE_WL_ARGS[@]} ${MY_SCRIPT_DIR}/build-base-wheels.sh ${BUILD_BASE_WL_ARGS[@]} --attempts ${MAX_ATTEMPTS}
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failure running build-base-wheels.sh" >&2 echo "Failure running build-base-wheels.sh" >&2
exit 1 exit 1
@ -177,13 +185,13 @@ else
OPENSTACK_BRANCH=stable/${CURRENT_STABLE_OPENSTACK} OPENSTACK_BRANCH=stable/${CURRENT_STABLE_OPENSTACK}
fi fi
wget https://raw.githubusercontent.com/openstack/requirements/${OPENSTACK_BRANCH}/global-requirements.txt with_retries ${MAX_ATTEMPTS} wget https://raw.githubusercontent.com/openstack/requirements/${OPENSTACK_BRANCH}/global-requirements.txt
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failed to download global-requirements.txt" >&2 echo "Failed to download global-requirements.txt" >&2
exit 1 exit 1
fi fi
wget https://raw.githubusercontent.com/openstack/requirements/${OPENSTACK_BRANCH}/upper-constraints.txt with_retries ${MAX_ATTEMPTS} wget https://raw.githubusercontent.com/openstack/requirements/${OPENSTACK_BRANCH}/upper-constraints.txt
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failed to download upper-constraints.txt" >&2 echo "Failed to download upper-constraints.txt" >&2
exit 1 exit 1

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# Copyright (c) 2018 Wind River Systems, Inc. # Copyright (c) 2018-2019 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -11,6 +11,7 @@
CFGFILE=/wheels.cfg CFGFILE=/wheels.cfg
OUTPUTDIR=/wheels OUTPUTDIR=/wheels
FAILED_LOG=$OUTPUTDIR/failed.lst FAILED_LOG=$OUTPUTDIR/failed.lst
declare -i MAX_ATTEMPTS=5
# #
# Function to log the start of a build # Function to log the start of a build
@ -102,6 +103,41 @@ function fix_setup {
} }
#
# Function to call a command, with support for retries
#
function with_retries {
local max_attempts=$1
local cmd=$2
# Pop the first two arguments off the list,
# so we can pass additional args to the command safely
shift 2
local -i attempt=0
while :; do
let -i attempt++
echo "Running: ${cmd} $@"
${cmd} "$@"
if [ $? -eq 0 ]; then
return 0
fi
echo "Command (${cmd}) failed, attempt ${attempt} of ${max_attempts}."
if [ ${attempt} -lt ${max_attempts} ]; then
local delay=5
echo "Waiting ${delay} seconds before retrying..."
sleep ${delay}
continue
else
echo "Max command attempts reached. Aborting..."
return 1
fi
done
}
# #
# Function to use git to clone the module source and build a wheel. # Function to use git to clone the module source and build a wheel.
# #
@ -176,9 +212,8 @@ function from_tar {
taropts="xf" taropts="xf"
fi fi
wget $wgetsrc with_retries ${MAX_ATTEMPTS} wget $wgetsrc
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failure running: wget $wgetsrc"
echo $wheelname >> $FAILED_LOG echo $wheelname >> $FAILED_LOG
continue continue
fi fi
@ -228,9 +263,8 @@ function from_zip {
continue continue
fi fi
wget $wgetsrc with_retries ${MAX_ATTEMPTS} wget $wgetsrc
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failure running: wget $wgetsrc"
echo $wheelname >> $FAILED_LOG echo $wheelname >> $FAILED_LOG
continue continue
fi fi
@ -280,9 +314,8 @@ function from_pypi {
continue continue
fi fi
wget $wgetsrc with_retries ${MAX_ATTEMPTS} wget $wgetsrc
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failure running: wget $wgetsrc"
echo $wheelname >> $FAILED_LOG echo $wheelname >> $FAILED_LOG
continue continue
fi fi

View File

@ -0,0 +1,44 @@
#!/bin/bash
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Image and wheel build utility functions
#
#
# Function to call a command, with support for retries
#
function with_retries {
local max_attempts=$1
local cmd=$2
# Pop the first two arguments off the list,
# so we can pass additional args to the command safely
shift 2
local -i attempt=0
while :; do
let -i attempt++
echo "Running: ${cmd} $@"
${cmd} "$@"
if [ $? -eq 0 ]; then
return 0
fi
echo "Command (${cmd}) failed, attempt ${attempt} of ${max_attempts}."
if [ ${attempt} -lt ${max_attempts} ]; then
local delay=5
echo "Waiting ${delay} seconds before retrying..."
sleep ${delay}
continue
else
echo "Max command attempts reached. Aborting..."
return 1
fi
done
}