~hacktivista/scripts

f80c9cc385e077a2cfddd0a3868034547d5a2748 — Felix Freeman 1 year, 7 months ago
dynfail
2 files changed, 88 insertions(+), 0 deletions(-)

A README.md
A dynfail
A  => README.md +1 -0
@@ 1,1 @@
Random scripts

A  => dynfail +87 -0
@@ 1,87 @@
#!/bin/sh
#
# Dynamic failover tools v0.1
#
# Calls to this script should be made on crontab
# on primary host:
# */1 * * * * . $HOME/.profile; dynfail failover
# */5 * * * * . $HOME/.profile; dynfail sync_ip
# on secondary host:
# */1 * * * * . $HOME/.profile; dynfail recover
# */5 * * * * . $HOME/.profile; dynfail sync_ip
#
# Requirements:
# - sudo with access to the postgres user
# - dig (bind9-dnsutils/bind-tools)
# - nc
# - linode-cli (don't follow me, use nsupdate instead)
# - PGLR https://git.hacktivista.org/pglr
#
# Copyright 2021 Felix Freeman <libsys@hacktivista.org>
#
# This software is licensed under the 'MIT No Attribution' license terms. I
# don't want attribution nor exclusive rights over it, but I'd love that you
# free your software too.

if [ $# -ne 1 ]; then
    echo "Usage: $0 <sync_ip|failover|recover>"
    exit 1
fi

domain_id=$DYNFAIL_DOMAIN_ID
root_record_id=$DYNFAIL_ROOT_RECORD_ID
root_host=$DYNFAIL_ROOT_HOST
primary_ip=$DYNFAIL_PRIMARY_IP
this_host=$DYNFAIL_THIS_HOST
this_record_id=$DYNFAIL_THIS_RECORD_ID
this_replica=$DYNFAIL_THIS_REPLICA
replicas=$DYNFAIL_REPLICAS
databases=$DYNFAIL_DATABASES # string list divided by space

update_root_ip () {
    target_ip=$(dig -4 +short "$1")
    linode-cli domains records-update "$domain_id" "$root_record_id" \
        --target "$target_ip"
}

sync_ip () {
    last_ip=$(dig -4 +short "$this_host")
    current_ip="$(dig -4 +short myip.opendns.com @resolver1.opendns.com)"
    if [ "$last_ip" != "$current_ip" ]; then
        linode-cli domains records-update "$domain_id" "$this_record_id" \
            --target="$current_ip"
        update_root_ip "$this_host"
    fi
}

failover () {
    # if primary host postgres can't be reached
    # and failover has not been executed yet
    if \
        ! nc -w 5 -z "$primary_ip" 5432 \
        && [ "$(dig -4 +short "$root_host")" != "$(dig -4 +short "$this_host")" ]
    then
        update_root_ip "$this_host"
        for database in $databases; do
            sudo -u postgres -- psql "$database" \
                -c "CALL pglr_seq_sync($replicas, $this_replica)"
        done
    fi
}

recover () {
    # if root is assigned to other host
    # and this (primary) host has connectivity
    if \
        [ "$(dig -4 +short "$root_host")" != "$(dig -4 +short "$this_host")" ] \
        && nc -w 5 -z 1.1.1.1 80
    then
        update_root_ip "$this_host"
        for database in $databases; do
            sudo -u postgres -- psql "$database" \
                -c "CALL pglr_seq_sync($replicas, $this_replica)"
        done
    fi
}

$1