#!/bin/bash

# All files in this package is subject to the GPL v2 license
# More information is in the COPYING file in the top directory of this package.
# Copyright (C) 2011 Severalnines

# Also see CREDITS, many thanks to Timothy Der (randomorzero.wordpress.com)
# for the work on the makecfg, mysqlckk, and haproxy.cfg.tmpl


function init
{    
    FILES=`ls /etc/cmon.cnf 2>&1`
    FILES2=`ls /etc/cmon.d/*.cnf 2>&1`
    FILES="$FILES $FILES2"
    configfile=""
    for f in $FILES
    do
	X=`grep -l cluster_id=${CLUSTER_ID} $f 2>&1 `
	if [ $? -eq 0 ]; then
            source $f
            configfile=$f
        fi
    done

    if [ -z "$configfile" ]; then
        echo "No matching configuration file found having cluster_id=${CLUSTER_ID}"
        exit 1
    fi

    source $configfile;
    
    CMON_DB_HOST=127.0.0.1
    CMON_DB_PORT=$mysql_port
    CMON_USER=cmon
    CMON_DB_DB=cmon
    CMON_PASSWORD=$mysql_password
    MYSQL_BIN=$mysql_basedir/bin/mysql
    MYSQL_BIN2=$mysql_bindir/mysql
    CONNECT_TIMEOUT=10
    CLUSTER_TYPE=$type
    MYSQL_OPTS="--connect-timeout=$CONNECT_TIMEOUT"
    LOCKFILE="/tmp/s9s_create.lock"
    OSUSER=$USER
    SUFFIX="1"
    PREFIX="s9s"
    JOBID=0
    HAPROXY_MYSQL_LISTEN_PORT="33306"
    HAPROXY_OPTS="-f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -st \$(cat /var/run/haproxy.pid)"
    LB_ADMIN_USER='admin'
    LB_ADMIN_PORT="9600"
    LB_ADMIN_PASSWORD='admin'
    
    if [ "$OSUSER" != "root" ]; then
	echo "must be executed as 'root' or with 'sudo'"
	exit 1
    fi
}
 

function log_job_message
{    
    MSG=$1
    EXIT_CODE=$2
    if [ -z "$EXIT_CODE" ]; then
	EXIT_CODE=1
    fi
    QUERY="INSERT INTO cmon_job_message(cid, jobid,message,exit_code,report_ts) VALUES($CLUSTER_ID,$JOBID,\"$MSG\",$EXIT_CODE,now())"
    if [ $JOBID -ne 0 ]; then 
	$MYSQL_BIN  -B -N  --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT  -e "$QUERY" 2>&1 >/tmp/err.log
    else
	if [ $EXIT_CODE -ne 0 ]; then
	    echo ""
	    echo "Failed: $MSG"
	fi
    fi
}

function log_job
{    
    STATUS=$1
    STATUS_TXT=$2
    EXIT_CODE=$3
    QUERY="UPDATE cmon_job SET status='$STATUS', status_txt='$STATUS_TXT', exit_code=$EXIT_CODE, report_ts=NOW()  WHERE cid=$CLUSTER_ID AND jobid=$JOBID"
    if [ $JOBID -ne 0 ]; then 
	$MYSQL_BIN  -B -N  --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT  -e "$QUERY" 2>&1 >/tmp/err.log
    fi
}


function remote_copy()
{
   srcfile=$1
   desthost=$2
   destfile=$3
   printf "%-4s: Copying '%s' " "$desthost" "$srcfile"
   scp $SSH_OPTS2 $srcfile $SSH_USER@$desthost:$destfile >> $HOME/s9s_deploy.log  2>/dev/null
   if [ $? -eq 0 ]; then
      log_job_message "copying file $srcfile --> $desthost:$destfile" 0
      printf "\033[32m[ok]\033[0m\n"
      return 0
   else
      log_job_message "copying file $srcfile --> $desthost:$destfile" 1
      log_job 'FAILED' 's9s_haproxy failed' 1
      printf "\033[31m[failed]\033[0m\n"
      exit 1
   fi
}

function remote_cmdx()
{
   desthost=$1
   xcommand=$2
   printf "%-4s: Executing '%s'" "$desthost" "$xcommand"
   ssh -q $SSH_OPTS $SSH_USER@$desthost "$SUDO $xcommand "
   if [ $? -eq 0 ]; then
      log_job_message "$desthost: Executed $xcommand" 0
      printf "\033[32m[ok]\033[0m\n"
      return 0
   else
      log_job_message "command failed: $xcommand" 1
      log_job 'FAILED' 'backup failed' 1
      printf "\033[31m[failed]\033[0m\n"
      exit 1
   fi
}

