solana/net/net.sh

455 lines
11 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
set -e
here=$(dirname "$0")
SOLANA_ROOT="$(cd "$here"/..; pwd)"
# shellcheck source=net/common.sh
source "$here"/common.sh
usage() {
exitcode=0
if [[ -n "$1" ]]; then
exitcode=1
echo "Error: $*"
fi
cat <<EOF
2018-09-04 15:16:25 -07:00
usage: $0 [start|stop|restart|sanity] [command-specific options]
2018-09-03 21:15:55 -07:00
Operate a configured testnet
2018-09-04 09:21:03 -07:00
start - Start the network
sanity - Sanity check the network
stop - Stop the network
restart - Shortcut for stop then start
2018-09-03 21:15:55 -07:00
start-specific options:
2018-11-06 15:02:55 -08:00
-S [snapFilename] - Deploy the specified Snap file
-s edge|beta|stable - Deploy the latest Snap on the specified Snap release channel
2018-11-07 13:32:48 -08:00
-T [tarFilename] - Deploy the specified release tarball
2018-11-06 15:02:55 -08:00
-t edge|beta|stable|vX.Y.Z - Deploy the latest tarball release for the
specified release channel (edge|beta|stable) or release tag
(vX.Y.Z)
-f [cargoFeatures] - List of |cargo --feaures=| to activate
(ignored if -s or -S is specified)
-r - Reuse existing node/ledger configuration from a
previous |start| (ie, don't run ./mulitnode-demo/setup.sh).
2018-09-03 21:15:55 -07:00
Note: if RUST_LOG is set in the environment it will be propogated into the
network nodes.
2018-09-04 09:21:03 -07:00
sanity/start-specific options:
2018-09-03 22:33:40 -07:00
-o noLedgerVerify - Skip ledger verification
-o noValidatorSanity - Skip fullnode sanity
-o rejectExtraNodes - Require the exact number of nodes
2018-09-03 22:33:40 -07:00
2018-09-03 21:15:55 -07:00
stop-specific options:
none
EOF
exit $exitcode
}
2018-09-03 21:15:55 -07:00
snapChannel=
releaseChannel=
2018-09-03 21:15:55 -07:00
snapFilename=
deployMethod=local
2018-09-03 22:33:40 -07:00
sanityExtraArgs=
2018-09-04 23:01:07 -07:00
cargoFeatures=
skipSetup=false
2018-09-03 21:15:55 -07:00
command=$1
[[ -n $command ]] || usage
shift
while getopts "h?S:s:T:t:o:f:r" opt; do
case $opt in
h | \?)
usage
;;
2018-09-03 21:15:55 -07:00
S)
snapFilename=$OPTARG
[[ -f $snapFilename ]] || usage "Snap not readable: $snapFilename"
deployMethod=snap
;;
s)
case $OPTARG in
edge|beta|stable)
snapChannel=$OPTARG
2018-09-04 09:21:03 -07:00
deployMethod=snap
2018-09-03 21:15:55 -07:00
;;
*)
usage "Invalid snap channel: $OPTARG"
;;
esac
;;
2018-11-07 13:32:48 -08:00
T)
tarballFilename=$OPTARG
[[ -f $tarballFilename ]] || usage "Snap not readable: $tarballFilename"
deployMethod=tar
;;
t)
case $OPTARG in
2018-11-06 15:02:55 -08:00
edge|beta|stable|v*)
releaseChannel=$OPTARG
deployMethod=tar
;;
*)
usage "Invalid release channel: $OPTARG"
;;
esac
;;
2018-09-04 23:01:07 -07:00
f)
cargoFeatures=$OPTARG
;;
r)
skipSetup=true
;;
2018-09-03 22:33:40 -07:00
o)
case $OPTARG in
noLedgerVerify|noValidatorSanity|rejectExtraNodes)
2018-09-03 22:33:40 -07:00
sanityExtraArgs="$sanityExtraArgs -o $OPTARG"
;;
*)
echo "Error: unknown option: $OPTARG"
exit 1
;;
esac
;;
*)
usage "Error: unhandled option: $opt"
;;
esac
done
loadConfigFile
build() {
declare MAYBE_DOCKER=
if [[ $(uname) != Linux ]]; then
MAYBE_DOCKER="ci/docker-run.sh solanalabs/rust"
fi
SECONDS=0
(
cd "$SOLANA_ROOT"
2018-09-04 09:21:03 -07:00
echo "--- Build started at $(date)"
set -x
rm -rf farf
2018-11-14 19:19:27 -08:00
if [[ -r target/perf-libs/env.sh ]]; then
# shellcheck source=/dev/null
source target/perf-libs/env.sh
fi
2018-11-16 08:04:46 -08:00
$MAYBE_DOCKER bash -c "
set -ex
export NDEBUG=1
2018-11-16 08:04:46 -08:00
cargo install --path drone --features=$cargoFeatures --root farf
cargo install --path . --features=$cargoFeatures --root farf
2018-12-08 19:04:54 -08:00
mkdir -p farf/bin/deps/
./scripts/install-native-programs.sh farf/bin/deps/ release
2018-11-16 08:04:46 -08:00
"
)
echo "Build took $SECONDS seconds"
}
2018-09-07 08:49:22 -07:00
startCommon() {
declare ipAddress=$1
2018-09-04 15:16:25 -07:00
test -d "$SOLANA_ROOT"
ssh "${sshOptions[@]}" "$ipAddress" "mkdir -p ~/solana ~/.cargo/bin; rm -rf ~/solana/"
2018-09-04 15:16:25 -07:00
rsync -vPrc -e "ssh ${sshOptions[*]}" \
"$SOLANA_ROOT"/{fetch-perf-libs.sh,scripts,net,multinode-demo} \
"$ipAddress":~/solana/
}
startBootstrapLeader() {
declare ipAddress=$1
declare logFile="$2"
echo "--- Starting bootstrap leader: $ipAddress"
2018-09-08 13:48:17 -07:00
echo "start log: $logFile"
# Deploy local binaries to bootstrap fullnode. Other fullnodes and clients later fetch the
# binaries from it
(
set -x
2018-09-07 08:49:22 -07:00
startCommon "$ipAddress" || exit 1
2018-09-03 21:15:55 -07:00
case $deployMethod in
snap)
2018-09-04 15:16:25 -07:00
rsync -vPrc -e "ssh ${sshOptions[*]}" "$snapFilename" "$ipAddress:~/solana/solana.snap"
2018-09-03 21:15:55 -07:00
;;
tar)
rsync -vPrc -e "ssh ${sshOptions[*]}" "$SOLANA_ROOT"/solana-release/bin/* "$ipAddress:~/.cargo/bin/"
;;
2018-09-03 21:15:55 -07:00
local)
2018-09-04 15:16:25 -07:00
rsync -vPrc -e "ssh ${sshOptions[*]}" "$SOLANA_ROOT"/farf/bin/* "$ipAddress:~/.cargo/bin/"
2018-09-03 21:15:55 -07:00
;;
*)
usage "Internal error: invalid deployMethod: $deployMethod"
;;
esac
2018-09-04 09:21:03 -07:00
ssh "${sshOptions[@]}" -n "$ipAddress" \
"./solana/net/remote/remote-node.sh \
$deployMethod \
bootstrap-leader \
$publicNetwork \
$entrypointIp \
${#fullnodeIpList[@]} \
\"$RUST_LOG\" \
$skipSetup \
2018-12-05 17:33:32 -08:00
$leaderRotation \
"
2018-09-04 15:16:25 -07:00
) >> "$logFile" 2>&1 || {
cat "$logFile"
echo "^^^ +++"
exit 1
}
}
startNode() {
declare ipAddress=$1
declare logFile="$netLogDir/fullnode-$ipAddress.log"
echo "--- Starting fullnode: $ipAddress"
2018-09-08 13:48:17 -07:00
echo "start log: $logFile"
(
set -x
2018-09-07 08:49:22 -07:00
startCommon "$ipAddress"
2018-09-04 09:21:03 -07:00
ssh "${sshOptions[@]}" -n "$ipAddress" \
"./solana/net/remote/remote-node.sh \
$deployMethod \
fullnode \
$publicNetwork \
$entrypointIp \
${#fullnodeIpList[@]} \
\"$RUST_LOG\" \
$skipSetup \
2018-12-05 17:33:32 -08:00
$leaderRotation \
"
2018-09-08 13:48:17 -07:00
) >> "$logFile" 2>&1 &
2018-09-04 09:21:03 -07:00
declare pid=$!
ln -sfT "fullnode-$ipAddress.log" "$netLogDir/fullnode-$pid.log"
2018-09-04 09:21:03 -07:00
pids+=("$pid")
}
startClient() {
declare ipAddress=$1
declare logFile="$2"
2018-09-04 15:16:25 -07:00
echo "--- Starting client: $ipAddress"
2018-09-08 13:48:17 -07:00
echo "start log: $logFile"
2018-09-03 22:33:40 -07:00
(
set -x
2018-09-07 08:49:22 -07:00
startCommon "$ipAddress"
2018-09-03 22:33:40 -07:00
ssh "${sshOptions[@]}" -f "$ipAddress" \
"./solana/net/remote/remote-client.sh $deployMethod $entrypointIp \"$RUST_LOG\""
2018-09-04 15:16:25 -07:00
) >> "$logFile" 2>&1 || {
cat "$logFile"
echo "^^^ +++"
exit 1
}
}
2018-09-03 22:33:40 -07:00
sanity() {
2018-09-06 13:00:01 -07:00
declare ok=true
2018-09-04 09:21:03 -07:00
echo "--- Sanity"
2018-09-06 13:00:01 -07:00
$metricsWriteDatapoint "testnet-deploy net-sanity-begin=1"
declare host=${fullnodeIpList[0]}
2018-09-03 22:33:40 -07:00
(
set -x
2018-09-04 14:36:35 -07:00
# shellcheck disable=SC2029 # remote-client.sh args are expanded on client side intentionally
2018-11-05 08:30:10 -08:00
ssh "${sshOptions[@]}" "$host" \
2018-09-04 14:36:35 -07:00
"./solana/net/remote/remote-sanity.sh $sanityExtraArgs"
2018-09-06 13:00:01 -07:00
) || ok=false
$metricsWriteDatapoint "testnet-deploy net-sanity-complete=1"
$ok || exit 1
2018-09-03 22:33:40 -07:00
}
2018-09-03 21:15:55 -07:00
2018-09-03 22:33:40 -07:00
start() {
2018-09-03 21:15:55 -07:00
case $deployMethod in
snap)
if [[ -n $snapChannel ]]; then
2018-09-04 09:21:03 -07:00
rm -f "$SOLANA_ROOT"/solana_*.snap
2018-09-03 21:15:55 -07:00
if [[ $(uname) != Linux ]]; then
2018-09-04 09:21:03 -07:00
(
set -x
SOLANA_DOCKER_RUN_NOSETUID=1 "$SOLANA_ROOT"/ci/docker-run.sh ubuntu:18.04 bash -c "
set -ex;
apt-get -qq update;
apt-get -qq -y install snapd;
2018-11-02 17:29:13 -07:00
until snap download --channel=$snapChannel solana; do
sleep 1;
done
2018-09-04 09:21:03 -07:00
"
)
else
(
cd "$SOLANA_ROOT"
2018-11-02 17:29:13 -07:00
until snap download --channel="$snapChannel" solana; do
sleep 1
done
)
2018-09-03 21:15:55 -07:00
fi
2018-09-04 09:21:03 -07:00
snapFilename="$(echo "$SOLANA_ROOT"/solana_*.snap)"
[[ -r $snapFilename ]] || {
echo "Error: Snap not readable: $snapFilename"
exit 1
}
2018-09-03 21:15:55 -07:00
fi
;;
tar)
if [[ -n $releaseChannel ]]; then
rm -f "$SOLANA_ROOT"/solana-release.tar.bz2
(
set -x
curl -o "$SOLANA_ROOT"/solana-release.tar.bz2 http://solana-release.s3.amazonaws.com/"$releaseChannel"/solana-release.tar.bz2
)
tarballFilename="$SOLANA_ROOT"/solana-release.tar.bz2
fi
(
set -x
rm -rf "$SOLANA_ROOT"/solana-release
(cd "$SOLANA_ROOT"; tar jxv) < "$tarballFilename"
cat "$SOLANA_ROOT"/solana-release/version.txt
)
;;
2018-09-03 21:15:55 -07:00
local)
build
;;
*)
usage "Internal error: invalid deployMethod: $deployMethod"
;;
esac
echo "Deployment started at $(date)"
2018-09-06 13:00:01 -07:00
$metricsWriteDatapoint "testnet-deploy net-start-begin=1"
bootstrapLeader=true
for ipAddress in "${fullnodeIpList[@]}"; do
if $bootstrapLeader; then
SECONDS=0
declare bootstrapNodeDeployTime=
startBootstrapLeader "$ipAddress" "$netLogDir/bootstrap-leader-$ipAddress.log"
bootstrapNodeDeployTime=$SECONDS
$metricsWriteDatapoint "testnet-deploy net-bootnode-leader-started=1"
bootstrapLeader=false
SECONDS=0
pids=()
loopCount=0
else
startNode "$ipAddress"
# Stagger additional node start time. If too many nodes start simultaneously
# the bootstrap node gets more rsync requests from the additional nodes than
# it can handle.
((loopCount++ % 2 == 0)) && sleep 2
fi
2018-09-04 09:21:03 -07:00
done
for pid in "${pids[@]}"; do
declare ok=true
wait "$pid" || ok=false
if ! $ok; then
cat "$netLogDir/fullnode-$pid.log"
2018-09-04 09:21:03 -07:00
echo ^^^ +++
exit 1
fi
done
2018-09-04 09:21:03 -07:00
$metricsWriteDatapoint "testnet-deploy net-fullnodes-started=1"
additionalNodeDeployTime=$SECONDS
2018-09-03 22:33:40 -07:00
sanity
2018-09-03 21:15:55 -07:00
SECONDS=0
for ipAddress in "${clientIpList[@]}"; do
startClient "$ipAddress" "$netLogDir/client-$ipAddress.log"
done
clientDeployTime=$SECONDS
2018-09-06 13:00:01 -07:00
$metricsWriteDatapoint "testnet-deploy net-start-complete=1"
declare networkVersion=unknown
case $deployMethod in
snap)
2018-09-03 21:15:55 -07:00
IFS=\ read -r _ networkVersion _ < <(
ssh "${sshOptions[@]}" "${fullnodeIpList[0]}" \
2018-09-03 21:15:55 -07:00
"snap info solana | grep \"^installed:\""
)
networkVersion=${networkVersion/0+git./}
;;
tar)
networkVersion="$(
tail -n1 "$SOLANA_ROOT"/solana-release/version.txt || echo "tar-unknown"
)"
;;
local)
networkVersion="$(git rev-parse HEAD || echo local-unknown)"
;;
*)
usage "Internal error: invalid deployMethod: $deployMethod"
;;
esac
$metricsWriteDatapoint "testnet-deploy version=\"${networkVersion:0:9}\""
2018-09-03 21:15:55 -07:00
echo
2018-09-08 14:12:32 -07:00
echo "+++ Deployment Successful"
echo "Bootstrap leader deployment took $bootstrapNodeDeployTime seconds"
echo "Additional fullnode deployment (${#fullnodeIpList[@]} instances) took $additionalNodeDeployTime seconds"
echo "Client deployment (${#clientIpList[@]} instances) took $clientDeployTime seconds"
echo "Network start logs in $netLogDir:"
ls -l "$netLogDir"
}
2018-09-07 08:49:22 -07:00
stopNode() {
local ipAddress=$1
2018-09-04 09:21:03 -07:00
echo "--- Stopping node: $ipAddress"
(
set -x
ssh "${sshOptions[@]}" "$ipAddress" "
2018-09-07 08:34:42 -07:00
set -x
2018-09-03 21:15:55 -07:00
if snap list solana; then
2018-09-07 08:34:42 -07:00
sudo snap set solana mode=
fi
! tmux list-sessions || tmux kill-session
for pattern in solana- remote- oom-monitor net-stats; do
2018-09-07 08:34:42 -07:00
pkill -9 \$pattern
done
"
) || true
}
stop() {
SECONDS=0
2018-09-06 13:00:01 -07:00
$metricsWriteDatapoint "testnet-deploy net-stop-begin=1"
2018-09-03 21:15:55 -07:00
for ipAddress in "${fullnodeIpList[@]}" "${clientIpList[@]}"; do
2018-09-07 08:49:22 -07:00
stopNode "$ipAddress"
done
2018-09-06 13:00:01 -07:00
$metricsWriteDatapoint "testnet-deploy net-stop-complete=1"
echo "Stopping nodes took $SECONDS seconds"
}
2018-09-03 22:33:40 -07:00
case $command in
2018-09-04 09:21:03 -07:00
restart)
2018-09-03 22:33:40 -07:00
stop
start
;;
2018-09-04 09:21:03 -07:00
start)
start
;;
2018-09-03 22:33:40 -07:00
sanity)
sanity
;;
stop)
stop
;;
*)
echo "Internal error: Unknown command: $command"
exit 1
esac