Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
447bb2d
added a function to obtain full path to a tool
truib Jan 24, 2023
e2c24cf
partial bot/build.sh for eessi_container.sh
truib Jan 24, 2023
a71f8e4
added function to determine IPv4 address
truib Jan 25, 2023
b5bf008
various updates for bot/build.sh and eessi_container.sh
truib Jan 25, 2023
b5c07ee
provide CVMFS_HTTP_PROXY if necessary
truib Jan 27, 2023
4ff3721
add functions to derive hostname and port number from proxy URL
truib Jan 27, 2023
7a58fbf
add function to determine config sections
truib Jan 27, 2023
a5ea7d8
add parameter to list repositories, fix bugs
truib Jan 27, 2023
6ed3d85
fix bash pattern matching operator
truib Jan 29, 2023
fd5cc3d
various updates to bot/build.sh
truib Jan 29, 2023
234bab3
Merge branch 'enhancement/bot-build-with-swl-216' of github-trz:trz42…
truib Jan 29, 2023
b2eab08
replace FILE with DIR in EESSI_REPOS_CFG_FILE_OVERRIDE
truib Jan 29, 2023
7663fbc
Merge branch 'main' of github-trz:eessi/software-layer into enhanceme…
truib Jan 29, 2023
7e200a1
fix whitespace issues
truib Jan 29, 2023
57b6f27
fix handling of HTTP(S)_PROXY settings
truib Jan 30, 2023
fce504f
include changes made to test PR for building with the bot
truib Feb 3, 2023
910d079
Merge branch 'nessi.no-2022.11-dev' into enhancement/bot-build-with-s…
trz42 Feb 3, 2023
7c418cd
Merge branch 'update_for_eessi_container_sh' of github-trz:trz42/soft…
trz42 Feb 22, 2023
712c40e
improvements to resuming job environment
trz42 Feb 22, 2023
16d9857
improved handling of container cache + explicit pull of image
trz42 Feb 22, 2023
9e8ca62
changed --info -> --verbose
trz42 Feb 22, 2023
c0350a9
improved messages for resume info and adjusted parsing in bot/build.sh
trz42 Feb 22, 2023
ef9a552
delete one of two tmp storage tarballs created by bot/build.sh
trz42 Feb 22, 2023
1c0081d
Merge branch 'main' of github-trz:EESSI/software-layer into enhanceme…
trz42 Feb 24, 2023
7cc6575
support cmd line arg flag terminator
trz42 Feb 25, 2023
0def4e9
just print contents of cfg/job.cfg
trz42 Feb 24, 2023
ef608d1
switching from json (YQ) to ini (cfg_files.sh)
trz42 Feb 24, 2023
429d5a0
add --generic arg when running install script
trz42 Feb 23, 2023
bd31faa
fix error in regex
trz42 Feb 23, 2023
1bafb78
use command separator --
trz42 Feb 23, 2023
c9041e3
try fixing arg issue
trz42 Feb 24, 2023
9d46a22
put build args into an array
trz42 Feb 24, 2023
ff5045f
use array to define args for build and tarball step
trz42 Feb 25, 2023
d08bd21
addressed comments and changes requested by first review
trz42 Mar 7, 2023
54d2a21
improved usage information
trz42 Mar 8, 2023
64d1866
fix bug, env var PWD is uppercase
trz42 Mar 11, 2023
ff78c62
make sure that CPU arch specific directories are used as container ca…
truib Mar 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions bot/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#!/usr/bin/env bash
#
# script to build the EESSI software layer. Intended use is that it is called
# by a (batch) job running on a compute node.
#
# This script is part of the EESSI software layer, see
# https://github.com/EESSI/software-layer.git
#
# author: Thomas Roeblitz (@trz42)
#
# license: GPLv2
#

# ASSUMPTIONs:
# - working directory has been prepared by the bot with a checkout of a
# pull request (OR by some other means)
# - the working directory contains a directory 'cfg' where the main config
# file 'job.cfg' has been deposited
# - the directory may contain any additional files referenced in job.cfg

# stop as soon as something fails
set -e