function remote_cmd_nofail()
{
   desthost=$1
   xcommand=$2
   printf "%-4s: Executing '%s'" "$desthost" "$xcommand"
   ssh -q $SSH_OPTS $SSH_USER@$desthost "$SUDO $xcommand "  >> $HOME/s9s_deploy.log 2>&1
   ret=$?
   log_job_message "$desthost: Executed $xcommand" 0
   printf "\033[32m[ok]\033[0m\n"
   return $ret
}

function remote_cmd()
{
   desthost=$1
   xcommand=$2
   MAX_RETRIES=1
   printf "%-4s: Executing '%s' " "$desthost" "$xcommand"
   retry=0
   while [ $retry -lt $MAX_RETRIES ]; 
   do
      x=`ssh -q $SSH_OPTS $SSH_USER@$desthost "$SUDO $xcommand " 2>&1  >> $HOME/s9s_deploy.log`
      if [ $? -eq 0 ]; then
	  log_job_message "$desthost: Executed $xcommand" 0
          printf "\033[32m[ok]\033[0m\n"
          return 0
      fi
      retry=`expr $retry + 1`
      printf "\033[31m[failed: retrying ${retry}/${MAX_RETRIES}]\033[0m\n"
      ssh -q $SSH_OPTS $SSH_USER@$desthost " sync " 2>&1  >> $HOME/s9s_deploy.log
      sleep 1
   done
   log_job_message "FAILED: ${desthost}@${xcommand}" 1
   printf "\033[31m[failed]\033[0m\n"
   echo $x
   echo 'The following command failed:'
   echo "ssh -q $SSH_OPTS $SSH_USER@$desthost \" $xcommand \""
   echo 'Try running the command on the line above again, contact http://support.severalnines.com/ticket/new, attach the output from deploy.sh and the error from running the command to the Support issue.'
   exit 1
}


function remote_cmd3()
{
   desthost=$1
   xcommand=$2
   printf "%-4s: Executing '%s' " "$desthost" "$xcommand"
   ssh -nq -tt $SSH_OPTS $SSH_USER@$desthost "$SUDO $xcommand "   >> $HOME/s9s_deploy.log 2>&1
   if [ $? -eq 0 ]; then
       log_job_message "$desthost: Executed $xcommand" 0
       printf "\033[32m[ok]\033[0m\n"
       return 0
   else
       printf "\033[31m[failed]\033[0m\n"
       log_job_message "FAILED: ${desthost}@${xcommand}" 1
       exit 1
   fi
}



function load_opts
{
    local CLUSTER_ID=$1
    echo "load opts $CLUSTER_ID"
    OS=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='OS' AND cid=$CLUSTER_ID" 2>/dev/null`
    CONFIGDIR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='CONFIGDIR' AND cid=$CLUSTER_ID" 2>/dev/null`
    MYSQL_PORT=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='MYSQL_PORT' AND cid=$CLUSTER_ID" 2>/dev/null`
    GALERA_PORT=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='GALERA_PORT' AND cid=$CLUSTER_ID" 2>/dev/null`
    MYSQL_BASEDIR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='MYSQL_BASEDIR' AND cid=$CLUSTER_ID" 2>/dev/null`
    TMPDIR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='STAGING_DIR' AND cid=$CLUSTER_ID"`
    S9S_TMPDIR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='STAGING_DIR' AND cid=$CLUSTER_ID"`
    MYSQL_SCRIPTDIR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='SCRIPTDIR' AND cid=$CLUSTER_ID" 2>/dev/null`
    SSH_IDENTITY=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='SSH_IDENTITY' AND cid=$CLUSTER_ID" 2>/dev/null`
    SSH_USER=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='SSH_USER' AND cid=$CLUSTER_ID" 2>/dev/null`
    SSH_PORT=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='SSH_PORT' AND cid=$CLUSTER_ID" 2>/dev/null`
    SSH_OPTSX=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='SSH_OPTS' AND cid=$CLUSTER_ID" 2>/dev/null`
    SUDO=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='SUDO' AND cid=$CLUSTER_ID" 2>/dev/null`
    XVENDOR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='VENDOR' AND cid=$CLUSTER_ID" 2>/dev/null`
    OS_USER_HOME=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='OS_USER_HOME' AND cid=$CLUSTER_ID" 2>/dev/null`
    NETWORKLESS=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon_configuration where param='NETWORKLESS' AND cid=$CLUSTER_ID" 2>/dev/null`
    DATADIR=`$MYSQL_BIN -N -B -A --user=$CMON_USER --password=$CMON_PASSWORD --database=$CMON_DB_DB --host=$CMON_DB_HOST --port=$CMON_DB_PORT -e "select value from cmon.cluster_config where variable='datadir' and cid=$CLUSTER_ID order by id asc limit 1" 2>/dev/null`
    if [ "$S9S_TMPDIR" = "" ] || [ "$TMPDIR" = "NULL" ];  then
	S9S_TMPDIR="/tmp/"
	TMPDIR="/tmp/"
    fi


    if [ $? -ne 0 ]; then 
        log_job_message "load opts failed"
        exit 1
    fi

    if [ -z "$MYSQL_PORT" ]; then 
        log_job_message "MYSQL_PORT not set in Cluster Settings"
        exit 1
    fi

    if [ -z "$SSH_USER" ]; then 
        log_job_message "SSH_USER not set in Cluster Settings"
        exit 1
    fi

    if [ -z "$OS" ]; then 
        log_job_message "OS not set in Cluster Settings"
        exit 1
    fi

    
    SSH_OPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -oNumberOfPasswordPrompts=0 -oConnectTimeout=10"
    if [ "$SSH_IDENTITY" = "" ]; then
	SSH_IDENTITY="-oIdentityFile=${OS_USER_HOME}/.ssh/id_rsa"
	SSH_IDENTITY2="-i ${OS_USER_HOME}/.ssh/id_rsa"
    else
	SSH_IDENTITY="-oIdentityFile=$SSH_IDENTITY"
	SSH_IDENTITY2="-i $SSH_IDENTITY"
    fi
    SSH_OPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -oNumberOfPasswordPrompts=0 -oConnectTimeout=10 $SSH_IDENTITY"
    SSH_OPTS2="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -oNumberOfPasswordPrompts=0 -oConnectTimeout=10 $SSH_IDENTITY"
    if [ "$SSH_USER" != "root" ]; then
	SSH_OPTS=" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -oNumberOfPasswordPrompts=0 -oConnectTimeout=10 $SSH_IDENTITY"
	if [ "$SUDO" = "" ] || [ "$SUDO" = "NULL" ];  then
           SUDO=sudo
        fi
    fi
    if [ "$SSH_PORT" = "" ] || [ "$SSH_PORT" = "NULL" ];  then
        SSH_PORT="22"
    fi
    SSH_OPTS="$SSH_OPTSX -p$SSH_PORT $SSH_OPTS"    
    SSH_OPTS2="-P$SSH_PORT $SSH_OPTS"    

}


