diff --git a/README.md b/README.md index 5555776165183e..bdb400248bce52 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,62 @@ $ snap info solana $ sudo snap refresh solana --devmode ``` +### Daemon support +The snap supports running a leader or validator node as a system daemon. + +Run `sudo snap get solana` to view the current daemon configuration, and +`sudo snap logs -f solana` to view the daemon logs. + +Disable the daemon at any time by running: +```bash +$ sudo snap set solana mode= +``` + +Runtime configuration files for the daemon can be found in +`/var/snap/solana/current`. + +#### Leader daemon +```bash +$ sudo snap set solana mode=leader public-address=$(curl -s ifconfig.co) +``` + +If CUDA is available: +```bash +$ sudo snap set solana mode=leader-cuda public-address=$(curl -s ifconfig.co) +``` + +`rsync` must be configured and running on the leader. + +1. Ensure rsync is installed with `sudo apt-get -y install rsync` +2. Edit `/etc/rsyncd.conf` to include the following +``` +[solana] +path = /var/snap/solana/current +hosts allow = * +read only = true +``` +3. Run `sudo systemctl enable rsync; sudo systemctl start rsync` +4. Test by running `rsync -Pzravv rsync:///solana +solana-config` from another machine. If the leader is running on a cloud +provider it may be necessary to configure the Firewall rules to permit ingress +to port tcp:873 and the port range udp:8000-udp:10000 + + +#### Validator daemon +```bash +$ sudo snap set solana mode=validator public-address=$(curl -s ifconfig.co) +``` +If CUDA is available: +```bash +$ sudo snap set solana mode=validator-cuda public-address=$(curl -s ifconfig.co) +``` + +By default the validator will connect to **testnet.solana.com**, override +the leader address by running: +```bash +$ sudo snap set solana mode=validator leader-address=127.0.0.1 #<-- change IP address +``` + Developing === diff --git a/ci/snap.sh b/ci/snap.sh index c12a9f2801dff0..8d68c77ec93574 100755 --- a/ci/snap.sh +++ b/ci/snap.sh @@ -36,5 +36,8 @@ set -x echo --- build snapcraft +source ci/upload_ci_artifact.sh +upload_ci_artifact solana_*.snap + echo --- publish $DRYRUN snapcraft push solana_*.snap --release $SNAP_CHANNEL diff --git a/ci/upload_ci_artifact.sh b/ci/upload_ci_artifact.sh new file mode 100644 index 00000000000000..94d4bd9d1c50fb --- /dev/null +++ b/ci/upload_ci_artifact.sh @@ -0,0 +1,18 @@ +# |source| me + +upload_ci_artifact() { + echo --- artifact: $1 + if [[ -r $1 ]]; then + ls -l $1 + if ${BUILDKITE:-false}; then + ( + set -x + buildkite-agent artifact upload $1 + ) + fi + else + echo ^^^ +++ + echo $1 not found + fi +} + diff --git a/multinode-demo/fullnode.sh b/multinode-demo/fullnode.sh new file mode 100755 index 00000000000000..4ddaecdbe19bd3 --- /dev/null +++ b/multinode-demo/fullnode.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# +# Runs a full node +# + +here="$(dirname "$0")" + +usage() { + if [[ -n "$1" ]]; then + echo "$*" + fi + + cat </dev/null 2>/dev/null + +case $MODE in +leader-cuda|leader) + echo "Starting $MODE" + set -x + exec "$FULLNODE" -l "$DATA_DIR/leader.json" \ + < "$DATA_DIR/genesis.log" "$DATA_DIR"/tx-*.log \ + > "$DATA_DIR"/tx-"$(date -u +%Y%m%d%H%M%S%N)".log + ;; + +validator-cuda|validator) + LEADER_ADDRESS=testnet.solana.com + if [[ -n "$3" ]]; then + LEADER_ADDRESS="$3" + elif [[ -d $SNAP ]]; then # Running as a Linux Snap? + LEADER_ADDRESS="$(snapctl get leader-address)" + fi + [[ -n "$LEADER_ADDRESS" ]] || usage "Error: leader_address not specified" + + echo "Fetching configuration from $LEADER_ADDRESS:" + ( + set -x + rsync -vrPz "rsync://$LEADER_ADDRESS/solana" "$DATA_DIR/$LEADER_ADDRESS" + ) || exit $? + + echo "Starting $MODE connecting to the leader at address: $LEADER_ADDRESS" + set -x + exec "$FULLNODE" \ + -l "$DATA_DIR/validator.json" -v "$DATA_DIR/$LEADER_ADDRESS/leader.json" \ + < "$DATA_DIR/$LEADER_ADDRESS/genesis.log" "$DATA_DIR/$LEADER_ADDRESS"/tx-*.log + ;; + +*) + echo "Error: Unknown mode: $MODE" + exit 1 + ;; +esac + +exit 1 diff --git a/multinode-demo/setup.sh b/multinode-demo/setup.sh index 3c68abccab1159..433700410ad0ea 100755 --- a/multinode-demo/setup.sh +++ b/multinode-demo/setup.sh @@ -8,6 +8,10 @@ myip=$(myip) || exit $? num_tokens=${1:-1000000000} +# +# TODO: Merge this file with ../snap/hooks/configure +# + cargo run --release --bin solana-mint-demo <<<"${num_tokens}" > mint-demo.json cargo run --release --bin solana-genesis-demo < mint-demo.json > genesis.log diff --git a/snap/hooks/configure b/snap/hooks/configure new file mode 100755 index 00000000000000..63b572f4463287 --- /dev/null +++ b/snap/hooks/configure @@ -0,0 +1,38 @@ +#!/bin/bash -e + +# Setup aliases to the normal solana command to make the reset of configure more +# readable. +shopt -s expand_aliases +export SNAP SNAP_LIBRARY_PATH +alias solana-mint-demo=$SNAP/command-mint-demo.wrapper +alias solana-genesis-demo=$SNAP/command-genesis-demo.wrapper +alias solana-fullnode-config=$SNAP/command-fullnode-config.wrapper + +echo Stopping daemon +snapctl stop --disable solana.daemon +if [[ -n "$(snapctl get mode)" ]]; then + + # + # TODO: Merge this file with ../../../multinode-demo/setup.sh + # + + NUM_TOKENS=1000000000 + + echo Cleaning $SNAP_DATA + rm -rvf $SNAP_DATA/* + + echo Creating $SNAP_DATA/mint-demo.json + solana-mint-demo <<<"$NUM_TOKENS" > $SNAP_DATA/mint-demo.json + + echo Creating $SNAP_DATA/genesis.log + solana-genesis-demo < $SNAP_DATA/mint-demo.json > $SNAP_DATA/genesis.log + + echo Creating $SNAP_DATA/leader.json + solana-fullnode-config -d > $SNAP_DATA/leader.json + + echo Creating $SNAP_DATA/validator.json + solana-fullnode-config -d -b 9000 > $SNAP_DATA/validator.json + + echo Starting daemon as $MODE + snapctl start --enable solana.daemon +fi diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index fc789b6d187bab..d457c47b19d4d7 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -10,6 +10,10 @@ grade: devel # CUDA dependency, so use 'devmode' confinement for now confinement: devmode +hooks: + configure: + plugs: [] + apps: drone: command: solana-drone @@ -44,7 +48,18 @@ apps: client-demo: command: solana-client-demo + daemon: + daemon: simple + command: fullnode.sh + parts: + solana-scripts: + plugin: nil + override-build: | + set -x + mkdir -p $SNAPCRAFT_PART_INSTALL/bin + cp -av multinode-demo/* $SNAPCRAFT_PART_INSTALL/bin/ + solana-cuda: plugin: rust rust-channel: stable