diff --git a/bin/benchmark-drivers-start.sh b/bin/benchmark-drivers-start.sh deleted file mode 100755 index 3b5e167..0000000 --- a/bin/benchmark-drivers-start.sh +++ /dev/null @@ -1,224 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that starts BenchmarkDriver on local machine. -# This script expects the argument to be a path to run properties file which contains -# the list of remote nodes to start server on and the list of configurations. -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -CONFIG_INCLUDE=$1 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-drivers-start.sh [PROPERTIES_FILE_PATH]" - echo "Script that starts BenchmarkDriver on local machine." - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: config/benchmark.properties" -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file is not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -shift - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -# Define user to establish remote ssh session. -if [ "${REMOTE_USER}" == "" ]; then - REMOTE_USER=$(whoami) -fi - -if [ "${DRIVER_HOSTS}" == "" ]; then - DRIVER_HOSTS="localhost" -fi - -if [ "${REMOTE_USER}" == "" ]; then - echo "ERROR: Remote user (REMOTE_USER) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${CONFIG}" == "" ]; then - IFS=',' read -ra cfg <<< "${CONFIGS}" - - if ((${#cfg[@]} > 0)); then - CONFIG=${cfg[0]} - fi -else - CONFIG="$CONFIG $*" -fi - -if [ "${CONFIG}" == "" ]; then - echo "ERROR: Configurations (CONFIGS) are not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -function cleanup() { - pkill -9 -f "Dyardstick.driver" - - IFS=',' read -ra hosts0 <<< "${DRIVER_HOSTS}" - - for host_name in "${hosts0[@]}"; - do - if [[ ${host_name} = "127.0.0.1" || ${host_name} = "localhost" ]] - then - pkill -9 -f "Dyardstick.driver" - else - `ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} \ - pkill -9 -f "Dyardstick.driver"` - fi - done -} - -trap "cleanup; exit" SIGHUP SIGINT SIGTERM SIGQUIT SIGKILL - -# Define logs directory. -LOGS_DIR=${LOGS_BASE}/logs_drivers - -if [[ "${OUTPUT_FOLDER}" == "" ]] && [[ ${CONFIG} != *'-of '* ]] && [[ ${CONFIG} != *'--outputFolder '* ]]; then - results_folder=${SCRIPT_DIR}/../output/results-$(date +"%Y%m%d-%H%M%S") - - OUTPUT_FOLDER="--outputFolder ${results_folder}" -fi - -CUR_DIR=$(pwd) - -DS="" - -id=0 - -drvNum=$((`echo ${DRIVER_HOSTS} | tr ',' '\n' | wc -l`)) - -IFS=',' read -ra hosts0 <<< "${DRIVER_HOSTS}" - -JVM_OPTS_ORIG="$JVM_OPTS" - -for host_name in "${hosts0[@]}"; -do - if ((${drvNum} > 1)); then - outFol=${OUTPUT_FOLDER}"/"${id}"-"${host_name} - - if [[ ${CONFIG} != *'-hn '* ]] && [[ ${CONFIG} != *'--hostName '* ]]; then - host_name0="--hostName ${host_name}" - fi - else - outFol=${OUTPUT_FOLDER} - fi - - cfg="${outFol} ${host_name0} -id ${id} ${CONFIG}" - - suffix=`echo "${cfg}" | tail -c 60 | sed 's/ *$//g'` - - echo "<"$(date +"%H:%M:%S")"> Starting driver config '..."${suffix}"' on "${host_name}" with id=${id}" - - now=`date +'%H%M%S'` - - # Extract description. - IFS=' ' read -ra cfg0 <<< "${CONFIG}" - for cfg00 in "${cfg0[@]}"; - do - if [[ ${found} == 'true' ]]; then - found="" - DS=${cfg00} - fi - - if [[ ${cfg00} == '-ds' ]] || [[ ${cfg00} == '--descriptions' ]]; then - found="true" - fi - done - - file_log=${LOGS_DIR}"/"${now}"-id"${id}"-"${host_name}"-"${DS}".log" - - if [[ ${JVM_OPTS} == *"#filename#"* ]] - then - filename_ptrn="${LOGS_DIR}/${now}-driver-id${id}-${host_name}-${DS}" - JVM_OPTS="$(echo $JVM_OPTS_ORIG | sed s=#filename#=${filename_ptrn}=g)" - fi - - if [[ ${JVM_OPTS} == *"PrintGC"* ]]; then - GC_JVM_OPTS=" -Xloggc:${LOGS_DIR}/gc-${now}-driver-id${id}-${host_name}-${DS}.log" - fi - - if [[ ${host_name} = "127.0.0.1" || ${host_name} = "localhost" ]]; then - mkdir -p ${LOGS_DIR} - - SAVED_JVM_OPTS=${JVM_OPTS} - - JAVA_HOME=${JAVA_HOME} MAIN_CLASS='org.yardstickframework.BenchmarkDriverStartUp' \ - JVM_OPTS="${JVM_OPTS} ${GC_JVM_OPTS} ${DRIVER_JVM_OPTS} -Dyardstick.driver${id} " CP=${CP} CUR_DIR=${CUR_DIR} \ - PROPS_ENV0=${PROPS_ENV} HOST_NAME=${host_name} nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh \ - ${cfg} "--config" ${CONFIG_INCLUDE} "--logsFolder" ${LOGS_DIR} > ${file_log} 2>& 1 & - - ${SCRIPT_DIR}/benchmark-wait-driver-up.sh - - JVM_OPTS=${SAVED_JVM_OPTS} - else - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} mkdir -p ${LOGS_DIR} - - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} \ - "JAVA_HOME='${JAVA_HOME}'" \ - "MAIN_CLASS='org.yardstickframework.BenchmarkDriverStartUp'" "JVM_OPTS='${JVM_OPTS} ${GC_JVM_OPTS} ${DRIVER_JVM_OPTS} -Dyardstick.driver${id} '" \ - "CP='${CP}'" "CUR_DIR='${CUR_DIR}'" "PROPS_ENV0='${PROPS_ENV}'" \ - "nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh ${cfg} "--config" ${CONFIG_INCLUDE} "--logsFolder" ${LOGS_DIR} > ${file_log} 2>& 1 &" - - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} "HOST_NAME='${host_name}'" \ - ${SCRIPT_DIR}/benchmark-wait-driver-up.sh - fi - - echo "<"$(date +"%H:%M:%S")"> Driver is started on "${host_name}" with id=${id}" - - id=$((1 + $id)) -done - -for host_name in "${hosts0[@]}"; -do - if [[ ${host_name} = "127.0.0.1" || ${host_name} = "localhost" ]] - then - ${SCRIPT_DIR}/benchmark-wait-driver-finish.sh - - # Create marker file denoting that subfolders contain results from multiple drivers. - if ((${drvNum} > 1)); then - touch ${OUTPUT_FOLDER#--outputFolder }"/.multiple-drivers" - fi - else - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} \ - ${SCRIPT_DIR}/benchmark-wait-driver-finish.sh - - # Create marker file denoting that subfolders contain results from multiple drivers. - if ((${drvNum} > 1)); then - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} \ - touch ${OUTPUT_FOLDER#--outputFolder }"/.multiple-drivers" - fi - fi - - echo "<"$(date +"%H:%M:%S")"> Driver is stopped on "${host_name} -done - diff --git a/bin/benchmark-manual-drivers-start.bat b/bin/benchmark-manual-drivers-start.bat deleted file mode 100644 index 73de0a8..0000000 --- a/bin/benchmark-manual-drivers-start.bat +++ /dev/null @@ -1,142 +0,0 @@ -:: Licensed under the Apache License, Version 2.0 (the "License"); -:: you may not use this file except in compliance with the License. -:: You may obtain a copy of the License at -:: -:: http://www.apache.org/licenses/LICENSE-2.0 -:: -:: Unless required by applicable law or agreed to in writing, software -:: distributed under the License is distributed on an "AS IS" BASIS, -:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -:: See the License for the specific language governing permissions and -:: limitations under the License. - -:: -:: Script that starts BenchmarkDriver on a local machine. -:: This script expects the argument to be a path to run properties file which contains -:: list of configurations. -:: - -@echo off - -set SCRIPT_DIR=%~dp0 -set SCRIPT_DIR=%SCRIPT_DIR:~0,-1% - -set CONFIG_INCLUDE=%1 - -setlocal - -set or=false -if "%CONFIG_INCLUDE%"=="-h" set or=true -if "%CONFIG_INCLUDE%"=="--help" set or=true - -if "%or%"=="true" ( - echo Usage: benchmark-manual-drivers-start.bat [PROPERTIES_FILE_PATH] - echo Script that starts BenchmarkDriver on a local machine. - - exit /b -) - -endlocal - -set now0=%time: =0% - -if not defined CONFIG_INCLUDE ( - set CONFIG_INCLUDE=%SCRIPT_DIR%\..\config\benchmark-win.properties - echo ^<%now0:~0,2%:%now0:~3,2%:%now0:~6,2%^>^ Using default properties file: config\benchmark-win.properties -) - -if not exist "%CONFIG_INCLUDE%" ( - echo ERROR: Properties file is not found. - echo Type \"--help\" for usage. - exit /b -) - -shift - -set CONFIG_TMP=tmp.%RANDOM%.bat - -echo off > %CONFIG_TMP% - -type %CONFIG_INCLUDE% >> %CONFIG_TMP% - -call "%CONFIG_TMP%" > nul 2>&1 - -del %CONFIG_TMP% - -if not defined CONFIG ( - for /f "tokens=1 delims=," %%a in ("%CONFIGS%") do ( - set CONFIG=%%a - ) -) - -if not defined CONFIG ( - echo ERROR: Configurations ^(CONFIGS^) are not defined in properties file. - echo Type \"--help\" for usage. - exit /b -) - -:: Define logs directory. -set now=%time: =0% -set LOGS_BASE=logs-%date:~10,4%%date:~4,2%%date:~7,2%-%now:~0,2%%now:~3,2%%now:~6,2% - -set LOGS_DIR=%SCRIPT_DIR%\..\%LOGS_BASE%\logs_drivers - -if not exist "%LOGS_DIR%" ( - mkdir %LOGS_DIR% -) - -if not defined OUTPUT_FOLDER ( - if "x%CONFIG%"=="x%CONFIG:-of =%" ( - if "x%CONFIG%"=="x%CONFIG:--outputFolder =%" ( - set OUTPUT_FOLDER=--outputFolder results-%date:~10,4%%date:~4,2%%date:~7,2%-%now:~0,2%%now:~3,2%%now:~6,2% - ) - ) -) - -:: JVM options. -set JVM_OPTS=%JVM_OPTS% -Dyardstick.driver - -set CUR_DIR=%cd% - -setlocal enabledelayedexpansion - -set cntr=0 - -set cfgs=%CONFIGS% - -:loop.configs.next -for /f "tokens=1* delims=," %%a in ("%cfgs%") do ( - set cfgs=%%b - - set cfg=%OUTPUT_FOLDER% %%a - - set file_log=%LOGS_DIR%\!cntr!_driver.log - - set now=%time: =0% - echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ Starting driver config '!cfg!' - echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ Log file: !file_log! - - start /min cmd /c ^ - "set MAIN_CLASS=org.yardstickframework.BenchmarkDriverStartUp && set JVM_OPTS=%JVM_OPTS%%DRIVER_JVM_OPTS% && set CP=%CP% && set CUR_DIR=%CUR_DIR% && %SCRIPT_DIR%\benchmark-bootstrap.bat !cfg! --config %CONFIG_INCLUDE% ^>^> !file_log! 2^>^&1" - - set HOST_NAME=localhost - - call %SCRIPT_DIR%\%benchmark-wait-driver-up.bat" - - set now=%time: =0% - echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ Driver is started - - call "%SCRIPT_DIR%\%benchmark-wait-driver-finish.bat" - - set now=%time: =0% - echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ Driver is stopped - - set /a cntr+=1 -) - -if defined cfgs ( - goto loop.configs.next -) - -set now=%time: =0% -echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ All drivers are stopped diff --git a/bin/benchmark-manual-drivers-start.sh b/bin/benchmark-manual-drivers-start.sh deleted file mode 100755 index e32bf67..0000000 --- a/bin/benchmark-manual-drivers-start.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that starts BenchmarkDriver on a local machine. -# This script expects the argument to be a path to run properties file which contains -# list of configurations. -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -CONFIG_INCLUDE=$1 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-manual-drivers-start.sh [PROPERTIES_FILE_PATH]" - echo "Script that starts BenchmarkDriver on a local machine." - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: config/benchmark.properties" -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file is not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -shift - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -if ! [[ -d ${SCRIPT_DIR}/../output ]] -then - echo "<"$(date +"%H:%M:%S")"> Creating output directory" - mkdir ${SCRIPT_DIR}/../output -fi - -# Define user to establish remote ssh session. -if [ "${REMOTE_USER}" == "" ]; then - REMOTE_USER=$(whoami) -fi - -if [ "${DRIVER_HOSTS}" == "" ]; then - DRIVER_HOSTS="localhost" -fi - -if [ "${REMOTE_USER}" == "" ]; then - echo "ERROR: Remote user (REMOTE_USER) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${CONFIG}" == "" ]; then - IFS=',' read -ra cfg <<< "${CONFIGS}" - - if ((${#cfg[@]} > 0)); then - CONFIG=${cfg[0]} - fi -else - CONFIG="$CONFIG $*" -fi - -if [ "${CONFIG}" == "" ]; then - echo "ERROR: Configurations (CONFIGS) are not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -function cleanup() { - pkill -9 -f "Dyardstick.driver" -} - -trap "cleanup; exit" SIGHUP SIGINT SIGTERM SIGQUIT SIGKILL - -# Define logs directory. -LOGS_BASE=${SCRIPT_DIR}/../output/logs-$(date +"%Y%m%d-%H%M%S") - -LOGS_DIR=${LOGS_BASE}/logs_drivers - -if [ ! -d "${LOGS_DIR}" ]; then - mkdir -p ${LOGS_DIR} -fi - -if [[ "${OUTPUT_FOLDER}" == "" ]] && [[ ${CONFIG} != *'-of '* ]] && [[ ${CONFIG} != *'--outputFolder '* ]]; then - results_folder=${SCRIPT_DIR}/../output/results-$(date +"%Y%m%d-%H%M%S") - - OUTPUT_FOLDER="--outputFolder ${results_folder}" -fi - -CUR_DIR=$(pwd) - -id=0 - -IFS=',' read -ra configs0 <<< "${CONFIGS}" -for cfg in "${configs0[@]}"; -do - now=`date +'%H%M%S'` - - cfgParams="${OUTPUT_FOLDER} -id ${id} ${cfg}" - - suffix=`echo "${cfgParams}" | tail -c 60 | sed 's/ *$//g'` - - file_log=${LOGS_DIR}"/"${now}"_id"${id}"_driver.log" - - echo "<"$(date +"%H:%M:%S")"> Starting driver config '..."${suffix}"' with id=${id}" - echo "<"$(date +"%H:%M:%S")"> Log file: "${file_log} - - MAIN_CLASS=org.yardstickframework.BenchmarkDriverStartUp JVM_OPTS=${JVM_OPTS}${DRIVER_JVM_OPTS}" -Dyardstick.driver${id}" CP=${CP} \ - CUR_DIR=${CUR_DIR} PROPS_ENV0=${PROPS_ENV} \ - ${SCRIPT_DIR}/benchmark-bootstrap.sh ${cfgParams} --config ${CONFIG_INCLUDE} > ${file_log} 2>& 1 & - - HOST_NAME=localhost ${SCRIPT_DIR}/benchmark-wait-driver-up.sh - - echo "<"$(date +"%H:%M:%S")"> Driver with id=${id} is started" - - HOST_NAME=localhost ${SCRIPT_DIR}/benchmark-wait-driver-finish.sh - - echo "<"$(date +"%H:%M:%S")"> Driver with id=${id} is stopped" - - id=$((1 + $id)) -done - -echo "<"$(date +"%H:%M:%S")"> All drivers are stopped" diff --git a/bin/benchmark-manual-servers-start.bat b/bin/benchmark-manual-servers-start.bat deleted file mode 100644 index df28c7e..0000000 --- a/bin/benchmark-manual-servers-start.bat +++ /dev/null @@ -1,158 +0,0 @@ -:: Licensed under the Apache License, Version 2.0 (the "License"); -:: you may not use this file except in compliance with the License. -:: You may obtain a copy of the License at -:: -:: http://www.apache.org/licenses/LICENSE-2.0 -:: -:: Unless required by applicable law or agreed to in writing, software -:: distributed under the License is distributed on an "AS IS" BASIS, -:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -:: See the License for the specific language governing permissions and -:: limitations under the License. - -:: -:: Script that starts BenchmarkServers on a local machine. -:: This script expects first argument to be a path to run properties file. -:: Second argument is optional and defines number of starting servers. -:: - -@echo off - -:: Define script directory. -set SCRIPT_DIR=%~dp0 -set SCRIPT_DIR=%SCRIPT_DIR:~0,-1% - -set CONFIG_INCLUDE=%1 - -setlocal - -set or=false -if "%CONFIG_INCLUDE%"=="-h" set or=true -if "%CONFIG_INCLUDE%"=="--help" set or=true - -if "%or%"=="true" ( - echo Usage: benchmark-manual-servers-start.bat [PROPERTIES_FILE_PATH] - echo Script that starts BenchmarkServers on a local machine. - - exit /b -) - -endlocal - -set now0=%time: =0% - -if not defined CONFIG_INCLUDE ( - set CONFIG_INCLUDE=%SCRIPT_DIR%\..\config\benchmark-win.properties - echo ^<%now0:~0,2%:%now0:~3,2%:%now0:~6,2%^>^ Using default properties file: config\benchmark-win.properties -) - -if not exist "%CONFIG_INCLUDE%" ( - echo ERROR: Properties file is not found. - echo Type \"--help\" for usage. - exit /b -) - -shift - -set CONFIG_TMP=tmp.%RANDOM%.bat - -echo off > %CONFIG_TMP% - -type %CONFIG_INCLUDE% >> %CONFIG_TMP% - -call "%CONFIG_TMP%" > nul 2>&1 - -del %CONFIG_TMP% - -if not defined CONFIG ( - for /f "tokens=1 delims=," %%a in ("%CONFIGS%") do ( - set CONFIG=%%a - ) -) - -if not defined CONFIG ( - echo ERROR: Configurations ^(CONFIGS^) are not defined in properties file. - echo Type \"--help\" for usage. - exit /b -) - -if "%1"=="" ( - if not defined SERVER_HOSTS ( - set SERVER_NODES=1 - ) else ( - setlocal enabledelayedexpansion - - set srv_num=0 - - set hosts=%SERVER_HOSTS% - - :loop.configs.next - for /f "tokens=1* delims=," %%a in ("%hosts%") do ( - set hosts=%%b - - if "%%a"=="localhost" ( - set /a srv_num+=1 - ) else if "%%a"=="127.0.0.1" ( - set /a srv_num+=1 - ) else ( - for /f "skip=1 delims={}, " %%A in ('wmic nicconfig get ipaddress') do for /f "tokens=1" %%B in ("%%~A") do set "ip=%%B" - - if "%%a"=="!ip!" ( - set /a srv_num+=1 - ) else ( - for /f %%i in ('hostname') do set host_name=%%i - - if "%%a"=="!host_name!" ( - set /a srv_num+=1 - ) - ) - ) - ) - - if defined hosts ( - goto loop.configs.next - ) - - endlocal & set srv_num=%srv_num% - ) -) else ( - set SERVER_NODES=%1 -) - -if defined srv_num ( - set SERVER_NODES=%srv_num% -) - -if %SERVER_NODES% LSS 1 ( - echo ERROR: Servers number is should be greater than 0: %SERVER_NODES% - echo Type \"--help\" for usage. - exit /b -) - -:: Define logs directory. -set now=%time: =0% -set LOGS_BASE=logs-%date:~10,4%%date:~4,2%%date:~7,2%-%now:~0,2%%now:~3,2%%now:~6,2% - -set LOGS_DIR=%SCRIPT_DIR%\..\%LOGS_BASE%\logs_servers - -if not exist "%LOGS_DIR%" ( - mkdir %LOGS_DIR% -) - -:: JVM options. -set JVM_OPTS=%JVM_OPTS% -Dyardstick.server - -set CUR_DIR=%cd% - -setlocal enabledelayedexpansion - -for /L %%i IN (1,1,%SERVER_NODES%) DO ( - set file_log=%LOGS_DIR%\%%i_server.log - - set now=%time: =0% - echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ Starting server config '%CONFIG%' - echo ^<%now:~0,2%:%now:~3,2%:%now:~6,2%^>^ Log file: !file_log! - - start /min /low cmd /c ^ - "set MAIN_CLASS=org.yardstickframework.BenchmarkServerStartUp && set JVM_OPTS=%JVM_OPTS%%SERVER_JVM_OPTS% && set CP=%CP% && set CUR_DIR=%CUR_DIR% && %SCRIPT_DIR%\benchmark-bootstrap.bat %CONFIG% --config %CONFIG_INCLUDE% ^>^> !file_log! 2^>^&1" -) \ No newline at end of file diff --git a/bin/benchmark-manual-servers-start.sh b/bin/benchmark-manual-servers-start.sh deleted file mode 100755 index 028a283..0000000 --- a/bin/benchmark-manual-servers-start.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that starts BenchmarkServers on a local machine. -# This script expects first argument to be a path to run properties file. -# Second argument is optional and defines number of starting servers. -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -CONFIG_INCLUDE=$1 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-manual-servers-start.sh [PROPERTIES_FILE_PATH]" - echo "Script that starts BenchmarkServers on a local machine." - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: config/benchmark.properties" -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file is not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -shift - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -if ! [[ -d ${SCRIPT_DIR}/../output ]] -then - echo "<"$(date +"%H:%M:%S")"> Creating output directory" - mkdir ${SCRIPT_DIR}/../output -fi - -if [ "${CONFIG}" == "" ]; then - IFS=',' read -ra cfg <<< "${CONFIGS}" - - if ((${#cfg[@]} > 0)); then - CONFIG=${cfg[0]} - fi -else - CONFIG="$CONFIG $*" -fi - -if [ "${CONFIG}" == "" ]; then - echo "ERROR: Configurations (CONFIGS) are not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ -z "$1" ]; then - if [ "${SERVER_HOSTS}" == "" ]; then - SERVER_NODES=1 - else - srv_num=0 - - IFS=',' read -ra hosts <<< "${SERVER_HOSTS}" - for host in "${hosts[@]}"; - do - if [ "${host}" == "localhost" ] || [ "${host}" == "127.0.0.1" ]; then - srv_num=$((1 + $srv_num)) - else - ip=$(hostname --ip-address) - - host_name=$(hostname) - - if [ "${host}" == "${ip}" ] || [ "${host}" == "${host_name}" ]; then - srv_num=$((1 + $srv_num)) - fi - fi - done - - SERVER_NODES=${srv_num} - fi -else - SERVER_NODES=$1 -fi - -if ((${SERVER_NODES} < 1)); then - echo "ERROR: Servers number is should be greater than 0:" ${SERVER_NODES} - echo "Type \"--help\" for usage." - exit 1 -fi - -function cleanup() { - pkill -9 -f "Dyardstick.server" -} - -trap "cleanup; exit" SIGHUP SIGINT SIGTERM SIGQUIT SIGKILL - -# Define logs directory. -LOGS_BASE=${SCRIPT_DIR}/../output/logs-$(date +"%Y%m%d-%H%M%S") - -LOGS_DIR=${LOGS_BASE}/logs_servers - -if [ ! -d "${LOGS_DIR}" ]; then - mkdir -p ${LOGS_DIR} -fi - -CUR_DIR=$(pwd) - -for id in $(eval echo {1..$SERVER_NODES}); -do - CONFIG_PRM="-id ${cntr} ${CONFIG}" - - suffix=`echo "${CONFIG}" | tail -c 60 | sed 's/ *$//g'` - - file_log=${LOGS_DIR}"/"${id}"_server.log" - - echo "<"$(date +"%H:%M:%S")"> Starting server config '..."${suffix}"' with id=${id}" - echo "<"$(date +"%H:%M:%S")"> Log file: "${file_log} - - MAIN_CLASS=org.yardstickframework.BenchmarkServerStartUp JVM_OPTS=${JVM_OPTS}${SERVER_JVM_OPTS}" -Dyardstick.server${id}" CP=${CP} \ - CUR_DIR=${CUR_DIR} PROPS_ENV0=${PROPS_ENV} \ - nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh ${CONFIG_PRM} --config ${CONFIG_INCLUDE} > ${file_log} 2>& 1 & -done diff --git a/bin/benchmark-run-all.sh b/bin/benchmark-run-all.sh deleted file mode 100755 index 1276862..0000000 --- a/bin/benchmark-run-all.sh +++ /dev/null @@ -1,212 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that starts BenchmarkServers on remote machines, runs BenchmarkDriver and stops the servers on remote machines. -# This procedure is performed for all configurations defined in run properties file. -# This script expects the argument to be a path to run properties file which contains -# the list of remote nodes to start server on and the list of configurations. -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) -MAIN_DIR=$(cd ${SCRIPT_DIR}/../; pwd) - -CONFIG_INCLUDE=$1 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-run-all.sh [PROPERTIES_FILE_PATH]" - echo "By default, all the necessary files will be automatically uploaded from this host" - echo "to every other remote host to the same path." - echo "If you prefer to do it manually set the AUTO_COPY variable in property file to `false`." - echo "For more information check the Yardstick framework site:" - echo "https://github.com/gridgain/yardstick" - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: config/benchmark.properties" -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -if [ "${CONFIGS}" == "" ]; then - echo "ERROR: Configurations (CONFIGS) are not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if ! [[ -d ${SCRIPT_DIR}/../output ]] -then - echo "<"$(date +"%H:%M:%S")"> Creating output directory" - mkdir ${SCRIPT_DIR}/../output -fi - -# Creating an array of IP addresses of the remote hosts from SERVER_HOSTS and DRIVER_HOSTS variables. -function define_ips() -{ - # Defining IP of the local machine. - local local_ip_addresses=`ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'` - local comma_separated_ips="${SERVER_HOSTS},${DRIVER_HOSTS}" - local ips=${comma_separated_ips//,/ } - local uniq_ips=`echo "${ips[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '` - for local_ip in ${local_ip_addresses[@]} - do - uniq_ips=( "${uniq_ips[@]/$local_ip}" ) - done - echo ${uniq_ips[@]} -} - -# Deleting all the yardstick directories from the working directory on remote host -# $1 IP address of the remote host -function clear_remote_work_directory() -{ - ssh -o StrictHostKeyChecking=no $1 rm -rf $MAIN_DIR/bin - ssh -o StrictHostKeyChecking=no $1 rm -rf $MAIN_DIR/config - ssh -o StrictHostKeyChecking=no $1 rm -rf $MAIN_DIR/libs - ssh -o StrictHostKeyChecking=no $1 rm -rf $MAIN_DIR/output - ssh -o StrictHostKeyChecking=no $1 rm -rf $MAIN_DIR/work -} - -# Copying working directory to remote hosts. -function copy_to_hosts() -{ - IFS=' ' read -ra ips_array <<< $(define_ips) - for ip in ${ips_array[@]} - do - if [[ $ip != "127.0.0.1" && $ip != "localhost" ]] - then - echo "<"$(date +"%H:%M:%S")"> Copying yardstick to the host ${ip}" - ssh -o StrictHostKeyChecking=no $ip mkdir -p $MAIN_DIR - clear_remote_work_directory $ip - scp -o StrictHostKeyChecking=no -rq $MAIN_DIR/* $ip:$MAIN_DIR - fi - done -} - -if [[ $AUTO_COPY != false ]]; then - copy_to_hosts -fi - -date_time=$(date +"%Y%m%d-%H%M%S") -result_dir_name=results-$date_time -log_dir_name=logs-$date_time - -results_folder=${SCRIPT_DIR}/../output/$result_dir_name -LOGS_BASE=${SCRIPT_DIR}/../output/$log_dir_name - -export LOGS_BASE - -if [[ "$RESTART_SERVERS" == "" ]]; then - RESTART_SERVERS="false" -fi - - -if [[ "$RESTART_SERVERS" == "false" ]]; then - /bin/bash ${SCRIPT_DIR}/benchmark-servers-start.sh ${CONFIG_INCLUDE} - - sleep 3s -fi - -IFS=',' read -ra configs0 <<< "${CONFIGS}" -for cfg in "${configs0[@]}"; -do - CONFIG=${cfg} - - if [[ ${CONFIG} != *'-of '* ]] && [[ ${CONFIG} != *'--outputFolder '* ]]; then - OUTPUT_FOLDER="--outputFolder ${results_folder}" - fi - - export CONFIG - export OUTPUT_FOLDER - - if [[ "$RESTART_SERVERS" != "false" ]]; then - /bin/bash ${SCRIPT_DIR}/benchmark-servers-start.sh ${CONFIG_INCLUDE} - - sleep 3s - fi - - /bin/bash ${SCRIPT_DIR}/benchmark-drivers-start.sh ${CONFIG_INCLUDE} - - if [[ "$RESTART_SERVERS" != "false" ]]; then - /bin/bash ${SCRIPT_DIR}/benchmark-servers-stop.sh ${CONFIG_INCLUDE} - - sleep 1s - fi -done - -if [[ "$RESTART_SERVERS" == "false" ]]; then - /bin/bash ${SCRIPT_DIR}/benchmark-servers-stop.sh ${CONFIG_INCLUDE} - - sleep 1s -fi - -# Collecting results and logs from the remote hosts -function collect_results() -{ - mkdir -p $MAIN_DIR/output/${log_dir_name} - mkdir -p $MAIN_DIR/output/${result_dir_name} - - IFS=' ' read -ra ips_array <<< $(define_ips) - for ip in ${ips_array[@]} - do - if [[ $ip != "127.0.0.1" && $ip != "localhost" ]] - then - echo "<"$(date +"%H:%M:%S")"> Collecting results from the host ${ip}" - # Checking if current IP belongs to the driver-host and therefore there should be the "results" directory - if [[ ${DRIVER_HOSTS} == *"$ip"* ]]; then - scp -o StrictHostKeyChecking=no -rq $ip:$results_folder/../../output/$result_dir_name/* $MAIN_DIR/output/$result_dir_name - fi - - scp -o StrictHostKeyChecking=no -rq $ip:$LOGS_BASE/../../output/$log_dir_name/* $MAIN_DIR/output/$log_dir_name - - clear_remote_work_directory $ip - fi - done -} - -if [[ $AUTO_COPY != false ]]; then - collect_results -fi - -# Creating graphs. -function create_charts() -{ - if [ -d $results_folder ] - then - OUT_DIR=$(cd $results_folder/../; pwd) - echo "<"$(date +"%H:%M:%S")"> Creating charts" - . ${SCRIPT_DIR}/jfreechart-graph-gen.sh -gm STANDARD -i $results_folder >> /dev/null - . ${SCRIPT_DIR}/jfreechart-graph-gen.sh -i $results_folder >> /dev/null - echo "<"$(date +"%H:%M:%S")"> Moving chart directory to the ${MAIN_DIR}/output/results-${date_time} directory." - mv $MAIN_DIR/output/results-compound* $MAIN_DIR/output/results-$date_time - fi -} - -if [[ $AUTO_COPY != false ]]; then - create_charts -fi diff --git a/bin/benchmark-server-restarter-start.sh b/bin/benchmark-server-restarter-start.sh deleted file mode 100755 index 9603a74..0000000 --- a/bin/benchmark-server-restarter-start.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that starts server restarter for given host name. -# This script expects the arguments to be -# - server host name to be restarted -# - config to start new instances of server -# - warmup delay -# - restart period -# - a path to run properties file which contains the list of remote nodes to start server on -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -HOST_NAME=$1 -ID=$2 -CONFIG=$3 -WARMPUP_DELAY=$4 -PAUSE=$5 -PERIOD=$6 -CONFIG_INCLUDE=$7 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-server-restarter-start.sh [HOST_NAME] [ID] [CONFIG] [DELAY] [PAUSE] [PERIOD] [PROPERTIES_FILE_PATH]" - echo "Script that starts server restarter according to given paramethers." - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: config/benchmark.properties" -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file is not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -shift - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -if [[ "$RESTART_SERVERS" == "" ]]; then - RESTART_SERVERS="false" -fi - -# Define user to establish remote ssh session. -if [ "${REMOTE_USER}" == "" ]; then - REMOTE_USER=$(whoami) -fi - -if [ "${SERVER_HOSTS}" == "" ]; then - echo "ERROR: Benchmark hosts (SERVER_HOSTS) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${REMOTE_USER}" == "" ]; then - echo "ERROR: Remote user (REMOTE_USER) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${CONFIG}" == "" ]; then - echo "ERROR: Config (CONFIG) is not defined. Restarter should be run with specified config." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${HOST_NAME}" == "" ]; then - echo "ERROR: HOST_NAME are not defined." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${WARMPUP_DELAY}" == "" ]; then - echo "ERROR: warmup_delay are not defined." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${PERIOD}" == "" ]; then - echo "ERROR: PERIOD are not defined." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${SERVERS_LOGS_DIR}" = "" ]; then - SERVERS_LOGS_DIR=${LOGS_BASE}/logs_servers -fi - -CUR_DIR=$(pwd) - -echo "<"$(date +"%H:%M:%S")"> Server restarer started for ${HOST_NAME} with id=${ID}." - -# -# Main. -# - -if [[ ${HOST_NAME} = "127.0.0.1" || ${HOST_NAME} = "localhost" ]] - then - mkdir -p ${SERVERS_LOGS_DIR} - else - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${HOST_NAME} mkdir -p ${SERVERS_LOGS_DIR} - fi - -DS="" - -# Extract description. -if [[ "${RESTART_SERVERS}" != "false" ]]; then - IFS=' ' read -ra cfg0 <<< "${CONFIG}" - for cfg00 in "${cfg0[@]}"; - do - if [[ ${found} == 'true' ]]; then - found="" - DS=${cfg00} - fi - - if [[ ${cfg00} == '-ds' ]] || [[ ${cfg00} == '--descriptions' ]]; then - found="true" - fi - done -fi - -cntr=1 - -sleep ${WARMPUP_DELAY} - -while [ true ] -do - echo "<"$(date +"%H:%M:%S")"> Killing server on "${HOST_NAME}" with id=${ID}" - - # Kill only first found yardstick.server on the host - - if [[ ${HOST_NAME} = "127.0.0.1" || ${HOST_NAME} = "localhost" ]]; then - pkill -9 -f "Dyardstick.server${ID} " - else - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${HOST_NAME} "pkill -9 -f 'Dyardstick.server${ID} '" - fi - - sleep ${PAUSE} # Wait for process stopping. - - suffix=`echo "${CONFIG}" | tail -c 60 | sed 's/ *$//g'` - - echo "<"$(date +"%H:%M:%S")"> Starting server config '...${suffix}' on ${HOST_NAME} with id=${ID}" - - now=`date +'%H%M%S'` - - server_file_log=${SERVERS_LOGS_DIR}"/"${now}"_id"${ID}"-"${cntr}"_"${HOST_NAME}"_"${DS}".log" - - if [[ ${JVM_OPTS} == *"PrintGC"* ]]; then - GC_JVM_OPTS=" -Xloggc:${SERVERS_LOGS_DIR}/gc-${now}-server-id${ID}-${HOST_NAME}-${DS}.log" - fi - - if [[ ${HOST_NAME} = "127.0.0.1" || ${HOST_NAME} = "localhost" ]]; then - SAVED_JVM_OPTS=${JVM_OPTS} - - JAVA_HOME=${JAVA_HOME} MAIN_CLASS='org.yardstickframework.BenchmarkServerStartUp' \ - JVM_OPTS="${JVM_OPTS} ${GC_JVM_OPTS} ${SERVER_JVM_OPTS} -Dyardstick.server${id} " CP=${CP} CUR_DIR=${CUR_DIR} \ - PROPS_ENV0=${PROPS_ENV} nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh ${CONFIG_PRM} "--config" ${CONFIG_INCLUDE} \ - "--logsFolder" ${LOGS_DIR} "--remoteuser" ${REMOTE_USER} "--remoteHostName" ${host_name} > ${file_log} 2>& 1 & - - JVM_OPTS=${SAVED_JVM_OPTS} - else - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${HOST_NAME} \ - "JAVA_HOME='${JAVA_HOME}'" \ - "MAIN_CLASS='org.yardstickframework.BenchmarkServerStartUp'" "JVM_OPTS='${JVM_OPTS} ${GC_JVM_OPTS} ${SERVER_JVM_OPTS} -Dyardstick.server${ID} '" "CP='${CP}'" \ - "CUR_DIR='${CUR_DIR}'" "PROPS_ENV0='${PROPS_ENV}'" \ - "nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh ${CONFIG} "--config" ${CONFIG_INCLUDE} > ${server_file_log} 2>& 1 &" - fi - - echo "<"$(date +"%H:%M:%S")"> Server on ${HOST_NAME} with id=${ID} was started." - - cntr=$((1 + $cntr)) - - sleep ${PERIOD} -done diff --git a/bin/benchmark-servers-start.sh b/bin/benchmark-servers-start.sh deleted file mode 100755 index f1e6e5c..0000000 --- a/bin/benchmark-servers-start.sh +++ /dev/null @@ -1,214 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that starts BenchmarkServer on remote machines. -# This script expects the argument to be a path to run properties file which contains -# the list of remote nodes to start server on and the list of configurations. -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -CONFIG_INCLUDE=$1 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-servers-start.sh [PROPERTIES_FILE_PATH]" - echo "Script that starts BenchmarkServer on remote machines." - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: config/benchmark.properties" -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file is not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -shift - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -if [[ "$RESTART_SERVERS" == "" ]]; then - RESTART_SERVERS="false" -fi - -# Define user to establish remote ssh session. -if [ "${REMOTE_USER}" == "" ]; then - REMOTE_USER=$(whoami) -fi - -if [ "${SERVER_HOSTS}" == "" ]; then - echo "ERROR: Benchmark hosts (SERVER_HOSTS) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${REMOTE_USER}" == "" ]; then - echo "ERROR: Remote user (REMOTE_USER) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${CONFIG}" == "" ]; then - IFS=',' read -ra cfg <<< "${CONFIGS}" - - if ((${#cfg[@]} > 0)); then - CONFIG=${cfg[0]} - fi -else - CONFIG="$CONFIG $*" -fi - -if [ "${CONFIG}" == "" ]; then - echo "ERROR: Configurations (CONFIGS) are not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -function cleanup() { - pkill -9 -f "Dyardstick.server" - - IFS=',' read -ra hosts0 <<< "${SERVER_HOSTS}" - for host_name in "${hosts0[@]}"; - do - `ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} pkill -9 -f "Dyardstick.server"` - done -} - -trap "cleanup; exit" SIGHUP SIGINT SIGTERM SIGQUIT SIGKILL - -# Define logs directory. -LOGS_DIR=${LOGS_BASE}/logs_servers - -if [ "${RESTARTERS_LOGS_DIR}" = "" ]; then - RESTARTERS_LOGS_DIR=${LOGS_BASE}/logs_restarters -fi - -if [[ "${RESTART_SERVERS}" != "false" ]] && [[ "${RESTART_SERVERS}" != "true" ]]; then - mkdir -p ${RESTARTERS_LOGS_DIR} -fi - -CUR_DIR=$(pwd) - -DS="" - -id=0 - -IFS=',' read -ra hosts0 <<< "${SERVER_HOSTS}" - -JVM_OPTS_ORIG="$JVM_OPTS" - -for host_name in "${hosts0[@]}"; -do - CONFIG_PRM="-id ${id} ${CONFIG}" - - suffix=`echo "${CONFIG}" | tail -c 60 | sed 's/ *$//g'` - - echo "<"$(date +"%H:%M:%S")"> Starting server config '..."${suffix}"' on "${host_name}" with id=${id}" - - now=`date +'%H%M%S'` - - # Extract description. - IFS=' ' read -ra cfg0 <<< "${CONFIG}" - for cfg00 in "${cfg0[@]}"; - do - if [[ ${found} == 'true' ]]; then - found="" - DS=${cfg00} - fi - - if [[ ${cfg00} == '-ds' ]] || [[ ${cfg00} == '--descriptions' ]]; then - found="true" - fi - done - - file_log=${LOGS_DIR}"/"${now}"-id"${id}"-"${host_name}"-"${DS}".log" - - if [[ ${JVM_OPTS_ORIG} == *"#filename#"* ]] - then - filename_ptrn=${LOGS_DIR}/${now}-server-id${id}-${host_name}-${DS} - JVM_OPTS="$(echo $JVM_OPTS_ORIG | sed s=#filename#=${filename_ptrn}=g)" - fi - - if [[ ${JVM_OPTS} == *"PrintGC"* ]]; then - GC_JVM_OPTS=" -Xloggc:${LOGS_DIR}/gc-${now}-server-id${id}-${host_name}-${DS}.log" - fi - - if [[ ${host_name} = "127.0.0.1" || ${host_name} = "localhost" ]]; then - mkdir -p ${LOGS_DIR} - - SAVED_JVM_OPTS=${JVM_OPTS} - - JAVA_HOME=${JAVA_HOME} MAIN_CLASS='org.yardstickframework.BenchmarkServerStartUp' \ - JVM_OPTS="${JVM_OPTS} ${GC_JVM_OPTS} ${SERVER_JVM_OPTS} -Dyardstick.server${id} " CP=${CP} CUR_DIR=${CUR_DIR} \ - PROPS_ENV0=${PROPS_ENV} nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh \ - ${CONFIG_PRM} "--config" ${CONFIG_INCLUDE} "--logsFolder" ${LOGS_DIR} \ - "--remoteuser" ${REMOTE_USER} "--remoteHostName" ${host_name} > ${file_log} 2>& 1 & - - JVM_OPTS=${SAVED_JVM_OPTS} - else - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} mkdir -p ${LOGS_DIR} - - ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} \ - "JAVA_HOME='${JAVA_HOME}'" \ - "MAIN_CLASS='org.yardstickframework.BenchmarkServerStartUp'" "JVM_OPTS='${JVM_OPTS} ${GC_JVM_OPTS} ${SERVER_JVM_OPTS} -Dyardstick.server${id} '" \ - "CP='${CP}'" "CUR_DIR='${CUR_DIR}'" "PROPS_ENV0='${PROPS_ENV}'" \ - "nohup ${SCRIPT_DIR}/benchmark-bootstrap.sh ${CONFIG_PRM} "--config" ${CONFIG_INCLUDE} "--logsFolder" ${LOGS_DIR} \ - "--remoteuser" ${REMOTE_USER} "--remoteHostName" ${host_name} > ${file_log} 2>& 1 &" - fi - - # Start a restarter if needed. - if [[ "${RESTART_SERVERS}" != "true" ]] && [[ "${RESTART_SERVERS}" != "false" ]]; then - IFS=',' read -ra hostsToRestart0 <<< "${RESTART_SERVERS}" - for host2Timeout in "${hostsToRestart0[@]}"; - do - IFS=':' read -ra hostToRestart <<< "${host2Timeout}" - - host_to_restart=${hostToRestart[0]} - id_to_restart=${hostToRestart[1]} - delay=${hostToRestart[2]} - pause=${hostToRestart[3]} - period=${hostToRestart[4]} - - if [[ "${host_to_restart}" = "${host_name}" ]] && [[ "${id_to_restart}" = "${id}" ]] ; then - if [[ "${delay}" != "" ]] && [[ "${pause}" != "" ]] && [[ "${period}" != "" ]] ; then - file_log=${RESTARTERS_LOGS_DIR}"/"${now}"_id"${id}"_"${host_name}".log" - - nohup ${SCRIPT_DIR}/benchmark-server-restarter-start.sh "${host_name}" "${id}" "${CONFIG_PRM}" \ - "${delay}" "${pause}" "${period}" "${CONFIG_INCLUDE}" > ${file_log} 2>& 1 & - - echo "<"$(date +"%H:%M:%S")"> Server restarter is started for ${host_to_restart} \ - with id=${id} and config '...${suffix}', warmup delay ${delay} sec., pause ${pause} sec. and period ${period} sec." - else - echo "<"$(date +"%H:%M:%S")"> Failed to start a server restarter for host \ - ${host_to_restart} with id=${id}. Next params should not be empty: [warmup delay='${delay}', pause='${pause}', period='${period}']" - fi - fi - done - fi - # End of restarter logic. - - id=$((1 + $id)) -done diff --git a/bin/benchmark-servers-stop.sh b/bin/benchmark-servers-stop.sh deleted file mode 100755 index 8f65ebe..0000000 --- a/bin/benchmark-servers-stop.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that stops BenchmarkServer on remote machines. -# This script expects the argument to be a path to run properties file which contains -# the list of remote nodes to start server on and the list of configurations. -# - -# Define script directory. -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -CONFIG_INCLUDE=$1 - -if [ "${CONFIG_INCLUDE}" == "-h" ] || [ "${CONFIG_INCLUDE}" == "--help" ]; then - echo "Usage: benchmark-servers-stop.sh [PROPERTIES_FILE_PATH]" - echo "Script that stops BenchmarkServer on remote machines." - exit 1 -fi - -if [ "${CONFIG_INCLUDE}" == "" ]; then - CONFIG_INCLUDE=${SCRIPT_DIR}/../config/benchmark.properties - echo "<"$(date +"%H:%M:%S")"> Using default properties file: 'config/benchmark.properties'." -fi - -if [ ! -f $CONFIG_INCLUDE ]; then - echo "ERROR: Properties file is not found." - echo "Type \"--help\" for usage." - exit 1 -fi - -shift - -CONFIG_TMP=`mktemp tmp.XXXXXXXX` - -cp $CONFIG_INCLUDE $CONFIG_TMP -chmod +x $CONFIG_TMP - -. $CONFIG_TMP -rm $CONFIG_TMP - -if [[ "$RESTART_SERVERS" == "" ]]; then - RESTART_SERVERS="false" -fi - -# Define user to establish remote ssh session. -if [ "${REMOTE_USER}" == "" ]; then - REMOTE_USER=$(whoami) -fi - -if [ "${SERVER_HOSTS}" == "" ]; then - echo "ERROR: Benchmark hosts (SERVER_HOSTS) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -if [ "${REMOTE_USER}" == "" ]; then - echo "ERROR: Remote user (REMOTE_USER) is not defined in properties file." - echo "Type \"--help\" for usage." - exit 1 -fi - -pkill -9 -f "benchmark-server-restarter-start.sh" - -if [[ "${RESTART_SERVERS}" != "true" ]] && [[ "${RESTART_SERVERS}" != "false" ]]; then - echo "<"$(date +"%H:%M:%S")"> All server restartets are stopped." -fi - -IFS=',' read -ra hosts0 <<< "${SERVER_HOSTS}" -for host_name in "${hosts0[@]}"; -do - if [[ ${host_name} = "127.0.0.1" || ${host_name} = "localhost" ]] - then - pkill -9 -f "Dyardstick.server" - - else - `ssh -o PasswordAuthentication=no ${REMOTE_USER}"@"${host_name} pkill -9 -f "Dyardstick.server"` - fi - - echo "<"$(date +"%H:%M:%S")"> Server is stopped on "${host_name} -done diff --git a/bin/benchmark-wait-driver-finish.bat b/bin/benchmark-wait-driver-finish.bat deleted file mode 100644 index 8eb9147..0000000 --- a/bin/benchmark-wait-driver-finish.bat +++ /dev/null @@ -1,26 +0,0 @@ -:: Licensed under the Apache License, Version 2.0 (the "License"); -:: you may not use this file except in compliance with the License. -:: You may obtain a copy of the License at -:: -:: http://www.apache.org/licenses/LICENSE-2.0 -:: -:: Unless required by applicable law or agreed to in writing, software -:: distributed under the License is distributed on an "AS IS" BASIS, -:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -:: See the License for the specific language governing permissions and -:: limitations under the License. - -:: -:: Script that waits for a driver to finish. -:: - -@echo off - -:loop - -for /f %%i in ('wmic process where (name^="java.exe" and commandline like "%%Dyardstick.driver%%"^) get ProcessId 2^>^&1 ^| findstr [0-9]') do ( - :: Sleep. - ping 192.0.2.2 -n 1 -w 1000 > nul - - goto loop -) \ No newline at end of file diff --git a/bin/benchmark-wait-driver-finish.sh b/bin/benchmark-wait-driver-finish.sh deleted file mode 100755 index 85c7a36..0000000 --- a/bin/benchmark-wait-driver-finish.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Script that waits for a driver to finish. -# - -while pgrep -f "Dyardstick.driver" > /dev/null 2>&1; do - sleep 1s -done diff --git a/bin/benchmark-wait-driver-up.bat b/bin/benchmark-wait-driver-up.bat deleted file mode 100644 index b49bcf3..0000000 --- a/bin/benchmark-wait-driver-up.bat +++ /dev/null @@ -1,51 +0,0 @@ -:: Licensed under the Apache License, Version 2.0 (the "License"); -:: you may not use this file except in compliance with the License. -:: You may obtain a copy of the License at -:: -:: http://www.apache.org/licenses/LICENSE-2.0 -:: -:: Unless required by applicable law or agreed to in writing, software -:: distributed under the License is distributed on an "AS IS" BASIS, -:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -:: See the License for the specific language governing permissions and -:: limitations under the License. - -:: -:: Script that waits for a driver to start. -:: - -@echo off - -set max_count=20 - -set timeout=10 - -setlocal enabledelayedexpansion - -set /a cnt=0 - -:loop - -for /f "skip=1" %%i in ('wmic process where (name^="java.exe" and commandline like "%%Dyardstick.driver%%"^) get ProcessId 2^>^&1') do ( - echo %%i | findstr [0-9] > nul - - if not !errorlevel! equ 0 ( - if !cnt! == %max_count% ( - echo ERROR: Driver process has not started on %HOST_NAME% during %timeout% seconds. - echo Type \"--help\" for usage. - - exit 1 - ) - - :: Sleep. - ping 192.0.2.2 -n 1 -w 500 > nul - - set /a cnt+=1 - - goto loop - ) else ( - goto end - ) -) - -:end \ No newline at end of file diff --git a/bin/build-and-run.sh b/bin/build-and-run.sh new file mode 100755 index 0000000..89c6576 --- /dev/null +++ b/bin/build-and-run.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Script that starts BenchmarkServer or BenchmarkDriver. +# + +SCRIPT_DIR=$(cd $(dirname "$0"); pwd) + +cd ${SCRIPT_DIR}/../ + +mvn clean install -DskipTests # -Dmaven.javadoc.skip=true + +cp /home/oostanin/.m2/repository/org/yardstickframework/yardstick/0.8.7/yardstick-0.8.7.jar /home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/libs/yardstick-0.8.7.jar + +cp -r /home/oostanin/yardstick/bin/* /home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/bin/ + +#cp -r /home/oostanin/yardstick/config/docker/* /home/oostanin/gg/incubator-ignite/modules/yardstick/config/docker/ +#cp -r /home/oostanin/yardstick/config/docker/* /home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/config/docker/ + +#cp /home/oostanin/gg/incubator-ignite/modules/yardstick/config/benchmark.properties /home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/config/benchmark.properties + +cd /home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly + +#/home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/bin/run-benchmarks.sh -h +#/home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/bin/run-benchmarks.sh -pf config/docker/benchmark.properties + +/home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/bin/run-benchmarks.sh +#/home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/bin/run-servers.sh + +#/home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/bin/run-benchmarks.sh -pf /home/oostanin/gg/incubator-ignite/modules/yardstick/target/assembly/config/docker/benchmark.properties + diff --git a/bin/clean-up.sh b/bin/clean-up.sh new file mode 100755 index 0000000..b51fcc6 --- /dev/null +++ b/bin/clean-up.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Script that starts BenchmarkServer or BenchmarkDriver. +# + +SCRIPT_DIR=$(cd $(dirname "$0"); pwd) + +source "${SCRIPT_DIR}"/functions.sh + +# +# Discover path to Java executable and check it's version. +# +checkJava + +ARGS=$* + +CP=${CP}":${SCRIPT_DIR}/../libs/*" + +# +# Assertions are disabled by default. +# If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. +# +ENABLE_ASSERTIONS="0" + +# +# Set '-ea' options if assertions are enabled. +# +if [ "${ENABLE_ASSERTIONS}" = "1" ]; then + JVM_OPTS="${JVM_OPTS} -ea" +fi + +export JAVA + +"$JAVA" ${JVM_OPTS} -cp ${CP} org.yardstickframework.runners.CleanUpRunner -sd $SCRIPT_DIR ${ARGS} diff --git a/bin/collect.sh b/bin/collect.sh new file mode 100755 index 0000000..11b9ef0 --- /dev/null +++ b/bin/collect.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Script that starts BenchmarkServer or BenchmarkDriver. +# + +SCRIPT_DIR=$(cd $(dirname "$0"); pwd) + +source "${SCRIPT_DIR}"/functions.sh + +# +# Discover path to Java executable and check it's version. +# +checkJava + +ARGS=$* + +CP=${CP}":${SCRIPT_DIR}/../libs/*" + +# +# JVM options. See http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp for more details. +# +# ADD YOUR/CHANGE ADDITIONAL OPTIONS HERE +# + +# +# Assertions are disabled by default. +# If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. +# +ENABLE_ASSERTIONS="0" + +# +# Set '-ea' options if assertions are enabled. +# +if [ "${ENABLE_ASSERTIONS}" = "1" ]; then + JVM_OPTS="${JVM_OPTS} -ea" +fi + +if [ -z "$PROPS_ENV" ]; then + if [ "$PROPS_ENV0" != "" ]; then + export PROPS_ENV=$PROPS_ENV0 + fi +fi + +export JAVA + +"$JAVA" ${JVM_OPTS} -cp ${CP} org.yardstickframework.runners.CollectRunner -sd $SCRIPT_DIR ${ARGS} diff --git a/bin/benchmark-bootstrap.sh b/bin/functions.sh old mode 100755 new mode 100644 similarity index 61% rename from bin/benchmark-bootstrap.sh rename to bin/functions.sh index 8f0af19..ecf03f1 --- a/bin/benchmark-bootstrap.sh +++ b/bin/functions.sh @@ -12,22 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# -# Script that starts BenchmarkServer or BenchmarkDriver. -# - -SCRIPT_DIR=$(cd $(dirname "$0"); pwd) - -if [ "${CUR_DIR}" != "" ]; then - cd ${CUR_DIR} -fi - -if [ "${MAIN_CLASS}" == "" ]; then - echo "ERROR: Java class is not defined." - echo "Type \"--help\" for usage." - exit 1 -fi - # # Discovers path to Java executable and checks it's version. # The function exports JAVA variable with path to Java executable. @@ -68,44 +52,3 @@ checkJava() { exit 1 fi } - -# -# Discover path to Java executable and check it's version. -# -checkJava - -ARGS=$* - -CP=${CP}":${SCRIPT_DIR}/../libs/*" - -# -# JVM options. See http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp for more details. -# -# ADD YOUR/CHANGE ADDITIONAL OPTIONS HERE -# -JVM_OPTS="-Xms2g -Xmx2g -server -Djava.net.preferIPv4Stack=true "${JVM_OPTS} - -# -# Assertions are disabled by default. -# If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. -# -ENABLE_ASSERTIONS="0" - -# -# Set '-ea' options if assertions are enabled. -# -if [ "${ENABLE_ASSERTIONS}" = "1" ]; then - JVM_OPTS="${JVM_OPTS} -ea" -fi - -if [ -z "$PROPS_ENV" ]; then - if [ "$PROPS_ENV0" != "" ]; then - export PROPS_ENV=$PROPS_ENV0 - fi -fi - -ARGS=${ARGS}" --currentFolder ${CUR_DIR} --scriptsFolder ${SCRIPT_DIR}" - -export JAVA - -"$JAVA" ${JVM_OPTS} -cp ${CP} ${MAIN_CLASS} ${ARGS} diff --git a/bin/benchmark-wait-driver-up.sh b/bin/run-benchmarks.sh similarity index 50% rename from bin/benchmark-wait-driver-up.sh rename to bin/run-benchmarks.sh index c6f68f6..c3c5daa 100755 --- a/bin/benchmark-wait-driver-up.sh +++ b/bin/run-benchmarks.sh @@ -13,25 +13,35 @@ # limitations under the License. # -# Script that waits for a driver to start. +# Script that starts Benchmark runner. # -i=1 +SCRIPT_DIR=$(cd $(dirname "$0"); pwd) -max_count=20 +source "${SCRIPT_DIR}"/functions.sh -sleep_time=0.5 +# +# Discover path to Java executable and check it's version. +# +checkJava + +ARGS=$* -for (( ; i < ${max_count}; i++ )) do - if pgrep -f "Dyardstick.driver" > /dev/null 2>&1; then - break - else - sleep ${sleep_time} - fi -done +CP=${CP}":${SCRIPT_DIR}/../libs/*" + +# +# Assertions are disabled by default. +# If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. +# +ENABLE_ASSERTIONS="0" -if ((${i} == ${max_count})); then - echo "ERROR: Driver process has not started on "${HOST_NAME}" during "$(echo "${max_count}*${sleep_time}" | bc)" seconds." - echo "Type \"--help\" for usage." - exit 1 +# +# Set '-ea' options if assertions are enabled. +# +if [ "${ENABLE_ASSERTIONS}" = "1" ]; then + JVM_OPTS="${JVM_OPTS} -ea" fi + +export JAVA + +"$JAVA" ${JVM_OPTS} -cp ${CP} org.yardstickframework.runners.FullRunner -sd $SCRIPT_DIR ${ARGS} diff --git a/bin/run-drivers.sh b/bin/run-drivers.sh new file mode 100755 index 0000000..b5a6220 --- /dev/null +++ b/bin/run-drivers.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Script that starts BenchmarkDrivers. +# + +SCRIPT_DIR=$(cd $(dirname "$0"); pwd) + +source "${SCRIPT_DIR}"/functions.sh + +# +# Discover path to Java executable and check it's version. +# +checkJava + +ARGS=$* + +CP=${CP}":${SCRIPT_DIR}/../libs/*" + +# +# Assertions are disabled by default. +# If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. +# +ENABLE_ASSERTIONS="0" + +# +# Set '-ea' options if assertions are enabled. +# +if [ "${ENABLE_ASSERTIONS}" = "1" ]; then + JVM_OPTS="${JVM_OPTS} -ea" +fi + +export JAVA + +"$JAVA" ${JVM_OPTS} -cp ${CP} org.yardstickframework.runners.DriverRunner -sd $SCRIPT_DIR ${ARGS} diff --git a/bin/run-servers.sh b/bin/run-servers.sh new file mode 100755 index 0000000..ab19a86 --- /dev/null +++ b/bin/run-servers.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Script that starts BenchmarkServers. +# + +SCRIPT_DIR=$(cd $(dirname "$0"); pwd) + +source "${SCRIPT_DIR}"/functions.sh + +# +# Discover path to Java executable and check it's version. +# +checkJava + +ARGS=$* + +CP=${CP}":${SCRIPT_DIR}/../libs/*" + +# +# Assertions are disabled by default. +# If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. +# +ENABLE_ASSERTIONS="0" + +# +# Set '-ea' options if assertions are enabled. +# +if [ "${ENABLE_ASSERTIONS}" = "1" ]; then + JVM_OPTS="${JVM_OPTS} -ea" +fi + +export JAVA + +"$JAVA" ${JVM_OPTS} -cp ${CP} org.yardstickframework.runners.ServerRunner -sd $SCRIPT_DIR ${ARGS} diff --git a/bin/benchmark-bootstrap.bat b/bin/test.bat similarity index 76% rename from bin/benchmark-bootstrap.bat rename to bin/test.bat index 34991b9..fa81079 100644 --- a/bin/benchmark-bootstrap.bat +++ b/bin/test.bat @@ -19,6 +19,8 @@ set SCRIPT_DIR=%~dp0 set SCRIPT_DIR=%SCRIPT_DIR:~0,-1% +set MAIN_CLASS=org.yardstickframework.runners.FullRunner + if defined CUR_DIR cd %CUR_DIR% if not defined MAIN_CLASS ( @@ -53,22 +55,4 @@ set ARGS=%* set CP=%CP%;%SCRIPT_DIR%\..\libs\* -:: -:: JVM options. See http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp for more details. -:: -:: ADD YOUR/CHANGE ADDITIONAL OPTIONS HERE -:: -set JVM_OPTS=-server -Djava.net.preferIPv4Stack=true %JVM_OPTS% - -:: -:: Assertions are disabled by default. -:: If you want to enable them - set 'ENABLE_ASSERTIONS' flag to '1'. -:: -set ENABLE_ASSERTIONS="0" - -:: -:: Set '-ea' options if assertions are enabled. -:: -if %ENABLE_ASSERTIONS% == "1" set JVM_OPTS=%JVM_OPTS% -ea - -"%JAVA_HOME%\bin\java.exe" %JVM_OPTS% -cp %CP% %MAIN_CLASS% %ARGS% +"%JAVA_HOME%\bin\java.exe" -cp %CP% %MAIN_CLASS% -sd %SCRIPT_DIR% %ARGS% diff --git a/config/docker/Dockerfile-driver b/config/docker/Dockerfile-driver new file mode 100644 index 0000000..7c12760 --- /dev/null +++ b/config/docker/Dockerfile-driver @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FROM airdock/oracle-jdk + +RUN apt-get update && apt-get install -y apt-transport-https dstat + + + + + + + + + diff --git a/config/docker/Dockerfile-server b/config/docker/Dockerfile-server new file mode 100644 index 0000000..acd993b --- /dev/null +++ b/config/docker/Dockerfile-server @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FROM airdock/oracle-jdk diff --git a/config/docker/benchmark.properties b/config/docker/benchmark.properties new file mode 100644 index 0000000..c3a38ef --- /dev/null +++ b/config/docker/benchmark.properties @@ -0,0 +1,44 @@ +# List of default probes. +BENCHMARK_DEFAULT_PROBES=ThroughputLatencyProbe,PercentileProbe + +# Packages where the specified benchmark is searched by reflection mechanism. +BENCHMARK_PACKAGES=org.yardstickframework + +# Probe point writer class name. +# BENCHMARK_WRITER= + +# Comma-separated list of the hosts to run BenchmarkServers on. +# If same host is specified multiple times, then benchmark server will be started on that host multiple times. +SERVER_HOSTS=localhost,localhost + +# Restart servers before each new benchmark. +# RESTART_SERVERS=true +# or +# Restart servers before each new benchmark and restart servers by period in process of benchmarking. +# RESTART_SERVERS=localhost:0:15:0.1:5,localhost:1:10:0.1:7 + +# Comma-separated list of the hosts to run BenchmarkDrivers on. +# If same host is specified multiple times, then benchmark driver will be started on that host multiple times. +DRIVER_HOSTS=localhost + +# Remote username. +# REMOTE_USER= + +# Server run mode. Supported modes is PLAIN and DOCKER. Default run mode is PLAIN. +RUN_SERVER_MODE=DOCKER + +# Driver run mode. +RUN_DRIVER_MODE=DOCKER + +# Path to remote work directory. If set yardstick will copy files into that path and run benchmarks using that path as +# a home directory. +#WORK_DIR= + +# Path to the docker context configuration file +DOCKER_CONTEXT_PATH=config/docker/docker-context-default.yaml + +# Comma-separated list of benchmark driver configuration parameters. +CONFIGS="\ +--localBind localhost --duration 30 -t 2 -sn EchoServer -dn EchoBenchmark -ds EchoServer-2-threads,\ +--localBind localhost --duration 30 -t 4 -sn EchoServer -dn EchoBenchmark -ds EchoServer-4-threads\ +" diff --git a/config/docker/docker-context-default.yaml b/config/docker/docker-context-default.yaml new file mode 100644 index 0000000..ed9c245 --- /dev/null +++ b/config/docker/docker-context-default.yaml @@ -0,0 +1,39 @@ +# Server context. +serverCtx: + # Path to the Dockerfile. + dockerfilePath: config/docker/Dockerfile-server + # Image name. + imageName: yardstickserver + # Container name prefix. + contPref: YARDSTICK_SERVER + +# Driver context. +driverCtx: + # Path to the Dockerfile. + dockerfilePath: config/docker/Dockerfile-driver + # Image name. + imageName: yardstickdriver + # Container name prefix. + contPref: YARDSTICK_DRIVER + +# Command to build docker images. If 'IMAGE_NAME_PLACEHOLDER' is present it will be replaced with defined image name. +dockerBuildCmd: "build --no-cache -t IMAGE_NAME_PLACEHOLDER -f DOCKERFILE_PATH_PLACEHOLDER ." + +# Flags to remove images. +removeImagesFlags: + before: true + after: true + +# List of arguments to use with docker 'run' command. If 'CONT_NAME_PLACEHOLDER' is present it will be replaced with +# YARDSTICK-- name. +dockerRunCmd: "run -d --network host --name CONT_NAME_PLACEHOLDER IMAGE_NAME_PLACEHOLDER sleep 1d" + +# Flags to remove containers. +removeContainersFlags: + before: true + after: true + +# List of container name prefixes to remove. +containersToRemove: + - YARDSTICK_DRIVER + - YARDSTICK_SERVER \ No newline at end of file diff --git a/config/log4j.xml b/config/log4j.xml new file mode 100644 index 0000000..73bb1ad --- /dev/null +++ b/config/log4j.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 7b336ba..6c9193e 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.yardstickframework yardstick Yardstick - 0.8.5 + 0.8.7 https://github.com/gridgain/yardstick Framework for benchmarks writing. @@ -98,6 +98,36 @@ 4.11 test + + + + + + + + + + + + + + + org.yaml + snakeyaml + 1.23 + + + + org.slf4j + slf4j-api + 1.7.7 + + + + org.slf4j + slf4j-log4j12 + 1.7.7 + @@ -228,6 +258,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + diff --git a/src/main/java/org/yardstickframework/BenchmarkUtils.java b/src/main/java/org/yardstickframework/BenchmarkUtils.java index c8da542..2f316fc 100644 --- a/src/main/java/org/yardstickframework/BenchmarkUtils.java +++ b/src/main/java/org/yardstickframework/BenchmarkUtils.java @@ -22,6 +22,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; +import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; @@ -360,6 +361,22 @@ private BenchmarkUtils() { // No-op. } + public static String dateTime() { + Date date = new Date(System.currentTimeMillis()); + + DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); + + return formatter.format(date); + } + + public static String hms() { + Date date = new Date(System.currentTimeMillis()); + + DateFormat formatter = new SimpleDateFormat("HH-mm-ss"); + + return formatter.format(date); + } + /** * Result of executed command. */ diff --git a/src/main/java/org/yardstickframework/runners/CleanUpRunner.java b/src/main/java/org/yardstickframework/runners/CleanUpRunner.java new file mode 100644 index 0000000..9439a28 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/CleanUpRunner.java @@ -0,0 +1,86 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.util.List; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.workers.host.CheckConnWorker; +import org.yardstickframework.runners.workers.host.CleanRemDirWorker; +import org.yardstickframework.runners.workers.host.HostWorker; +import org.yardstickframework.runners.workers.host.KillWorker; + +/** + * Cleans up docker on hosts. + */ +public class CleanUpRunner extends Runner { + /** {@inheritDoc} */ + private CleanUpRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * + * @param args Command line arguments. + */ + public static void main(String[] args) { + RunContext runCtx = RunContext.getRunContext(args); + + CleanUpRunner runner = new CleanUpRunner(runCtx); + + runner.run0(); + } + + /** + * + * @return Exit code. + */ + @Override protected int run0() { + super.run0(); + + checkPlain(new CheckConnWorker(runCtx, runCtx.getHostSet())); + + List dockerList = runCtx.nodeTypes(RunMode.DOCKER); + + DockerRunner dockerRunner = new DockerRunner(runCtx); + + if (!dockerList.isEmpty()) { + dockerRunner.check(dockerList); + + dockerRunner.cleanUp(dockerList, "after"); + } + + HostWorker killWorker = new KillWorker(runCtx, runCtx.getHostSet()); + + killWorker.workOnHosts(); + + HostWorker cleanWorker = new CleanRemDirWorker(runCtx, runCtx.getHostSet()); + + cleanWorker.workOnHosts(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for cleaning up remote work directory."); + System.out.println("Usage: ./bin/clean-up.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/CollectRunner.java b/src/main/java/org/yardstickframework/runners/CollectRunner.java new file mode 100644 index 0000000..3f9cb9b --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/CollectRunner.java @@ -0,0 +1,79 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.util.List; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.workers.host.CheckConnWorker; +import org.yardstickframework.runners.workers.host.CollectWorker; + +/** + * Collects data. + */ +public class CollectRunner extends Runner { + /** + * Constructor. + * + * @param runCtx Run context. + */ + private CollectRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * + * @param args Command line arguments. + */ + public static void main(String[] args) { + RunContext runCtx = RunContext.getRunContext(args); + + CollectRunner runner = new CollectRunner(runCtx); + + runner.run0(); + } + + /** + * + * @return Exit code. + */ + @Override protected int run0() { + super.run0(); + + checkPlain(new CheckConnWorker(runCtx, runCtx.getHostSet())); + + List dockerList = runCtx.nodeTypes(RunMode.DOCKER); + + DockerRunner dockerRunner = new DockerRunner(runCtx); + + if (!dockerList.isEmpty()) + dockerRunner.collect(dockerList); + + new CollectWorker(runCtx, runCtx.getHostSet()).workOnHosts(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for collecting data from remote hosts."); + System.out.println("Usage: ./bin/collect.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/CommandExecutionResult.java b/src/main/java/org/yardstickframework/runners/CommandExecutionResult.java new file mode 100644 index 0000000..96795e1 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/CommandExecutionResult.java @@ -0,0 +1,107 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.util.ArrayList; +import java.util.List; + +/** + * Command execution result. + */ +public class CommandExecutionResult { + /** */ + private int exitCode; + + /** */ + private List outList; + + /** */ + private List errList; + + /** */ + private Process proc; + + /** + * Constructor. + * + * @param exitCode Exit code. + * @param outList Output stream. + * @param errList Error stream. + * @param proc Process. + */ + CommandExecutionResult(int exitCode, List outList, List errList, Process proc) { + this.exitCode = exitCode; + this.outList = new ArrayList<>(outList); + this.errList = new ArrayList<>(errList); + this.proc = proc; + } + + /** + * + * @return Command execution result with exit code 1 and empty output and error stream. + */ + public static CommandExecutionResult emptyFailedResult(){ + return new CommandExecutionResult(1, new ArrayList<>(), new ArrayList<>(), null); + } + + /** + * + * @return Exit code. + */ + public int exitCode() { + return exitCode; + } + + /** + * + * @param exitCode New exit code. + */ + public void exitCode(int exitCode){ + this.exitCode = exitCode; + } + + /** + * + * @return Output stream. + */ + public List outputList() { + return new ArrayList<>(outList); + } + + /** + * + * @return Error stream. + */ + public List errorList() { + return new ArrayList<>(errList); + } + + /** + * + * @return Process. + */ + public Process process() { + return proc; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "CommandExecutionResult{" + + "exitCode=" + exitCode + + ", outputList=" + outList + + ", errorList=" + errList + + '}'; + } +} diff --git a/src/main/java/org/yardstickframework/runners/CommandHandler.java b/src/main/java/org/yardstickframework/runners/CommandHandler.java new file mode 100644 index 0000000..db3f35a --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/CommandHandler.java @@ -0,0 +1,660 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeStatus; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; + +/** + * Command handler. + */ +public class CommandHandler { + /** */ + private static CommandHandler instance; + + /** */ + private static final String DFLT_SSH_PREF = "ssh -o StrictHostKeyChecking=no"; + + /** */ + private RunContext runCtx; + + /** Field to store last executed command to avoid repetition in log. */ + private String lastCmd = ""; + + /** */ + private static final String[] excluded = new String[] { + "image has dependent child images" + }; + + /** + * Constructor. + * + * @param runCtx Run context. + */ + private CommandHandler(RunContext runCtx) { + this.runCtx = runCtx; + } + + /** + * @param runCtx Run context. + * @return Command handler. + */ + public static CommandHandler getCommandHandler(RunContext runCtx) { + if (instance == null) { + synchronized (CommandHandler.class) { + if (instance == null) + instance = new CommandHandler(runCtx); + } + } + + return instance; + } + + /** + * @param host Host. + * @param cmd Command to execute. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult runCmd(String host, String cmd) throws IOException, InterruptedException { + while (cmd.contains(" ")) + cmd = cmd.replace(" ", " "); + + if (isLocal(host)) + return runLocCmd(cmd); + + String fullCmd = String.format("%s %s", getFullSSHPref(host), cmd); + + return runRmtCmd(fullCmd); + } + + /** + * @param host Host. + * @param path File path. + * @param keyWords Key words to look for. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult runGrepCmd(String host, String path, List keyWords) + throws IOException, InterruptedException { + if (isLocal(host)) + return runGrepCmdLocale(path, keyWords); + + StringBuilder sb = new StringBuilder(String.format("head -20 %s | grep", path)); + + for (String keyWord : keyWords) + sb.append(String.format(" -e '%s'", keyWord)); + + return runCmd(host, sb.toString()); + } + + /** + * @param path File path. + * @param keyWords Key words to look for. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult runGrepCmdLocale(String path, List keyWords) + throws IOException, InterruptedException { + List outRes = new ArrayList<>(); + List errRes = new ArrayList<>(); + + int exitCode = 0; + + try (BufferedReader br = new BufferedReader(new FileReader(path))) { + String line; + + while ((line = br.readLine()) != null) + for (String keyWord : keyWords) { + if (line.contains(keyWord)) + outRes.add(line); + } + + } + catch (IOException e) { + log().error(String.format("Failed to check file '%s'.", path), e); + + errRes.add(e.getMessage()); + + exitCode = 1; + } + + return new CommandExecutionResult(exitCode, outRes, errRes, null); + } + + /** + * @param cmd Command to execute. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + private CommandExecutionResult runLocCmd(String cmd) throws IOException, InterruptedException { + while (cmd.contains(" ")) + cmd = cmd.replace(" ", " "); + + if (!cmd.equals(lastCmd)) + log().debug(String.format("Running local cmd '%s'", cmd)); + + lastCmd = cmd; + + String[] cmdArr = cmd.split(" "); + + final ProcessBuilder pb = new ProcessBuilder() + .command(cmdArr); + + pb.directory(new File(runCtx.localeWorkDirectory())); + + Process p = pb.start(); + + int exitCode = p.waitFor(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + + String lineE; + + List errList = new ArrayList<>(); + + BufferedReader errReader = new BufferedReader(new InputStreamReader(p.getErrorStream())); + + while ((lineE = errReader.readLine()) != null) { + log().error(String.format("Command '%s' returned error line: %s:", cmd, lineE)); + + errList.add(lineE); + } + + String lineO; + + final List outStr = new ArrayList<>(); + + while ((lineO = reader.readLine()) != null) + outStr.add(lineO); + + return new CommandExecutionResult(exitCode, outStr, errList, p); + } + + /** + * @param cmd Command to execute. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + private CommandExecutionResult runRmtCmd(final String cmd) throws IOException, InterruptedException { + if (!cmd.equals(lastCmd)) + log().debug(String.format("Running remote cmd '%s'", cmd)); + + lastCmd = cmd; + + ExecutorService errStreamPrinter = Executors.newSingleThreadExecutor(); + + final Process proc = Runtime.getRuntime().exec(cmd); + + int exitCode = proc.waitFor(); + + BufferedReader outReader = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + String lineE; + + List errStr = new ArrayList<>(); + + BufferedReader errReader = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + + while ((lineE = errReader.readLine()) != null) { + if (!checkIfExcluded(lineE)) + log().error(String.format("Command '%s' returned error line: %s:", cmd, lineE)); + + errStr.add(lineE); + } + + errStreamPrinter.shutdown(); + + String lineO; + + final List outStr = new ArrayList<>(); + + while ((lineO = outReader.readLine()) != null) + outStr.add(lineO); + + return new CommandExecutionResult(exitCode, outStr, errStr, proc); + } + + /** + * @param host Host. + * @param cmd Command to execute. + * @param logPath Log file path. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult startNode(String host, String cmd, + String logPath) throws IOException, InterruptedException { + if (isLocal(host)) + return startNodeLocale(cmd, logPath); + + String startNodeCmd = String.format("%s nohup %s > %s 2>& 1 &", getFullSSHPref(host), cmd, logPath); + + return runRmtCmd(startNodeCmd); + } + + /** + * @param host Host. + * @param pathLoc Locale path. + * @param pathRem Remote path. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult upload(String host, String pathLoc, String pathRem) + throws IOException, InterruptedException { + String cpCmd = String.format("scp -o StrictHostKeyChecking=no -rq %s %s:%s", + pathLoc, host, pathRem); + + return runRmtCmd(cpCmd); + } + + /** + * @param host Host. + * @param pathLoc Locale path. + * @param pathRem Remote path. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult download(String host, String pathLoc, String pathRem) + throws IOException, InterruptedException { + String cpCmd = String.format("scp -o StrictHostKeyChecking=no -rq %s:%s %s", + host, pathRem, pathLoc); + + return runRmtCmd(cpCmd); + } + + /** + * @param cmd Command to execute. + * @param logPath Log file path. + * @return Command execution result. + * @throws IOException If failed. + */ + private CommandExecutionResult startNodeLocale(String cmd, + String logPath) throws IOException { + + while (cmd.contains(" ")) + cmd = cmd.replace(" ", " "); + + String[] cmdArr = cmd.split(" "); + + String java = cmdArr[0]; + + if(!new File(java).exists()){ + log().error(String.format("Failed to find java '%s'.", java)); + + return CommandExecutionResult.emptyFailedResult(); + } + + File logFile = new File(logPath); + + if (!logFile.exists()) + logFile.createNewFile(); + + final ProcessBuilder pb = new ProcessBuilder().command(cmdArr); + + pb.redirectErrorStream(true); + + pb.redirectOutput(logFile); + + pb.directory(new File(runCtx.localeWorkDirectory())); + + final Process proc = pb.start(); + + ExecutorService exec = Executors.newSingleThreadExecutor(); + + exec.submit(new Callable() { + @Override public Process call() throws InterruptedException { + if(!runCtx.startServersEndExit()) + proc.waitFor(); + + return proc; + } + }); + + exec.shutdown(); + + return new CommandExecutionResult(0, new ArrayList<>(), new ArrayList<>(), proc); + } + + /** + * @param nodeInfo Node info. + * @return Node info. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public NodeInfo checkPlainNode(NodeInfo nodeInfo) throws IOException, InterruptedException { + String host = nodeInfo.host(); + + if (isLocal(host)) { + Process proc = nodeInfo.commandExecutionResult().process(); + + if (proc != null && proc.isAlive()) + nodeInfo.nodeStatus(NodeStatus.RUNNING); + else + nodeInfo.nodeStatus(NodeStatus.NOT_RUNNING); + + return nodeInfo; + } + + String checkCmd = String.format("%s ps -ax|grep 'java'", getFullSSHPref(host)); + + CommandExecutionResult res = runRmtCmd(checkCmd); + + String toLook = String.format("-Dyardstick.%s ", nodeInfo.toShortStr()); + + if (checkList(res.outputList(), toLook)) + nodeInfo.nodeStatus(NodeStatus.RUNNING); + else + nodeInfo.nodeStatus(NodeStatus.NOT_RUNNING); + + return nodeInfo; + } + + /** + * Checks if at least one line in the list contains a given string. + * + * @param toCheck List to check. + * @param toLook String to look for. + * @return + */ + public boolean checkList(List toCheck, String toLook){ + boolean found = false; + + for (String str : toCheck) + if (str.contains(toLook)) + found = true; + + return found; + } + + /** + * @param nodeInfo Node info. + * @return Node info. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public NodeInfo killNode(NodeInfo nodeInfo) throws IOException, InterruptedException { + String host = nodeInfo.host(); + + RunMode runMode = nodeInfo.runMode(); + + if (isLocal(host) && runMode == RunMode.PLAIN) { + Process proc = nodeInfo.commandExecutionResult().process(); + + proc.destroyForcibly(); + + return nodeInfo; + } + + String killCmd = String.format("pkill -9 -f \"Dyardstick.%s \"", nodeInfo.toShortStr()); + + if (runMode == RunMode.DOCKER) { + String contName = nodeInfo.dockerInfo().contName(); + + String docKillCmd = String.format("exec %s %s", contName, killCmd); + + runDockerCmd(host, docKillCmd); + + return nodeInfo; + } + + runCmd(host, killCmd); + + return nodeInfo; + } + + /** + * @param args Arguments. + * @return Command execution result. + */ + public CommandExecutionResult runLocalJava(String args) { + while (args.contains(" ")) + args = args.replace(" ", " "); + + String javaHome = System.getProperty("java.home"); + + String cmd = String.format("%s/bin/java %s", javaHome, args); + + String[] cmdArr = cmd.split(" "); + + ProcessBuilder pb = new ProcessBuilder() + .command(cmdArr); + + pb.redirectErrorStream(true); + + pb.directory(new File(runCtx.localeWorkDirectory())); + + try { + pb.start(); + } + catch (IOException e) { + log().error("Failed to start java process.", e); + } + + return null; + } + + /** + * @param host Host. + * @param path Directory to create. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult runMkdirCmd(String host, String path) throws IOException, InterruptedException { + if (isLocal(host)) { + List errStream = new ArrayList<>(); + + try { + File dirToMake = new File(path); + + dirToMake.mkdirs(); + } + catch (Exception e) { + log().info(e.getMessage()); + + errStream.add(e.getMessage()); + } + + return new CommandExecutionResult(errStream.size(), new ArrayList<>(), errStream, null); + } + else { + String mkdirCmd = String.format("%s mkdir -p %s", + getFullSSHPref(host), + path); + + return runRmtCmd(mkdirCmd); + } + } + + /** + * @param host Host. + * @param cmd Command to execute. + * @return Command execution result. + * @throws IOException If failed. + * @throws InterruptedException If interrupted. + */ + public CommandExecutionResult runDockerCmd(String host, String cmd) throws IOException, InterruptedException { + String fullCmd = String.format("docker %s", cmd); + + if (isLocal(host)) + return runRmtCmd(fullCmd); + else { + fullCmd = String.format("%s docker %s", getFullSSHPref(host), cmd); + + return runRmtCmd(fullCmd); + } + } + + /** + * @param host Host. + * @return {@code true} if host address is "localhost" or "127.0.0.1" or {@code false} otherwise. + */ + private boolean isLocal(String host) { + return host.equalsIgnoreCase("localhost") || host.equals("127.0.0.1"); + } + + /** + * @param host Host. + * @return Full ssh prefix. + */ + private String getFullSSHPref(String host) { + if (runCtx.remoteUser() == null || runCtx.remoteUser().isEmpty()) + return String.format("%s %s", DFLT_SSH_PREF, host); + + return String.format("%s %s@%s", DFLT_SSH_PREF, runCtx.remoteUser(), host); + } + + /** + * @param host Host. + * @return Host Java home. + */ + public String getHostJavaHome(String host) { + String javaHome = null; + + if (isLocal(host)) + javaHome = System.getProperty("java.home"); + else { + CommandExecutionResult res = null; + + try { + String echoCmd = "echo $JAVA_HOME"; + + res = runCmd(host, echoCmd); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to get Java home from the host '%s'", host), e); + } + + if (!res.outputList().isEmpty()) + javaHome = res.outputList().get(0); + } + + return javaHome; + } + + /** + * @param host Host. + * @return {@code true} if connection is established or {@code false} otherwise. + */ + public boolean checkConn(String host) { + if (isLocal(host)) + return true; + + CommandExecutionResult res; + + String checkCmd = String.format("%s echo check", getFullSSHPref(host)); + + try { + res = runRmtCmd(checkCmd); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to check connection to the host '%s'", host), e); + + return false; + } + + return res != null + && res.exitCode() == 0 + && !res.outputList().isEmpty() + && res.outputList().get(0).equals("check"); + } + + /** + * @param host Host. + * @param javaHome Path to Java home. + * @return {@code true} if Java actually exists at the specified path or {@code false} otherwise. + */ + public boolean checkJava(String host, String javaHome) { + if (isLocal(host)) + return new File(javaHome + "/bin/java").exists(); + + String checkCmd = String.format("%s test -f %s/bin/java", getFullSSHPref(host), javaHome); + + CommandExecutionResult res = null; + + try { + res = runRmtCmd(checkCmd); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to check Java home on the host '%s'", host), e); + } + + return res != null && res.exitCode() == 0; + } + + /** + * @param host Host. + * @param path Path. + * @return {@code true} if file actually exists at the specified path or {@code false} otherwise. + */ + public boolean checkRemFile(String host, String path) { + if (isLocal(host)) + return new File(path).exists(); + + String checkCmd = String.format("%s test -f %s", getFullSSHPref(host), path); + + CommandExecutionResult res = null; + + try { + res = runRmtCmd(checkCmd); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to check file '%s' home on the host '%s'", path, host), e); + } + + return res != null && res.exitCode() == 0; + } + + /** + * @param lineE Source string. + * @return {@code true} if source string contains excluded patern or {@code false} otherwise. + */ + private boolean checkIfExcluded(String lineE) { + for (String excl : excluded) + if (lineE.contains(excl)) + return true; + + return false; + } + + /** + * @return Logger. + */ + protected Logger log() { + return LogManager.getLogger(getClass().getSimpleName()); + } +} diff --git a/src/main/java/org/yardstickframework/runners/DockerDriverRunner.java b/src/main/java/org/yardstickframework/runners/DockerDriverRunner.java new file mode 100644 index 0000000..15496f5 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/DockerDriverRunner.java @@ -0,0 +1,64 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.util.ArrayList; +import org.yardstickframework.runners.context.RunContext; + +/** + * Docker driver runner. + */ +public class DockerDriverRunner extends DockerRunner { + /** + * @param runCtx Run context. + */ + DockerDriverRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @return Exit code. TODO implement exit code return. + */ + @Override protected int run0() { + if (runCtx.config().help()) { + printHelp(); + + System.exit(0); + } + + driverPrepare(); + + dockerPrepare(); + + for (String cfgStr : runCtx.configList()) + iterationBody(cfgStr, new ArrayList<>()); + + dockerAfterExecution(); + + afterExecution(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for starting driver nodes."); + System.out.println("Usage: ./bin/run-drivers.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/DockerRunner.java b/src/main/java/org/yardstickframework/runners/DockerRunner.java new file mode 100644 index 0000000..add80ed --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/DockerRunner.java @@ -0,0 +1,227 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.workers.host.DockerBuildImagesWorker; +import org.yardstickframework.runners.workers.host.DockerCheckWorker; +import org.yardstickframework.runners.workers.host.DockerCleanContWorker; +import org.yardstickframework.runners.workers.host.DockerCleanImagesWorker; +import org.yardstickframework.runners.workers.node.DockerCollectWorker; +import org.yardstickframework.runners.workers.node.DockerStartContWorker; + +/** + * Helper class. Executes docker related tasks. + */ +public class DockerRunner extends FullRunner { + /** */ + private List dockerList; + + /** + * Constructor. + * + * @param runCtx Run context. + */ + public DockerRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @return Exit code. + */ + @Override protected int run0() { + super.run0(); + + generalPrepare(); + + dockerPrepare(); + + execute(); + + dockerAfterExecution(); + + afterExecution(); + + return runCtx.exitCode(); + } + + /** + * + */ + void dockerPrepare() { + dockerList = runCtx.nodeTypes(RunMode.DOCKER); + + check(dockerList); + + cleanUp(dockerList, "before"); + + prepare(dockerList); + + start(dockerList); + } + + /** + * + */ + void dockerAfterExecution() { + collect(dockerList); + + cleanUp(dockerList, "after"); + } + + /** + * @param nodeTypeList Node type list. + */ + public void check(Iterable nodeTypeList) { + for (NodeType type : nodeTypeList) { + log().info(String.format("Run mode 'DOCKER' enabled for '%s' nodes.", type.toString().toLowerCase())); + + checkForNodeType(type); + } + } + + /** + * @param type Node type. + */ + private void checkForNodeType(NodeType type) { + new DockerCheckWorker(runCtx, runCtx.uniqueHostsByType(type)).workOnHosts(); + } + + /** + * @param nodeTypeList Node type list. + */ + private void prepare(Iterable nodeTypeList) { + int poolSize = runCtx.checkIfDifferentHosts() ? 2 : 1; + + ExecutorService prepareServ = Executors.newFixedThreadPool(poolSize); + + Collection> futList = new ArrayList<>(2); + + for (final NodeType type : nodeTypeList) { + futList.add(prepareServ.submit(new Callable() { + @Override public Object call() throws Exception { + Thread.currentThread().setName(String.format("Prepare-%ss", + type.toString().toLowerCase())); + + prepareForNodeType(type); + + return null; + } + })); + } + + for (Future fut : futList) { + try { + fut.get(); + } + catch (ExecutionException | InterruptedException e) { + log().error("Failed to prepare docker.", e); + } + } + + prepareServ.shutdown(); + } + + /** + * @param nodeTypeList Node type list. + * @param flag Flag. + */ + public void cleanUp(Iterable nodeTypeList, String flag) { + for (final NodeType type : nodeTypeList) + cleanForNodeType(type, flag); + } + + /** + * @param type Node type. + * @param flag Flag. + */ + private void cleanForNodeType(NodeType type, String flag) { + if (runCtx.dockerContext().getRemoveContainersFlags().get(flag)) { + List resList = new DockerCleanContWorker(runCtx, runCtx.uniqueHostsByType(type)) + .workOnHosts(); + + checkRes(resList); + } + + if (runCtx.dockerContext().getRemoveImagesFlags().get(flag)) { + if (!runCtx.dockerContext().getRemoveContainersFlags().get(flag)) { + log().error(String.format("Cannot remove %s docker images. removeContainersFlag '%s' in docker " + + "context file is set to '%s'. Docker images can be removed only after removing all " + + "related containers.", type.toString().toLowerCase(), flag, "false")); + } + else + new DockerCleanImagesWorker(runCtx, runCtx.uniqueHostsByType(type)).workOnHosts(); + } + } + + /** + * @param type Node type. + */ + private void prepareForNodeType(NodeType type) { + List resList = new DockerBuildImagesWorker(runCtx, runCtx.uniqueHostsByType(type), type) + .workOnHosts(); + + checkRes(resList); + } + + /** + * @param nodeTypeList Node type list. + */ + public void start(Iterable nodeTypeList) { + for (NodeType type : nodeTypeList) + startForNodeType(type); + + } + + /** + * @param type Node type. + */ + private void startForNodeType(NodeType type) { + Collection resList = new DockerStartContWorker(runCtx, runCtx.getNodeInfos(type)).workForNodes(); + + for(NodeInfo nodeInfo : resList){ + if(nodeInfo.commandExecutionResult().exitCode() != 0) + System.exit(runCtx.exitCode()); + } + } + + /** + * @param nodeTypeList Node type list. + */ + public void collect(Iterable nodeTypeList) { + for (NodeType type : nodeTypeList) + collectForNodeType(type); + } + + /** + * @param type Node type. + */ + private void collectForNodeType(NodeType type) { + new DockerCollectWorker(runCtx, runCtx.getNodeInfos(type)).workForNodes(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/DockerServerRunner.java b/src/main/java/org/yardstickframework/runners/DockerServerRunner.java new file mode 100644 index 0000000..44f21a3 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/DockerServerRunner.java @@ -0,0 +1,58 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import org.yardstickframework.runners.context.RunContext; + +/** + * Docker driver runner. + */ +public class DockerServerRunner extends DockerRunner { + /** + * @param runCtx Run context. + */ + DockerServerRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @return Exit code. TODO implement exit code return. + */ + @Override protected int run0() { + if (runCtx.config().help()) { + printHelp(); + + System.exit(0); + } + + generalPrepare(); + + dockerPrepare(); + + startServers(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for starting server nodes."); + System.out.println("Usage: ./bin/run-servers.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/DriverRunner.java b/src/main/java/org/yardstickframework/runners/DriverRunner.java new file mode 100644 index 0000000..3a71af3 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/DriverRunner.java @@ -0,0 +1,50 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import org.yardstickframework.runners.context.RunContext; + +/** + * Driver runner. + */ +public class DriverRunner extends Runner { + /** + * @param runCtx Run context. + */ + private DriverRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @param args Command line arguments. + */ + public static void main(String[] args) { + RunContext runCtx = RunContext.getRunContext(args); + + Runner runner = driverRunner(runCtx); + + runner.run0(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for starting driver nodes."); + System.out.println("Usage: ./bin/run-drivers.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/FullRunner.java b/src/main/java/org/yardstickframework/runners/FullRunner.java new file mode 100644 index 0000000..93c416e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/FullRunner.java @@ -0,0 +1,52 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import org.yardstickframework.runners.context.RunContext; + +/** + * Full runner. + */ +public class FullRunner extends Runner { + /** + * + * @param runCtx Run context. + */ + FullRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * + * @param args Command line arguments. + */ + public static void main(String[] args) { + RunContext runCtx = RunContext.getRunContext(args); + + Runner runner = runner(runCtx); + + runner.run0(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for running benchmarks. Starts servers and drivers and collects results."); + System.out.println("Usage: ./bin/run-benchmarks.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/PlainDriverRunner.java b/src/main/java/org/yardstickframework/runners/PlainDriverRunner.java new file mode 100644 index 0000000..42d3083 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/PlainDriverRunner.java @@ -0,0 +1,56 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.util.ArrayList; +import org.yardstickframework.runners.context.RunContext; + +/** + * Driver runner. + */ +public class PlainDriverRunner extends Runner { + /** + * @param runCtx Run context. + */ + PlainDriverRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @return Exit code. TODO implement exit code return. + */ + @Override protected int run0() { + super.run0(); + + driverPrepare(); + + for (String cfgStr : runCtx.configList()) + iterationBody(cfgStr, new ArrayList<>()); + + afterExecution(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for starting driver nodes."); + System.out.println("Usage: ./bin/run-drivers.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/PlainRunner.java b/src/main/java/org/yardstickframework/runners/PlainRunner.java new file mode 100644 index 0000000..fb9a74e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/PlainRunner.java @@ -0,0 +1,53 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import org.yardstickframework.runners.context.RunContext; + +/** + * Plain runner. + */ +public class PlainRunner extends FullRunner { + /** + * + * @param runCtx Run context. + */ + PlainRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * + * @return Exit code. TODO implement exit code return. + */ + @Override protected int run0() { + super.run0(); + + generalPrepare(); + + execute(); + + afterExecution(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + super.printHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/PlainServerRunner.java b/src/main/java/org/yardstickframework/runners/PlainServerRunner.java new file mode 100644 index 0000000..e9a5f2b --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/PlainServerRunner.java @@ -0,0 +1,52 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import org.yardstickframework.runners.context.RunContext; + +/** + * Driver runner. + */ +public class PlainServerRunner extends Runner { + /** + * @param runCtx Run context. + */ + PlainServerRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @return Exit code. TODO implement exit code return. + */ + @Override protected int run0() { + super.run0(); + + generalPrepare(); + + startServers(); + + return runCtx.exitCode(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for starting driver nodes."); + System.out.println("Usage: ./bin/run-drivers.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/Runner.java b/src/main/java/org/yardstickframework/runners/Runner.java new file mode 100644 index 0000000..c32e9cb --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/Runner.java @@ -0,0 +1,425 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Set; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yardstickframework.BenchmarkUtils; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeStatus; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.workers.host.CheckConnWorker; +import org.yardstickframework.runners.workers.host.CheckJavaWorker; +import org.yardstickframework.runners.workers.host.CollectWorker; +import org.yardstickframework.runners.workers.host.DeployWorker; +import org.yardstickframework.runners.workers.host.HostWorker; +import org.yardstickframework.runners.workers.host.KillWorker; +import org.yardstickframework.runners.workers.node.CheckLogWorker; +import org.yardstickframework.runners.workers.node.NodeWorker; +import org.yardstickframework.runners.workers.node.RestartNodeWorker; +import org.yardstickframework.runners.workers.node.StartNodeWorker; +import org.yardstickframework.runners.workers.node.StopNodeWorker; +import org.yardstickframework.runners.workers.node.WaitNodeWorker; + +/** + * Parent for runners. + */ +public abstract class Runner { + /** Run context. */ + protected RunContext runCtx; + + /** + * Constructor. + * + * @param runCtx Run context. + */ + public Runner(RunContext runCtx) { + this.runCtx = runCtx; + } + + /** + * @return Exit code. + */ + protected int run0() { + if (runCtx.config().help()) { + printHelp(); + + System.exit(0); + } + + return runCtx.exitCode(); + } + + /** + * + */ + protected abstract void printHelp(); + + /** + * + */ + protected void commonHelp() { + System.out.println(); + System.out.println("Options:"); + System.out.println(); + System.out.println("-pf || --propertyFile Property file."); + System.out.println("-rwd || --remoteWorkDir Remote work directory path."); + System.out.println("-s || --serverHosts Comma separated list of server nodes addresses."); + System.out.println("-d || --driverHosts Comma separated list of driver nodes addresses."); + } + + /** + * + * @param runCtx Run context. + * @return Runner. + */ + protected static Runner runner(RunContext runCtx) { + return runCtx.dockerEnabled() ? new DockerRunner(runCtx) : new PlainRunner(runCtx); + } + + /** + * + * @param runCtx Run context. + * @return Runner. + */ + static Runner driverRunner(RunContext runCtx) { + return runCtx.dockerEnabled() ? new DockerDriverRunner(runCtx) : new PlainDriverRunner(runCtx); + } + + /** + * + * @param runCtx Run context. + * @return Runner. + */ + static Runner serverRunner(RunContext runCtx) { + return runCtx.dockerEnabled() ? new DockerServerRunner(runCtx) : new PlainServerRunner(runCtx); + } + + /** + * @param checkWorker Check worker. + */ + void checkPlain(HostWorker checkWorker) { + List checks = checkWorker.workOnHosts(); + + for (WorkResult check : checks) { + CheckWorkResult res = (CheckWorkResult)check; + + if (res.exit()) + System.exit(runCtx.exitCode()); + } + } + + /** + * + */ + void generalPrepare() { + Set fullSet = runCtx.getHostSet(); + + check(fullSet); + + new KillWorker(runCtx, fullSet).workOnHosts(); + + new DeployWorker(runCtx, fullSet).workOnHosts(); + } + + /** + * + */ + void driverPrepare() { + Set driverSet = runCtx.driverSet(); + + check(driverSet); + + new DeployWorker(runCtx, driverSet).workOnHosts(); + } + + /** + * @param hostSet Host set. + */ + private void check(Set hostSet) { + checkPlain(new CheckConnWorker(runCtx, hostSet)); + + checkPlain(new CheckJavaWorker(runCtx, runCtx.uniqueHostsByMode(RunMode.PLAIN))); + } + + /** + * @return Exit value. + */ + protected int execute() { + String cfgStr0 = runCtx.configList().get(0); + + List servRes = null; + + if (runCtx.startServersOnce()) + servRes = startNodes(NodeType.SERVER, cfgStr0); + + for (String cfgStr : runCtx.configList()) { + if (!runCtx.startServersOnce()) + servRes = startNodes(NodeType.SERVER, cfgStr); + + checkLogs(servRes); + + waitForNodes(servRes, NodeStatus.RUNNING); + + iterationBody(cfgStr, servRes); + + if (!runCtx.startServersOnce()) { + stopNodes(servRes); + + waitForNodes(servRes, NodeStatus.NOT_RUNNING); + } + } + + if (runCtx.startServersOnce()) { + stopNodes(servRes); + + waitForNodes(servRes, NodeStatus.NOT_RUNNING); + } + + return runCtx.exitCode(); + } + + /** + * + */ + protected void startServers(){ + String cfgStr0 = runCtx.configList().get(0); + + List servRes = startNodes(NodeType.SERVER, cfgStr0); + + checkLogs(servRes); + + waitForNodes(servRes, NodeStatus.RUNNING); + } + + /** + * @param cfgStr Config string. + * @param servRes List of started server nodes. + */ + void iterationBody(String cfgStr, List servRes) { + List drvrRes = startNodes(NodeType.DRIVER, cfgStr); + + checkLogs(drvrRes); + + waitForNodes(drvrRes, NodeStatus.RUNNING); + + ExecutorService restServ = Executors.newSingleThreadExecutor(); + + final List forRestart = new ArrayList<>(servRes); + + Future> restFut = restServ.submit(new Callable>() { + @Override public List call() throws Exception { + String threadName = String.format("Restart-handler-%s", BenchmarkUtils.hms()); + + Thread.currentThread().setName(threadName); + + return restart(forRestart, cfgStr, NodeType.SERVER); + } + }); + + if(runCtx.restartContext(NodeType.DRIVER) != null) + restart(drvrRes, cfgStr, NodeType.DRIVER); + + waitForNodes(drvrRes, NodeStatus.NOT_RUNNING); + + restFut.cancel(true); + + restServ.shutdown(); + } + + /** + * + */ + void afterExecution() { + new CollectWorker(runCtx, runCtx.getHostSet()).workOnHosts(); + + createCharts(); + } + + /** + * @return Logger. + */ + protected Logger log() { + return LogManager.getLogger(getClass().getSimpleName()); + } + + /** + * + */ + private void createCharts() { + String mainResDir = String.format("%s/output/result-%s", runCtx.localeWorkDirectory(), runCtx.mainDateTime()); + + log().info(String.format("Creating charts for result directory '%s'.", mainResDir)); + + String cp = String.format("%s/libs/*", runCtx.localeWorkDirectory()); + + String mainCls = "org.yardstickframework.report.jfreechart.JFreeChartGraphPlotter"; + + String jvmOpts = "-Xmx1g"; + + String stdCharts = String.format("%s -cp %s %s -gm STANDARD -i %s", jvmOpts, cp, mainCls, mainResDir); + + runCtx.handler().runLocalJava(stdCharts); + + String charts = String.format("%s -cp %s %s -i %s", jvmOpts, cp, mainCls, mainResDir); + + runCtx.handler().runLocalJava(charts); + + try { + new CountDownLatch(1).await(3000L, TimeUnit.MILLISECONDS); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + + File outDir = new File(mainResDir).getParentFile(); + + if (outDir.exists() && outDir.isDirectory()) { + File[] arr = outDir.listFiles(); + + for (File resComp : arr) { + if (resComp.getName().startsWith("results-compound")) { + try { + String mvCmd = String.format("mv %s %s", + resComp.getAbsolutePath(), mainResDir); + + runCtx.handler().runCmd("localhost", mvCmd); + } + catch (IOException | InterruptedException e) { + log().error("Failed to create charts", e); + } + } + } + } + } + + /** + * @param type Node type. + * @param cfgStr Config string. + * @return List of {@code NodeInfo} objects. + */ + protected List startNodes(NodeType type, String cfgStr) { + List nodeList = runCtx.getNodeInfos(type); + + if(nodeList.isEmpty()){ + log().info(String.format("%s_HOSTS property is not set. Will not start %s nodes.", type, + type.toString().toLowerCase())); + + return nodeList; + } + + NodeWorker startNodeWorker = new StartNodeWorker(runCtx, nodeList, cfgStr); + + return startNodeWorker.workForNodes(); + } + + /** + * @param list List of {@code NodeInfo} objects. + */ + private void checkLogs(List list) { + NodeWorker checkWorker = new CheckLogWorker(runCtx, list); + + List resList = checkWorker.workForNodes(); + + exitIfNodeNotRunning(resList); + } + + /** + * @param nodeList List of {@code NodeInfo} objects. + * @param expStatus Expected status. + */ + private void waitForNodes(List nodeList, NodeStatus expStatus) { + NodeWorker waitWorker = new WaitNodeWorker(runCtx, nodeList, expStatus); + + List resList = waitWorker.workForNodes(); + + if (expStatus == NodeStatus.RUNNING) + exitIfNodeNotRunning(resList); + } + + /** + * + * @param nodeList List of {@code NodeInfo} objects. + */ + private void exitIfNodeNotRunning(List nodeList){ + for (NodeInfo nodeInfo : nodeList){ + if (nodeInfo.nodeStatus() != NodeStatus.RUNNING){ + new CollectWorker(runCtx, runCtx.getHostSet()).workOnHosts(); + + runCtx.exitCode(1); + + System.exit(runCtx.exitCode()); + } + } + } + + /** + * @param nodeList Node list. + * @return List of nodes. + */ + private List stopNodes(List nodeList) { + NodeWorker stopWorker = new StopNodeWorker(runCtx, nodeList); + + stopWorker.workForNodes(); + + return null; + } + + /** + * @param nodeList Node list. + * @param cfgStr Config string. + * @param type Node type. + * @return List of nodes. + */ + private List restart(List nodeList, String cfgStr, NodeType type) { + if (runCtx.restartContext(type) == null) + return nodeList; + + RestartNodeWorker restWorker = new RestartNodeWorker(runCtx, nodeList, cfgStr); + + restWorker.runAsyncOnHost(true); + + return restWorker.workForNodes(); + } + + /** + * Checks work result list and exit if some of the check results return exit() == true. + * + * @param resList Work result list. + */ + protected void checkRes(List resList) { + for (WorkResult wRes : resList) { + CheckWorkResult cRes = (CheckWorkResult)wRes; + + if (cRes.exit()) + System.exit(runCtx.exitCode()); + } + } +} diff --git a/src/main/java/org/yardstickframework/runners/ServerRunner.java b/src/main/java/org/yardstickframework/runners/ServerRunner.java new file mode 100644 index 0000000..d568b39 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/ServerRunner.java @@ -0,0 +1,52 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners; + +import org.yardstickframework.runners.context.RunContext; + +/** + * Driver runner. + */ +public class ServerRunner extends Runner { + /** + * @param runCtx Run context. + */ + private ServerRunner(RunContext runCtx) { + super(runCtx); + } + + /** + * @param args Command line arguments. + */ + public static void main(String[] args) { + RunContext runCtx = RunContext.getRunContext(args); + + runCtx.startServersEndExit(true); + + Runner runner = serverRunner(runCtx); + + runner.run0(); + } + + /** + * + */ + @Override protected void printHelp(){ + System.out.println("Script for starting server nodes."); + System.out.println("Usage: ./bin/run-servers.sh ."); + + commonHelp(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/checkers/InDockerNodeChecker.java b/src/main/java/org/yardstickframework/runners/checkers/InDockerNodeChecker.java new file mode 100644 index 0000000..3ce3a4e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/checkers/InDockerNodeChecker.java @@ -0,0 +1,64 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.checkers; + +import java.io.IOException; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeStatus; +import org.yardstickframework.runners.context.RunContext; + +/** + * Node checker for docker run. + */ +public class InDockerNodeChecker extends NodeChecker { + /** + * Constructor. + * + * @param runCtx Run context. + */ + public InDockerNodeChecker(RunContext runCtx) { + super(runCtx); + } + + /** {@inheritDoc} */ + @Override public NodeInfo checkNode(NodeInfo nodeInfo) throws InterruptedException{ + String host = nodeInfo.host(); + + String checkCmd = String.format("exec %s sh -c 'ps -a|grep java'", nodeInfo.dockerInfo().contName()); + + CommandExecutionResult res = CommandExecutionResult.emptyFailedResult(); + + try { + res = runCtx.handler().runDockerCmd(host, checkCmd); + } + catch (IOException e) { + log().error(String.format("Failed to check node '%s' on the host '%s'.", + nodeInfo.toShortStr(), + nodeInfo.host())); + + nodeInfo.commandExecutionResult(res); + } + + String toLook = String.format("-Dyardstick.%s ", nodeInfo.toShortStr()); + + if(runCtx.handler().checkList(res.outputList(), toLook)) + nodeInfo.nodeStatus(NodeStatus.RUNNING); + else + nodeInfo.nodeStatus(NodeStatus.NOT_RUNNING); + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/checkers/NodeChecker.java b/src/main/java/org/yardstickframework/runners/checkers/NodeChecker.java new file mode 100644 index 0000000..568aa7c --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/checkers/NodeChecker.java @@ -0,0 +1,54 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.checkers; + +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunContext; + +/** + * Node checker. + */ +public abstract class NodeChecker { + /** */ + protected RunContext runCtx; + + /** + * + * @param runCtx Run context. + */ + public NodeChecker(RunContext runCtx) { + this.runCtx = runCtx; + } + + + /** + * Sets {@code NodeInfo.nodeStatus} to NodeStatus.RUNNING if node is running or NodeStatus.NOT_RUNNING otherwise. + * + * @param nodeInfo {@code Nodeinfo} object. + * @return {@code Nodeinfo} object. + * @throws InterruptedException if interrupted. + */ + public abstract NodeInfo checkNode(NodeInfo nodeInfo) throws InterruptedException; + + /** + * + * @return Logger. + */ + protected Logger log(){ + return LogManager.getLogger(getClass().getSimpleName()); + } +} diff --git a/src/main/java/org/yardstickframework/runners/checkers/PlainNodeChecker.java b/src/main/java/org/yardstickframework/runners/checkers/PlainNodeChecker.java new file mode 100644 index 0000000..e27c2d4 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/checkers/PlainNodeChecker.java @@ -0,0 +1,50 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.checkers; + +import java.io.IOException; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunContext; + +/** + * Node checker for plain run. + */ +public class PlainNodeChecker extends NodeChecker { + /** + * Constructor. + * + * @param runCtx Run context. + */ + public PlainNodeChecker(RunContext runCtx) { + super(runCtx); + } + + /** {@inheritDoc} */ + @Override public NodeInfo checkNode(NodeInfo nodeInfo) throws InterruptedException{ + try { + return runCtx.handler().checkPlainNode(nodeInfo); + } + catch (IOException e) { + log().error(String.format("Failed to check node '%s' on the host '%s'.", + nodeInfo.toShortStr(), + nodeInfo.host())); + + nodeInfo.commandExecutionResult(CommandExecutionResult.emptyFailedResult()); + } + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/DockerContext.java b/src/main/java/org/yardstickframework/runners/context/DockerContext.java new file mode 100644 index 0000000..3e97642 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/DockerContext.java @@ -0,0 +1,251 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Map; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +/** + * Docker context. + */ +public class DockerContext { + /** */ + private static final Logger LOG = LogManager.getLogger(DockerContext.class); + + /** */ + private NodeDockerContext serverCtx; + + /** */ + private NodeDockerContext driverCtx; + + /** */ + private Map removeImagesFlags; + + /** */ + private String dockerBuildCmd; + + /** */ + private String dockerRunCmd; + + /** */ + private Map removeContainersFlags; + + /** */ + private List containersToRemove; + + /** */ + private String serverDockerJavaHome; + + /** */ + private String driverDockerJavaHome; + + public NodeDockerContext getServerCtx() { + return serverCtx; + } + + public void setServerCtx(NodeDockerContext serverCtx) { + this.serverCtx = serverCtx; + } + + public NodeDockerContext getDriverCtx() { + return driverCtx; + } + + public void setDriverCtx(NodeDockerContext driverCtx) { + this.driverCtx = driverCtx; + } + + /** + * + * @return {@code String} Docker build command. + */ + public String getDockerBuildCmd() { + return dockerBuildCmd; + } + + /** + * + * @param dockerBuildCmd Docker build command. + */ + public void setDockerBuildCmd(String dockerBuildCmd) { + this.dockerBuildCmd = dockerBuildCmd; + } + + /** + * + * @return {@code Map} Contains boolean flags indicating whether or not images should be removed. + */ + public Map getRemoveImagesFlags() { + return removeImagesFlags; + } + + /** + * + * @param removeImagesFlags {@code Map} Contains boolean flags indicating whether or not images should be removed. + */ + public void setRemoveImagesFlags(Map removeImagesFlags) { + this.removeImagesFlags = removeImagesFlags; + } + + /** + * + * @return {@code String} Docker run command. + */ + public String getDockerRunCmd() { + return dockerRunCmd; + } + + /** + * + * @param dockerRunCmd Docker run command. + */ + public void setDockerRunCmd(String dockerRunCmd) { + this.dockerRunCmd = dockerRunCmd; + } + + /** + * + * @return {@code Map} Contains boolean flags indicating whether or not containers should be removed. + */ + public Map getRemoveContainersFlags() { + return removeContainersFlags; + } + + /** + * + * @param removeContainersFlags {@code Map} Contains boolean flags indicating whether or not containers should + * be removed. + */ + public void setRemoveContainersFlags(Map removeContainersFlags) { + this.removeContainersFlags = removeContainersFlags; + } + + /** + * + * @return {@code List} List of containers names to remove. + */ + public List getContainersToRemove() { + return containersToRemove; + } + + /** + * + * @param containersToRemove {@code List} List of containers names to remove. + */ + public void setContainersToRemove(List containersToRemove) { + this.containersToRemove = containersToRemove; + } + + /** + * + * @return {@code String} Server Java home path. + */ + public String serverDockerJavaHome() { + return serverDockerJavaHome; + } + + /** + * + * @param serverDockerJavaHome {@code String} Server Java home path. + */ + public void serverDockerJavaHome(String serverDockerJavaHome) { + this.serverDockerJavaHome = serverDockerJavaHome; + } + + /** + * + * @return {@code String} Driver Java home path. + */ + public String driverDockerJavaHome() { + return driverDockerJavaHome; + } + + /** + * + * @param driverDockerJavaHome {@code String} Server Java home path. + */ + public void driverDockerJavaHome(String driverDockerJavaHome) { + this.driverDockerJavaHome = driverDockerJavaHome; + } + + /** + * + * @param yamlPath {@code String} Path to docker context file. + * @return Instance of {@code DockerContext}. + */ + public static DockerContext getDockerContext(String yamlPath){ + Yaml yaml = new Yaml(new Constructor(DockerContext.class)); + + try { + return yaml.load(new FileInputStream(yamlPath)); + } + catch (FileNotFoundException ignored) { + LOG.info(String.format("Failed to find file %s. Will use default docker context.", yamlPath)); + + return new DockerContext(); + } + } + + /** + * + * @param type {@code NodeType} Node type. + * @return {@code String} Image name depending on node type. + */ + public String getImageName(NodeType type){ + return getNodeContext(type).getImageName(); + } + + /** + * + * @param type Node type. + * @return Java home path. + */ + public String javaHome(NodeType type){ + return type == NodeType.SERVER ? + serverDockerJavaHome: + driverDockerJavaHome; + } + + /** + * + * @param type Node type. + * @return Node docker context. + */ + public NodeDockerContext getNodeContext(NodeType type){ + switch (type) { + case SERVER: + return serverCtx; + case DRIVER: + return driverCtx; + default: + throw new IllegalArgumentException(String.format("Unknown node type: %s", type)); + } + } + + /** + * + * @param type Node type. + * @return Container name prefix. + */ + public String contNamePrefix(NodeType type){ + return getNodeContext(type).getContPref(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/DockerInfo.java b/src/main/java/org/yardstickframework/runners/context/DockerInfo.java new file mode 100644 index 0000000..a0e9c9e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/DockerInfo.java @@ -0,0 +1,99 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +/** + * Docker info. + */ +public class DockerInfo { + /** */ + private String imageName; + + /** */ + private String imageVer; + + /** */ + private String contName; + + /** */ + private String contId; + + /** + * Constructor. + * + * @param imageName Image name. + * @param contName Container name. + */ + public DockerInfo(String imageName, String contName) { + this.imageName = imageName; + this.contName = contName; + } + + /** + * @return Image name. + */ + public String imageName() { + return imageName; + } + + /** + * @param imageName New image name. + */ + public void imageName(String imageName) { + this.imageName = imageName; + } + + /** + * @return Image version. + */ + public String imageVersion() { + return imageVer; + } + + /** + * @param imageVer New image version. + */ + public void imageVersion(String imageVer) { + this.imageVer = imageVer; + } + + /** + * @return Cont name. + */ + public String contName() { + return contName; + } + + /** + * @param contName New cont name. + */ + public void contName(String contName) { + this.contName = contName; + } + + /** + * @return Cont id. + */ + public String contId() { + return contId; + } + + /** + * @param contId New cont id. + */ + public void contId(String contId) { + this.contId = contId; + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/NodeDockerContext.java b/src/main/java/org/yardstickframework/runners/context/NodeDockerContext.java new file mode 100644 index 0000000..83010f7 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/NodeDockerContext.java @@ -0,0 +1,77 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +/** + * Node docker context. + */ +public class NodeDockerContext { + /** */ + private String dockerfilePath; + + /** */ + private String imageName; + + /** Container name prefix. */ + private String contPref; + + /** + * + * @return Dockerfile path. + */ + public String getDockerfilePath() { + return dockerfilePath; + } + + /** + * + * @param dockerfilePath Dockerfile path. + */ + public void setDockerfilePath(String dockerfilePath) { + this.dockerfilePath = dockerfilePath; + } + + /** + * + * @return Image name. + */ + public String getImageName() { + return imageName; + } + + /** + * + * @return Container name prefix. + */ + public String getContPref() { + return contPref; + } + + /** + * + * @param contPref Container name prefix. + */ + public void setContPref(String contPref) { + this.contPref = contPref; + } + + /** + * + * @param imageName Image name. + */ + public void setImageName(String imageName) { + this.imageName = imageName; + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/NodeInfo.java b/src/main/java/org/yardstickframework/runners/context/NodeInfo.java new file mode 100644 index 0000000..be5c8e7 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/NodeInfo.java @@ -0,0 +1,289 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import org.yardstickframework.BenchmarkConfiguration; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.workers.WorkResult; + +/** + * Node info. + */ +public class NodeInfo implements WorkResult { + /** */ + private NodeType nodeType; + + /** */ + private String host; + + /** */ + private String port; + + /** */ + private String id; + + /** */ + private String paramStr; + + /** */ + private String logPath; + + /** */ + private RunMode runMode; + + /** */ + private DockerInfo dockerInfo; + + /** */ + private CommandExecutionResult cmdExRes; + + /** */ + private List errMsg = new ArrayList<>(); + + /** */ + private NodeStatus nodeStatus; + + /** */ + private String nodeStartTime; + + /** */ + private String descr; + + /** */ + private BenchmarkConfiguration cfg; + + /** + * Constructor. + * + * @param nodeType Node type. + * @param host Host. + * @param port Port. + * @param id Id. + * @param runMode Run Mode. + */ + public NodeInfo(NodeType nodeType, String host, @Nullable String port, String id, RunMode runMode) { + this.nodeType = nodeType; + this.host = host; + this.port = port; + this.id = id; + this.runMode = runMode; + } + + /** + * @return Node status. + */ + public NodeStatus nodeStatus() { + return nodeStatus; + } + + /** + * @param nodeStatus New node status. + */ + public void nodeStatus(NodeStatus nodeStatus) { + this.nodeStatus = nodeStatus; + } + + /** + * @return Run mode. + */ + public RunMode runMode() { + return runMode; + } + + /** + * @return Node start time. + */ + public String nodeStartTime() { + return nodeStartTime; + } + + /** + * @param nodeStartTime New node start time. + */ + public void nodeStartTime(String nodeStartTime) { + this.nodeStartTime = nodeStartTime; + } + + /** + * @return Description. + */ + public String description() { + return descr; + } + + /** + * @param descr New description. + */ + public void description(String descr) { + this.descr = descr; + } + + /** + * @return Docker info. + */ + public DockerInfo dockerInfo() { + return dockerInfo; + } + + /** + * @param dockerInfo New docker info. + */ + public void dockerInfo(DockerInfo dockerInfo) { + this.dockerInfo = dockerInfo; + } + + /** + * @return Parameter string. + */ + public String parameterString() { + return paramStr; + } + + /** + * @param paramStr New parameter string. + */ + public void parameterString(String paramStr) { + this.paramStr = paramStr; + } + + /** + * @return Log path. + */ + public String logPath() { + return logPath; + } + + /** + * @param logPath New log path. + */ + public void logPath(String logPath) { + this.logPath = logPath; + } + + /** + * @return Command execution result. + */ + public CommandExecutionResult commandExecutionResult() { + return cmdExRes; + } + + /** + * @param cmdExRes Command execution result. + */ + public void commandExecutionResult(CommandExecutionResult cmdExRes) { + this.cmdExRes = cmdExRes; + } + + /** + * @return Id. + */ + public String id() { + return id; + } + + /** + * @param id New id. + */ + public void id(String id) { + this.id = id; + } + + /** + * @return Node type. + */ + public NodeType nodeType() { + return nodeType; + } + + /** + * @param nodeType New node type. + */ + public void nodeType(NodeType nodeType) { + this.nodeType = nodeType; + } + + /** + * @return Host. + */ + public String host() { + return host; + } + + /** + * @param host New host. + */ + public void host(String host) { + this.host = host; + } + + /** + * @return Port. + */ + public String port() { + return port; + } + + /** + * @param port New port. + */ + public void port(String port) { + this.port = port; + } + + /** + * @return Error messages. + */ + public List errorMessages() { + return new ArrayList<>(errMsg); + } + + /** + * @param errMsg New error messages. + */ + public void errorMessages(List errMsg) { + this.errMsg = new ArrayList<>(errMsg); + } + + /** + * @return {@code String} Node type in lower case.. + */ + public String typeLow() { + return nodeType.toString().toLowerCase(); + } + + /** + * @return {@code String} Short string e.g. server0. + */ + public String toShortStr() { + return String.format("%s%s", typeLow(), id); + } + + /** + * @return Config. + */ + public BenchmarkConfiguration config() { + return cfg; + } + + /** + * @param cfg New config. + */ + public void config(BenchmarkConfiguration cfg) { + this.cfg = cfg; + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/NodeStatus.java b/src/main/java/org/yardstickframework/runners/context/NodeStatus.java new file mode 100644 index 0000000..60bffc6 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/NodeStatus.java @@ -0,0 +1,26 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +/** + * Node Status. + */ +public enum NodeStatus { + /** */ + RUNNING, + + /** */ + NOT_RUNNING +} diff --git a/src/main/java/org/yardstickframework/runners/context/NodeType.java b/src/main/java/org/yardstickframework/runners/context/NodeType.java new file mode 100644 index 0000000..e2bacda --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/NodeType.java @@ -0,0 +1,26 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +/** + * Node type. + */ +public enum NodeType { + /** */ + SERVER, + + /** */ + DRIVER +} diff --git a/src/main/java/org/yardstickframework/runners/context/RestartContext.java b/src/main/java/org/yardstickframework/runners/context/RestartContext.java new file mode 100644 index 0000000..8ad804b --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/RestartContext.java @@ -0,0 +1,53 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +import java.util.HashMap; + +/** + * Restart context. + */ +public class RestartContext extends HashMap> { + /** + * + * @return {@code String} value of map content. + */ + private String mapToString(){ + StringBuilder sb = new StringBuilder("RestartContext"); + + for(String host : keySet()){ + sb.append("{"); + sb.append(host); + + for(String id : get(host).keySet()){ + sb.append("{"); + sb.append(id); + sb.append(":"); + sb.append(get(host).get(id)); + sb.append(";"); + } + + sb.append("}"); + + } + + return sb.toString(); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return mapToString(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/RestartSchedule.java b/src/main/java/org/yardstickframework/runners/context/RestartSchedule.java new file mode 100644 index 0000000..384a54f --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/RestartSchedule.java @@ -0,0 +1,103 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +/** + * Restart schedule. + */ +public class RestartSchedule { + /** */ + private long delay; + + /** */ + private long pause; + + /** */ + private long period; + + /** + * Constructor. + * + * @param delay Delay. + * @param pause Pause. + * @param period Period. + */ + RestartSchedule(long delay, long pause, long period) { + this.delay = delay; + this.pause = pause; + this.period = period; + } + + /** + * @return Delay. + */ + public long delay() { + return delay; + } + + /** + * @param delay New delay. + */ + public void delay(long delay) { + this.delay = delay; + } + + /** + * @return Pause. + */ + public long pause() { + return pause; + } + + /** + * @param pause New pause. + */ + public void pause(long pause) { + this.pause = pause; + } + + /** + * @return Period. + */ + public long period() { + return period; + } + + /** + * @param period New period. + */ + public void period(long period) { + this.period = period; + } + + /** + * Converts milliseconds to seconds. + * + * @param millis {@code Long} Milliseconds to convert. + * @return {@code String} String value in seconds e.g. 10.5. + */ + private String millisToSec(Long millis){ + return String.format("%(.1f", millis.doubleValue() / 1000); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "RestartSchedule{" + + "delay=" + millisToSec(delay) + + ", pause=" + millisToSec(pause) + + ", period=" + millisToSec(period) + + '}'; + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/RunContext.java b/src/main/java/org/yardstickframework/runners/context/RunContext.java new file mode 100644 index 0000000..101422e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/RunContext.java @@ -0,0 +1,764 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; +import java.util.Map; +import java.util.Properties; +import java.util.List; +import java.util.TreeSet; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yardstickframework.runners.CommandHandler; +import org.yardstickframework.runners.checkers.InDockerNodeChecker; +import org.yardstickframework.runners.starters.InDockerNodeStarter; +import org.yardstickframework.runners.checkers.NodeChecker; +import org.yardstickframework.runners.starters.NodeStarter; +import org.yardstickframework.runners.checkers.PlainNodeChecker; +import org.yardstickframework.runners.starters.PlainNodeStarter; + +/** + * Run context. + */ +public class RunContext { + /** */ + private static RunContext instance; + + /** */ + private int exitCode; + + /** */ + private static RunnerConfiguration cfg = new RunnerConfiguration(); + + /** */ + private boolean help; + + /** */ + private Properties props; + + /** */ + private String[] configs; + + /** */ + private String locWorkDir; + + /** */ + private String remWorkDir; + + /** */ + private String propPath; + + /** */ + private String locJavaHome; + + /** */ + private String remJavaHome; + + /** */ + private Map hostJavaHomeMap = new HashMap<>(); + + /** */ + private String remUser; + + /** */ + private List servHosts; + + /** */ + private List drvrHosts; + + /** */ + private String serverName; + + /** */ + private String warmup = "20"; + + /** */ + private String duration = "40"; + + /** */ + private String threads = "1"; + + /** */ + private String currHost; + + /** */ + private String mainDateTime; + + /** */ + private RunMode servRunMode; + + /** */ + private RunMode drvrRunMode; + + /** */ + private List cfgList; + + /** */ + private boolean startServOnce; + + /** */ + private boolean startServEndExit; + + /** */ + private RestartContext servRestartCtx; + + /** */ + private RestartContext driverRestartCtx; + + /** */ + private DockerContext dockerCtx; + + /** */ + private CommandHandler hand; + + /** + * Constructor. + */ + private RunContext() { + //No_op + } + + /** + * @return Exit code. + */ + public int exitCode() { + return exitCode; + } + + /** + * @param exitCode New exit code. + */ + public void exitCode(int exitCode) { + this.exitCode = exitCode; + } + + /** + * @return Help. + */ + public boolean help() { + return help; + } + + /** + * Creates and sets run context. + * + * @param args {@code String[]} Command line arguments. + * @return {@code RunContext} Run context instance. + */ + public static synchronized RunContext getRunContext(String[] args) { + if (instance == null) { + instance = new RunContext(); + + RunContextInitializer init = new RunContextInitializer(instance); + + init.initialize(args); + } + + return instance; + } + + /** + * @return Full list of server and driver IP addresses. + */ + public List getFullHostList() { + List res = new ArrayList<>(servHosts); + + res.addAll(drvrHosts); + + return res; + } + + /** + * @return Full unique list of server and driver IP addresses. + */ + public Set getHostSet() { + Set res = new TreeSet<>(servHosts); + + if (!startServEndExit) + res.addAll(drvrHosts); + + return res; + } + + /** + * @return Unique list of driver IP addresses. + */ + public Set driverSet() { + return new TreeSet<>(drvrHosts); + } + + /** + * @param nodeInfo Node info. + * @return Node starter depending on node run mode. + */ + public NodeStarter nodeStarter(NodeInfo nodeInfo) { + RunMode mode = nodeInfo.runMode(); + + switch (mode) { + case PLAIN: + return new PlainNodeStarter(this); + case DOCKER: + return new InDockerNodeStarter(this); + default: + throw new IllegalArgumentException(String.format("Unknown start mode: %s", mode.toString())); + } + } + + /** + * @param nodeInfo Node info. + * @return Node checker depending on node run mode. + */ + public NodeChecker nodeChecker(NodeInfo nodeInfo) { + RunMode mode = nodeInfo.runMode(); + + switch (mode) { + case PLAIN: + return new PlainNodeChecker(this); + case DOCKER: + return new InDockerNodeChecker(this); + default: + throw new IllegalArgumentException(String.format("Unknown start mode: %s", mode.toString())); + } + } + + /** + * @param src {@code String} Source string. + * @return Description. + */ + public String description(String src) { + String[] argArr = src.split(" "); + + String res = "Unknown"; + + for (int i = 0; i < argArr.length; i++) { + if ("-ds".equals(argArr[i]) || "--descriptions".equals(argArr[i])) { + if (argArr.length < i + 2) { + log().info("Failed to get description"); + + return res; + } + else + res = argArr[i + 1]; + } + } + + return res; + } + + /** + * Resolves remote path. + * + * @param srcPath Relative path. + * @return Remote path. + */ + public String resolveRemotePath(String srcPath) { + if (!srcPath.startsWith(remWorkDir)) + return String.format("%s/%s", remWorkDir, srcPath); + + return srcPath; + } + + /** + * Checks if server host list contains any of driver hosts and vice versa. + * + * @return {@code true} if all hosts are different or {@code false} otherwise. + */ + public boolean checkIfDifferentHosts() { + for (String host : servHosts) + if (drvrHosts.contains(host)) + return false; + + return true; + } + + /** + * @param mode Run mode. + * @return List of related node types depending on run mode. + */ + public List nodeTypes(RunMode mode) { + List res = new ArrayList<>(); + + if (servRunMode == mode) + res.add(NodeType.SERVER); + + if (drvrRunMode == mode && !startServEndExit) + res.add(NodeType.DRIVER); + + return res; + } + + /** + * @param type Node type. + * @return List of related hosts depending on node type. + */ + List hostsByType(NodeType type) { + return type == NodeType.SERVER ? servHosts : drvrHosts; + } + + /** + * @param mode Run mode. + * @return List of related hosts depending on run mode. + */ + private List hostsByMode(RunMode mode) { + List res = new ArrayList<>(); + + if (servRunMode == mode) + res.addAll(servHosts); + + if (drvrRunMode == mode && !startServEndExit) + res.addAll(drvrHosts); + + return res; + } + + /** + * @param type Node type. + * @return List of unique related hosts depending on node type. + */ + public Set uniqueHostsByType(NodeType type) { + return new TreeSet<>(hostsByType(type)); + } + + /** + * @param mode Run mode. + * @return List of unique related hosts depending on run mode. + */ + public Set uniqueHostsByMode(RunMode mode) { + return new TreeSet<>(hostsByMode(mode)); + } + + /** + * @param host Host. + * @return {@code String} Host Java home. + */ + public String getHostJava(String host) { + return hostJavaHomeMap.get(host); + } + + /** + * @param type Node type. + * @return Node run mode. + */ + private RunMode getRunMode(NodeType type) { + switch (type) { + case SERVER: + return servRunMode; + case DRIVER: + return drvrRunMode; + default: + throw new IllegalArgumentException(String.format("Unknown node type: %s", type)); + } + } + + /** + * @param type Node type. + * @return List of {@code NodeInfo} objects created with related run modes. + */ + public List getNodeInfos(NodeType type) { + List hosts = hostsByType(type); + + RunMode mode = getRunMode(type); + + List res = new ArrayList<>(hosts.size()); + + for (int i = 0; i < hosts.size(); i++) + res.add(new NodeInfo(type, hosts.get(i), null, String.valueOf(i), mode)); + + return res; + } + + /** + * @return {@code true} If all defined hosts are local. + */ + public boolean onlyLocal() { + for (String host : getHostSet()) { + if (!host.equalsIgnoreCase("localhost") && !host.equals("127.0.0.1")) + return false; + } + + return true; + } + + /** + * @param type Node type. + * @return Restart context. + */ + public RestartContext restartContext(NodeType type) { + switch (type) { + case SERVER: + return servRestartCtx; + case DRIVER: + return driverRestartCtx; + default: + throw new IllegalArgumentException(String.format("Unknown node type: %s", type)); + } + } + + /** + * @return Logger. + */ + protected static Logger log() { + return LogManager.getLogger(RunContext.class.getSimpleName()); + } + + /** + * @return Config. + */ + public RunnerConfiguration config() { + return cfg; + } + + /** + * @return Start servers once. + */ + public boolean startServersOnce() { + return startServOnce; + } + + /** + * @param startSrvsOnce New start servers once. + */ + public void startServersOnce(boolean startSrvsOnce) { + startServOnce = startSrvsOnce; + } + + /** + * @return Start serv end exit. + */ + public boolean startServersEndExit() { + return startServEndExit; + } + + /** + * @param startServEndExit New start serv end exit. + */ + public void startServersEndExit(boolean startServEndExit) { + this.startServEndExit = startServEndExit; + } + + /** + * @param srvRestartCtx New server restart context. + */ + public void serverRestartContext(RestartContext srvRestartCtx) { + servRestartCtx = srvRestartCtx; + } + + /** + * @param driverRestartCtx New driver restart context. + */ + public void driverRestartContext(RestartContext driverRestartCtx) { + this.driverRestartCtx = driverRestartCtx; + } + + /** + * @return Locale work directory. + */ + public String localeWorkDirectory() { + return locWorkDir; + } + + /** + * @param locWorkDir New locale work directory. + */ + public void localeWorkDirectory(String locWorkDir) { + this.locWorkDir = locWorkDir; + } + + /** + * @return Main date time. + */ + public String mainDateTime() { + return mainDateTime; + } + + /** + * @param mainDateTime New main date time. + */ + public void mainDateTime(String mainDateTime) { + this.mainDateTime = mainDateTime; + } + + /** + * @return Remote work directory. + */ + public String remoteWorkDirectory() { + return remWorkDir; + } + + /** + * @param remWorkDir New remote work directory. + */ + public void remoteWorkDirectory(String remWorkDir) { + this.remWorkDir = remWorkDir; + } + + /** + * @return Properties. + */ + public Properties properties() { + return props; + } + + /** + * @param props New properties. + */ + public void properties(Properties props) { + this.props = props; + } + + /** + * @return Configs. + */ + public String[] configs() { + return configs; + } + + /** + * @param configs New configs. + */ + public void configs(String[] configs) { + this.configs = configs; + } + + /** + * @return Docker context. + */ + public DockerContext dockerContext() { + return dockerCtx; + } + + /** + * @param dockerCtx New docker context. + */ + public void dockerContext(DockerContext dockerCtx) { + this.dockerCtx = dockerCtx; + } + + /** + * @return Config list. + */ + public List configList() { + return new ArrayList<>(cfgList); + } + + /** + * @param cfgList New config list. + */ + public void configList(List cfgList) { + this.cfgList = new ArrayList<>(cfgList); + } + + /** + * @return Rem user. + */ + public String remoteUser() { + return remUser; + } + + /** + * @param remUser New rem user. + */ + public void remoteUser(String remUser) { + this.remUser = remUser; + } + + /** + * @param servRunMode New server run mode. + */ + public void serverRunMode(RunMode servRunMode) { + this.servRunMode = servRunMode; + } + + /** + * @param drvrRunMode New driver run mode. + */ + public void driverRunMode(RunMode drvrRunMode) { + this.drvrRunMode = drvrRunMode; + } + + /** + * @return Locale java home. + */ + public String localeJavaHome() { + return locJavaHome; + } + + /** + * @param locJavaHome New locale java home. + */ + public void localeJavaHome(String locJavaHome) { + this.locJavaHome = locJavaHome; + } + + /** + * @return Rem java home. + */ + public String remoteJavaHome() { + return remJavaHome; + } + + /** + * @param remJavaHome New rem java home. + */ + public void remoteJavaHome(String remJavaHome) { + this.remJavaHome = remJavaHome; + } + + /** + * @return Server hosts. + */ + public List serverHosts() { + return new ArrayList<>(servHosts); + } + + /** + * @param servHosts New server hosts. + */ + void serverHosts(List servHosts) { + this.servHosts = new ArrayList<>(servHosts); + } + + /** + * @return Driver hosts. + */ + public List driverHosts() { + return new ArrayList<>(drvrHosts); + } + + /** + * @param drvrHosts New drvr hosts. + */ + void driverHosts(List drvrHosts) { + this.drvrHosts = new ArrayList<>(drvrHosts); + } + + /** + * @return Server name. + */ + public String serverName() { + return serverName; + } + + /** + * @param srvName New server name. + */ + public void serverName(String srvName) { + serverName = srvName; + } + + /** + * @return Warmap. + */ + public String warmup() { + return warmup; + } + + /** + * @param warmup New warmup. + */ + public void warmup(String warmup) { + this.warmup = warmup; + } + + /** + * @return Duration. + */ + public String duration() { + return duration; + } + + /** + * @param duration New duration. + */ + public void duration(String duration) { + this.duration = duration; + } + + /** + * @return Threads. + */ + public String threads() { + return threads; + } + + /** + * @param threads New threads. + */ + public void threads(String threads) { + this.threads = threads; + } + + /** + * @return Current host. + */ + public String currentHost() { + return currHost; + } + + /** + * @param currHost New current host. + */ + public void currentHost(String currHost) { + this.currHost = currHost; + } + + /** + * @return Property path. + */ + public String propertyPath() { + return propPath; + } + + /** + * @param propPath New property path. + */ + public void propertyPath(String propPath) { + this.propPath = propPath; + } + + /** + * @return Host java home map. + */ + public Map hostJavaHomeMap() { + return new HashMap<>(hostJavaHomeMap); + } + + /** + * @param host Host. + * @param javaHome Java home. + */ + public void putInJavaHostMap(String host, String javaHome) { + hostJavaHomeMap.put(host, javaHome); + } + + /** + * @return Command Handler. + */ + public CommandHandler handler() { + if (hand == null) + hand = CommandHandler.getCommandHandler(this); + + return hand; + } + + /** + * @return {@code true} if docker is enabled for server or driver nodes or {@code false} otherwise. + */ + public boolean dockerEnabled() { + return servRunMode == RunMode.DOCKER || drvrRunMode == RunMode.DOCKER; + } +} \ No newline at end of file diff --git a/src/main/java/org/yardstickframework/runners/context/RunContextInitializer.java b/src/main/java/org/yardstickframework/runners/context/RunContextInitializer.java new file mode 100644 index 0000000..b6e3130 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/RunContextInitializer.java @@ -0,0 +1,701 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.FileAppender; +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; +import org.apache.log4j.PropertyConfigurator; +import org.yardstickframework.BenchmarkUtils; + +/** + * Initializes run context. + */ +public class RunContextInitializer { + /** */ + private static final Logger LOG = LogManager.getLogger(RunContextInitializer.class); + + /** Instance to initialize */ + private RunContext ctx; + + /** + * Constructor. + * + * @param ctx {@code RunContext} instance to initialize. + */ + RunContextInitializer(RunContext ctx) { + this.ctx = ctx; + } + + /** + * + * @param args Command line arguments. + * @return {@code true} if initialization completed or {@code false} otherwise. + */ + void initialize(String[] args) { + ctx.mainDateTime(BenchmarkUtils.dateTime()); + + if (!handleArgs(args)) + return; + + setHosts(); + + setProps(); + + setConfigs(); + + setServerName(); + + setWarmup(); + + setDuration(); + + setThreads(); + + setJavaHome(); + + setRunModes(); + + setUser(); + + setCfgList(); + + setRestartCtx(NodeType.SERVER); + + setRestartCtx(NodeType.DRIVER); + + if(ctx.dockerEnabled()) + setDockerContext(); + + handleAdditionalArgs(); + } + + /** + * @param args Command line arguments. + * @return {@code true} if '-h' or '--help' was not passed or {@code false} otherwise. + */ + private boolean handleArgs(String[] args) { + try { + BenchmarkUtils.jcommander(args, ctx.config(), ""); + } + catch (Exception e) { + BenchmarkUtils.println("Failed to parse command line arguments. " + e.getMessage()); + + ctx.config().help(true); + + ctx.exitCode(1); + + return false; + } + + if (ctx.config().help()) + return false; + + if (ctx.config().scriptDirectory() == null) { + System.out.println("Error: Script directory is not defined."); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + } + + ctx.localeWorkDirectory(new File(ctx.config().scriptDirectory()).getParentFile().getAbsolutePath()); + + configLog(); + + LOG.debug(String.format("Locale work directory is '%s'.", ctx.localeWorkDirectory())); + + if (ctx.config().propertyFile() == null) { + String dfltPropPath = String.format("%s/config/benchmark.properties", ctx.localeWorkDirectory()); + + LOG.info(String.format("Using as a default property file '%s'.", dfltPropPath)); + + if (!new File(dfltPropPath).exists()) { + LOG.error(String.format("Failed to find default property file '%s'.", dfltPropPath)); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + } + + ctx.propertyPath(dfltPropPath); + } + else { + String propFilePath = ctx.config().propertyFile(); + + if (new File(propFilePath).exists()) + ctx.propertyPath(new File(propFilePath).getAbsolutePath()); + else if (Paths.get(ctx.localeWorkDirectory(), propFilePath).toFile().exists()) + ctx.propertyPath(Paths.get(ctx.localeWorkDirectory(), propFilePath).toAbsolutePath().toString()); + else { + LOG.error(String.format("Failed to find property file '%s'", propFilePath)); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + } + } + + LOG.debug(String.format("Property file path is '%s'.", ctx.propertyPath())); + + try { + checkPropertyFile(); + + Properties props = new Properties(); + + props.load(new FileReader(ctx.propertyPath())); + + ctx.properties(props); + } + catch (IOException e) { + e.printStackTrace(); + } + + return true; + } + + /** + * Changes values taken from property file to values taken from command line arguments. + */ + private void handleAdditionalArgs() { + if (ctx.config().serverHosts() != null) + ctx.serverHosts(hostsToList(ctx.config().serverHosts())); + + if (ctx.config().driverHosts() != null) + ctx.driverHosts(hostsToList(ctx.config().driverHosts())); + + if (ctx.config().remoteWorkDirectory() != null) + ctx.remoteWorkDirectory(ctx.config().remoteWorkDirectory()); + } + + /** + * @param type Node type. + */ + private void setRestartCtx(NodeType type) { + String restProp = ctx.properties().getProperty(String.format("RESTART_%sS", type)); + + if (restProp == null) + return; + + if ("true".equals(restProp.toLowerCase()) || "false".equals(restProp.toLowerCase())) { + setRestart(Boolean.valueOf(restProp), type); + + return; + } + + parseRestartProp(restProp, type); + } + + /** + * + * @param val value to set. + * @param type Node type. + */ + private void setRestart(boolean val, NodeType type) { + if (type == NodeType.SERVER) + ctx.startServersOnce(!val); + } + + /** + * Parse following string e.g. 172.25.1.49:0:5:5:5,172.25.1.49:1:5:5:5 to create restart schedule for node. + * + * @param restProp Restart property string. + * @param type Node type. + */ + private void parseRestartProp(String restProp, NodeType type) { + String[] nodeList = restProp.split(","); + + RestartContext restCtx = new RestartContext(); + + for (String nodeInfo : nodeList) { + String[] values = nodeInfo.split(":"); + + if (values.length != 5) { + LOG.error(String.format("Wrong value for 'RESTART_%sS' property. String '%s' does not have 5 values.", + type, nodeInfo)); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + } + + String host = values[0]; + String id = values[1]; + + try { + int idInt = Integer.valueOf(id); + + List hosts = ctx.hostsByType(type); + + String node = String.format("%s%s", type.toString().toLowerCase(), id); + + if(idInt >= hosts.size()) + LOG.warn(String.format("Restart schedule '%s' was set for the node '%s' on the host '%s', but " + + "node '%s' will not start. (Number of defined hosts is less than %d).", + nodeInfo, node, host, node, idInt)); + + if(idInt < hosts.size() && !hosts.get(idInt).equals(host)) + LOG.warn(String.format("Restart schedule '%s' was set for the node '%s' on the host '%s', but " + + "node '%s' will be started on the host '%s'.", nodeInfo, node, host, node, hosts.get(idInt))); + + } + catch (NumberFormatException e){ + LOG.error(String.format("Wrong value for 'RESTART_%sS' property. %s", + type, nodeInfo, e.getMessage())); + } + + try { + Long delay = convertSecToMillis(values[2]); + Long pause = convertSecToMillis(values[3]); + Long period = convertSecToMillis(values[4]); + + HashMap hostMap = restCtx.get(host); + + if (hostMap == null) + hostMap = new HashMap<>(); + + RestartSchedule restInfo = new RestartSchedule(delay, pause, period); + + hostMap.put(id, restInfo); + + restCtx.put(host, hostMap); + } + catch (NumberFormatException e) { + LOG.error(String.format("Wrong value for 'RESTART_%sS' property. %s", + type, e.getMessage())); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + } + } + + LOG.debug(String.format("Restart context for '%s' nodes set as '%s'", type, restCtx)); + + if (type == NodeType.SERVER) + ctx.serverRestartContext(restCtx); + else + ctx.driverRestartContext(restCtx); + } + + /** + * + * @param sec Seconds. + * @return Milliseconds. + * @throws NumberFormatException if failed. + */ + private long convertSecToMillis(String sec) throws NumberFormatException { + Double d = Double.valueOf(sec); + + Double dt = d * 1000; + + return dt.longValue(); + } + + /** + * + */ + private void setProps() { +// ctx.properties(parseProps(ctx.propertiesOrig())); +// ctx.properties(ctx.propertiesOrig()); + + String remWorkDir = ctx.properties().getProperty("WORK_DIR") != null ? + ctx.properties().getProperty("WORK_DIR") : + ctx.localeWorkDirectory(); + + ctx.remoteWorkDirectory(remWorkDir); + + LOG.debug(String.format("Remote work directory is '%s'.", ctx.remoteWorkDirectory())); + } + + /** + * + */ + private void setHosts() { + ctx.serverHosts(getHosts("SERVER_HOSTS")); + + ctx.driverHosts(getHosts("DRIVER_HOSTS")); + + Set allHosts = ctx.getHostSet(); + + Enumeration e = null; + + try { + e = NetworkInterface.getNetworkInterfaces(); + } + catch (SocketException e1) { + LOG.error("Failed to get network interfaces.", e1); + } + + while (e.hasMoreElements()) { + Enumeration ee = e.nextElement().getInetAddresses(); + + while (ee.hasMoreElements()) { + String adr = ee.nextElement().getHostAddress(); + + if (allHosts.contains(adr)) { + LOG.debug(String.format("Setting current host address as '%s'.", adr)); + + ctx.currentHost(adr); + } + } + } + + if (ctx.currentHost() == null) { + LOG.debug("Setting current host address as '127.0.0.1'."); + + ctx.currentHost("127.0.0.1"); + } + } + + /** + * + */ + private void setConfigs(){ + String cfgFromProps = ctx.properties().getProperty("CONFIGS"); + + if (cfgFromProps == null || cfgFromProps.isEmpty()){ + LOG.error(String.format("'CONFIGS' property is not defined in property file.")); + + System.exit(1); + } + + ctx.configs(cfgFromProps.split(",")); + } + + /** + * + */ + private void setServerName(){ + if(ctx.properties().getProperty("SERVER_NAME") != null) + ctx.serverName(ctx.properties().getProperty("SERVER_NAME")); + } + + /** + * + */ + private void setWarmup(){ + if(ctx.properties().getProperty("WARMUP") != null) + ctx.warmup(ctx.properties().getProperty("WARMUP")); + } + + /** + * + */ + private void setDuration(){ + if(ctx.properties().getProperty("DURATION") != null) + ctx.duration(ctx.properties().getProperty("DURATION")); + } + + /** + * + */ + private void setThreads(){ + if(ctx.properties().getProperty("THREADS") != null) + ctx.threads(ctx.properties().getProperty("THREADS")); + } + + /** + * + */ + private void setJavaHome() { + String remJavaHome = null; + + if (ctx.properties().getProperty("JAVA_HOME") != null) + remJavaHome = ctx.properties().getProperty("JAVA_HOME"); + + String locJavaHome = System.getProperty("java.home"); + + if (ctx.properties().getProperty("JAVA_HOME") != null && new File(String.format("%s/bin/java", remJavaHome)).exists()) + locJavaHome = String.format("%s/bin/java", remJavaHome); + + ctx.localeJavaHome(locJavaHome); + + ctx.remoteJavaHome(remJavaHome); + } + + /** + * + */ + private void setRunModes() { + RunMode servRunMode = ctx.properties().getProperty("RUN_SERVER_MODE") != null ? + RunMode.valueOf(ctx.properties().getProperty("RUN_SERVER_MODE")) : + RunMode.PLAIN; + + LOG.debug(String.format("Server run mode set as %s", servRunMode)); + + ctx.serverRunMode(servRunMode); + + RunMode drvrRunMode = ctx.properties().getProperty("RUN_DRIVER_MODE") != null ? + RunMode.valueOf(ctx.properties().getProperty("RUN_DRIVER_MODE")) : + RunMode.PLAIN; + + LOG.debug(String.format("Driver run mode set as %s", drvrRunMode)); + + ctx.driverRunMode(drvrRunMode); + } + + /** + * + */ + private void setUser() { + String remUser; + + if (ctx.properties().getProperty("REMOTE_USER") != null) + remUser = ctx.properties().getProperty("REMOTE_USER"); + else { + String locUser = System.getProperty("user.name"); + + if (!ctx.onlyLocal()) { + LOG.info(String.format("'REMOTE_USER' is not defined in property file. Will use '%s' " + + "username for remote connections.", locUser)); + } + + remUser = locUser; + } + + ctx.remoteUser(remUser); + } + + /** + * + */ + private void setCfgList() { + List cfgList = new ArrayList<>(); + + for (String cfgStr : ctx.configs()) { + if (cfgStr.length() < 10) + continue; + + cfgList.add(cfgStr); + } + + ctx.configList(cfgList); + } + + /** + * + * @return Number of nodes. + */ + private int getNodesNum() { + return ctx.getFullHostList().size(); + } + + /** + * @param prop Host property. + * @return List of host addresses. + */ + private List getHosts(String prop) { + List res = hostsToList(ctx.properties().getProperty(prop)); + + if (res.isEmpty()) + LOG.info(String.format("WARNING! %s is not defined in property file.", prop)); + + return res; + } + + /** + * + * @param commaSepList Comma separated list of addresses. + * @return List of host addresses. + */ + private List hostsToList(String commaSepList) { + List res = new ArrayList<>(); + + if (commaSepList == null) + return res; + + String[] ips = commaSepList.split(","); + + for (String ip : ips) + res.add(ip); + + return res; + } + + /** + * + */ + private void setDockerContext() { + String dockerCtxPropPath; + + if (ctx.properties().getProperty("DOCKER_CONTEXT_PATH") == null) { + dockerCtxPropPath = String.format("%s/config/docker/docker-context-default.yaml", ctx.localeWorkDirectory()); + + LOG.info("'DOCKER_CONTEXT_PATH' is not defined in property file. Will " + + "use default docker context configuration:"); + + LOG.info(dockerCtxPropPath); + } + else { + dockerCtxPropPath = resolvePath(ctx.properties().getProperty("DOCKER_CONTEXT_PATH")); + + if(dockerCtxPropPath == null || !new File(dockerCtxPropPath).exists()){ + LOG.error(String.format("Failed to find docker context file '%s'.", dockerCtxPropPath)); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + } + } + + ctx.dockerContext(DockerContext.getDockerContext(dockerCtxPropPath)); + } + + /** + * + * @param srcPath Relative path. + * @return Absolute path. + */ + private String resolvePath(String srcPath) { + if (srcPath == null || srcPath.isEmpty()) + return null; + + if (new File(srcPath).exists()) + return srcPath; + + String fullPath = null; + + if(!srcPath.startsWith(ctx.localeWorkDirectory())) + fullPath = String.format("%s/%s", ctx.localeWorkDirectory(), srcPath); + + if (new File(fullPath).exists()) + return fullPath; + + LOG.error(String.format("Failed to find '%s' or '%s'.", srcPath, fullPath)); + + ctx.exitCode(1); + + System.exit(ctx.exitCode()); + + return null; + } + + /** + * + * @return {@code true} if property file is OK or {@code false} otherwise. + * @throws IOException if failed. + */ + private boolean checkPropertyFile() throws IOException { + String path = ctx.propertyPath(); + + Set propSet = new HashSet<>(); + + BufferedReader reader = new BufferedReader(new FileReader(path)); + + String line; + + while ((line = reader.readLine()) != null) { + if (!line.contains("=") || line.startsWith("#")) + continue; + + int idx0 = line.indexOf("="); + + String propName = line.substring(0, idx0); + + if (propSet.contains(propName)) { + LOG.error(String.format("Property '%s' defined more than once in property file.", propName)); + + System.exit(1); + } + else + propSet.add(propName); + } + + return false; + } + + /** + * + */ + private void configLog() { + String logPropPath = String.format("%s/config/log4j.properties", ctx.localeWorkDirectory()); + + String logPath = Paths.get(ctx.localeWorkDirectory(), "output", String.format("logs-%s/%s-run.log", + ctx.mainDateTime(), ctx.mainDateTime())).toString(); + + if (new File(logPropPath).exists()){ + Properties logProps = new Properties(); + + try { + logProps.load(new FileInputStream(logPropPath)); + + if (logProps.getProperty("log4j.appender.file.File") == null) + logProps.setProperty("log4j.appender.file.File", logPath); + + PropertyConfigurator.configure(logProps); + } catch (IOException e) { + configDefaultLog(logPath); + + LOG.error(String.format("Failed to load logging property file %s :", logPropPath), e); + } + } + else + configDefaultLog(logPath); + } + + /** + * + * @param logPath Log file path. + */ + private void configDefaultLog(String logPath){ + ConsoleAppender console = new ConsoleAppender(); + + String ptrn = "[%d{yyyy-MM-dd HH:mm:ss}][%-5p] %m%n"; + + console.setLayout(new PatternLayout(ptrn)); + + console.setThreshold(Level.INFO); + + console.activateOptions(); + + Logger.getRootLogger().addAppender(console); + + FileAppender fileApp = new FileAppender(); + + fileApp.setName("FileLogger"); + + fileApp.setFile(logPath); + + fileApp.setLayout(new PatternLayout("[%d{yyyy-MM-dd HH:mm:ss,SSS}][%-5p][%t] %m%n")); + + fileApp.setThreshold(Level.INFO); + + fileApp.setAppend(true); + + fileApp.activateOptions(); + + Logger.getRootLogger().addAppender(fileApp); + } +} diff --git a/src/main/java/org/yardstickframework/runners/context/RunMode.java b/src/main/java/org/yardstickframework/runners/context/RunMode.java new file mode 100644 index 0000000..17a242e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/RunMode.java @@ -0,0 +1,26 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +/** + * Run mode. + */ +public enum RunMode { + /** */ + PLAIN, + + /** */ + DOCKER +} diff --git a/src/main/java/org/yardstickframework/runners/context/RunnerConfiguration.java b/src/main/java/org/yardstickframework/runners/context/RunnerConfiguration.java new file mode 100644 index 0000000..30a290f --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/context/RunnerConfiguration.java @@ -0,0 +1,136 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.context; + +import com.beust.jcommander.Parameter; +import java.io.Serializable; + +/** + * Input arguments for benchmarks. + */ +@SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"}) +public class RunnerConfiguration implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** */ + @Parameter(names = {"-h", "--help"}, description = "Print help message", help = true, hidden = true) + private boolean help; + + /** */ + @Parameter(names = {"-sd", "--scriptDir"}, description = "Local script directory path") + private String scriptDir; + + /** */ + @Parameter(names = {"-rwd", "--remoteWorkDir"}, description = "Remote work directory path") + private String remoteWorkDir; + + /** */ + @Parameter(names = {"-pf", "--propertyFile"}, description = "Framework configuration file path") + private String propertyFile; + + /** */ + @Parameter(names = {"-s", "--serverHosts"}, description = "Comma separated list of server nodes addresses.") + private String serverHosts; + + /** */ + @Parameter(names = {"-d", "--driverHosts"}, description = "Comma separated list of driver nodes addresses.") + private String driverHosts; + + + /** + * @return Help. + */ + public boolean help() { + return help; + } + + /** + * @param help New help. + */ + public void help(boolean help) { + this.help = help; + } + + /** + * @return Local work directory. + */ + public String scriptDirectory() { + return scriptDir; + } + + /** + * @param scriptDir New local work directory. + */ + public void scriptDirectory(String scriptDir) { + this.scriptDir = scriptDir; + } + + /** + * @return Remote work directory. + */ + public String remoteWorkDirectory() { + return remoteWorkDir; + } + + /** + * @param remoteWorkDir New remote work directory. + */ + public void remoteWorkDirectory(String remoteWorkDir) { + this.remoteWorkDir = remoteWorkDir; + } + + /** + * @return Property file. + */ + public String propertyFile() { + return propertyFile; + } + + /** + * @param propFile New property file. + */ + public void propertyFile(String propFile) { + propertyFile = propFile; + } + + /** + * @return Server hosts. + */ + public String serverHosts() { + return serverHosts; + } + + /** + * @param srvHosts New server hosts. + */ + public void serverHosts(String srvHosts) { + serverHosts = srvHosts; + } + + /** + * @return Driver hosts. + */ + public String driverHosts() { + return driverHosts; + } + + /** + * @param driverHosts New driver hosts. + */ + public void driverHosts(String driverHosts) { + this.driverHosts = driverHosts; + } +} diff --git a/src/main/java/org/yardstickframework/runners/starters/InDockerNodeStarter.java b/src/main/java/org/yardstickframework/runners/starters/InDockerNodeStarter.java new file mode 100644 index 0000000..5740659 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/starters/InDockerNodeStarter.java @@ -0,0 +1,70 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.starters; + +import java.io.File; +import java.io.IOException; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.DockerInfo; +import org.yardstickframework.runners.context.RunContext; + +/** + * Starts nodes in docker containers. + */ +public class InDockerNodeStarter extends NodeStarter { + /** + * + * @param runCtx Run context. + */ + public InDockerNodeStarter(RunContext runCtx) { + super(runCtx); + } + + /** {@inheritDoc} */ + @Override public NodeInfo startNode(NodeInfo nodeInfo) throws InterruptedException { + String contName = String.format("%s_%s", runCtx.dockerContext().contNamePrefix(nodeInfo.nodeType()), + nodeInfo.id()); + + String nodeLogDir = new File(nodeInfo.logPath()).getParent(); + + String javaParams = nodeInfo.parameterString(); + + String javaHome = runCtx.dockerContext().javaHome(nodeInfo.nodeType()); + + try { + String mkdirCmd = String.format("exec %s mkdir -p %s", contName, nodeLogDir); + + String startNodeCmd = String.format("%s/bin/java %s", javaHome, javaParams); + + String cmd = String.format("exec %s nohup %s > %s 2>& 1 &", contName, startNodeCmd, nodeInfo.logPath()); + + runCtx.handler().runDockerCmd(nodeInfo.host(), mkdirCmd); + + runCtx.handler().runDockerCmd(nodeInfo.host(), cmd); + } + catch (IOException e) { + log().error(String.format("Failed to start node '%s' on the host '%s'.", + nodeInfo.toShortStr(), + nodeInfo.host())); + + nodeInfo.commandExecutionResult(CommandExecutionResult.emptyFailedResult()); + } + + nodeInfo.dockerInfo(new DockerInfo(null, contName)); + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/starters/NodeStarter.java b/src/main/java/org/yardstickframework/runners/starters/NodeStarter.java new file mode 100644 index 0000000..57a3073 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/starters/NodeStarter.java @@ -0,0 +1,52 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.starters; + +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunContext; + +/** + * Node starter. + */ +public abstract class NodeStarter { + /** */ + protected RunContext runCtx; + + /** + * + * @param runCtx Run context. + */ + public NodeStarter(RunContext runCtx) { + this.runCtx = runCtx; + } + + /** + * + * @param nodeInfo Node info. + * @return Node info. + * @throws InterruptedException if interrupted. + */ + public abstract NodeInfo startNode(NodeInfo nodeInfo) throws InterruptedException; + + /** + * + * @return Logger. + */ + protected Logger log(){ + return LogManager.getLogger(getClass().getSimpleName()); + } +} diff --git a/src/main/java/org/yardstickframework/runners/starters/PlainNodeStarter.java b/src/main/java/org/yardstickframework/runners/starters/PlainNodeStarter.java new file mode 100644 index 0000000..f9e22b8 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/starters/PlainNodeStarter.java @@ -0,0 +1,95 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.starters; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.yardstickframework.runners.Runner; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunContext; + +/** + * Starts nodes. + */ +public class PlainNodeStarter extends NodeStarter { + /** */ + private static Map hostJavaHomeMap = new HashMap<>(); + + /** + * + * @param runCtx Run context. + */ + public PlainNodeStarter(RunContext runCtx) { + super(runCtx); + } + + /** {@inheritDoc} */ + @Override public NodeInfo startNode(NodeInfo nodeInfo) throws InterruptedException{ + String host = nodeInfo.host(); + + String param = nodeInfo.parameterString(); + + String javaHome = runCtx.getHostJava(host); + + CommandExecutionResult res = null; + + try { + String withJavaHome = String.format("%s/bin/java %s", javaHome, param); + + res = runCtx.handler().startNode(host, withJavaHome, nodeInfo.logPath()); + + nodeInfo.commandExecutionResult(res); + } + catch (IOException e) { + log().error(String.format("Failed to start node '%s' on the host '%s'.", + nodeInfo.toShortStr(), + nodeInfo.host())); + + nodeInfo.commandExecutionResult(CommandExecutionResult.emptyFailedResult()); + } + + return nodeInfo; + } + + /** + * + * @param host Host. + * @return Host Java home path. + */ + private String getHostJavaHome(String host) { + return runCtx.handler().getHostJavaHome(host); + } + + /** + * + * @param host Host. + */ + private void printNoJavaError(String host) { + log().info(String.format("Failed to get default JAVA_HOME variable from the host %s", host)); + log().info(String.format("Will not start node on the host %s", host)); + + } + + /** + * + * @param host Host. + * @return {@code boolean} true if host already been checked or {@code false} otherwise. + */ + private boolean checked(String host) { + return hostJavaHomeMap.containsKey(host); + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/CheckWorkResult.java b/src/main/java/org/yardstickframework/runners/workers/CheckWorkResult.java new file mode 100644 index 0000000..c9d77aa --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/CheckWorkResult.java @@ -0,0 +1,37 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers; + +/** + * Check work result. + */ +public class CheckWorkResult implements WorkResult { + /** Flag indicating whether or not process should be terminated.*/ + private boolean exit; + + /** + * @return Exit. + */ + public boolean exit() { + return exit; + } + + /** + * @param exit New exit. + */ + public void exit(boolean exit) { + this.exit = exit; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/WorkResult.java b/src/main/java/org/yardstickframework/runners/workers/WorkResult.java new file mode 100644 index 0000000..e46f4e6 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/WorkResult.java @@ -0,0 +1,21 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers; + +/** + * Work result. + */ +public interface WorkResult { +} diff --git a/src/main/java/org/yardstickframework/runners/workers/Worker.java b/src/main/java/org/yardstickframework/runners/workers/Worker.java new file mode 100644 index 0000000..dca16a7 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/Worker.java @@ -0,0 +1,92 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.yardstickframework.BenchmarkUtils; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunContext; + +/** + * Parent for workers. + */ +public abstract class Worker{ + /** Run context */ + protected RunContext runCtx; + + /** Local addresses*/ + private static final Set LOC_ADR_SET = Stream.of("localhost", "127.0.0.1") + .collect(Collectors.toCollection(HashSet::new)); + + /** + * Constructor. + * + * @param runCtx Run context. + */ + public Worker(RunContext runCtx) { + this.runCtx = runCtx; + } + + /** + * Executes before workOnHosts() + */ + public void beforeWork(){}; + + /** + * Executes after workOnHosts(). + */ + public void afterWork(){}; + + /** + * + * @return Logger. + */ + protected Logger log(){ + return LogManager.getLogger(workerName()); + } + + /** + * + * @return Worker name. + */ + protected String workerName(){ + return getClass().getSimpleName(); + } + + /** + * + * @param nodeInfo Node info. + * @return Thread name. + */ + protected String threadName(NodeInfo nodeInfo){ + return String.format("%s-%s", + workerName(), + nodeInfo.host()); + } + + /** + * + * @param host Host. + * @return {@code true} if host address is "localhost" or "127.0.0.1" or {@code false} otherwise. + */ + protected boolean isLocal(String host) { + return LOC_ADR_SET.contains(host.toLowerCase()); + } +} \ No newline at end of file diff --git a/src/main/java/org/yardstickframework/runners/workers/host/CheckConnWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/CheckConnWorker.java new file mode 100644 index 0000000..f99c446 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/CheckConnWorker.java @@ -0,0 +1,48 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.util.Set; +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Checks ssh connection. + */ +public class CheckConnWorker extends CheckWorker { + /** {@inheritDoc} */ + public CheckConnWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + CheckWorkResult res = new CheckWorkResult(); + + if (isLocal(host)) + return res; + + log().info(String.format("Checking ssh connection to the host '%s'.", host)); + + if (!runCtx.handler().checkConn(host)) { + log().info(String.format("Failed to establish connection to the host '%s'.", host)); + + res.exit(true); + } + + return res; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/CheckJavaWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/CheckJavaWorker.java new file mode 100644 index 0000000..7815770 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/CheckJavaWorker.java @@ -0,0 +1,99 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Checks java on remote hosts and set host map. + */ +public class CheckJavaWorker extends CheckWorker { + /** */ + private String locJavaHome; + + /** */ + private static final Collection checked = new HashSet<>(); + + /** {@inheritDoc} */ + public CheckJavaWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public void beforeWork() { + super.beforeWork(); + + locJavaHome = System.getProperty("java.home"); + + if (!runCtx.onlyLocal() && runCtx.properties().getProperty("JAVA_HOME") == null) + log().warn("'JAVA_HOME' is not defined in property file."); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + CheckWorkResult res = new CheckWorkResult(); + + synchronized (this) { + if (checked.contains(host)) + return res; + + checked.add(host); + } + + if (runCtx.remoteJavaHome() != null) { + if (!runCtx.handler().checkJava(host, runCtx.remoteJavaHome())) { + log().info(String.format("Failed to find %s/bin/java on the host %s.", + runCtx.remoteJavaHome(), host)); + + res.exit(true); + } + else + runCtx.putInJavaHostMap(host, runCtx.remoteJavaHome()); + + return res; + } + + if (runCtx.handler().checkJava(host, locJavaHome)) { + log().info(String.format("Using JAVA_HOME '%s' on the host '%s'.", locJavaHome, host)); + + runCtx.putInJavaHostMap(host, locJavaHome); + } + else { + String hostJava = runCtx.handler().getHostJavaHome(host); + + String warn1 = String.format("Default JAVA_HOME " + + "'%s' on the host '%s' is different from default JAVA_HOME on the current host '%s'.", + hostJava, + host, + locJavaHome); + + String warn2 = String.format("Will use '%s' to start nodes on the host %s.", + hostJava, + host); + + log().warn(warn1); + log().warn(warn2); + + runCtx.putInJavaHostMap(host, hostJava); + } + + return res; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/CheckWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/CheckWorker.java new file mode 100644 index 0000000..60a5093 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/CheckWorker.java @@ -0,0 +1,40 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.util.Set; +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Parent for check workers. + */ +public abstract class CheckWorker extends HostWorker { + /** {@inheritDoc} */ + CheckWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public void afterWork() { + for(WorkResult res : resList()){ + CheckWorkResult checkRes = (CheckWorkResult) res; + + if(checkRes.exit()) + System.exit(runCtx.exitCode()); + } + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/CleanRemDirWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/CleanRemDirWorker.java new file mode 100644 index 0000000..f40a6e9 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/CleanRemDirWorker.java @@ -0,0 +1,67 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.Set; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Cleans remote directory. + */ +public class CleanRemDirWorker extends HostWorker { + /** */ + private String[] toClean = new String[] {"bin", "config", "libs", "output", "work"}; + + /** {@inheritDoc} */ + public CleanRemDirWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + return clean(host); + } + + /** + * @param host Host + * @return Work result. + */ + private WorkResult clean(String host) { + if ((isLocal(host) && runCtx.localeWorkDirectory().equals(runCtx.remoteWorkDirectory())) + || host.equals(runCtx.currentHost()) && runCtx.localeWorkDirectory().equals(runCtx.remoteWorkDirectory())) + return null; + + String remDir = runCtx.remoteWorkDirectory(); + + log().info(String.format("Cleaning up directory '%s' on the host '%s'.", remDir, host)); + + try { + for (String name : toClean) { + String cleanCmd = String.format("rm -rf %s/%s", + runCtx.remoteWorkDirectory(), name); + + runCtx.handler().runCmd(host, cleanCmd); + } + + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to clean remote directory on the host '%s'", host), e); + } + + return null; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/CollectWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/CollectWorker.java new file mode 100644 index 0000000..ca9b2d1 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/CollectWorker.java @@ -0,0 +1,68 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.File; +import java.io.IOException; +import java.util.Set; +import org.yardstickframework.runners.CommandHandler; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Collects data from remote hosts. + */ +public class CollectWorker extends HostWorker { + /** Main output directory */ + private File outDir; + + /** {@inheritDoc} */ + public CollectWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + + outDir = new File(String.format("%s/output", runCtx.localeWorkDirectory())); + } + + /** {@inheritDoc} */ + @Override public void beforeWork() { + if (!outDir.exists()) + outDir.mkdirs(); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + if (isLocal(host) && runCtx.localeWorkDirectory().equals(runCtx.remoteWorkDirectory())) + return null; + + String nodeOutDir = String.format("%s/output", runCtx.remoteWorkDirectory()); + + log().info(String.format("Collecting data from the host '%s'.", host)); + + String pathLoc = outDir.getAbsolutePath(); + + try { + String pathRem = String.format("%s/*", nodeOutDir); + + runCtx.handler().download(host, pathLoc, pathRem); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to collect data from the host '%s'", host), e); + + runCtx.exitCode(1); + } + + return null; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/DeployWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/DeployWorker.java new file mode 100644 index 0000000..ec0ec87 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/DeployWorker.java @@ -0,0 +1,75 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Set; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Deploys on hosts. + */ +public class DeployWorker extends HostWorker { + /** List of directories to deploy. */ + private String[] toDeploy = new String[] {"bin", "config", "libs"}; + + /** */ + private CleanRemDirWorker cleaner; + + /** {@inheritDoc} */ + public DeployWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + + cleaner = new CleanRemDirWorker(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public void beforeWork() { + cleaner.workOnHosts(); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + if ((isLocal(host) && runCtx.localeWorkDirectory().equals(runCtx.remoteWorkDirectory())) + || host.equals(runCtx.currentHost()) && runCtx.localeWorkDirectory().equals(runCtx.remoteWorkDirectory())) + return null; + + String createCmd = String.format("mkdir -p %s", runCtx.remoteWorkDirectory()); + + try { + runCtx.handler().runCmd(host, createCmd); + + log().info(String.format("Deploying on the host '%s'.", host)); + + for (String name : toDeploy) { + String fullPath = Paths.get(runCtx.remoteWorkDirectory(), name).toAbsolutePath().toString(); + + if (runCtx.handler().checkRemFile(host, fullPath)) + runCtx.handler().runMkdirCmd(host, fullPath); + + String locPath = String.format("%s/%s", runCtx.localeWorkDirectory(), name); + + runCtx.handler().upload(host, locPath, runCtx.remoteWorkDirectory()); + } + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to deploy on the host '%s'", host), e); + } + + return null; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/DockerBuildImagesWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/DockerBuildImagesWorker.java new file mode 100644 index 0000000..6148740 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/DockerBuildImagesWorker.java @@ -0,0 +1,105 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.Set; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; + +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; + +/** + * Builds docker images on hosts. + */ +public class DockerBuildImagesWorker extends DockerHostWorker { + /** */ + private static final String DFLT_BUILD_CMD = "build --no-cache -t IMAGE_NAME_PLACEHOLDER -f " + + "DOCKERFILE_PATH_PLACEHOLDER ."; + + /** */ + private static final String IMAGE_NAME_PLACEHOLDER = "IMAGE_NAME_PLACEHOLDER"; + + /** */ + private static final String DOCKERFILE_PATH_PLACEHOLDER = "DOCKERFILE_PATH_PLACEHOLDER"; + + /** */ + private NodeType nodeType; + + /** + * Constructor. + * + * @param runCtx Run context. + * @param hostSet Main host list to work with. + * @param nodeType Node type + */ + public DockerBuildImagesWorker(RunContext runCtx, Set hostSet, + NodeType nodeType) { + super(runCtx, hostSet); + this.nodeType = nodeType; + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + String nameToUse = getImageNameToUse(nodeType); + + CheckWorkResult res = new CheckWorkResult(); + + if (!checkIfImageExists(host, nameToUse)) { + log().info(String.format("Building docker image '%s' on the host '%s'.", nameToUse, + host)); + + String docFilePath = runCtx.resolveRemotePath(dockerCtx.getNodeContext(nodeType).getDockerfilePath()); + + if(!runCtx.handler().checkRemFile(host, docFilePath)){ + log().error(String.format("Failed to find file '%s' on the host '%s'. Cannot build docker image.", + docFilePath, host)); + + res.exit(true); + + return res; + } + + String src = dockerCtx.getDockerBuildCmd() != null ? dockerCtx.getDockerBuildCmd() : + DFLT_BUILD_CMD; + + String buildCmd = src.replace(IMAGE_NAME_PLACEHOLDER, nameToUse) + .replace(DOCKERFILE_PATH_PLACEHOLDER, docFilePath); + + try { + runCtx.handler().runDockerCmd(host, buildCmd); + + if(checkIfImageExists(host, nameToUse)) + log().info(String.format("Successfully built image '%s' on the host '%s'.", nameToUse, + host)); +// else { +// log().error(String.format("Failed to build image '%s' on the host '%s'.", nameToUse, host)); +// +// runCtx.exitCode(1); +// +// res.exit(true); +// } + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to build image '%s' on the host '%s'.", nameToUse, host), e); + } + } + else + log().info(String.format("Found image '%s' on the host '%s'.", nameToUse, host)); + + return res; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/DockerCheckWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/DockerCheckWorker.java new file mode 100644 index 0000000..e7d6050 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/DockerCheckWorker.java @@ -0,0 +1,56 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.Set; +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.RunContext; + +import org.yardstickframework.runners.workers.WorkResult; + +/** + * Checks docker on remote hosts. + */ +public class DockerCheckWorker extends CheckWorker { + /** {@inheritDoc} */ + public DockerCheckWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + CheckWorkResult workRes = new CheckWorkResult(); + + try { + CommandExecutionResult res = runCtx.handler().runDockerCmd(host, "images"); + + if(res.exitCode() != 0 || !res.errorList().isEmpty()){ + for(String err : res.errorList()) + log().error(err); + + workRes.exit(true); + } + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to check docker on the host '%s'", host), e); + + workRes.exit(true); + } + + return workRes; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/DockerCleanContWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/DockerCleanContWorker.java new file mode 100644 index 0000000..503d1af --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/DockerCleanContWorker.java @@ -0,0 +1,105 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.RunContext; + +import org.yardstickframework.runners.workers.CheckWorkResult; +import org.yardstickframework.runners.workers.WorkResult; + +/** + * Cleans docker containers. + */ +public class DockerCleanContWorker extends DockerHostWorker { + /** {@inheritDoc} */ + public DockerCleanContWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + return removeContainers(host); + } + + /** + * @param host Host. + * @return Work result. + */ + private WorkResult removeContainers(String host) { + CheckWorkResult res = new CheckWorkResult(); + + if (dockerCtx.getContainersToRemove() == null){ + log().error("Failed to remove containers. Property 'containersToRemove' is not defined."); + + res.exit(true); + + return res; + } + + Collection> contMaps = getProcesses(host); + + for (Map contMap : contMaps) { + for (String contName : dockerCtx.getContainersToRemove()) { + String names = contMap.get("NAMES"); + + if (names.contains(contName)) { + log().info(String.format("Removing the container '%s' (id = %s) from the host '%s'.", + names, contMap.get("CONTAINER ID"), host)); + + removeSingleCont(host, contMap.get("CONTAINER ID")); + } + } + } + + return res; + } + + /** + * @param host Host. + * @param contId Container id. + * @return Command execution result. + */ + private CommandExecutionResult removeSingleCont(String host, String contId) { + + CommandExecutionResult cmdRes = null; + + try { + runCtx.handler().runDockerCmd(host, String.format("stop %s", contId)); + + cmdRes = runCtx.handler().runDockerCmd(host, String.format("rm %s", contId)); + } + catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + + Collection> processes = getProcesses(host); + + String res = "successfully removed"; + + for (Map proc : processes) + if (proc.get("CONTAINER ID").equals(contId)) + res = "not removed"; + + log().info(String.format("The container '%s' is %s.", contId, res)); + + return cmdRes; + } + +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/DockerCleanImagesWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/DockerCleanImagesWorker.java new file mode 100644 index 0000000..40ed0ff --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/DockerCleanImagesWorker.java @@ -0,0 +1,95 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.workers.WorkResult; + +/** + * Cleans docker containers. + */ +public class DockerCleanImagesWorker extends DockerHostWorker { + /** {@inheritDoc} */ + public DockerCleanImagesWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + removeImages(host); + + return null; + } + + /** + * @param host Host. + */ + private void removeImages(String host) { + Collection> imageMaps = getImages(host); + + Map toRem = new HashMap<>(); + + for (Map imageMap : imageMaps) { + String imageName = imageMap.get("REPOSITORY"); + + if (nameToDelete(imageName)) + toRem.put(imageMap.get("IMAGE ID"), imageName); + } + + int tryes = 2; + + // Removing images twice because some of the server-node images can have child driver-node images and therefore + // cannot be removed right away. + while (tryes-- > 0) { + for (String id : toRem.keySet()) { + if (checkIfImageIdExists(host, id)) + removeImage(host, id, toRem.get(id)); + } + } + } + + /** + * @param host Host. + * @param imageId Image id. + * @param imageName Image name. + * @return Command execution result. + */ + private CommandExecutionResult removeImage(String host, String imageId, String imageName) { + log().info(String.format("Removing the image '%s' (id=%s) from the host '%s'", + imageName, imageId, host)); + + CommandExecutionResult cmdRes = CommandExecutionResult.emptyFailedResult(); + + try { + cmdRes = runCtx.handler().runDockerCmd(host, String.format("rmi -f %s", imageId)); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to remove image '%s' from the host '%s'.", imageName, host)); + } + + if(!checkIfImageIdExists(host, imageId)) + log().info(String.format("Image '%s' on the host '%s' is successfully removed.", imageName, host)); + else + log().info(String.format("Image '%s' on the host '%s' is not removed.", imageName, host)); + + return cmdRes; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/DockerHostWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/DockerHostWorker.java new file mode 100644 index 0000000..776e405 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/DockerHostWorker.java @@ -0,0 +1,170 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.DockerContext; +import org.yardstickframework.runners.context.RunContext; + +/** + * Parent for docker host workers. + */ +abstract class DockerHostWorker extends HostWorker { + /** */ + private static final String[] IMAGES_HEADERS = new String[] {"REPOSITORY", "TAG", "IMAGE ID", "CREATED", "SIZE"}; + + /** */ + private static final String[] PROCESS_HEADERS = new String[] {"CONTAINER ID", "IMAGE", "COMMAND", "CREATED", "STATUS", "PORTS", "NAMES"}; + + /** */ + DockerContext dockerCtx; + + /** {@inheritDoc} */ + public DockerHostWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + + dockerCtx = runCtx.dockerContext(); + } + + + /** + * @param host Host. + * @param name Image name. + * @return {@code true} if image with given name exists on the specified host or {@code false} otherwise. + */ + public boolean checkIfImageExists(String host, String name) { + Collection> imageMaps = getImages(host); + + for (Map imageMap : imageMaps) { + if (imageMap.get("REPOSITORY").equals(name)) + return true; + + } + + return false; + } + + /** + * @param host Host. + * @param id Image id. + * @return {@code true} if image with given name exists on the specified host or {@code false} otherwise. + */ + boolean checkIfImageIdExists(String host, String id) { + Collection> imageMaps = getImages(host); + + for (Map imageMap : imageMaps) { + if (imageMap.get("IMAGE ID").equals(id)) + return true; + + } + + return false; + } + + /** + * @param host Host. + * @return Result of 'docker images' execution. + */ + Collection> getImages(String host) { + return getMaps(host, "images", IMAGES_HEADERS); + } + + /** + * @param host Host. + * @return Result of 'docker ps -a' execution. + */ + Collection> getProcesses(String host) { + return getMaps(host, "ps -a", PROCESS_HEADERS); + } + + /** + * Maps with docker command response. + * + * @param host Host. + * @param cmd Command e.g. images' or 'ps -a'. + * @param headers Headers to create map. Each header will be the key and the value will be corresponding line + * from the output string. + * @return Maps with docker command response. + */ + private Collection> getMaps(String host, String cmd, String[] headers) { + + try { + CommandExecutionResult cmdRes = runCtx.handler().runDockerCmd(host, cmd); + + List outStr = cmdRes.outputList(); + + Collection> res = new ArrayList<>(); + + if (outStr.size() == 1 && outStr.get(0).equals(headers[0])) + return res; + + String hdrStr = outStr.get(0); + + for (int i = 1; i < outStr.size(); i++) { + String toParse = outStr.get(i); + + Map valMap = new HashMap<>(headers.length); + + for (int hdr = 0; hdr < headers.length; hdr++) { + int idx0 = hdrStr.indexOf(headers[hdr]); + + int idx1 = hdr == headers.length - 1 ? toParse.length() : hdrStr.indexOf(headers[hdr + 1]); + + String val = toParse.substring(idx0, idx1); + + while (val.endsWith(" ")) + val = val.substring(0, val.length() - 1); + + valMap.put(headers[hdr], val); + } + + res.add(valMap); + } + + return res; + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to get response for command '%s' from the host '%s'", cmd, host), e); + + return new ArrayList<>(); + } + } + + /** + * @param type Node type. + * @return Image name for the given type. + */ + String getImageNameToUse(NodeType type) { + return dockerCtx.getNodeContext(type).getImageName(); + } + + /** + * @param name Image name. + * @return {@code true} if image name is defined server image name or driver image name, + * or {@code false otherwise}. + */ + boolean nameToDelete(String name) { + return name.equals(dockerCtx.getNodeContext(NodeType.SERVER).getImageName()) + || name.equals(dockerCtx.getNodeContext(NodeType.DRIVER).getImageName()); + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/HostWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/HostWorker.java new file mode 100644 index 0000000..134217e --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/HostWorker.java @@ -0,0 +1,118 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; +import java.util.List; +import java.util.TreeSet; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.workers.Worker; +import org.yardstickframework.runners.context.RunContext; + +/** + * Parent for host workers. + */ +public abstract class HostWorker extends Worker { + /** Main host list to work with. */ + private final Set hostSet; + + /** Result list. */ + private final List resList; + + /** + * Getter for result list. + * + * @return Result list. + */ + List resList() { + return new ArrayList<>(resList); + } + + /** + * Constructor. + * + * @param runCtx Run context. + * @param hostSet Main host list to work with. + */ + HostWorker(RunContext runCtx, Set hostSet) { + super(runCtx); + this.hostSet = new TreeSet<>(hostSet); + + resList = new ArrayList<>(hostSet.size()); + } + + /** + * Actual work method which every worker must implement. + * + * @param host Host. + * @param cnt Number in host list. + * @return Work result. + */ + public abstract WorkResult doWork(String host, int cnt); + + /** + * Executes doWork() method defined in worker class asynchronously. + * + * @return List of {@code WorkResult} objects. + */ + public List workOnHosts() { + if (hostSet.isEmpty()) + return new ArrayList<>(); + + beforeWork(); + + ExecutorService exec = Executors.newFixedThreadPool(Math.min(hostSet.size(), + Runtime.getRuntime().availableProcessors())); + + Collection> futList = new ArrayList<>(); + + List hostList = new ArrayList<>(hostSet); + + for (int cnt = 0; cnt < hostList.size(); cnt++) { + final int cntF = cnt; + + final String host = hostList.get(cntF); + + futList.add(exec.submit(new Callable() { + @Override public WorkResult call() throws Exception { + Thread.currentThread().setName(String.format("%s-%s", workerName(), host)); + + return doWork(host, cntF); + } + })); + } + + for (Future f : futList) { + try { + resList.add(f.get()); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + exec.shutdown(); + + afterWork(); + + return new ArrayList<>(resList); + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/host/KillWorker.java b/src/main/java/org/yardstickframework/runners/workers/host/KillWorker.java new file mode 100644 index 0000000..c32f17c --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/host/KillWorker.java @@ -0,0 +1,50 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.host; + +import java.io.IOException; +import java.util.Set; +import org.yardstickframework.runners.workers.WorkResult; +import org.yardstickframework.runners.context.RunContext; + +/** + * Kills nodes. + */ +public class KillWorker extends HostWorker { + /** {@inheritDoc} */ + public KillWorker(RunContext runCtx, Set hostSet) { + super(runCtx, hostSet); + } + + /** {@inheritDoc} */ + @Override public WorkResult doWork(String host, int cnt) { + + + try { + String killServCmd = "pkill -9 -f Dyardstick.server"; + + runCtx.handler().runCmd(host, killServCmd); + + String killDrvrCmd = "pkill -9 -f Dyardstick.driver"; + + runCtx.handler().runCmd(host, killDrvrCmd); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to kill nodes on the host '%s'", host), e); + } + + return null; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/CheckLogWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/CheckLogWorker.java new file mode 100644 index 0000000..d6f6fbb --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/CheckLogWorker.java @@ -0,0 +1,94 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.checkers.NodeChecker; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeStatus; +import org.yardstickframework.runners.context.RunContext; + +/** + * Checks node log. + */ +public class CheckLogWorker extends NodeWorker { + /** {@inheritDoc} */ + public CheckLogWorker(RunContext runCtx, List nodeList) { + super(runCtx, nodeList); + } + + /** */ + private static final String[] keyWords = new String[]{"Exception", "failed", "Error"}; + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + String host = nodeInfo.host(); + + String logPath = nodeInfo.logPath(); + + boolean fileExists = false; + + int cnt = 10; + + while (!fileExists && cnt-- > 0) { + fileExists = runCtx.handler().checkRemFile(host, logPath); + + new CountDownLatch(1).await(1000L, TimeUnit.MILLISECONDS); + } + + NodeChecker checker = runCtx.nodeChecker(nodeInfo); + + checker.checkNode(nodeInfo); + + if (nodeInfo.nodeStatus() == NodeStatus.NOT_RUNNING) + log().info(String.format("Node '%s' on the host '%s' in not running. Will check log file and exit.", + nodeInfo.toShortStr(), + host)); + + if (!fileExists) { + log().info(String.format("No log file '%s' on the host '%s'.", logPath, host)); + + return nodeInfo; + } + + try { + CommandExecutionResult res = runCtx.handler().runGrepCmd(host, logPath, Arrays.asList(keyWords)); + + if (!res.outputList().isEmpty()) { + nodeInfo.errorMessages().addAll(res.outputList()); + + log().warn(String.format("Log file '%s' contains following error messages:", + logPath)); + + for (String msg : res.outputList()) + log().error(msg); + + return nodeInfo; + } + } + catch (IOException e) { + log().error(String.format("Failed to check log for the node '%s' on the host '%s'", + nodeInfo.toShortStr(), + host), e); + } + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/DockerCollectWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/DockerCollectWorker.java new file mode 100644 index 0000000..a5edc90 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/DockerCollectWorker.java @@ -0,0 +1,66 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.io.IOException; +import java.util.List; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; + +/** + * Collects data from docker containers/ + */ +public class DockerCollectWorker extends NodeWorker { + /** {@inheritDoc} */ + public DockerCollectWorker(RunContext runCtx, List nodeList) { + super(runCtx, nodeList); + } + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + NodeType type = nodeInfo.nodeType(); + + String host = nodeInfo.host(); + + String id = nodeInfo.id(); + + String contNamePref = runCtx.dockerContext().contNamePrefix(type); + + String contName = String.format("%s_%s", contNamePref, id); + + String nodeOutDir = String.format("%s/output", runCtx.remoteWorkDirectory()); + + String cpCmd = String.format("cp %s:%s/output %s", contName, runCtx.remoteWorkDirectory(), runCtx.remoteWorkDirectory()); + + log().info(String.format("Collecting data from the container '%s' on the host '%s'.", contName, host)); + + try { + String mkdirCmd = String.format("mkdir -p %s", nodeOutDir); + + runCtx.handler().runCmd(host, mkdirCmd); + + runCtx.handler().runDockerCmd(host, cpCmd); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to collect data from container '%s' on the host '%s'", + contName, host), e); + + runCtx.exitCode(1); + } + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/DockerStartContWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/DockerStartContWorker.java new file mode 100644 index 0000000..51b07c9 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/DockerStartContWorker.java @@ -0,0 +1,205 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.TreeSet; +import org.yardstickframework.runners.CommandExecutionResult; +import org.yardstickframework.runners.context.DockerInfo; +import org.yardstickframework.runners.DockerRunner; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.DockerContext; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.workers.host.DockerBuildImagesWorker; + +/** + * Starts docker containers. + */ +public class DockerStartContWorker extends NodeWorker { + /** */ + private static final String DFLT_RUN_CMD = + "run -d --network host --name CONT_NAME_PLACEHOLDER IMAGE_NAME_PLACEHOLDER sleep 1d"; + + /** */ + private static final String CONT_NAME_PLACEHOLDER = "CONT_NAME_PLACEHOLDER"; + + /** */ + private static final String IMAGE_NAME_PLACEHOLDER = "IMAGE_NAME_PLACEHOLDER"; + + /** */ + private DockerContext dockerCtx; + + /** {@inheritDoc} */ + public DockerStartContWorker(RunContext runCtx, List nodeList) { + super(runCtx, nodeList); + + dockerCtx = runCtx.dockerContext(); + } + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + String host = nodeInfo.host(); + + String id = nodeInfo.id(); + + NodeType type = nodeInfo.nodeType(); + + String imageName = dockerCtx.getImageName(type); + + String contName = "Undefined"; + + try { + CommandExecutionResult res = CommandExecutionResult.emptyFailedResult(); + + DockerBuildImagesWorker imageWorker = new DockerBuildImagesWorker(runCtx, new TreeSet<>(), nodeInfo.nodeType()); + + if (!imageWorker.checkIfImageExists(host, imageName)) { + log().error(String.format("Image '%s' does not exist on the host '%s'. Cannot start containers.", + imageName, host)); + + runCtx.exitCode(1); + + return nodeInfo; + } + + String contNamePref = dockerCtx.contNamePrefix(type); + + contName = String.format("%s_%s", contNamePref, id); + + DockerInfo docInfo = new DockerInfo(imageName, contName); + + nodeInfo.dockerInfo(docInfo); + + log().info(String.format("Starting the container '%s' on the host '%s'", contName, host)); + + String startContCmd = getStartContCmd(imageName, contName); + + res = runCtx.handler().runDockerCmd(host, startContCmd); + + String mkdirCmd = String.format("exec %s mkdir -p %s", contName, runCtx.remoteWorkDirectory()); + + res = runCtx.handler().runDockerCmd(host, mkdirCmd); + + String remPath = runCtx.remoteWorkDirectory(); + + String parentPath = new File(remPath).getParentFile().getAbsolutePath(); + + String cpCmd = String.format("cp %s %s:%s", remPath, contName, parentPath); + + res = runCtx.handler().runDockerCmd(host, cpCmd); + + nodeInfo.commandExecutionResult(res); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to start container '%s' on the host '%s'", + contName, host), e); + + runCtx.exitCode(1); + + nodeInfo.commandExecutionResult(CommandExecutionResult.emptyFailedResult()); + + return nodeInfo; + } + + return nodeInfo; + } + + /** + * @param imageName Image name. + * @param contName Container name. + * @return Command to start docker container. + */ + private String getStartContCmd(String imageName, String contName) { + String withPlaceHolders = dockerCtx.getDockerRunCmd() != null ? dockerCtx.getDockerRunCmd() : DFLT_RUN_CMD; + + String withImageName = withPlaceHolders.replace(IMAGE_NAME_PLACEHOLDER, imageName); + + return withImageName.replace(CONT_NAME_PLACEHOLDER, contName); + } + + /** {@inheritDoc} */ + @Override public void afterWork() { + if (runCtx.exitCode() != 0) + System.exit(runCtx.exitCode()); + + if (!resNodeList().isEmpty()) { + try { + setDockerJavaHome(resNodeList().get(0)); + } + catch (IOException | InterruptedException e) { + log().error(String.format("Failed to set Java home for the node type'%s'", + resNodeList().get(0).nodeType()), e); + } + } + } + + /** + * @param nodeInfo Node info. + * @throws IOException if failed. + * @throws InterruptedException if interrupted. + */ + private void setDockerJavaHome(NodeInfo nodeInfo) throws IOException, InterruptedException { + NodeType type = nodeInfo.nodeType(); + + String contName = nodeInfo.dockerInfo().contName(); + + String echoCmd = String.format("exec %s sh -c 'echo $JAVA_HOME'", contName); + + String host = nodeInfo.host(); + + CommandExecutionResult res = runCtx.handler().runDockerCmd(host, echoCmd); + + if (!res.outputList().isEmpty()) { + String javaHome = res.outputList().get(0); + + switch (type) { + case SERVER: + if (dockerCtx.serverDockerJavaHome() == null) { + log().info(String.format("Using docker JAVA_HOME for server nodes: '%s'", + javaHome)); + + dockerCtx.serverDockerJavaHome(javaHome); + } + break; + case DRIVER: + if (dockerCtx.driverDockerJavaHome() == null) { + log().info(String.format("Using docker JAVA_HOME for driver nodes: '%s'", + javaHome)); + + dockerCtx.driverDockerJavaHome(javaHome); + } + break; + default: + log().info("Unknown node type " + type); + } + } + else { + log().info(String.format("Failed to get JAVA_HOME variable from docker container '%s'", contName)); + + log().info("Will clean up docker and exit."); + + DockerRunner runner = new DockerRunner(runCtx); + + runner.cleanUp(runCtx.nodeTypes(RunMode.DOCKER), "after"); + + System.exit(runCtx.exitCode()); + } + + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/NodeWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/NodeWorker.java new file mode 100644 index 0000000..283ff81 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/NodeWorker.java @@ -0,0 +1,173 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.workers.Worker; + +/** + * Parent class for node workers. + */ +public abstract class NodeWorker extends Worker { + /** Main list of NodeInfo objects to work with. */ + private List nodeList; + + /** Result list */ + private List resNodeList; + + /** Flag indicating whether or not task should run on the same host at the same time. */ + private boolean runAsyncOnHost; + + /** + * Constructor. + * + * @param runCtx Run context. + * @param nodeList Main list of NodeInfo objects to work with. + */ + NodeWorker(RunContext runCtx, List nodeList) { + super(runCtx); + this.nodeList = new ArrayList<>(nodeList); + resNodeList = new ArrayList<>(nodeList.size()); + } + + /** + * Executes actual work for node. + * + * @param nodeInfo {@code NodeInfo} object to work with. + * @return {@code NodeInfo} result. + * @throws InterruptedException if interrupted. + */ + public abstract NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException; + + /** + * @return {@code int} Number of objects in the main list. + */ + int getNodeListSize() { + return nodeList.size(); + } + + /** + * Executes doWork() method defined in worker class asynchronously. + * + * @return List of NodeInfo objects. + */ + public List workForNodes() { + beforeWork(); + + if (nodeList.isEmpty()) + return nodeList; + + ExecutorService exec = Executors.newFixedThreadPool(nodeList.size()); + + Collection> futList = new ArrayList<>(nodeList.size()); + + final Map semMap = new HashMap<>(); + + for (final NodeInfo nodeInfo : nodeList) + semMap.put(nodeInfo.host(), new Semaphore(1)); + + for (final NodeInfo nodeInfo : nodeList) { + futList.add(exec.submit(new Callable() { + @Override public NodeInfo call() throws Exception { + String host = nodeInfo.host(); + + Thread.currentThread().setName(threadName(nodeInfo)); + + if (!runAsyncOnHost) + semMap.get(host).acquire(); + + final NodeInfo res = doWork(nodeInfo); + + semMap.get(host).release(); + + return res; + } + })); + } + + for (Future f : futList) { + try { + NodeInfo nodeInfo = f.get(); + + resNodeList.add(nodeInfo); + } + catch (InterruptedException e) { + for (Future f0 : futList) + f0.cancel(true); + + Thread.currentThread().interrupt(); + + log().info(String.format("%s stopped.", workerName())); + + log().debug(e.getMessage(), e); + + break; + } + catch (Exception e) { + e.printStackTrace(); + } + } + + exec.shutdown(); + + afterWork(); + + for(NodeInfo nodeInfo : resNodeList){ + if(nodeInfo.commandExecutionResult() != null && nodeInfo.commandExecutionResult().exitCode() != 0) + System.exit(nodeInfo.commandExecutionResult().exitCode()); + } + + return new ArrayList<>(resNodeList); + } + + /** + * @return Response node list. + */ + public List resNodeList() { + return new ArrayList<>(resNodeList); + } + + /** + * @return Node list. + */ + public List nodeList() { + return new ArrayList<>(nodeList); + } + + /** + * @return Run async on host. + */ + public boolean runAsyncOnHost() { + return runAsyncOnHost; + } + + /** + * @param runAsyncOnHost New run async on host. + */ + public void runAsyncOnHost(boolean runAsyncOnHost) { + this.runAsyncOnHost = runAsyncOnHost; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/RestartNodeWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/RestartNodeWorker.java new file mode 100644 index 0000000..dacda14 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/RestartNodeWorker.java @@ -0,0 +1,128 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RestartSchedule; +import org.yardstickframework.runners.context.RestartContext; +import org.yardstickframework.runners.context.RunContext; + +/** + * Restart nodes. + */ +public class RestartNodeWorker extends StartNodeWorker { + /** */ + private long startTime; + + /** {@inheritDoc} */ + public RestartNodeWorker(RunContext runCtx, List nodeList, String cfgFullStr) { + super(runCtx, nodeList, cfgFullStr); + } + + /** {@inheritDoc} */ + @Override public void beforeWork() { + super.beforeWork(); + + startTime = System.currentTimeMillis(); + + servLogDirFullName = String.format("%s/log_servers_restarted", baseLogDirFullName); + + drvrLogDirFullName = String.format("%s/log_drivers_restarted", baseLogDirFullName); + } + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + String host = nodeInfo.host(); + + String id = nodeInfo.id(); + + NodeType type = nodeInfo.nodeType(); + + if (runCtx.restartContext(type) == null) { + log().debug(String.format("No restart schedule for %s nodes.", nodeInfo.typeLow())); + + return nodeInfo; + } + + RestartContext restCtx = runCtx.restartContext(type); + + if (restCtx.get(host) == null || restCtx.get(host).get(id) == null) { + log().info(String.format("No restart schedule for '%s' node.", nodeInfo.toShortStr())); + + return nodeInfo; + } + + RestartSchedule restartInfo = runCtx.restartContext(type).get(host).get(id); + + log().info(String.format("Restart schedule for the node '%s' on the host '%s': %s.", + nodeInfo.toShortStr(), + host, + restartInfo)); + + while (!Thread.currentThread().isInterrupted()) { + try { + new CountDownLatch(1).await(restartInfo.delay(), TimeUnit.MILLISECONDS); + + log().info(String.format("Stopping node '%s' on the host '%s'.", nodeInfo.toShortStr(), host)); + + StopNodeWorker stopWorker = new StopNodeWorker(runCtx, Collections.singletonList(nodeInfo)); + + stopWorker.stopNode(nodeInfo); + + new CountDownLatch(1).await(restartInfo.pause(), TimeUnit.MILLISECONDS); + + long currTime = System.currentTimeMillis(); + + // Set new duration only for DRIVER nodes to avoid stopping server restarts due to small duration. + long newDuration = nodeInfo.nodeType() == NodeType.DRIVER ? + initDuration - ((currTime - startTime) / 1000) : + initDuration; + + if(newDuration <= 0) + break; + + // Set warmup to '0' for restarted node. + warmup("0"); + + duration(String.valueOf(newDuration)); + + startNode(nodeInfo); + + if(newDuration * 1000L <= restartInfo.delay() + restartInfo.period()) + break; + + new CountDownLatch(1).await(restartInfo.period(), TimeUnit.MILLISECONDS); + } + catch (InterruptedException ignored) { + log().debug("Restart worker stopped."); + + break; + } + catch (IOException e) { + log().error(String.format("Failed to restart node '%s'", nodeInfo.toShortStr()), e); + } + + log().debug("Restart worker stopped."); + } + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/StartNodeWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/StartNodeWorker.java new file mode 100644 index 0000000..8531411 --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/StartNodeWorker.java @@ -0,0 +1,357 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.io.IOException; +import java.util.List; +import org.yardstickframework.BenchmarkConfiguration; +import org.yardstickframework.BenchmarkUtils; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.starters.NodeStarter; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.context.RunContext; + +/** + * Starts node. + */ +public class StartNodeWorker extends NodeWorker { + /** */ + private String dateTime; + + /** */ + private String logDirName; + + /** */ + protected String baseLogDirFullName; + + /** */ + private String cfgFullStr; + + /** */ + protected String servLogDirFullName; + + /** */ + private String servMainCls = "org.yardstickframework.BenchmarkServerStartUp"; + + /** */ + protected String drvrLogDirFullName; + + /** */ + private String drvrMainCls = "org.yardstickframework.BenchmarkDriverStartUp"; + + /** */ + private String warmup; + + /** */ + private String duration; + + /** Initial duration. */ + protected Long initDuration; + + /** */ + private BenchmarkConfiguration cfg; + + /** + * Constructor. + * + * @param runCtx Run context. + * @param nodeList Main list of NodeInfo objects to work with. + * @param cfgFullStr Config string. + */ + public StartNodeWorker(RunContext runCtx, List nodeList, String cfgFullStr) { + super(runCtx, nodeList); + + // We need to extract data from config string into BenchmarkConfiguration object, set warmap and durations + // from that object and than remove --warmap (-w) and -- duration (-d) from config string in order to oveerride + // those values later if needed. + parseConfigString(cfgFullStr); + + this.cfgFullStr = cfgFullStr; + } + + /** {@inheritDoc} */ + @Override public void beforeWork() { + dateTime = runCtx.mainDateTime(); + + logDirName = String.format("logs-%s", dateTime); + + baseLogDirFullName = String.format("%s/output/%s", runCtx.remoteWorkDirectory(), logDirName); + + servLogDirFullName = String.format("%s/log_servers", baseLogDirFullName); + + drvrLogDirFullName = String.format("%s/log_drivers", baseLogDirFullName); + + warmup = runCtx.warmup(); + + duration = runCtx.duration(); + + initDuration = Long.valueOf(runCtx.duration()); + } + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + return startNode(nodeInfo); + } + + /** + * Starts node. + * + * @param nodeInfo Node info. + * @return Node info. + * @throws InterruptedException if interrupted. + */ + NodeInfo startNode(NodeInfo nodeInfo) throws InterruptedException { + final String nodeStartTime = BenchmarkUtils.dateTime(); + + if(nodeInfo.config() == null) + nodeInfo.config(cfg); + + nodeInfo.nodeStartTime(nodeStartTime); + + String host = nodeInfo.host(); + + String id = nodeInfo.id(); + + NodeType type = nodeInfo.nodeType(); + + String mode = ""; + + String descript = cfg.descriptions() != null ? listToString(cfg.descriptions()) : + String.format("%s-%s-threads", listToString(cfg.driverNames()), runCtx.threads()); + + if (nodeInfo.runMode() != RunMode.PLAIN) + mode = String.format(" Run mode='%s';", nodeInfo.runMode()); + + String wd = nodeInfo.nodeType() == NodeType.DRIVER ? + String.format("Warmup=%s; Duration=%s; ", warmup, duration) : ""; + + log().info(String.format("Starting node '%s' on the host '%s'; %sDescription='%s';%s", + nodeInfo.toShortStr(), + host, + wd, + descript, + mode)); + + String logDirFullName = logDirFullName(nodeInfo); + + try { + runCtx.handler().runMkdirCmd(host, logDirFullName); + } + catch (IOException e) { + e.printStackTrace(); + } + + nodeInfo.description(descript); + + String paramStr = getParamStr(nodeInfo); + + nodeInfo.parameterString(paramStr); + + String logFileName = String.format("%s/%s-%s-id%s-%s-%s.log", + logDirFullName, + nodeStartTime, + nodeInfo.nodeType().toString().toLowerCase(), + id, + host, + descript); + + nodeInfo.logPath(logFileName); + + NodeStarter starter = runCtx.nodeStarter(nodeInfo); + + return starter.startNode(nodeInfo); + } + + /** + * @param nodeInfo Node info. + * @return Parameter string. + */ + private String getParamStr(NodeInfo nodeInfo) { + String host = nodeInfo.host(); + + String id = nodeInfo.id(); + + NodeType type = nodeInfo.nodeType(); + + String drvrResDir = String.format("%s/output/result-%s", runCtx.remoteWorkDirectory(), runCtx.mainDateTime()); + + String outputFolderParam = getNodeListSize() > 1 ? + String.format("--outputFolder %s/%s-%s", drvrResDir, id, host) : + String.format("--outputFolder %s", drvrResDir); + + String jvmOptsStr = runCtx.properties().getProperty("JVM_OPTS") != null ? + runCtx.properties().getProperty("JVM_OPTS") : + ""; + + String nodeJvmOptsProp = String.format("%s_JVM_OPTS", type); + + String nodeJvmOptsStr = runCtx.properties().getProperty(nodeJvmOptsProp) != null ? + runCtx.properties().getProperty(nodeJvmOptsProp) : + ""; + + String concJvmOpts = jvmOptsStr + " " + nodeJvmOptsStr; + + String gcJvmOpts = ""; + + // If path for GC log file is not already defined in JVM options, CG log will be directed to node log directory. + if (!concJvmOpts.contains("-Xloggc")) { + gcJvmOpts = concJvmOpts.contains("PrintGC") ? + String.format(" -Xloggc:%s/gc-%s-%s-id%s-%s-%s.log", + logDirFullName(nodeInfo), + nodeInfo.nodeStartTime(), + nodeInfo.typeLow(), + id, + host, + nodeInfo.description()) : + ""; + } + + String fullJvmOpts = (concJvmOpts + " " + gcJvmOpts).replace("\"", ""); + + String propPath = runCtx.propertyPath().replace(runCtx.localeWorkDirectory(), runCtx.remoteWorkDirectory()); + + String cfgStr = cfgFullStr.replace(runCtx.localeWorkDirectory(), runCtx.remoteWorkDirectory()); + + String servName = runCtx.serverName() != null ? runCtx.serverName() : cfg.serverName(); + + return String.format("%s -Dyardstick.%s%s -cp :%s/libs/* %s -id %s %s %s --serverName %s --warmup %s " + + "--duration %s --threads %s --config %s --logsFolder %s --remoteuser %s --currentFolder %s " + + "--scriptsFolder %s/bin", + fullJvmOpts, + nodeInfo.typeLow(), + id, + runCtx.remoteWorkDirectory(), + mainClass(type), + id, + outputFolderParam, + cfgStr, + servName, + warmup, + duration, + runCtx.threads(), + propPath, + logDirFullName(nodeInfo), + runCtx.remoteUser(), + runCtx.remoteWorkDirectory(), + runCtx.remoteWorkDirectory()); + } + + /** + * @param type Node type. + * @return Path to log directory. + */ + private String logDirFullName(NodeInfo nodeInfo) { + String path; + + NodeType type = nodeInfo.nodeType(); + + switch (type) { + case SERVER: + path = servLogDirFullName; + + break; + case DRIVER: + path = drvrLogDirFullName; + + break; + default: + throw new IllegalArgumentException("Unknown node type"); + } + + // Log directory name suffix for non PLAIN run modes. + String runModeSuf = ""; + + if (nodeInfo.runMode() != RunMode.PLAIN) + runModeSuf = String.format("_%s", nodeInfo.runMode().toString().toLowerCase()); + + return path + runModeSuf; + } + + /** + * @param type Node type + * @return Main class to start node. + */ + private String mainClass(NodeType type) { + switch (type) { + case SERVER: + return servMainCls; + case DRIVER: + return drvrMainCls; + default: + throw new IllegalArgumentException("Unknown node type"); + } + } + + /** + * @param cfgStr Config string. + * @return Benchmark configuration. + */ + private BenchmarkConfiguration parseConfigString(String cfgStr) { + cfg = new BenchmarkConfiguration(); + + String[] toNewCfg = cfgStr.split(" "); + + BenchmarkUtils.jcommander(toNewCfg, cfg, ""); + + return cfg; + } + + /** + * @return Warmup. + */ + public String warmup() { + return warmup; + } + + /** + * @param warmup New warmup. + */ + public void warmup(String warmup) { + this.warmup = warmup; + } + + /** + * @return Duration. + */ + public String duration() { + return duration; + } + + /** + * @param duration New duration. + */ + public void duration(String duration) { + this.duration = duration; + } + + /** + * + * @param list List. + * @return Dash separated string of list items. + */ + private String listToString(List list){ + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < list.size(); i++){ + sb.append(list.get(i)); + + if(i < list.size() - 1) + sb.append("-"); + } + + return sb.toString(); + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/StopNodeWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/StopNodeWorker.java new file mode 100644 index 0000000..9b40afe --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/StopNodeWorker.java @@ -0,0 +1,62 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.io.IOException; +import java.util.List; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.RunMode; +import org.yardstickframework.runners.context.RunContext; + +/** + * Terminates nodes. + */ +public class StopNodeWorker extends NodeWorker { + /** {@inheritDoc} */ + public StopNodeWorker(RunContext runCtx, List nodeList) { + super(runCtx, nodeList); + } + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + log().info(String.format("Stopping node '%s' on the host '%s'.", + nodeInfo.toShortStr(), + nodeInfo.host())); + + try { + return stopNode(nodeInfo); + } + catch (IOException e) { + log().error(String.format("Failed to stop node '%s' on the host '%s'", + nodeInfo.toShortStr(), + nodeInfo.host()), e); + } + + return nodeInfo; + } + + /** + * @param nodeInfo Node info. + * @return Node info. + * @throws IOException if failed. + * @throws InterruptedException if interrupted. + */ + public NodeInfo stopNode(NodeInfo nodeInfo) throws IOException, InterruptedException { + + nodeInfo = runCtx.handler().killNode(nodeInfo); + + return nodeInfo; + } +} diff --git a/src/main/java/org/yardstickframework/runners/workers/node/WaitNodeWorker.java b/src/main/java/org/yardstickframework/runners/workers/node/WaitNodeWorker.java new file mode 100644 index 0000000..a5c2c8b --- /dev/null +++ b/src/main/java/org/yardstickframework/runners/workers/node/WaitNodeWorker.java @@ -0,0 +1,113 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package org.yardstickframework.runners.workers.node; + +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.yardstickframework.runners.checkers.NodeChecker; +import org.yardstickframework.runners.context.NodeInfo; +import org.yardstickframework.runners.context.NodeStatus; +import org.yardstickframework.runners.context.NodeType; +import org.yardstickframework.runners.context.RunContext; +import org.yardstickframework.runners.context.RunMode; + +/** + * Class waiting for node to start or stop. + */ +public class WaitNodeWorker extends NodeWorker { + /** */ + private NodeStatus expStatus; + + /** + * Constructor. + * + * @param runCtx Run context. + * @param nodeList Main list of NodeInfo objects to work with. + * @param expStatus {@code NodeStatus} status to wait for. + */ + public WaitNodeWorker(RunContext runCtx, List nodeList, NodeStatus expStatus) { + super(runCtx, nodeList); + this.expStatus = expStatus; + } + + /** {@inheritDoc} */ + @Override public NodeInfo doWork(NodeInfo nodeInfo) throws InterruptedException { + boolean exp = false; + + NodeChecker checker = runCtx.nodeChecker(nodeInfo); + + int waitCnt = 0; + + boolean noMoreWaiting = false; + + int fullTime = (int) (Integer.valueOf(runCtx.warmup()) + Integer.valueOf(runCtx.duration())); + + double warnTime = fullTime * 1.25; + + while (!exp && !noMoreWaiting) { + checker.checkNode(nodeInfo); + + if (nodeInfo.nodeStatus() == expStatus) { + exp = true; + + noMoreWaiting = true; + } + else{ + waitCnt++; + + if (expStatus == NodeStatus.RUNNING){ + if (waitCnt > 10){ + log().error(String.format("Node '%s' is not running after %d seconds.", + nodeInfo.toShortStr(), 10)); + + noMoreWaiting = true; + } + } + else{ + if (nodeInfo.nodeType() == NodeType.DRIVER){ + if (waitCnt > warnTime && waitCnt % 30 == 0){ + log().info(String.format("Combined warmup and duration time for node '%s' is %d but " + + "node still running after %d seconds.", nodeInfo.toShortStr(), fullTime, waitCnt)); + } + } + } + + new CountDownLatch(1).await(1000L, TimeUnit.MILLISECONDS); + } + } + + String status = nodeInfo.nodeStatus().toString().toLowerCase().replace("_", " "); + + log().info(String.format("Node '%s' on the host '%s' is %s.", + nodeInfo.toShortStr(), + nodeInfo.host(), + status)); + + return nodeInfo; + } + + /** {@inheritDoc} */ + @Override public void afterWork() { + if (!nodeList().isEmpty()) { + NodeInfo nodeInfo = nodeList().get(0); + + if (nodeInfo.runMode() == RunMode.DOCKER + && expStatus == NodeStatus.NOT_RUNNING + && nodeInfo.nodeType() == NodeType.SERVER) + log().info("Keeping docker containers running."); + } + } +}