diff --git a/backup.sh b/backup.sh new file mode 100644 index 0000000..2be30c7 --- /dev/null +++ b/backup.sh @@ -0,0 +1,69 @@ +# Author : Thibaut Meyer +# Created Date: 09/07/2014 + + +extractDate(){ + ls $VM_BACKUP_VOLUME"/"$vm"/" | while read name + do + echo "Liste fichier backup" + dateStr=${name:${#vm}:9}; + dt2=$(date -d ${dateStr:1}); + echo $dt2; + echo $name; + done +} + +printUsage() { + echo $0": "$1" : wrong option" + echo "Usage: $0 -b [VM_TO_BACKUP] -r [VM_TO_RESTORE] [PATH_TO_RESTORE] -rm" + echo + echo "OPTIONS:" + echo " -b Backup VM" + echo " -r Restore VM" + echo " -d Remove all backup" + echo + exit 1 +} + +while test $# -ne 0 ;do + case $1 in + +-b)shift; + vm=$1; shift; + echo "Run backup $vm"; + sh ./ghettoVCB.sh -m $vm -g ghettoVCB.conf; + echo "Backup end" + ;; + +-r)shift; + vm=$1; shift; + PATH_TO_RESTORE=$1; shift; + echo "Run restore $vm" + + source ghettoVCB.conf + cat ghettoVCB-restore_vm_restore_configuration_template > vm_to_restore; + echo "\""$vm";"$PATH_TO_RESTORE";3\"" >> vm_to_restore; + sh ./ghettoVCB-restore.sh -c vm_to_restore -f 1; + echo "Restore end" + ;; + +-d)shift; + echo "Remove all backup of this vm" + vm=$1; shift; + source ghettoVCB.conf + rm -R $VM_BACKUP_VOLUME"/"$vm; + echo "All backup of this vm are removed" +;; + +-h)shift; + printUsage + exit 1; + ;; + +*)printUsage + exit 1; + ;; +esac +done + +exit 0; \ No newline at end of file diff --git a/ghettoVCB-restore.sh b/ghettoVCB-restore.sh index 81673ea..76ec415 100755 --- a/ghettoVCB-restore.sh +++ b/ghettoVCB-restore.sh @@ -21,12 +21,13 @@ printUsage() { echo "#" echo "###############################################################################" echo - echo "Usage: $0 -c [VM_BACKUP_UP_LIST] -l [LOG_FILE] -d [DRYRUN_DEBUG_INFO]" + echo "Usage: $0 -c [VM_BACKUP_UP_LIST] -l [LOG_FILE] -d [DRYRUN_DEBUG_INFO] -f [FORCE_VM_DELETION]" echo echo "OPTIONS:" echo " -c VM backup list" echo " -l File ot output logging" echo " -d Dryrun/Debug Info [1|2]" + echo " -f Off/On [0|1]" echo echo "(e.g.)" echo -e "\nOutput will go to stdout" @@ -36,6 +37,7 @@ printUsage() { echo -e "\nDryrun/Debug Info (dryrun only)" echo -e "\t$0 -c vms_to_restore -d 1" echo -e "\t$0 -c vms_to_restore -d 2" + echo -e "\t$0 -c vms_to_restore -f 1" echo exit 1 } @@ -59,7 +61,7 @@ sanityCheck() { exit 1 fi - if [[ ${NUM_OF_ARGS} -ne 2 ]] && [[ ${NUM_OF_ARGS} -ne 4 ]] && [[ ${NUM_OF_ARGS} -ne 6 ]]; then + if [[ ${NUM_OF_ARGS} -gt 7 ]]; then printUsage fi @@ -171,8 +173,8 @@ ghettoVCBrestore() { VM_DISPLAY_NAME=$(grep -i "displayName" "${VM_TO_RESTORE}/${VM_ORIG_VMX}" | awk -F '=' '{print $2}' | sed 's/"//g' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//') VM_ORIG_FOLDER_NAME=$(echo "${VM_FOLDER_NAME}" | sed 's/-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-1].*//g') VM_VMX_NAME=${VM_ORIG_VMX} - VM_RESTORE_FOLDER_NAME=${VM_ORIG_FOLDER_NAME} - VM_RESTORE_VMX=${VM_ORIG_VMX} + VM_RESTORE_FOLDER_NAME=${VM_ORIG_FOLDER_NAME} + VM_RESTORE_VMX=${VM_ORIG_VMX} else VM_DISPLAY_NAME=${RESTORE_VM_NAME} VM_RESTORE_FOLDER_NAME=${RESTORE_VM_NAME} @@ -255,8 +257,8 @@ if [ ! "${IS_TGZ}" == "1" ]; then logger "ERROR: Unable to define all required variables: VM_RESTORE_VMX, VM_VMDK_DESCR and VM_DISPLAY_NAME!" #validates that a directory with the same VM does not already exists - elif [ -d "${DATASTORE_TO_RESTORE_TO}/${VM_RESTORE_FOLDER_NAME}" ]; then - logger "ERROR: Directory \"${DATASTORE_TO_RESTORE_TO}/${VM_RESTORE_FOLDER_NAME}\" looks like it already exists, please check contents and remove directory before trying to restore!" + elif [[ -d "${DATASTORE_TO_RESTORE_TO}/${VM_RESTORE_FOLDER_NAME}" ]] && [[ ! "$FORCE_MODE" == 1 ]]; then + logger "ERROR: Directory \"${DATASTORE_TO_RESTORE_TO}/${VM_RESTORE_FOLDER_NAME}\" looks like it already exists, please check contents and remove directory before trying to restore or use -f option to force" else logger "################## Restoring VM: $VM_DISPLAY_NAME #####################" @@ -272,7 +274,13 @@ if [ ! "${IS_TGZ}" == "1" ]; then #create VM folder on datastore if it doesn't already exists logger "Creating VM directory: \"${VM_RESTORE_DIR}\" ..." - if [ ! "${DEVEL_MODE}" == "2" ]; then + if [ ! "${DEVEL_MODE}" == "2" ]; then + + if [ -d "${VM_RESTORE_DIR}" ]; then + logger "Force mode delete \"${VM_RESTORE_DIR}\" because already exist..." + rm -R "${VM_RESTORE_DIR}" + fi + mkdir -p "${VM_RESTORE_DIR}" fi @@ -280,7 +288,7 @@ if [ ! "${IS_TGZ}" == "1" ]; then logger "Copying \"${VM_ORIG_VMX}\" file ..." if [ ! "${DEVEL_MODE}" == "2" ]; then cp "${VM_TO_RESTORE}/${VM_ORIG_VMX}" "${VM_RESTORE_DIR}/${VM_RESTORE_VMX}" - sed -i "s/displayName =.*/displayName = ${VM_DISPLAY_NAME}/g" "${VM_RESTORE_DIR}/${VM_RESTORE_VMX}" + sed -i "s/displayName =.*/displayName = \"${VM_DISPLAY_NAME}\"/g" "${VM_RESTORE_DIR}/${VM_RESTORE_VMX}" fi #loop through all VMDK(s) and vmkfstools copy to destination @@ -352,7 +360,8 @@ if [ ! "${IS_TGZ}" == "1" ]; then logger "Registering $VM_DISPLAY_NAME ..." if [ ! "${DEVEL_MODE}" == "2" ]; then - ${VMWARE_CMD} solo/registervm "${VM_RESTORE_DIR}/${VM_RESTORE_VMX}" + #${VMWARE_CMD} solo/registervm "${VM_RESTORE_DIR}/${VM_RESTORE_VMX}" + echo "shunt" fi logger "End time: $(date)" @@ -375,7 +384,7 @@ VMDK_LIST_TO_MODIFY='' #################### #read user input -while getopts ":c:l:d:" ARGS; do +while getopts ":c:l:d:f:" ARGS; do case $ARGS in c) CONFIG_FILE="${OPTARG}" @@ -386,6 +395,9 @@ while getopts ":c:l:d:" ARGS; do d) DEVEL_MODE="${OPTARG}" ;; + f) + FORCE_MODE="${OPTARG}" + ;; :) echo "Option -${OPTARG} requires an argument." exit 1 diff --git a/ghettoVCB.conf b/ghettoVCB.conf index 21d7627..06b5992 100644 --- a/ghettoVCB.conf +++ b/ghettoVCB.conf @@ -21,6 +21,8 @@ EMAIL_LOG=0 EMAIL_SERVER=auroa.primp-industries.com EMAIL_SERVER_PORT=25 EMAIL_DELAY_INTERVAL=1 +EMAIL_USER_NAME= +EMAIL_USER_PASSWORD= EMAIL_TO=auroa@primp-industries.com EMAIL_FROM=root@ghettoVCB WORKDIR_DEBUG=0 diff --git a/ghettoVCB.sh b/ghettoVCB.sh index 6f93744..7fa5eec 100755 --- a/ghettoVCB.sh +++ b/ghettoVCB.sh @@ -102,6 +102,12 @@ EMAIL_FROM=root@ghettoVCB # Email RCPT EMAIL_TO=auroa@primp-industries.com +# Email SMTP username +EMAIL_USER_NAME= + +# Email SMTP password +EMAIL_USER_PASSWORD= + # Comma separated list of VM startup/shutdown ordering VM_SHUTDOWN_ORDER= VM_STARTUP_ORDER= @@ -288,7 +294,7 @@ sanityCheck() { # Enable multiextent VMkernel module if disk format is 2gbsparse (disabled by default in 5.1) if [[ "${DISK_BACKUP_FORMAT}" == "2gbsparse" ]] && [[ "${VER}" -eq 5 ]]; then esxcli system module list | grep multiextent > /dev/null 2>&1 - if [ $? -eq 1 ]; then + if [ $? -eq 1 ]; then logger "info" "multiextent VMkernel module is not loaded & is required for 2gbsparse, enabling ..." esxcli system module load -m multiextent fi @@ -332,6 +338,7 @@ captureDefaultConfigurations() { DEFAULT_VM_SHUTDOWN_ORDER="${VM_SHUTDOWN_ORDER}" DEFAULT_VM_STARTUP_ORDER="${VM_STARTUP_ORDER}" DEFAULT_RSYNC_LINK="${RSYNC_LINK}" + DEFAULT_EMAIL_SERVER_PORT="${EMAIL_SERVER_PORT}" } useDefaultConfigurations() { @@ -353,6 +360,7 @@ useDefaultConfigurations() { VM_SHUTDOWN_ORDER="${DEFAULT_VM_SHUTDOWN_ORDER}" VM_STARTUP_ORDER="${DEFAULT_VM_STARTUP_ORDER}" RSYNC_LINK="${RSYNC_LINK}" + EMAIL_SERVER_PORT="${DEFAULT_EMAIL_SERVER_PORT}" } reConfigureGhettoVCBConfiguration() { @@ -600,7 +608,7 @@ checkVMBackupRotation() { NFS_IO_HACK_STATUS=0 NFS_IO_HACK_FILECHECK="$BACKUP_DIR_PATH/nfs_io.check" - while [[ "${NFS_IO_HACK_STATUS}" -eq 0 ]] && [[ "${NFS_IO_HACK_COUNTER}" -lt 60 ]]; do + while [[ "${NFS_IO_HACK_STATUS}" -eq 0 ]] && [[ "${NFS_IO_HACK_COUNTER}" -lt 600 ]]; do sleep 1 NFS_IO_HACK_COUNTER=$((NFS_IO_HACK_COUNTER+1)) touch "${NFS_IO_HACK_FILECHECK}" @@ -765,12 +773,12 @@ ghettoVCB() { #1 = readonly #0 = readwrite logger "debug" "Mounting NFS: ${NFS_SERVER}:${NFS_MOUNT} to /vmfs/volume/${NFS_LOCAL_NAME}" - if [ ${ESX_RELEASE} == "5.5.0" ]; then + if [ ${ESX_RELEASE} == "5.5.0" ]; then ${VMWARE_CMD} hostsvc/datastore/nas_create "${NFS_LOCAL_NAME}" "${NFS_VERSION}" "${NFS_MOUNT}" 0 "${NFS_SERVER}" else ${VMWARE_CMD} hostsvc/datastore/nas_create "${NFS_LOCAL_NAME}" "${NFS_SERVER}" "${NFS_MOUNT}" 0 fi - fi + fi fi captureDefaultConfigurations @@ -915,7 +923,7 @@ ghettoVCB() { $VMWARE_CMD vmsvc/snapshot.removeall ${VM_ID} > /dev/null 2>&1 fi fi - #nfs case and backup to root path of your NFS mount + #nfs case and backup to root path of your NFS mount if [[ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ]] ; then BACKUP_DIR="/vmfs/volumes/${NFS_LOCAL_NAME}/${NFS_VM_BACKUP_DIR}/${VM_NAME}" if [[ -z ${VM_NAME} ]] || [[ -z ${NFS_LOCAL_NAME} ]] || [[ -z ${NFS_VM_BACKUP_DIR} ]]; then @@ -1274,7 +1282,21 @@ getFinalStatus() { buildHeaders() { EMAIL_ADDRESS=$1 - echo -ne "HELO $(hostname -s)\r\n" > "${EMAIL_LOG_HEADER}" + # echo -ne "HELO $(hostname -s)\r\n" > "${EMAIL_LOG_HEADER}" + echo -ne "EHLO $(hostname -s)\r\n" > "${EMAIL_LOG_HEADER}" + + #If username is provided, we add an AUTH LOGIN command to perform authentication + if [[ ! -z "${EMAIL_USER_NAME}" ]]; then + # EMAIL_LOGIN_PLAIN_B64=$(printf '%s\0%s\0%s' "$EMAIL_USER_NAME" "$EMAIL_USER_NAME" "$EMAIL_USER_PASSWORD" | python -m base64) + # echo -ne "AUTH PLAIN $EMAIL_LOGIN_PLAIN_B64\r\n" >> "${EMAIL_LOG_HEADER}" + + EMAIL_LOGIN_PLAIN_B64=$(printf '%s\0%s\0%s' "$EMAIL_USER_NAME" | python -m base64) + echo -ne "AUTH LOGIN $EMAIL_LOGIN_PLAIN_B64\r\n" >> "${EMAIL_LOG_HEADER}" + + EMAIL_LOGIN_PLAIN_B64=$(printf '%s\0%s\0%s' "$EMAIL_USER_PASSWORD" | python -m base64) + echo -ne "$EMAIL_LOGIN_PLAIN_B64\r\n" >> "${EMAIL_LOG_HEADER}" + fi + echo -ne "MAIL FROM: <${EMAIL_FROM}>\r\n" >> "${EMAIL_LOG_HEADER}" echo -ne "RCPT TO: <${EMAIL_ADDRESS}>\r\n" >> "${EMAIL_LOG_HEADER}" echo -ne "DATA\r\n" >> "${EMAIL_LOG_HEADER}" @@ -1305,13 +1327,15 @@ sendMail() { fi fi + if ! grep "###### Final status: All VMs backed up OK! ######" ghettoVCB.log > /dev/null 2>&1 + then echo "${EMAIL_TO}" | grep "," > /dev/null 2>&1 if [[ $? -eq 0 ]] ; then ORIG_IFS=${IFS} IFS=',' for i in ${EMAIL_TO}; do buildHeaders ${i} - "${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}" < "${EMAIL_LOG_CONTENT}" > /dev/null 2>&1 + cat "${EMAIL_LOG_CONTENT}" | ./slowcat.sh | "${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}" > /dev/null 2>&1 if [[ $? -eq 1 ]] ; then logger "info" "ERROR: Failed to email log output to ${EMAIL_SERVER}:${EMAIL_SERVER_PORT} to ${EMAIL_TO}\n" fi @@ -1319,11 +1343,12 @@ sendMail() { unset IFS else buildHeaders ${EMAIL_TO} - "${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}" < "${EMAIL_LOG_CONTENT}" > /dev/null 2>&1 + cat "${EMAIL_LOG_CONTENT}" | ./slowcat.sh | "${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}" > /dev/null 2>&1 if [[ $? -eq 1 ]] ; then logger "info" "ERROR: Failed to email log output to ${EMAIL_SERVER}:${EMAIL_SERVER_PORT} to ${EMAIL_TO}\n" fi fi + fi fi } diff --git a/slowcat.sh b/slowcat.sh new file mode 100644 index 0000000..50f8101 --- /dev/null +++ b/slowcat.sh @@ -0,0 +1,6 @@ +#!/bin/sh +while read -r line +do + echo $line + sleep 1 +done