#!/bin/bash

log()
{
    echo $(date +"%Y-%m-%d %H:%M:%S,%3N") $@
}

wait_for_host()
{
    local host=$1

    retry=20
    while (($retry > 0)); do
        log INFO "Check $host, retry: $retry."
        ssh -o ConnectTimeout=3 root@$host date > /dev/null 2>&1
        if (($? == 0)); then
            log INFO "Host $host is up."
            break
        fi
        retry=$((retry - 1))
        sleep 4
    done
    if (($retry == 0)); then
        log ERROR "Timeout!"
        exit 1
    fi
}

set_repo()
{
    log INFO "Check repo."
    if [ ! -d "/etc/yum.repos.d.orig" ]; then
        mv /etc/yum.repos.d /etc/yum.repos.d.orig
        mkdir -p /etc/yum.repos.d
    fi
    mv /tmp/depot.repo /etc/yum.repos.d/
}

disable_selinux()
{
    log INFO "Disable SELinux."
    setenforce 0
    cat > /etc/selinux/config << __EOF__
SELINUX=permissive
SELINUXTYPE=targeted
__EOF__
}

install_postgresql()
{
    log INFO "Install PostgreSQL."
    mv /tmp/hosts /etc/
    dnf install -y postgresql-server nc
    systemctl enable postgresql
}

install_keepalived()
{
    log INFO "Install keepalived."
    dnf install -y keepalived
    mv -f /tmp/keepalived.conf /tmp/check-svc \
            /etc/keepalived/
    chmod +x /etc/keepalived/check-svc
    systemctl enable keepalived
}

deploy()
{
    local ha=$1

    echo ""
    log INFO "Deploy PostgreSQL."
    set_repo
    disable_selinux
    install_postgresql
    if [ "$ha" == "True" ]; then
        install_keepalived
    fi
}

start_primary()
{
    log INFO "Start the primary."
    postgresql-setup --initdb
    systemctl start postgresql
    pwd=$(pwd)
    cd /var/lib/pgsql
    pgsql_cmd="sudo -u postgres psql -c"
    $pgsql_cmd "create role replica with replication login password 'replica';"
    $pgsql_cmd "create role root with superuser createdb createrole inherit \
            bypassrls login password 'Root1234';"
    sudo -u postgres cp -f /tmp/postgresql.conf /var/lib/pgsql/data/
    sudo -u postgres cp -f /tmp/pg_hba.conf /var/lib/pgsql/data/
    cd $pwd
    systemctl restart postgresql
    systemctl is-enabled keepalived > /dev/null 2>&1
    if [ $? == 0 ]; then
        systemctl start keepalived
    fi
}

create_slot()
{
    local name=$1

    log INFO "Create replication slot."
    pwd=$(pwd)
    cd /var/lib/pgsql
    pgsql_cmd="sudo -u postgres psql -c"
    $pgsql_cmd "select * from pg_create_physical_replication_slot('$name');"
    cd $pwd
}

start_standby()
{
    local primary=$1

    log INFO "Start the standby."
    systemctl stop postgresql
    rm -rf /var/lib/pgsql/data/*
    pwd=$(pwd)
    cd /var/lib/pgsql
    sudo_cmd="sudo -u postgres"
    $sudo_cmd pg_basebackup -h $primary -D /var/lib/pgsql/data \
            -p 5432 -X stream -U replica -w
    file="/var/lib/pgsql/data/standby.signal"
    $sudo_cmd touch $file
    $sudo_cmd chmod 600 $file
    $sudo_cmd cp -f /tmp/postgresql.conf /var/lib/pgsql/data/
    $sudo_cmd cp -f /tmp/pg_hba.conf /var/lib/pgsql/data/
    cd $pwd
    systemctl restart postgresql
    systemctl is-enabled keepalived > /dev/null 2>&1
    if [ $? == 0 ]; then
        systemctl start keepalived
    fi
}

help()
{
    echo "Help"
    echo "$0 deploy <host> <id> <ha>"
    echo "$0 start-primary <host> <id> <idx>"
    echo "$0 start-standby <host> <id> <idx>"
}

start()
{
    local copy_files tmp_files host id ha

    if [ -z "$2" ]; then help; exit 1; else host=$2; fi
    if [ -z "$3" ]; then help; exit 1; else id=$3; fi

    if [ "$cli_path" != "/tmp" ]; then
        copy_files="$0"
    fi
    case "$1" in
    deploy)
        ha=$4
        if [ "$copy_files" ]; then
            tmp_path=/tmp/$id
            copy_files="$copy_files $tmp_path/depot.repo $tmp_path/hosts"
            if [ $ha == "True" ]; then
                copy_files="$copy_files $tmp_path/keepalived.conf
                        $tmp_path/check-svc"
            fi
        else
            deploy $ha
        fi
        ;;
    start-primary)
        if [ "$copy_files" ]; then
            tmp_path=/tmp/$id
            copy_files="$copy_files $tmp_path/postgresql.conf
                    $tmp_path/pg_hba.conf"
        else
            start_primary
        fi
        ;;
    start-standby)
        if [ "$copy_files" ]; then
            tmp_path=/tmp/$id
            copy_files="$copy_files $tmp_path/postgresql.conf
                    $tmp_path/pg_hba.conf"
        else
            start_standby $4
        fi
        ;;
    create-slot)
        if [ "$copy_files" ]; then
            echo ""
        else
            create_slot $4
        fi
        ;;
    *)
        help
        return
        ;;
    esac
    if [ "$copy_files" ]; then
        echo ""
        log INFO $@
        wait_for_host $host
        log INFO "Copy files to $host."
        scp $copy_files root@$host:/tmp/
        log INFO "Run $cli_name on $host."
        ssh root@$host /tmp/$cli_name "$@"
        log INFO "Clean up on $host."
        for f in $copy_files; do
            tmp_files="$tmp_files /tmp/$(basename $f)"
        done
        ssh root@$host rm -f $tmp_files
    fi
}


cli_name=$(basename $0)
cli_path=$(dirname $0)
start "$@"

exit 0