function change_controller_address
{
    local h=$1
    local new_address=$2
    remote_cmd_nofail $h "sed -i 's#mysql_hostname=.*#mysql_hostname=$new_address#g' $CMONCNF"
    remote_cmd_nofail $h "sed -i 's#controller_address=.*#controller_address=$new_address#g' $CMONCNF"    
}

function failover
{
    args=`getopt p:s:P:h:i:N:n:j:o: $*`
    set -- $args
    for i
    do
        case "$i" in
            -p)
                CMON_PASSWORD="$2"; shift;
                shift;;
            -i)
                CLUSTER_ID="$2"; shift;
                shift;;
            -n)
                NEW_ADDRESS="$2"; shift;
                shift;;
            -o)
                OLD_ADDRESS="$2"; shift;
                shift;;
            -j)
                JOBID="$2"; shift;
                shift;;
            --)
                shift; break;;
                esac
    done

    
    if [ -z "$CMON_PASSWORD" ]; then
        echo "s9s_cc_failover -p <current cmon password> is missing"
      exit 1
    fi

    if [ -z "$CLUSTER_ID" ]; then
        echo "s9s_cc_failover -i <cluster id> is missing"
	exit 1
    fi
    init
    if [ -z "$NEW_ADDRESS" ]; then
        echo "s9s_cc_failover -n <new cc address> is missing"
        exit 1
    fi

    if [ -z "$OLD_ADDRESS" ]; then
        echo "s9s_cc_failover -o <old cc address> is missing"
        exit 1
    fi
    
    
    if ! test -f $MYSQL_BIN; then
	if ! test -f $MYSQL_BIN2; then
	    echo "Could not find mysql client binary"
	    echo "Change MYSQL_BIN in beginning of the scipt"
	    exit 1
	fi
	MYSQL_BIN=$MYSQL_BIN2
    fi
    

    load_opts $CLUSTER_ID
    QUERY="select group_concat(h.hostname SEPARATOR ' ') from hosts h WHERE h.cid=$CLUSTER_ID"
    all_hostnames=`$MYSQL_BIN -B -N --host=$CMON_DB_HOST --port=$CMON_DB_PORT --user=cmon --password=$CMON_PASSWORD --database=$CMON_DB_DB -e "$QUERY"`

    CMONCNF=/etc/cmon.cnf

    if [ -z "$all_hostnames" ]; then
       echo "No hostnames found."
       exit 1
    fi

    if [ "$all_hostnames" = "NULL" ]; then
       echo "No hostnames found."
       exit 1
    fi
    
    for h in $all_hostnames
    do
	if [ "$h" = "$NEW_ADDRESS" ] || [ "$h" = "$OLD_ADDRESS" ] ; then
	    echo "Ignoring $h - it is a controller"
	else
	    change_controller_address $h $NEW_ADDRESS
	fi
    done

    for h in $all_hostnames
    do
	if [ "$h" = "$NEW_ADDRESS" ] || [ "$h" = "$OLD_ADDRESS" ] ; then
	    echo "Ignoring $h - it is a controller"
	else
	    remote_cmd_nofail $h "/etc/init.d/cmon restart"
	fi
    done
    CMONCNF=/etc/cmon.cnf
    CMONINITD=cmon
    if [ $CLUSTER_ID -gt 1 ]; then
          CMONCNF=/etc/cmon_${CLUSTER_ID}.cnf
          CMONINITD=cmon_${CLUSTER_ID}
    fi
    if [ `grep enable_autorecovery $CMONCNF` ]; then
	echo "enable_autorecovery=1" >> $CMONCNF
    fi
    sed -i 's#enable_autorecovery=.*#enable_autorecovery=1#g' $CMONCNF
    service $CMONINITD restart
    ssh-copy-id $SSH_IDENTITY2 $SSH_USER@$OLD_ADDRESS
    remote_cmd_nofail $OLD_ADDRESS "sed -i 's#enable_autorecovery=.*#enable_autorecovery=0#g' $CMONCNF"    
    remote_cmd_nofail $OLD_ADDRESS "service $CMONINITD stop"    
    exit 0
    
}




