Initial version
This commit is contained in:
parent
eb98a946c4
commit
ff5ba970b1
93
README.md
93
README.md
@ -1,2 +1,95 @@
|
|||||||
# laconicd-network-deployment
|
# 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
32
scripts/01-pull-stack-images.sh
Executable 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
28
scripts/02-init-network-dirs.sh
Executable 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
|
81
scripts/03-merge-genesis-txns.sh
Executable file
81
scripts/03-merge-genesis-txns.sh
Executable 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}
|
||||||
|
|
43
scripts/04-create-deployments.sh
Executable file
43
scripts/04-create-deployments.sh
Executable 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
31
scripts/delete-deployments.sh
Executable 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
26
scripts/delete-network-dirs.sh
Executable 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
25
scripts/deployment-command.sh
Executable 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
39
scripts/lib.sh
Normal 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
3
scripts/network.cfg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
machine_domain=borgboxes.network
|
||||||
|
node_count=4
|
||||||
|
ssh_user=laconic
|
Loading…
Reference in New Issue
Block a user