Initial version

This commit is contained in:
David Boreham 2024-07-08 06:22:16 -06:00
parent eb98a946c4
commit ff5ba970b1
10 changed files with 401 additions and 0 deletions

View File

@ -1,2 +1,95 @@
# laconicd-network-deployment
A set of scripts to drive the mainnet-laconic stack stack orchestrator commands.
## Background
The mainnet-laconic stack implements a scheme for deploying multi-node networks where each node runs an instance of the stack.
The configuration of these nodes is done via a "network directory" created on each node, and by arranging to copy a genesis
transaction file from each node to a coordinating node that generates a chain genesis file. This file in turn is copied
to the remaining nodes before stack startup. In addition, the IP addresses of all peer nodes need to be configured in
each node. This scheme is implemented with the following stack orchestrator commands:
```
$ laconic-so --stack mainnet-laconic deploy setup --network-dir <network_dir> --initialize-network --chain-id <chain_id> --node-moniker <node_name>
$ laconic-so --stack mainnet-laconic deploy setup --network-dir <network_dir> --join-network --key-name <key_name>
$ laconic-so --stack mainnet-laconic deploy setup --network-dir <network_dir> --create-network --gentx-files <gentx_files>
$ laconic-so --stack mainnet-laconic deploy init --map-ports-to-host any-same --output <spec_file_name> --config "LACONIC_HOSTED_ENDPOINT=http://$<node_dns_name>:9473"
$ laconic-so --stack mainnet-laconic deploy create --deployment-dir <deployment_dir> --spec-file <spec_file_name> --network-dir <network_dir> --initial-peers <peers>
```
The scripts in this repository provide a convenient wrapper around these commands for the testnet use case
where there can be some level of coordination and common ownership between the nodes.
## Machine setup
The scripts assume a set of machines with dns host names assigned with the pattern <machine-name-prefix>-<node-number>.<machine-domain>, e.g.
testnet-a-1.testnets.servesthe.world
Testnet machines must be setup with stack orchestrator and docker installed.
The local machine (where the scripts are run) needs to be configured with `ssh-agent` and the relevant key added, such that ssh commands to connect to the testnet machines succeed without user interaction.
## Testnet deployment steps
```
$ cd scripts
```
In the example commands below we assume the machine-name-prefix "testnet-a".
### network.cfg
The scripts load a set of configuration variables from a file named `network.cfg`. An example file is provided, edit to suit:
```
$ cat network.cfg
machine_domain=testnets.servesthe.world
node_count=4
ssh_user=laconic
```
### Pull stack images
Run the 00-pull-stack-images.sh script to pull stack container images from a container registry:
```
$ ./01-pull-stack-images.sh testnet-a <image-registry-user> <image-registry-token>
```
### Initialize network directories
```
$ ./02-init-network-dirs.sh testnet-a
```
### Merge genesis files
```
$ ./03-merge-genesis-txns.sh testnet-a
```
Copy the peer list this script displays for use in the next step.
### Create deployments
```
$ ./04-create-deployments.sh testnet-a <peers-list>
```
### Start stacks
```
$ ./deployment-command testnet-a start
```
### Check testnet status
```
$ ./deployment-command testnet-a status
$ ./deployment-command testnet-a logs
```
The laconic console should be available on all nodes at http://<node-host-name>

32
scripts/01-pull-stack-images.sh Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Pull stack images for mainnet-laconic
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source ${SCRIPT_DIR}/lib.sh
usage="Usage: $0 <machine-name-prefix> <image-registry-user> <image-registry-token>"
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo ${usage}
exit 1
fi
if [[ -n "$2" ]]; then
image_registry_user=$2
else
echo ${usage}
exit 1
fi
if [[ -n "$3" ]]; then
image_registry_token=$3
else
echo ${usage}
exit 1
fi
registry_info="--image-registry git.vdb.to/cerc-io --registry-username ${image_registry_user} --registry-token ${image_registry_token}"
fetch_command="${so_command} --stack mainnet-laconic fetch-containers ${registry_info} --force-local-overwrite"
run_on_all_nodes ${machine_name_prefix} "${fetch_command}"

