Задать вопрос

Как можно улучшить данный backup-скрипт?

Доброго времени суток.

Написал скрипт для резервного копирования содержимого сетевых шар в офисе.

Так как я раньше этим не занимался (использовались готовые решения типа flexbackup), хотелось бы услышать, хорош ли метод бэкапа, приведённый в нём, и как его можно улучшить.

Заранее спасибо.

Код скрипта
require 'fileutils'
# We will keep 30 latest data snapshots
FileUtils.rm_r '/ext/30', :force => true
# Here we delete the oldest snapshot
range = (1..29).to_a.reverse # Literally the same as (29..1)
for i in range
	FileUtils.mv "/ext/#{i}","/ext/#{i+1}"
	# Shift backup one position to the past
	# Folder 1 becomes folder 2, folder 28 becomes folder 29, etc
end
%x[cp -al /ext/0 /ext/1]
# -a means archive: we go recursively through
# the directory tree, preserving permissions, access dates, etc
# -l means hardlinking: together with -a we create an
# illusion of the directory tree with the hardlinks to
# real files inside
%x[rsync -ae ssh --delete user@host.local:/shares /ext/0]
# We update the 0 folder with the latest data

  • Вопрос задан
  • 4602 просмотра
Подписаться 7 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 3
foxmuldercp
@foxmuldercp
Системный администратор, программист, фотограф
У меня в одной из публикаций описана схема обработки видео с вебкамер на фтп.
Там всё документировано и откомментировано, можете посмотреть и поправить под себя, при желании.
Ответ написан
Комментировать
Cresh
@Cresh
ИТ Архитектор X5 Retail Group
Сейчас использую вот этот способ ранее описанный на хабре, работает быстро ни разу не подвел

backup.sh
#!/bin/sh

. /usr/local/sbin/backup_functions.sh
BACKUP_EXPIRES_DAYS=0
# резерв 30Гб
RESERVE_G=4
BACKUP_MAIN_DIR='/media/backup'
VERIFY_BACKUP_MOUNTED='yes'
prepare_for_backup
cd /
make_backup etc boot home root opt srv usr/local /var
#make_backup_with_delta home/123 var/www

backup_functions.sh
#!/bin/sh

export LC_ALL=en_US.utf8
DIR_PATTERN='20..-..-..'
CURR_DATE=`date +%F`
RESERVE_G=5
BACKUP_MAIN_DIR='/backup'
BACKUP_TMP_DIR='/tmp'
BACKUP_DELTA=$BACKUP_TMP_DIR/backup.delta
BACKUP_ERRORS=$BACKUP_TMP_DIR/backup.err
BACKUP_REPORT=$BACKUP_TMP_DIR/backup.report
BACKUP_LOG_FACILITY='user.notice'
BACKUP_EXPIRES_DAYS=0
VERIFY_BACKUP_MOUNTED='no'
PID_FILE='/var/run/backup.pid'
BACKUP_MYSQL_DIR=$BACKUP_TMP_DIR/mysql_dump
MYSQL_DATA_DIR='/var/lib/mysql'

touch /etc/default/backup_exclude
rm $BACKUP_DELTA $BACKUP_ERRORS $BACKUP_REPORT 1>/dev/null 2>/dev/null

