blob: 668f46bd7cd9c9544c800e56156d0c2e7f48f443 (
plain) (
tree)
|
|
#!/bin/bash
proj_server_bin="hotstuff-app"
proj_server_path="/home/ted/hot-stuff/$proj_server_bin"
proj_conf_name="hotstuff.conf"
peer_list="./nodes.txt" # the list of nodes
conf_src="./hotstuff.gen.conf"
server_map="./server_map.txt" # optional mapping from node ip to server ip
template_dir="template" # the dir that keeps the content shared among all nodes
remote_base="/home/ted/testbed" # remote dir used to keep files for the experiment
#remote_base="/tmp/" # remote dir used to keep files for the experiment
remote_log="log" # log filename
remote_user="ted"
copy_to_remote_pat="rsync -avz <local_path> <remote_user>@<remote_ip>:<remote_path>"
copy_from_remote_pat="rsync -avz <remote_user>@<remote_ip>:<remote_path> <local_path>"
exe_remote_pat="ssh <remote_user>@<remote_ip> bash"
run_remote_pat="cd \"<rworkdir>\"; gdb -ex r -ex bt -ex generate-core-file -ex q --args '$proj_server_path' --conf \"hotstuff.gen-sec<node_id>.conf\""
reset_remote_pat="pgrep -f '$proj_server_bin' | xargs kill -9"
fin_keyword="error:" # the keyword indicating completion of execution
fin_chk_period=1
fin_chk_skip_pat='^([A-O][0-9]*)|(_ctl)$'
force_peer_list=0
function join { local IFS="$1"; shift; echo "$*"; }
function split {
local IFS="$1"
local arr=($2)
echo "${arr[@]}"
}
function die { echo "$1"; exit 1; }
declare -A nodes
declare -A node_confs
nodes_cnt=0
function get_node_info {
pl="$1"
if [[ "$force_peer_list" == 1 ]]; then
pl="$peer_list"
fi
OIFS="$IFS"
IFS=$'\n'
node_list=($(cat "$pl"))
IFS="$OIFS"
for tuple in "${node_list[@]}"; do
tup0=($(split $'\t' "$tuple"))
tup=($(split : "${tup0[0]}"))
nodes[${tup[0]}]="${tup[1]}:${tup[2]}"
node_confs[${tup[0]}]="${tup0[@]:1}"
echo "${tup[0]} => ${nodes[${tup[0]}]} & ${node_confs[${tup[0]}]}"
let nodes_cnt++
done
}
declare -A server_map
function get_server_map {
{
IFS=$'\n'
map_list=($(cat "$1"))
}
IFS=$'\n \t'
for pair in "${map_list[@]}"; do
p=($pair)
server_map[${p[0]}]="${p[1]}"
echo "mapping ${p[0]} => ${p[1]}"
done
}
function get_addr {
tup=($(split ';' $1))
echo "${tup[0]}"
}
function get_ip {
tup=($(split : $1))
echo "${tup[0]}"
}
function get_peer_port {
tup=($(split : $1))
tup2=($(split ';' ${tup[1]}))
echo "${tup2[0]}"
}
function get_client_port {
tup=($(split : $1))
tup2=($(split ';' ${tup[1]}))
echo "${tup2[1]}"
}
function get_ip_by_id {
get_ip "${nodes[$1]}"
}
function get_peer_port_by_id {
get_peer_port "${nodes[$1]}"
}
function get_client_port_by_id {
get_client_port "${nodes[$1]}"
}
function copy_file {
local pat="$1"
local cmd="${pat//<local_path>/$2}"
cmd="${cmd//<remote_ip>/$3}"
cmd="${cmd//<remote_user>/$remote_user}"
cmd="${cmd//<remote_path>/$4}"
echo $cmd
eval "$cmd"
} >> log 2>&1
function execute_remote_cmd_pid {
local node_ip="$1"
local c="$2"
local l="$3"
local cmd="${exe_remote_pat//<remote_ip>/$node_ip}"
cmd="${cmd//<remote_user>/$remote_user}"
eval $cmd << EOF
$c > $l 2>&1 & echo \$!
EOF
}
function execute_remote_cmd_stat {
local node_ip="$1"
local c="$2"
local l="$3"
local cmd="${exe_remote_pat//<remote_ip>/$node_ip}"
cmd="${cmd//<remote_user>/$remote_user}"
eval $cmd << EOF
$c > $l 2>&1 ; echo \$?
EOF
}
function _remote_load {
local workdir="$1"
local rworkdir="$2"
local node_ip="$3"
local rid="$4"
local extra_conf=($5)
local tmpldir="$workdir/$template_dir/"
local node_tmpldir="$workdir/$rid"
[[ $(execute_remote_cmd_stat "$node_ip" \
"mkdir -p \"$rworkdir\"" \
/dev/null) == 0 ]] || die "failed to create directory $rworkdir"
copy_file "$copy_to_remote_pat" "$tmpldir" "$node_ip" "$rworkdir"
for conf in "${extra_conf[@]}"; do
copy_file "$copy_to_remote_pat" "$node_tmpldir/$conf" "$node_ip" "$rworkdir"
done
}
function _remote_start {
local workdir="$1"
local rworkdir="$2"
local node_id="$3"
local node_ip="$4"
local client_port="$5"
local cmd="${run_remote_pat//<rworkdir>/$rworkdir}"
cmd="${cmd//<node_id>/$node_id}"
cmd="${cmd//<cport>/$client_port}"
execute_remote_cmd_pid "$node_ip" "$cmd" \
"\"$rworkdir/$remote_log\"" > "$workdir/${node_id}.pid"
}
function _remote_exec {
local workdir="$1"
local rworkdir="$2"
local node_ip="$3"
local cmd="$4"
[[ $(execute_remote_cmd_stat "$node_ip" "$cmd" /dev/null) == 0 ]]
}
function _remote_stop {
local node_pid="$4"
_remote_exec "$1" "$2" "$3" "kill $node_pid"
}
function _remote_status {
local node_pid="$4"
_remote_exec "$1" "$2" "$3" "kill -0 $node_pid"
}
function _remote_finished {
_remote_exec "$1" "$2" "$3" "grep \"$fin_keyword\" \"$rworkdir/$remote_log\""
}
function _remote_fetch {
local workdir="$1"
local rworkdir="$2"
local node_id="$3"
local node_ip="$4"
copy_file "$copy_from_remote_pat" "$workdir/${node_id}.log" "$node_ip" "$rworkdir/$remote_log"
}
function start_all {
local workdir="$1"
local tmpldir="$workdir/$template_dir/"
mkdir "$workdir" > /dev/null 2>&1 || die "workdir already exists"
rm -rf "$tmpldir"
mkdir "$tmpldir"
cp "$peer_list" "$workdir/peer_list.txt"
cp "$server_map" "$workdir/server_map.txt"
get_node_info "$workdir/peer_list.txt"
get_server_map "$workdir/server_map.txt"
echo "copying configuration file"
rsync -avP "$conf_src" "$tmpldir/$proj_conf_name"
for rid in "${!nodes[@]}"; do
local node_tmpldir="$workdir/$rid"
local ip="$(get_ip_by_id $rid)"
ip="${server_map[$ip]:-$ip}"
local pport="$(get_peer_port_by_id $rid)"
local cport="$(get_client_port_by_id $rid)"
local rworkdir="$remote_base/$workdir/${rid}"
local
|