Skip to content

Instantly share code, notes, and snippets.

@blockpane

blockpane/snap.sh

Last active Apr 24, 2021
Embed
What would you like to do?
FIO Snapshots Script
#!/bin/bash
CONTAINER=snap_testnet_nodeos_1
ZPOOL=docker
CHAIN_NAME=testnet
OUT_DIR=/var/tmp
BUCKET=s3://snap.blockpane.com
URL=https://snap.blockpane.com
AWSCLI_OPTS="--endpoint-url https://s3.us-west-1.wasabisys.com"
# Uses ZFS snapshots to minimize node downtime when creating history node archives:
#
# - needs root
# - needs producer API enabled in config.ini
# - needs curl installed in container, needs 'pixz' on host.
# - expects the FIO home to be in the only docker volume for the container.
# - executes a nodeos state snapshot from inside the container
# - stops the container
# - takes ZFS snapshot of the entire docker volume
# - restarts the container
# - mounts the ZFS snapshot
# - creates 3 files: tar and compresses (maintains sparseness)
# 1. just the snapshot
# 2. snapshot and blocks.log
# 3. full archive of the data directory and history directory. (includes state)
# - destroys the ZFS snapshot
# - uploads to an S3 compatible destination
# always exit when something fails
set -e
# uncomment to debug
#set -x
[ $(id -u) -eq 0 ] || { echo "must be root"; kill 0; }
# ensure the container gets started and snapshot removed just in case of an error, these can fail silently.
function cleanup(){
docker start "${CONTAINER}" >/dev/null 2>&1 || true
cd /
umount "/mnt/${CONTAINER}" >/dev/null 2>&1 || true
zfs destroy "${ZPOOL}@${CONTAINER}" >/dev/null 2>&1 || true
}
trap 'cleanup' err exit
TODAY=$(date +%Y%m%d)
MNT=$(docker inspect "${CONTAINER}" |jq -r .[0].Mounts[0].Source | sed 's_/var/lib/docker/__')
[ "$MNT" == "null" ] && exit 1
SNAP=$(docker exec "${CONTAINER}" curl -s -m 300 -XPOST http://localhost:8888/v1/producer/create_snapshot \
| jq -r .snapshot_name | awk -F/ '{print $NF}') || exit 1
[ "$SNAP" == "null" ] && exit 1
docker stop "${CONTAINER}"
zfs snapshot "${ZPOOL}@${CONTAINER}"
docker start "${CONTAINER}"
docker exec "${CONTAINER}" rm -f data/snapshots/${SNAP}
mkdir -p /mnt/${CONTAINER}
mount -t zfs "${ZPOOL}@${CONTAINER}" /mnt/${CONTAINER}
# cleanup previous snapshots
rm -f ${OUT_DIR}/${CHAIN_NAME}-*.txz
pushd /mnt/${CONTAINER}/${MNT}/data/snapshots
tar -cS -I'pixz -9' -f "${OUT_DIR}/${CHAIN_NAME}-${TODAY}-snap.txz" "${SNAP}"
pushd /mnt/${CONTAINER}/${MNT}
tar -cS -I'pixz' -f "${OUT_DIR}/${CHAIN_NAME}-${TODAY}-blocks.txz" data/blocks "data/snapshots/${SNAP}"
tar -cS -I'pixz' -f "${OUT_DIR}/${CHAIN_NAME}-${TODAY}-history.txz" data/ history/ history_index/
popd; popd
###########################################################
### Delete below this line if not uploading to a bucket ###
###########################################################
aws ${AWSCLI_OPTS} s3 cp --only-show-errors "${OUT_DIR}/${CHAIN_NAME}-${TODAY}-snap.txz" "${BUCKET}/${CHAIN_NAME}-${TODAY}-snap.txz"
aws ${AWSCLI_OPTS} s3 cp --only-show-errors "${BUCKET}/${CHAIN_NAME}-${TODAY}-snap.txz" "${BUCKET}/${CHAIN_NAME}-latest-snap.txz"
aws ${AWSCLI_OPTS} s3 mv --only-show-errors "${BUCKET}/${CHAIN_NAME}-latest-blocks.txz" "${BUCKET}/${CHAIN_NAME}-previous-blocks.txz"
aws ${AWSCLI_OPTS} s3 cp --only-show-errors "${OUT_DIR}/${CHAIN_NAME}-${TODAY}-blocks.txz" "${BUCKET}/${CHAIN_NAME}-latest-blocks.txz"
aws ${AWSCLI_OPTS} s3 mv --only-show-errors "${BUCKET}/${CHAIN_NAME}-latest-history.txz" "${BUCKET}/${CHAIN_NAME}-previous-history.txz"
aws ${AWSCLI_OPTS} s3 cp --only-show-errors "${OUT_DIR}/${CHAIN_NAME}-${TODAY}-history.txz" "${BUCKET}/${CHAIN_NAME}-latest-history.txz"
######################################################################
### Delete below this line if not creating an HTML file with links ###
######################################################################
echo '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>snapshots</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="bootstrap.css"></head>
<body>
<div class="container-fluid">
<div class="w-65 mx-auto" style="max-width: 1200px;">' > "${OUT_DIR}/${CHAIN_NAME}-index.html"
echo "<h3>${CHAIN_NAME} snapshots:</h3><br />" >> "${OUT_DIR}/${CHAIN_NAME}-index.html"
aws ${AWSCLI_OPTS} s3 ls "${BUCKET}" | grep "${CHAIN_NAME}-.*txz" | sort -r | while read f; do
echo "<a href=\"${URL}/$(echo $f |awk '{print $NF}')\"><pre>${f}</pre></a>" >> "${OUT_DIR}/${CHAIN_NAME}-index.html"
done
echo '</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</body>
</html>' >> "${OUT_DIR}/${CHAIN_NAME}-index.html"
aws ${AWSCLI_OPTS} s3 cp --only-show-errors "${OUT_DIR}/${CHAIN_NAME}-index.html" "${BUCKET}/${CHAIN_NAME}-index.html"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment