#!/bin/sh
#################################################################################
#                                                                               #
#    XSIBACKUP Automated Backups for ESXi 5.1, 5.5 & 6.0                        #
#    By Daniel J. Garcia Fidalgo (33HOPS) daniel.garcia@33hops.com              #
#    Copyright (C) 2013-2016  33HOPS, Sistemas de Informacin y Redes, S.L.     #
#    ALL RIGHTS RESERVED                                                        #
#                                                                               #	
#################################################################################

PWD=$(pwd)

APPNAM="XSIBACKUP-FREE"
APPVER="6.0.4"
APPCOM=" VMWARE ESXi Hypervisor"
OLDIFS=$IFS
newline=$'\012'
backuproom=0
xsidefaultpath="/vmfs/volumes/datastore1/xsi-dir"
HOSTNAME=$(hostname -f)
HOSTIP=$(esxcli network ip interface ipv4 get -i vmk0 | grep vmk0 | awk '{ print $2 }')
HOSTMASK=$(esxcli network ip interface ipv4 get -i vmk0 | grep vmk0 | awk '{ print $3 }')
CURRDIR=$(dirname $0)

xsib_shutdown(){
	if [ -f "$PWD"/xsibackup-pid ]
	then
	    pid=$( cat "$PWD"/xsibackup-pid )
	    if [ "$pid" == "$$" ]
	    then
	    	KRET=$( kill -9 $pid > /dev/null 2>&1 )
	    	rm -rf "$PWD"/xsibackup-pid > /dev/null 2>&1
	    fi
	fi
}

trap "echo \"\";echo -e \"\033[0;32mShutting down nicely...\033[0m\" ; xsib_shutdown & exit 0" SIGINT SIGTERM

DEBUGINFO=""

keyvalstr="$@"
keyvalstr=${keyvalstr//--/}

IFS=""
for block in $keyvalstr
do
    if [ ! -z "$block" ]
    then
        VARNAM=$( echo $block | awk -F "=" '{print $1}' | sed -e 's/^ *//g' -e 's/ *$//g' )
        VARNAM=${VARNAM//-/}
        VARVAL="$( echo $block | awk -F "=" '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' )"
        VARVAL="${VARVAL//"/\"}"
        if [ "$VARNAM" != "smtppwd" -a "$VARNAM" != "backupvms" -a "$VARNAM" != "backuppoint" ]
        then
                VARVAL=$( echo "$VARVAL" | awk '{print tolower($0)}' )
                DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;${VARNAM}:&nbsp;$VARVAL"
        fi
    	eval $VARNAM=\""$VARVAL"\"
    fi
done
IFS=$OLDIFS

keyvalstr=${keyvalstr///--}

datedir=$( echo $datedir | awk '{print tolower($0)}' )

DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;DATE DIR: $datedir"

if [ "${CURRDIR:0:1}" = "/" ]
then
        PWD="$CURRDIR"
else
        CURRDIR=${CURRDIR//./}
        PWD="$PWD""$CURRDIR"
fi

DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;XSIDIR: $PWD"

# Find out if we are in interactive mode
if [ -t 1 ]
then 
	launched="user"
else
	launched="cron"
fi

DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;LAUNCHED BY: $launched"

if [ "$backuphow" != "cold" ]
then
	backuphow="hot"
fi

if [ -z $from ] && [ "$launched" == "cron" ]
then
	if [ "$exec" = "yes" ]
	then
		righttime=1
	elif [ ! -z "${time}" ]
	then
		righttime=0
		IFS="|"
		for moment in $time	
		do
			NOW="$( date +"%a %H:%M" | awk '{print tolower($0)}' )"
			if [ "$moment" == "$NOW" ]
			then
				righttime=1
			fi
		done
		IFS=$OLDIFS
	
		if [ ${righttime} == 0 ]
		then
			exit 0
		fi	
	else
		#echo -e "\033[1;31mSet the --time argument to launch a job from the cron file.\033[0m"
		exit 0
	fi

	echo -ne "\033[1;36mAs a preventive measure XSIBackup will now restart the ESXi cron service:\033[0m"
	/bin/kill -9 $(cat /var/run/crond.pid) && /usr/lib/vmware/busybox/bin/busybox crond
	echo -e " \033[0;32mDONE\033[0m"

elif [ "$launched" == "user" ]
then
	trap "echo -e \"\033[0;32mCleaning up...\033[0m\" ; xsib_shutdown" EXIT

	if [ -f "${PWD}/xsibackup-pid" ]
	then
            echo "There is an xsibackup-pid file present at the working dir"
            echo "Please remove it manually if you are sure there aren't any xsibackup processes running now."
            echo -e "Execute this: \033[1;36mrm -rf $PWD/xsibackup-pid\033[0m"
            exit 0
	fi
	if [ -f "$PWD/EULA" ]
	then
        	EULATEXT=$(cat "$PWD/EULA")
        	EULATEXT="$EULATEXT"
		READEULA=$(cat "$PWD/EULA" | head -n1)
        	READEULA="$READEULA"
		eval $READEULA
        	if [ "$read" == "0" ]
        	then
                	echo -e "$EULATEXT" | sed 1d | more
                	echo ""
                	read -p "I ACCEPT THE LICENSE AGREEMENT (y/n) " yn
                	case $yn in
                	[Yy]* )
                        	sed -i 's/read=0/read=1/g' EULA
                	;;
                	[Nn]* ) exit 0;;
                	* ) echo "Please answer (y)es or (n)o."; exit 0;;
                	esac
        	fi
	else
        	echo -e "\033[1;31mCannot find the EULA. The license agreement file [$PWD/EULA] must be kept.\033[0m"
        	exit 0
	fi
fi

checksrv(){
        OLDIFS=$IFS
        s=0
        IFS=':'
        for srvpart in $1
        do
                if [[ $s -eq 0 ]]
                then
                        srvaddr=$srvpart
                elif [[ $s -eq 1 ]]
                then
                        srvport=$srvpart
                fi
        s=$(($s+1))
        done
        IFS=$OLDIFS

        scanresp=$( nc $srvaddr $srvport -w 1 )

        if [[ "${scanresp/$2/}" != "$scanresp" ]]
        then
                echo -n "1"
        else
                echo -e "\033[1;31mThe server $1 cannot be contacted\033[0m"
                exit 1
        fi
        IFS=$OLDIFS
}

compHashes(){
        
	r1=${1// /\ }
        r2=${2// /\ }

        if [ -f "$r1" ]
        then
                md5hash1=$( md5sum "$r1" | awk -F " " '{print $1}' )
        else
                md5hash1=""
                echo "The file ${r1} does not exist"
                exit 1
        fi

        if [ -f "$r2" ]
        then
                md5hash2=$( md5sum "$r2" | awk -F " " '{print $1}' )
        else

                IFS=":"
                s=1
                for spart in $r2
                do
                        eval "srv"$s=\""$spart"\"
                s=$(($s+1))
                done
                IFS=$OLDIFS

                if [ $(eval ssh "$SSHOPTS" -p "$srv2" "$srv1" "ls -la \"${srv3// /\ }\" 2> /dev/null | wc -l") -eq 0 ]
                then
                        md5hash2="null"
                else
                        md5hash2=$(eval ssh "$SSHOPTS" -p "$srv2" "$srv1" "md5sum \"${srv3// /\ }\"")
                        md5hash2=$( echo "$md5hash2" | awk '{print $1}')
                fi
        fi

        if [ $md5hash1 == $md5hash2 ]
        then
                echo "1"
        else
                echo "0"
        fi
}

#SSHOPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i \"$PWD/xsibackup_id_rsa\""
SSHOPTS="-o StrictHostKeyChecking=no -i "$PWD"/xsibackup_id_rsa"

DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;KEY: $SSHOPTS"

backupConfig(){

	vim-cmd hostsvc/firmware/backup_config 1>/dev/null
	configPath=$( find /scratch/downloads -type f -name "*.tgz" -exec ls -1rt "{}" + | head -n1 )
	if [ ! -f "$configPath" ]
	then
		echo "Could not find the generated ESXi config .tgz file. Returned path: $configPath">>"$errfileb" 
	fi
	if [ "$SERVERTYPE" = "NET" ]
	then
		eval scp "$SSHOPTS" -P$baksrvport "$configPath" root@$baksrvaddr:"$baksrvdire"/${HOSTNAME}-${HOSTIP}-config.tgz && echo "1" || echo "0"				
	else
		cp "$configPath" "$1"/${HOSTNAME}-${HOSTIP}-config.tgz && echo "1" || echo "0"
	fi
}

if [ ! -z "$watch" ]
then
	if [ $( echo "$watch" | grep -oE "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" | wc -l ) -eq 0 ]
	then
		echo -e "The provided IP cannot evaluated as an IPv4 address"
		exit 0	
	else
		if [ -f "${PWD}/xsibackup-cron-${watch}.log" ]
		then
			echo -e "\033[0;32mMonitoring XSIBackup activity at ${watch}\033[0m"
			echo -e "\033[0;32mYou can stop watching at any time by pressing [Control+C]\033[0m"
			echo -e "\033[0;32mThe remote backup process will continue at ${watch}...\033[0m"
			echo -e "\033[0;32m----------------------------------------------------------\033[0m"
			tail -n20 -f "${PWD}/xsibackup-cron-${watch}.log"	
		else
			echo -e "\033[0;31mCannot find the log file ${PWD}/xsibackup-cron-${watch}.log\033[0m"
			exit 0
		fi	
	fi
fi

longdate=$( date '+%a, %d %b %Y %H:%M:%S %z' )
newdirmask=$( date +%Y%m%d''%H%M%S )
# yearstring=$( date +%Y )
yearstring="20"

proginf=$'
###############################################################################
#                                                                             #
#   --APPNAM-- --APPVER-- backup for --APPCOM-- by 33hops.com   #
#                                                                             #
###############################################################################
'

help=$'\033[0;36m--APPNAM-- --APPVER--\033[0m

RULES:
Arguments are a list of variable/value pairs separated by an equal sign. 
You can use any character to define values with the exception of double quotes (") and the equal sign (=).
You must double quote variables if you use spaces or any scapable character.

USAGE:
Example 1 (backup all running VMs):
xsibackup --backup-point=/vmfs/volumes/backup --backup-type=running --mail-from=email.sender@yourdomain.com 
--mail-to=email.recipient@anotherdomain.com --smtp-srv=smtp.yourdomain.com --smtp-port=25 --smtp-usr=username 
--smtp-pwd=password

Example 2 (backup 3 VMs even if they are swiched off):
xsibackup --backup-point=/vmfs/volumes/backup --backup-type=custom --backup-vms="WINDOWSVM1,LINUXVM2,New VM" 
--mail-from=email.sender@yourdomain.com --mail-to=email.recipient@anotherdomain.com --smtp-srv=smtp.yourdomain.com 
--smtp-port=25 --smtp-usr=username --smtp-pwd=password

OPTIONS:

--install-cron		This will install the cron system and file xsibackup-cron to the current dir.
			You can add as many XSIBackup commands as you want into this file, one per line.
			The only thing you have to do is add the parameter --time, i.e. --time="Mon 23:30".
			You can find detailed instructions in the sample xsibackup-cron file.

--backup-point		1) Full path to the backup mount point within the local server, it will tipically be under
			/vmfs/volumes, i.e. /vmfs/volumes/backup, /vmfs/volumes/datastore2.
			2) Full path in a remote ESXi host by using the following syntax:
			--backup-point="IP.OF.REMOTE.SERVER:PORT:/full/path/to/datastore"
			Example: --backup-point="192.168.1.200:22:/vmfs/volumes/datastore2
			You need to previously link the remote server to this host by using --link-srv option.

--backup-how		hot | cold
			Hot (default): selected virtual machines are backed up without being switched off,
			this is usefull for e-mail, http servers and VMs that cannot be switched off. If 
			you do not specify a value for --backup-how a hot backup will be carried out.
			Cold: selected VMs will be switched off before backup and turned on right afterwards.
			Good if you need a reboot cicle from time to time to refresh resources and don\'t
			mind having a little downtime. 

--backup-type		custom | all | running
			Custom: if this methos is chosen then a list of the VMs to backup must be passed to
			the --backup-vms option.
			All: backup -all- VMS.
			Running: backup only running virtual machines.

--date-dir		no (default) | yes
			Determines if a date subfolder in the form yyyymmddhhmmss is created, if no is chosen
			the backups will be directly made to the backup root overwriting files or adding the
			differential data depending on the --backup-prog argument.

--backup-vms		List of virtual machines to backup as a comma separated list. You can exclude disks by
			adding an exclamation sign followed by a list of disks delimited by a semicolon [;]
			Example: --backup-vms=VM1!scsi0:1;scsi0:2,VM2!disk1;disk2
			You can use any string, full or partial, that may help identify the disk by its name
			or by its device descriptor. Take on account that if you use an ambiguous string per
			instance "scsi" more than one disk may be excluded. This parameter is only needed if 
			custom is selected as the --backup-type.

--backup-prog		Defaults to Rsync for TCP/IP backups and to vmkfstools for datastore backups, unless
			explicitly set to rsync. In this case local copies will be done by means of rsync.

--backup-room		Space that will be used for backups in gigabytes. Once this limit is reached the 
			eldest backup folders with XSIBackup folder mask will be deleted. If this argument
			is omitted all available space will be used.

--test-mode=true	Allows testing backup procedure and e-mail submission without having to wait for a
			full backup process. In this mode VMs are not copied to the backup disk.

--smart-info=yes	Will add a complete S.M.A.R.T. report for every local disk, defaults to no.

--mail-from		E-mail address as from where the HTML e-mail report will be sent.

--mail-to		E-mail address to which the HTML e-mail report will be sent.

--subject		Set your own subject for the e-mail report

--smtp-srv		SMTP server that we will use to send the HTML e-mail report through.

--smtp-auth		none|plain. You can choose plain text authentication or no authentication for SMTP
			servers configured as open relays inside a controlled LAN. Use at your own risk.
			If you set --smtp-auth to none you do not need to supply a username and password.

--smtp-port		SMTP server port

--smtp-usr		SMTP username used for authentication against the SMTP server.

--smtp-pwd		SMTP password used for authentication against the SMTP server.			

--smtp-sec		SMTP authentication scheme, set it =TLS (upper case) if needed, default is no 
			encription. Your SMTP server must support secure renegotiation through the
			regular SMTP port.

--smtp-delay		Set number of seconds from 1 to 3. This will add a delay after the e-mail body and 
			before the QUIT command. May help as a workaround with some e-mail servers like 
			hMailServer. Use only as last resource.

--link-srv		This command needs an argument like this --link-srv=192.168.0.100. It generates a DSA
			key locally and adds it to the authorized_keys file at the remote host allowing to
			communicate without a password.
'

###############################################
#             HELP CONTENT END                #
###############################################


###############################################
#   BASE64 ASH NATIVE ENCODING FUNCTIONS      #
###############################################
# These are base64 encodig functions programmed to 
# work natively in busybox present on ESXi >= 5.1
# Needless to say they are not very efficient for
# encoding big files, but very convenient to
# encode SMTP usr & pwd on the other side and be
# able to send e-mail from the stripped down ESXi
# version.


        base64arr="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /"

        a=0
        for car in $base64arr
        do
                eval char$a=$car
        a=$(($a+1))
        done

dec_to_bin(){

        n=$1
        b=1
        while [ $n -ge 2 ]
        do
                binstr="$(($n % 2))"$binstr
        n=$(($n/2))
        b=$(($b+1))
        done
        echo `printf "%0$(($(($b/8+1))*8))d" $(echo $n$binstr | sed 's/^0*//')`
}

bin_to_dec(){

        binnum=$1
        c=0
        while [ $c -lt ${#binnum} ]
        do
        p=$((${#binnum}-$c-1))
                decnum=$(($decnum+$(($((${binnum:$c:1}))*$((2**$p))))))
        c=$(($c+1))
        done
        echo $decnum
}

bin_to_b64(){

        binstr=$1
        u=0
        while [ $u -lt ${#binstr} ]
        do
                b64str=$b64str$( eval echo \$char$(bin_to_dec `echo ${binstr:$u:6} | sed -e :a -e 's/^.\{1,5\}$/&0/;ta'`) )
        u=$(($u+6))
        done
        echo $b64str

}

base64_encode(){

        rawstr=$@
        linewidth=64
        s=0
        while [ $s -lt ${#rawstr} ]
        do
                binout=$binout$( dec_to_bin `printf "%d\n" \'"${rawstr:$s:1}"` )
        s=$(($s+1))
        done
        b64out=$( bin_to_b64 $binout )
        app=0
        if [[ $(( ${#rawstr}%3 )) -ne 0 ]]
        then
                while [ $app -lt $(( 3-${#rawstr}%3 )) ]
                do
                        b64out=$b64out"="
                app=$(($app+1))
                done
        fi
        echo $b64out
}

###############################################
#   BASE64 ASH NATIVE ENCODING FUNCTIONS      #
###############################################

ord() {
  LC_CTYPE=C printf '%d' "'$1"
}

chr() {
  [ "$1" -lt 256 ] || return 1
    printf "\\$(printf '%03o' "$1")"
}

get_file_b64(){

        attdir=".xsibackup-att"
        attext=".xsib64"

        if [ ! -d "$attdir" ]
        then
                mkdir "$attdir"
        fi

        if [ "${1:0:7}" == "http://" ]
        then
                if [ ! -e $(pwd)"/$attdir/.${2}${attext}" ]
                then
                        wget -q "$1" -O "$(pwd)/$attdir/.${2}" && openssl enc -base64 -in "$(pwd)/$attdir/.${2}" > "$(pwd)/$attdir/.${2}${attext}"
                else
                        thefile1=$(cat $(pwd)"/$attdir/.${2}${attext}")
                        wget -q "$1" -O "$(pwd)/$attdir/.${2}" && thefile2=$(cat "$(pwd)/$attdir/.${2}")
                        if [ "$thefile1" != "$thefile2"  ]
                        then
                                openssl enc -base64 -in "$(pwd)/$attdir/.${2}" > "$(pwd)/$attdir/.${2}${attext}"
                        fi
                fi
        else
                if [ ! -e $(pwd)"/$attdir/.${2}${attext}" ]
                then
                        openssl enc -base64 -in "$1" > "$(pwd)/$attdir/.${2}${attext}"
                else
                        thefile1=$(cat "$1")
                        thefile2=$(cat "$(pwd)/$attdir/.${2}${attext}")
                        if [ "$thefile1" != "$thefile2"  ]
                        then
                                openssl enc -base64 -in "$1" > "$(pwd)/$attdir/.${2}${attext}"
                        fi
                fi
        fi

}

disk_smart_info(){

        echo "&nbsp;&nbsp;<table class=\"report\"><tr><td colspan=\"4\"><b>S.M.A.R.T. REPORT</b></td></tr>"
        #echo "<table class=\"report\">"
        DISKSi=$( esxcli storage core device list | grep "Devfs Path" | awk -F "/" '{print $5}' | sed -e 's/^ *//g' -e 's/ *$//g' )
        IFS=$newline
        serr=0
        for dline in $DISKSi
        do
                smartinfo=$( esxcli storage core device smart get -d "$dline" )
                serr=0
                for sline in $smartinfo
                do
                        if [ ${sline//CANNOT\ open/} != $sline ]
                        then
                                serr=1
                                break
                        fi
                done

                if [ $serr -eq 0 ]
                then
                        diskname=$( echo $dline echo $a | awk -F "_____" '{print $2}' )
                        echo "<tr><td colspan=\"4\" class=\"separator\">&nbsp;</td></tr>"
                        echo "<tr><td colspan=\"4\"><b>Disk: "$diskname"</b></td></tr>"
                        cnt=0
                        for pline in $smartinfo
                        do
                            if [ "${pline:0:3}" != "---" ]
                            then
                                echo "<tr>"
                                        echo "<td>"
                                                echo "${pline:0:28}" | sed -e 's/^ *//g' -e 's/ *$//g'
                                        echo "</td>"
                                        echo "<td>"
                                                echo "${pline:30:5}" | sed -e 's/^ *//g' -e 's/ *$//g'
                                        echo "</td>"
                                        echo "<td>"
                                                echo "${pline:37:9}" | sed -e 's/^ *//g' -e 's/ *$//g'
                                        echo "</td>"
                                        echo "<td>"
                                                echo "${pline:48:5}" | sed -e 's/^ *//g' -e 's/ *$//g'
                                        echo "</td>"
                                echo "</tr>"
			    fi
                        cnt=$(( $cnt+1 ))
                        done
                fi

        done
        echo "</table>"
}

if [ "$smartinfo" == "yes" ]
then
    smartinfo=$( disk_smart_info ) 
fi

is_running(){
    echo $(esxcfg-info | grep sh.${1} | grep "Group Name" | grep -c ^)
}

if [ -f "${PWD}/xsibackup-pid" ]
then
	pidfileval=$(cat "${PWD}/xsibackup-pid")
	pidrunning=$(is_running $pidfileval)
	if [ "$pidrunning" -eq "0" ]
	then
		rm -rf "${PWD}/xsibackup-pid"
	fi
fi

if [ -e "${PWD}/xsibackup-pid" ]
then
	if [ "${time}" != "" ]
	then
		echo ""
        	echo "###########################################################"
        	echo ""
        	echo "WARNING"
        	echo ""
        	echo "XSIBackup was launched from the cron file without user input"
        	echo "But another XSIBackup process is still running. Only one"
        	echo "XSIBackup process is allowed at a time."
        	echo "This execution request will be ignored."
        	echo ""
        	echo "###########################################################"
		echo ""
		exit 0
	else
	        echo ""
        	echo "###########################################################"
        	echo ""
        	echo -e "\033[0;36mWARNING\033[0m"
        	echo ""
        	echo "There is an XSIBackup process running. Only one instance of"
        	echo "XSIBackup can be executed at a time. If you are confident"
        	echo "there are no current XSIBackup processes running you can"
        	echo "delete the xsibackup-pid file in the XSIBackup working"
        	echo "directory."
        	echo ""
        	echo "###########################################################"
		echo ""
        	read -p "Do you wish to delete the XSIBackup PID file (xsibackup-pid)? (y/n) " yn
                case $yn in
                [Yy]* ) rm -rf "${PWD}/xsibackup-pid";;
                [Nn]* ) exit 0;;
                * ) echo "Please answer (y)es or (n)o."; exit 0;;
                esac
	fi
fi

HOSTUUID=$( vim-cmd hostsvc/hosthardware | grep uuid | awk -F "=" '{print $2}' ) && HOSTUUID=${HOSTUUID// /} && HOSTUUID=${HOSTUUID//,/} && HOSTUUID=${HOSTUUID//\"/}
SESSIONID=$HOSTUUID$(date +%s) && SESSIONID=$( echo $SESSIONID | openssl base64 2> /dev/null ) && SESSIONID=${SESSIONID// /} && SESSIONID=${SESSIONID//=/}

proginf="${proginf//--APPNAM--/$APPNAM}"
proginf="${proginf//--APPVER--/$APPVER}"
proginf="${proginf//--APPCOM--/$APPCOM}"
echo -e "$proginf"
echo "XSIBackup PID: "$$

DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;PID: $$"

if [ "$backupid" != "" ]
then
	echo "Backup Id: " $backupid
fi
echo $$ > "${PWD}/xsibackup-pid"

rm -rf .ERR*
errseed=$( date )
errfileb="$( base64_encode $errseed )"
errfileb="${PWD}/.ERR-${errfileb//=/}"
touch "$errfileb"
THERESERR=0
ERR()
{
	if [ "$3" == "W" ]
	then
		c="warn"
		t="WARNING"
	else
		c="errr"
		t="ERROR"
	fi
	if [ "$1" -ne "0" ]
	then
     		VMERRS="$(date) - Exit code: $1 - ${t}: $2"
     		echo "$(date) - Exit code: $1<br /><span class=${c}><b>${t}:</b> $2</span><br />" >> "$errfileb"
	fi
}

ESX_VERSION=$(vmware -v | awk '{print $3}')
if [[ "${ESX_VERSION}" != "5.1.0" -a "${ESX_VERSION}" != "5.5.0" -a "${ESX_VERSION}" != "6.0.0" ]]
then
        echo -e "\033[0;31mOnly ESXi 5.X and 6.X series are supported. You are free to try it in previous versions of ESXi but it has not been officially tested\033[0m"
        exit 1
fi

DEBUGINFO="${DEBUGINFO}<br />&bull;&nbsp;ESXi VERSION: $ESX_VERSION"

if [ $# -eq 0 ]
then
	echo -e "\033[0;36mPreparing help, please wait...\033[0m"
	help=${help//--APPNAM--/$APPNAM}
	#help=${help//--APPCOM--/$APPCOM}
	help=${help//--APPVER--/$APPVER}
	echo "$help"
	exit 0
fi

if [[ "${keyvalstr// /}" == "--help" ]]
then
        echo -e "\033[0;36mPreparing help, please wait...\033[0m"
        help=${help//--APPNAM--/$APPNAM}
        #help=${help//--APPCOM--/$APPCOM}
        help=${help//--APPVER--/$APPVER}
        echo "$help"
        exit 0
fi

link_to_host(){

IFS=":"
i=1
hp="22"
for sp in $1
do
	if [ "$i" -eq 1 ]
	then
		# If it's a hostname we find the IP
		theIp=$( ping -c 1 "$sp" | head -n1 | awk -F "(" '{print $2}' |  awk -F ")" '{print $1}' )
		if [ $( echo "$theIp" | grep -oE "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" | wc -l ) -eq 0 ]
		then
			echo -e "\033[0;31m${sp} can't be evaluated as an IPv4 address\033[0m"
			exit 0	
		else
			hip="$sp"	
		fi		
	fi
	if [ "$i" -eq 2 ]
	then
		if [ $sp -gt 0 ] && [ $sp -lt 65536 ]
		then
			hp=$sp	
		else
			hp=22
		fi
	fi
	i=$(( $i+1 ))	
done
IFS=$OLDIFS

if [ "$(checksrv $hip:$hp OpenSSH)" != "1" ]
then
     echo "\033[0;31mThe server at IP:Port $hip:$hp cannot be contacted\033[0m"
     exit 33
fi

if [ -f "$PWD"/xsibackup_id_rsa.pub ]
then
        echo -e "\033[0;36mThere is already an RSA public key at "$PWD"/xsibackup_id_rsa.pub. We will use the existing one.\033[0m"
        echo -e "\033[0;36mEnter the remote server root password twice when prompted.\033[0m"
        ssh_key=$(cat "$PWD"/xsibackup_id_rsa.pub)
        ssh_key2=$( ssh -p$hp root@$hip "cat /etc/ssh/keys-root/authorized_keys")

                IFS=$newline
                for key in $ssh_key2
                do
                        if [[ "${key// /}" == "${ssh_key// /}" ]]
                        then
                                echo -e "\033[0;36mThe local RSA key has already been added to the authorized_keys file at $1.\033[0m"
                                echo -e "\033[0;36mThere is no need to add it again, you should be able to connect with XSIBackup to $1 without any password.\033[0m"
                                exit 0
                        fi
                done
                IFS=$OLDIFS
                
        ssh -p$hp root@$hip "echo $ssh_key >> /etc/ssh/keys-root/authorized_keys"
        echo -e "\033[0;32mThe RSA key has been added to the authorized_keys file at $1.\033[0m"
        echo -e "\033[0;32mRebooting local SSH service...\033[0m"
        /etc/init.d/SSH restart
        echo -e "\033[0;32mRebooting remote SSH service...\033[0m"
        eval ssh -p$hp "$SSHOPTS" root@$hip "/etc/init.d/SSH restart"
        exit 0
else
        echo -e "\033[0;36mNo RSA public key found, we will generate one...\033[0m"
        rm -rf "$PWD"/id_rsa*
        /usr/lib/vmware/openssh/bin/ssh-keygen -t rsa -f "$PWD"/xsibackup_id_rsa -q -N ''
        echo -e "\033[0;32mThe RSA key has been generated.\033[0m"
        ssh_key=$(cat "$PWD"/xsibackup_id_rsa.pub)
        echo -e "\033[0;32mEnter the remote server root password when prompted.\033[0m"
        ssh -p$hp root@$hip "echo $ssh_key >> /etc/ssh/keys-root/authorized_keys"
        echo -e "\033[0;32mThe RSA key has been added to the authorized_keys file at $1.\033[0m"
        echo -e "\033[0;32mRebooting local SSH service...\033[0m"
        /etc/init.d/SSH restart
        echo -e "\033[0;32mRebooting remote SSH service...\033[0m"
        eval ssh -p$hp "$SSHOPTS" root@$hip "/etc/init.d/SSH restart"
        exit 0
fi

}

if [[ "$linksrv" != "" ]]
then
	link_to_host "$linksrv"
	exit 0
fi

if [[ "${keyvalstr// /}" == "--install-cron" ]]
then
   
ISTHERE=$( grep -c "xsibackup-cron" /etc/rc.local.d/local.sh )
if [ $ISTHERE -gt 0 ]
then
        echo "XSIBackup cron has already been installed."
        read -p "Do you wish to remove it? (y/n) " yn
        case $yn in
        	[Yy]* )
        	# BusyBox sed is broken fails in line deletions so we
                # inverse the file, take the whole minus the matched line
                # and overwrite both files /etc/rc.local.d/local.sh and /var/spool/cron/crontabs/root
                TAB1=$( sed -n '/xsibackup/!p' /etc/rc.local.d/local.sh )
                echo "$TAB1" > /etc/rc.local.d/local.sh
                TAB2=$( sed -n '/xsibackup/!p' /var/spool/cron/crontabs/root )
                echo "$TAB2" > /var/spool/cron/crontabs/root
       		echo "xsibackup-cron has been removed"	 
        
        exit 0;;
        [Nn]* ) exit 0;;
            * ) echo "Please answer (y)es or (n)o."; exit 0;;
        esac    	
fi

echo "This command will install XSIBackup cron to your ESXi > 5.1 BOX"
echo "xsibackup-cron will be installed to the current working directory"
echo "You should cd to the desired directory before installing the cron"
read -p "Do you wish to continue? (y/n) " yn
case $yn in
    [Yy]* )

        sed -i 's/exit 0//g' /etc/rc.local.d/local.sh
        echo "/bin/kill \$(cat /var/run/crond.pid) && /bin/echo \"*/1 * * * * '${PWD}/xsibackup-cron' >> '${PWD}/xsibackup-cron.log' 2>&1\" >> /var/spool/cron/crontabs/root && /usr/lib/vmware/busybox/bin/busybox crond" >> /etc/rc.local.d/local.sh
        #echo "/bin/echo \"*/1 * * * * '${PWD}/xsibackup-cron' >> '${PWD}/xsibackup-cron.log' 2>&1\" >> /var/spool/cron/crontabs/root" >> /etc/rc.local.d/local.sh
        #echo "/usr/lib/vmware/busybox/bin/busybox crond" >> /etc/rc.local.d/local.sh
        echo "" >> /etc/rc.local.d/local.sh
        echo "exit 0" >> /etc/rc.local.d/local.sh
        touch "${PWD}"/xsibackup-cron
        chmod 0700 "${PWD}"/xsibackup-cron
        echo "#!/bin/sh" > "${PWD}"/xsibackup-cron
        echo "# This is your XSIBackup crontab, you can add your backup schedules here" >> "${PWD}"/xsibackup-cron
        echo "# You can use regular XSIBackup commands appending the parameter --time=\"Day HH:mm\", i.e. --time=\"Mon 21:57\"" >> "${PWD}"/xsibackup-cron
        echo "# The --time format is compounded by three letters weekday acronym (Mon,Tue,Wed,Thu,Fri,Sat,Sun) + space + hh:mm" >> "${PWD}"/xsibackup-cron
        echo "# You can add multiple \"moments\" in a --time argument separated by a pipeline | like: Mon 17:31|Tue 21:33|Sun 19:21" >> "${PWD}"/xsibackup-cron
        echo "#" >> "${PWD}"/xsibackup-cron
        echo "# Example:" >> "${PWD}"/xsibackup-cron
        echo "#\"${PWD}/xsibackup\" --time=\"Mon 02:00|Tue 02:00|Wed 02:00|Thu 02:00|Fri 02:00|Sat 02:00|Sun 02:00\" --backup-point=\"/vmfs/volumes/backup\" --backup-type=custom --backup-vms=\"XP01,W701!scsi2:0;scsi3:1;scsi3:2,LIN02,BSD03\"  --mail-from=me@mydomain.com --mail-to=someoneelse@otherdomain.com  --smtp-srv=smtp.mydomain.com --smtp-port=587 --smtp-usr=me@mydomain.com --smtp-pwd=mypassword" >> "${PWD}"/xsibackup-cron
        echo -e "\033[0;36mRemoving cron info...\033[0m"
        # BusyBox sed is broken fails in line deletions so we 
        # inverse the file, take the whole minus de matched line 
        # and overwrite /var/spool/cron/crontabs/root
        TAB=$( sed -n '/xsibackup/!p' /var/spool/cron/crontabs/root )
        echo "$TAB" > /var/spool/cron/crontabs/root
        echo "Adding new cron info..."
        /bin/echo "*/1 * * * * '${PWD}/xsibackup-cron' >> '${PWD}/xsibackup-cron.log' 2>&1" >> /var/spool/cron/crontabs/root
        echo "The local cron service will be restarted"
        echo "You might need to reboot the ESXi server for the changes to take effect..."
        /bin/kill $(cat /var/run/crond.pid) && /usr/lib/vmware/busybox/bin/busybox crond
        echo -e "\033[0;32mcron service restarted\033[0m"

    exit 0;;
    [Nn]* ) exit 0;;
        * ) echo "Please answer (y)es or (n)o."; exit 0;;
esac

fi
                
echo $longdate
DO_BACKUP=1

if [ -z ${backuppoint} ]
then
	echo -e "\033[0;31mThe --backup-point string is a mandatory value\033[0m"	
	DO_BACKUP=0
else
	if [[ -d "${backuppoint}" ]]
	then
		echo -e "\033[0;32mFound --backup-point at ${backuppoint}\033[0m"
		SERVERTYPE="DIR"
	else
		if [ "${backuppoint:0:1}" == "/" ]
		then
			echo -e "\033[0;31mBad --backup-point, the directory ${backuppoint} does not exist\033[0m"
			exit 0
		fi
		
		# The backup point might be a server
		IFS=":"
                side=0
                for eachside in $backuppoint
                do
                	if [ $side -eq 0 ]
                	then
                        	#if [ $( echo "$eachside" | grep -oE "^((25[0-5]|2[0-4][0-9]|[1]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[1]?[1-9]?[0-9])$" | wc -l ) -eq 0 ]
                        	if [ $( echo "$eachside" | grep -oE "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" | wc -l ) -eq 0 ]
                        	then
                        		echo -e "\033[0;31mThe --backup-point is not a directory and can't be evaluated as a server either\033[0m"
                        		echo -e "\033[0;31m${eachside} can't be evaluated as an IPv4 address\033[0m"
                        		exit 0
                        	fi
                        	baksrvaddr="$eachside"
                        elif [ $side -eq 1 ]
                        then
                                baksrvport="$eachside"
                        elif [ $side -eq 2 ]
                        then
                                baksrvdire="$eachside"
                        elif [ $side -eq 3 ]
                        then
                        	backsrvtrf="$eachside"
                        fi
                side=$(( $side+1 ))
                done
		IFS=$OLDIFS
		
		srvchkstr=$( checksrv "$baksrvaddr:$baksrvport" "OpenSSH" )
		if [ "$srvchkstr" = "1" ]
		then
			SERVERTYPE="NET"
			backupprog="rsync"
		else
			echo -e "\033[0;31mThe server --backup-point=${backuppoint} does not exist\033[0m"
			echo -e "\033[0;31mMake sure there is an SSH server listening on $baksrvaddr port $baksrvport and that the firewall allows this connection\033[0m"
			DO_BACKUP=0
		fi
	fi	
fi

if [ "$SERVERTYPE" = "NET" ]
then
	echo "Mirroring to server "$baksrvaddr" port "$baksrvport
	echo "Checking xsibackup-rsync exists on the other side..."
	
	if [ $(compHashes "$PWD"/xsibackup-rsync "$baksrvaddr:$baksrvport:$baksrvdire/xsibackup-rsync") == "0" ]
	then
		echo -e "\033[0;36mxsibackup-rsync needs to be copied/updated in the remote server\033[0m"
		eval scp "$SSHOPTS" -P$baksrvport "$PWD"/xsibackup-rsync root@$baksrvaddr:$baksrvdire
	else	
		echo -e "\033[0;36mxsibackup-rsync found on the other end and same version. Continuing IP mirror backup...\033[0m"		
	fi
fi

if [ -z "$backuptype" ]
then
        echo -e "\033[0;31mYou have to set the variable --backup-type to some of the values described in the help\033[0m"
	DO_BACKUP=0
else
	if [[ "$backuptype" == "custom" ]]
	then
        	if [ -z "$backupvms" ]
        	then
                	echo -e "\033[0;31mThe --backup-vms string is a mandatory value when --backup-type is set to: \033[0m"$backuptype
        		DO_BACKUP=0
		fi
	fi
fi

if [ -z "$backupprog" ]
then
	backupprog="vmkfstools"
else
	if [[ "$backupprog" != "vmkfstools" -a "$backupprog" != "rsync" ]]
	then
		echo -e "\033[0;31mThe only accepted values for --backup-prog are vmkfstools | rsync\033[0m"
		DO_BACKUP=0	
	fi
fi

SEND_EMAIL=1

if [[ -z ${mailfrom} ]]
then
	SEND_EMAIL=0
	SEND_EMAIL_MSG="\033[0;36mThe --mail-from string has not been set\033[0m$newline"
fi

if [[ -z ${mailto} ]]
then
        SEND_EMAIL=0
        SEND_EMAIL_MSG=$SEND_EMAIL_MSG"\033[0;36mThe --mail-to string has not been set\033[0m$newline"
fi
                
if [ -z "${subject}" ]
then
        subject="ESXi Backup Report. More OSS at http://33hops.com/free-open-source-software.html#xsibackup"
fi
  
if [[ -z ${smtpsrv} ]]
then
        SEND_EMAIL=0
        SEND_EMAIL_MSG=$SEND_EMAIL_MSG"\033[0;36mThe --smtp-srv string has not been set\033[0m$newline"
fi

if [[ -z ${smtpport} ]]
then
        SEND_EMAIL=0
        SEND_EMAIL_MSG=$SEND_EMAIL_MSG"\033[0;36mThe --smtp-port string has not been set\033[0m$newline"
fi

if [[ -z ${smtpauth} ]]
then
        smtpauth="plain"
elif [ "$smtpauth" = "none" ]
then
	SEND_EMAIL_MSG=$SEND_EMAIL_MSG"\033[0;36mThe --smtp-auth string has been set to -none-\033[0m$newline"
fi

if [[ -z ${smtpusr} ]]
then
        if [[ "${smtpauth}" != "none" ]]
        then
        	SEND_EMAIL=0
        	SEND_EMAIL_MSG=$SEND_EMAIL_MSG"\033[0;36mThe --smtp-usr string has not been set, you need --smtp-usr if --smtp-auth is other than -none-\033[0m$newline"
	fi
fi

if [[ -z ${smtppwd} ]]
then
        if [[ "${smtpauth}" != "none" ]]
        then
        	SEND_EMAIL=0
        	SEND_EMAIL_MSG=$SEND_EMAIL_MSG"\033[0;36mThe --smtp-pwd string has not been set, you need --smtp-pwd if --smtp-auth is other than -none-\033[0m$newline"
	fi
fi

#if [[ -e "${busyboxbin}" ]]
#then
#                echo "BusyBox binary found at - $busyboxbin -"	
#else
#                SEND_EMAIL=0
#                SEND_EMAIL_MSG=$SEND_EMAIL_MSG"No BusyBox binary has been found in the specified path - $busyboxbin - if you want an e-mail report to be sent you will need BusyBox.$newline"
#fi

                
if [[ "${SEND_EMAIL}" == 0 ]]
then
        echo -e "\033[0;36mThe e-mail report will not be sent becouse of the followig reasons:\033[0m$newline$SEND_EMAIL_MSG$newline"
fi

if [[ "${DO_BACKUP}" == 0 ]]
then
        echo -e "\033[0;31mThe backup will halt here becouse some mandatory values are missing\033[0m"
        exit 0
fi

if [ "$backuproom" -gt 0 ]
then
	echo -e "\033[0;36mThe backup room has been limited to $backuproom gb.\033[0m"
fi

getDatastorepathByDatastorename(){

        VMDATA=$(vim-cmd vmsvc/get.datastores $1)
                IFS=$newline
                for ds in $VMDATA
                do
                ln=$( echo $ds | awk '{ print $1 }' | sed -e 's/^ *//g' -e 's/ *$//g' )
                if [ $ln = "name" ]
                then
                        tkn=0
                        IFS=$OLDIFS
                        for tk in $ds
                        do
                                if [ "$tk" == "$2" ]
                                then
                                        ord=$tkn
                                fi
                        tkn=$(( $tkn+1 ))
                        done
                fi
                if [ $ln = "url" ]
                then
                        tkn=0
                        IFS=$OLDIFS
                        for tk in $ds
                        do
                                if [ "$tkn" == "$ord" ]
                                then
                                        echo "$tk"
                                fi
                        tkn=$(( $tkn+1 ))
                        done
                fi
                done
}
                                        
avail_backup_room(){

        OLDIFS=$IFS
        AVAILS=$( df -m )
        MYPATH=$( getMountedPath $1 )
        IFS=$newline
               	for line in $AVAILS
               	do
               	DFPATH=$( echo $line | awk '{ print $6 }' )
                       	if [[ "${MYPATH#*$DFPATH}" != "$MYPATH" ]]
                       	then
				dirs=$(ls -1d "$backuppoint/$yearstring"* 2>/dev/null | wc -l)
				if [ $dirs -gt 0 ]
                       		then
                       			THEUSED=$( du -scm "$backuppoint"/$yearstring* | grep total | awk '{ print $1 }' )
                       		else
                       			THEUSED=0
                       		fi
                       		THEROOM=$( echo $line | awk '{ print $4 }' )
                       	fi
               	done
        IFS=$OLDIFS

	if [[ -z ${THEROOM} ]]
	then
		echo -e "\033[0;31mCould not get available backup room in backup device\033[0m"	
	else
		if [ "$backuproom" -gt 0 ]
		then
			echo $(( $backuproom*1024-$THEUSED ))			
		else	
			echo $THEROOM
		fi
	fi

}

get_vm_state(){

        if [ "$2" != "" ]
        then
       		IFS=":"
       		pn=1
       		for spart in $2
       		do
       			eval "srv"$pn=\""$spart"\"		
       		pn=$(( $pn+1 ))	
       		done
       		IFS=$OLDIFS
       		
       		SOUTPUT=$(eval ssh "$SSHOPTS" -p "$srv2" "$srv1" exec "vim-cmd vmsvc/power.getstate $1 | grep Powered 2> /dev/null")
       		 
        else
        	SOUTPUT=$(vim-cmd vmsvc/power.getstate $1 | grep Powered)
        fi

        if [ "$SOUTPUT" = "Powered off" ]
        then
        	echo "OFF"
        else
                echo "ON"
        fi
}

make_room(){

        OLDIFS=$IFS
        ROOMUSED=$( du -sm $2 )
        n=0
        while [[ "$1" -gt "$(avail_backup_room $2)" ]]
        do
                if [ "$n" -gt 99 ]
                then
                	available=$(avail_backup_room $2)
                	echo -e "\033[0;36mCannot make $(( $1/1024 ))G of room, only $(( $available/1024 ))G can be made available\033[0m"
                	exit 0
                fi
                
                OLDESTDIR=$( find $2/ -type d -name "$yearstring*" -maxdepth 1 | sort -nr | tail -1 )
                n=$(( $n+1 ))
                if [ -d "$OLDESTDIR" ]
                then
                	rm -rf "$OLDESTDIR" 2>/dev/null
                fi
                DELDIRS=$DELDIRS"<br />"$OLDESTDIR
        done
        IFS=$OLDIFS
        echo "$DELDIRS"
}

getValue(){

        RawData=`eval $1`

        IFS=$newline
        for dataline in $RawData
        do
                if [[ ${dataline//$2/} != "$dataline" ]]
                then
                        if [[ ${dataline//=/} != "$dataline" ]]
                        then

                                keyval=$dataline

                                if [[ ${dataline//vmfs/} == "$dataline" ]]
                                then
                                keyval=${keyval//-/}
                                fi

                                keyval=${keyval//\"/}
                                keyval=${keyval//,/}
                                keyval=${keyval// /}
                                keyval=${keyval//:/}
                                echo $keyval
                                exit 0

                        elif [[ ${dataline//:/} != "$dataline" ]]
                        then

                                keyval=$dataline
                                keyval=${keyval//-/}
                                keyval=${keyval//\"/}
                                keyval=${keyval//,/}
                                keyval=${keyval// /}
                                keyval=${keyval//:/=}
                                echo $keyval
                                exit 0

                        else

                                keyval=$dataline
                                keyval=${keyval//-/}
                                keyval=${keyval//\"/}
                                keyval=${keyval//,/}
                                keyval=${keyval// /}
                                keyval=`echo $keyval | sed 's/[ \t]\+/ /g'`
                                keyval=${keyval// /=}
                                echo $keyval
                                exit 0

                        fi
                                exit 0

                fi

        done
        IFS=$OLDIFS

}

openFirewall(){

   # We check if the firewall is loaded
   FWOUT=$( esxcli network firewall get )
   IFS=$newline
   for fwline in $FWOUT
   do
        # trim
        fwline=$( echo $fwline | sed -e 's/^ *//' -e 's/ *$//' )

        if [ "$fwline" = "Loaded: false"  ]
        then
                LOADFW=$( esxcli network firewall load )
        fi

   done

   IFS=$OLDIFS
   FWOUT=$( esxcli network firewall ruleset list | grep "$2" )

        if [[ "$FWOUT" == "" ]]
        then
        
	        chmod 644 /etc/vmware/firewall/service.xml
                chmod +t /etc/vmware/firewall/service.xml
                
		FWRULE="<service id='"$3"'>\n
                <id>"$2"</id>\n
                <rule id='"$4"'>\n
                <direction>outbound</direction>\n
                <protocol>"$5"</protocol>\n
                <porttype>dst</porttype>\n
                <port>"$1"</port>\n
                </rule>\n
                <enabled>true</enabled>\n
                <required>false</required>\n
                </service>\n
                </ConfigRoot>"
                ADDT=`echo $FWRULE | sed 's/$newline//g'`
                sed -i 's,<\/ConfigRoot>,'"$ADDT"',g' "/etc/vmware/firewall/service.xml"
                chmod 444 /etc/vmware/firewall/service.xml
                esxcli network firewall refresh
		echo "Firewall rule $2 added..."
		        
	else
        
	        # If the firewall service $2 exists we make sure it is open
                esxcli network firewall ruleset set --ruleset-id="$2" --enabled=true
        	echo "Opening port $1 for $2 service..."
	fi

}

getFilename(){
IFS="/"
	for trozo in $1
	do
        	disk=$trozo
	done
IFS=$OLDIFS
	echo $disk
}

getVMDir(){

        VMDIR=$( vim-cmd vmsvc/get.filelayout $1 | grep vmPathName )
                ivmd=0
                IFS="="
                for pa in $VMDIR
                do
                        #pa=${pa// /}
                        if [ $ivmd -eq 1 ]
                        then
                                IFS="]"
                                ivme=0
                                for pb in $pa
                                do
                                        if [ $ivme -eq 1 ]
                                        then
                                        	vmxpath=$( echo $pb | sed -e 's/^ *//g' -e 's/ *$//g' )
                                        	vmxdir=$( dirname "${vmxpath}" )
                                        	echo ${vmxdir}
                                        fi
                                ivme=$(( $ivme+1 ))
                                done
                        fi
                ivmd=$(( $ivmd+1 ))
                done
}

getVMName(){

        VMNAME=$( vim-cmd vmsvc/get.config $1 | grep name )
        ivmg=0
        IFS=","
        for name in $VMNAME
        do
                if [ $ivmg -eq 0 ]
                then
                        name=${name// = /=}
                        eval $name
                        echo $name
                fi
        ivmg=$(( $ivmg+1 ))
        done

}

getVMSize(){
        
        VMDATA=$(vim-cmd vmsvc/get.datastores $1)
        VMNOME=$(getVMName $1)
        vmxdir=$(getVMXDir $1)
        totalsize=0
                
                IFS=','
                for evm in $backupvms
                do
                        if [ "${evm//$VMNOME/}" != "$evm" ]
                        then
                                IFS='!'
                                        nex=0
                                        vmdk2exclude=""
                                        for excparts in $evm
                                        do
                                                if [ $nex -eq 1 ]
                                                then
                                                        vmdk2exclude="$excparts"
                                                fi
                                        nex=$(( $nex+1 ))
                                        done
                                IFS=$OLDIFS
                        fi
                done
                IFS=$OLDIFS

		diskpaths=$(getAllFiles $1)

                IFS=$newline
                for disk in $diskpaths
                do
		if [ "${disk:$(( ${#disk}-5 ))}" == ".vmdk" ]
		then
		
                matchex=0
                IFS=";"
                for exvmdk in $vmdk2exclude
                do
                        if [ "${disk//$exvmdk/}" != "$disk" ]
                        then
                                matchex=1
                        fi
                done
                IFS=$OLDIFS

		if [ $matchex -eq 0 ]
                then
                        IFS='='
                        tm=0
                        for term in $disk
                        do
                                if [ $tm -eq 1 ]
                                then
                                        path=${term//\"/}
                                        if [ ${path:0:1} == "/" ]
                                        then
                                            if [ -f "$path" ]
                                            then     
                                                vmdksize=$(du -ms "$path" | awk '{print $1}')
                                                flat=$(cat "$path" | grep "flat.vmdk\|delta.vmdk" | awk -F "\"" '{print $2}')
                                                if [ "$flat" != "" ]
                                                then
                                                	flat=${flat//\"/}
                                                	flat=$(dirname "$path")/"$flat"
                                                	flatsize=$(du -m "$flat" | awk '{print $1}')
                                            	else
                                            		flatsize=0
                                            	fi
                                            else
                                            	vmdksize=0
                                            	flatsize=0
                                            fi
                                        else
                                            if [ -f "${vmxdir}/${path}" ]
                                            then    
                                                vmdksize=$(du -ms "${vmxdir}/${path}" | awk '{print $1}')
                                                flat=$(cat "${vmxdir}/${path}" | grep flat.vmdk | awk -F "\"" '{print $2}')
                                                flat="${vmxdir}/${flat//\"/}"
                                                flatsize=$(du -m "${flat}" | awk '{print $1}')
                                            else
                                            	vmdksize=0
                                            	flatsize=0
                                            fi
                                        fi
                                        totalsize=$(( $totalsize+$vmdksize+$flatsize ))
                                fi
                        tm=$(( $tm+1 ))
                        done
                        IFS=$OLDIFS
                fi
		fi
                done

        echo $totalsize
}

getVMXDir(){
        VMDATA=$(vim-cmd vmsvc/get.datastores $1)
                theVMXDir=""
                IFS=$newline
                for ds in $VMDATA
                do
                ln=$( echo $ds | awk '{ print $1 }' | sed -e 's/^ *//g' -e 's/ *$//g' )
                if [ $ln = "url" ]
                then
                        tkn=0
                        IFS=$OLDIFS
                        for tk in $ds
                        do
                                if [[ $tk != "url" ]]
                                then
                                        if [ -f "$tk/$(getVMDir $1)/"*".vmx" ]
                                        then
                                                theVMXDir=$tk"/"$(getVMDir $1)
                                        	theVMXDir=$( echo "$theVMXDir" | sed -e 's/^ *//g' -e 's/ *$//g' )
                                        fi
                                fi
                        tkn=$(( $tkn+1 ))
                        done
                fi
                done
                if [ ${#theVMXDir} -gt 0 -a -d "$theVMXDir" ]
                then
                	echo "$theVMXDir"
                else
                	VMERRS="Could not find the VMX dir or the .vmx file itself for VM($1)."
                	echo "VM($1) VMX dir or the .vmx file itself do not exist, they might have been removed by accident">>"$errfileb"
                fi
}

killRsync(){

        if [ "$1" != "" ]
        then
                if [ "$2" != "" ]
                then
                        sshport="$2"
                else
                        sshport="22"
                fi
                REMPIDS=$(eval ssh "$SSHOPTS" -p "$sshport" "$1" exec "pkill -9 xsibackup-rsync 2>&1")
        fi
	RSPID=$(pkill -9 xsibackup-rsync)
        echo -e "\033[0;36mPrevious xsibackup-rsync process terminated\033[0m"
}

compSizes(){

        s1=${1// /\ }
        s2=${2// /\ }

        if [ -f "$s1" ]
        then
                size1=$( ls -las "$s1" 2> /dev/null | awk -F " " '{print $1}' )
        else
                size1=""
                echo -e "\033[0;31mThe file ${s1} does not exist\033[0m"
                exit 1
        fi

        if [ -f "$s2" ]
        then
                size2=$( ls -las "$s2" 2> /dev/null | awk -F " " '{print $1}' )
        else
                IFS=":"
                s=1
                for spart in $s2
                do
                        eval "srv"$s=\""$spart"\"
                s=$(($s+1))
                done
                IFS=$OLDIFS

                size2=$( eval ssh "$SSHOPTS" -p "$srv2" "$srv1" "ls -las \"${srv3// /\ }\"" )
                size2=$( echo "$size2" | awk '{print $1}')
        fi

        if [ "$size1" -eq "$size2" ]
        then
                echo "1"
        else
                echo "0"
        fi
}

getTopVmdks(){

snapshots=$( cat "$( getVMXDir $1 )/"*.vmsd )
IFS=$newline
for eachsnap in $snapshots
do
        if [ ${eachsnap//displayName/} != ${eachsnap} ]
        then
                eval $( echo ${eachsnap// /} | awk -F '.' '{for (i=2; i<=NF; i++) print $i}' )
        fi
        if [ ${eachsnap//uid/} != ${eachsnap} ]
        then
                eval $( echo ${eachsnap// /} | awk -F '.' '{for (i=2; i<=NF; i++) print $i}' )
        fi
        if [ "$displayName" == "xsibackup" ]
        then
        	if [ ${eachsnap//numDisks/} != ${eachsnap} ]
        	then
                	eval $( echo ${eachsnap// /} | awk -F '.' '{for (i=2; i<=NF; i++) print $i}' )
                	topsnapshot=$( echo ${eachsnap// /} | awk -F '.' '{print $1}' )
			theuid=$uid
        	fi
        fi
done
IFS=$OLDIFS

theDisks=""
for i in $( seq 0 $(( $numDisks-1 )) )
do
        theDisk=$( echo "$snapshots" | grep "${topsnapshot}.disk$i.fileName" | awk -F '=' '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' )
        theNode=$( echo "$snapshots" | grep "${topsnapshot}.disk$i.node" | awk -F '=' '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' )
        theDisks=${theDisks}${newline}${theNode//\"/}".fileName = "${theDisk}
	#theDisks=${theDisks}${newline}${theDisk}
done

if [ "$2" == "id" ]
then
	echo "$theuid"
else
	echo "$theDisks"
fi

}

deleteSnapshot(){
        # Get last snapshot id
        lastId=$( vim-cmd vmsvc/snapshot.get $1 | grep Id | awk -F ':' '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' | tail -n1 )
        if [ "$lastId" == "$( getTopVmdks $1 id )" ] && [ "$lastId" != "" ]  
	then
		delSna=$( vim-cmd vmsvc/snapshot.remove $1 $lastId false )
		
	fi
}

getAllFiles(){
        FILES=$(vim-cmd vmsvc/get.filelayout $1 | grep "vmdk\|vmsn" | sed "s/\t//g" | sed "s/vmPathName = //g" \
        | sed "s/,//g" | sed 's/"//g' | sed -e 's/^ *//g' -e 's/ *$//g' | sort -u)
        IFS=$newline
        for paz in $FILES
        do
                if [ "${paz:0:1}" == "[" ]
                then
                        dsname=$( echo "$paz" | awk '{print $1}' | sed -e 's/\[//g' -e 's/\]//g' | sed -e 's/^ *//g' -e 's/ *$//g' )
                        dspath=$( getDatastorepathByDatastorename $1 "$dsname" )
                        tlpath=$( echo ${paz/"["$dsname"]"/} | sed -e 's/^ *//g' -e 's/ *$//g' )
                        echo "DISK=""$dspath"/"$tlpath"
                else
                        echo "DISK=""$( getVMXDir $1 )"/"$paz"
                fi
        done
        IFS=$OLDIFS
}

isFileOpen(){
        ISOPEN=$( tail -n1 "$1" 2>&1 )
        if [ "${ISOPEN/Device or resource busy/}" != "$ISOPEN" ]
        then
                echo "1"
        else
                echo "0"
        fi
}

getSnapshotIdByName(){
	# $1 => Snapshot Name
	# $2 => .vmsd path
	SNAPORD=$( grep ".displayName = \"$1\"" "$2" | awk -F "." '{print $1}' )
	SNAPID=$( grep "${SNAPORD}.uid" "$2" | awk -F "=" '{print $2}' | sed 's/\"//g' | sed 's/\ //g' )
	echo "$SNAPID"
}

getSnapshotFilesById(){
	# $1 => Snapshot Id
	# $2 => .vmsd path
	snf=$( grep "uid = \"$1\"" "$2" | awk -F "." '{print $1}' )
	snf1=$( grep ${snf}.filename "$2" | awk -F "=" '{print $2}' | sed 's/\"//g' )
	snf=$( grep "parent = \"$1\"" "$2" | awk -F "." '{print $1}' | sed 's/snapshot//g' )	
	snf2=$( grep -E snapshot${snf}.disk[0-9]+.fileName "$2" | grep .vmdk | awk -F "=" '{print $2}' | sed 's/\"//g' )
	snf3=${snf2//.vmdk/-delta.vmdk}
	
	output="$snf1"${newline}"$snf2"${newline}"$snf3"
	vmsddir=$( dirname "${2}" )
	vmsddir="$vmsddir"
	IFS=$newline
	for snaplin in $output
	do
		snapl=$(echo "${snaplin}" | sed -e 's/^ *//g' -e 's/ *$//g' )
		if [ "${snapl:0:1}" = "/" ]
		then
		    if [ -f "${snapl}" ]
		    then
		    	spout="${spout}"${newline}"${snapl}"
		    fi
		else
		    snaplp="$(echo ${snapl} | sed -e 's/^ *//g' -e 's/ *$//g' )"
		    if [ -f "${vmsddir}"/"${snaplp}" ]
		    then	
			spout="${spout}"${newline}"${vmsddir}"/"${snaplp}"
		    fi
		fi
	done
	IFS=$OLDIFS
	echo "$spout"
}

replaceAbsolutePaths(){
	if [ -f "$1" ]
	then
		filecontent=$( cat "$1" )
		filecontent="$filecontent"	
	else
		filecontent="$1"
	fi
	abspath="0"
	newfilecontent=""
	IFS=$newline
	for fileline in $filecontent
	do
		value=$( echo "$fileline" | awk -F "=" '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' | sed 's/\"//g' )
		if [ "${value:0:1}" = "/" ]
		then
			newvalue=$( basename "$value" )
			#newfileline="${fileline//$value/$newvalue}"
			newfileline=$( echo "$fileline" | sed "s|$value|$newvalue|g" )
			newfileline="$newfileline"
			abspath="1"
		else
			newfileline="$fileline"
		fi
		newfilecontent="${newfilecontent}${newfileline}"$newline	
	done
	IFS=$OLDIFS
	if [ "$abspath" = "1" ]
	then
		echo "$newfilecontent"
	else
		echo "$filecontent"
	fi
}

cloneVM(){
	
	delSnapshot=$( (deleteSnapshot $1) 2>&1 )
        if [ "$delSnapshot" != "" ]
        then
        	VMERRS="$delSnapshot"
                echo "$delSnapshot">>"$errfileb"
        fi
        
        if NAM=$( getVMName $1)
        then
                cloneMsg="\033[0;36mVM name:\033[0m $NAM\n"
        else
                $( ERR $? "Error getting VM name for: \"$1\"" )
        fi
	
	VMPID=$( ps | grep "$NAM" | awk '{print $2}' | head -n1 )
	
        if VMXDir=$( getVMXDir "$1" )
        then
                cloneMsg="\033[0;36mVMX file directory:\033[0m \"$VMXDir\"\n"
        else
                $( ERR $? "Error getting VMX file directory for: \"$NAM\"" )
        fi

	VMXFILEPATH=$( ls "$VMXDir/"*".vmx" 2>&1 )
	if [ ! -f "$VMXFILEPATH" ]
	then
	    echo -e "\033[0;31mNo .vmx config file found for $NAM ($1)\033[0m"
	    $( ERR $? "No .vmx config file found for $NAM ($1)" )	    
	fi
	VMXFILEDIR=$( dirname "$VMXFILEPATH" )
	VMXFILENAME=$( basename "$VMXFILEPATH" )

	VMSDFILEPATH=$( ls "$VMXDir/"*".vmsd" 2>&1 )
	if [ ! -f "$VMSDFILEPATH" ]
	then
	    echo -e "\033[0;31mNo .vmsd file found for $NAM ($1)\033[0m"
	    $( ERR $? "No .vmsd file found for $NAM ($1)" )
	fi
	VMSDFILEDIR=$( dirname "$VMSDFILEPATH" )
	VMSDFILENAME=$( basename "$VMSDFILEPATH" )

	VMXFFILEPATH=$( ls "$VMXDir/"*".vmxf" 2>&1 )
	if [ ! -f "$VMXFFILEPATH" ]
	then
	    echo -e "\033[0;36mNo .vmxf file found for $NAM ($1)\033[0m"
	    $( ERR $? "No .vmxf file found for $NAM ($1)" "W" )
	fi
	NVRAMFILEPATH=$( ls "$VMXDir/"*".nvram" 2>&1 )
	if [ ! -f "$NVRAMFILEPATH" ]
	then
	    echo -e "\033[0;36mNo .nvram file found for $NAM ($1)\033[0m"
	    $( ERR $? "No .nvram file found for $NAM ($1)" "W" )
	fi
        if VMD=$( getVMDir $1 )
	then
		cloneMsg="\033[0;36mVM directory:\033[0m $VMD\n"
	else
		$( ERR $? "Error getting VM directory for: \"$1\"" )
	fi

	VMXFILECONTENT=$( cat "$VMXFILEPATH" )
	VMSDFILECONTENT=$( cat "$VMSDFILEPATH" )

	if [ "$SERVERTYPE" = "DIR" ]
	then
        	if [ "$datedir" = "yes" ]
        	then
                	thedir="$2"/"$newdirmask"/"$NAM"
        	else
                	thedir="$2"/"$NAM"
        	fi

		if [ -d "$thedir" ]
        	then
                	if [ "$backupprog" = "vmkfstools" ]
                	then
                	    if [ -d "$thedir" ]
                	    then
                		rm -rf "$thedir/"*
                	    fi
        		fi
        	else
                	mkdir -p "$thedir"
        	fi
		if [ -f "$VMXFILEPATH" ]
		then
			#VMXFILECONTENT=$( cat "$VMXFILEPATH" )
			VMXFILECONTENT=$( replaceAbsolutePaths "${VMXFILECONTENT}" )
			echo "$VMXFILECONTENT" > "$thedir"/"$VMXFILENAME"
		fi
                if [ -f "$VMSDFILEPATH" ]
                then
                        #VMSDFILECONTENT=$( cat "$VMSDFILEPATH" )
                        VMSDFILECONTENT=$( replaceAbsolutePaths "${VMSDFILECONTENT}" )
                        echo "$VMSDFILECONTENT" > "$thedir"/"$VMSDFILENAME"
                fi		
		if [ -f "$VMXFFILEPATH" ]
		then
			cp "$VMXFFILEPATH" "$thedir"
		fi
		if [ -f "$NVRAMFILEPATH" ]
		then
			cp "$NVRAMFILEPATH" "$thedir"
		fi
	elif [ "$SERVERTYPE" = "NET" ]
	then	
                thedir="$2"
		if [ "$backsrvtrf" = "F" ]
                then
			# Delete remote folder
			RM=$(eval ssh "$SSHOPTS" -p "$baksrvport" "$baksrvaddr" exec "rm -rf \"${2// /\ }\" 2>&1")	
                fi
                
                LS=$(eval ssh "$SSHOPTS" -p "$baksrvport" "$baksrvaddr" exec "ls -la \"${2// /\ }\" 2>&1")
		if [ "${LS/No such file or directory/}" != "$LS" ]
                then
                        CR=$(eval ssh "$SSHOPTS" -p $baksrvport "$baksrvaddr" exec "mkdir -p \"${2// /\ }\" 2>&1")
                        if [ "${CR/Operation not permitted/}" != "$CR" ]
                        then
				$( ERR 1 "Not allowed to create dir at \"$baksrvaddr\":\"$2\"" )
				exit 1
                        fi
                fi
		if [ -f "$VMXFILEPATH" ]
		then
			#VMXFILECONTENT=$( cat "$VMXFILEPATH" )
			VMXFILECONTENT=$( replaceAbsolutePaths "${VMXFILECONTENT}" )
			TMPFILE=/tmp/"$$_${NAM}_${VMXFILENAME}"
			echo "$VMXFILECONTENT" > "${TMPFILE}"
			scp -o StrictHostKeyChecking=no -i "${PWD}"/xsibackup_id_rsa -P$baksrvport "${TMPFILE}" "$baksrvaddr":\"${2// /\ }/${VMXFILENAME}\" && echo "VMX file copied succesfully." || echo "Error copying VMX file."
			rm -rf "${TMPFILE}"
		fi
		if [ -f "$VMSDFILEPATH" ]
		then
			#VMSDFILECONTENT=$( cat "$VMSDFILEPATH" )
			VMSDFILECONTENT=$( replaceAbsolutePaths "${VMSDFILECONTENT}" )
			TMPFILE=/tmp/"$$_${NAM}_${VMSDFILENAME}"
			echo "$VMSDFILECONTENT" > "${TMPFILE}"
			scp -o StrictHostKeyChecking=no -i "${PWD}"/xsibackup_id_rsa -P$baksrvport "${TMPFILE}" "$baksrvaddr":\"${2// /\ }/${VMSDFILENAME}\" && echo "VMSD file copied succesfully." || echo "Error copying VMSD file."
			rm -rf "${TMPFILE}"
		fi
		
		if [ -f "$VMXFFILEPATH" ]
		then
			scp -o StrictHostKeyChecking=no -i "${PWD}"/xsibackup_id_rsa -P$baksrvport "$VMXFFILEPATH" "$baksrvaddr":\"${2// /\ }\" && echo "VMXF file copied succesfully." || echo "Error copying VMXF file."
		fi

		if [ -f "$NVRAMFILEPATH" ]
		then		
			scp -o StrictHostKeyChecking=no -i "${PWD}"/xsibackup_id_rsa -P$baksrvport "$NVRAMFILEPATH" "$baksrvaddr":\"${2// /\ }\" && echo "NVRAM file copied succesfully." || echo "Error copying NVRAM file."
		fi
	fi

	NOTPRES=$( grep ".present = \"FALSE\"" "$VMXFILEPATH" | grep -E "scsi|ide" | awk -F '.' '{print $1}' )
	if [ "$7" != "" ]
	then
		VMXFILE="$7"
		DOSNAPS="0"
	else
		VMXFILE=$( cat "$VMXFILEPATH" )
		DOSNAPS="1"
	fi
	ALLVMDKVMX=$( echo "$VMXFILE" | grep -vE '^\s*(#|$)' | grep .vmdk )

	if [ "$NOTPRES" != "" ]
	then
		for exd in $NOTPRES
		do
			ALLVMDKVMX=$( echo "$ALLVMDKVMX" | grep -v $exd )
		done	
	fi

	INDEPENDENTNUM=$( echo "$VMXFILE" | grep ".mode = \"independent-" | wc -l )
	INDEPENDENTDSK=$( echo "$VMXFILE" | grep ".mode = \"independent-" | awk -F "." '{print $1}' )

	if [ "${backuphow}" != "cold" ] && [ "$6" = "ON" ]
	then
		if [ $INDEPENDENTNUM -gt 0 ]
		then
		    IFS=$newline
              	    THEEXCLUSIONS2=""
        	    for inddisk in $INDEPENDENTDSK
        	    do
            	    	toexclude=$( echo "$VMXFILE" | grep "$inddisk".fileName | awk -F "=" '{print $2}' | sed 's/\"//g' | sed -e 's/^ *//g' -e 's/ *$//g' )
            	    	if [ "${toexclude:0:1}" == "/" ]
            	    	then
                	    toexclude=$( basename "$toexclude" )
            	    	fi
            	    	THEEXCLUSIONS2=${toexclude}";"${THEEXCLUSIONS2}
            	    	THEEXCLUSIONS2=$( echo "$THEEXCLUSIONS2" | sed 's/;$//')
            	    	THEEXCLUSIONS3=${toexclude}";"${THEEXCLUSIONS3}
        	    done
		    snapshot="excludememory"
		    echo -e "\033[0;36mAt least one independent disk has been detected, excluding memory from snapshot\033[0m"
		    echo -e "\033[0;36mThe following disks will be automatically excluded from the backup:\033[0m"
		    echo -e "\033[1;36m${THEEXCLUSIONS2//;/\\n}\033[0m"
		    echo -e "\033[0;36mThey are independent disks and cannot be hot backed up\033[0m"
		fi
		if [ "$snapshot" = "excludememory" ]
                then
                    echo -e "\033[1;36mMemory has been excluded from the snapshot file\033[0m"
                    sm="0"
                else
                    sm="1"
                fi	

		if [ "$DOSNAPS" = "1" ]
		then	
		if [ "$5" = "toolsOk" ]
		then
			echo -e "\033[0;32mVMWare Tools detected, the system will be quiesced\033[0m"
			CREATESNAP=$( ( vim-cmd vmsvc/snapshot.create $1 xsibackup "XSIBackup snapshot" $sm 1 ) 2>&1 )
			if [ "$CREATESNAP" != "Create Snapshot:" ]
			then
                		VMERRS="$CREATESNAP"
                                echo "$CREATESNAP">>"$errfileb"				
			fi
		else
			echo -e "\033[1;36mVMWare tools were not detected, the system will not be quiesced to take the snapshot\033[0m"
			CREATESNAP=$( ( vim-cmd vmsvc/snapshot.create $1 xsibackup "XSIBackup snapshot" $sm 0 ) 2>&1 )
                        if [ "$CREATESNAP" != "Create Snapshot:" ]
                        then
                                VMERRS="$CREATESNAP"
                                echo "$CREATESNAP">>"$errfileb"
                        fi
		fi
		fi

                # Now lets exclude the snapshots the VM is running on when we make an IP Rsync backup
                if [ "$SERVERTYPE" = "NET" ]
                then
                    LOCKEDDISKS=$( cat "$VMXFILEPATH" | grep -E [-][0-9]{6}.vmdk | awk -F "=" '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' -e 's/\"//g' )
                    IFS=$newline
                    for lckdisk in $LOCKEDDISKS
                    do
                        toexclude=$( basename "$lckdisk" )
                        delta2exclude="${toexclude//.vmdk/-delta.vmdk}"
                        THEEXCLUSIONS2=${toexclude}";"${delta2exclude}";"${THEEXCLUSIONS2}
                    done
                fi

	fi

	if [ "$backupprog" = "rsync" ]
	then
		VMDKLIST=ALL
		ALLVMDK=$( getAllFiles $1 )
	else
		if [ "$backuphow" = "cold" ] || [ "$6" = "OFF" ] || [ "$DOSNAPS" = "0" ]
		then
			VMDKLIST=VMX
			ALLVMDK=$ALLVMDKVMX
		else
			VMDKLIST=TOP
			ALLVMDK=$( getTopVmdks $1 )	
		fi	
	fi

	THEEXCLUSIONS="${3};${THEEXCLUSIONS2}"
	THEEXCLUSIONS="$( echo "${THEEXCLUSIONS}" | sed -e 's/^;//g' -e 's/;$//g' )"

        IFS=$newline
        for eachdisk in $ALLVMDK
        do
        	EXCLUDEDISK=0
        	if [ "$THEEXCLUSIONS" != "" ]
        	then
        		IFS=';'
        		for exclusion in $THEEXCLUSIONS
        		do
        			exclstr=${exclusion//.vmdk/}
        			matchex=$( echo "$eachdisk" | sed -e "s/${exclstr}-*[0-9]*.vmdk//" )
        			if [ "$matchex" != "$eachdisk" ]
        			then
        				EXCLUDEDISK=1
        				eachbasedisk=$( echo "$eachdisk" | awk -F "=" '{print $2}' |  sed -e 's/^ *//g' -e 's/ *$//g' )
        				echo -e "\033[1;36mDisk [$eachbasedisk] excluded\033[0m"	
        			fi	
        		done
        	fi

        	if [ $EXCLUDEDISK -eq 0  ]
        	then

                IFS="="
                part=0
                for eachpart in $eachdisk
                do
                        if [[ $part -eq 1 ]]
                        then
                                thedisk=${eachpart//\"/}
                                thedisk=$( echo $thedisk | sed -e 's/^ *//g' -e 's/ *$//g' )

                                if [ ${thedisk:0:1} == "/" ] && [ -e "$thedisk" ]
                                then
                                	origin="$thedisk"
                                	target="$thedir"/$(getFilename "$thedisk")
                                else
                                        origin="$VMXDir/$thedisk"
                                        target="$thedir/$thedisk"
                                fi
                               
                                if [ "$SERVERTYPE" = "DIR" ] && [ "$backupprog" = "vmkfstools" ]
                                then
                                	target=$( echo "$target" | sed -r 's/[-][0-9]{6}.vmdk/.vmdk/g' )
                                fi

                                if [ "$SERVERTYPE" = "DIR" ]
                                then
                                	if [ -f "$origin" ]
                                	then
                                		exec 5>&1	
                                		if [ "$4" = "rsync" ]
                                		then
							if [ -f "$target" ] && [ "$datedir" == "yes" ]
							then
                                				target=${target//.vmdk/_1.vmdk}
							fi
							#killRsync
                                			if [ $( isFileOpen "$origin" ) == "0" ]
							then
								RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress --partial "$origin" "$target" >&5) 2>&1 )
								if [ "$RSYNCOUT" != "" ]
								then
									VMERRS="$RSYNCOUT"
									echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
									echo "$RSYNCOUT">>"$errfileb"	
                                				fi
                                			fi
							# And now the eventual flat/delta files
                                			flatorigin=""
                                			flatfile=""
                                			flatfile="$(grep -ri '\-delta.vmdk\|\-flat.vmdk' "$origin" | cut -d' ' -f 4- )"
                                			if [ "$flatfile" != "" ]
                                			then
                                				flatfile="${flatfile//\"/}"
                                				vmdkfile=$( basename "$origin" )
                                				vmdkdire=${origin//"$vmdkfile"/}
                                				flatorigin="$vmdkdire""$flatfile"
                                				flattarget="$thedir"/"$flatfile"
                                			fi
                                			if [ "$flatorigin" != "" ] && [ -f "$flatorigin" ] && [ $( isFileOpen "$flatorigin" ) == "0" ]
                                			then
                                			    	if [ -f "$flattarget" ] && [ "$datedir" == "yes" ]
							    	then
									flattarget=${flattarget//.vmdk/_1.vmdk}								
							    	fi	
								if [ -f "$flattarget" ]
                                				then
                                					RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress "$flatorigin" "$flattarget" >&5) 2>&1 )
                                					if [ "$RSYNCOUT" != "" ]
                                					then
                                						VMERRS="$RSYNCOUT"
                                						echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
                                						echo "$RSYNCOUT">>"$errfileb"
                                					fi	
                                				else
                                					RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress --whole-file --sparse "$flatorigin" "$flattarget" >&5) 2>&1 )
                                					if [ "$RSYNCOUT" != "" ]
                                					then
                                						VMERRS="$RSYNCOUT"
                                						echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
                                						echo "$RSYNCOUT">>"$errfileb"
                                					fi	
                                				fi
							#else
                                			#	$( ERR 33 "Missing file, cannot copy: $flatorigin" )
                                			fi
                                		else
                                			if [ -f "$target" ] && [ "$datedir" == "yes" ]
							then	
								target=${target//.vmdk/_1.vmdk}
							fi
							if [ -f "$target" ] && [ "$datedir" != "yes" ]
							then
								REMTARGET=$( rm -rf "$target" )
								if [ "$REMTARGET" != "" ]
								then
									VMERRS="$REMTARGET"
									echo "Error removing target file: $REMTARGET">>"$errfileb"
								fi
							fi
							flatfile="$(grep -ri '\-delta.vmdk\|\-flat.vmdk' "$origin" | cut -d' ' -f 4- )"
							flatfile="${flatfile//\"/}"
							flattarget="$thedir"/"$flatfile"
							if [ -f "$flattarget" ]
							then
								REMFLATTARGET=$( rm -rf "$flattarget" )
								if [ "$REMFLATTARGET" != "" ]
								then
									VMERRS="$REMFLATTARGET"
									echo "Error removing flat target file: $REMFLATTARGET">>"$errfileb"
								fi
							fi			
							if [ $( isFileOpen "${origin//.vmdk/-flat.vmdk}" ) == "0" ]
							then
								VMKFSTOOLSOUT=$( (vmkfstools -d thin -i "$origin" "$target" >&5) 2>&1 )
								if [ "$VMKFSTOOLSOUT" != "" ]
								then
									VMERRS="$VMKFSTOOLSOUT"
									echo -e "\033[0;31m${VMKFSTOOLSOUT}\033[0m" >&5
									echo "$VMKFSTOOLSOUT">>"$errfileb"
								fi
                                			else
                                				VMWARNS="Disk $origin at $NAM is locked by the VM. Persistent or RDM disks can only be -cold- backed up. Exclude $(basename "$origin") from the backup to skip this message."
                                				echo -e "\033[1;31mDisk $origin at $NAM is locked by the VM. Persistent or RDM disks can only be COLD backed up. Exclude $(basename "$origin") from the backup to skip this message.\033[0m" >&5
                                				echo "<span class=warn><b>WARNING:</b> disk $origin at $NAM is locked by the VM. Persistent or RDM disks can only be -cold- backed up. Exclude <b>$(basename "$origin")</b> from the backup to skip this message</span>" >>"$errfileb"
                                			fi
                                			sed -ir 's/[-][0-9]{6}.vmdk/.vmdk/g' "$thedir"/*.vmx 
						    fi
                                		exec 5>&-
                                	else
                                		VMERRS="No origin disk found at: $origin for VM: $VMNAM"
                                		$( ERR 33 "No origin disk found at: $origin" )
                                	fi
                                
				elif [ "$SERVERTYPE" = "NET" ]
				then
				   if [ -f "$origin" ]	
				   then
				     if [ $( isFileOpen "$origin" ) == "0" ]
				     then
					# We kill any posible remote xsibackup-rsync process
					KR=$( killRsync "$baksrvaddr" "$baksrvport" )
					echo $KR
					wait 1
					
					LS=$(eval ssh "$SSHOPTS" -p "$baksrvport" "$baksrvaddr" exec "ls -la \"${target// /\ }\" 2>&1")
					if [ "${LS/No such file or directory/}" != "$LS" ]
					then
						exec 5>&1	
						RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress --partial --whole-file --rsh="ssh -o StrictHostKeyChecking=no -i \"$PWD/xsibackup_id_rsa\" -p$baksrvport" --rsync-path=$baksrvdire"/xsibackup-rsync" "$origin" root@"$baksrvaddr":"${target// /\ }" >&5) 2>&1 )
                                                if [ "$RSYNCOUT" != "" ]
                                                then
                                                	VMERRS="$RSYNCOUT"
                                                        echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
                                                        echo "$RSYNCOUT">>"$errfileb"
                                                fi							
						exec 5>&-
					else
						exec 5>&1
						RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress --partial --inplace --rsh="ssh -o StrictHostKeyChecking=no -i \"$PWD/xsibackup_id_rsa\" -p$baksrvport" --rsync-path=$baksrvdire"/xsibackup-rsync" "$origin" root@"$baksrvaddr":"${target// /\ }" >&5) 2>&1 )
						if [ "$RSYNCOUT" != "" ]
						then
							VMERRS="$RSYNCOUT"
							echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
							echo "$RSYNCOUT">>"$errfileb"
						fi
						exec 5>&-
					fi

					if [ "$backuphow" == "cold" ] && [ $( cat "$origin" | grep parentCID=ffffffff | wc -l ) -gt 0 ]
					then
						echo "Removing unused blocks, please wait..."
						vmkfstools -K "$origin"
					fi

					flatfile="$(grep -ri '\-delta.vmdk\|\-flat.vmdk' "$origin" | cut -d' ' -f 4- )"
					
					if [ "$flatfile" != "" ]
					then
					
					vmdkdire=$( dirname "$origin" )
					flatfile=${flatfile//\"/}
					flatorigin="$vmdkdire"/"$flatfile"
					flattarget="$thedir"/"$flatfile"
				
					if [ -f "$flatorigin" ]
					then
					    if [ $( isFileOpen "$flatorigin" ) == "0" ]
					    then	
						
						LS=$(eval ssh "$SSHOPTS" -p "$baksrvport" "$baksrvaddr" exec "ls -la \"${flattarget// /\ }\" 2>&1")
						if [ "${LS/No such file or directory/}" != "$LS" ]
						then
							exec 5>&1	
							RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress --partial --whole-file --sparse --rsh="ssh -o Compression=no -o StrictHostKeyChecking=no -i \"$PWD/xsibackup_id_rsa\" -p$baksrvport" --rsync-path=$baksrvdire"/xsibackup-rsync" "$flatorigin" root@"$baksrvaddr":"${flattarget// /\ }" >&5) 2>&1 )
							if [ "$RSYNCOUT" != "" ]
							then
								VMERRS="$RSYNCOUT"
								echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
								echo "$RSYNCOUT">>"$errfileb"
							fi
							exec 5>&-
						else
							FRsync=0					
							echo "Comparing file sizes..."
							if [ $(compSizes "$flatorigin" "$baksrvaddr:$baksrvport:$flattarget") == "0" ]
							then
								echo -e "\033[0;36mSizes are different, calculating delta checksums, can take a while, time for a coffee...\033[0m"
								FRsync=1
							else
								echo -e "\033[0;36mFile sizes are equal\033[0m"
								echo -e "\033[0;36mComparing MD5 checksums on both files, can take from a few seconds to several minutes, depending on the sizes...\033[0m"
								if [ $(compHashes "$flatorigin" "$baksrvaddr:$baksrvport:$flattarget") == "0" ]
								then
									echo -e "\033[0;36mChecksums are different, calculating delta checksums, can take a while, time for a coffee...\033[0m"
									FRsync=1
								else
									echo -e "\033[0;32mChecksums are equal, skipping $flatorigin\033[0m"
									FRsync=0
								fi
							fi							
							if [ $FRsync -eq 1 ]
							then
								exec 5>&1
								RSYNCOUT=$( ("$PWD/xsibackup-rsync" -rlpDv --progress --block-size=131072 --inplace --partial --rsh="ssh -T -x -o Compression=no -o StrictHostKeyChecking=no -i \"$PWD/xsibackup_id_rsa\" -p$baksrvport" --rsync-path=$baksrvdire"/xsibackup-rsync" "$flatorigin" root@"$baksrvaddr":"${flattarget// /\ }" >&5) 2>&1 )
                    						if [ "$RSYNCOUT" != "" ]
								then
									VMERRS="$RSYNCOUT"
									echo -e "\033[0;31m${RSYNCOUT}\033[0m" >&5
									echo "$RSYNCOUT">>"$errfileb"
								fi
								exec 5>&-
                    					fi
                    				fi
                    			    else
                    			    	VMWARNS="The file \"$flatorigin\" is locked. Independent disks cannot be hot backed up, please issue a cold backup for [$VMNAME] or exlude the disk from the backup"
                    			    	echo -e "\033[0;31mThe file \"$flatorigin\" is locked. Independent disks cannot be hot backed up, please issue a cold backup for [$VMNAME] or exlude the disk from the backup\033[0m"
                    			    	$( ERR 1 "1051 - The file \"$flatorigin\" is locked. Independent disks cannot be hot backed up, please issue a cold backup for [$VMNAME] or exlude the disk from the backup" "W" )
                    			    fi
                    			#else
                    			#	$( ERR 1 "1051 - The file \"$flatorigin\" does not exist" )
                    			fi
                    		    fi
                    		    else
                    		    	VMWARNS="The file \"$flatorigin\" is locked. Independent disks cannot be hot backed up, please issue a cold backup for [$VMNAME] or exlude the disk from the backup"
                    		    	$( ERR 1 "1447 - The file \"$origin\" is locked by some process, it was not copied" "W" )
                    		    fi	
				    #else
				    #	$( ERR 1 "1447 - The file \"$origin\" does not exist" )
				    fi            
                       		fi
                       	fi	 
                part=$(( $part+1 ))
                done
                IFS=$newline
        
        	fi
        done

       	    # Remove excluded disks from the .vmx file
	    if [ "$THEEXCLUSIONS" != "" ]
       	    then
           	echo -e "\033[0;36m----------------------------------------------------\033[0m"
	      if [ "$SERVERTYPE" = "DIR" ]
	      then
		IFS=';'
           	for exclusion in $THEEXCLUSIONS
           	do
               	    # Remove disks
              	    exclstr=${exclusion//.vmdk/}
		    remvmxpath=$( ls "$thedir"/*.vmx )
		    deletewhat=$( cat "$remvmxpath" | grep -E "${exclstr}-*[0-9]*.vmdk" | awk -F "." '{print $1}' | head -n1 | sed -e 's/^ *//g' -e 's/ *$//g' )
		    if [ "$deletewhat" != "" ]
		    then    
			sed -i "/$deletewhat/d" "$remvmxpath"
		    fi
		done
	      elif [ "$SERVERTYPE" = "NET" ]
	      then	
		TMPFILE=/tmp/"$$_${NAM}_${VMXFILENAME}"
                echo "$VMXFILECONTENT" > "${TMPFILE}"
		IFS=';'
		for exclusion in $THEEXCLUSIONS
		do
    		    exclstr=${exclusion//.vmdk/}
		    deletewhat=$( cat "$TMPFILE" | grep -E "${exclstr}-*[0-9]*.vmdk" | awk -F "." '{print $1}' | head -n1 | sed -e 's/^ *//g' -e 's/ *$//g' )
		    if [ "$deletewhat" != "" ]
		    then	
		    	sed -i "/$deletewhat/d" "$TMPFILE"
		    fi	
		done
                rmd=$( (scp -o StrictHostKeyChecking=no -i "${PWD}"/xsibackup_id_rsa -P$baksrvport "${TMPFILE}" "$baksrvaddr":\"${2// /\ }/${VMXFILENAME}\" ) 2>&1 )
                rm -rf "${TMPFILE}"
                if [ "$rmd" != "" ]
                then
                    VMERRS="Error updating VMX file ${rmd}"
                    echo -e "\033[0;31mError updating VMX file: ${rmd}\033[0m"
                    echo "Error updating VMX file ${rmd}">>"$errfileb"
                fi
	      fi
	    	echo -e "\033[0;36mExcluded disks removed from backup .vmx file\033[0m"
	    fi

        if [ "$SERVERTYPE" = "NET" ] && [ "$domigrate" == "yes" ]
        then
        	REMOTEVMID=$(echo $(eval ssh "$SSHOPTS" -p "$baksrvport" "$baksrvaddr" exec "vim-cmd vmsvc/getallvms | grep \"$VMNAME\" 2>&1") | awk '{print $1}')
        	if [ "$REMOTEVMID" != "" ]
        	then
        		# Check if remote VM is on
        		if [ $( get_vm_state $REMOTEVMID "$baksrvaddr:$baksrvport" ) == "ON" ]
        		then
        			eval ssh "$SSHOPTS" -p "$baksrvport" "$baksrvaddr" exec "vim-cmd vmsvc/power.off $REMOTEVMID 2>&1"
        		fi
        	else
        		# We must register the VM remotely
        		REMOTEVMID=0	
        	fi
	fi
	
        delSnapshot=$( (deleteSnapshot $1 ) 2>&1 )
        if [ "$delSnapshot" != "" ]
        then
                VMERRS="$delSnapshot"
                echo "$delSnapshot">>"$errfileb"
        fi
	
}

getMountedPath(){

        OLDIFS=$IFS
        DIRLIST=$( ls -la /vmfs/volumes 2> /dev/null )
        MYPATH=$1
        PHYS=0
        IFS=$newline
                for line in $DIRLIST
                do
                THEPART=$( echo $line | awk '{ print $11 }' | sed 's/[ \t]\+/ /g' )
                THEMOUN=$( echo $line | awk '{ print $9 }' | sed 's/[ \t]\+/ /g' )
                THEMOUNT="/vmfs/volumes/"$THEMOUN

                if [[ "${MYPATH//$THEPART/}" != "$MYPATH" ]]
                then
                        PHYS=1
                        echo "${MYPATH//$THEPART/$THEMOUN}"
                fi

                done

                if [ $PHYS -eq 0 ]
                then
                        echo "$MYPATH"
                fi


        IFS=$OLDIFS

}

# Preparing of images for the HTML layout

img0="<a href=\"http://33hops.com/\"><img src=\"http://33hops.com/downloads/?f=../images/logo1.gif&${SESSIONID}\" /></a>"
img1="<a href=\"https://twitter.com/intent/user?screen_name=xsibackup\"><img src=\"http://33hops.com/images/follow_tw.jpg\" /></a>"
img2="<a href=\"https://www.facebook.com/xsibackup\"><img src=\"http://33hops.com/images/follow_fb.jpg\" border=\"0\" /></a>"
img3="<a href=\"https://es.linkedin.com/pub/daniel-j-garc%C3%ADa-fidalgo/21/b41/55b\"><img src=\"http://33hops.com/images/follow_ln.jpg\" border=\"0\" /></a>"
img4="<a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RGCHH6EJG93DL\"><img src=\"http://33hops.com/images/paypal_donate.jpg\" border=\"0\" /></a>"
img5="<a href=\"http://33hops.com/?xsipancar\"><img src=\"http://33hops.com/images/xsibackup_banner.jpg?${SESSIONID}\" /></a>"

# We define the HTML and table e-mail header
headHTMLStr="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n
		<html>\n"
		
	stylesHTMLStr="<style type=\"text/css\">\n
		
		body{\n
                  font-size:14px;\n
                  font-family:arial,helvetica;\n
                  font-weight:400;\n
		  color:#333333;	
		}\n	
		
		.txthost{\n
		  color:#0000AA;\n  
		}\n
		
		.errr{\n
		  color:#DD0000;\n
		}\n
		
                .warn{\n
                  color:#D74700;\n
                }\n
		
                .lok{\n
                  color:#FFFFFF;\n
                  background-color:#669933;\n
                  font-weight:600;\n
                }\n

                .lko{\n
                  color:#FFFFFF;\n
                  background-color:#CC3333;\n
                  font-weight:600;\n
                }\n
		
                .ok{\n
                  color:#FFFFFF;\n
                  background-color:#0C3300;\n 
                  font-weight:600;\n 
                }\n	
                
                .ko{\n
                  color:#FFFFFF;\n
                  background-color:#A10008;\n
                  font-weight:600;\n
                }\n                	
			
		.report td{\n
		  font-size:12px;\n
		  font-family:arial,helvetica;\n
		  font-weight:400;\n
		  border-color:#AAAAAA;\n
		  border-width: 1px 1px 1px 1px;\n
		  border-top-style:dotted;\n
		  border-left-style:dotted;\n
		  border-right-style:solid;\n
		  border-bottom-style:solid;\n
		  margin:0;\n
		  padding:4px;\n
		}\n
		
		.report td.separator{\n
		  border-width: 0px;\n
		}\n
		
                .l{\n
                  float: left;\n
                }\n		
		
		.r{\n
		  float: right;\n
		}\n
					
		</style>\n"
		
	logosHTMLStr="<body>\n"
	
	if [ "$img0" != "&nbsp;" ] || [ "$img2" != "&nbsp;" ] || [ "$img3" != "&nbsp;" ] || [ "$img4" != "&nbsp;" ]
	then
	logosHTMLStr="<table border=\"0\">\n
			  <tr>\n
			    <td>\n
				"$img0"
			    </td>\n
			    <td width=\"70\">\n
			    	&nbsp;
			    </td>\n
                            <td>\n
                            	"$img1"
                            </td>\n
                            <td>\n
                            	"$img2"
                            </td>\n
                            <td>\n
                            	"$img3"
			    </td>\n                            
                            <td>\n
                            	"$img4"
			    </td>\n
			  </tr>\n
			</table>\n    
			<br />\n"
	fi	
	if [ "$img5" != "" ]
	then	  
		bannerHTMLStr="
			<table width=\"700\">\n
                          <tr>\n
                            <td colspan=\"8\" align=\"center\">\n
                            	"$img5"
                            </td>\n
                          </tr>\n
                          <tr>\n
                            <td colspan=\"8\" height=\"10\" class=\"error\">
                            	&nbsp;
                            </td>\n
                         </tr>\n
                        </table>\n
                        "
	fi
		
		hostipHTMLStr="
			<table border=\"0\" width=\"700\">\n
			 <tr>\n
			   <td width=\"50%\">\n
			   	"$(date)"<br />\n
			  	<b>"$APPNAM" "$APPVER" AT HOST:<br />\n
				<span class=\"txthost\">"$HOSTNAME"</span></b><br />\n
                           </td>\n
                           <td width=\"50%\" align=\"right\">\n
                        	<b>IP v4:</b> "${HOSTIP}"/&nbsp;"${HOSTMASK}"<br/>"$(vmware -v)"<br /><br />\n
	        	   </td>\n	
                	  </tr>\n
                	   "
                if [ "$testmode" == "true" ]
                then 
                	hostipHTMLStr="${hostipHTMLStr}<tr><td colspan=\"2\"><br /><span class=errr><b>TEST MODE ACTIVATED, REMOVE --test-mode=true TO MAKE A BACKUP</b></span></td></tr>\n"        	
                fi
                        	
		hostipHTMLStr="${hostipHTMLStr}
			  <tr>\n
			   <td colspan=\"2\">&nbsp;</td>
			  </tr>\n
			 </table>\n"  
			
		vmlistHTMLStr="<table width=\"700\" border=\"0\" class=\"report\">\n"


echo "Getting list of all VMs..."
LISTA=$( vim-cmd vmsvc/getallvms )

i=0
IFS=$newline
for line in $LISTA
do

ISVMLINE=0
if [ "${line/vmx-/}" != "$line"  ] && [ "${line/Guest/}" != "$line"  ] && [ "${line/.vmx/}" != "$line"  ] && [ "${line/_XSIBAK/}" == "$line"  ]
then
	ISVMLINE=1
fi
	if [[ "$i" -gt "0" ]] && [[ "$ISVMLINE" == "1" ]]
	then
		echo $line		
		
		VMPID=$(echo $line | awk '{ print $1 }')		
		VMLDIR=$( getVMDir $VMPID )
		VMPATH=$( getVMXDir $VMPID )
		VMSIZE=$( getVMSize $VMPID )
		VMSALL=$(($VMSALL+$VMSIZE)) 
		VMNAM=$( getVMName $VMPID )
		LISTA2=$LISTA2$newline"$line"

		if [[ "$(get_vm_state $VMPID)" == "ON" ]]
		then
			LISTAON="$LISTAON"$newline"$line"
			VMSIZON=$(($VMSIZON+VMSIZE))
		else
			LISTAOF=$LISTAOF$newline"$line"
			VMSIZOF=$(($VMSIZOF+VMSIZE))	
		fi
		
		IFS=','
		for svm in $backupvms
		do
			IFS='!'
			tp=1
			for vmpart in $svm
			do
				if [ $tp -eq 1 ]
				then
					if [[ "$vmpart" == "$VMNAM" ]]
                        		then
                                		LISTACU=$LISTACU$newline"$line"
                                		VMSCUST=$(($VMSCUST+VMSIZE))
                        		fi
				fi
			tp=$(( $tp+1 ))
			done
			IFS=','	
		done
	
	fi

i=$(( $i+1 ))
done
IFS=$OLDIFS

if [[ "$backuptype" == "custom" ]]
then
	LISTA2=$LISTACU
	VMSALL=$VMSCUST
fi

if [[ "$backuptype" == "running" ]]
then
        LISTA2=$LISTAON
        VMSALL=$VMSIZON
fi

if [[ "$LISTA2" == "" ]]
then
	echo -e "\033[0;31mNo VMs to backup\033[0m"
	rm -rf "${PWD}/xsibackup-pid"
        exit 0
else        
	echo "VMs to backup: $LISTA2"
fi

if [[ "$testmode" == "true" ]]
then
	ENOUGH_ROOM=1
fi
	vmlistHTMLStr=$vmlistHTMLStr"<tr>
              <td colspan=\"8\">Done <b>"$backuphow"</b> backup, using <b>"$backupprog"</b>.<br />
              </td>
        </tr>\n"

if [ "$datedir" == "yes" ]
then
        vmlistHTMLStr=$vmlistHTMLStr"<tr>
              <td colspan=\"8\">Backing up to folder <b>"$backuppoint"/"$newdirmask"</b><br />
              </td>
        </tr>\n"        
fi

if [ "$SERVERTYPE" = "DIR" ]
then
	NEEDED_ROOM=$(($VMSALL/1024))
	AVAILA_ROOM=$(($(avail_backup_room "$backuppoint")/1024))
	echo "Needed room: $NEEDED_ROOM Gb."
	echo "Available room: $AVAILA_ROOM Gb."

	if [[ $(($NEEDED_ROOM+4)) -lt $AVAILA_ROOM ]]
	then
		ENOUGH_ROOM=1
	else	

	ENOUGH_ROOM=0
	echo -e "\033[0;36mNot enough room to make the backup, some older folders will be deleted\033[0m"
	fi

	if [ "$backuproom" -gt 0 ]
	then
        vmlistHTMLStr=$vmlistHTMLStr"<tr>
			<td colspan=\"8\">The backup room has been limited to "$backuproom" Gb.<br />
			</td>
		 </tr>\n"	        	
        fi

	vmlistHTMLStr=$vmlistHTMLStr"<tr>
                <td colspan=\"8\">Available room in device $backuppoint before backup: "$AVAILA_ROOM" Gb.<br />
                		  Needed room in device $backuppoint for backup: "$NEEDED_ROOM" Gb.</td>
		           </tr>\n"
else
	vmlistHTMLStr=$vmlistHTMLStr"<tr>
                <td colspan=\"8\">Mirroring following VMs to "$backuppoint"...<br />
                                  </td>
                           </tr>\n"
fi

vmlistHTMLStr=$vmlistHTMLStr"<tr>\n
                <td><b>VM Name</b></td>\n
		<td><b>State</b></td>\n
		<td><b>Size</b></td>\n
                <td><b>Stop</b></td>\n
                <td><b>Copy</b></td>\n
                <td><b>Start</b></td>\n
                <td><b>Time (min)</b></td>\n
                <td><b>Speed (mb/s)</b></td>\n
               </tr>\n"
STARTALL=$(date +%s)
i=0
IFS=$newline
for line in $LISTA2
do
	VMERRS=""
	VMWARNS=""
	vmlistHTMLStr=$vmlistHTMLStr"<tr>\n"
	STARTVM=$(date +%s)

	VMIDNU=`echo $line | awk '{ print $1 }'`
	VMNAME=$(getVMName $VMIDNU)
		vmlistHTMLStr=$vmlistHTMLStr"<td><b>"$VMNAME"</b></td>\n"
	VMSTAT=$(get_vm_state $VMIDNU)
	if [ "$VMSTAT" == "ON" ]
	then
		c="lok"
	else
		c="lko"
	fi	
		vmlistHTMLStr=$vmlistHTMLStr"<td class=\""${c}"\"><b>"${VMSTAT}"</b></td>\n"
	VMSIZE=$( getVMSize $VMIDNU )
		vmlistHTMLStr=$vmlistHTMLStr"<td><b>"$(($VMSIZE/1024))"G</b></td>\n"
	
	VMLOCA=$( echo $line | awk '{ print $8 }' )
	ETOOLS=$( getValue "vim-cmd vmsvc/get.guest $VMIDNU" "toolsStatus" )
	eval $ETOOLS

	if [[ "$backuphow" == "cold" ]]
	then
	
	if [[ "$VMSTAT" == "ON" ]]
	then	
	
	#1	
	echo "Stopping VM [$VMNAME]"
	
	if [ "$toolsStatus" == "toolsNotInstalled" ]
	then
		vim-cmd vmsvc/power.off $VMIDNU
		echo -e "\033[0;36mNo VMware Tools detected in VM: [$VMNAME], power-off issued\033[0m"
		EXITCODE="OK (Power Off)"
	else
		vim-cmd vmsvc/power.shutdown $VMIDNU
	fi
	
	sleep 30
	echo "SLEEPING 30 s, waiting for VM to be off"	
			EXITCODE="OK (Shutdown)"	
	m=0	
	while [ "$(get_vm_state $VMIDNU)" == "ON" ]
	do
		
		if [[ $m -lt 3 ]]
		then
		
			echo "SLEEPING 10 s, waiting for VM to be off"
			sleep 10
			EXITCODE="OK (Shutdown)"
		
		else
			
			#2
			if [[ $m -eq 3 ]]
			then
				vim-cmd vmsvc/power.off $VMIDNU
				sleep 10
			fi
			
			if [[ $? != 0 ]]
                        then
                                EXITCODE="KO (Power Off)"
                        else
                                EXITCODE="OK (Power Off)"
                        fi

		fi
	
	m=$(($m+1))
	done

	else
		echo "VM [$VMNAME] was already in an Off state"	
		EXITCODE="-"
	fi
	
	else
		echo -e "\033[0;36mHot backup selected for VM: ["$VMNAME"], will not be switched off\033[0m"
		EXITCODE="NO (hot backup)"
	
	fi
		# EXCLUDE DISKS
                EXCLUDEVMDK=""
                IFS=','
                for evm in $backupvms
                do
                        IFS='!'
                        tp=1
                        for evmpart in $evm
                        do
                                if [ $tp -eq 1 ]
                                then
                                        evmname="$evmpart"
                                fi

                                if [ $tp -eq 2 ]
                                then
                                        if [[ "$evmname" == "$VMNAME" ]]
                                        then
                                                EXCLUDEVMDK="$evmpart"
                                        fi
                                fi
                        tp=$(($tp+1))
                        done
                        IFS=','
                done
                IFS=$newline
		if [ "$EXCLUDEVMDK" != "" ]
		then
                	echo -e "\033[0;36mExcluding disk [$EXCLUDEVMDK] and derived files\033[0m"
		fi

	vmlistHTMLStr=$vmlistHTMLStr"<td><b>"$EXITCODE"</b></td>\n"

	VMOS=$( echo "$line" | awk -F "Guest" '{print $1}' | awk -F ".vmx" '{print $2}' | sed -e 's/^ *//g' -e 's/ *$//g' )
	QUIESCEVM="1"
	if [ "$VMOS" = "winLonghorn64" ]
	then
		QUIESCEVM="0"
	else
		QUIESCEVM="1"
	fi

	if [[ "$testmode" != "true" ]]
	then		
		VMDIRN=$( getVMDir $VMIDNU )
		if [ "$SERVERTYPE" = "DIR" ]
		then
			if [[ $ENOUGH_ROOM == 0 ]]
			then
				makeRoomHtml=""
				# Now we make room for the current backup
				ROOMWENEED=$(( $VMSIZE * (120/100) ))
				# Deprecated 120% + 12288 VMWare rule
				# ROOMWENEED=$(( $VMSIZE * (120/100) + 12288 ))
				echo "Attempting to make room at $backuppoint in local server"
				MAKEROOMRESP=$(make_room $ROOMWENEED "$backuppoint")	
				if [[ "$MAKEROOMRESP" != "" ]]
				then
        				makeRoomHtml="<tr>
                 			<td colspan=\"8\"><b>The eldest folders were deleted to make room:</b><br />"$MAKEROOMRESP"</td>
                			</tr>\n"
				fi
			fi

			cloneVM $VMIDNU "$backuppoint" "$EXCLUDEVMDK" "$backupprog" "$toolsStatus" "$VMSTAT"
			
		elif [ "$SERVERTYPE" = "NET" ]
		then
			cloneVM $VMIDNU "$baksrvdire/$VMDIRN" "$EXCLUDEVMDK" "rsync" "$toolsStatus" "$VMSTAT"
			#CLONERETURN=$(cloneVM $VMIDNU "$baksrvdire/$VMDIRN")
			if [ $? -ne 0 ]
			then
				echo -e "\033[0;31mThe remote backup path does not exist and cannot be created\033[0m"
				exit 0
			fi
		else
			echo -e "\033[0;31mUnable to determine the type of server parsed\033[0m"
			exit 0
		fi
	else
		echo -e "\033[0;36mTest mode activated VMs will not be cloned, please remove --test-mode=true to allow backups\033[0m"
	fi
	sleep 10
	if [[ $? != 0 -o "$VMERRS" != "" ]]
	then
		EXITCODE="KO!"
		EXITCLAS="ko"
	else
		EXITCODE="OK"
		EXITCLAS="ok"
	fi
	vmlistHTMLStr=$vmlistHTMLStr"<td class=\""$EXITCLAS"\"><b>"$EXITCODE"</b></td>\n"
	
	if [[ "$backuphow" == "cold" ]]
	then
		if [ "$VMSTAT" == "ON" ]
		then
	
		#4	
		vim-cmd vmsvc/power.on $VMIDNU
	        	if [[ $? != 0 ]]
	        	then
	        		EXITCODE="KO"
	        	else
	                	EXITCODE="OK"
	        	fi
		else
			EXITCODE="-"
		fi        
	else
		EXITCODE="-"		
	fi
	vmlistHTMLStr=$vmlistHTMLStr"<td><b>"$EXITCODE"</b></td>\n"

sleep 1	
ENDVM=$(date +%s)
DIFFVM=$(( $ENDVM - $STARTVM ))
	
		vmlistHTMLStr=$vmlistHTMLStr"
               	<td><b>"$(($DIFFVM/60))"</b></td>\n
               	<td><b>"$(($VMSIZE/$DIFFVM))"</b></td>\n
             	</tr>\n"$makeRoomHtml
		if [ "$VMERRS" != "" ]
		then		
			# If we have an error in the context of the current VM we output it (only last)
			vmlistHTMLStr=$vmlistHTMLStr"
			<tr>\n
			<td colspan=\"8\"><b>Last error for the above VM:</b><br />"$VMERRS"</td>			
			</tr>\n"
		fi
		# We treat warnings independently
                if [ "$VMWARNS" != "" ]
                then
                        # If we have a warning in the context of the current VM we output it (only last)
                        vmlistHTMLStr=$vmlistHTMLStr"
                        <tr>\n
                        <td colspan=\"8\" class=\"warn\"><b>Last warning for the above VM:</b><br />"$VMWARNS"</td>
                        </tr>\n"
                fi		
i=$(( $i + 1 ))
done
IFS=$OLDIFS

ENDALL=$(date +%s)
DIFFALL=$(( $ENDALL - $STARTALL ))

	if [ "$SERVERTYPE" = "DIR" ]
	then
	     AVAILA_ROOM=$(( $(avail_backup_room $backuppoint)/1024 ))
	     vmlistHTMLStr=$vmlistHTMLStr"<tr>
         	<td colspan=\"8\">Available space in device $backuppoint after backup: "$AVAILA_ROOM" Gb.</td>
		</tr>\n"
	fi	
	vmlistHTMLStr=$vmlistHTMLStr"<tr> 
	 <td colspan=\"8\">Complete backup elapsed time: "$(($DIFFALL/60))" min</td>
        </tr>\n"
	
	if [ "$testmode" != "true" ]
	then
		# Backup ESXi server configuration
		if [ "$datedir" == "yes" ] && [ "$SERVERTYPE" == "DIR" ]
        	then
        		backConfPath="$backuppoint"/"$newdirmask"
                	backConfResult=$( backupConfig "$backConfPath" 2>>"$errfileb" )
        	else
                	backConfPath="$backuppoint"
                	backConfResult=$( backupConfig "$backConfPath" 2>>"$errfileb" )
        	fi
		if [ "$backConfResult" == "1" ]
        	then
        		echo -e "\033[0;32mThe ESXi configuration was saved to $backConfPath\033[0m"

        		vmlistHTMLStr=$vmlistHTMLStr"
        		<tr>\n
         		<td colspan=\"8\">The ESXi configuration was saved to $backConfPath</td>\n
        		</tr>\n"
		else
                	echo -e "\033[0;31mError backing the ESXi host config to $backConfPath\033[0m"
                	echo -n "Error backing the ESXi host config to $backConfPath" >>"$errfileb"
        	fi
		# End of Backup ESXi server configuration
        	if [ "$debuginfo" == "yes" ]
        	then
                	echo -e "\033[0;32mAdding debug information to the report\033[0m"
                	vmlistHTMLStr=$vmlistHTMLStr"
                	<tr>\n
                	<td colspan=\"8\"><b>DEBUG INFORMATION:</b><br />$DEBUGINFO</td>\n
                	</tr>\n"
        	fi
		# End of testmode check
	fi
	
	IFS=","
        for email in $mailto
        do
            if [ ! $(echo "${email}" | grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b") ]
            then
            	$( ERR 2188 "<b>${email}</b> excluded from the e-mail recipient list, not evaluable as an e-mail address" "W" )
            fi
        done
        IFS=$OLDIFS


rm -rf "$errfileb"


vmlistHTMLStr=$vmlistHTMLStr"</table>\n"

emailHTMLStr=${headHTMLStr}${stylesHTMLStr}${logosHTMLStr}${bannerHTMLStr}${hostipHTMLStr}${vmlistHTMLStr}"<br /><br />"${smartinfo}			                                                                                                

# We write the footer of the e-mail
emailHTMLStr=$emailHTMLStr"\n</body>\n</html>"

# If we have set a custom template we process it here

if [ "$skin" != "" ]
then
        skindir=".xsibackup-skins"
        skinext=".xsiskin"
        
        if [ ! -d ${pwd}"$skindir" ]
        then
                mkdir "$skindir"
        fi	
	
	if [ "${skin:0:7}" == "http://" ]
	then	
		theskin=$( wget -qO- "$skin" )
		# Lets replace the images
		i=0
		IFS=","
		for imgx in $imglist
		do
			imgvar="img"${i}
			eval "echo $imgvar"		
		i=$(( $i + 1 ))
		done
		IFS=$OLDIFS
		exit 0	
	else
		if [ -e "$skin" ]
		then
			echo "We got a local file"
		fi
	fi
fi

# We send the e-mail

if [[ $SEND_EMAIL == 1 ]]
then

        IFS=","
        em=0
        for email in $mailto
        do
            if [ $(echo "${email}" | grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b") ]
            then
                recipient="$email"
                break
            fi
        em=$(( $em+1 ))
        done
        IFS=$OLDIFS

		err_exit() { echo -e 1>&2; exit 1; }

		mail_input() {
  		
  		if [ "${smtpsrv//gmail/}" != "${smtpsrv}" ]
  		then
  			nl="\n"
  			delay="2"
  		else
  			nl="\r\n"
  			delay="0"
  		fi
  		
  		echo -ne "helo ${HOSTNAME}${nl}"
  		sleep ${delay}
  		echo -ne "ehlo ${HOSTNAME}${nl}"
  		sleep ${delay}
  		if [ "$smtpauth" != "none" ]
  		then
  			echo -ne "AUTH LOGIN${nl}"
  			sleep ${delay}
  			if [ "${smtpsrv//gmail/}" != "${smtpsrv}" ]
  			then
  				echo -ne "$( echo $smtpusr | openssl base64 2>/dev/null )${nl}"
  				sleep ${delay}
  				echo -ne "$( echo $smtppwd | openssl base64 2>/dev/null )${nl}"
  			else
  				echo -ne "$( base64_encode $smtpusr )${nl}"
  				sleep ${delay}
  				echo -ne "$( base64_encode $smtppwd )${nl}"
  			fi
  			sleep ${delay}
  		fi
  		echo -ne "MAIL FROM: <${mailfrom}>${nl}"
               	sleep ${delay}
                IFS=","
                for email in $mailto
                do
                        if [ $(echo "${email}" | grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b") ]
                        then
                                echo -ne "RCPT TO: <${email}>${nl}"
                        	sleep ${delay}
                        fi
                done
                IFS=$OLDIFS
  		echo -ne "DATA${nl}"
  		sleep ${delay}
  		echo -ne "SUBJECT: ${subject}${nl}"
  		sleep ${delay}
  		echo -ne "TO: <${recipient}>${nl}"
  		sleep ${delay}
  		echo -ne "Content-type: text/html${nl}"
  		sleep ${delay}
  		echo -ne "From: <${mailfrom}>${nl}"
  		sleep ${delay}
		echo -ne "Date: $(date -R)${nl}"
		sleep ${delay}
		echo -ne "${nl}"
  		echo -ne $emailHTMLStr"${nl}"
  		sleep ${delay}
  		if [ -z "$smtpdelay" ]
  		then
  			smtpdelay=0
  		fi
  		if [ $smtpdelay -gt 0 -a $smtpdelay -lt 4 ]
  		then
  			sleep $smtpdelay
  		fi
  		echo -ne ".${nl}"
                sleep ${delay}
                if [ $smtpdelay -gt 0 -a $smtpdelay -lt 4 ]
                then
                        sleep $smtpdelay
                fi  		
		echo -ne "quit${nl}"
		}

        FWRESPONSE=$( openFirewall "$smtpport" "SMTPout-$smtpport" "9999" "0000" "tcp" )

        sleep 2
        echo $FWRESPONSE

        FWRESPONSE=$( esxcli network firewall ruleset set --ruleset-id=SMTPout-$smtpport --enabled=true )
        FWRESPONSE=$( esxcli network firewall refresh )

		
		if [ "${smtpsrv//gmail/}" != "${smtpsrv}" ]
		then
			mail_input | openssl s_client -pause -connect ${smtpsrv}:${smtpport} -ign_eof -crlf 2>/dev/null
		elif [ "$smtpsec" = "tls" ]
		then		
			mail_input | openssl s_client -starttls smtp -connect ${smtpsrv}:${smtpport} -ign_eof 2>/dev/null
		else
			mail_input | nc $smtpsrv $smtpport || err_exit
		fi
		
	# We close the SMTP port
	esxcli network firewall ruleset set --ruleset-id=SMTPout-$smtpport --enabled=false
	echo "Firewall rule SMTPout-$smtpport closed."	
fi

rm -rf "${PWD}/xsibackup-pid" > /dev/null 2>&1
rm -rf "${PWD}/.ERR"* > /dev/null 2>&1
echo -e "\033[0;32mPID file deleted\033[0m"
echo -e "\033[0;32mBackup finished\033[0m"
if [ ${#next} -gt 0 ]
then
	echo -e "\033[0;36mExecuting next chained backup ID($backupId)\033[0m"
	eval $next >> "${PWD}/xsibackup-cron.log"
fi	
