#!/bin/sh # # Dynamic failover tools v0.1 # # Calls to this script should be made on crontab # on primary host: # */1 * * * * . $HOME/.profile; $HOME/.local/bin/dynfail failover # */5 * * * * . $HOME/.profile; $HOME/.local/bin/dynfail sync_ip # on secondary host: # */1 * * * * . $HOME/.profile; dynfail $HOME/.local/bin/recover # */5 * * * * . $HOME/.profile; dynfail $HOME/.local/bin/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 # # 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 " 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") $HOME/.local/bin/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 $HOME/.local/bin/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