#!/bin/bash

PATH=/bin:/sbin:/usr/bin:/usr/sbin:usr/local/bin:/usr/local/sbin:/usr/lib/ksvd/bin
export PATH

O2CB_CONFIG='/etc/sysconfig/o2cb'
OCFS2_CONFIG='/etc/ocfs2/cluster.conf'
OCFS2_CONFIG_BAK='/etc/ocfs2/cluster.conf.old'

cur_node_name_array=()
cur_node_ip_array=()

new_node_name_array=()
new_node_ip_array=()

create_o2cb_config(){

        cat > ${O2CB_CONFIG} <<EOF
#
# This is a configuration file for automatic startup of the O2CB
# driver.  It is generated by running /etc/init.d/o2cb configure.
# On Debian based systems the preferred method is running
# 'dpkg-reconfigure ocfs2-tools'.
#

# O2CB_ENABLED: 'true' means to load the driver on boot.
O2CB_ENABLED=true

# O2CB_STACK: The name of the cluster stack backing O2CB.
O2CB_STACK=o2cb

# O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start.
O2CB_BOOTCLUSTER=ocfs2

# O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead.
O2CB_HEARTBEAT_THRESHOLD=

# O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead.
O2CB_IDLE_TIMEOUT_MS=

# O2CB_KEEPALIVE_DELAY_MS: Max time in ms before a keepalive packet is sent
O2CB_KEEPALIVE_DELAY_MS=

# O2CB_RECONNECT_DELAY_MS: Min time in ms between connection attempts
O2CB_RECONNECT_DELAY_MS=


EOF

}

log(){
    local prefix=`date "+%Y-%m-%d %H:%M:%S"`" : "
    echo "${prefix}" $@ >> ${LOGFILE}
}

warn(){
    local prefix=`date "+%Y-%m-%d %H:%M:%S"`" : WARN : "
    echo "${prefix}" $@ >> ${LOGFILE}
}

fatal(){
    local prefix=`date "+%Y-%m-%d %H:%M:%S"`" : ERROR : "
    echo "${prefix}" $@ >> ${LOGFILE}
    exit 1
}