verify_backup_mounted() {
 mount -a
 [ -d "$BACKUP_MAIN_DIR" ] || { echo "BACKUP main directory does not exist!"; exit; }
 str=`df "$BACKUP_MAIN_DIR" | tail -1 | grep ' /$'`
 [ "$str" ] && { echo 'BACKUP partition is not mounted!!!!!!!!'; exit; }
 return 0
}
prepare_for_backup() {
 if [ -s "$PID_FILE" ] && [ `cat "$PID_FILE"` -ne $PPID ]
 then
 if [ "`ps ax | awk '{print $1;}' | grep -f \"$PID_FILE\"`" ]
 then
 echo -n "Previous BACKUP script is still running. PID = "; cat "$PID_FILE"; exit
 else
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "Previous BACKUP ended unexpectly"
 fi
 fi
 rm "$PID_FILE" 1>/dev/null 2>/dev/null
 echo $PPID > "$PID_FILE"
 old_dir=`pwd`
 cd "$BACKUP_MAIN_DIR" || { echo "BACKUP main directory does not exist!"; exit; }
 VERIFY_BACKUP_MOUNTED=`echo "$VERIFY_BACKUP_MOUNTED" | tr 'A-Z' 'a-z'`
 [ "$VERIFY_BACKUP_MOUNTED" = "yes" ] && verify_backup_mounted
 reserve_k=$(($RESERVE_G * 1048576))
 mkdir -p $BACKUP_TMP_DIR 1>/dev/null 2>/dev/null
 dirs_list=`ls | grep $DIR_PATTERN | sort`
 if [ -n "$dirs_list" ]
 then
 while { free_k=`df -k .|grep -v Filesystem| sed -e "s/.\+ \([0-9]\+\) .\+/\1/"`
 dirs_list=`ls | grep $DIR_PATTERN | sort`
 free_pre=$free_k
 [ $free_pre -lt $reserve_k ] ; }
 do
 dir_oldest=`echo $dirs_list | tr " " "\n" | head -1`
 [ -d $dir_oldest ] && { logger -t BACKUP -p $BACKUP_LOG_FACILITY "Deleting old backup in $BACKUP_MAIN_DIR/$dir_oldest" ; rm -rf $dir_oldest; }
 done
 fi
 [ "$VERIFY_BACKUP_MOUNTED" = "yes" ] && verify_backup_mounted
 last_date=`ls | grep $DIR_PATTERN | sort | tail -1`
 if [ -n "$last_date" -a \( "$CURR_DATE" != "$last_date" \) ]
 then
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "Preparing. Copying $BACKUP_MAIN_DIR/$last_date -> $BACKUP_MAIN_DIR/$CURR_DATE"
 mkdir $CURR_DATE 1>/dev/null 2>/dev/null
 cp -al "$last_date"/* $CURR_DATE 1>/dev/null 2>/dev/null
 rm -rf $CURR_DATE/_delta 1>/dev/null 2>/dev/null
 fi
 mkdir $CURR_DATE/_delta 1>/dev/null 2>/dev/null
 if [ $BACKUP_EXPIRES_DAYS -gt 0 ]
 then
 for expired_dir in `find "$BACKUP_MAIN_DIR" -maxdepth 1 -mtime +$BACKUP_EXPIRES_DAYS -type d | grep "$DIR_PATTERN"`
 do
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "Deleting expired backup $expired_dir" ; rm -rf $expired_dir;
 done
 fi
 cd $old_dir
 return 0
}
make_backup() {
 while [ -n "$1" ]
 do
 [ "$VERIFY_BACKUP_MOUNTED" = "yes" ] && verify_backup_mounted
 src=$1
 full_src=`echo $PWD/$1 | sed -e 's://:/:g'`
 dst=`echo $BACKUP_MAIN_DIR/$CURR_DATE/$src | sed -e "s/\/\w\+$//"`
 mkdir -p $dst 1>/dev/null 2>/dev/null
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "$full_src started"
 rsync -axW8 --del --exclude-from=/etc/default/backup_exclude $src $dst 2>>$BACKUP_ERRORS
 sync
 shift
 done
 return 0
}
make_backup_with_delta() {
 while [ -n "$1" ]
 do
 [ "$VERIFY_BACKUP_MOUNTED" = "yes" ] && verify_backup_mounted
 src=$1
 full_src=`echo $PWD/$1 | sed -e 's://:/:g'`
 dst=`echo $BACKUP_MAIN_DIR/$CURR_DATE/$src | sed -e "s/\/\w\+$//"`
 mkdir -p $dst 1>/dev/null 2>/dev/null
 rm $BACKUP_DELTA 1>/dev/null 2>/dev/null
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "$full_src (with delta) started"
 rsync -axW8i --del $src $dst --exclude-from=/etc/default/backup_exclude 2>>$BACKUP_ERRORS | grep "^>f" | cut -d ' ' -f 2- 1>$BACKUP_DELTA
 old_dir=`pwd`
 cd $BACKUP_MAIN_DIR/$CURR_DATE
 dst=`echo $src | sed -e "s/\w\+$//"`
 xargs -a $BACKUP_DELTA -r -n5 -d '\n' -I '{}' echo $dst{} | xargs -r -n10 -d '\n' cp -ul --parents -t _delta
 rm $BACKUP_DELTA 1>/dev/null 2>/dev/null
 cd $old_dir
 sync
 shift
 done
 return 0
}
send_email_report() {
 if [ -s $BACKUP_ERRORS ]
 then
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "Sending email report"
 echo 'Content-type: text/plain; charset=utf-8' >> $BACKUP_REPORT
 echo 'Content-Transfer-Encoding: 8bit' >> $BACKUP_REPORT
 echo 'From: root@'`hostname --fqdn` >> $BACKUP_REPORT
 echo 'To: root' >> $BACKUP_REPORT
 echo 'Date:' `date` >> $BACKUP_REPORT
 echo -e 'Subject: Cron <root@'`hostname --fqdn`'> BACKUP\n\n' >> $BACKUP_REPORT
 cat $BACKUP_ERRORS >> $BACKUP_REPORT
 cat $BACKUP_REPORT | sendmail root
 fi
 rm $BACKUP_DELTA $BACKUP_ERRORS $BACKUP_REPORT $PID_FILE 1>/dev/null 2>/dev/null
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "Finished"
 return 0
}
make_mysql_backup() {
 MYSQL_DATA_DIR='/var/lib/mysql'
 mkdir $BACKUP_MAIN_DIR/$CURR_DATE/MySQL 1>/dev/null 2>/dev/null
 rm -rf $BACKUP_MAIN_DIR/$CURR_DATE/MySQL/* 1>/dev/null 2>/dev/null
 rm -rf $BACKUP_MYSQL_DIR 1>/dev/null 2>/dev/null
 mkdir -p $BACKUP_MYSQL_DIR 1>/dev/null 2>/dev/null
 cd $MYSQL_DATA_DIR
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "MySQL started"
 for db_dir in `ls -p | grep '/' | tr -d '/'`
 do
 cd $MYSQL_DATA_DIR/$db_dir
 db_name=`echo $db_dir | sed -e 's/@003d/=/g' -e 's/@002d/-/g'`
 logger -t BACKUP -p $BACKUP_LOG_FACILITY "MySQL database '$db_name' started"
 for table in `ls | grep '.frm' | sed -e 's/\.frm//' -e 's/ /:::/g'`
 do
 table=`echo $table | sed -e 's/:::/ /g' -e 's/@003d/=/g' -e 's/@002d/-/g'`
 mysqldump $db_name "$table" --skip-lock-tables -Q -u $mysql_user -p$mysql_pass > "$BACKUP_MYSQL_DIR/$table.sql"
 done
 cd $BACKUP_MYSQL_DIR
 tar czf $BACKUP_MAIN_DIR/$CURR_DATE/MySQL/$db_name.tar.gz * 1>/dev/null 2>/dev/null
 rm $BACKUP_MYSQL_DIR/* 1>/dev/null 2>/dev/null
 done
 return 0
}
Ответ написан
@Flaxing
Для бэкапа виртуальных машин на ESX используем этот скрипт, возможно найдете, что-то для себя, выглядит довольно слажено:
ghettoVCB.sh (осторожно большой)
# Author: William Lam
# Created Date: 11/17/2008
# http://www.virtuallyghetto.com/
# http://communities.vmware.com/docs/DOC-8760
##################################################################

# directory that all VM backups should go (e.g. /vmfs/volumes/SAN_LUN1/mybackupdir)
VM_BACKUP_VOLUME=/vmfs/volumes/dlgCore-NFS-bigboi.VM-Backups/WILLIAM_BACKUPS

# Format output of VMDK backup
# zeroedthick
# 2gbsparse
# thin
# eagerzeroedthick
DISK_BACKUP_FORMAT=thin

# Number of backups for a given VM before deleting
VM_BACKUP_ROTATION_COUNT=3

# Shutdown guestOS prior to running backups and power them back on afterwards
# This feature assumes VMware Tools are installed, else they will not power down and loop forever
# 1=on, 0 =off
POWER_VM_DOWN_BEFORE_BACKUP=0

# enable shutdown code 1=on, 0 = off
ENABLE_HARD_POWER_OFF=0

# if the above flag "ENABLE_HARD_POWER_OFF "is set to 1, then will look at this flag which is the # of iterations
# the script will wait before executing a hard power off, this will be a multiple of 60seconds 
# (e.g) = 3, which means this will wait up to 180seconds (3min) before it just powers off the VM
ITER_TO_WAIT_SHUTDOWN=3

# Number of iterations the script will wait before giving up on powering down the VM and ignoring it for backup
# this will be a multiple of 60 (e.g) = 5, which means this will wait up to 300secs (5min) before it gives up
POWER_DOWN_TIMEOUT=5

# enable compression with gzip+tar 1=on, 0=off
ENABLE_COMPRESSION=0

############################
####### NEW PARAMS #########
############################

# Include VMs memory when taking snapshot
VM_SNAPSHOT_MEMORY=0

# Quiesce VM when taking snapshot (requires VMware Tools to be installed)
VM_SNAPSHOT_QUIESCE=0

##########################################################
# NON-PERSISTENT NFS-BACKUP ONLY
# 
# ENABLE NON PERSISTENT NFS BACKUP 1=on, 0=off

ENABLE_NON_PERSISTENT_NFS=0

# umount NFS datastore after backup is complete 1=yes, 0=no
UNMOUNT_NFS=0

# IP Address of NFS Server
NFS_SERVER=172.51.0.192

# Path of exported folder residing on NFS Server (e.g. /some/mount/point )
NFS_MOUNT=/upload

# Non-persistent NFS datastore display name of choice
NFS_LOCAL_NAME=backup

# Name of backup directory for VMs residing on the NFS volume
NFS_VM_BACKUP_DIR=mybackups 

############################
######### EMAIL ############
############################ 

# Email debug 1=yes, 0=no
EMAIL_DEBUG=0

# Email log 1=yes, 0=no 
EMAIL_LOG=0

# Email Delay Interval from NC (netcat) - default 1
EMAIL_DELAY_INTERVAL=1

# Email SMTP server
EMAIL_SERVER=auroa.primp-industries.com

# Email SMTP server port
EMAIL_SERVER_PORT=25

# Email FROM
EMAIL_FROM=root@ghettoVCB

# Email RCPT
EMAIL_TO=auroa@primp-industries.com

########################## DO NOT MODIFY PAST THIS LINE ##########################

# RSYNC LINK 1=yes, 0 = no
RSYNC_LINK=0

LOG_LEVEL="info"
VMDK_FILES_TO_BACKUP="all"
# default 15min timeout
SNAPSHOT_TIMEOUT=15

LAST_MODIFIED_DATE=2011_11_19
VERSION=1
VERSION_STRING=${LAST_MODIFIED_DATE}_${VERSION}

# Directory naming convention for backup rotations (please ensure there are no spaces!)
VM_BACKUP_DIR_NAMING_CONVENTION="$(date +%F_%H-%M-%S)"

printUsage() {
        echo "###############################################################################"
        echo "#"
        echo "# ghettoVCB for ESX/ESXi 3.5, 4.x+ and 5.0"
        echo "# Author: William Lam"
        echo "# http://www.virtuallyghetto.com/"
	echo "# Documentation: http://communities.vmware.com/docs/DOC-8760"
        echo "# Created: 11/17/2008"
        echo "# Last modified: ${LAST_MODIFIED_DATE} Version ${VERSION}"
        echo "#"
        echo "###############################################################################"
        echo
        echo "Usage: $0 -f [VM_BACKUP_UP_LIST] -c [VM_CONFIG_DIR] -l [LOG_FILE] -d [DEBUG_LEVEL] -g [GLOBAL_CONF] -e [VM_EXCLUSION_LIST]"
        echo
        echo "OPTIONS:"
	echo "   -a     Backup all VMs on host"
        echo "   -f     List of VMs to backup"
	echo "   -c     VM configuration directory for VM backups"
	echo "   -g     Path to global ghettoVCB configuration file"
        echo "   -l     File to output logging"
	echo "   -d     Debug level [info|debug|dryrun] (default: info)"
        echo
        echo "(e.g.)"
        echo -e "\nBackup VMs stored in a list"
        echo -e "\t$0 -f vms_to_backup"
	echo -e "\nBackup all VMs residing on this host"
        echo -e "\t$0 -a"
	echo -e "\nBackup all VMs residing on this host except for the VMs in the exclusion list"
        echo -e "\t$0 -a -e vm_exclusion_list"
	echo -e "\nBackup VMs based on specific configuration located in directory"
        echo -e "\t$0 -f vms_to_backup -c vm_backup_configs"
	echo -e "\nBackup VMs using global ghettoVCB configuration file"
        echo -e "\t$0 -f vms_to_backup -g /global/ghettoVCB.conf"
        echo -e "\nOutput will log to /tmp/ghettoVCB.log (consider logging to local or remote datastore to persist logs)"
        echo -e "\t$0 -f vms_to_backup -l /vmfs/volume/local-storage/ghettoVCB.log"
	echo -e "\nDry run (no backup will take place)"
        echo -e "\t$0 -f vms_to_backup -d dryrun"
        echo
        exit 1
}

logger() {
	LOG_TYPE=$1
        MSG=$2

	if [[ "${LOG_LEVEL}" == "debug" ]] && [[ "${LOG_TYPE}" == "debug" ]] || [[ "${LOG_TYPE}" == "info" ]] || [[ "${LOG_TYPE}" == "dryrun" ]]; then
		TIME=$(date +%F" "%H:%M:%S)
       		if [ "${LOG_TO_STDOUT}" -eq 1 ]; then
               		echo -e "${TIME} -- ${LOG_TYPE}: ${MSG}"
		fi
        	if [ -n "${LOG_OUTPUT}" ]; then
       	        	echo -e "${TIME} -- ${LOG_TYPE}: ${MSG}" >> "${LOG_OUTPUT}"
		fi

		if [ "${EMAIL_LOG}" -eq 1 ]; then
			echo -ne "${TIME} -- ${LOG_TYPE}: ${MSG}\r\n" >> "${EMAIL_LOG_OUTPUT}"		
		fi
	fi
}

sanityCheck() {
        NUM_OF_ARGS=$1

	if [ "${USE_GLOBAL_CONF}" -eq 1 ]; then
                reConfigureGhettoVCBConfiguration "${GLOBAL_CONF}"
        fi

	#always log to STDOUT, use "> /dev/null" to ignore output
	LOG_TO_STDOUT=1
	
	#if no logfile then provide default logfile in /tmp
        if [ -z "${LOG_OUTPUT}" ]; then
		LOG_OUTPUT="/tmp/ghettoVCB-$(date +%F_%H-%M-%S).log"
                echo "Logging output to \"${LOG_OUTPUT}\" ..."
        fi
        touch "${LOG_OUTPUT}"
        # REDIRECT is used by the "tail" trick, use REDIRECT=/dev/null to redirect vmkfstool to STDOUT only
        REDIRECT=${LOG_OUTPUT}

	if [[ ${NUM_OF_ARGS} -lt 1 ]] || [[ ${NUM_OF_ARGS} -gt 12 ]]; then
		logger "info" "ERROR: Incorrect number of arguments!"
                printUsage
        fi

	if [[ ! -f "${VM_FILE}" ]] && [[ "${USE_VM_CONF}" -eq 0 ]] && [[ "${BACKUP_ALL_VMS}" -eq 0 ]]; then
		logger "info" "ERROR: \"${VM_FILE}\" is not valid VM input file!"
		printUsage
	fi

	if [[ ! -f "${VM_EXCLUSION_FILE}" ]] && [[ "${EXCLUDE_SOME_VMS}" -eq 1 ]]; then
		logger "info" "ERROR: \"${VM_EXCLUSION_FILE}\" is not valid VM exclusion input file!"
		printUsage
	fi

 	if [[ ! -d "${CONFIG_DIR}" ]] && [[ "${USE_VM_CONF}" -eq 1 ]]; then
		logger "info" "ERROR: \"${CONFIG_DIR}\" is not valid directory!"
                printUsage
       	fi

	if [[ ! -f "${GLOBAL_CONF}" ]] && [[ "${USE_GLOBAL_CONF}" -eq 1 ]]; then
		logger "info" "ERROR: \"${GLOBAL_CONF}\" is not valid global configuration file!"
                printUsage
        fi

	if [ -f /usr/bin/vmware-vim-cmd ]; then
                VMWARE_CMD=/usr/bin/vmware-vim-cmd
                VMKFSTOOLS_CMD=/usr/sbin/vmkfstools
        elif [ -f /bin/vim-cmd ]; then
                VMWARE_CMD=/bin/vim-cmd
                VMKFSTOOLS_CMD=/sbin/vmkfstools
        else
                logger "info" "ERROR: Unable to locate *vimsh*! You're not running ESX(i) 3.5+, 4.x+ or 5.0!"
                echo "ERROR: Unable to locate *vimsh*! You're not running ESX(i) 3.5+, 4.x+ or 5.0!"
                exit 1
        fi

        ESX_VERSION=$(vmware -v | awk '{print $3}')
	if [[ "${ESX_VERSION}" == "5.0.0" ]]; then
		VER=5
        elif [[ "${ESX_VERSION}" == "4.0.0" ]] || [[ "${ESX_VERSION}" == "4.1.0" ]]; then
                VER=4
        else
                ESX_VERSION=$(vmware -v | awk '{print $4}')
                if [[ "${ESX_VERSION}" == "3.5.0" ]] || [[ "${ESX_VERSION}" == "3i" ]]; then
                        VER=3
                else
                        echo "You're not running ESX(i) 3.5, 4.x, 5.x!"
                        exit 1
                fi
        fi

	NEW_VIMCMD_SNAPSHOT="no"
	${VMWARE_CMD} vmsvc/snapshot.remove | grep "snapshotId" > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		NEW_VIMCMD_SNAPSHOT="yes"
	fi

	if [[ "${EMAIL_LOG}" -eq 1 ]] && [[ -f /usr/bin/nc ]] || [[ -f /bin/nc ]]; then
		if [ -f /usr/bin/nc ]; then
			NC_BIN=/usr/bin/nc
		elif [ -f /bin/nc ]; then 
			NC_BIN=/bin/nc
		fi
        else 
		EMAIL_LOG=0
	fi

        if [ ! $(whoami) == "root" ]; then
                logger "info" "This script needs to be executed by \"root\"!"
		echo "ERROR: This script needs to be executed by \"root\"!"
                exit 1
        fi
}

startTimer() {
        START_TIME=$(date)
        S_TIME=$(date +%s)
}

endTimer() {
        END_TIME=$(date)
        E_TIME=$(date +%s)
        DURATION=$(echo $((E_TIME - S_TIME)))

        #calculate overall completion time
        if [ ${DURATION} -le 60 ]; then
                logger "info" "Backup Duration: ${DURATION} Seconds"
        else
                logger "info" "Backup Duration: $(awk 'BEGIN{ printf "%.2f\n", '${DURATION}'/60}') Minutes"
        fi
}

captureDefaultConfigurations() {
	DEFAULT_VM_BACKUP_VOLUME="${VM_BACKUP_VOLUME}"
	DEFAULT_DISK_BACKUP_FORMAT="${DISK_BACKUP_FORMAT}"
	DEFAULT_VM_BACKUP_ROTATION_COUNT="${VM_BACKUP_ROTATION_COUNT}"
	DEFAULT_POWER_VM_DOWN_BEFORE_BACKUP="${POWER_VM_DOWN_BEFORE_BACKUP}"
	DEFAULT_ENABLE_HARD_POWER_OFF="${ENABLE_HARD_POWER_OFF}"
	DEFAULT_ITER_TO_WAIT_SHUTDOWN="${ITER_TO_WAIT_SHUTDOWN}"
	DEFAULT_POWER_DOWN_TIMEOUT="${POWER_DOWN_TIMEOUT}"
	DEFAULT_SNAPSHOT_TIMEOUT="${SNAPSHOT_TIMEOUT}"
	DEFAULT_ENABLE_COMPRESSION="${ENABLE_COMPRESSION}"
	DEFAULT_VM_SNAPSHOT_MEMORY="${VM_SNAPSHOT_MEMORY}"
	DEFAULT_VM_SNAPSHOT_QUIESCE="${VM_SNAPSHOT_QUIESCE}"
	DEFAULT_VMDK_FILES_TO_BACKUP="${VMDK_FILES_TO_BACKUP}"
	DEFAULT_EMAIL_LOG="${EMAIL_LOG}"
	DEFAULT_EMAIL_DEBUG="${EMAIL_DEBUG}"
}

useDefaultConfigurations() {
	VM_BACKUP_VOLUME="${DEFAULT_VM_BACKUP_VOLUME}"
	DISK_BACKUP_FORMAT="${DEFAULT_DISK_BACKUP_FORMAT}"
	VM_BACKUP_ROTATION_COUNT="${DEFAULT_VM_BACKUP_ROTATION_COUNT}"
	POWER_VM_DOWN_BEFORE_BACKUP="${DEFAULT_POWER_VM_DOWN_BEFORE_BACKUP}"
	ENABLE_HARD_POWER_OFF="${DEFAULT_ENABLE_HARD_POWER_OFF}"
	ITER_TO_WAIT_SHUTDOWN="${DEFAULT_ITER_TO_WAIT_SHUTDOWN}"
	POWER_DOWN_TIMEOUT="${DEFAULT_POWER_DOWN_TIMEOUT}"
	SNAPSHOT_TIMEOUT="${DEFAULT_SNAPSHOT_TIMEOUT}"
	ENABLE_COMPRESSION="${DEFAULT_ENABLE_COMPRESSION}"
	VM_SNAPSHOT_MEMORY="${DEFAULT_VM_SNAPSHOT_MEMORY}"
	VM_SNAPSHOT_QUIESCE="${DEFAULT_VM_SNAPSHOT_QUIESCE}"
	VMDK_FILES_TO_BACKUP="all"
	EMAIL_LOG=0
	EMAIL_DEBUG=0
}

reConfigureGhettoVCBConfiguration() {
	GLOBAL_CONF=$1
	
	if [ -f "${GLOBAL_CONF}" ]; then
                . "${GLOBAL_CONF}"
        else
                useDefaultConfigurations
        fi
}

reConfigureBackupParam() {
        VM=$1

        if [ -e "${CONFIG_DIR}/${VM}" ]; then
                logger "info" "CONFIG - USING CONFIGURATION FILE = ${CONFIG_DIR}/${VM}"
                . "${CONFIG_DIR}/${VM}"
        else
                useDefaultConfigurations
        fi
}

dumpHostInfo() {
	VERSION=$(vmware -v)
	logger "debug" "HOST VERSION: ${VERSION}"
	echo ${VERSION} | grep "Server 3i" > /dev/null 2>&1
	if [ $? -eq 1 ]; then
		logger "debug" "HOST LEVEL: $(vmware -l)"
	fi
	logger "debug" "HOSTNAME: $(hostname)\n"
}

findVMDK() {
        VMDK_TO_SEARCH_FOR=$1

	#if [ "${USE_VM_CONF}" -eq 1 ]; then
		logger "debug" "findVMDK() - Searching for VMDK: \"${VMDK_TO_SEARCH_FOR}\" to backup"

		OLD_IFS2="${IFS}"
        	IFS=","
	        for k in ${VMDK_FILES_TO_BACKUP}
        	do
                	VMDK_FILE=$(echo $k | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//')
		        if [ "${VMDK_FILE}" == "${VMDK_TO_SEARCH_FOR}" ]; then
				logger "debug" "findVMDK() - Found VMDK! - \"${VMDK_TO_SEARCH_FOR}\" to backup"
        	                isVMDKFound=1
			fi	
	        done
		IFS="${OLD_IFS2}"
	#fi
}

getVMDKs() {
	#get all VMDKs listed in .vmx file
        VMDKS_FOUND=$(grep -iE '(scsi|ide)' "${VMX_PATH}" | grep -i fileName | awk -F " " '{print $1}')

        TMP_IFS=${IFS}
        IFS=${ORIG_IFS}
        #loop through each disk and verify that it's currently present and create array of valid VMDKS
        for DISK in ${VMDKS_FOUND};
        do
        	#extract the SCSI ID and use it to check for valid vmdk disk
                SCSI_ID=$(echo ${DISK%%.*})
                grep -i "${SCSI_ID}.present" "${VMX_PATH}" | grep -i "true" > /dev/null 2>&1
                #if valid, then we use the vmdk file
                if [ $? -eq 0 ]; then
			#verify disk is not independent
			grep -i "${SCSI_ID}.mode" "${VMX_PATH}" | grep -i "independent" > /dev/null 2>&1 
			if [ $? -eq 1 ]; then
	                	grep -i "${SCSI_ID}.deviceType" "${VMX_PATH}" | grep -i "scsi-hardDisk" > /dev/null 2>&1
        	                #if we find the device type is of scsi-disk, then proceed
                	        if [ $? -eq 0 ]; then
                        		DISK=$(grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | awk -F "\"" '{print $2}')
					echo "${DISK}" | grep "\/vmfs\/volumes" > /dev/null 2>&1
					if [ $? -eq 0 ]; then
						DISK_SIZE_IN_SECTORS=$(cat "${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
					else
						DISK_SIZE_IN_SECTORS=$(cat "${VMX_DIR}/${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
					fi
					DISK_SIZE=$(echo "${DISK_SIZE_IN_SECTORS}" | awk '{printf "%.0f\n",$1*512/1024/1024/1024}')
                                	VMDKS="${DISK}###${DISK_SIZE}:${VMDKS}"
					TOTAL_VM_SIZE=$((TOTAL_VM_SIZE+DISK_SIZE))
	                        else
        	                        #if the deviceType is NULL for IDE which it is, thanks for the inconsistency VMware
                	                #we'll do one more level of verification by checking to see if an ext. of .vmdk exists
                        	        #since we can not rely on the deviceType showing "ide-hardDisk"
                                	grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | grep -i ".vmdk" > /dev/null 2>&1
	                                if [ $? -eq 0 ]; then
        	                	        DISK=$(grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | awk -F "\"" '{print $2}')
						echo "${DISK}" | grep "\/vmfs\/volumes" > /dev/null 2>&1
						if [ $? -eq 0 ]; then
							DISK_SIZE_IN_SECTORS=$(cat "${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
						else
							DISK_SIZE_IN_SECTORS=$(cat "${VMX_DIR}/${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
						fi
						DISK_SIZE=$(echo "${DISK_SIZE_IN_SECTORS}" | awk '{printf "%.0f\n",$1*512/1024/1024/1024}')
                	                        VMDKS="${DISK}###${DISK_SIZE}:${VMDKS}"
						TOTAL_VM_SIZE=$((TOTAL_VM_SIZE_IN+DISK_SIZE))
                        	        fi
                        	fi
			else
				#independent disks are not affected by snapshots, hence they can not be backed up
				DISK=$(grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | awk -F "\"" '{print $2}')
				echo "${DISK}" | grep "\/vmfs\/volumes" > /dev/null 2>&1
				if [ $? -eq 0 ]; then
					DISK_SIZE_IN_SECTORS=$(cat "${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
				else
					DISK_SIZE_IN_SECTORS=$(cat "${VMX_DIR}/${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
				fi
				DISK_SIZE=$(echo "${DISK_SIZE_IN_SECTORS}" | awk '{printf "%.0f\n",$1*512/1024/1024/1024}')
				INDEP_VMDKS="${DISK}###${DISK_SIZE}:${INDEP_VMDKS}"
			fi
                fi
	done
        IFS=${TMP_IFS}
	logger "debug" "getVMDKs() - ${VMDKS}"
}

dumpVMConfigurations() {
	logger "info" "CONFIG - VERSION = ${VERSION_STRING}"
	logger "info" "CONFIG - GHETTOVCB_PID = ${GHETTOVCB_PID}"
	logger "info" "CONFIG - VM_BACKUP_VOLUME = ${VM_BACKUP_VOLUME}"
	if [ "${ENABLE_NON_PERSISTENT_NFS}" -eq 1 ]; then
		logger "info" "CONFIG - ENABLE_NON_PERSISTENT_NFS = ${ENABLE_NON_PERSISTENT_NFS}"
		logger "info" "CONFIG - UNMOUNT_NFS = ${UNMOUNT_NFS}"
		logger "info" "CONFIG - NFS_SERVER = ${NFS_SERVER}"
		logger "info" "CONFIG - NFS_MOUNT = ${NFS_MOUNT}"
	fi
        logger "info" "CONFIG - VM_BACKUP_ROTATION_COUNT = ${VM_BACKUP_ROTATION_COUNT}"
	logger "info" "CONFIG - VM_BACKUP_DIR_NAMING_CONVENTION = ${VM_BACKUP_DIR_NAMING_CONVENTION}"
        logger "info" "CONFIG - DISK_BACKUP_FORMAT = ${DISK_BACKUP_FORMAT}"
        logger "info" "CONFIG - POWER_VM_DOWN_BEFORE_BACKUP = ${POWER_VM_DOWN_BEFORE_BACKUP}"
        logger "info" "CONFIG - ENABLE_HARD_POWER_OFF = ${ENABLE_HARD_POWER_OFF}"
	logger "info" "CONFIG - ITER_TO_WAIT_SHUTDOWN = ${ITER_TO_WAIT_SHUTDOWN}"
	logger "info" "CONFIG - POWER_DOWN_TIMEOUT = ${POWER_DOWN_TIMEOUT}"
	logger "info" "CONFIG - SNAPSHOT_TIMEOUT = ${SNAPSHOT_TIMEOUT}"
        logger "info" "CONFIG - LOG_LEVEL = ${LOG_LEVEL}"
	logger "info" "CONFIG - BACKUP_LOG_OUTPUT = ${LOG_OUTPUT}"
        logger "info" "CONFIG - VM_SNAPSHOT_MEMORY = ${VM_SNAPSHOT_MEMORY}"
        logger "info" "CONFIG - VM_SNAPSHOT_QUIESCE = ${VM_SNAPSHOT_QUIESCE}"
        logger "info" "CONFIG - VMDK_FILES_TO_BACKUP = ${VMDK_FILES_TO_BACKUP}"
	logger "info" "CONFIG - EMAIL_LOG = ${EMAIL_LOG}"
	if [ "${EMAIL_LOG}" -eq 1 ]; then
		logger "info" "CONFIG - EMAIL_DEBUG = ${EMAIL_DEBUG}"
		logger "info" "CONFIG - EMAIL_SERVER = ${EMAIL_SERVER}"
		logger "info" "CONFIG - EMAIL_SERVER_PORT = ${EMAIL_SERVER_PORT}"
		logger "info" "CONFIG - EMAIL_DELAY_INTERVAL = ${EMAIL_DELAY_INTERVAL}"
		logger "info" "CONFIG - EMAIL_FROM = ${EMAIL_FROM}"
		logger "info" "CONFIG - EMAIL_TO = ${EMAIL_TO}"
	fi
	logger "info" ""
}

checkVMBackupRotation() {
	local BACKUP_DIR_PATH=$1
	local VM_TO_SEARCH_FOR=$2

	#default rotation if variable is not defined
        if [ -z ${VM_BACKUP_ROTATION_COUNT} ]; then
                VM_BACKUP_ROTATION_COUNT=1
        fi

	LIST_BACKUPS=$(ls -t "${BACKUP_DIR_PATH}" | grep "${VM_TO_SEARCH_FOR}-[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}_[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}")
	BACKUPS_TO_KEEP=$(ls -t "${BACKUP_DIR_PATH}" | grep "${VM_TO_SEARCH_FOR}-[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}_[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}" | head -"${VM_BACKUP_ROTATION_COUNT}")

	ORIG_IFS=${IFS}
        IFS='
'
        for i in ${LIST_BACKUPS};
        do
                FOUND=0
                for j in ${BACKUPS_TO_KEEP};
                do
                        if [ $i == $j ]; then
                                FOUND=1
                        fi
                done

                if [ $FOUND -eq 0 ]; then
			logger "debug" "Removing $BACKUP_DIR_PATH/$i"
			rm -rf "$BACKUP_DIR_PATH/$i"

			#NFS I/O error handling hack
			if [ $? -ne 0 ]; then
				NFS_IO_HACK_COUNTER=0
				NFS_IO_HACK_STATUS=0
				NFS_IO_HACK_FILECHECK="$BACKUP_DIR_PATH/nfs_io.check"		

				while [ "${NFS_IO_HACK_STATUS}" -eq 0 -a "${NFS_IO_HACK_COUNTER}" -lt 60 ]; 
				do
					sleep 1
					NFS_IO_HACK_COUNTER=$((NFS_IO_HACK_COUNTER+1))
					touch "${NFS_IO_HACK_FILECHECK}"
				
					if [ $? -eq 0 ]; then
						NFS_IO_HACK_STATUS=1
					fi	
				done

				rm -rf "${NFS_IO_HACK_FILECHECK}"

				if [ "${NFS_IO_HACK_STATUS}"  -eq 1 ]; then
					logger "info" "Slept ${NFS_IO_HACK_COUNTER} seconds to work around NFS I/O error"
				else 
					logger "info" "Slept ${NFS_IO_HACK_COUNTER} seconds but failed work around for NFS I/O error"
				fi
			fi
                fi
        done
	IFS=${ORIG_IFS}
}

storageInfo() {
	SECTION=$1

	#SOURCE DATASTORE
        SRC_DATASTORE_CAPACITY=$($VMWARE_CMD hostsvc/datastore/info "${VMFS_VOLUME}" | grep -i "capacity" | awk '{print $3}' | sed 's/,//g')
        SRC_DATASTORE_FREE=$($VMWARE_CMD hostsvc/datastore/info "${VMFS_VOLUME}" | grep -i "freespace" | awk '{print $3}' | sed 's/,//g')
        SRC_DATASTORE_BLOCKSIZE=$($VMWARE_CMD hostsvc/datastore/info "${VMFS_VOLUME}" | grep -i blockSizeMb | awk '{print $3}' | sed 's/,//g')
        if [ -z ${SRC_DATASTORE_BLOCKSIZE} ]; then
        	SRC_DATASTORE_BLOCKSIZE="NA"
                SRC_DATASTORE_MAX_FILE_SIZE="NA"
        else
        	case ${SRC_DATASTORE_BLOCKSIZE} in
                	1)SRC_DATASTORE_MAX_FILE_SIZE="256 GB";;
                        2)SRC_DATASTORE_MAX_FILE_SIZE="512 GB";;
                        4)SRC_DATASTORE_MAX_FILE_SIZE="1024 GB";;
                        8)SRC_DATASTORE_MAX_FILE_SIZE="2048 GB";;
                esac
        fi
        SRC_DATASTORE_CAPACITY_GB=$(echo "${SRC_DATASTORE_CAPACITY}" | awk '{printf "%.1f\n",$1/1024/1024/1024}')
        SRC_DATASTORE_FREE_GB=$(echo "${SRC_DATASTORE_FREE}" | awk '{printf "%.1f\n",$1/1024/1024/1024}')

	#DESTINATION DATASTORE
        DST_VOL_1=$(echo "${VM_BACKUP_VOLUME#/*/*/}")
        DST_DATASTORE=$(echo "${DST_VOL_1%%/*}")
        DST_DATASTORE_CAPACITY=$($VMWARE_CMD hostsvc/datastore/info "${DST_DATASTORE}" | grep -i "capacity" | awk '{print $3}' | sed 's/,//g')
        DST_DATASTORE_FREE=$($VMWARE_CMD hostsvc/datastore/info "${DST_DATASTORE}" | grep -i "freespace" | awk '{print $3}' | sed 's/,//g')
        DST_DATASTORE_BLOCKSIZE=$($VMWARE_CMD hostsvc/datastore/info "${DST_DATASTORE}" | grep -i blockSizeMb | awk '{print $3}' | sed 's/,//g')
       	if [ -z ${DST_DATASTORE_BLOCKSIZE} ]; then
               	DST_DATASTORE_BLOCKSIZE="NA"
                DST_DATASTORE_MAX_FILE_SIZE="NA"
       	else
                case ${DST_DATASTORE_BLOCKSIZE} in
        	        1)DST_DATASTORE_MAX_FILE_SIZE="256 GB";;
                        2)DST_DATASTORE_MAX_FILE_SIZE="512 GB";;
                        4)DST_DATASTORE_MAX_FILE_SIZE="1024 GB";;
                        8)DST_DATASTORE_MAX_FILE_SIZE="2048 GB";;
                esac
       	fi
       	DST_DATASTORE_CAPACITY_GB=$(echo "${DST_DATASTORE_CAPACITY}" | awk '{printf "%.1f\n",$1/1024/1024/1024}')
       	DST_DATASTORE_FREE_GB=$(echo "${DST_DATASTORE_FREE}" | awk '{printf "%.1f\n",$1/1024/1024/1024}')

        logger "debug" "Storage Information ${SECTION} backup: "
        logger "debug" "SRC_DATASTORE: ${VMFS_VOLUME}"
        logger "debug" "SRC_DATASTORE_CAPACITY: ${SRC_DATASTORE_CAPACITY_GB} GB"
        logger "debug" "SRC_DATASTORE_FREE: ${SRC_DATASTORE_FREE_GB} GB"
        logger "debug" "SRC_DATASTORE_BLOCKSIZE: ${SRC_DATASTORE_BLOCKSIZE}"
        logger "debug" "SRC_DATASTORE_MAX_FILE_SIZE: ${SRC_DATASTORE_MAX_FILE_SIZE}"
        logger "debug" ""
        logger "debug" "DST_DATASTORE: ${DST_DATASTORE}"
        logger "debug" "DST_DATASTORE_CAPACITY: ${DST_DATASTORE_CAPACITY_GB} GB"
        logger "debug" "DST_DATASTORE_FREE: ${DST_DATASTORE_FREE_GB} GB"
        logger "debug" "DST_DATASTORE_BLOCKSIZE: ${DST_DATASTORE_BLOCKSIZE}"
        logger "debug" "DST_DATASTORE_MAX_FILE_SIZE: ${DST_DATASTORE_MAX_FILE_SIZE}"
        if [[ "${SRC_DATASTORE_BLOCKSIZE}" != "NA" ]] && [[ "${DST_DATASTORE_BLOCKSIZE}" != "NA" ]]; then
        	if [ "${SRC_DATASTORE_BLOCKSIZE}" -lt "${DST_DATASTORE_BLOCKSIZE}" ]; then
                	logger "debug" ""
                        logger "debug" "SRC VMFS blocksze of ${SRC_DATASTORE_BLOCKSIZE}MB is less than DST VMFS blocksize of ${DST_DATASTORE_BLOCKSIZE}MB which can be an issue for VM snapshots"
                fi
        fi
	logger "debug" ""
}

