#!/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= #Daily Retention (Nb of months) export DAILY_RETENTION=7 #Monthly Retention (Nb of months) # 0 = disable monthly backup export MONTHLY_RETENTION=0 # 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 #Set TimeZone export TZ=Europe/Paris TODAY=$(date +"%Y-%m-%d_%HH%M") DAY_OF_MONTH=$(date +"%d") MONTH_OF_YEAR=$(date +"%m") #Set Binary OPENSTACK=/usr/bin/openstack JQ=jq 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 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+=(${BCK_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+=(${BCK_SERVER}) ${OPENSTACK} server backup create --name ${BCK_SERVER} ${SERVER} _info_blue " ------> [Instance : ${SERVER}] === === End of the backup === ===" done } 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 RESULT=false while [ ! "$RESULT" = "true" ]; do _info " Checking Backup for ${BCK_VOLUME} and waiting ${CHECK_FREQUENCY} secondes" CURRENT_TIMESTAMP=`date +%s` if [ "$CURRENT_TIMESTAMP" -gt "$MAXIMUM_TIMESTAMP" ]; then _err " Backup for ${BCK_VOLUME} verification time expired" exit -1 fi RESULT=$(${OPENSTACK} volume backup list -f json | jq -c '.[] | select(.Name | contains("'${BCK_VOLUME}'")) | .Status == "available"') sleep ${CHECK_FREQUENCY} done _info_action " Backup Volume ${BCK_VOLUME} is OK" done echo "" _info " => Checking Backup Instance" for BCK_INSTANCE in "${BCK_INSTANCES_LIST[@]}" do RESULT=false while [ ! "$RESULT" = "true" ]; do _info " Checking Backup for ${BCK_INSTANCE} and waiting 60 secondes" CURRENT_TIMESTAMP=`date +%s` if [ "$CURRENT_TIMESTAMP" -gt "$MAXIMUM_TIMESTAMP" ]; then _err " Backup for ${BCK_INSTANCE} verification time expired" exit -1 fi RESULT=`${OPENSTACK} image show ${BCK_INSTANCE} -f json | ${JQ} -r '.properties.image_state == "available" and .status == "active"'` sleep 60 done _info_action " Backup Instance ${BCK_INSTANCE} 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 ${OS_TENANT_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 exit check_prerequistes backup check_backup manage_retention } main "$@" exit ${EXIT}