check_config(){

    i=0
    tmp_file='/tmp/cur.ocfs2.node'
    o2cb list-nodes ocfs2 --oneline > ${tmp_file}
    while read line
    do
        cur_node_name_array[$i]=$(echo $line | awk '{print $3}')
        cur_node_ip_array[$i]=$(echo $line | awk '{print $4}' | awk -F ':' '{print $1}')
        log "$i, ${cur_node_name_array[$i]}, ${cur_node_ip_array[$i]} "
        i=$((i+1))
    done < ${tmp_file}

    j=0
    while read line
    do
        new_node_name_array[$j]=$(echo $line | awk -F '|' '{print $1}')
        new_node_ip_array[$j]=$(echo $line | awk -F '|' '{print $2}')
        log "$j, ${new_node_name_array[$j]}, ${new_node_ip_array[$j]} "
        ((j=j+1))
    done < ${nodefile}

    log "new_node_num=${#new_node_name_array[*]}"
    log "cur_node_num=${#cur_node_name_array[*]}"
    if [ ${#new_node_name_array[*]} -eq ${#cur_node_name_array[*]} ]; then
        for((n=0;n<${#new_node_name_array[*]};n++))
        do
            if [ ${cur_node_name_array[$n]} == ${new_node_name_array[$n]} -a ${cur_node_ip_array[$n]} == ${new_node_ip_array[$n]} ] ;then
                continue
            else
                return 0
            fi
        done
    else
        return 0
    fi

    return 1
}

restart_o2cb_service(){
    host=$1
    #log "ssh ${host} exec o2cb.init stop"
    #ssh root@${host} exec "o2cb.init stop" 1>/dev/null 2>>${LOGFILE}
    log "ssh ${host} exec o2cb.init start"
    ssh root@${host} exec "o2cb.init start" 1>/dev/null 2>>${LOGFILE}
    log "ssh ${host} exec o2cb register-cluster ocfs2"
    ssh root@${host} exec "o2cb register-cluster ocfs2" 1>/dev/null 2>>${LOGFILE}
}

create_ocfs2_config(){

    check_config
    ret=$?
    if [ -f "$OCFS2_CONFIG" ]; then

        if [ $ret -eq 1 ]; then
            log "check ocfs2 config no change, do nothing!"
            exit 0
        fi
    fi

    rm -f ${O2CB_CONFIG}
    rm -f ${OCFS2_CONFIG}

    create_o2cb_config

    o2cb add-cluster ocfs2
    for((n=0;n<${#new_node_name_array[*]};n++))
    do
    o2cb add-node --ip ${new_node_ip_array[$n]} --port 7777 --number $n ocfs2 ${new_node_name_array[$n]}
    done

    for((n=0;n<${#new_node_ip_array[*]};n++))
    do
        scp ${OCFS2_CONFIG} root@${new_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}
        if [ $? -ne 0 ]; then
            warn "scp ${OCFS2_CONFIG} root@${new_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}  failed!"
            break
        fi
        ssh root@${new_node_ip_array[$n]} exec "systemctl disable o2cb" 1>/dev/null 2>>${LOGFILE}
        scp ${O2CB_CONFIG} root@${new_node_ip_array[$n]}:${O2CB_CONFIG} 1>/dev/null 2>>${LOGFILE}
        if [ $? -ne 0 ]; then
            warn "scp ${O2CB_CONFIG} root@${new_node_ip_array[$n]}:${O2CB_CONFIG} 1>/dev/null 2>>${LOGFILE} failed!"
            break
        fi
        restart_o2cb_service ${new_node_ip_array[n]}
    done

    if [ $n -eq ${#new_node_ip_array[*]} ]; then
        log "create_ocfs2_config success!"
        exit 0
    fi

    ###rollback
    for((n=0;n<${#new_node_ip_array[*]};n++))
    do
        ssh root@${new_node_ip_array[n]} exec "rm -rf ${O2CB_CONFIG}" 1>/dev/null 2>>${LOGFILE}
        ssh root@${new_node_ip_array[n]} exec "rm -rf ${OCFS2_CONFIG}" 1>/dev/null 2>>${LOGFILE}
        restart_o2cb_service ${new_node_ip_array[n]}
    done
    warn "rollback ocfs2 config!"
    fatal "create_ocfs2_config failed!"
}

add_ocfs2_node(){

    check_config
    ret=$?
    if [ -f "$OCFS2_CONFIG" ]; then

        if [ $ret -eq 1 ]; then
            log "check ocfs2 config no change, do nothing!"
            exit 0
        fi
    else
        warn "When add node , the ocfs2 config not exsit!"
        create_ocfs2_config
        exit 0
    fi

    create_o2cb_config
    cp -af  ${OCFS2_CONFIG} ${OCFS2_CONFIG_BAK}

    for((n=0;n<${#new_node_ip_array[*]};n++))
    do
	found=0
        for((m=0;m<${#cur_node_ip_array[*]};m++))
        do
            if [ ${cur_node_name_array[$m]} == ${new_node_name_array[$n]} -a ${cur_node_ip_array[$m]} == ${new_node_ip_array[$n]} ] ;then
	        found=1
                break
	    else
	        continue
            fi
        done

        if [ $found -eq 0 ]; then
            log "o2cb add-node --ip ${new_node_ip_array[$n]} --port 7777 ocfs2 ${new_node_name_array[$n]}"
            o2cb add-node --ip ${new_node_ip_array[$n]} --port 7777 ocfs2 ${new_node_name_array[$n]} 1>/dev/null 2>>${LOGFILE}
        fi
    done

    for((n=0;n<${#new_node_ip_array[*]};n++))
    do
        scp ${OCFS2_CONFIG} root@${new_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}
        if [ $? -ne 0 ]; then
            warn "scp ${OCFS2_CONFIG} root@${new_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}  failed!"
            break
        fi
        ssh root@${new_node_ip_array[$n]} exec "systemctl disable o2cb" 1>/dev/null 2>>${LOGFILE}
        scp ${O2CB_CONFIG} root@${new_node_ip_array[$n]}:${O2CB_CONFIG} 1>/dev/null 2>>${LOGFILE}
        if [ $? -ne 0 ]; then
            warn "scp ${O2CB_CONFIG} root@${new_node_ip_array[$n]}:${O2CB_CONFIG} 1>/dev/null 2>>${LOGFILE} failed!"
            break
        fi
        restart_o2cb_service ${new_node_ip_array[n]}
    done

    if [ $n -eq ${#new_node_ip_array[*]} ]; then
        log "add_ocfs2_node success!"
        exit 0
    fi

    ###rollback
    for((n=0;n<${#new_node_ip_array[*]};n++))
    do
        ssh root@${new_node_ip_array[$n]} exec "rm -rf ${OCFS2_CONFIG}" 1>/dev/null 2>>${LOGFILE}
    done

    mv  ${OCFS2_CONFIG_BAK} ${OCFS2_CONFIG}
    for((n=0;n<${#cur_node_ip_array[*]};n++))
    do
        scp ${OCFS2_CONFIG} root@${cur_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}
        restart_o2cb_service ${cur_node_ip_array[$n]}
    done
    warn "rollback ocfs2 config!"
    fatal "add_ocfs2_node failed!"
}

remove_ocfs2_node(){

    check_config
    ret=$?
    if [ -f "$OCFS2_CONFIG" ]; then

        if [ $ret -eq 1 ]; then
            log "check ocfs2 config no change, do nothing!"
            exit 0
        fi
    else
        warn "When remove node , the ocfs2 config not exsit!"
        create_ocfs2_config
        exit 0
    fi

    cp -af  ${OCFS2_CONFIG} ${OCFS2_CONFIG_BAK}

    for((n=0;n<${#cur_node_ip_array[*]};n++))
    do
	found=0
        for((m=0;m<${#new_node_ip_array[*]};m++))
        do
            if [ ${cur_node_name_array[$n]} == ${new_node_name_array[$m]} -a ${cur_node_ip_array[$n]} == ${new_node_ip_array[$m]} ] ;then
	        found=1
                break
	    else
	        continue
            fi
        done

        if [ $found -eq 0 ]; then
            log "o2cb remove-node ocfs2 ${cur_node_name_array[$n]}"
            o2cb remove-node ocfs2 ${cur_node_name_array[$n]} 1>/dev/null 2>>${LOGFILE}
        fi
    done

    for((n=0;n<${#new_node_ip_array[*]};n++))
    do
        scp ${OCFS2_CONFIG} root@${new_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}
        if [ $? -ne 0 ]; then
            warn "scp ${OCFS2_CONFIG} root@${new_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}  failed!"
            break
        fi
        restart_o2cb_service ${new_node_ip_array[$n]}
    done

    if [ $n -eq ${#new_node_ip_array[*]} ]; then
        log "remove_ocfs2_node success!"
        exit 0
    fi

    ###rollback
    mv  ${OCFS2_CONFIG_BAK} ${OCFS2_CONFIG}
    for((n=0;n<${#cur_node_ip_array[*]};n++))
    do
        scp ${OCFS2_CONFIG} root@${cur_node_ip_array[$n]}:${OCFS2_CONFIG} 1>/dev/null 2>>${LOGFILE}
        restart_o2cb_service ${cur_node_ip_array[$n]}
    done
    warn "rollback ocfs2 config!"
    fatal "remove_ocfs2_node failed!"
}

usage(){
        cat <<EOT

        usage: $1 <action> <config> <log>
                  action:  create|add-node|remove-node
                  config:  node config file
                  log:     log file
EOT
}

if [ $# -ne 3 ]; then
    usage $0
    exit 1
fi

ACTION=${1}
nodefile=${2}
LOGFILE=${3}

case "$ACTION" in
    create)
        create_ocfs2_config
        ;;

    add-node)
        add_ocfs2_node
         ;;

    remove-node)
        remove_ocfs2_node
        ;;

    *)
        echo "ERROR: unknow action: ${ACTION}";
        exit 1
        ;;
esac