ghettoVCB() {
	VM_INPUT=$1
	VM_OK=0
	VM_FAILED=0
	VMDK_FAILED=0

	dumpHostInfo

        if [ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ]; then
                VM_BACKUP_VOLUME="/vmfs/volumes/${NFS_LOCAL_NAME}/${NFS_VM_BACKUP_DIR}"
                if [ "${LOG_LEVEL}" !=  "dryrun" ]; then
                        #1 = readonly
                        #0 = readwrite
                        logger "debug" "Mounting NFS: ${NFS_SERVER}:${NFS_MOUNT} to /vmfs/volume/${NFS_LOCAL_NAME}"
			${VMWARE_CMD} hostsvc/datastore/nas_create "${NFS_LOCAL_NAME}" "${NFS_SERVER}" "${NFS_MOUNT}" 0
                fi
        fi

	captureDefaultConfigurations

	if [ "${USE_GLOBAL_CONF}" -eq 1 ]; then
		logger "info" "CONFIG - USING GLOBAL GHETTOVCB CONFIGURATION FILE = ${GLOBAL_CONF}"
	fi

	if [ "${USE_VM_CONF}" -eq 0 ]; then
		dumpVMConfigurations
	fi

	#dump out all virtual machines allowing for spaces now
	${VMWARE_CMD} vmsvc/getallvms | sed 's/[[:blank:]]\{3,\}/   /g' | awk -F'   ' '{print "\""$1"\";\""$2"\";\""$3"\""}' |  sed 's/\] /\]\";\"/g' | sed '1,1d' > /tmp/vms_list

	if [ "${BACKUP_ALL_VMS}" -eq 1 ]; then
		${VMWARE_CMD} vmsvc/getallvms | sed 's/[[:blank:]]\{3,\}/   /g' | awk -F'   ' '{print ""$2""}' | sed '1,1d' | sed '/^$/d' > "${VM_INPUT}"
	fi

	ORIG_IFS=${IFS}
	IFS='
'
	for VM_NAME in $(cat "${VM_INPUT}" | grep -v "#" | sed '/^$/d' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//');
        do
		IGNORE_VM=0
		if [ "${EXCLUDE_SOME_VMS}" -eq 1 ]; then
			grep -E "${VM_NAME}" "${VM_EXCLUSION_FILE}" > /dev/null 2>&1
			if [ $? -eq 0 ]; then
				IGNORE_VM=1
			fi
		fi
	
		VM_ID=$(grep -E "\"${VM_NAME}\"" /tmp/vms_list | awk -F ";" '{print $1}' | sed 's/"//g')

		#ensure default value if one is not selected or variable is null
                if [ -z ${VM_BACKUP_DIR_NAMING_CONVENTION} ]; then
                        VM_BACKUP_DIR_NAMING_CONVENTION="$(date +%F_%k-%M-%S)"
                fi

		if [[ "${USE_VM_CONF}" -eq 1 ]] && [[ ! -z ${VM_ID} ]]; then
                        reConfigureBackupParam "${VM_NAME}"
                        dumpVMConfigurations
                fi

		VMFS_VOLUME=$(grep -E "\"${VM_NAME}\"" /tmp/vms_list | awk -F ";" '{print $3}' | sed 's/\[//;s/\]//;s/"//g')
		VMX_CONF=$(grep -E "\"${VM_NAME}\"" /tmp/vms_list | awk -F ";" '{print $4}' | sed 's/\[//;s/\]//;s/"//g')
		VMX_PATH="/vmfs/volumes/${VMFS_VOLUME}/${VMX_CONF}"
		VMX_DIR=$(dirname "${VMX_PATH}")

		#storage info
		if [[ ! -z ${VM_ID} ]] && [[ "${LOG_LEVEL}" != "dryrun" ]]; then
			storageInfo "before"
		fi

		#ignore VM as it's in the exclusion list
		if [ "${IGNORE_VM}" -eq 1 ]; then 
			logger "debug" "Ignoring ${VM_NAME} for backup since its located in exclusion list\n"			
		#checks to see if we can pull out the VM_ID
		elif [ -z ${VM_ID} ]; then
			logger "info" "ERROR: failed to locate and extract VM_ID for ${VM_NAME}!\n"
			VM_FAILED=1

		elif [ "${LOG_LEVEL}" == "dryrun" ]; then
			logger "dryrun" "###############################################"
			logger "dryrun" "Virtual Machine: $VM_NAME"
			logger "dryrun" "VM_ID: $VM_ID"
			logger "dryrun" "VMX_PATH: $VMX_PATH"
			logger "dryrun" "VMX_DIR: $VMX_DIR"
			logger "dryrun" "VMX_CONF: $VMX_CONF"
			logger "dryrun" "VMFS_VOLUME: $VMFS_VOLUME"
			logger "dryrun" "VMDK(s): "
			TOTAL_VM_SIZE=0
			getVMDKs
			OLD_IFS="${IFS}"
                        IFS=":"
                        for j in ${VMDKS};
                        do
				J_VMDK=$(echo "${j}" | awk -F "###" '{print $1}')
				J_VMDK_SIZE=$(echo "${j}" | awk -F "###" '{print $2}')
				logger "dryrun" "\t${J_VMDK}\t${J_VMDK_SIZE} GB"
			done
			HAS_INDEPENDENT_DISKS=0
			logger "dryrun" "INDEPENDENT VMDK(s): "
			for k in ${INDEP_VMDKS};
			do
				HAS_INDEPENDENT_DISKS=1
				K_VMDK=$(echo "${k}" | awk -F "###" '{print $1}')
				K_VMDK_SIZE=$(echo "${k}" | awk -F "###" '{print $2}')
				logger "dryrun" "\t${K_VMDK}\t${K_VMDK_SIZE} GB"
			done
			IFS="${OLD_IFS}"
			VMDKS=""
			INDEP_VMDKS=""
			logger "dryrun" "TOTAL_VM_SIZE_TO_BACKUP: ${TOTAL_VM_SIZE} GB"
			if [ ${HAS_INDEPENDENT_DISKS} -eq 1 ]; then
				logger "dryrun" "Snapshots can not be taken for indepdenent disks!"
				logger "dryrun" "THIS VIRTUAL MACHINE WILL NOT HAVE ALL ITS VMDKS BACKED UP!"
			fi

			ls "${VMX_DIR}" | grep -q "\-delta\.vmdk" > /dev/null 2>&1;
			if [ $? -eq 0 ]; then
				logger "dryrun" "Snapshots found for this VM, please commit all snapshots before continuing!"
				logger "dryrun" "THIS VIRTUAL MACHINE WILL NOT BE BACKED UP DUE TO EXISTING SNAPSHOTS!"
			fi

			if [ ${TOTAL_VM_SIZE} -eq 0 ]; then
				logger "dryrun" "THIS VIRTUAL MACHINE WILL NOT BE BACKED UP DUE TO EMPTY VMDK LIST!"
			fi
			logger "dryrun" "###############################################\n"

                #checks to see if the VM has any snapshots to start with
                elif ls "${VMX_DIR}" | grep -q "\-delta\.vmdk" > /dev/null 2>&1; then
	                logger "info" "Snapshot found for ${VM_NAME}, backup will not take place\n"
			VM_FAILED=1

                elif [[ -f "${VMX_PATH}" ]] && [[ ! -z "${VMX_PATH}" ]]; then
		 	#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
                                        logger "info" "ERROR: Variable BACKUP_DIR was not set properly, please ensure all required variables for non-persistent NFS backup option has been defined"
                                        exit 1
                                fi

	              	#non-nfs (SAN,LOCAL)  	
	                else
	                	BACKUP_DIR="${VM_BACKUP_VOLUME}/${VM_NAME}"
                                if [[ -z ${VM_BACKUP_VOLUME} ]]; then
                                        logger "info" "ERROR: Variable VM_BACKUP_VOLUME was not defined"
                                        exit 1
                                fi
	                fi

			#initial root VM backup directory
			if [ ! -d "${BACKUP_DIR}" ]; then
				mkdir -p "${BACKUP_DIR}"
				if [ ! -d "${BACKUP_DIR}" ]; then
					logger "info" "Unable to create \"${BACKUP_DIR}\"! - Ensure VM_BACKUP_VOLUME was defined correctly"
					exit 1
				fi
	                fi

			# directory name of the individual Virtual Machine backup followed by naming convention followed by count
			VM_BACKUP_DIR="${BACKUP_DIR}/${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}"

			# Rsync relative path variable if needed
			RSYNC_LINK_DIR="./${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}"

			mkdir -p "${VM_BACKUP_DIR}"

			cp "${VMX_PATH}" "${VM_BACKUP_DIR}"

			#new variable to keep track on whether VM has independent disks
			VM_HAS_INDEPENDENT_DISKS=0

			#extract all valid VMDK(s) from VM
			getVMDKs

			if [ ! -z ${INDEP_VMDKS} ]; then
				VM_HAS_INDEPENDENT_DISKS=1
			fi

			ORGINAL_VM_POWER_STATE=$(${VMWARE_CMD} vmsvc/power.getstate ${VM_ID} | tail -1)
			CONTINUE_TO_BACKUP=1	
	
			#section that will power down a VM prior to taking a snapshot and backup and power it back on
			if [ ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]; then
				START_ITERATION=0
				logger "info" "Powering off initiated for ${VM_NAME}, backup will not begin until VM is off..."

				${VMWARE_CMD} vmsvc/power.shutdown ${VM_ID} > /dev/null 2>&1
				while ${VMWARE_CMD} vmsvc/power.getstate ${VM_ID} | grep -i "Powered on" > /dev/null 2>&1;
				do
					#enable hard power off code
					if [ ${ENABLE_HARD_POWER_OFF} -eq 1 ]; then
						if [ ${START_ITERATION} -ge ${ITER_TO_WAIT_SHUTDOWN} ]; then
							logger "info" "Hard power off occured for ${VM_NAME}, waited for $((ITER_TO_WAIT_SHUTDOWN*60)) seconds" 
							${VMWARE_CMD} vmsvc/power.off ${VM_ID} > /dev/null 2>&1 
							#this is needed for ESXi, even the hard power off did not take affect right away
							sleep 60
							break
						fi
					fi

					logger "info" "VM is still on - Iteration: ${START_ITERATION} - sleeping for 60secs (Duration: $((START_ITERATION*60)) seconds)"
        	                        sleep 60

					#logic to not backup this VM if unable to shutdown
					#after certain timeout period
					if [ ${START_ITERATION} -ge ${POWER_DOWN_TIMEOUT} ]; then
						logger "info" "Unable to power off ${VM_NAME}, waited for $((POWER_DOWN_TIMEOUT*60)) seconds! Ignoring ${VM_NAME} for backup!"
						VM_FAILED=1
						CONTINUE_TO_BACKUP=0
						break
					fi
					START_ITERATION=$((START_ITERATION + 1))
				done
				if [ ${CONTINUE_TO_BACKUP} -eq 1 ]; then
					logger "info" "VM is powerdOff"
				fi
			fi

			if [ ${CONTINUE_TO_BACKUP} -eq 1 ]; then 
				logger "info" "Initiate backup for ${VM_NAME}"
				startTimer

				SNAP_SUCCESS=1
				VM_VMDK_FAILED=0

				#powered on VMs only
                        	if [[ ! ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" != "Powered off" ]]; then
					SNAPSHOT_NAME="ghettoVCB-snapshot-$(date +%F)"
					logger "info" "Creating Snapshot \"${SNAPSHOT_NAME}\" for ${VM_NAME}"
        	                        ${VMWARE_CMD} vmsvc/snapshot.create ${VM_ID} "${SNAPSHOT_NAME}" "${SNAPSHOT_NAME}" "${VM_SNAPSHOT_MEMORY}" "${VM_SNAPSHOT_QUIESCE}" > /dev/null 2>&1

					logger "debug" "Waiting for snapshot \"${SNAPSHOT_NAME}\" to be created"
					logger "debug" "Snapshot timeout set to: $((SNAPSHOT_TIMEOUT*60)) seconds"
                                        START_ITERATION=0
					while [ $(${VMWARE_CMD} vmsvc/snapshot.get ${VM_ID} | wc -l) -eq 1 ]
					do
						if [ ${START_ITERATION} -ge ${SNAPSHOT_TIMEOUT} ]; then
							logger "info" "Snapshot timed out, failed to create snapshot: \"${SNAPSHOT_NAME}\" for ${VM_NAME}"
							SNAP_SUCCESS=0
							echo "ERROR: Unable to backup ${VM_NAME} due to snapshot creation" >> ${VM_BACKUP_DIR}/STATUS.error
							break
						fi

						logger "debug" "Waiting for snapshot creation to be completed - Iteration: ${START_ITERATION} - sleeping for 60secs (Duration: $((START_ITERATION*30)) seconds)"
                                                sleep 60
						
						START_ITERATION=$((START_ITERATION + 1))
					done
                	        fi

				if [ ${SNAP_SUCCESS} -eq 1 ]; then 
					OLD_IFS="${IFS}"
					IFS=":"
					for j in ${VMDKS};
					do
						VMDK=$(echo "${j}" | awk -F "###" '{print $1}')
						isVMDKFound=0
		
						findVMDK "${VMDK}"

						if [[ $isVMDKFound -eq 1 ]] || [[ "${VMDK_FILES_TO_BACKUP}" == "all" ]]; then 
							#added this section to handle VMDK(s) stored in different datastore than the VM
							echo ${VMDK} | grep "^/vmfs/volumes" > /dev/null 2>&1
							if [ $? -eq 0 ]; then
								SOURCE_VMDK="${VMDK}"
								DS_UUID="$(echo ${VMDK#/vmfs/volumes/*})"
								DS_UUID="$(echo ${DS_UUID%/*/*})"
								VMDK_DISK="$(echo ${VMDK##/*/})"
								mkdir -p "${VM_BACKUP_DIR}/${DS_UUID}"
								DESTINATION_VMDK="${VM_BACKUP_DIR}/${DS_UUID}/${VMDK_DISK}"
							else
								SOURCE_VMDK="${VMX_DIR}/${VMDK}"
								DESTINATION_VMDK="${VM_BACKUP_DIR}/${VMDK}"
							fi
	
							#support for vRDM and deny pRDM
							grep "vmfsPassthroughRawDeviceMap" "${SOURCE_VMDK}" > /dev/null 2>&1
							if [ $? -eq 1 ]; then
								FORMAT_OPTION="UNKNOWN"
								if [ "${DISK_BACKUP_FORMAT}" == "zeroedthick" ]; then
									if [[ "${VER}" == "4" ]] || [[ "${VER}" == "5" ]] ; then
										FORMAT_OPTION="zeroedthick"
									else
										FORMAT_OPTION=""
									fi
		        		        	        elif [ "${DISK_BACKUP_FORMAT}" == "2gbsparse" ]; then
									FORMAT_OPTION="2gbsparse"
		                		        	elif [ "${DISK_BACKUP_FORMAT}" == "thin" ]; then
									 FORMAT_OPTION="thin"
				                	        elif [ "${DISK_BACKUP_FORMAT}" == "eagerzeroedthick" ]; then
									if [[ "${VER}" == "4" ]] || [[ "${VER}" == "5" ]] ; then
										FORMAT_OPTION="eagerzeroedthick"
                        	        				else
										FORMAT_OPTION=""
	                                        			fi
	        	                        		fi

								if  [ "${FORMAT_OPTION}" == "UNKNOWN" ]; then
									logger "info" "ERROR: wrong DISK_BACKUP_FORMAT \"${DISK_BACKUP_FORMAT}\ specified for ${VM_NAME}"
									VM_VMDK_FAILED=1
								else
									VMDK_OUTPUT=$(mktemp /tmp/ghettovcb.XXXXXX)
									tail -f "${VMDK_OUTPUT}" &
									TAIL_PID=$!

									ADAPTER_FORMAT=$(grep -i "ddb.adapterType" "${SOURCE_VMDK}" | awk -F "=" '{print $2}' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//;s/"//g')

									if  [ -z "${FORMAT_OPTION}" ] ; then
										logger "debug" "${VMKFSTOOLS_CMD} -i \"${SOURCE_VMDK}\" -a \"${ADAPTER_FORMAT}\" \"${DESTINATION_VMDK}\""
										${VMKFSTOOLS_CMD} -i "${SOURCE_VMDK}" -a "${ADAPTER_FORMAT}" "${DESTINATION_VMDK}" > "${VMDK_OUTPUT}" 2>&1					
									else 
										logger "debug" "${VMKFSTOOLS_CMD} -i \"${SOURCE_VMDK}\" -a \"${ADAPTER_FORMAT}\" -d \"${FORMAT_OPTION}\" \"${DESTINATION_VMDK}\""
										${VMKFSTOOLS_CMD} -i "${SOURCE_VMDK}" -a "${ADAPTER_FORMAT}" -d "${FORMAT_OPTION}" "${DESTINATION_VMDK}" > "${VMDK_OUTPUT}" 2>&1
									fi
									
									VMDK_EXIT_CODE=$?
									kill "${TAIL_PID}"
									cat "${VMDK_OUTPUT}" >> "${REDIRECT}"
									echo >> "${REDIRECT}"
									echo
									rm "${VMDK_OUTPUT}"

									if [ "${VMDK_EXIT_CODE}" != 0 ] ; then
										logger "info" "ERROR: error in backing up of \"${SOURCE_VMDK}\" for ${VM_NAME}"
										VM_VMDK_FAILED=1
									fi
								fi
							else
                	        	        		logger "info" "WARNING: A physical RDM \"${SOURCE_VMDK}\" was found for ${VM_NAME}, which will not be backed up"
								VM_VMDK_FAILED=1
                        				fi
						fi
					done
					IFS="${OLD_IFS}"
				fi

				#powered on VMs only w/snapshots
                        	if [[ ${SNAP_SUCCESS} -eq 1 ]] && [[ ! ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" == "Powered on" ]] || [[ "${ORGINAL_VM_POWER_STATE}" == "Suspended" ]]; then
					if [ "${NEW_VIMCMD_SNAPSHOT}" == "yes" ]; then
						SNAPSHOT_ID=$(${VMWARE_CMD} vmsvc/snapshot.get ${VM_ID} | grep -E '(Snapshot Name|Snapshot Id)' | grep -A1 ${SNAPSHOT_NAME} | grep "Snapshot Id" | awk -F ":" '{print $2}' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//')
						${VMWARE_CMD} vmsvc/snapshot.remove ${VM_ID} ${SNAPSHOT_ID} > /dev/null 2>&1
					else
                                		${VMWARE_CMD} vmsvc/snapshot.remove ${VM_ID} > /dev/null 2>&1
					fi

	                                #do not continue until all snapshots have been committed
        	                        logger "info" "Removing snapshot from ${VM_NAME} ..."
                	                while ls "${VMX_DIR}" | grep -q "\-delta\.vmdk";
                        	        do
                                	        sleep 5
	                                done
        	                fi

				if [[ ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" == "Powered on" ]]; then
        	                        #power on vm that was powered off prior to backup
                	                logger "info" "Powering back on ${VM_NAME}"
                        	        ${VMWARE_CMD} vmsvc/power.on ${VM_ID} > /dev/null 2>&1
	                        fi

				TMP_IFS=${IFS}
                	        IFS=${ORIG_IFS}
	                        if [ ${ENABLE_COMPRESSION} -eq 1 ]; then
					COMPRESSED_ARCHIVE_FILE="${BACKUP_DIR}/${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}.gz"

        	                        logger "info" "Compressing VM backup \"${COMPRESSED_ARCHIVE_FILE}\"..."
					if [ ${IS_4I} -eq 1 ]; then
						busybox tar -cz -C "${BACKUP_DIR}" "${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}" -f "${COMPRESSED_ARCHIVE_FILE}"
					else 
						tar -cz -C "${BACKUP_DIR}" "${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}" -f "${COMPRESSED_ARCHIVE_FILE}"
					fi
					
					# verify compression
					if [[ $? -eq 0 ]] && [[ -f "${COMPRESSED_ARCHIVE_FILE}" ]]; then
						logger "info" "Successfully compressed backup for ${VM_NAME}!\n"
						COMPRESSED_OK=1
					else
						logger "info" "Error in compressing ${VM_NAME}!\n"
						COMPRESSED_OK=0
					fi
                	                rm -rf "${VM_BACKUP_DIR}"
					checkVMBackupRotation "${BACKUP_DIR}" "${VM_NAME}"
	                        else
        	                	checkVMBackupRotation "${BACKUP_DIR}" "${VM_NAME}"
                	        fi
                        	IFS=${TMP_IFS}
	                        VMDKS=""
				INDEP_VMDKS=""

				endTimer
				if [ ${SNAP_SUCCESS} -ne 1 ]; then
					logger "info" "ERROR: Unable to backup ${VM_NAME} due to snapshot creation!\n"
					[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "ERROR: Unable to backup ${VM_NAME} due to snapshot creation" >> ${VM_BACKUP_DIR}/STATUS.error
					VM_FAILED=1
				elif [ ${VM_VMDK_FAILED} -ne 0 ]; then
					logger "info" "ERROR: Unable to backup ${VM_NAME} due to error in VMDK backup!\n"
					[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "ERROR: Unable to backup ${VM_NAME} due to error in VMDK backup" >> ${VM_BACKUP_DIR}/STATUS.error
					VMDK_FAILED=1
				elif [ ${VM_HAS_INDEPENDENT_DISKS} -eq 1 ]; then
					logger "info" "WARN: ${VM_NAME} has some Independent VMDKs that can not be backed up!\n";
					[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "WARN: ${VM_NAME} has some Independent VMDKs that can not be backed up" > ${VM_BACKUP_DIR}/STATUS.warn
					VMDK_FAILED=1
					#experimental
                                        #create symlink for the very last backup to support rsync functionality for additinal replication
                                        if [ "${RSYNC_LINK}" -eq 1 ]; then
                                                SYMLINK_DST=${VM_BACKUP_DIR}
                                                if [ ${ENABLE_COMPRESSION} -eq 1 ]; then
                                                        SYMLINK_DST1="${RSYNC_LINK_DIR}.gz"
                                                else
                                                        SYMLINK_DST1=${RSYNC_LINK_DIR}
                                                fi
                                                SYMLINK_SRC="$(echo "${SYMLINK_DST%*-*-*-*_*-*-*}")-symlink"
                                                logger "info" "Creating symlink \"${SYMLINK_SRC}\" to \"${SYMLINK_DST1}\""
                                                ln -sf "${SYMLINK_DST1}" "${SYMLINK_SRC}"
                                        fi

                                        #storage info after backup
                                        storageInfo "after"
				else
					logger "info" "Successfully completed backup for ${VM_NAME}!\n"
					[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "Successfully completed backup" > ${VM_BACKUP_DIR}/STATUS.ok
					VM_OK=1
				
					#experimental
				        #create symlink for the very last backup to support rsync functionality for additinal replication
				        if [ "${RSYNC_LINK}" -eq 1 ]; then
						SYMLINK_DST=${VM_BACKUP_DIR}
						if [ ${ENABLE_COMPRESSION} -eq 1 ]; then
							SYMLINK_DST1="${RSYNC_LINK_DIR}.gz"
						else
							SYMLINK_DST1=${RSYNC_LINK_DIR}
						fi
						SYMLINK_SRC="$(echo "${SYMLINK_DST%*-*-*-*_*-*-*}")-symlink"
				                logger "info" "Creating symlink \"${SYMLINK_SRC}\" to \"${SYMLINK_DST1}\""
				                ln -sf "${SYMLINK_DST1}" "${SYMLINK_SRC}"
				        fi

					#storage info after backup
                        		storageInfo "after"
				fi
	                else
				if [ ${CONTINUE_TO_BACKUP} -eq 0 ]; then
					logger "info" "ERROR: Failed to backup ${VM_NAME}!\n"
					VM_FAILED=1
				else
        	                	logger "info" "ERROR: Failed to lookup ${VM_NAME}!\n"
					VM_FAILED=1
				fi
	                fi	
		fi
        done
	unset IFS

        if [[ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ]] && [[ ${UNMOUNT_NFS} -eq 1 ]] && [[ "${LOG_LEVEL}" != "dryrun" ]]; then
		logger "debug" "Sleeping for 30seconds before unmounting NFS volume"
		sleep 30
		${VMWARE_CMD} hostsvc/datastore/destroy ${NFS_LOCAL_NAME}	
	fi
}

getFinalStatus() {
	if [[ "${LOG_TYPE}" == "dryrun" ]]; then
		FINAL_STATUS="###### Final status: OK, only a dryrun. ######"
		LOG_STATUS="OK"
		EXIT=0
	elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 0 ]] && [[ $VMDK_FAILED == 0 ]]; then
		FINAL_STATUS="###### Final status: All VMs backed up OK! ######"
		LOG_STATUS="OK"
		EXIT=0
	elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 0 ]] && [[ $VMDK_FAILED == 1 ]]; then
		FINAL_STATUS="###### Final status: WARNING: All VMs backed up, but some disk(s) failed! ######"
		LOG_STATUS="WARNING"
		EXIT=3
	elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 1 ]] && [[ $VMDK_FAILED == 0 ]]; then
		FINAL_STATUS="###### Final status: ERROR: Only some of the VMs backed up! ######"
		LOG_STATUS="ERROR"
		EXIT=4
	elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 1 ]] && [[ $VMDK_FAILED == 1 ]]; then
		FINAL_STATUS="###### Final status: ERROR: Only some of the VMs backed up, and some disk(s) failed! ######"
		LOG_STATUS="ERROR"
		EXIT=5
	elif [[ $VM_OK == 0 ]] && [[ $VM_FAILED == 1 ]]; then
		FINAL_STATUS="###### Final status: ERROR: All VMs failed! ######"
		LOG_STATUS="ERROR"
		EXIT=6
	elif [[ $VM_OK == 0 ]]; then
		FINAL_STATUS="###### Final status: ERROR: No VMs backed up! ######"
		LOG_STATUS="ERROR"
		EXIT=7
	fi
	logger "info" "$FINAL_STATUS\n"
}

buildHeaders() {
	EMAIL_ADDRESS=$1	

	echo -ne "HELO $(hostname -s)\r\n" > "${EMAIL_LOG_HEADER}"
        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}"
        echo -ne "From: ${EMAIL_FROM}\r\n" >> "${EMAIL_LOG_HEADER}"
        echo -ne "To: ${EMAIL_ADDRESS}\r\n" >> "${EMAIL_LOG_HEADER}"
        echo -ne "Subject: ghettoVCB - ${FINAL_STATUS}\r\n" >> "${EMAIL_LOG_HEADER}"

        echo -en ".\r\n" >> "${EMAIL_LOG_OUTPUT}"
        echo -en "QUIT\r\n" >> "${EMAIL_LOG_OUTPUT}"

        cat "${EMAIL_LOG_HEADER}" > "${EMAIL_LOG_CONTENT}"
        cat "${EMAIL_LOG_OUTPUT}" >> "${EMAIL_LOG_CONTENT}"
}

sendMail() {
	#close email message
	if [ "${EMAIL_LOG}" -eq 1 ]; then
		#validate firewall has email port open for ESXi 5
		if [ "${VER}" == "5" ]; then
			/sbin/esxcli network firewall ruleset rule list | grep "${EMAIL_SERVER_PORT}" > /dev/null 2>&1
			if [ $? -eq 1 ]; then
				logger "info" "ERROR: Please enable firewall rule for email traffic on port ${EMAIL_SERVER_PORT}\n"
				logger "info" "Please refer to ghettoVCB documentation for ESXi 5 firewall configuration\n"
			fi
		fi

		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
				if [ $? -eq 1 ]; then
					logger "info" "ERROR: Failed to email log output to ${EMAIL_SERVER}:${EMAIL_SERVER_PORT} to ${EMAIL_TO}\n"
				fi
			done
			unset IFS
		else
			buildHeaders ${EMAIL_TO}
			"${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}" < "${EMAIL_LOG_CONTENT}" > /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
			
		if [ "${EMAIL_DEBUG}" -eq 1 ]; then
			logger "info" "Email log output will not be deleted and is stored in ${EMAIL_LOG_CONTENT}"
		else
			logger "info" "Removing ${EMAIL_LOG_OUTPUT} and ${EMAIL_LOG_HEADER} and ${EMAIL_LOG_CONTENT}"
			rm -f "${EMAIL_LOG_OUTPUT}"
			rm -f "${EMAIL_LOG_HEADER}"
			rm -f "${EMAIL_LOG_CONTENT}"
		fi
	fi
}

####################
#		   #
# Start of Script  #
#		   #
####################

IS_4I=0

if [ ! -f /bin/bash ]; then
	IS_4I=1
fi

USE_VM_CONF=0
USE_GLOBAL_CONF=0
BACKUP_ALL_VMS=0
EXCLUDE_SOME_VMS=0
EMAIL_LOG_HEADER=/tmp/ghettoVCB-email-$$.header
EMAIL_LOG_OUTPUT=/tmp/ghettoVCB-email-$$.log
EMAIL_LOG_CONTENT=/tmp/ghettoVCB-email-$$.content

#read user input
while getopts ":af:c:g:l:d:e:" ARGS; do
        case $ARGS in
		a)
			BACKUP_ALL_VMS=1
			VM_FILE="/tmp/backup_all_vms_on-$(hostname)"
			touch "${VM_FILE}"
			;;			
                f)      VM_FILE="${OPTARG}"
                        ;;
		e)
			VM_EXCLUSION_FILE="${OPTARG}"
			EXCLUDE_SOME_VMS=1
			;;
		c)
			CONFIG_DIR="${OPTARG}"
			USE_VM_CONF=1
			;;
		g)
			GLOBAL_CONF="${OPTARG}"
			USE_GLOBAL_CONF=1
			;;
                l)
                        LOG_OUTPUT="${OPTARG}"
                        ;;
                d)
                        LOG_LEVEL="${OPTARG}"
                        ;;
                :)
                        echo "Option -${OPTARG} requires an argument."
                        exit 1
                        ;;
                *)
			printUsage
                        exit 1
                        ;;
        esac
done

#performs a check on the number of commandline arguments + verifies $2 is a valid file
sanityCheck $# 

LOCKDIR=/tmp/ghettoVCB.lock

if mkdir "${LOCKDIR}"
then
	GHETTOVCB_PID=$$

	logger "info" "============================== ghettoVCB LOG START ==============================\n"
	logger "debug" "Succesfully acquired lock directory - ${LOCKDIR}\n"
	
	# Remove lockdir when the script finishes, or when it receives a signal
	trap 'rm -rf "${LOCKDIR}"' 0    # remove directory when script finishes
	trap "exit 2" 1 2 3 13 15       # terminate script when receiving signal

	ghettoVCB ${VM_FILE}

	getFinalStatus

	logger "debug" "Succesfully removed lock directory - ${LOCKDIR}\n"
	logger "info" "============================== ghettoVCB LOG END ================================\n"

	sendMail

	rm -rf "${LOCKDIR}"
	exit $EXIT
else 
	logger "info" "Failed to acquire lock, another instance of script may be running, giving up on ${LOCKDIR}\n"
	exit 1
fi

Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы