ESXi 4 VM Backup using unsupported SSH login and ftpput

I got the skeleton of…

Login

Blog History

I got the skeleton of this script from another post.

DISCLAIMER: Use this at your own risk. I am not responsible for any data corruption or loss that may occur if you decide to use this without first making sure it works for you.

After playing around with it for hours I have made some changes:

  • When called without arguments show a list of backup candidates
  • Validate the VMID
  • Make sure all VM files are copied even if a VM is stored on multiple data stores
  • Work around some weird ash bugs I discovered while testing

To use copy this file to /sbin/vmbackup.sh on ESXi box and make it executeable.

You need to change the BACKUPHOST, BACKUPUSER and BACKUPPW values to suit and copy it in scp mode because the ESXi box doesn't have a sftp server on the SSH console.

#!/bin/sh 
VERSION=2.0
if [ -z "$1" ]; then 
echo "Usage: $0 vmid"
echo "Your choices are:"
vim-cmd /vmsvc/getallvms | grep -v "Name" | awk -F"[" '{ print $1 }'
exit 1 
fi 
SERVNAME=$1 
# Backup host information 
BACKUPHOST=10.11.12.13
BACKUPUSER=ftpuser
BACKUPPW='ftppassword' 
# you must create the backup target
# if vmname is "WinXP Pro Client" then
# make a dir on the remote ftp server under BACKUPDIR with that name
# ftpput will not do it for you
# e.g. mkdir "/media/disk/backup/WinXP Pro Client"

BACKUPDIR='/media/disk/backup'

# Get vm info 
#VMID=`echo $1  /vmsvc/getallvms | grep -v "^Vmid" | grep "$SERVNAME" | awk '{ print $1 }'` 

# Using the passed in VMID check if it's valid and exit if not
VMID=`vim-cmd /vmsvc/getallvms | grep -v "Name" | awk '{ print $1 }' | grep  -E "^$1$"`

if [ -z "$VMID" ]; then
	echo Invalid VM ID
	exit 1
fi

VMNAME=`vim-cmd /vmsvc/getallvms | grep -i "^$VMID " | awk -F" {2,}" '{ print $2 }'`
 # awk -F" {2,}" '{ print $2 }'
VMSTAT=`vim-cmd /vmsvc/power.getstate $VMID | grep Powered | awk '{ print $2 }'`

# vms can exist on multiple data stores so...
# grab  the entire url line 
# e.g.
# url                  /vmfs/volumes/4c372585-c5be3670-5b7e-001d091edb9f   /vmfs/volumes/4c371e81-0c463360-dfe3-001d091edb9f
VMDATASTORES=`vim-cmd /vmsvc/get.datastores $VMID | grep url`

# this is better but untested (doens't capture the url first token)
# comment out the "if [ "$j" != "url" ] ; then" if statement
# line if you use this
#VMDATASTORES=`vim-cmd /vmsvc/get.datastores $VMID | grep url | awk '{$1=""; print $0}'`

echo "Datastores for $VMID"
echo $VMDATASTORES
#echo At the end
#exit 1
# vmname can be wildly different from vmdir so find vmdir
VMDIR=`vim-cmd /vmsvc/getallvms |  grep -i "^$VMID " | awk -F"[]/]" '{ print $2 }' | sed 's/^[[:space:]]*\(.*\)[[:space:]]*$/\1/'`

# get the power status (is it on or off)
VMSTAT=`vim-cmd /vmsvc/power.getstate $VMID | grep Powered | awk '{ print $2 }'` 
if [ "$VMSTAT" = "off" ]; then 
	echo "Server $VMNAME with VMID $VMID is already powered off"
else 
	echo "Powering off server $VMNAME with ID $j" 
	vim-cmd /vmsvc/power.shutdown $VMID

	VMSTAT=on
	echo "Checking status (now $VMSTAT)"
	while [ "$VMSTAT" = "on" ]; do
		echo wait for "$VMNAME" to shutdown.. 
		sleep 10 
		VMSTAT=`vim-cmd /vmsvc/power.getstate $VMID | grep Powered | awk '{ print $2 }'` 
	done 
	# ensure to start vm again when it was running:
	VMSTAT=on
fi 

# set the field separator to new line because it doesn't like
# spaces in the names
# IFS=$(echo -e '\n')

# or you can use
#IFS='
#'

# working around ash bug regarding spaces in files

# echo Ok succesfully changed dir
for j in $VMDATASTORES
do 
	# vmlocation is the vmdatastore and vmdir
	if [ "$j" != "url" ] ; then 
		VMLOCATE="$j/$VMDIR"
		echo "Location: $VMLOCATE"
		echo change to vmware dir
		cd "$VMLOCATE" || exit 1

		for i in ./*; do
			FILE=`echo $i | sed s+\./++`
			echo backup "$VMLOCATE/$FILE" to "$BACKUPDIR/$VMNAME/$FILE" on $BACKUPHOST
			ftpput -u $BACKUPUSER -p $BACKUPPW $BACKUPHOST "$BACKUPDIR/$VMNAME/$FILE" "$FILE"
		done
	fi 
done

if [ "$VMSTAT" = "on" ]; then
	# vm was on when we started the backup, now start it again 
	vim-cmd /vmsvc/power.on $VMID
fi

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.