#!/usr/bin/env bash

# Copyright (C) 2013-2018:
# This file is part of Shinken Enterprise, all rights reserved.

# Set default umask to avoid problems when creating Shinken files
umask 0022

source /var/lib/shinken/libexec/libs/shinken_protected_fields.sh

sestatus | grep "SELinux status.*enabled" > /dev/null 2>&1
SELINUX_ENABLED=$?
sanatizeOnExit=0
doRestartDaemonsOnExit=0

function doexit {
    if [[ ${sanatizeOnExit} -eq 1 ]] && [[ "$2" != "no_sanatize" ]]; then
        /var/lib/shinken/libexec/tools/sanatize-data.py -a
    fi
    printf "\n"
    printf "\033[91m $1 \033[0m\n"
    exit 2
}

function display_help {
    printf "shinken-restore [options] [backup dir]\n"
    printf "This tool will restore shinken backup.\n"
    printf "Options:\n"
    printf "  -h,    --help                                 : will display this help\n"
    printf "  -a,    --addons                               : restore addons data\n"
    printf "\n"
    printf "  -c,    --configuration                        : restore configuration data\n"
    printf "         --with-key-backup [hash]               : restore the protected fields key backup as well. You must use the same parameter as in shinken-protected-fields-keyfile-restore.\n"
    printf "\n"
    printf "  -rocd  --restore-only-configuration-database  : restore only the database, no the configuration files\n"
    printf "\n"
    printf "  -e,    --events                               : restore event manager data\n"
    printf "\n"
    printf "  -l,    --log                                  : restore log data\n"
    printf "\n"
    printf "  -m,    --metrology                            : restore metrology data\n"
    printf "\n"
    printf "  -M,    --modules                              : restore all custom modules\n"
    printf "         --module-type [type]                   : restore only this type of module\n"
    printf "  -L,    --list-modules                         : list all custom modules present in this archive\n"
    printf "\n"
    printf "  -s,    --sla                                  : restore SLA data\n"
    printf "\n"
    printf "  -u,    --user                                 : restore user data(hive, etc...)\n"
    printf "         --restore-only-user [user]             : restore only the user data (hive, etc..) for this specific user\n"
    printf "\n"
}

function record_history {

    data_type=$1
    comment=$2
    # We must restore the data_history, and for this we have 2 cases:
    # * backup BEFORE 2.5.0: we do not have a backup context.json, and maybe not even a saveVersion (if so, do not Create the entry at all)
    # * backup AFTER  2.5.0: we have a backup context.json, so just load from it
    if [[ -e "${backupDir}/context/context.json" ]]; then  # >=2.5.0 and configuration is in backup
        shinken-context-manage --import-data-history-from-file="${backupDir}/context/context.json" --data-type "${data_type}" --backup-path="${backupDir}" --comment "${comment}"
    else  # BEFORE 2.5.0, just fake from a version
        # maybe we do not even have a saveVersion file, if so, do not create the entry
        if [[ -e "${backupDir}/saveVersion" ]]; then
            RESTORED_VERSION=$(cat "${backupDir}/saveVersion")
            shinken-context-manage --import-data-history-from-version="${RESTORED_VERSION}" --data-type "${data_type}" --backup-path="${backupDir}" --comment "${comment}"
        else  # No version, cannot create the INSTALLATION/UPDATE entries, only the RESTORE ONE
            shinken-context-manage --import-data-history-no-version --data-type "${data_type}" --backup-path="${backupDir}" --comment "${comment}"
        fi
    fi
}

function get_dashboards_for_user {
    # Returns a list of dashboard ids separated by spaces

    local userUUID="$1"
    mongo shinken --quiet --eval "db.getCollection('hive').find({'owner.uuid':'$userUUID'}).forEach( function (hive) { hive.tiles.forEach( function(tile) { print (tile.screen.uuid);})});"
}

function stop_shinken_before_restore {
    doRestartDaemonsOnExit=1
    if [[ "${shinken_stopped}" == "false" ]]; then
        printf "\n\033[92mStopping Shinken before restoring\033[0m\n"
        /etc/init.d/shinken stop >/dev/null 2>/dev/null
        shinken_stopped="true"
    fi
}

# Try a mongorestore, but look at mongo fail
function restore_mongo_bson {
    mongorestore --drop "$1" >>"$2" 2>>"$2"
    if [[ $? -ne 0 ]]; then
        doexit "Mongodb collection $1 restoration fail. Please look at $2"
    fi
    grep 'ERROR' "$2" >/dev/null
    if [[ $? -ne 1 ]]; then
        doexit "Mongodb collection $1 restoration fail. Please look at $2"
    fi
}

# Simulates "mongorestore --filter" from Mongo 2.6
# Restores a collection backup to a separate collection
# Applies the filter and replace matching documents (and insert missing ones)
function mongorestore__filter {
    local db="$1"
    local path="$2"
    local filter="$3"

    local collection_name=$(basename "$path" .bson)
    local collection_name_restore="${collection_name}_restore"

    mongorestore --db "$db" -c "$collection_name_restore" "$path" 2>>"${logFile}" >>"${logFile}"
    if [[ $? -ne 0 ]]; then
        return $?
    fi

    doc_ids=$(mongo --quiet "$db" --eval \
        "db.getCollection('$collection_name_restore').find($filter).forEach(function (doc) {
            db.getCollection('$collection_name').update({_id:doc._id}, doc, {upsert: true});
            print(doc._id);
        });
        db.getCollection('$collection_name_restore').drop();" 2>>${logFile})

    if [[ $? -ne 0 ]]; then
        return $?
    fi

    echo $doc_ids
}