# source utils.sh and cfg_files.sh
source scripts/utils.sh
source scripts/cfg_files.sh

# defaults
export JOB_CFG_FILE="${JOB_CFG_FILE_OVERRIDE:=./cfg/job.cfg}"
HOST_ARCH=$(uname -m)

# check if ${JOB_CFG_FILE} exists
if [[ ! -r "${JOB_CFG_FILE}" ]]; then
fatal_error "job config file (JOB_CFG_FILE=${JOB_CFG_FILE}) does not exist or not readable"
fi
echo "bot/build.sh: showing ${JOB_CFG_FILE} from software-layer side"
cat ${JOB_CFG_FILE}

echo "bot/build.sh: obtaining configuration settings from '${JOB_CFG_FILE}'"
cfg_load ${JOB_CFG_FILE}

# if http_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $http_proxy
HTTP_PROXY=$(cfg_get_value "site_config" "http_proxy")
HTTP_PROXY=${HTTP_PROXY:-${http_proxy}}
echo "bot/build.sh: HTTP_PROXY='${HTTP_PROXY}'"

# if https_proxy is defined in ${JOB_CFG_FILE} use it, if not use env var $https_proxy
HTTPS_PROXY=$(cfg_get_value "site_config" "https_proxy")
HTTPS_PROXY=${HTTPS_PROXY:-${https_proxy}}
echo "bot/build.sh: HTTPS_PROXY='${HTTPS_PROXY}'"

LOCAL_TMP=$(cfg_get_value "site_config" "local_tmp")
echo "bot/build.sh: LOCAL_TMP='${LOCAL_TMP}'"
# TODO should local_tmp be mandatory? --> then we check here and exit if it is not provided

SINGULARITY_CACHEDIR=$(cfg_get_value "site_config" "container_cachedir")
echo "bot/build.sh: SINGULARITY_CACHEDIR='${SINGULARITY_CACHEDIR}'"
if [[ ! -z ${SINGULARITY_CACHEDIR} ]]; then
# make sure that separate directories are used for different CPU families
SINGULARITY_CACHEDIR=${SINGULARITY_CACHEDIR}/${HOST_ARCH}
export SINGULARITY_CACHEDIR
fi

echo -n "setting \$STORAGE by replacing any var in '${LOCAL_TMP}' -> "
# replace any env variable in ${LOCAL_TMP} with its
# current value (e.g., a value that is local to the job)
STORAGE=$(envsubst <<< ${LOCAL_TMP})
echo "'${STORAGE}'"

# make sure ${STORAGE} exists
mkdir -p ${STORAGE}

# make sure the base tmp storage is unique
JOB_STORAGE=$(mktemp --directory --tmpdir=${STORAGE} bot_job_tmp_XXX)
echo "bot/build.sh: created unique base tmp storage directory at ${JOB_STORAGE}"

# obtain list of modules to be loaded
LOAD_MODULES=$(cfg_get_value "site_config" "load_modules")
echo "bot/build.sh: LOAD_MODULES='${LOAD_MODULES}'"

# singularity/apptainer settings: CONTAINER, HOME, TMPDIR, BIND
CONTAINER=$(cfg_get_value "repository" "container")
export SINGULARITY_HOME="${PWD}:/eessi_bot_job"
export SINGULARITY_TMPDIR="${PWD}/singularity_tmpdir"
mkdir -p ${SINGULARITY_TMPDIR}

# load modules if LOAD_MODULES is not empty
if [[ ! -z ${LOAD_MODULES} ]]; then
for mod in $(echo ${LOAD_MODULES} | tr ',' '\n')
do
echo "bot/build.sh: loading module '${mod}'"
module load ${mod}
done
else
echo "bot/build.sh: no modules to be loaded"
fi

# determine repository to be used from entry .repository in ${JOB_CFG_FILE}
REPOSITORY=$(cfg_get_value "repository" "repo_id")
EESSI_REPOS_CFG_DIR_OVERRIDE=$(cfg_get_value "repository" "repos_cfg_dir")
export EESSI_REPOS_CFG_DIR_OVERRIDE=${EESSI_REPOS_CFG_DIR_OVERRIDE:-${PWD}/cfg}
echo "bot/build.sh: EESSI_REPOS_CFG_DIR_OVERRIDE='${EESSI_REPOS_CFG_DIR_OVERRIDE}'"

