#!/usr/bin/env bash

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_cluster()
{
    name="${1}"
    cmd="onecluster"
    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}
}

function manage_cluster()
{
    NAME="${1}"
    CMD="onecluster create"
    AUTH=$(get_one_auth)

    check_cluster ${clst_name}
    if [[ ${?} -eq 0 ]]
    then
        crt=$(${CMD} --user ${AUTH%:*} --password ${AUTH#*:} ${NAME})
        if [[ ${?} -ne 0 ]]
        then
            error "Cluster create failed"
        else
            echo "Cluster ${NAME} created"
        fi
    else
        echo "Cluster \"${NAME}\" already exist"
    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}
}

function manage_host()
{
    NAME=${1}
    CMD="onehost"
    IM_MAD='kvm'
    VM_MAD='kvm'
    VNET_MAD='ovswitch'
    OPT="create ${NAME} -i ${IM_MAD} -v ${VM_MAD} -n ${VNET_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}
    CLST_ID=$(get_cluster_id_by_name ${CLST})
    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
#
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}"
    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#*:} -c ${ds_cluster} ${TMPL_FILE}"
    opt="create --user ${AUTH%:*} --password ${AUTH#*:} ${TMPL_FILE}"
    RUN=$(${cmd} ${opt})
    if [[ ${?} -eq 0 ]]
    then
        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()
{
    cluster=${1}
    AUTH=$(get_one_auth)

    SYSTEM_DS="$(CreoleGet 'one_ds_system_prefix')${cluster}"
    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
      create_datastore "SYSTEM" "${SYSTEM_DS}" "${cluster}"
    else
      update_datastore ${AUTH} ${sid}
    fi

    imgid=$(get_ds_id_by_name ${IMAGE_DS})
    if [[ ${imgid} = "ERR" ]]
    then
      create_datastore "IMAGE" "${IMAGE_DS}" "${cluster}"
    else
      update_datastore ${AUTH} ${imgid}
    fi

    isoid=$(get_ds_id_by_name ${ISO_DS})
    if [[ ${isoid} = "ERR" ]]
    then
      create_datastore "ISO" "${ISO_DS}" "${cluster}"
    else
      update_datastore ${AUTH} ${isoid}
    fi
    return 0
}

function main()
{
    #
    # Creating Cluster
    #
    clst_name=$(CreoleGet one_cluster_name)
    manage_cluster ${clst_name}

    #
    # Creating Host
    #
    host=$(CreoleGet nom_machine)
    manage_host ${host}

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

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

main