Philippe Caseiro
78a27b4fdd
Ajouter la possibilité de créer une grappe haute disponibilité entre plusieurs Hâpy (https://docs.opennebula.org/5.6/advanced_components/ha/index.html) Pré-requis : Les datastores doivent être partagés entre tous les Hâpy via NFS ou tout autre système de fichiers accécibles de manière concurrente entre les serveurs (Glusterfs, Ceph, DRBD). Pour faire ce développement nous nous sommes basés sur eole-glusterfs qui permet de créer une grappe glusterfs (https://dev-eole.ac-dijon.fr/projects/eole-glusterfs)
495 lines
11 KiB
Bash
Executable File
495 lines
11 KiB
Bash
Executable File
#!/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}"
|
|
local ha=$(CreoleGet activer_one_ha)
|
|
# ref https://dev-eole.ac-dijon.fr/issues/16797
|
|
#ds_cluster="${3}"
|
|
|
|
if [[ $(CreoleGet activer_multinode 2>&1) == 'oui' ]] && [[ ${ha} == "non" ]]
|
|
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)
|
|
local ha=$(CreoleGet activer_one_ha)
|
|
ds_type=""
|
|
ds_mad=""
|
|
ds_name=""
|
|
|
|
TMPL_FILE=$(mktemp)
|
|
|
|
if [[ ${multinode} == 'oui' ]] && [[ ${ha} == "non" ]]
|
|
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 main()
|
|
{
|
|
wait_true_retcode "Wait for oned to be started" "onecluster show 0 > /dev/null"
|
|
if [ "$(CreoleGet activer_one_ha)" = "oui" ]; then
|
|
if [ "$(CreoleGet one_ha_server_index)" != "0" ]; then
|
|
# ne pas faire sur les followers
|
|
return
|
|
fi
|
|
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 activer_one_ha)" = "oui" ]; then
|
|
if [[ $(CreoleGet eole_module non) != 'hapy-master' ]]
|
|
then
|
|
host=$(CreoleGet nom_machine)
|
|
manage_host ${host}
|
|
fi
|
|
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 $@
|
|
|
|
exit 0
|