# determine pilot version to be used from .repository.repo_version in ${JOB_CFG_FILE}
# here, just set & export EESSI_PILOT_VERSION_OVERRIDE
# next script (eessi_container.sh) makes use of it via sourcing init scripts
# (e.g., init/eessi_defaults or init/minimal_eessi_env)
export EESSI_PILOT_VERSION_OVERRIDE=$(cfg_get_value "repository" "repo_version")
echo "bot/build.sh: EESSI_PILOT_VERSION_OVERRIDE='${EESSI_PILOT_VERSION_OVERRIDE}'"

# determine CVMFS repo to be used from .repository.repo_name in ${JOB_CFG_FILE}
# here, just set EESSI_CVMFS_REPO_OVERRIDE, a bit further down
# "source init/eessi_defaults" via sourcing init/minimal_eessi_env
export EESSI_CVMFS_REPO_OVERRIDE=$(cfg_get_value "repository" "repo_name")
echo "bot/build.sh: EESSI_CVMFS_REPO_OVERRIDE='${EESSI_CVMFS_REPO_OVERRIDE}'"

# determine architecture to be used from entry .architecture in ${JOB_CFG_FILE}
# fallbacks:
# - ${CPU_TARGET} handed over from bot
# - left empty to let downstream script(s) determine subdir to be used
EESSI_SOFTWARE_SUBDIR_OVERRIDE=$(cfg_get_value "architecture" "software_subdir")
EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE:-${CPU_TARGET}}
export EESSI_SOFTWARE_SUBDIR_OVERRIDE
echo "bot/build.sh: EESSI_SOFTWARE_SUBDIR_OVERRIDE='${EESSI_SOFTWARE_SUBDIR_OVERRIDE}'"

# get EESSI_OS_TYPE from .architecture.os_type in ${JOB_CFG_FILE} (default: linux)
EESSI_OS_TYPE=$(cfg_get_value "architecture" "os_type")
export EESSI_OS_TYPE=${EESSI_OS_TYPE:-linux}
echo "bot/build.sh: EESSI_OS_TYPE='${EESSI_OS_TYPE}'"

# prepare arguments to eessi_container.sh common to build and tarball steps
declare -a COMMON_ARGS=()
COMMON_ARGS+=("--verbose")
COMMON_ARGS+=("--access" "rw")
COMMON_ARGS+=("--mode" "run")
[[ ! -z ${CONTAINER} ]] && COMMON_ARGS+=("--container" "${CONTAINER}")
[[ ! -z ${HTTP_PROXY} ]] && COMMON_ARGS+=("--http-proxy" "${HTTP_PROXY}")
[[ ! -z ${HTTPS_PROXY} ]] && COMMON_ARGS+=("--https-proxy" "${HTTPS_PROXY}")
[[ ! -z ${REPOSITORY} ]] && COMMON_ARGS+=("--repository" "${REPOSITORY}")

# make sure to use the same parent dir for storing tarballs of tmp
PREVIOUS_TMP_DIR=${PWD}/previous_tmp

# prepare directory to store tarball of tmp for build step
TARBALL_TMP_BUILD_STEP_DIR=${PREVIOUS_TMP_DIR}/build_step
mkdir -p ${TARBALL_TMP_BUILD_STEP_DIR}

# prepare arguments to eessi_container.sh specific to build step
declare -a BUILD_STEP_ARGS=()
BUILD_STEP_ARGS+=("--save" "${TARBALL_TMP_BUILD_STEP_DIR}")
BUILD_STEP_ARGS+=("--storage" "${STORAGE}")

# prepare arguments to install_software_layer.sh (specific to build step)
GENERIC_OPT=
if [[ ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} =~ .*/generic$ ]]; then
GENERIC_OPT="--generic"
fi

# create tmp file for output of build step
build_outerr=$(mktemp build.outerr.XXXX)

