Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change shutdown snapshot backup logic #165

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 33 additions & 29 deletions ghettoVCB.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
# User Definable Parameters
##################################################################

LAST_MODIFIED_DATE=2019_01_06
VERSION=4
LAST_MODIFIED_DATE=2019_02_07
VERSION=1

# directory that all VM backups should go (e.g. /vmfs/volumes/SAN_LUN1/mybackupdir)
VM_BACKUP_VOLUME=/vmfs/volumes/mini-local-datastore-hdd/backups
Expand All @@ -24,8 +24,10 @@ DISK_BACKUP_FORMAT=thin
# Number of backups for a given VM before deleting
VM_BACKUP_ROTATION_COUNT=3

# Shutdown guestOS prior to running backups and power them back on afterwards
# This feature assumes VMware Tools are installed, else they will not power down and loop forever
# Shutdown guestOS, take a snapshot, power back on the VM, backup the snapshot and consolidate the
# snapshot afterwards (making a "cold" backup). This feature needs working VMware Tools installed,
# else the shutdown will loop forever. ENABLE_HARD_POWER_OFF=1 is recommended to avoid an infinite
# loop.
# 1=on, 0 =off
POWER_VM_DOWN_BEFORE_BACKUP=0

Expand Down Expand Up @@ -189,6 +191,7 @@ printUsage() {
echo
echo "OPTIONS:"
echo " -a Backup all VMs on host"
echo " -e Path to VM exclusion list"
echo " -f List of VMs to backup"
echo " -m Name of VM to backup (overrides -f)"
echo " -c VM configuration directory for VM backups"
Expand Down Expand Up @@ -533,7 +536,7 @@ dumpVMConfigurations() {
logger "info" "CONFIG - GHETTOVCB_PID = ${GHETTOVCB_PID}"
logger "info" "CONFIG - VM_BACKUP_VOLUME = ${VM_BACKUP_VOLUME}"
logger "info" "CONFIG - ENABLE_NON_PERSISTENT_NFS = ${ENABLE_NON_PERSISTENT_NFS}"
if [[ "${ENABLE_NON_PERSISTENT_NFS}" -eq 1 ]]; then
if [[ "${ENABLE_NON_PERSISTENT_NFS}" -eq 1 ]]; then
logger "info" "CONFIG - UNMOUNT_NFS = ${UNMOUNT_NFS}"
logger "info" "CONFIG - NFS_SERVER = ${NFS_SERVER}"
logger "info" "CONFIG - NFS_VERSION = ${NFS_VERSION}"
Expand Down Expand Up @@ -567,18 +570,18 @@ dumpVMConfigurations() {
logger "info" "CONFIG - EMAIL_TO = ${EMAIL_TO}"
logger "info" "CONFIG - WORKDIR_DEBUG = ${WORKDIR_DEBUG}"
fi
if [[ "${ENABLE_NFS_IO_HACK}" -eq 1 ]]; then
logger "info" "CONFIG - ENABLE NFS IO HACK = ${ENABLE_NFS_IO_HACK}"
logger "info" "CONFIG - NFS IO HACK LOOP MAX = ${NFS_IO_HACK_LOOP_MAX}"
logger "info" "CONFIG - NFS IO HACK SLEEP TIMER = ${NFS_IO_HACK_SLEEP_TIMER}"
logger "info" "CONFIG - NFS BACKUP DELAY = ${NFS_BACKUP_DELAY}\n"
else
logger "info" "CONFIG - ENABLE NFS IO HACK = ${ENABLE_NFS_IO_HACK}\n"
fi
if [[ "${ENABLE_NFS_IO_HACK}" -eq 1 ]]; then
logger "info" "CONFIG - ENABLE NFS IO HACK = ${ENABLE_NFS_IO_HACK}"
logger "info" "CONFIG - NFS IO HACK LOOP MAX = ${NFS_IO_HACK_LOOP_MAX}"
logger "info" "CONFIG - NFS IO HACK SLEEP TIMER = ${NFS_IO_HACK_SLEEP_TIMER}"
logger "info" "CONFIG - NFS BACKUP DELAY = ${NFS_BACKUP_DELAY}\n"
else
logger "info" "CONFIG - ENABLE NFS IO HACK = ${ENABLE_NFS_IO_HACK}\n"
fi
}

# Added the function below to allow reuse of the basics of the original hack in more places in the script.
# Rewrote the code to reduce the calls to the NAS when it slows. Why make a bad situation worse with extra calls?
# Rewrote the code to reduce the calls to the NAS when it slows. Why make a bad situation worse with extra calls?
NfsIoHack() {
# NFS I/O error handling hack
NFS_IO_HACK_COUNTER=0
Expand Down Expand Up @@ -715,7 +718,7 @@ checkVMBackupRotation() {
# Added the NFS_IO_HACK check and function call here. Also set the script to function the same, if the new feature is turned off.
# Added variables to the code to control the timers and loops.
# This code could be optimized based on the work in the NFS_IO_HACK function or that code could be used all the time with a few minor changes.
if [[ $? -ne 0 ]] && [[ "${ENABLE_NFS_IO_HACK}" -eq 1 ]]; then
if [[ $? -ne 0 ]] && [[ "${ENABLE_NFS_IO_HACK}" -eq 1 ]]; then
NfsIoHack
else
#NFS I/O error handling hack
Expand Down Expand Up @@ -893,12 +896,12 @@ ghettoVCB() {
#1 = readonly
#0 = readwrite
logger "debug" "Mounting NFS: ${NFS_SERVER}:${NFS_MOUNT} to /vmfs/volume/${NFS_LOCAL_NAME}"
if [[ ${ESX_RELEASE} == "5.5.0" ]] || [[ ${ESX_RELEASE} == "6.0.0" || ${ESX_RELEASE} == "6.5.0" || ${ESX_RELEASE} == "6.7.0" ]] ; then
if [[ ${ESX_RELEASE} == "5.5.0" ]] || [[ ${ESX_RELEASE} == "6.0.0" || ${ESX_RELEASE} == "6.5.0" || ${ESX_RELEASE} == "6.7.0" ]] ; then
${VMWARE_CMD} hostsvc/datastore/nas_create "${NFS_LOCAL_NAME}" "${NFS_VERSION}" "${NFS_MOUNT}" 0 "${NFS_SERVER}"
else
${VMWARE_CMD} hostsvc/datastore/nas_create "${NFS_LOCAL_NAME}" "${NFS_SERVER}" "${NFS_MOUNT}" 0
fi
fi
fi
fi

captureDefaultConfigurations
Expand Down Expand Up @@ -1053,15 +1056,15 @@ ghettoVCB() {
$VMWARE_CMD vmsvc/snapshot.removeall ${VM_ID} > /dev/null 2>&1
fi
fi
#nfs case and backup to root path of your NFS mount
#nfs case and backup to root path of your NFS mount
if [[ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ]] ; then
BACKUP_DIR="/vmfs/volumes/${NFS_LOCAL_NAME}/${NFS_VM_BACKUP_DIR}/${VM_NAME}"
if [[ -z ${VM_NAME} ]] || [[ -z ${NFS_LOCAL_NAME} ]] || [[ -z ${NFS_VM_BACKUP_DIR} ]]; then
logger "info" "ERROR: Variable BACKUP_DIR was not set properly, please ensure all required variables for non-persistent NFS backup option has been defined"
exit 1
fi

#non-nfs (SAN,LOCAL)
#non-nfs (SAN,LOCAL)
else
BACKUP_DIR="${VM_BACKUP_VOLUME}/${VM_NAME}"
if [[ -z ${VM_BACKUP_VOLUME} ]]; then
Expand Down Expand Up @@ -1124,7 +1127,7 @@ ghettoVCB() {
VM_VMDK_FAILED=0

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

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

for j in ${VMDKS}; do
VMDK=$(echo "${j}" | awk -F "###" '{print $1}')
isVMDKFound=0
Expand Down Expand Up @@ -1233,7 +1243,7 @@ ghettoVCB() {
fi

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

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

TMP_IFS=${IFS}
IFS=${ORIG_IFS}
if [[ ${ENABLE_COMPRESSION} -eq 1 ]] ; then
Expand Down Expand Up @@ -1351,8 +1355,8 @@ ghettoVCB() {
# Added the Brute-force delay in case it is needed.
if [[ "${ENABLE_NFS_IO_HACK}" -eq 1 ]]; then
NfsIoHack
sleep "${NFS_BACKUP_DELAY}"
fi
sleep "${NFS_BACKUP_DELAY}"
fi
done
# UNTESTED CODE
# Why is this outside of the main loop & it looks like checkVMBackupRotation() could be called twice?
Expand Down
37 changes: 37 additions & 0 deletions rc.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

####################### start ghettoVCB #######################
# add this to /etc/rc.local.d/local.sh BEFORE the 'exit 0'!

# create firewall config for ghettoVCB mail
VCBDIR="/vmfs/volumes/<DATASTORE>/scripts/ghettoVCB"
HOST=$(hostname -s)
if [ -d ${VCBDIR} ]; then
if [ -f ${VCBDIR}/vcb-smtp.xml -a ! -f /etc/vmware/firewall/vcb-smtp.xml ] ; then
cp -p ${VCBDIR}/vcb-smtp.xml /etc/vmware/firewall/
localcli network firewall refresh
fi
fi

# create crontab entries for ghettoVCB script
/bin/kill $(cat /var/run/crond.pid)
CRONTAB="/var/spool/cron/crontabs/root"

# cleanup current crontab
grep -v "ghettoVCB" ${CRONTAB} >/tmp/crontab-root.tmp
chmod 0444 /tmp/crontab-root.tmp
chmod -t ${CRONTAB}
mv /tmp/crontab-root.tmp ${CRONTAB}
chmod +t ${CRONTAB}

# ATTENTION: start time is in UTC, not local time!
# to start at 19:33 local time
# CET: 33 18 <--
# CEST: 33 17
echo "33 18 * * * ${VCBDIR}/ghettoVCB-wrapper.sh >${VCBDIR}/${HOST}-wrapper.log 2>&1" >> ${CRONTAB}
/bin/crond

# load multiextent module for 2gbsparse - needed with 5.0u3/5.1u1 and newer,
# doesn't hurt on other systems
localcli system module load -m multiextent

######################## end ghettoVCB ########################
14 changes: 14 additions & 0 deletions vcb-smtp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- Firewall configuration information for vcb-smtp -->
<ConfigRoot>
<service>
<id>vcb-smtp</id>
<rule id='0000'>
<direction>outbound</direction>
<protocol>tcp</protocol>
<porttype>dst</porttype>
<port>25</port>
</rule>
<enabled>true</enabled>
<required>false</required>
</service>
</ConfigRoot>