This repository has been archived by the owner on Jan 22, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
Copy pathremote-node.sh
executable file
·433 lines (385 loc) · 12.9 KB
/
remote-node.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")"/../..
set -x
deployMethod="$1"
nodeType="$2"
entrypointIp="$3"
numNodes="$4"
if [[ -n $5 ]]; then
export RUST_LOG="$5"
fi
skipSetup="$6"
failOnValidatorBootupFailure="$7"
externalPrimordialAccountsFile="$8"
maybeDisableAirdrops="$9"
internalNodesStakeLamports="${10}"
internalNodesLamports="${11}"
nodeIndex="${12}"
numBenchTpsClients="${13}"
benchTpsExtraArgs="${14}"
numBenchExchangeClients="${15}"
benchExchangeExtraArgs="${16}"
genesisOptions="${17}"
extraNodeArgs="${18}"
gpuMode="${19:-auto}"
GEOLOCATION_API_KEY="${20}"
set +x
missing() {
echo "Error: $1 not specified"
exit 1
}
[[ -n $deployMethod ]] || missing deployMethod
[[ -n $nodeType ]] || missing nodeType
[[ -n $entrypointIp ]] || missing entrypointIp
[[ -n $numNodes ]] || missing numNodes
[[ -n $skipSetup ]] || missing skipSetup
[[ -n $failOnValidatorBootupFailure ]] || missing failOnValidatorBootupFailure
airdropsEnabled=true
if [[ -n $maybeDisableAirdrops ]]; then
airdropsEnabled=false
fi
cat > deployConfig <<EOF
deployMethod="$deployMethod"
entrypointIp="$entrypointIp"
numNodes="$numNodes"
failOnValidatorBootupFailure=$failOnValidatorBootupFailure
genesisOptions="$genesisOptions"
airdropsEnabled=$airdropsEnabled
EOF
source net/common.sh
source multinode-demo/common.sh
loadConfigFile
initCompleteFile=init-complete-node.log
cat > ~/solana/on-reboot <<EOF
#!/usr/bin/env bash
cd ~/solana
source scripts/oom-score-adj.sh
now=\$(date -u +"%Y-%m-%dT%H:%M:%SZ")
ln -sfT validator.log.\$now validator.log
EOF
chmod +x ~/solana/on-reboot
GPU_CUDA_OK=false
GPU_FAIL_IF_NONE=false
case "$gpuMode" in
on) # GPU *required*, any vendor
GPU_CUDA_OK=true
GPU_FAIL_IF_NONE=true
;;
off) # CPU-only
;;
auto) # Use GPU if installed, any vendor
GPU_CUDA_OK=true
;;
cuda) # GPU *required*, CUDA-only
GPU_CUDA_OK=true
GPU_FAIL_IF_NONE=true
;;
*)
echo "Unexpected gpuMode: \"$gpuMode\""
exit 1
;;
esac
waitForNodeToInit() {
hostname=$(hostname)
echo "--- waiting for $hostname to boot up"
SECONDS=
while [[ ! -r $initCompleteFile ]]; do
if [[ $SECONDS -ge 240 ]]; then
echo "^^^ +++"
echo "Error: $initCompleteFile not found in $SECONDS seconds"
exit 1
fi
echo "Waiting for $initCompleteFile ($SECONDS) on $hostname..."
sleep 5
done
echo "$hostname booted up"
}
case $deployMethod in
local|tar|skip)
PATH="$HOME"/.cargo/bin:"$PATH"
export USE_INSTALL=1
./fetch-perf-libs.sh
cat >> ~/solana/on-reboot <<EOF
PATH="$HOME"/.cargo/bin:"$PATH"
export USE_INSTALL=1
sudo RUST_LOG=info ~solana/.cargo/bin/solana-sys-tuner --user $(whoami) > sys-tuner.log 2>&1 &
echo \$! > sys-tuner.pid
(
sudo SOLANA_METRICS_CONFIG="$SOLANA_METRICS_CONFIG" scripts/oom-monitor.sh
) > oom-monitor.log 2>&1 &
echo \$! > oom-monitor.pid
scripts/fd-monitor.sh > fd-monitor.log 2>&1 &
echo \$! > fd-monitor.pid
scripts/net-stats.sh > net-stats.log 2>&1 &
echo \$! > net-stats.pid
scripts/iftop.sh > iftop.log 2>&1 &
echo \$! > iftop.pid
scripts/system-stats.sh > system-stats.log 2>&1 &
echo \$! > system-stats.pid
if ${GPU_CUDA_OK} && [[ -e /dev/nvidia0 ]]; then
echo Selecting solana-validator-cuda
export SOLANA_CUDA=1
elif ${GPU_FAIL_IF_NONE} ; then
echo "Expected GPU, found none!"
export SOLANA_GPU_MISSING=1
fi
EOF
case $nodeType in
bootstrap-leader)
set -x
if [[ $skipSetup != true ]]; then
clear_config_dir "$SOLANA_CONFIG_DIR"
if [[ -n $internalNodesLamports ]]; then
echo "---" >> config/validator-balances.yml
fi
setupValidatorKeypair() {
declare name=$1
if [[ -f net/keypairs/"$name".json ]]; then
cp net/keypairs/"$name".json config/"$name".json
else
solana-keygen new --no-passphrase -so config/"$name".json
fi
if [[ -n $internalNodesLamports ]]; then
declare pubkey
pubkey="$(solana-keygen pubkey config/"$name".json)"
cat >> config/validator-balances.yml <<EOF
$pubkey:
balance: $internalNodesLamports
owner: 11111111111111111111111111111111
data:
executable: false
EOF
fi
}
for i in $(seq 1 "$numNodes"); do
setupValidatorKeypair validator-identity-"$i"
done
setupValidatorKeypair blockstreamer-identity
lamports_per_signature="42"
# shellcheck disable=SC2206 # Do not want to quote $genesisOptions
genesis_args=($genesisOptions)
for i in "${!genesis_args[@]}"; do
if [[ "${genesis_args[$i]}" = --target-lamports-per-signature ]]; then
lamports_per_signature="${genesis_args[$((i+1))]}"
break
fi
done
for i in $(seq 0 $((numBenchTpsClients-1))); do
# shellcheck disable=SC2086 # Do not want to quote $benchTpsExtraArgs
solana-bench-tps --write-client-keys config/bench-tps"$i".yml \
--target-lamports-per-signature "$lamports_per_signature" $benchTpsExtraArgs
# Skip first line, as it contains header
tail -n +2 -q config/bench-tps"$i".yml >> config/client-accounts.yml
echo "" >> config/client-accounts.yml
done
for i in $(seq 0 $((numBenchExchangeClients-1))); do
# shellcheck disable=SC2086 # Do not want to quote $benchExchangeExtraArgs
solana-bench-exchange --batch-size 1000 --fund-amount 20000 \
--write-client-keys config/bench-exchange"$i".yml $benchExchangeExtraArgs
tail -n +2 -q config/bench-exchange"$i".yml >> config/client-accounts.yml
echo "" >> config/client-accounts.yml
done
if [[ -f $externalPrimordialAccountsFile ]]; then
cat "$externalPrimordialAccountsFile" >> config/validator-balances.yml
fi
if [[ -f config/validator-balances.yml ]]; then
genesisOptions+=" --primordial-accounts-file config/validator-balances.yml"
fi
if [[ -f config/client-accounts.yml ]]; then
genesisOptions+=" --primordial-accounts-file config/client-accounts.yml"
fi
if [[ -n $internalNodesStakeLamports ]]; then
args+=(--bootstrap-leader-stake-lamports "$internalNodesStakeLamports")
fi
if [[ -n $internalNodesLamports ]]; then
args+=(--bootstrap-leader-lamports "$internalNodesLamports")
fi
# shellcheck disable=SC2206 # Do not want to quote $genesisOptions
args+=($genesisOptions)
if [[ -f net/keypairs/mint.json ]]; then
export FAUCET_KEYPAIR=net/keypairs/mint.json
fi
if [[ -f net/keypairs/bootstrap-leader-identity.json ]]; then
export BOOTSTRAP_LEADER_IDENTITY_KEYPAIR=net/keypairs/bootstrap-leader-identity.json
fi
multinode-demo/setup.sh "${args[@]}"
fi
args=(
--gossip-host "$entrypointIp"
--gossip-port 8001
--init-complete-file "$initCompleteFile"
)
if [[ $airdropsEnabled = true ]]; then
cat >> ~/solana/on-reboot <<EOF
./multinode-demo/faucet.sh > faucet.log 2>&1 &
EOF
fi
# shellcheck disable=SC2206 # Don't want to double quote $extraNodeArgs
args+=($extraNodeArgs)
cat >> ~/solana/on-reboot <<EOF
nohup ./multinode-demo/bootstrap-leader.sh ${args[@]} > validator.log.\$now 2>&1 &
pid=\$!
oom_score_adj "\$pid" 1000
disown
EOF
~/solana/on-reboot
waitForNodeToInit
if [[ $skipSetup != true ]]; then
solana --url http://"$entrypointIp":8899 \
--keypair ~/solana/config/bootstrap-leader/identity-keypair.json \
validator-info publish "$(hostname)" -n team/solana --force || true
fi
;;
validator|blockstreamer)
if [[ $deployMethod != skip ]]; then
net/scripts/rsync-retry.sh -vPrc "$entrypointIp":~/.cargo/bin/ ~/.cargo/bin/
net/scripts/rsync-retry.sh -vPrc "$entrypointIp":~/version.yml ~/version.yml
fi
if [[ $skipSetup != true ]]; then
clear_config_dir "$SOLANA_CONFIG_DIR"
if [[ $nodeType = blockstreamer ]]; then
net/scripts/rsync-retry.sh -vPrc \
"$entrypointIp":~/solana/config/blockstreamer-identity.json config/validator-identity.json
else
net/scripts/rsync-retry.sh -vPrc \
"$entrypointIp":~/solana/config/validator-identity-"$nodeIndex".json config/validator-identity.json
fi
fi
args=(
--entrypoint "$entrypointIp:8001"
--gossip-port 8001
--rpc-port 8899
)
if [[ $nodeType = blockstreamer ]]; then
args+=(
--blockstream /tmp/solana-blockstream.sock
--no-voting
--dev-no-sigverify
)
else
args+=(--enable-rpc-exit)
if [[ -n $internalNodesLamports ]]; then
args+=(--node-lamports "$internalNodesLamports")
fi
fi
if [[ ! -f config/validator-identity.json ]]; then
solana-keygen new --no-passphrase -so config/validator-identity.json
fi
args+=(--identity-keypair config/validator-identity.json)
if [[ $airdropsEnabled != true ]]; then
args+=(--no-airdrop)
fi
set -x
# Add the mint keypair to validators for convenient access from tools
# like bench-tps and add to blocktreamers to run a faucet
scp "$entrypointIp":~/solana/config/faucet-keypair.json config/
if [[ $nodeType = blockstreamer ]]; then
# Run another faucet with the mint keypair on the blockstreamer node.
# Typically the blockstreamer node has a static IP/DNS name for hosting
# the blockexplorer web app, and is a location that somebody would expect
# to be able to airdrop from
scp "$entrypointIp":~/solana/config/faucet-keypair.json config/
if [[ $airdropsEnabled = true ]]; then
cat >> ~/solana/on-reboot <<EOF
multinode-demo/faucet.sh > faucet.log 2>&1 &
EOF
fi
# Grab the TLS cert generated by /certbot-restore.sh
if [[ -f /.cert.pem ]]; then
sudo install -o $UID -m 400 /.cert.pem /.key.pem .
ls -l .cert.pem .key.pem
fi
cat > ~/solana/restart-explorer <<EOF
#!/bin/bash -ex
cd ~/solana
export GEOLOCATION_API_KEY=$GEOLOCATION_API_KEY
if [[ -f blockexplorer.pid ]]; then
pgid=\$(ps opgid= \$(cat blockexplorer.pid) | tr -d '[:space:]')
if [[ -n \$pgid ]]; then
kill -- -\$pgid
fi
fi
killall node || true
npm install @solana/blockexplorer@1
export BLOCKEXPLORER_GEOIP_WHITELIST=$PWD/net/config/geoip.yml
npx solana-blockexplorer > blockexplorer.log 2>&1 &
echo \$! > blockexplorer.pid
# Redirect port 80 to port 5000
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 5000 -j ACCEPT
sudo iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 5000
# Confirm the explorer is accessible
curl --head --retry 3 --retry-connrefused http://localhost:5000/
# Confirm the explorer is now globally accessible
curl --head "\$(curl ifconfig.io)"
EOF
chmod +x ~/solana/restart-explorer
cat >> ~/solana/on-reboot <<EOF
~/solana/restart-explorer
EOF
fi
args+=(--init-complete-file "$initCompleteFile")
# shellcheck disable=SC2206 # Don't want to double quote $extraNodeArgs
args+=($extraNodeArgs)
cat >> ~/solana/on-reboot <<EOF
nohup multinode-demo/validator.sh ${args[@]} > validator.log.\$now 2>&1 &
pid=\$!
oom_score_adj "\$pid" 1000
disown
EOF
~/solana/on-reboot
waitForNodeToInit
if [[ $skipSetup != true && $nodeType != blockstreamer ]]; then
# Wait for the validator to catch up to the bootstrap leader before
# delegating stake to it
solana --url http://"$entrypointIp":8899 catchup config/validator-identity.json
args=(
--url http://"$entrypointIp":8899
)
if [[ $airdropsEnabled != true ]]; then
args+=(--no-airdrop)
fi
if [[ -f config/validator-identity.json ]]; then
args+=(--keypair config/validator-identity.json)
fi
multinode-demo/delegate-stake.sh "${args[@]}" "$internalNodesStakeLamports"
fi
if [[ $skipSetup != true ]]; then
solana --url http://"$entrypointIp":8899 \
--keypair config/validator-identity.json \
validator-info publish "$(hostname)" -n team/solana --force || true
fi
;;
archiver)
if [[ $deployMethod != skip ]]; then
net/scripts/rsync-retry.sh -vPrc "$entrypointIp":~/.cargo/bin/ ~/.cargo/bin/
fi
args=(
--entrypoint "$entrypointIp:8001"
)
if [[ $airdropsEnabled != true ]]; then
# If this ever becomes a problem, we need to provide the `--identity-keypair`
# argument to an existing system account with lamports in it
echo "Error: archivers not supported without airdrops"
exit 1
fi
cat >> ~/solana/on-reboot <<EOF
nohup multinode-demo/archiver.sh ${args[@]} > validator.log.\$now 2>&1 &
pid=\$!
oom_score_adj "\$pid" 1000
disown
EOF
~/solana/on-reboot
sleep 1
;;
*)
echo "Error: unknown node type: $nodeType"
exit 1
;;
esac
;;
*)
echo "Unknown deployment method: $deployMethod"
exit 1
esac