#!/usr/bin/env bash

. /usr/lib/eole/utils.sh

function error()
{
    MSG=${1}
    echo "[ERROR][${MSG}]"
    exit 1
}

function get_user_home()
{
    HOMEDIR=$(getent passwd ${1} | cut -d ':' -f 6)
    echo ${HOMEDIR}
}

function get_one_auth()
{
    CMD="cat"
    HOME=$(get_user_home oneadmin)
    FILE="${HOME}/.one/one_auth"
    ${CMD} ${FILE}
}

function check_default_cluster()
{
   name="${1}"
   cmd="onecluster show 0"
   auth=$(get_one_auth)

   DEFAULT_NAME=$(${cmd} --user ${auth%:*} --password ${auth#*:} | awk '/^NAME/ {print $3}')
   [[ "${name}" = "${DEFAULT_NAME}" ]]
}

function rename_default_cluster()
{
   NAME="${1}"
   CMD="onecluster rename 0 ${NAME}"
   AUTH=$(get_one_auth)

   if ! check_default_cluster "${NAME}"
   then

       if ${CMD} --user ${AUTH%:*} --password ${AUTH#*:}
       then
           echo "The default cluster name is now '${NAME}'"
       else
           error "The default cluster can not be renamed"
       fi
   else
       echo "The default cluster name is already \"${NAME}\""
   fi
}

function check_host()
{
    name="${1}"
    cmd="onehost"
    opt="list"
    auth=$(get_one_auth)

    res=0
    clst_list=$(${cmd} ${opt} --user ${auth%:*} --password ${auth#*:} | tail -n +2 |  awk -F ' ' '{print $2}')
    for hst in ${clst_list}
    do
        [[ "${NAME}" = "${hst}" ]] && res=$((res+1))
    done
    return ${res}
}

# Fix host creation error from 5.6.1 with sync methode rsync
function sync_host()
{
    CMD="onehost"
    OPT="sync -f --rsync"
    AUTH=$(get_one_auth)
    res=$(su - oneadmin -c "${CMD} ${OPT} --user ${AUTH%:*} --password ${AUTH#*:}")
    if [[ ${?} -ne 0  ]]
    then
        error "Hosts sync failed"
    else
        echo "Hosts sync OK"
    fi
}

function manage_host()
{
    NAME=${1}
    CMD="onehost"
    IM_MAD='kvm'
    VM_MAD='kvm'
    OPT="create ${NAME} -i ${IM_MAD} -v ${VM_MAD}"
    AUTH=$(get_one_auth)

    check_host ${NAME}
    if [[ ${?} -eq 0 ]]
    then
        res=$(${CMD} ${OPT} --user ${AUTH%:*} --password ${AUTH#*:})
        if [[ ${?} -ne 0 ]]
        then
            error "Host creation failed"
        else
            echo "Host ${NAME} created"
        fi
    else
        echo "Host ${NAME} already exist"
    fi
}

function get_cluster_id_by_name()
{
    name=${1}
    cmd="onecluster"
    opt="show ${name}"
    opt="list -l ID,NAME -f NAME=${name} --csv"


    res=$(${cmd} ${opt} --user ${AUTH%:*} --password ${AUTH#*:} | awk -F ',' '/^[0-9]/ { print $1 }')
    if [[ ${?} -eq 0 ]]
    then
        echo ${res#*:}
        return 0
    else
        echo ""
        return 1
    fi
}

#
# Get Host ID by a name
#
function get_host_id_by_name()
{
    name=${1}
    cmd="onehost"
    opt="show ${name}"

    res=$(${cmd} ${opt} --user ${AUTH%:*} --password ${AUTH#*:} | grep "ID.*:")
    if [[ ${?} -eq 0 ]]
    then
        echo ${res#*:}
        return 0
    else
        echo ""
        return 1
    fi
}

#
# Get Datastore ID by a name
#
function get_ds_id_by_name()
{
    name=${1}
    cmd="onedatastore"
    opt="show ${name}"

    res=$(${cmd} ${opt} --user ${AUTH%:*} --password ${AUTH#*:} | grep "ID.*:")
    if [[ ${?} -eq 0 ]]
    then
        echo ${res#*:}
        return 0
    else
        echo "ERR"
        return 1
    fi
}

#
# check_host_in_cluster
# if host is attached to cluster  : return 0
# if host not attached to cluster : return 1
#
function check_host_in_cluster()
{
    hst=${1}
    clst=${2}
    auth=$(get_one_auth)
    cmd="onehost"
    opt="show ${hst} --user ${AUTH%:*} --password ${AUTH#*:}"

    RES=$(${cmd} ${opt} | grep CLUSTER)
    cluster=${RES#*:}
    # clean Outpu
    cluster="${cluster#"${cluster%%[![:space:]]*}"}"   # remove leading whitespace characters
    cluster="${cluster%"${cluster##*[![:space:]]}"}"   # remove trailing whitespace characters
    if [[ "${cluster}" = "${clst}" ]]
    then
        return 0
    else
        return 1
    fi
}

#
# Attach a host to a cluster
#
function attach_host()
{
    HOST=${1}
    CLST=${2}
    # ref https://dev-eole.ac-dijon.fr/issues/16797
    #CLST_ID=$(get_cluster_id_by_name ${CLST})
    CLST_ID=0
    HST_ID=$(get_host_id_by_name ${HOST})
    AUTH=$(get_one_auth)
    CMD="onecluster"
    OPT="addhost ${CLST_ID} ${HST_ID}"

    check_host_in_cluster ${HOST} ${CLST}
    if [[ ${?} -eq 1 ]]
    then
        if [[ -n ${CLST_ID} ]]
        then
            if [[ -n ${HST_ID} ]]
            then
                RES=$(${CMD} ${OPT} --user ${AUTH%:*} --password ${AUTH#*:})
                if [[ ${?} -ne 0 ]]
                then
                    error "Attaching ${HOST} to ${CLST} failed"
                else
                    echo "${HOST} attached to ${CLST}"
                    return 0
                fi
            else
                error "No host id for ${HOST}"
            fi
        else
            error "No Cluster id for ${CLST}"
        fi
    else
        echo "Host ${HOST} already present in cluster ${CLST}"
    fi
    return 0
}

#
# Attach a datastore to a cluster
#
# ref https://dev-eole.ac-dijon.fr/issues/16797
#function attach_ds_to_cluster()
#{
#    DS=${1}
#    CLST=${2}
#    CLST_ID=$(get_cluster_id_by_name ${CLST})
#    DS_ID=$(get_ds_id_by_name ${ds_name})
#    AUTH=$(get_one_auth)
#    CMD="onecluster"
#    OPT="adddatastore ${CLST_ID} ${DS_ID}"
#
#    RES=$(${CMD} ${OPT} --user ${AUTH%:*} --password ${AUTH#*:})
#    if [[ ${?} -ne 0 ]]
#    then
#        error "Attaching ${DS} to ${CLST} failed."
#    else
#        echo "Datastore ${DS} attached to ${CLST}."
#        return 0
#    fi
#    return 0
#}

function create_datastore()
{
    ds_type="${1}"
    ds_name="${2}"
    # ref https://dev-eole.ac-dijon.fr/issues/16797
    #ds_cluster="${3}"

    if [[ $(CreoleGet activer_multinode 2>&1) == 'oui' ]]
    then
      SYS_TM_MAD='ssh'
      ISO_TM_MAD='ssh'
      IMG_TM_MAD='ssh'
    else
      SYS_TM_MAD='shared'
      ISO_TM_MAD='shared'
      IMG_TM_MAD='qcow2'
    fi

    echo "Creating datastore ${ds_name}"
    TMPL_FILE=$(mktemp)
    case ${ds_type} in
        "SYSTEM")
            cat <<__EOF__ > ${TMPL_FILE}
NAME    = ${ds_name}
TM_MAD  = ${SYS_TM_MAD}
TYPE    = SYSTEM_DS
__EOF__
        ;;
        "ISO")
            cat <<__EOF__ > ${TMPL_FILE}
NAME   = ${ds_name}
DS_MAD =  fs
TM_MAD =  ${ISO_TM_MAD}
TYPE   =  IMAGE_DS
__EOF__
        ;;
        "IMAGE")
            cat <<__EOF__ > ${TMPL_FILE}
NAME   = ${ds_name}
DS_MAD = fs
TM_MAD = ${ISO_TM_MAD}
TYPE   = IMAGE_DS
__EOF__
        ;;

        *) echo "Nothing to do with ${ds_type}"
        ;;
    esac

    auth=$(get_one_auth)
    cmd="onedatastore"
    opt="create --user ${AUTH%:*} --password ${AUTH#*:} ${TMPL_FILE}"
    RUN=$(${cmd} ${opt})
    if [[ ${?} -eq 0 ]]
    then
        # ref https://dev-eole.ac-dijon.fr/issues/16797
        #attach_ds_to_cluster ${ds_name} ${ds_cluster}
        rm ${TMPL_FILE}
        return 0
    else
        return 1
    fi
}

function update_datastore()
{
  local auth=${1}
  local ds_id=${2}
  local cmd="onedatastore"
  local opt="show"
  local multinode=$(CreoleGet activer_multinode 2>&1)
  ds_type=""
  ds_mad=""
  ds_name=""

  TMPL_FILE=$(mktemp)

  if [[ ${multinode}  == 'oui' ]]
  then
    SYS_TM_MAD='ssh'
    ISO_TM_MAD='ssh'
    IMG_TM_MAD='ssh'
  else
    SYS_TM_MAD='shared'
    ISO_TM_MAD='shared'
    IMG_TM_MAD='qcow2'
  fi

  out=$(${cmd} ${opt} ${ds_id} --user ${auth%:*} --password ${auth#*:} | \
        awk -F ':' '/^DATASTORE.*INFORMATION/,/DATASTORE CAPACITY/ {gsub(" |\t",""); print $1 ":" $2 " " }')
  for line in ${out}
  do
    [[ ${line} =~ ^TM_MAD ]] && ds_mad=${line#*:}
    [[ ${line} =~ ^NAME ]] && ds_name=${line#*:}
    [[ ${line} =~ ^TYPE ]] && ds_type=${line#*:}
  done

  if [[ ${ds_name} == "$(CreoleGet one_ds_system_prefix 2>&1)$(CreoleGet one_cluster_name 2>&1)" ]]
  then
    cat <<__EOF__ > ${TMPL_FILE}
NAME   = ${ds_name}
TM_MAD  = ${SYS_TM_MAD}
TYPE    = SYSTEM_DS
__EOF__
  elif [[ ${ds_name} == "$(CreoleGet one_ds_iso_name 2>&1)" ]]
  then
    cat <<__EOF__ > ${TMPL_FILE}
NAME   = ${ds_name}
DS_MAD =  fs
TM_MAD =  ${ISO_TM_MAD}
TYPE   =  IMAGE_DS
__EOF__
  elif [[ ${ds_name} == "$(CreoleGet one_ds_image_name 2>&1)" ]]
  then
    cat <<__EOF__ > ${TMPL_FILE}
NAME   = ${ds_name}
DS_MAD = fs
TM_MAD = ${ISO_TM_MAD}
TYPE   = IMAGE_DS
__EOF__
  else
    echo "Nothing to do with ${ds_name}"
  fi

  if [[ -s ${TMPL_FILE} ]]
  then
      echo "Updating ${ds_name} datastore"
      opt="update ${ds_id} --user ${AUTH%:*} --password ${AUTH#*:} ${TMPL_FILE}"
      RUN=$(${cmd} ${opt})
      rm ${TMPL_FILE}
      return ${?}
  else
      rm ${TMPL_FILE}
      return 1
  fi
}

function manage_datastores()
{
    # ref https://dev-eole.ac-dijon.fr/issues/16797
    #cluster=${1}
    AUTH=$(get_one_auth)

    # ref https://dev-eole.ac-dijon.fr/issues/16797
    #SYSTEM_DS="$(CreoleGet 'one_ds_system_prefix')${cluster}"
    SYSTEM_DS="$(CreoleGet 'one_ds_system_prefix')default"
    ISO_DS=$(CreoleGet 'one_ds_iso_name')
    IMAGE_DS=$(CreoleGet 'one_ds_image_name')

    echo "Configuring datastores for Cluster"
    sid=$(get_ds_id_by_name ${SYSTEM_DS})
    if [[ ${sid} = "ERR" ]]
    then
      # ref https://dev-eole.ac-dijon.fr/issues/16797
      #create_datastore "SYSTEM" "${SYSTEM_DS}" "${cluster}"
      create_datastore "SYSTEM" "${SYSTEM_DS}"
    else
      update_datastore ${AUTH} ${sid}
    fi

    imgid=$(get_ds_id_by_name ${IMAGE_DS})
    if [[ ${imgid} = "ERR" ]]
    then
      # ref https://dev-eole.ac-dijon.fr/issues/16797
      #create_datastore "IMAGE" "${IMAGE_DS}" "${cluster}"
      create_datastore "IMAGE" "${IMAGE_DS}"
    else
      update_datastore ${AUTH} ${imgid}
    fi

    isoid=$(get_ds_id_by_name ${ISO_DS})
    if [[ ${isoid} = "ERR" ]]
    then
      # ref https://dev-eole.ac-dijon.fr/issues/16797
      #create_datastore "ISO" "${ISO_DS}" "${cluster}"
      create_datastore "ISO" "${ISO_DS}"
    else
      update_datastore ${AUTH} ${isoid}
    fi
    return 0
}

function init_ha() {
    # server with index 1 exists if already instanciate
    onezone show 0 | grep -A 3 ^"HA & FEDERATION SYNC STATUS" | tail -n 1 | grep -q ^" 1 "
    if [ ! $? = 0 ]; then
        FOLLOWER=$(CreoleGet one_nodes)
        for follower in $FOLLOWER; do
            onezone server-add 0 --name $follower --rpc http://$follower:2633/RPC2
        done
    fi
}

function main()
{
    wait_true_retcode "Wait for oned to be started" "onecluster show 0 > /dev/null"
    if [ "$(CreoleGet activer_one_ha)" = "oui" ] && [ "$(CreoleGet one_ha_server_index)" = "0" ]; then
        init_ha
    fi
    #
    # Rename default cluster
    clst_name=$(CreoleGet one_cluster_name)
    rename_default_cluster "${clst_name}"

    # Wait 4 seconds for service (ref #16848)
    sleep 4

    #
    # Creating Host
    #
    if [[ $(CreoleGet eole_module non) != 'hapy-master' ]]
    then
        host=$(CreoleGet nom_machine)
        manage_host ${host}
    fi

    #
    # Attaching Host to the Cluster
    #
    attach_host ${host} "${clst_name}"

    #
    # Force host synchronisation
    #
    sync_host

    #
    # Création des Datastores
    #
    manage_datastores "${clst_name}"
}

main