28
scripts/02-init-network-dirs.sh Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo "Usage: $0 <machine-name-prefix>"
exit 1
fi
machine_domain=borgboxes.network
node_count=4
node_network_dir=testnet-dir
chain_id=laconic_81337-6
echo "Initializing network dirs on all nodes"
for (( i=1 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}
node_host_name=${node_name}.${machine_domain}
echo "Running initialize-network ${node_network_dir} on ${node_host_name}"
ssh laconic@${node_host_name} /home/laconic/bin/laconic-so --stack mainnet-laconic deploy setup --network-dir ${node_network_dir} --initialize-network --chain-id ${chain_id} --node-moniker ${node_name}
echo "Running join-network ${node_network_dir} on ${node_host_name}"
ssh laconic@${node_host_name} /home/laconic/bin/laconic-so --stack mainnet-laconic deploy setup --network-dir ${node_network_dir} --join-network --key-name ${node_name}
done

View File

@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo "Usage: $0 <machine-name-prefix>"
exit 1
fi
machine_domain=borgboxes.network
node_count=4
node_network_dir=testnet-dir
chain_id=laconic_81337-6a
p2p_port="26656"
so_command=/home/laconic/bin/laconic-so
gentx_dir=${node_network_dir}/config/gentx
local_gentx_dir=gentx-${machine_name_prefix}
echo "Fetch node ids and node ips for persistent-peers"
for (( i=1 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}
node_host_name=${node_name}.${machine_domain}
gentx_file_name=$(ssh laconic@${node_host_name} ls /home/laconic/${gentx_dir} | head -1)
node_id=$(echo ${gentx_file_name} | sed -e 's/^gentx-//' -e 's/.json$//')
node_ip=$(dig +short ${node_host_name})
peer=${node_id}@${node_ip}:${p2p_port}
persistent_peers+=${peer}
if [[ ${i} -lt ${node_count} ]]; then
persistent_peers+=','
fi
done
echo "Copying gentx from all nodes except 1"
rm -rf ${local_gentx_dir}
mkdir ${local_gentx_dir}
# Note: start at node 2 here because we're going to copy to node 1
for (( i=2 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}
node_host_name=${node_name}.${machine_domain}
echo "Copying ${gentx_dir} on ${node_name} to ${local_gentx_dir}"
scp laconic@${node_host_name}:~/${gentx_dir}/* ${local_gentx_dir}
done
echo "Copying gentx files to node 1"
node_1_host_name=${machine_name_prefix}-1.${machine_domain}
ssh laconic@${node_1_host_name} rm -rf ${local_gentx_dir}
ssh laconic@${node_1_host_name} mkdir ${local_gentx_dir}
scp ${local_gentx_dir}/* laconic@${node_1_host_name}:~/${local_gentx_dir}
gentx_file_list=$(ssh laconic@${node_1_host_name} ls -m ${local_gentx_dir}/*)
echo "Node 1 now has: ${gentx_file_list}"
gentx_files=$(echo ${gentx_file_list} | tr -d ' ' | tr -d '\n')
echo "Generate genesis on node 1"
ssh laconic@${node_1_host_name} ${so_command} --stack mainnet-laconic deploy setup --network-dir ${node_network_dir} --create-network --gentx-files ${gentx_files}
echo "Fetching genesis file from node 1"
local_genesis_file=${local_gentx_dir}/genesis.json
scp laconic@${node_1_host_name}:~/${node_network_dir}/config/genesis.json ${local_gentx_dir}
echo "Copying genesis file to other nodes"
# Note: start at node 2 here because we're going to copy to node 1
for (( i=2 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}
node_host_name=${node_name}.${machine_domain}
echo "Copying ${local_genesis_file} to ${node_name} to ${node_name}"
scp ${local_genesis_file} laconic@${node_host_name}:~/${node_network_dir}/config
done
echo "Use this for persistent_peers:"
echo ${persistent_peers}

View File

@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
usage="Usage: $0 <machine-name-prefix> <peers>"
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo ${usage}
exit 1
fi
if [[ -n "$2" ]]; then
peers=$2
else
echo ${usage}
exit 1
fi
machine_domain=borgboxes.network
node_count=4
node_network_dir=testnet-dir
so_command=/home/laconic/bin/laconic-so
echo "Run deploy init on all nodes"
spec_file_name=${machine_name_prefix}-spec.yml
deployment_dir=${machine_name_prefix}-deployment
echo "Creating deployments on all nodes"
for (( i=1 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}
node_host_name=${node_name}.${machine_domain}
laconic_console_config="LACONIC_HOSTED_ENDPOINT=http://${node_host_name}:9473"
echo "Creating deployment dir on ${node_name}"
ssh laconic@${node_host_name} ${so_command} --stack mainnet-laconic deploy init --map-ports-to-host any-same --output ${spec_file_name} --config ${laconic_console_config}
ssh laconic@${node_host_name} ${so_command} --stack mainnet-laconic deploy create --deployment-dir ${deployment_dir} --spec-file ${spec_file_name} --network-dir ${node_network_dir} --initial-peers ${peers}
done

31
scripts/delete-deployments.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo "Usage: $0 <machine-name-prefix>"
exit 1
fi
machine_domain=borgboxes.network
node_count=4
node_network_dir=testnet-dir
so_command=/home/laconic/bin/laconic-so
echo "Delete deployment dirs on all nodes"
spec_file_name=${machine_name_prefix}-spec.yml
deployment_dir=${machine_name_prefix}-deployment
for (( i=1 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}
node_host_name=${node_name}.${machine_domain}
echo "Deleting deployment dir on ${node_name}"
ssh laconic@${node_host_name} sudo rm -rf ${deployment_dir}
done

26
scripts/delete-network-dirs.sh Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo "Usage: $0 <machine-name-prefix>"
exit 1
fi
machine_domain=borgboxes.network
node_count=4
node_network_dir=testnet-dir
local_gentx_dir=gentx-${machine_name_prefix}
echo "Deleting network dirs on all nodes"
for (( i=1 ; i<=$node_count ; i++ ));
do
node_name=${machine_name_prefix}-${i}.${machine_domain}
echo "Deleting ${node_network_dir} on ${node_name}"
ssh laconic@${node_name} rm -rf ${node_network_dir} ${local_gentx_dir}
done

25
scripts/deployment-command.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Run a specified deployment subcommand on all nodes
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source ${SCRIPT_DIR}/lib.sh
usage="Usage: $0 <machine-name-prefix> <deployment-subcommand>"
if [[ -n "$1" ]]; then
machine_name_prefix=$1
else
echo ${usage}
exit 1
fi
if [[ -n "$2" ]]; then
subcommand=$2
else
echo ${usage}
exit 1
fi
deployment_dir=${machine_name_prefix}-deployment
deployment_command="${so_command} deployment --dir ${deployment_dir} ${subcommand}"
run_on_all_nodes ${machine_name_prefix} "${deployment_command}"

39
scripts/lib.sh Normal file
View File

@ -0,0 +1,39 @@
function error_exit() {
echo "Error: $1"
exit 1
}
function assert_defined() {
local variable_name=$1
if [[ ! ${!variable_name} ]]; then
error_exit "$variable_name is not defined"
fi
}
network_config_file=./network.cfg
if [[ ! -f ${network_config_file} ]]; then
error_exit "$network_config_file does not exist"
fi
source ${network_config_file}
assert_defined "machine_domain"
assert_defined "node_count"
assert_defined "ssh_user"
# Hack until we fix PATH for remote sessions
so_command=/home/laconic/bin/laconic-so
# run_on_all_nodes(machine_name_prefix, command_to_run)
function run_on_all_nodes() {
local machine_name_prefix=$1
local command_to_run=$2
for (( i=1 ; i<=$node_count ; i++ ));
do
local machine_name=${machine_name_prefix}-${i}.${machine_domain}
echo "${machine_name}:"
echo "Running: ${command_to_run}"
ssh ${ssh_user}@${machine_name} ${command_to_run}
done
}

3
scripts/network.cfg Normal file
View File

@ -0,0 +1,3 @@
machine_domain=borgboxes.network
node_count=4
ssh_user=laconic