echo "Executing command to build software:"
echo "./eessi_container.sh ${COMMON_ARGS[@]} ${BUILD_STEP_ARGS[@]}"
echo " -- ./install_software_layer.sh ${GENERIC_OPT} \"$@\" 2>&1 | tee -a ${build_outerr}"
./eessi_container.sh "${COMMON_ARGS[@]}" "${BUILD_STEP_ARGS[@]}" \
-- ./install_software_layer.sh ${GENERIC_OPT} "$@" 2>&1 | tee -a ${build_outerr}

# prepare directory to store tarball of tmp for tarball step
TARBALL_TMP_TARBALL_STEP_DIR=${PREVIOUS_TMP_DIR}/tarball_step
mkdir -p ${TARBALL_TMP_TARBALL_STEP_DIR}

# create tmp file for output of tarball step
tar_outerr=$(mktemp tar.outerr.XXXX)

# prepare arguments to eessi_container.sh specific to tarball step
declare -a TARBALL_STEP_ARGS=()
TARBALL_STEP_ARGS+=("--save" "${TARBALL_TMP_TARBALL_STEP_DIR}")

# determine temporary directory to resume from
BUILD_TMPDIR=$(grep ' as tmp directory ' ${build_outerr} | cut -d ' ' -f 2)
TARBALL_STEP_ARGS+=("--resume" "${BUILD_TMPDIR}")

