Backup/Backup_OpenStack_Vms_And_Volumes.sh
nono 0f87d1c896 Actualiser Backup_OpenStack_Vms_And_Volumes.sh
Ajout de la gestion de la réplication inter-région
2024-02-07 08:42:58 +00:00

497 lines
No EOL
19 KiB
Bash

#!/usr/bin/env bash
#source openrc.sh
#export OS_AUTH_TYPE=v3applicationcredential
#export OS_AUTH_URL=https://auth.cloud.ovh.net/
#export OS_IDENTITY_API_VERSION=3
#export OS_INTERFACE=public
#export OS_REGION_NAME="GRA11"
#export OS_APPLICATION_CREDENTIAL_ID=
#export OS_APPLICATION_CREDENTIAL_SECRET=
#export PROJECT_ID=
#Daily Retention (Nb of months)
#export DAILY_RETENTION=20
#Monthly Retention (Nb of months)
# 0 = disable monthly backup
#export MONTHLY_RETENTION=12
# DAY OF MOUNTH TO EXECUTE MONTHLY BACKUP
# 01 ... 30 31
#export DAY_MONTHLY_BACKUP=01
#Yearly Retention (Nb of year)
# 0 = disable Yearly backup
#export YEARLY_RETENTION=0
# DAY OF MOUNTH TO EXECUTE YEARLY BACKUP
# 01 ... 30 31
#export DAY_OF_YEARLY_BACKUP=01
# MOUNTH TO EXECUTE YEARLY BACKUP
# 01:january... 12:December
#export MONTH_OF_YEARLY_BACKUP=01
# BACKUP_REPLICATE_REGION
# "" = disable replication
#export BCK_REPLICATE_REGION=""
#export BCK_RCLONE_SRC_ALIAS=""
#export BCK_RCLONE_DST_ALIAS=""
export BCK_REPLICATE_TMP_DIR=/opt/backup/tmp
# Number of backup instances to keep
export MAX_KEEP_BACKUP_INSTANCES=100
#Set TimeZone
#export TZ=Europe/Paris
ORIGIN_REGION=${OS_REGION_NAME}
TODAY=$(date +"%Y-%m-%d_%HH%M")
DAY_OF_MONTH=$(date +"%d")
MONTH_OF_YEAR=$(date +"%m")
#Set Binary
OPENSTACK=/usr/local/bin/openstack
JQ=jq
RCLONE=rclone
GREP=grep
SORT=sort
#Delay to wait and to check the end of backup
CHECK_BACKUP_DELAY=3600
CHECK_FREQUENCY=300
#Init Variables
BCK_VOLUMES_LIST=()
BCK_INSTANCES_LIST=()
PREFIX=Daily
if [ "${DAY_OF_MONTH}" = "${DAY_MONTHLY_BACKUP}" ] && [ "${MONTHLY_RETENTION}" != "0" ]; then
PREFIX=Monthly
fi
if [ "${DAY_OF_MONTH}" = "${DAY_OF_YEARLY_BACKUP}" ] && [ "${MONTH_OF_YEAR}" = "${MONTH_OF_YEARLY_BACKUP}" ] && [ "${YEARLY_RETENTION}" != "0" ]; then
PREFIX=Yearly
fi
EXIT=0
function check_prerequistes(){
echo ""
_info "================================================================================"
_info " - checking prerequisites"
_info "================================================================================"
_info " ---> Show OpenStack Version"
${OPENSTACK} --version
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> with openstack client"
${OPENSTACK} --version 2>&1
exit $retVal
fi
_info " ---> Show jq version"
${JQ} --version
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> with jq"
${JQ} --version 2>&1
exit $retVal
fi
_info " ---> Show rclone version"
${RCLONE} --version
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> with rclone"
${RCLONE} --version 2>&1
exit $retVal
fi
_info " ---> Show grep version"
${GREP} --version
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> with grep"
${GREP} --version 2>&1
exit $retVal
fi
_info " ---> Show sort version"
${SORT} --version
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> with sort"
${SORT} --version 2>&1
exit $retVal
fi
}
function backup(){
echo""
_info "================================================================================"
_info " - Starting Backup of instances and volumes"
_info "================================================================================"
_info_blue " ---> Listing instance(s) to be backed up"
SERVERS=$(${OPENSTACK} server list -f json| ${JQ} -r '.[].Name')
echo $SERVERS;
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> Listing servers"
${OPENSTACK} server list -f json| ${JQ} -r '.[].Name' 2>&1
exit $retVal
fi
if [[ -z "$SERVERS" ]]; then
_warning " ---> No instance found ! Exit"
echo $SERVERS
exit 0
fi
_info " ---> Instance(s) found"
for SERVER in $SERVERS
do
SNAPSHOT_SERVER=${SERVER}_${TODAY}
_info_blue " ------> [Instance : ${SERVER}] === === Launching the backup === ==="
_info " ------> [Instance : ${SERVER}] ---> Listing of volumes attached"
VOLUMES_ATTACHED=$(${OPENSTACK} server volume list ${SERVER} -f json | ${JQ} -r '.[]."Volume ID"')
retVal=$?
if [ $retVal -ne 0 ]; then
_err " ---> Listing volumes"
${OPENSTACK} server volume list ${SERVER} -f json | ${JQ} -r '.[]."Volume ID"' 2>&1
EXIT=$retVal
fi
if [[ -n "$VOLUMES_ATTACHED" ]]; then
_info " ------> [Instance : ${SERVER}] ------> Attached volume(s) Found"
for VOLUME_ATTACHED_ID in $VOLUMES_ATTACHED
do
VOLUME_ATTACHED_NAME=$(${OPENSTACK} volume show ${VOLUME_ATTACHED_ID} -f json | ${JQ} -r '.name')
BCK_VOLUME_ATTACHED_NAME=${PREFIX}_${VOLUME_ATTACHED_NAME}_${TODAY}
_info_action " ------> [Instance : ${SERVER}] ------> Launching the backup of the volume ${VOLUME_ATTACHED_NAME} to ${BCK_VOLUME_ATTACHED_NAME}"
BCK_VOLUMES_LIST+=(${PREFIX}_${VOLUME_ATTACHED_NAME})
${OPENSTACK} volume backup create --name ${BCK_VOLUME_ATTACHED_NAME} ${VOLUME_ATTACHED_NAME} --force
done
else
_info " ------> [Instance : ${SERVER}] ------> No volumes attached"
${OPENSTACK} server volume list ${SERVER} -f json | ${JQ} -r '.[]."Volume ID"' 2>&1
fi
BCK_SERVER=${PREFIX}_${SERVER}_${TODAY}
_info_action " ------> [Instance : ${SERVER}] ---> Launching the Snapshot of the instance ${SERVER} to ${BCK_SERVER}"
BCK_INSTANCES_LIST+=(${PREFIX}_${SERVER})
${OPENSTACK} server backup create --rotate ${MAX_KEEP_BACKUP_INSTANCES} --name ${BCK_SERVER} ${SERVER}
_info_blue " ------> [Instance : ${SERVER}] === === End of the backup === ==="
done
}
function replicate_backup(){
echo ""
_info "================================================================================"
_info " - Start Backup Replication"
_info "================================================================================"
echo ""
_info " => Starting Backup Instance Replication"
for BCK_INSTANCE in "${BCK_INSTANCES_LIST[@]}"
do
BCK_INSTANCE_TODAY=${BCK_INSTANCE}_${TODAY}
export OS_REGION_NAME=${ORIGIN_REGION}
_info_action " Local recording backup Instance ${BCK_INSTANCE_TODAY}"
BCK_INSTANCE_ID=$(${OPENSTACK} image show ${BCK_INSTANCE_TODAY} -c id -f value)
${OPENSTACK} image save --file ${BCK_REPLICATE_TMP_DIR}/${BCK_INSTANCE_TODAY}.qcow ${BCK_INSTANCE_ID}
export OS_REGION_NAME=${BCK_REPLICATE_REGION}
_info_action " Replicating backup Instance ${BCK_INSTANCE_TODAY}"
${OPENSTACK} image create --disk-format qcow2 --container-format bare --file ${BCK_REPLICATE_TMP_DIR}/${BCK_INSTANCE_TODAY}.qcow ${BCK_INSTANCE_TODAY}
_info_action "Remove local image ${BCK_REPLICATE_TMP_DIR}/${BCK_INSTANCE_TODAY}.qcow"
rm ${BCK_REPLICATE_TMP_DIR}/${BCK_INSTANCE_TODAY}.qcow
_info_action " Backup Replication of ${BCK_INSTANCE_TODAY} is OK"
done
export OS_REGION_NAME=${ORIGIN_REGION}
echo ""
_info " => Starting Backup Volume Replication"
_info_action " Syncing S3 volumebackups"
${RCLONE} sync --fast-list --transfers=30 --checkers=12 ${BCK_RCLONE_SRC_ALIAS}:volumebackups/ ${BCK_RCLONE_DST_ALIAS}:volumebackups/
for BCK_VOLUME in "${BCK_VOLUMES_LIST[@]}"
do
BCK_VOLUME_TODAY=${BCK_VOLUME}_${TODAY}
export OS_REGION_NAME=${ORIGIN_REGION}
_info_action " Exporting Metadata for backup volume ${BCK_VOLUME_TODAY}"
BCK_VOLUME_ID=$(${OPENSTACK} volume backup list --name ${BCK_VOLUME_TODAY} -c ID -f value)
BCK_VOLUME_JSON_EXPORT=$(${OPENSTACK} volume backup record export -f json ${BCK_VOLUME_ID})
BCK_VOLUME_EXPORT_SVC=$(echo $BCK_VOLUME_JSON_EXPORT | ${JQ} -r '.backup_service')
BCK_VOLUME_EXPORT_URL=$(echo $BCK_VOLUME_JSON_EXPORT | ${JQ} -r '.backup_url')
export OS_REGION_NAME=${BCK_REPLICATE_REGION}
_info_action " Importing Metadata for backup volume ${BCK_VOLUME_TODAY}"
${OPENSTACK} volume backup record import ${BCK_VOLUME_EXPORT_SVC} ${BCK_VOLUME_EXPORT_URL}
done
export OS_REGION_NAME=${ORIGIN_REGION}
}
function check_backup(){
echo ""
_info "================================================================================"
_info " - Confirm that's all backup is OK"
_info "================================================================================"
MAXIMUM_TIMESTAMP=`date -d '+'${CHECK_BACKUP_DELAY}' seconds' '+%s'`
echo ""
_info " => Checking the backup of volumes"
for BCK_VOLUME in "${BCK_VOLUMES_LIST[@]}"
do
BCK_VOLUME_TODAY=${BCK_VOLUME}_${TODAY}
RESULT=false
while [ ! "$RESULT" = "true" ];
do
_info " Checking Backup for ${BCK_VOLUME_TODAY} and waiting ${CHECK_FREQUENCY} secondes"
CURRENT_TIMESTAMP=`date +%s`
if [ "$CURRENT_TIMESTAMP" -gt "$MAXIMUM_TIMESTAMP" ]; then
_err " Backup for ${BCK_VOLUME_TODAY} verification time expired"
exit -1
fi
RESULT=$(${OPENSTACK} volume backup list -f json | ${JQ} -c '.[] | select(.Name | contains("'${BCK_VOLUME_TODAY}'")) | .Status == "available" ')
sleep ${CHECK_FREQUENCY}
done
_info_action " Backup Volume ${BCK_VOLUME_TODAY} is OK"
done
echo ""
_info " => Checking Backup Instance"
for BCK_INSTANCE in "${BCK_INSTANCES_LIST[@]}"
do
BCK_INSTANCE_TODAY=${BCK_INSTANCE}_${TODAY}
RESULT=false
while [ ! "$RESULT" = "true" ];
do
_info " Checking Backup for ${BCK_INSTANCE_TODAY} and waiting 60 secondes"
CURRENT_TIMESTAMP=`date +%s`
if [ "$CURRENT_TIMESTAMP" -gt "$MAXIMUM_TIMESTAMP" ]; then
_err " Backup for ${BCK_INSTANCE_TODAY} verification time expired"
exit -1
fi
RESULT=`${OPENSTACK} image show ${BCK_INSTANCE_TODAY} -f json | ${JQ} -r '.properties.image_state == "available" and .status == "active"'`
sleep 60
done
_info_action " Backup Instance ${BCK_INSTANCE_TODAY} is OK"
done
}
function manage_retention(){
echo ""
_info "================================================================================"
_info " - Manage Backup Retention"
_info "================================================================================"
echo ""
_info " ====> Manage Retention for Backup Volumes <===="
ALL_BCK_VOLUMES=$(${OPENSTACK} volume backup list -f json)
for BCK_VOLUME in "${BCK_VOLUMES_LIST[@]}"
do
_info " ---> Manage Daily Backup Volume ${BCK_VOLUME} retention : Keep last ${DAILY_RETENTION} Days"
_info " ---> List Backup Volume(s) :"
echo ${ALL_BCK_VOLUMES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_VOLUME} | ${SORT} -r
OLD_DAILY_VOLUMES=$(echo ${ALL_BCK_VOLUMES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_VOLUME} | ${SORT} -r | sed "1,${DAILY_RETENTION}d" | ${GREP} "^Daily")
if [ "${OLD_DAILY_VOLUMES}" != "0" ]; then
_info_blue " ------> Daily Backup Volume(s) to be removed Found"
for OLD_DAILY_VOLUME in $OLD_DAILY_VOLUMES
do
_info_action " ---------> Remove Daily Backup Volume ${OLD_DAILY_VOLUME}"
${OPENSTACK} volume backup delete ${OLD_DAILY_VOLUME}
done
else
_info_blue " ------> No Old Daily Backup Volume found"
fi
if [ "${MONTHLY_RETENTION}" != "0" ]; then
_info " ---> Manage Monthly Backup Volume ${BCK_VOLUME} retention : Keep last ${MONTHLY_RETENTION} Months"
echo ${ALL_BCK_VOLUMES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_VOLUME} | ${SORT} -r | ${GREP} "^Monthly"
OLD_MONTHLY_VOLUMES=$(echo ${ALL_BCK_VOLUMES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_VOLUME} | ${SORT} -r | ${GREP} "^Monthly" | sed "1,${MONTHLY_RETENTION}d")
if [ ! -z "$OLD_MONTHLY_VOLUMES" ]; then
_info_blue " ------> Monthly Backup Volume(s) to be removed Found"
for OLD_MONTHLY_VOLUME in $OLD_MONTHLY_VOLUMES
do
_info_action " ---------> Remove Monthly Backup Volume ${OLD_MONTHLY_VOLUME}"
${OPENSTACK} volume backup delete ${OLD_MONTHLY_VOLUME}
done
else
_info_blue " ------> No Old Monthly Backup Volume found"
fi
else
_info_blue " ------> Monthly Backup disabled"
fi
if [ "${YEARLY_RETENTION}" != "0" ]; then
_info " ---> Manage Yearly Backup Volume ${BCK_VOLUME} retention : Keep last ${YEARLY_RETENTION} Months"
echo ${ALL_BCK_VOLUMES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_VOLUME} | ${SORT} -r | ${GREP} "^Yearly"
OLD_YEARLY_VOLUMES=$(echo ${ALL_BCK_VOLUMES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_VOLUME} | ${SORT} -r | ${GREP} "^Yearly" | sed "1,${YEARLY_RETENTION}d")
if [ ! -z "$OLD_YEARLY_VOLUMES" ]; then
_info_blue " ------> Yearly Backup Volume(s) to be removed Found"
for OLD_YEARLY_VOLUME in $OLD_YEARLY_VOLUMES
do
_info_action " ---------> Remove Yearly Backup Volume ${OLD_YEARLY_VOLUME}"
${OPENSTACK} volume backup delete ${OLD_YEARLY_VOLUME}
done
else
_info_blue " ------> No Old Yearly Backup Volume found"
fi
else
_info_blue " ------> Yearly Backup disabled"
fi
done
echo ""
_info " ====> Manage Retention for Backup Instances <===="
ALL_IMAGES=$(${OPENSTACK} image list -f json)
for BCK_INSTANCE in "${BCK_INSTANCES_LIST[@]}"
do
_info " ---> Manage Daily Backup Instance ${BCK_INSTANCE} retention : Keep last ${DAILY_RETENTION} Days"
_info " ---> List Backup Instance(s) :"
echo $ALL_IMAGES | ${JQ} -r '.[].Name' | ${GREP} ${BCK_INSTANCE} | ${SORT} -r
OLD_DAILY_INSTANCES=$(echo ${ALL_IMAGES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_INSTANCE} | ${SORT} -r | sed "1,${DAILY_RETENTION}d" | ${GREP} "^Daily")
if [ ! -z "$OLD_DAILY_INSTANCES" ]; then
_info_blue " ---> Backup Instance(s) to be removed Found"
for OLD_DAILY_INSTANCE in $OLD_DAILY_INSTANCES
do
_info_action " ------> Remove Backup Instance ${OLD_DAILY_INSTANCE}"
${OPENSTACK} image delete ${OLD_DAILY_INSTANCE}
done
else
_info_blue " ------> No Old Daily Backup Instance found"
fi
if [ "${MONTHLY_RETENTION}" != "0" ]; then
_info " ---> Manage Monthly Backup Instance ${BCK_INSTANCE} retention : Keep last ${MONTHLY_RETENTION} Months"
echo ${ALL_IMAGES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_INSTANCE} | ${SORT} -r | ${GREP} "^Monthly"
OLD_MONTHLY_INSTANCES=$(echo ${ALL_IMAGES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_INSTANCE} | ${SORT} -r | ${GREP} "^Monthly" | sed "1,${MONTHLY_RETENTION}d")
if [ ! -z "$OLD_MONTHLY_INSTANCES" ]; then
_info_blue " ------> Monthly Backup Instance(s) to be removed Found"
for OLD_MONTHLY_INSTANCE in $OLD_MONTHLY_INSTANCES
do
_info_action " ---------> Remove Monthly Instance ${OLD_MONTHLY_INSTANCE}"
${OPENSTACK} image delete ${OLD_MONTHLY_INSTANCE}
done
else
_info_blue " ------> No Old Monthly Backup Instance found"
fi
else
_info_blue " ------> Monthly Backup disabled"
fi
if [ "${YEARLY_RETENTION}" != "0" ]; then
_info " ---> Manage Yearly Backup Instance ${BCK_INSTANCE} retention : Keep last ${YEARLY_RETENTION} Months"
echo ${ALL_IMAGES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_INSTANCE} | ${SORT} -r | ${GREP} "^Yearly"
OLD_YEARLY_INSTANCES=$(echo ${ALL_IMAGES} | ${JQ} -r '.[].Name' | ${GREP} ${BCK_INSTANCE} | ${SORT} -r | ${GREP} "^Yearly" | sed "1,${YEARLY_RETENTION}d")
if [ ! -z "$OLD_YEARLY_INSTANCES" ]; then
_info_blue " ------> Yearly Backup Instance(s) to be removed Found"
for OLD_YEARLY_INSTANCE in $OLD_YEARLY_INSTANCES
do
_info_action " ---------> Remove Yearly Instance ${OLD_YEARLY_INSTANCE}"
${OPENSTACK} image delete ${OLD_YEARLY_INSTANCE}
done
else
_info_blue " ------> No Old Yearly Backup Instance found"
fi
else
_info_blue " ------> Monthly Yearly disabled"
fi
done
}
function job_details(){
_info_blue "#######################################################################################"
_info_blue "Starting Backup Job "
PJT_DESC=$(${OPENSTACK} project show ${PROJECT_ID} -f json | ${JQ} -r '.description')
_info_blue " ---> Project Description : ${PJT_DESC}"
_info_blue " ---> Region : ${OS_REGION_NAME}"
if [ ! -z "$OS_USERNAME" ]; then
_info_blue " ---> User Id: ${OS_USERNAME}"
fi
if [ ! -z "$OS_APPLICATION_CREDENTIAL_ID" ]; then
_info_blue " ---> Application Role Id : ${OS_APPLICATION_CREDENTIAL_ID}"
fi
_info_blue " ---> Retention Details"
_info_blue " --> Daily Retention : ${DAILY_RETENTION} Day(s)"
if [ "${MONTHLY_RETENTION}" != "0" ]; then
_info_blue " --> Monthly Retention : ${MONTHLY_RETENTION} Month(s)"
else
_info_blue " --> Monthly Retention : Disabled"
fi
if [ "${YEARLY_RETENTION}" != "0" ]; then
_info_blue " --> Yearly Retention : ${YEARLY_RETENTION} Year(s)"
else
_info_blue " --> Yearly Retention : Disabled"
fi
_info_blue "#######################################################################################"
}
function _info() {
echo -e "\e[92m$(date +"[%Y-%m-%d_%HH%M] [INFO]") ${1}\e[0m"
}
function _info_blue() {
echo -e "\e[38;5;33m$(date +"[%Y-%m-%d_%HH%M] [INFO]") ${1}\e[0m"
}
function _info_action() {
echo -e "\e[38;5;129m$(date +"[%Y-%m-%d_%HH%M] [INFO]") ${1}\e[0m"
}
function _err(){
echo -e "\e[38;5;196m$(date +"[%Y-%m-%d_%HH%M] [ERROR]") ${1}\e[0m"
}
function _warning(){
echo -e "\e[38;5;214m$(date +"[%Y-%m-%d_%HH%M] [WARNING]") ${1}\e[0m"
}
function main() {
job_details
check_prerequistes
backup
check_backup
manage_retention
if [ -n "$BCK_REPLICATE_REGION" ]; then
replicate_backup
export OS_REGION_NAME=${BCK_REPLICATE_REGION}
manage_retention
export OS_REGION_NAME=${ORIGIN_REGION}
fi
}
main "$@"
exit ${EXIT}