#!/usr/bin/env bash set -e here=$(dirname "$0") # shellcheck source=net/common.sh source "$here"/common.sh cloudProvider=$(basename "$0" .sh) bootDiskType="" case $cloudProvider in gce) # shellcheck source=net/scripts/gce-provider.sh source "$here"/scripts/gce-provider.sh cpuBootstrapLeaderMachineType="--machine-type n1-standard-16 --min-cpu-platform Intel%20Skylake" gpuBootstrapLeaderMachineType="$cpuBootstrapLeaderMachineType --accelerator count=1,type=nvidia-tesla-p100" bootstrapLeaderMachineType=$cpuBootstrapLeaderMachineType fullNodeMachineType=$cpuBootstrapLeaderMachineType clientMachineType="--custom-cpu 16 --custom-memory 20GB" blockstreamerMachineType="--machine-type n1-standard-8" replicatorMachineType="--custom-cpu 4 --custom-memory 16GB" ;; ec2) # shellcheck source=net/scripts/ec2-provider.sh source "$here"/scripts/ec2-provider.sh cpuBootstrapLeaderMachineType=c5.2xlarge # NOTE: At this time only the p3dn.24xlarge EC2 instance type has GPU and # AVX-512 support. The default, p2.xlarge, does not support # AVX-512 gpuBootstrapLeaderMachineType=p2.xlarge bootstrapLeaderMachineType=$cpuBootstrapLeaderMachineType fullNodeMachineType=$cpuBootstrapLeaderMachineType clientMachineType=c5.2xlarge blockstreamerMachineType=c5.2xlarge replicatorMachineType=c5.xlarge ;; azure) # shellcheck source=net/scripts/azure-provider.sh source "$here"/scripts/azure-provider.sh # TODO: Dial in machine types for Azure cpuBootstrapLeaderMachineType=Standard_D16s_v3 gpuBootstrapLeaderMachineType=Standard_NC12 bootstrapLeaderMachineType=$cpuBootstrapLeaderMachineType fullNodeMachineType=$cpuBootstrapLeaderMachineType clientMachineType=Standard_D16s_v3 blockstreamerMachineType=Standard_D16s_v3 replicatorMachineType=Standard_D4s_v3 ;; *) echo "Error: Unknown cloud provider: $cloudProvider" ;; esac prefix=testnet-dev-${USER//[^A-Za-z0-9]/} additionalFullNodeCount=2 clientNodeCount=1 replicatorNodeCount=0 blockstreamer=false fullNodeBootDiskSizeInGb=1000 clientBootDiskSizeInGb=75 replicatorBootDiskSizeInGb=1000 externalNodes=false failOnValidatorBootupFailure=true publicNetwork=false letsEncryptDomainName= enableGpu=false customAddress= zones=() containsZone() { local e match="$1" shift for e; do [[ "$e" == "$match" ]] && return 0; done return 1 } usage() { exitcode=0 if [[ -n "$1" ]]; then exitcode=1 echo "Error: $*" fi cat <> "$configFile" else rm -f "$geoipConfigFile" cat >> "$configFile" <> "$configFile" declare latlng= latlng=$(zoneLocation "$zone") if [[ -n $latlng ]]; then echo "$publicIp: $latlng" >> "$geoipConfigFile" fi fi } if $externalNodes; then echo "Bootstrap leader is already configured" else echo "Looking for bootstrap leader instance..." cloud_FindInstance "$prefix-bootstrap-leader" [[ ${#instances[@]} -eq 1 ]] || { echo "Unable to find bootstrap leader" exit 1 } echo "fullnodeIpList=()" >> "$configFile" echo "fullnodeIpListPrivate=()" >> "$configFile" cloud_ForEachInstance recordInstanceIp true fullnodeIpList fi if [[ $additionalFullNodeCount -gt 0 ]]; then for zone in "${zones[@]}"; do echo "Looking for additional fullnode instances in $zone ..." cloud_FindInstances "$prefix-$zone-fullnode" if [[ ${#instances[@]} -gt 0 ]]; then cloud_ForEachInstance recordInstanceIp "$failOnValidatorBootupFailure" fullnodeIpList else echo "Unable to find additional fullnodes" if $failOnValidatorBootupFailure; then exit 1 fi fi done fi if ! $externalNodes; then echo "clientIpList=()" >> "$configFile" echo "clientIpListPrivate=()" >> "$configFile" fi echo "Looking for client bencher instances..." cloud_FindInstances "$prefix-client" [[ ${#instances[@]} -eq 0 ]] || { cloud_ForEachInstance recordInstanceIp true clientIpList } if ! $externalNodes; then echo "blockstreamerIpList=()" >> "$configFile" echo "blockstreamerIpListPrivate=()" >> "$configFile" fi echo "Looking for blockstreamer instances..." cloud_FindInstances "$prefix-blockstreamer" [[ ${#instances[@]} -eq 0 ]] || { cloud_ForEachInstance recordInstanceIp true blockstreamerIpList } if ! $externalNodes; then echo "replicatorIpList=()" >> "$configFile" echo "replicatorIpListPrivate=()" >> "$configFile" fi echo "Looking for replicator instances..." cloud_FindInstances "$prefix-replicator" [[ ${#instances[@]} -eq 0 ]] || { cloud_ForEachInstance recordInstanceIp true replicatorIpList } echo "Wrote $configFile" $metricsWriteDatapoint "testnet-deploy net-config-complete=1" } delete() { $metricsWriteDatapoint "testnet-deploy net-delete-begin=1" # Filter for all nodes filter="$prefix-" echo "Searching for instances: $filter" cloud_FindInstances "$filter" if [[ ${#instances[@]} -eq 0 ]]; then echo "No instances found matching '$filter'" else cloud_DeleteInstances true & fi wait if $externalNodes; then echo "Let's not delete the current configuration file" else rm -f "$configFile" fi $metricsWriteDatapoint "testnet-deploy net-delete-complete=1" } case $command in delete) delete ;; create) [[ -n $additionalFullNodeCount ]] || usage "Need number of nodes" delete $metricsWriteDatapoint "testnet-deploy net-create-begin=1" rm -rf "$sshPrivateKey"{,.pub} # Note: using rsa because |aws ec2 import-key-pair| seems to fail for ecdsa ssh-keygen -t rsa -N '' -f "$sshPrivateKey" printNetworkInfo() { cat < "$startupScript" < /etc/motd < /solana-id_ecdsa < /solana-id_ecdsa.pub < /etc/motd <= 0; i--)); do zone=${zones[i]} if [[ $i -eq 0 ]]; then numNodesPerZone=$((numNodesPerZone + numLeftOverNodes)) fi cloud_CreateInstances "$prefix" "$prefix-$zone-fullnode" "$numNodesPerZone" \ "$enableGpu" "$fullNodeMachineType" "$zone" "$fullNodeBootDiskSizeInGb" \ "$startupScript" "" "$bootDiskType" & done wait fi if [[ $clientNodeCount -gt 0 ]]; then cloud_CreateInstances "$prefix" "$prefix-client" "$clientNodeCount" \ "$enableGpu" "$clientMachineType" "${zones[0]}" "$clientBootDiskSizeInGb" \ "$startupScript" "" "$bootDiskType" fi if $blockstreamer; then cloud_CreateInstances "$prefix" "$prefix-blockstreamer" "1" \ "$enableGpu" "$blockstreamerMachineType" "${zones[0]}" "$fullNodeBootDiskSizeInGb" \ "$startupScript" "$blockstreamerAddress" "$bootDiskType" fi if [[ $replicatorNodeCount -gt 0 ]]; then cloud_CreateInstances "$prefix" "$prefix-replicator" "$replicatorNodeCount" \ false "$replicatorMachineType" "${zones[0]}" "$replicatorBootDiskSizeInGb" \ "$startupScript" "" "" fi $metricsWriteDatapoint "testnet-deploy net-create-complete=1" prepareInstancesAndWriteConfigFile ;; config) prepareInstancesAndWriteConfigFile ;; info) loadConfigFile printNode() { declare nodeType=$1 declare ip=$2 declare ipPrivate=$3 declare zone=$4 printf " %-16s | %-15s | %-15s | %s\n" "$nodeType" "$ip" "$ipPrivate" "$zone" } printNode "Node Type" "Public IP" "Private IP" "Zone" echo "-------------------+-----------------+-----------------+--------------" nodeType=bootstrap-leader for i in $(seq 0 $(( ${#fullnodeIpList[@]} - 1)) ); do ipAddress=${fullnodeIpList[$i]} ipAddressPrivate=${fullnodeIpListPrivate[$i]} zone=${fullnodeIpListZone[$i]} printNode $nodeType "$ipAddress" "$ipAddressPrivate" "$zone" nodeType=fullnode done for i in $(seq 0 $(( ${#clientIpList[@]} - 1)) ); do ipAddress=${clientIpList[$i]} ipAddressPrivate=${clientIpListPrivate[$i]} zone=${clientIpListZone[$i]} printNode client "$ipAddress" "$ipAddressPrivate" "$zone" done for i in $(seq 0 $(( ${#blockstreamerIpList[@]} - 1)) ); do ipAddress=${blockstreamerIpList[$i]} ipAddressPrivate=${blockstreamerIpListPrivate[$i]} zone=${blockstreamerIpListZone[$i]} printNode blockstreamer "$ipAddress" "$ipAddressPrivate" "$zone" done for i in $(seq 0 $(( ${#replicatorIpList[@]} - 1)) ); do ipAddress=${replicatorIpList[$i]} ipAddressPrivate=${replicatorIpListPrivate[$i]} zone=${replicatorIpListZone[$i]} printNode replicator "$ipAddress" "$ipAddressPrivate" "$zone" done ;; *) usage "Unknown command: $command" esac