timestamp=$(date +%s)
# to set EESSI_PILOT_VERSION we need to source init/eessi_defaults now
source init/eessi_defaults
export TGZ=$(printf "eessi-%s-software-%s-%s-%d.tar.gz" ${EESSI_PILOT_VERSION} ${EESSI_OS_TYPE} ${EESSI_SOFTWARE_SUBDIR_OVERRIDE//\//-} ${timestamp})

# value of first parameter to create_tarball.sh - TMP_IN_CONTAINER - needs to be
# synchronised with setting of TMP_IN_CONTAINER in eessi_container.sh
# TODO should we make this a configurable parameter of eessi_container.sh using
# /tmp as default?
TMP_IN_CONTAINER=/tmp
echo "Executing command to create tarball:"
echo "./eessi_container.sh ${COMMON_ARGS[@]} ${TARBALL_STEP_ARGS[@]}"
echo " -- ./create_tarball.sh ${TMP_IN_CONTAINER} ${EESSI_PILOT_VERSION} ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} /eessi_bot_job/${TGZ} 2>&1 | tee -a ${tar_outerr}"
./eessi_container.sh "${COMMON_ARGS[@]}" "${TARBALL_STEP_ARGS[@]}" \
-- ./create_tarball.sh ${TMP_IN_CONTAINER} ${EESSI_PILOT_VERSION} ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} /eessi_bot_job/${TGZ} 2>&1 | tee -a ${tar_outerr}

exit 0
20 changes: 13 additions & 7 deletions eessi_container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export EESSI_REPOS_CFG_FILE="${EESSI_REPOS_CFG_DIR}/repos.cfg"
# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash

display_help() {
echo "usage: $0 [OPTIONS] [SCRIPT]"
echo "usage: $0 [OPTIONS] [[--] SCRIPT or COMMAND]"
echo " OPTIONS:"
echo " -a | --access {ro,rw} - ro (read-only), rw (read & write) [default: ro]"
echo " -c | --container IMG - image file or URL defining the container to use"
Expand All @@ -77,10 +77,10 @@ display_help() {
echo " temporary data) [default: 1. TMPDIR, 2. /tmp]"
echo " -l | --list-repos - list available repository identifiers [default: false]"
echo " -m | --mode MODE - with MODE==shell (launch interactive shell) or"
echo " MODE==run (run a script) [default: shell]"
echo " MODE==run (run a script or command) [default: shell]"
echo " -r | --repository CFG - configuration file or identifier defining the"
echo " repository to use [default: EESSI-pilot via"
echo " container configuration]"
echo " default container, see --container]"
echo " -u | --resume DIR/TGZ - resume a previous run from a directory or tarball,"
echo " where DIR points to a previously used tmp directory"
echo " (check for output 'Using DIR as tmp ...' of a previous"
Expand All @@ -98,7 +98,9 @@ display_help() {
echo " -y | --https-proxy URL - provides URL for the env variable https_proxy"
echo " [default: not set]; uses env var \$https_proxy if set"
echo
echo " If value for --mode is 'run', the SCRIPT provided is executed."
echo " If value for --mode is 'run', the SCRIPT/COMMAND provided is executed. If"
echo " arguments to the script/command start with '-' or '--', use the flag terminator"
echo " '--' to let eessi_container.sh stop parsing arguments."
}

# set defaults for command line arguments
Expand Down Expand Up @@ -173,6 +175,11 @@ while [[ $# -gt 0 ]]; do
export https_proxy=${HTTPS_PROXY}
shift 2
;;
--)
shift
POSITIONAL_ARGS+=("$@") # save positional args
break
;;
-*|--*)
fatal_error "Unknown option: $1" "${CMDLINE_ARG_UNKNOWN_EXITCODE}"
;;
Expand All @@ -185,7 +192,6 @@ done

set -- "${POSITIONAL_ARGS[@]}"


if [[ ${LIST_REPOS} -eq 1 ]]; then
echo "Listing available repositories with format 'name [source]':"
echo " EESSI-pilot [default]"
Expand Down Expand Up @@ -285,7 +291,7 @@ else
[[ ${VERBOSE} -eq 1 ]] && echo "skipping sanity checks for /tmp"
fi
EESSI_HOST_STORAGE=$(mktemp -d --tmpdir eessi.XXXXXXXXXX)
echo "Using ${EESSI_HOST_STORAGE} as tmp storage (add '--resume ${EESSI_HOST_STORAGE}' to resume where this session ended)."
echo "Using ${EESSI_HOST_STORAGE} as tmp directory (to resume session add '--resume ${EESSI_HOST_STORAGE}')."
fi

# if ${RESUME} is a file (assume a tgz), unpack it into ${EESSI_HOST_STORAGE}
Expand Down Expand Up @@ -572,7 +578,7 @@ if [[ ! -z ${SAVE} ]]; then
TGZ=${SAVE}
fi
tar cf ${TGZ} -C ${EESSI_TMPDIR} .
echo "Saved contents of '${EESSI_TMPDIR}' to '${TGZ}' (to resume, add '--resume ${TGZ}')"
echo "Saved contents of tmp directory '${EESSI_TMPDIR}' to tarball '${TGZ}' (to resume session add '--resume ${TGZ}')"
fi

# TODO clean up tmp by default? only retain if another option provided (--retain-tmp)
Expand Down
14 changes: 13 additions & 1 deletion run_in_compat_layer_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ INPUT=$(echo "$@")
if [ ! -z ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} ]; then
INPUT="export EESSI_SOFTWARE_SUBDIR_OVERRIDE=${EESSI_SOFTWARE_SUBDIR_OVERRIDE}; ${INPUT}"
fi
if [ ! -z ${EESSI_CVMFS_REPO_OVERRIDE} ]; then
INPUT="export EESSI_CVMFS_REPO_OVERRIDE=${EESSI_CVMFS_REPO_OVERRIDE}; ${INPUT}"
fi
if [ ! -z ${EESSI_PILOT_VERSION_OVERRIDE} ]; then
INPUT="export EESSI_PILOT_VERSION_OVERRIDE=${EESSI_PILOT_VERSION_OVERRIDE}; ${INPUT}"
fi
if [ ! -z ${http_proxy} ]; then
INPUT="export http_proxy=${http_proxy}; ${INPUT}"
fi
if [ ! -z ${https_proxy} ]; then
INPUT="export https_proxy=${https_proxy}; ${INPUT}"
fi

echo "Running '${INPUT}' in EESSI ${EESSI_PILOT_VERSION} compatibility layer environment..."
echo "Running '${INPUT}' in EESSI (${EESSI_CVMFS_REPO}) ${EESSI_PILOT_VERSION} compatibility layer environment..."
${EESSI_COMPAT_LAYER_DIR}/startprefix <<< "${INPUT}"