function restore_tar_gz_archive_to_folder {
    archive_path=$1
    dest_folder=$2
    timestamp=$3

    folder_backup_name="${dest_folder}_before_restore.$now"

    cp -rp ${archive_path} /tmp
    if [[ $? -ne 0 ]]; then
        doexit "Cannot copy configuration archive to /tmp. Please check this directory"
    fi

    cd /tmp
    rm -fr etc
    tar xfz /tmp/$(basename ${archive_path})

    if [[ $? -ne 0 ]]; then
        doexit "Cannot extract /tmp/$(basename ${archive_path}) to /tmp. Please check this directory"
    fi

    # NOTE: we do not delete the destination directory because maybe it's a symbolic link we want to keep
    mkdir ${folder_backup_name} 2>/dev/null
    mv "${dest_folder}/" "${folder_backup_name}/" 2>/dev/null # Maybe the directory do not exist any more

    # Maybe the destination folder do not exists (and is not a link too), if so, recreate it
    if [[ ! -d "$dest_folder" ]] && [[ ! -L "$dest_folder" ]]; then
        mkdir ${dest_folder}
    fi

    if [[ -n "$(ls -A ${dest_folder#/}/)" ]]; then
        mv ${dest_folder#/}/* "${dest_folder}/"
    fi

    if [[ $? -ne 0 ]]; then
        doexit "Cannot restore $dest_folder directory ; the one you had before the restore is stored in $folder_backup_name"
    fi
    chown -R ${KEYFILE_OWNER}:${KEYFILE_GROUP} "${dest_folder}/"
    rm -fr "$folder_backup_name"
}

function list_modules_in_archive {
    moduleTypeAvailable=()
    for f in $(/bin/ls -1 "${backupDir}/modules/"); do
        if [[ -d "${backupDir}/modules/${f}" ]]; then
            moduleTypeAvailable+=("$f")
        fi
    done
}

function move_tree_structure_with_exclude {
    origin_path=$1
    dest_path=$2
    exclude_dirs=$3

    escaped_origin_path=$(echo "${origin_path}" | sed 's/\//\\\//g')

    for file in $(find ${origin_path} | egrep -v "${exclude_dirs}" | sed "s/${escaped_origin_path}//g" | sort -r); do

        if [[ -d "${origin_path}${file}" ]]; then
            rmdir --ignore-fail-on-non-empty "${origin_path}${file}"
        else
            file_path=$(dirname "${dest_path}${file}")
            if [[ ! -d "${file_path}" ]]; then
                mkdir -p "${file_path}"
            fi
            mv "${origin_path}${file}" "${dest_path}${file}"
        fi
    done
}

if [[ "$(id -u)" != "0" ]]; then
    doexit "This script must be run as root" "no_sanatize"
fi

restore_only_user=""
restore_only_configuration_database=""
restoreModuleType=""

sla="0"
configuration="0"
metrology="0"
logs="0"
user="0"
addons="0"
events="0"
restore_only_user=""
modules="0"
moduleType="0"
listModules="0"

mustRestoreSla=0
mustRestoreConfiguration=0
mustRestoreMetrology=0
mustRestoreLogs=0
mustRestoreUser=0
mustRestoreAddons=0
mustRestoreModules=0
mustListModules=0
mustRestoreEvents=0

key_hash_from_cli=""
selectRestore=0

while :
do
    case "$1" in

    -h | --help)
        display_help
        # Call help function no shifting needed here, we're done.
        exit 0
    ;;
    -s | --sla)
        sla="sla"
        selectRestore=1
        shift
    ;;
    -u | --user)
        user="user"
        selectRestore=1
        shift
    ;;
        --restore-only-user)
        if [[ ${user} == "user" ]]; then
            restore_only_user="$2"
        else
            display_help
            doexit "you must use -u/--user option to use --restore-only-user option" "no_sanatize"
        fi
        shift
        shift
    ;;
    -c | --configuration)
        if [[ ${restore_only_configuration_database} == "restore_only_configuration_database" ]]; then
            display_help
            doexit "you can't use -c/--configuration option with option --restore-only-configuration-database" "no_sanatize"
        else
            configuration="configuration"
            selectRestore=1
        fi
        shift
    ;;
    --rocd | --restore-only-configuration-database)
        if [[ ${configuration} == "configuration" ]]; then
            display_help
            doexit "you can't use -c/--configuration option with option --restore-only-configuration-database" "no_sanatize"
        else
            restore_only_configuration_database="restore_only_configuration_database"
            selectRestore=1
        fi
        shift
    ;;
    -m | --metrology)
        metrology="metrology"
        selectRestore=1
        shift
    ;;
    -l | --log)
        logs="logs"
        selectRestore=1
        shift
    ;;
    -a | --addons)
        addons="addons"
        selectRestore=1
        shift
    ;;
    -M | --modules)
        modules="modules"
        selectRestore=1
        shift
    ;;
        --module-type)
        if [[ ${modules} == "modules" ]]; then
            restoreModuleType="$2"
            if [[ -z "${restoreModuleType}" ]]; then
                display_help
                doexit "Please give a module type" "no_sanatize"
            fi
        else
            display_help
            doexit "you must use -M/--modules option to use -t/--module-type option" "no_sanatize"
        fi
        shift
        shift
    ;;
    -L | --list-modules)
        listModules="listModules"
        selectRestore=1
        shift
    ;;
    -e | --events)
        events="events"
        selectSave=1
        shift
    ;;
    --with-key-backup)
        if [[ $# -ge 2 ]]; then
            key_hash_from_cli="$2"
            shift 2
        else
            display_help
            doexit "You must provide the key export with the \033[35m--with-key-backup\033[0m option" "no_sanatize"
            exit 1
        fi
    ;;
    -*)
        display_help
        doexit "Unknown option: $1" "no_sanatize"
        exit 1
    ;;
    *)  # No more options
        backupDir="$1"
        break
    ;;
    esac
done

if [[ ${selectRestore} -eq 1 ]]; then
    if [[ ${sla} == "sla" ]]; then
        mustRestoreSla=1
    fi
    if [[ ${user} == "user" ]]; then
        mustRestoreUser=1
    fi
    if [[ ${configuration} == "configuration" ]] || [[ ${restore_only_configuration_database} == "restore_only_configuration_database" ]]; then
        mustRestoreConfiguration=1
    fi
    if [[ ${metrology} == "metrology" ]]; then
        mustRestoreMetrology=1
    fi
    if [[ ${logs} == "logs" ]]; then
        mustRestoreLogs=1
    fi
    if [[ ${events} == "events" ]]; then
        mustRestoreEvents=1
    fi
    if [[ $addons == "addons" ]]; then
        mustRestoreAddons=1
    fi
    if [[ $modules == "modules" ]]; then
        mustRestoreModules=1
    fi
    if [[ $listModules == "listModules" ]]; then
        mustListModules=1
    fi
else
    mustRestoreSla=1
    mustRestoreConfiguration=1
    mustRestoreMetrology=1
    mustRestoreLogs=1
    mustRestoreUser=1
    mustRestoreAddons=1
    mustRestoreModules=1
    mustRestoreEvents=1
fi

if [[ ${mustRestoreEvents} -eq 1 ]] || [[ ${mustRestoreSla} -eq 1 ]] || [[ ${mustRestoreConfiguration} -eq 1 ]] || [[ ${mustRestoreUser} -eq 1 ]] || [[ ${mustRestoreAddons} -eq 1 ]] || [[ ${mustRestoreMetrology} -eq 1 ]]; then
    mongo --quiet --eval 'db.getMongo().getDBNames()' > /dev/null  2>&1
    if [[ $? -ne 0 ]]; then
       doexit "Cannot join Mongodb. Please check mongo is available." "no_sanatize"
    fi
fi

if [[ ${mustRestoreConfiguration} -eq 0 ]] && [[ -n "${key_hash_from_cli}" ]]; then
    doexit "You can specify a key backup only when you restore a configuration" "no_sanatize"
fi

if [[ -z "${backupDir}" ]]; then
    display_help
    doexit "Missing parameter : path to the backup directory" "no_sanatize"
fi

if [[ ! -d "${backupDir}" ]]; then
    doexit "Directory ${backupDir} does not exist or it is not a directory" "no_sanatize"
fi

# now get full path from here
backupDir=$(readlink -e "${backupDir}")
cd "${backupDir}/"

if [[ ${mustListModules} -eq 1 ]]; then
    # only list modules databases and exit. Do not create backupdir or print it's sucessful !
    list_modules_in_archive

    if [[ ${#moduleTypeAvailable[@]} == 0 ]]; then
        printf "\033[91m \nThere is no custom module in this backup to restore.\n \033[0m\n"
    else
        printf "\nCustom module type available for restore are :\n"
        for moduleType in "${moduleTypeAvailable[@]}"; do
            printf " - $moduleType\n"
        done
        printf "\nTo restore one of theses custom modules, do shinken-restore --modules --module-type <module_type>\n"
    fi
    exit 0
fi

currentVersion=$(sed -ne "s/.*\?\"current_version\" *: *\"\([^\"]*\)\".*/\1/p" /var/lib/shinken/context.json)
if [[ -e saveVersion ]]; then
    backupVersion=$(<saveVersion)
else
    backupVersion="unknown version"
fi

shinken_stopped="false"

printf "\033[92mRestoring from ${backupVersion} to ${currentVersion} \033[0m\n"

## ----------- configuration start -----------
if [[ ${mustRestoreConfiguration} -eq 1 ]]; then
    printf "\033[92m-Restoring Configuration \033[0m\n"
    if [[ ${restore_only_configuration_database} == "restore_only_configuration_database" ]]; then
        printf "\033[92m-Will restore only the database \033[0m\n"
    fi
    # Try to detect the backup structure, can be old or new
    if [[ -d "${backupDir}/configuration" ]]; then
        logFile="${backupDir}/configuration/restore-configuration.log"
        restore_dir="${backupDir}/configuration/dump-configuration"
        src_dir="${backupDir}/configuration"
    else
        logFile="${backupDir}/restore-configuration.log"
        restore_dir="${backupDir}/dump"
        src_dir="${backupDir}"
    fi

    if [[ ! -d "${restore_dir}" ]] && [[ "${backupDir}" == */configuration ]]; then
        printf "\n\033[33mThe backup folder end with configuration : trying with backup dir at parent\033[0m\n"
        logFile="${backupDir}/restore-configuration.log"
        restore_dir="${backupDir}/dump-configuration"
        src_dir="${backupDir}"
    fi

    if [[ -d "${restore_dir}" ]]; then
        spf_check_mongo_connexion "synchronizer"

        #clean old logFile
        printf "" >"$logFile"
        sanatizeOnExit=1

        # First be sure mongodb is start before everything...
        /etc/init.d/mongod start >/dev/null 2>/dev/null

        temp_db="backup_synchronizer_info"

        # Second check the status of protected fields in the backup
        # If the key from the backup exists and has never been saved, display a warning as the key backup could have
        # been made after the data backup

        mongorestore --drop --db "${temp_db}" --collection synchronizer-info "${restore_dir}/synchronizer/synchronizer-info.bson" >>"${logFile}" 2>>"${logFile}"
        encryption_enabled_from_backup_database=$(spf_get_key_activated_from_db_with_database "${temp_db}")
        encryption_enabled_from_backup_config=$(spf_get_key_activated_from_db)
        encryption_enabled_from_actual_database=$(spf_get_key_activated_from_db_with_database "synchronizer")
        no_need_to_restore_keyfile=0
        keyfile_was_saved_from_backup=$(spf_get_key_extracted_from_db_with_database "${temp_db}")
        keyfile_was_saved_from_config=$(spf_get_key_extracted_from_db)
        key_name_from_backup=$(spf_get_key_name_from_db_with_database "${temp_db}")
        key_hash_from_backup=$(spf_get_key_hash_from_db_with_database "${temp_db}")
        keyfile_from_config=$(spf_get_keyfile_name_from_synchronizer_cfg)
        checking_status="$(show_success "NOT ENCRYPTED")"
        if [[ -n "${keyfile_from_config}" ]] && [[ "${encryption_enabled_from_backup_config}" == "true" ]]; then
            checking_status="$(show_success "ENCRYPTED")"
            if [[ "${keyfile_was_saved_from_config}" != "true" ]]; then
                shinken_save_keyfile=/root/$(basename "${keyfile_from_config}")-export-$(date +"%Y-%m-%d__%H-%M-%S")

                if [[ -e "${keyfile_from_config}" ]]; then
                    if [[ "${keyfile_was_saved_from_config}" != "true" ]]; then
                        warning_message="${warning_message}$(show_critical_info "The current key was never exported")\n"
                        warning_message="${warning_message}\t$(show_important_info "I'm exporting it to") $(show_data "${shinken_save_keyfile}")\n"
                        warning_message="${warning_message}\t$(show_important_info "The current key will be replaced by the one from the backup.")\n"
                        warning_message="${warning_message}\t\t=> $(show_critical_info "Remove this file as soon as possible to prevent security holes")\n"
                        _spf_encode_key "$(<${keyfile_from_config})" >"${shinken_save_keyfile}"
                        checking_status="$(show_warning "WARNING")"
                    fi
                fi
            fi
        fi

        printf "Checking encryption status for your current database : ${checking_status}\n\n"
        printf "${warning_message}"

        if [[ "${encryption_enabled_from_backup_database}" == "true" ]]; then
            if [[ -e ${keyfile_from_config} ]]; then
                key_hash_from_config=$(spf_get_key_hash_from_key_file $keyfile_from_config)
            else
                key_hash_from_config=
            fi

            printf "\n\n"
            if [[ -n "${key_hash_from_config}" ]] && [[ "${key_hash_from_config}" == "${key_hash_from_backup}" ]]; then
                printf "\t$(show_important_info "The keyfile used in the backup is the same as the one from the current configuration.")\n"
                no_need_to_restore_keyfile=1
            elif [[ ${keyfile_was_saved_from_backup} == "false" ]] && [[ -z "${key_hash_from_cli}" ]]; then
                printf "\tThe name of the key used in the backup is : $(show_data "${key_name_from_backup}")\n"
                printf "\t$(show_important_info "and it looks like it has never been saved.")\n"
                printf "\t$(show_critical_info "As the key from the backup is not the same as the current one, the restoration process is aborted to prevent possible data loss.")\n\n"
                printf "\tTo restore the configuration from this backup anyway, you can use the option $(show_command_parameter "--with-key-backup HASH") with the $(show_command shinken-restore "") command\n"
                printf "\tto restore the key along with the backup\n\n"
                printf "\tIf you don't have the right key, you can use the following command and follow its instructions:\n"
                printf "\t$(show_command /var/lib/shinken/libexec/tools/shinken-protected-fields-keyfile-rescue-from-backup "${backupDir}")\n\n"

                mongo "${temp_db}" --eval "db.dropDatabase()" >>"${logFile}" 2>>"${logFile}"
                doexit "Restoration aborted to prevent possible data loss." "no_sanatize"
            elif [[ -z "${key_hash_from_cli}" ]]; then
                printf "\n$(show_important_info "The key from the backup was exported")\n"
                printf "$(show_important_info "Its name is :") $(show_data "${key_name_from_backup}")\n"
                printf "\tPlease re-run this command with use the option $(show_command_parameter "--with-key-backup HASH")\n"
                printf "\twith the HASH provided when that key was exported.\n"
                printf "\nIf your key export was lost, you can use the following command and follow its instructions:\n\n"
                printf "\t$(show_command /var/lib/shinken/libexec/tools/shinken-protected-fields-keyfile-rescue-from-backup "${backupDir}")\n"
                mongo "${temp_db}" --eval "db.dropDatabase()" >>"${logFile}" 2>>"${logFile}"
                doexit "Restore aborted : you need to provide the key used in the backup on the command line." "no_sanatize"
            fi

            if [[ -n "${key_hash_from_cli}" ]]; then
                spf_check_consistency_backup_db_with_database "${key_hash_from_cli}" "${temp_db}"
                RC=$?
                if [[ $RC == 1 ]]; then
                    if [[ ${no_need_to_restore_keyfile} == 0 ]]; then
                        printf "\n\n\t$(show_failure "Backup restoration aborted : protected fields consistency check failed")\n"
                        printf "\nIn order to solve this issue, please use the right key export.\n"
                        printf "\nThe key you need to restore is named $(show_data "${key_name_from_backup}")\n"
                        printf "\nIf you don't have the right key, you can use the following command and follow its instructions:\n\n"
                        printf "\t$(show_command /var/lib/shinken/libexec/tools/shinken-protected-fields-keyfile-rescue-from-backup "${backupDir}")\n"
                        mongo "${temp_db}" --eval "db.dropDatabase()" >>"${logFile}" 2>>"${logFile}"
                        doexit "Restore aborted to prevent possible data loss: protected fields consistency check failed" "no_sanatize"
                    else
                        printf "However, the key from your current config matches the one used in the backup so I will use it and ignore the one you provided.\n"
                    fi
                else
                    no_need_to_restore_keyfile=0
                fi
            fi
        fi

        mongo "${temp_db}" --eval "db.dropDatabase()" >>"${logFile}" 2>>"${logFile}"

        # If we restore only the database and the backup is not encrypted, we will restore only if the configuration is not encrypted also.
        if [[ ${restore_only_configuration_database} == "restore_only_configuration_database" ]] && [[ ${encryption_enabled_from_backup_database} == "" ]] && [[ ${encryption_enabled_from_actual_database} == "true" ]]; then
            doexit "Restore aborted : you can't restore a not encrypted database on a encrypted configuration. You can disable encryption with : $(show_command shinken-protected-fields-encryption-disable "")\n" "no_sanatize"
        fi

        stop_shinken_before_restore

        # We are reasonably sure we won't loose any data, so we can proceed with Mongo database restore
        mongo synchronizer --eval "db.dropDatabase()" >>"${logFile}" 2>>"${logFile}"
        # NOTE: find instead of ls -1 because if the file have space, it will for with spaces instead of line return
        # so change split, standard IFS (separator for bash) will fail, so force a \n sperapation here
        OLDIFS=${IFS}
        IFS=$'\n'
        for bson_file in $(/bin/ls -1 "${restore_dir}"/synchronizer/*bson); do
            restore_mongo_bson "${bson_file}" "${logFile}"
        done
        # restore old split method
        IFS=${OLDIFS}

        printf " \033[92m=> Restoring configuration database : DONE\033[0m\n"

        if [[ ${restore_only_configuration_database} == "" ]]; then
            ########## Restore the /etc/shinken directory
            cp -rp "${src_dir}/shinken-etc.tar.gz" /tmp
            if [[ $? -ne 0 ]]; then
                doexit "Cannot copy configuration archive to /tmp. Please check this directory"
            fi

            cd /tmp
            rm -fr etc
            tar xfz /tmp/shinken-etc.tar.gz

            if [[ $? -ne 0 ]]; then
                doexit "Cannot extract /tmp/shinken-etc.tar.gz to /tmp. Please check this directory"
            fi

            keyfile_from_config_backup="$backupDir/$(basename "$keyfile_from_config")"
            if [[ -f "$keyfile_from_config" ]] ; then
                _spf_encode_key "$(<"$keyfile_from_config")" >"$keyfile_from_config_backup"
            fi

            if [[ "${encryption_enabled_from_backup_database}" == "true" ]]; then
                if [[ ${no_need_to_restore_keyfile} == 0 ]]; then
                    ## Check encryption keyfile and hash to avoid as much as possible data loss
                    printf "\n$(show_info "Checking protected fields key :") "
                    checking_status="$(show_success "OK")"
                    warning_message=""
                    # Check that the keyfile name has not changed (there may not be any keyfile in current config)
                    backup_file_activated="$(spf_get_activated_from_synchronizer_cfg_with_file /tmp/etc/shinken/synchronizer.cfg 2>/dev/null)"

                    if [[ "${backup_file_activated}" == "true" ]] ; then
                        keyfile_from_backup="$(spf_get_keyfile_name_from_synchronizer_cfg_with_file /tmp/etc/shinken/synchronizer.cfg 2>/dev/null)"
                    fi

                    hash_from_db=$(spf_get_key_hash_from_db) # This is the one from the backup since the DB war restored
                    # remove the encrypted keyfile.enc from the /tmp/etc
                    encrypted_keyfile_name="$(basename ${keyfile_from_backup}.enc)"
                    encrypted_keyfile_path="/tmp/etc/shinken/${encrypted_keyfile_name}"
                    rm -rf ${encrypted_keyfile_path}

                    printf "${checking_status}\n\n"
                    printf "${warning_message}"
                fi
                printf "$(show_important_info "The backup you are restoring contains a encrypted Synchronizer database.")\n"
            else
                printf " The database in this backup is not encrypted."
            fi

            # If the synchronizer config file activates protected fields encryption in the database, we ask the user to restore the key
            if [[ ${no_need_to_restore_keyfile} == 0 ]] && [[ -z "${key_hash_from_cli}" ]] && [[ "${encryption_enabled_from_backup_database}" == "true" ]]; then
                if [[ "$(spf_get_activated_from_synchronizer_cfg_with_file /tmp/etc/shinken/synchronizer.cfg)" == "true" ]]; then
                    printf "\n$(show_critical_info "If your key was changed after this backup was made, you must restore the  key named") $(show_data "${key_name_from_backup}") $(show_critical_info "from your manual backup using the command")\n"
                    printf "\t$(show_command shinken-protected-fields-keyfile-restore "")\n"
                    printf "$(show_critical_info "before starting the synchronizer")\n"

                    printf "\nIf you don't have the right key, you can use the following command and follow its instructions:\n"
                    printf "\t$(show_command /var/lib/shinken/libexec/tools/shinken-protected-fields-keyfile-rescue-from-backup "${backupDir}")\n"
                    keyfile_to_restore=0
                fi
            elif [[ "${encryption_enabled_from_backup_database}" != "true" ]]; then
                needs_restore_keyfile=0
                if [[ ! -z "${key_hash_from_cli}" ]]; then
                    printf "\n$(show_important_info "The database in your backup was not crypted therefore I won't restore the key export you provided.")\n"
                    printf "$(show_info "If you want to restore it nonetheless, You can use the following command :")\n"
                    printf "\t$(show_command "shinken-protected-fields-keyfile-restore" "${key_hash_from_cli}")\n\n"
                fi
            elif [[ ${no_need_to_restore_keyfile} == 0 ]]; then
                needs_restore_keyfile=1
            fi
            # End of check

            now="$(date +%s)"
            before_restore="/etc/shinken.before_restore.${now}"
            # NOTE: we do not delete the destination directory because maybe it's a symbolic link we want to keep
            mkdir "${before_restore}" 2>/dev/null

        exclude_dirs="_default|external|packs/shinken|packs/shinken-core"
        move_tree_structure_with_exclude "/etc/shinken" "${before_restore}/" $exclude_dirs 2>/dev/null

            # Maybe the /etc/shinken/ do not exists (and is not a link too), if so, recreate it
            if [[ ! -d "/etc/shinken/" ]] && [[ ! -L "/etc/shinken/" ]]; then
                mkdir /etc/shinken/
            fi
        move_tree_structure_with_exclude "etc/shinken" "/etc/shinken/" $exclude_dirs 2>/dev/null

        if [[ $? -ne 0 ]]; then
            doexit "Cannot restore /etc/shinken directory ; the one you had before the restore is stored in ${before_restore}"
        fi

        if [[ -f "$keyfile_from_config_backup" ]]; then
            mkdir -p $(dirname $keyfile_from_config)
            _spf_decode_key "$(<"$keyfile_from_config_backup")" >"$keyfile_from_config"
            chown ${KEYFILE_OWNER}:${KEYFILE_GROUP} "${keyfile_from_config}"
            chmod 600 "${keyfile_from_config}"
            rm -f "$keyfile_from_config_backup"
        fi

        if [[ -n "${key_hash_from_cli}" ]] && [[ ${needs_restore_keyfile} -eq 1 ]]; then
            spf_restore_key_file_from_backup "${key_hash_from_cli}" "${keyfile_from_backup}.from_backup"
            # DB is now the one restored from backup, so we check that the keyfile has not changed between the last backup and the current version
            mv "${keyfile_from_backup}.from_backup" "${keyfile_from_backup}"
            chown ${KEYFILE_OWNER}:${KEYFILE_GROUP} "${keyfile_from_backup}"
            chmod 600 "${keyfile_from_backup}"
        elif [[ -n "${shinken_save_keyfile}" ]] && [[ -r "${shinken_save_keyfile}" ]] && [[ -n "${keyfile_from_config}" ]]; then
            keyfile_dir_from_config="$(dirname "${keyfile_from_config}")"
            mkdir -p "${keyfile_dir_from_config}"
            chown ${KEYFILE_OWNER}:${KEYFILE_GROUP} "${keyfile_dir_from_config}"
            _spf_decode_key "$(<"${shinken_save_keyfile}")" >"${keyfile_from_config}"
            chown ${KEYFILE_OWNER}:${KEYFILE_GROUP} "${keyfile_from_config}"
            chmod 600 "${keyfile_from_config}"
        fi

        rm -fr "${before_restore}"

        ########## Restore the /etc/shinken-user directory now
        if [[ -f "${src_dir}/shinken-user.tar.gz" ]]; then
            restore_tar_gz_archive_to_folder "${src_dir}/shinken-user.tar.gz" "/etc/shinken-user" ${now}
        fi

        ########## Restore the /var/lib/shinken-user/libexec directory now
        if [[ -f "${src_dir}/var-lib-shinken-user-libexec.tar.gz" ]]; then
            restore_tar_gz_archive_to_folder "${src_dir}/var-lib-shinken-user-libexec.tar.gz" "/var/lib/shinken-user/libexec" ${now}
        fi

        if [[ ! -e /var/lib/shinken/context.json ]]; then
            doexit "/var/lib/shinken/context.json is missing"
        fi

        # Backup context.json

        cp /var/lib/shinken/context.json /tmp/shinken_backup_context_file.orig

        if [[ -e "${backupDir}/context/context.json.daemons" ]]; then
            shinken-context-manage --merge-with-key daemons --merge-json-file "${backupDir}/context/context.json.daemons"
        fi

        if [[ -e "${backupDir}/context/context.json.localinstances" ]]; then
            shinken-context-manage --merge-with-key local_instances --merge-json-file "${backupDir}/context/context.json.localinstances"
        fi

        shinken-context-manage --disable-addons
        if [[ -e "${backupDir}/context/context.json.addons" ]]; then
            shinken-context-manage --merge-with-key addons --merge-json-file "${backupDir}/context/context.json.addons"
        fi

        # Force enabled and disabled states for addons during restore
        printf "\nSetting addons state\n"
        addons_list=$(shinken-addons-list | cut -f 2 -d' ')
        for addon in $addons_list; do
            shinken-addons-has $addon >/dev/null 2>&1
            enabled=$?
            if [[ ${enabled} -eq 0 ]]; then
                shinken-addons-enable --force ${addon}
            else
                shinken-addons-disable --force ${addon}
            fi
        done

        rm -f /var/lib/shinken/arbiter-retention*.json >>"${logFile}" 2>>"${logFile}"
        cp "${src_dir}"/arbiter-retention*.json /var/lib/shinken/ >>"${logFile}" 2>>"${logFile}"
        if [[ $? -ne 0 ]]; then
            printf "\n \033[93mFailed to restore arbiter retention. First monitoring date for elements will be lost.\033[0m\\n"
        fi

        printf " \033[92m=> Restoring configuration files : DONE\033[0m\n"
        fi
        record_history configuration
        printf " \033[92m=> Restoring configuration : DONE\033[0m\n"
    else
        printf " => Restoring configuration : \033[91mKO\033[0m\n \033[91m No configuration data to restore in ${backupDir} \033[0m\n"
    fi
fi
## ----------- configuration end -----------

## ----------- sla start -----------
if [[ ${mustRestoreSla} -eq 1 ]]; then

    printf "\033[92m-Restoring Sla           \033[0m"

    # Try to detect the backup structure, can be old or new
    if [[ -d "${backupDir}/sla" ]]; then
        logFile="${backupDir}/sla/restore-sla.log"
        restore_dir="${backupDir}/sla/dump-sla"
        src_dir="${backupDir}/sla"
    else
        logFile="${backupDir}/restore-sla.log"
        restore_dir="${backupDir}/dump"
        src_dir="${backupDir}"
    fi

    if [[ ! -d "${restore_dir}" ]] && [[ "${backupDir}" == */sla ]]; then
        printf "\n\033[33mThe backup folder end with sla : trying with backup dir at parent\033[0m\n"
        logFile="${backupDir}/restore-sla.log"
        restore_dir="${backupDir}/dump-sla"
    fi

    if [[ -d "${restore_dir}" ]]; then

        stop_shinken_before_restore
        #clean old logFile
        printf "" >"${logFile}"
        sanatizeOnExit=1

        # First be sure mongodb is start before everything...
        /etc/init.d/mongod start >/dev/null 2>/dev/null
        # First clean the collection; because we cannot filter the restore in mongorestore
        # so we will restore only void collections
        mongo shinken --eval "db.getCollection('acknowledge').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo shinken --eval "db.getCollection('downtime').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo shinken --eval "db.getCollection('sla').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo shinken --eval "db.getCollection('sla_archive').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo shinken --eval "db.getCollection('sla_info').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo shinken --eval "db.getCollection('sla_future_states').drop()" >>"${logFile}" 2>>"${logFile}"

        ## dump sla not archive
        collection=$(mongo shinken --quiet --eval "db.getCollectionNames()")
        IFS=',' read -ra ADDR <<<"${collection}"
        for i in "${ADDR[@]}"; do
            if [[ ${i} =~ ^[0-9]+_[1-2][0-9]{3}$ ]]; then
                mongo shinken --eval "db.getCollection('${i}').drop()" >>"${logFile}" 2>>"${logFile}"
            fi
        done

        mongorestore "${restore_dir}" >>"${logFile}" 2>>"${logFile}"
        if [[ $? -ne 0 ]]; then
            doexit "Mongodb database restore fail. Please look at ${logFile}"
        fi

        record_history sla
        printf " \033[92mDONE\033[0m\n"
    else
        printf " \033[91mKO\033[0m\n \033[91mNo sla data to restore in ${backupDir}\033[0m\\n"
    fi

fi
## ----------- sla end -----------

## ----------- events start -----------
if [[ ${mustRestoreEvents} -eq 1 ]]; then

    printf "\033[92m-Restoring Events        \033[0m"

    if [[ -d "${backupDir}/events" ]]; then
        logFile="${backupDir}/events/restore-events.log"
        restore_dir="${backupDir}/events/dump-events"
    fi

    if [[ ! -d "${restore_dir}" ]] && [[ "${backupDir}" == */events ]]; then
        printf "\n\033[33mThe backup folder end with events : trying with backup dir at parent\033[0m\n"
        logFile="${backupDir}/restore-events.log"
        restore_dir="${backupDir}/dump-events"
    fi

    if [[ -d "${restore_dir}" ]]; then
        # Clean old logFile
        printf "" >"${logFile}"
        sanatizeOnExit=1
        stop_shinken_before_restore

        # Force start of mongodb
        /etc/init.d/mongod start >/dev/null 2>/dev/null

        # Clean previous collections
        mongo event_container --eval "db.getCollection('ec_datas').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo event_container --eval "db.getCollection('ec_state_cache').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo event_container --eval "db.getCollection('ec_info').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo event_container --eval "db.getCollection('ec_acknowledge').drop()" >>"${logFile}" 2>>"${logFile}"
        mongo event_container --eval "db.getCollection('ec_downtime').drop()" >>"${logFile}" 2>>"${logFile}"

        # Restore backup collections
        mongorestore "${restore_dir}" >>"${logFile}" 2>>"${logFile}"
        if [[ $? -ne 0 ]]; then
            doexit "Mongodb database restore fail. Please look at ${logFile}"
        fi

        record_history events
        printf " \033[92mDONE\033[0m\n"
    else
        printf " \033[91mKO\033[0m\n \033[91mNo events data to restore in ${backupDir}\033[0m\\n"
    fi

fi
## ----------- events end -----------

## ----------- user start -----------
if [[ ${mustRestoreUser} -eq 1 ]]; then

    printf "\033[92m-Restoring User          \033[0m"

    # Try to detect the backup structure, can be old or new
    if [[ -d "${backupDir}/user" ]]; then
        logFile="${backupDir}/user/restore-user.log"
        restore_dir="${backupDir}/user/dump-user"
    else
        logFile="${backupDir}/restore-user.log"
        restore_dir="${backupDir}/dump"
    fi

    if [[ ! -d "${restore_dir}" ]] && [[ "${backupDir}" == */user ]]; then
        printf "\n\033[33mThe backup folder end with user : trying with backup dir at parent\033[0m\n"
        logFile="${backupDir}/restore-user.log"
        restore_dir="${backupDir}/dump-user"
    fi

    if [[ -d "${restore_dir}" ]]; then
        #clean old logFile
        printf "" >"${logFile}"

        if [[ "${restore_only_user}" != "" ]]; then
            printf "\n\033[33m Restoring only the user ${restore_only_user}\033[0m\n"

            mongo shinken --eval 'db.tiles.remove({ "_id" : "${restore_only_user}"});' >>"${logFile}" 2>>"${logFile}"
            mongorestore__filter shinken "${restore_dir}/shinken/tiles.bson" "{_id:'${restore_only_user}'}" >>"${logFile}" 2>>"${logFile}"

            if [[ -e "${restore_dir}/shinken/user.bson" ]]; then
                userUUID=$(mongo shinken --quiet --eval "db.getCollection('user').find({'userName': '${restore_only_user}'}).forEach( function(x) { print(x.uuid); } );")
                if [[ -n "${userUUID}" ]]; then
                    mongo shinken --eval "db.user.copyTo('user_backup');" >>"${logFile}" 2>>"${logFile}"
                fi
                mongo shinken --eval "db.user.remove({ 'userName' : '${restore_only_user}'});" >>"${logFile}" 2>>"${logFile}"
                user_ids=$(mongorestore__filter shinken "${restore_dir}/shinken/user.bson" "{userName:'${restore_only_user}'}")
                if [[ "${user_ids}" == "true" ]] || [[ "{$user_ids}" == "false" ]]; then
                    mongo shinken --eval "user = db.user_backup.findOne({'userName': '${restore_only_user}'}); db.user.insert(user); db.user_backup.drop();" >>"${logFile}" 2>>"${logFile}"
                    doexit "\n\033[31m The user ${restore_only_user} does not exist\033[0m\n" "no_sanatize"

                fi
                userUUID=$(mongo shinken --quiet --eval "db.getCollection('user').find({'userName': '${restore_only_user}'}).forEach( function(x) { print(x.uuid); } );")
                dashboard_ids=$(get_dashboards_for_user "$userUUID")
                for board_id in $dashboard_ids; do
                    mongo shinken --eval "db.dashboard.remove({ 'uuid' : '${board_id}'});" >>"${logFile}" 2>>"${logFile}"
                done

                mongo shinken --eval "db.share.remove({ 'owner.uuid' : '${userUUID}'});" >>"${logFile}" 2>>"${logFile}"
                mongo shinken --eval "db.list.remove({ 'owner.uuid' : '${userUUID}'});" >>"${logFile}" 2>>"${logFile}"
                mongo shinken --eval "db.hive.remove({ 'owner.uuid' : '${userUUID}'});" >>"${logFile}" 2>>"${logFile}"
                mongo shinken --eval "db.dashboard.remove({ 'owner.uuid' : '${userUUID}'});" >>"${logFile}" 2>>"${logFile}"

                if [[ -e "${restore_dir}/shinken/share.bson" ]]; then
                    mongorestore__filter shinken "${restore_dir}/shinken/share.bson" "{ 'owner.uuid' : '${userUUID}'}" >>"${logFile}" 2>>"${logFile}"
                fi
                if [[ -e "${restore_dir}/shinken/list.bson" ]]; then
                    mongorestore__filter shinken "${restore_dir}/shinken/list.bson" "{ 'owner.uuid' : '${userUUID}'}" >>"${logFile}" 2>>"${logFile}"
                fi
                if [[ -e "${restore_dir}/shinken/hive.bson" ]]; then
                    mongorestore__filter shinken "${restore_dir}/shinken/hive.bson" "{ 'owner.uuid' : '${userUUID}'}" >>"${logFile}" 2>>"${logFile}"
                fi
                if [[ -e "${restore_dir}/shinken/dashboard.bson" ]]; then
                    dashboard_ids=$(get_dashboards_for_user "$userUUID")
                    for dashboard_id in $dashboard_ids; do
                        mongorestore__filter shinken "${restore_dir}/shinken/dashboard.bson" "{ 'uuid' : '${dashboard_id}'}" >>"${logFile}" 2>>"${logFile}"
                    done
                fi
            fi

            if [[ $? -ne 0 ]]; then
                doexit "Mongodb database restore fail. Please look at ${logFile}" "no_sanatize"
            fi
            printf "\n\033[32mRestore of the user ${restore_only_user} data is OK\033[0m\n"
        else
            sanatizeOnExit=1
            stop_shinken_before_restore

            # First be sure mongodb is start before everything...
            /etc/init.d/mongod start >/dev/null 2>/dev/null

            # Need to clean the collections as we can't say to mongorestore which db/collection we want to restore
            mongo shinken --eval "db.getCollection('tiles').drop()" >>"${logFile}" 2>>"${logFile}"
            mongo shinken --eval "db.getCollection('ui_user_preferences').drop()" >>"${logFile}" 2>>"${logFile}"
            mongo shinken --eval "db.getCollection('dashboard').drop()" >>"${logFile}" 2>>"${logFile}"
            mongo shinken --eval "db.getCollection('hive').drop()" >>"${logFile}" 2>>"${logFile}"
            mongo shinken --eval "db.getCollection('list').drop()" >>"${logFile}" 2>>"${logFile}"
            mongo shinken --eval "db.getCollection('share').drop()" >>"${logFile}" 2>>"${logFile}"
            mongo shinken --eval "db.getCollection('user').drop()" >>"${logFile}" 2>>"${logFile}"

            mongorestore "${restore_dir}" >>"${logFile}" 2>>"${logFile}"

        if [[ $? -ne 0 ]]; then
                doexit "Mongodb database restore fail. Please look at ${logFile}"
            fi

            record_history user
            printf " \033[92mDONE\033[0m\n"
        fi
    else
        printf " \033[91mKO\033[0m\n \033[91mNo user data to restore in ${backupDir}\033[0m\n"
    fi
fi
## ----------- user end -----------

## ----------- metrology start -----------
if [[ ${mustRestoreMetrology} -eq 1 ]]; then

    printf "\033[92m-Restoring Metrology     \033[0m"

    # Try to detect the backup structure, can be old or new
    if [[ -d "${backupDir}/metrology" ]]; then
        logFile="${backupDir}/metrology/restore-metrology.log"
        restore_dir="${backupDir}/metrology/dump-trending"
        src_dir="${backupDir}/metrology"
    else
        logFile="${backupDir}/restore-metrology.log"
        restore_dir="${backupDir}/dump"
        src_dir="${backupDir}"
    fi

    if [[ ! -d "${restore_dir}" ]] && [[ "${backupDir}" == */metrology ]]; then
        printf "\n\033[33mThe backup folder end with metrology : trying with backup dir at parent\033[0m\n"
        logFile="${backupDir}/restore-metrology.log"
        restore_dir="${backupDir}/dump-trending"
        src_dir="${backupDir}"
    fi

    if [[ -f "${src_dir}/whisper.tar.gz" ]]; then
        #clean old logFile
        printf "" >"${logFile}"
        sanatizeOnExit=1
        stop_shinken_before_restore

        # start by deleting the old graphs, but do NOT remove the whisper directory
        # as it can be a symbolic link
        rm -rf /opt/graphite/storage/whisper/*
        # NOTE: h to keep whisper as link if set as this
        tar fhxz "${src_dir}/whisper.tar.gz" -C /opt/graphite/storage/ >>"${logFile}" 2>>"${logFile}"
        chmod -R 0755 /opt/graphite/storage/ /var/log/graphite
        chown -R apache:apache /opt/graphite/storage/ /var/log/graphite

        if [[ ${SELINUX_ENABLED} -eq 0 ]]; then
            # use semanage (yum install policycoreutils-python)
            semanage fcontext -a -t httpd_sys_rw_content_t "/opt/graphite/storage(/.*)?"
            restorecon -R /opt/graphite/storage
            semanage fcontext -a -t httpd_log_t "/var/log/graphite(/.*)?"
            restorecon -R /var/log/graphite
        fi

        if [[ $? -ne 0 ]]; then
            doexit "Metrology database restore fail. Please look at ${logFile}"
        fi

        # Only restore trending if there is such a backup
        if [[ -f "${restore_dir}/shinken/trending.bson" ]]; then
            # First be sure mongodb is start before everything...
            /etc/init.d/mongod start >/dev/null 2>/dev/null
            mongo shinken --eval "db.getCollection('trending').drop()" >>"${logFile}" 2>>"${logFile}"
            restore_mongo_bson "${restore_dir}/shinken/trending.bson" "${logFile}"
        fi
        record_history metrology
        printf " \033[92mDONE\033[0m\n"
    else
        printf " \033[91mKO\033[0m\n \033[91m No metrology data to restore in ${backupDir}\033[0m\n"
    fi
fi
## ----------- metrology end -----------

## ----------- logs start -----------
if [[ ${mustRestoreLogs} -eq 1 ]]; then

    printf "\033[92m-Restoring Logs          \033[0m"

    # Try to detect the backup structure, can be old or new
    if [[ -d "${backupDir}/logs" ]]; then
        logFile="${backupDir}/logs/restore-logs.log"
        src_dir="${backupDir}/logs"
    else
        logFile="${backupDir}/restore-logs.log"
        src_dir="${backupDir}"
    fi

    if [[ ! -d "${src_dir}" ]] && [[ "${backupDir}" == */logs ]]; then
        printf "\n\033[33mThe backup folder end with logs : trying with backup dir at parent\033[0m\n"
        logFile="${backupDir}/restore-logs.log"
        src_dir="${backupDir}"
    fi

    if [[ -d "${src_dir}" ]]; then
        #clean old logFile
        printf "" > "${logFile}"
        stop_shinken_before_restore

        # Look if there are logs to restore before clean all
        if [[ -f "${src_dir}/logs.tar.gz" ]]; then
            # NOTE: we do not delete the directory as it can be a symbolic link
            rm -fr /var/log/shinken/*
            tar hfxz "${src_dir}/logs.tar.gz" -C /var/log >>"${logFile}" 2>>"${logFile}"
            if [[ $? -ne 0 ]]; then
                doexit "Logs restore fail. Please look at ${logFile}"
            fi
            chown -R shinken:shinken /var/log/shinken
        fi

        printf " \033[92mDONE\033[0m\n"
    else
        printf " \033[91mKO\033[0m\n \033[91m No logs data to restore in ${backupDir}\033[0m\n"
    fi
fi
## ----------- logs end -----------

## ----------- addons start -----------
if [[ ${mustRestoreAddons} -eq 1 ]]; then

    printf "\033[92m-Restoring Addons        \033[0m"

    logFile="$backupDir/addons/restore-addons.log"
    restore_dir="$backupDir/addons"

    if [[ ! -d "$restore_dir" ]] && [[ $backupDir == */addons ]]; then
        printf "\n\033[33mThe backup folder end with addons : trying with backup dir at parent\033[0m\n"
        # Pop last folder of $backupDir path
        backupDir=$(dirname $backupDir)
        logFile="$backupDir/addons/restore-addons.log"
        restore_dir="$backupDir/addons"
    fi

    if [[ -d "$restore_dir" ]]; then
        #clean old logFile
        printf "" >"$logFile"
        sanatizeOnExit=1
        stop_shinken_before_restore

        # Create associative array containing the following data:
        #     key: addon name
        #     value: string containing addon_nagvis_install_path:nagvis_apache_cfg_file_path
        declare -A addonsConfigurationFiles=(["nagvis-shinken-architecture"]="/var/lib/shinken-nagvis/:/etc/httpd/conf.d/nagvis_etc.conf*" ["nagvis"]="/opt/nagvis/:/etc/httpd/conf.d/nagvis_opt.conf*")

        for addon in "${!addonsConfigurationFiles[@]}"; do
            nagvis_folder="${addonsConfigurationFiles[$addon]%%:*}"
            apache_cfg_file="${addonsConfigurationFiles[$addon]##*:}"

            if [[ -d "$restore_dir/$addon" ]]; then
                # NOTE: we do not delete the directory as it can be a symbolic link
                rm -fr ${nagvis_folder}/*
                if [[ ! -d ${nagvis_folder} ]]; then
                    mkdir -p ${nagvis_folder}
                fi

                tar hfxz "$restore_dir/$addon/addon.tar.gz" -C ${nagvis_folder} >>"$logFile" 2>>"$logFile"
                if [[ $? -ne 0 ]]; then
                    doexit "The restore of addon $addon failed. Please look at $logFile"
                fi
                chown -R apache:apache $nagvis_folder

                # Clean then restore apache configuration file for this addon
                rm ${apache_cfg_file}
                cp ${restore_dir}/${addon}/*.conf* $(dirname ${apache_cfg_file})
                chown apache:apache ${apache_cfg_file}

                if [[ $(ls -1 ${apache_cfg_file}) == *disabled ]]; then
                    shinken-addons-disable --force ${addon} >>"$logFile" 2>>"$logFile"
                else
                    shinken-addons-enable --force ${addon} >>"$logFile" 2>>"$logFile"
                fi
            fi
        done

        printf " \033[92mDONE\033[0m\n"
    else
        printf " \033[91mKO\033[0m\n \033[91m No addons data to restore in $backupDir\033[0m\n"
    fi
fi
## ----------- addons end -----------

## ----------- Modules start -----------
if [[ ${mustRestoreModules} -eq 1 ]]; then
    printf "\033[92m-Restoring custom modules data        \033[0m"

    logFile="$backupDir/modules/restore-modules.log"
    restore_dir="$backupDir/modules/"

    if [[ ! -d "$restore_dir" ]] && [[ $backupDir == */modules ]]; then
        printf "\n\033[33mThe backup folder end with modules : trying with backup dir at parent\033[0m\n"
        # Pop last folder of $backupDir path
        backupDir=$(dirname $backupDir)
        logFile="$backupDir/modules/restore-modules.log"
        restore_dir="$backupDir/modules"
    fi

    if [[ -d "$restore_dir" ]]; then
        #clean old logFile
        printf "" >"$logFile"

        list_modules_in_archive

        if [[ ${#moduleTypeAvailable[@]} == 0 ]]; then
            printf "\033[91m\n\nThere is no custom module in this backup to restore.\n \033[0m\n"
        else

            stop_shinken_before_restore

            # First be sure mongodb is start before everything...
            /etc/init.d/mongod start >/dev/null 2>/dev/null

            restored_modules=""

            for moduleType in "${moduleTypeAvailable[@]}"; do
                if [[ ${restoreModuleType} == "" ]] || [[ ${moduleType} == ${restoreModuleType} ]]; then
                    # Need to clean the collections as we can't say to mongorestore which db/collection we want to restore
                    printf "Restore custom module ${moduleType}\n"

                    mongorestore --drop --db "shinken_module_${moduleType}" "${restore_dir}${moduleType}/dump-module/shinken_module_${moduleType}" >>"${logFile}" 2>>"${logFile}"

                    if [[ $? -ne 0 ]]; then
                        doexit "Mongodb database restore fail. Please look at ${logFile}" "no_sanatize"
                    fi

                    if [[ ! -n ${restored_modules} ]]; then
                        restored_modules="${module_type}"
                    else
                        restored_modules+=", ${module_type}"
                    fi
                fi
            done

            record_history "modules" "${restored_modules}"
            printf " \033[92mDONE\033[0m\n"

        fi

    else
        printf " \033[91mKO\033[0m\n \033[91m No custom modules data to restore in $backupDir\033[0m\n"
    fi
fi
## ----------- Modules end -----------

if [[ ${sanatizeOnExit} -eq 1 ]]; then
    printf "\n\033[33mSanatizing your restored configuration for this version of Shinken\033[0m\n"
    /var/lib/shinken/libexec/tools/sanatize-data.py -a
fi
if [[ ${doRestartDaemonsOnExit} -eq 1 ]]; then
    printf "\n\033[92mDone. You can restart your Shinken with /etc/init.d/shinken start\033[0m\n"
fi