function sync_cc
{
    args=`getopt p:s:P:h:i:N:n:j:o: $*`
    set -- $args
    for i
    do
        case "$i" in
            -p)
                CMON_PASSWORD="$2"; shift;
                shift;;
            -i)
                CLUSTER_ID="$2"; shift;
                shift;;
            -n)
                NEW_ADDRESS="$2"; shift;
                shift;;
            -o)
                OLD_ADDRESS="$2"; shift;
                shift;;
            -j)
                JOBID="$2"; shift;
                shift;;
            --)
                shift; break;;
                esac
    done

    
    if [ -z "$CMON_PASSWORD" ]; then
        echo "s9s_cc_failover -p <current cmon password> is missing"
      exit 1
    fi

    if [ -z "$CLUSTER_ID" ]; then
        echo "s9s_cc_failover -i <cluster id> is missing"
	exit 1
    fi
    init
    if [ -z "$NEW_ADDRESS" ]; then
        echo "s9s_cc_failover -n <new cc address> is missing"
        exit 1
    fi

    if [ -z "$OLD_ADDRESS" ]; then
        echo "s9s_cc_failover -o <old cc address> is missing"
        exit 1
    fi
    
    
    if ! test -f $MYSQL_BIN; then
	if ! test -f $MYSQL_BIN2; then
	    echo "Could not find mysql client binary"
	    echo "Change MYSQL_BIN in beginning of the scipt"
	    exit 1
	fi
	MYSQL_BIN=$MYSQL_BIN2
    fi
    

    load_opts $CLUSTER_ID
    
    TABLES="backup_schedule  cmon_configuration ext_proc haproxy_server galera_garbd_proc keepalived mailserver user_event_categories user_events email_notification license"
    
    echo "Dumping data to $S9S_TMPDIR/data.sql"
    mysqldump --no-create-info --single-transaction -ucmon -p$CMON_PASSWORD -h$OLD_ADDRESS -P$CMON_DB_PORT $CMON_DB_DB $TABLES > $S9S_TMPDIR/data.sql
    if [ $? -ne 0 ]; then 
	exit 1
    fi
    sed -i.bak 's#INSERT INTO#REPLACE INTO#g' $S9S_TMPDIR/data.sql
    
    cat $S9S_TMPDIR/data.sql | mysql -ucmon -p$CMON_PASSWORD -h$NEW_ADDRESS -P$CMON_DB_PORT $CMON_DB_DB 
    if [ $? -ne 0 ]; then 
	exit 1
    fi
    
    exit 0
    
}




#if [ ! -e $LOCKFILE ]; then
#    trap "rm -f $LOCKFILE; exit" INT TERM EXIT
#    touch $LOCKFILE    
    ARG=$1
    shift
    case $ARG in
	--failover)
	    failover $*
	    ;;
	--sync-cc)
	    sync_cc $*
	    ;;
	*)
	    echo "Usage: "
	    echo "s9s_cc_failover [--failover|sync-cc] "
	    exit 1
	    ;;
    esac
#    rm $LOCKFILE
 #   trap - INT TERM EXIT
#fi

