mirror of https://github.com/schoebel/mars
268 lines
9.2 KiB
Bash
Executable File
268 lines
9.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Copyright 2010-2014 Frank Liepold / 1&1 Internet AG
|
|
#
|
|
# Email: frank.liepold@1und1.de
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
#####################################################################
|
|
|
|
## For a general documentation please refer to README, section "Running a test"
|
|
|
|
function set_host_locks
|
|
{
|
|
local host
|
|
echo "================= Creating lock files =========================================="
|
|
if [ ${#global_host_list[*]} -eq 0 ]; then
|
|
lib_vmsg " global_host_list empty, no lock files necessary"
|
|
return
|
|
fi
|
|
for host in "${global_host_list[@]}"; do
|
|
local lock_file=${main_lock_file_list[$host]}
|
|
if [ -z "$lock_file" ]; then
|
|
lib_exit 1 "no entry in main_lock_file_list for host $host"
|
|
fi
|
|
if [ -f $lock_file ]; then
|
|
echo "Failure lockfile $lock_file for host $host exists!" >&2
|
|
lib_exit $main_prevent_remove_lock_files_exit_code
|
|
fi
|
|
date > $lock_file || lib_exit 1
|
|
lib_vmsg " created lockfile $lock_file on $host"
|
|
done
|
|
echo "================= End creating lock files ======================================"
|
|
}
|
|
|
|
function release_host_locks
|
|
{
|
|
echo "================= Deleting lock files =========================================="
|
|
for host in "${global_host_list[@]}"; do
|
|
local lock_file=${main_lock_file_list[$host]}
|
|
rm -f $lock_file || lib_exit 1
|
|
lib_vmsg " deleted lockfile $lock_file on $host"
|
|
done
|
|
echo "================= End deleting lock files ======================================"
|
|
}
|
|
|
|
function source_module
|
|
{
|
|
local module="$1"
|
|
local modname="$(basename $module .sh)"
|
|
if source_config default-$modname; then
|
|
echo "Sourcing module $modname"
|
|
source $module || start_test_exit $?
|
|
else
|
|
start_test_exit 1
|
|
fi
|
|
}
|
|
|
|
function save_environment
|
|
{
|
|
# we cannot use lib_exit because the libs are not yet sourced in
|
|
environ_save=/tmp/environ.sav.$$
|
|
rm -f $environ_save || lib_exit 1 "cannot remove $environ_save"
|
|
set >$environ_save || lib_exit 1 "cannot create $environ_save"
|
|
}
|
|
|
|
# prints all shell variables which are set via sourcing the *.conf files
|
|
function print_config_environment
|
|
{
|
|
local f
|
|
local environ_actual=/tmp/environ.act.$$
|
|
[ -n "$environ_save" ] || lib_exit 1 "variable environ_save not set"
|
|
[ -r "$environ_save" ] || lib_exit 1 "file $environ_save not readable"
|
|
rm -f $environ_actual || lib_exit 1 "cannot remove $environ_actual"
|
|
set >$environ_actual || lib_exit 1 "cannot create $environ_actual"
|
|
# delete function definitions and sort
|
|
for f in $environ_save $environ_actual; do
|
|
sed -i -e '/^.* () *$/d;/^{ *$/,/^} *$/d' $f || lib_exit 1
|
|
sort -o $f $f || lib_exit 1
|
|
done
|
|
|
|
echo "================= Configuration variables ======================================"
|
|
# print lines uniq to $environ_actual and remove some not interesting
|
|
# variables
|
|
comm -2 -3 $environ_actual $environ_save | \
|
|
egrep -v '^(BASH_LINENO|FUNCNAME|OLDPWD|_)='
|
|
rm -f $environ_actual
|
|
echo "================= End configuration variables =================================="
|
|
|
|
}
|
|
|
|
# wrapper for the exit builtin to be able to remove temporary files
|
|
function start_test_exit
|
|
{
|
|
rm -f $environ_save
|
|
exit $1
|
|
}
|
|
|
|
function usage
|
|
{
|
|
echo "usage: $(basename $0) [--dry-run] [--config_root_dir=<my_dir>]" >&2
|
|
echo " Option --dry-run:" >&2
|
|
echo " Print all configuration variables and the name " >&2
|
|
echo " of the test. Don't execute it." >&2
|
|
echo " Option --config_root_dir:" >&2
|
|
echo " Include all *.conf files belonging to subdirectories " >&2
|
|
echo " between my_dir and test directory." >&2
|
|
echo " Default: my_dir = working directory" >&2
|
|
echo " Option --doc:" >&2
|
|
echo " Show all config variables for the actual test directory.">&2
|
|
echo " The variable run_list contains the functions called in this test." >&2
|
|
exit 1
|
|
}
|
|
|
|
dry_run_script=0
|
|
start_dir=$(pwd)
|
|
# all directories between config_root_dir and the actual test directory will be
|
|
# considered as "configuration options". That means that a <dirname>.conf file
|
|
# must be provided for all these directories
|
|
config_root_dir=$start_dir
|
|
|
|
# parse options.
|
|
while [ $# -ge 1 ]; do
|
|
key="$(echo "$1" | cut -d= -f1)"
|
|
val="$(echo "$1" | cut -d= -f2-)"
|
|
case "$key" in
|
|
--dry-run)
|
|
dry_run_script="$val"
|
|
shift
|
|
;;
|
|
--config_root_dir)
|
|
config_root_dir="$val"
|
|
shift
|
|
;;
|
|
--doc)
|
|
dry_run_script=1
|
|
shift
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if ! cd $config_root_dir ; then
|
|
echo "cannot cd $config_root_dir" >&2
|
|
start_test_exit 1
|
|
else
|
|
config_root_dir=$(pwd) # we need the absolute path
|
|
cd $start_dir
|
|
fi
|
|
|
|
shopt -s extdebug
|
|
|
|
# Use directory names as basis for configuration variants
|
|
|
|
script_dir="$(cd "$(dirname "$(which "$0")")"; pwd)"
|
|
lib_dir=$script_dir/lib
|
|
echo "================= Sourcing libraries in $lib_dir ==============================="
|
|
for lib in $lib_dir/lib*.sh; do
|
|
echo "Sourcing $lib"
|
|
source "$lib" || start_test_exit $?
|
|
done
|
|
echo "================= End sourcing libraries ======================================="
|
|
|
|
to_start="${to_start:-main}"
|
|
marker_file="i_am_a_testdirectory"
|
|
|
|
# check some preconditions
|
|
|
|
check_list="truncate grep sed gawk head tail cut nice date gzip gunzip zcat buffer pstree"
|
|
check_installed "$check_list"
|
|
|
|
# include modules
|
|
prepare_list=""
|
|
setup_list=""
|
|
run_list=""
|
|
cleanup_list=""
|
|
finish_list=""
|
|
|
|
save_environment # for later use in print_config_environment
|
|
|
|
shopt -s nullglob
|
|
echo "================= Sourcing modules and default configuration ==================="
|
|
module_dir=$script_dir/modules
|
|
[ -d "$module_dir" ] || \
|
|
lib_exit 1 "directory module_dir=$module_dir not found"
|
|
for module in $script_dir/modules/*.sh; do
|
|
source_module "$module"
|
|
done
|
|
source_config global || lib_exit 1
|
|
[ -n "$global_user_module_dir" ] || lib_exit 1 "global_user_module_dir not set"
|
|
[ -d "$global_user_module_dir" ] || \
|
|
lib_exit 1 "directory global_user_module_dir=$global_user_module_dir not found"
|
|
for module in $global_user_module_dir/*.sh; do
|
|
source_module "$module"
|
|
done
|
|
|
|
echo "================= End sourcing modules and default configuration ==============="
|
|
|
|
# find directories
|
|
echo "================= Scanning subdirectories of $start_dir ========================"
|
|
for marker in $(find . -type f -name "$marker_file" | sort); do
|
|
test_dir=$(dirname $marker)
|
|
shopt -u nullglob
|
|
(
|
|
cd $test_dir
|
|
echo "================= Test directory $(pwd) $date =================================="
|
|
echo "================= Sourcing config files between $config_root_dir and $(pwd) ===="
|
|
|
|
# to be able to call error recovery functions in case of signals
|
|
trap 'lib_exit 1 "caught signal"' SIGHUP SIGINT
|
|
|
|
# source all individual config files (for overrides)
|
|
# between $config_root_dir (exclusive) and $(pwd) (inclusive)
|
|
shopt -s nullglob
|
|
t=$(pwd) # absolute path
|
|
if [ "$t" = "$config_root_dir" ]; then
|
|
components=$(basename $(pwd))
|
|
else
|
|
components=$(echo ${t#$config_root_dir/} | sed 's/\// /g')
|
|
fi
|
|
for i in $components; do
|
|
[ "$i" = "." ] && continue
|
|
if ! source_config "$i"; then
|
|
echo "Cannot source config file '$i.conf' -- please provide one."
|
|
start_test_exit -1
|
|
fi
|
|
done
|
|
echo "================= End sourcing config files between $config_root_dir and $(pwd) "
|
|
print_config_environment
|
|
shopt -u nullglob
|
|
|
|
if (( dry_run_script )); then
|
|
echo "would start $(pwd)"
|
|
exit 0
|
|
else
|
|
set_host_locks
|
|
echo "================= Starting $(pwd) $(date) ======================================"
|
|
eval "$to_start"
|
|
test_rc=$?
|
|
release_host_locks
|
|
exit $test_rc
|
|
fi
|
|
)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
echo "========================== Failure $rc $(cd $test_dir; pwd) $date ==============" >&2
|
|
else
|
|
echo "========================== Finished $(cd $test_dir; pwd) $(date) ==============="
|
|
fi
|
|
[ $rc -ne 0 ] && start_test_exit $rc
|
|
done
|
|
|
|
echo "========================== Finished start directory $start_dir ================="
|
|
start_test_exit 0
|