VMware server 2.0 (Backup Script)
Eindelijk de moed verzameld om mijn VMware server 1.0.5 te upgraden naar 2.0.
Eerst op een oude server (32bit) uitgeprobeerd en na installatie werkte alles .. behalve het vmware-vim-cmd. Wat vervelend is omdat ik intensief gebruik maak van het in versie 1.0.5 aanwezige vmware-cmd om periodiek een backup van verschillende VM’s te maken (o.a. mijn webserver en Zimbra mailserver). Maar ik heb een grenzeloos vertrouwen in de kwaliteit van VMware producten dus ik heb de stoute schoenen aangetrokken en VMware Server 2.0.0 op de productie server (BigBrother) geïnstalleerd. BigBrother draait openSUSE 10.3 64 bit en heeft 8 cores Intel 3.0GHz met 16GM intern geheugen.
Installatie van VMware Server 2.0.0 Build 122956 x86_64 verliep ook nu zonder problemen. Wel werd de default poort op 904 gezet en zag ik nergens dat de Web UI via 8222 en 8333 benaderd kan worden (wat op de test server wel het geval was). Na installatie werden de draaiende VM’s automatisch gestart wat hoopgevend was. Helaas startte VMWare Server niet automatisch op na een reboot van BigBrother. Dat is minder, temeer omdat dit via Yast wel stond aangegeven. Maar gelukkig wist Google mij te vertellen dat in /etc/sysconfig/boot de parameter RUN_PARALLEL op “No” gezet moet worden om VMware Server automatisch te starten.
Ik lees dat er veel kritiek op de Web UI is, maar ik vind het een mooi tool. Temeer omdat BigBrother geen beeldscherm en toetsenbord heeft en ik nu vanaf andere PC’s (MacBook Air, Windows XP enz.) de VM’s kan beheren … alleen werkt dat dus niet. Waar de installatie op de test (32bit) server vanaf ieder werkstation in mijn netwerk netjes toegang gaf tot de UI via poort 8222 en 8333 doet BigBrother dat niet. Via NX Client kan ik gelukkig wel met KDE op BigBrother werken en daar kan ik ook een FireFox browser starten en zo de UI benaderen (via poort 80 of 433), maar waarom kan ik de UI op de testserver wél vanaf andere werkstations starten maar kan dit niet op de productie server?
Een mogelijke rede kan zijn dat er al een Apache webserver op de test machine draaide en dat VMware ervan uitgaat dat deze webserver vrij benaderbaar moet zijn en dus verder geen restricties op legt. Daarom moest VMware server natuurlijk andere poorten dan de default 80 en 433 gebruiken. Maar helaas kan ik nergens vinden hoe ik WebAccess ‘vertel’ dat ik de UI ook vanaf andere machines binnen mijn domein wil benaderen…
Ok, het komt dus omdat de FireWall niet toestaat dat er verkeer over de poorten 80 en 443 heen gaat! Simpel toestaan van http en https!
Een tweede uitdaging was om het weer mogelijk te maken om automatisch backups van al-dan-niet draaiende VM’s te kunnen maken. Helaas was het enige resultaat bij het uitvoeren van vmware-vim-cmd een niet hoopgevende melding “Cannot connect to host localhost: Connection refused“. Maar ook daar gaf Google uitkomst. Bij het gebruik van vmware-vim-cmd moet worden opgegeven welke poort je wilt gebruiken (in mijn geval dus: “-O 904“). Helaas moet je erg diep graven om erachter te komen dat de “-O” optie alleen werkt als je óók “-H localhost” opgeeft. Maar goed, als je daar achter bent kun je hartstikke leuke dingen doen met dit commando. Ter leering ende vermaeck het bash script dat ik gebruik om via cron backups te maken.
#!/bin/bash
#==================================================================
# Backup Script for VMware server 2.0
#==================================================================
# Developed by Willem Aandewiel (The Netherlands)
# Released under the GPL
#
# Copyright (C) 2009 Willem Aandewiel [Willem (a) Aandewiel (d0t) nl]
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, check with
# http://www.gnu.org/copyleft/gpl.html or write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111,
# USA.
#==================================================================
#
# All VirtualMachines in subdir (vm-container) of $VMPATH directory
# All VM-files in $VMPATH/$SUBDIR
# .. VM's are referenced by the name of the SUBDIR
# .. they reside in
# .. Tree looks like:
#
# -- $VMPATH ---\
# +-- $SUBDIR - VM-One
# +-- $SUBDIR - VM-Two
# \-- $SUBDIR - VM-three
#
# All VM-backups in $BKPATH
# For eacht VM a subdir with the name $SUBDIR will be created
# .. and every backup risides in a subdir YYYY-MM-DD
# .. so there can only be one backup per date!
# .. Default there will be 5 genarations of every VM backedup
# .. this can be overrided by setting a number of backups in
# .. a file called BNUM in the $BKPATH/$SUBDIR
# .. Tree looks like:
#
# -- $BKPATH --\
# +-- $SUBDIR - VM-One ---\
# | +-- BNUM
# | +-- 2008-09-12
# | +-- 2008-09-12
# | \-- 2009-01-09
# +-- $SUBDIR - VM-Two --\
# | +-- 2008-07-02
# | \-- 2008-07-19
# \-- $SUBDIR - VM-three -\
# +-- 2008-03-13
# \-- 2009-01-13
#
#set -v
#set -x
#
#------------------------------------------------------------------
# use: VMBackup.sh <subdirvm>
#------------------------------------------------------------------
NOW=`date +"%Y-%m-%d_%H%M%S"`
OLDPWD=`pwd`
BDAT=`date +"%Y-%m-%d"` # Date string
BNUM=5 # Default number of backups to keep
VMPATH=/var/vmware # path to Virtual Machines
BKPATH=/var/vmware/Backup # path to the Backups
SUBDIR=${1} # subdir where this VM resides
COMMANDsh=`basename ${0}`
COMMAND=${COMMANDsh%.sh}
PID=/tmp/VMSuite_${SUBDIR}.pid
echo "20" > ${PID} # move value 20 to PID file
# Used in VMControl.sh
VMSERVER=localhost
VMPORT=904 # Depending on your config
VMWARECMD="/usr/bin/vmware-vim-cmd -H ${VMSERVER} -O ${VMPORT} "
#================================= functions ======================
#------------------------------------------------------------------
function VMget_Guest_ID {
#------------------------------------------------------------------
aVM=( `${VMWARECMD} vmsvc/getallvms | egrep "${1}/"` )
# echo "Array [${aVM[0]} ${aVM[1]} ${aVM[2]}]"
VM_Guest_ID=${aVM[0]}
VMMACHINE=${aVM[1]}
} # VMget_Guest_ID()
#
#------------------------------------------------------------------
function VMget_Summary {
#------------------------------------------------------------------
VIMCMD="${VMWARECMD} vmsvc/get.summary ${VM_Guest_ID}"
VM_Summary=`${VIMCMD}`
} # VMget_Summary()
#
#------------------------------------------------------------------
function VMget_Parameter {
#------------------------------------------------------------------
Parameter=${1}
# echo "Parameter: [${Parameter}]"
Items=${#VM_Summary[*]}
i=0
while [ $i -lt $Items ]
do
# echo "${i}: ${VM_Summary[$i]} "
echo "${VM_Summary[$i]} " \
| grep -i "${Parameter}" \
| tr -d ',' | tr -d '"' \
| awk '{ print $3 }'
let i++
done
} # VMget_Parameter()
#
#------------------------------------------------------------------
function VMget_State {
#------------------------------------------------------------------
${VMWARECMD} vmsvc/power.getstate ${VM_Guest_ID} | grep -v "Retrieve"
} # VMget_State()
#
#------------------------------------------------------------------
function VM_Start {
#------------------------------------------------------------------
if [ `VMget_State ${VM_Guest_ID} | grep -i 'Powered off' | wc -l` -gt 0 ]
then
echo "${COMMAND}: Starting..."
echo -n "${COMMAND}: "
${VMWARECMD} vmsvc/power.on ${VM_Guest_ID}
RUNSTAT=${?}
else
echo "${COMMAND}: Allready running "
RUNSTAT=0
fi
} # VM_Start()
#
#------------------------------------------------------------------
function VM_Wait_Till_Stopped {
#------------------------------------------------------------------
w=${1}
while [ "`VMget_State`" != "Powered off" ]
do
echo -n "${w} "
if [ ${w} -lt 1 ]
then
break
fi
sleep 2
let w--
done
} # VM_Wait_Till_Stopped()
#
#------------------------------------------------------------------
function VM_Stop {
#------------------------------------------------------------------
if [ `VMget_State | grep -i 'Powered on' | wc -l` -gt 0 ]
then
echo -n "${COMMAND}: Stopping.. "
${VMWARECMD} vmsvc/power.shutdown ${VM_Guest_ID}
VM_Wait_Till_Stopped 30
if [ `VMget_State | grep -i 'Powered off' | wc -l` -gt 0 ]
then
echo "Stopped!"
RUNSTAT=0
else
echo "Can't stop it!"
RUNSTAT=2
fi
else
echo "${COMMAND}: Not Running (stopped or suspended) "
RUNSTAT=0
fi
} # VM_Stop()
#
#------------------------------------------------------------------
function VM_Kill {
#------------------------------------------------------------------
${VMWARECMD} vmsvc/power.off ${VM_Guest_ID}
VM_Wait_Till_Stopped 4
if [ `VMget_State | grep -i 'Powered off' | wc -l` -gt 0 ]
then
echo "Stopped!"
RUNSTAT=0
else
echo "Can't stop it!"
RUNSTAT=2
fi
} # VM_Kill()
#
#------------------------------------------------------------------
function Status_VM {
#------------------------------------------------------------------
echo "${COMMAND}: ${VM_State}"
RUNSTAT=0
} # Status_VM()
#
#
#------------------------------------------------------------------
#-------------------- M A I N P R O G R A M ---------------------
#------------------------------------------------------------------
if [ ${#} != 1 ]
then
echo "Use: ${COMMAND} <vm-container-name>"
rm -f ${PID}
exit 1
fi
#
#--- Retrieve the ID of the Virtual machine
VMget_Guest_ID ${1}
echo "${COMMAND}: ${1} has ID [${VM_Guest_ID}]"
#
#--- Get Summary info about Virtual machine
VMget_Summary
#
#--- Are the VMware tools installed on the VM?
VM_toolsStatus=`VMget_Parameter "toolsStatus"`
#echo "${COMMAND}: [${VM_toolsStatus}]"
#
#--- Does the VM exists in the given path?
if [ ! -d "${VMPATH}/${SUBDIR}" ]
then
echo "${COMMAND} Error: no such directory [${SUBDIR}]"
rm -f ${PID}
exit 1
fi
#
#--- What is the state the VM is in?
VM_State=`VMget_State`
#--- Save the state for later use
OLDSTATE=${VM_State}
echo "${COMMAND}: ${1} is ${VM_State}"
#
#
echo "${COMMAND}: Backup ${VMACHINE} in ${VMPATH}/${SUBDIR} to ${BKPATH}/${SUBDIR}/${BDAT}"
Status_VM;
#
#--- Does the Backup Directory exist? If not Create!
if [ ! -d ${BKPATH} ]
then
mkdir ${BKPATH}
fi
#
#--- Does the Subdir for this VM exist? If not Create!
if [ ! -d "${BKPATH}/${SUBDIR}" ]
then
mkdir "${BKPATH}/${SUBDIR}"
fi
#
#--- Does the Sub-dir for this date exist? If not Create!
if [ ! -d "${BKPATH}/${SUBDIR}/${BDAT}" ]
then
mkdir "${BKPATH}/${SUBDIR}/${BDAT}"
fi
#
#--- Are the VMware Tools installed on the VM?
if [ "${VM_toolsStatus}" = "toolsNotInstalled" ]
then
echo "${COMMAND}: Tools are not installed "
VM_Kill
else
echo "${COMMAND}: Tools are installed "
VM_Stop
fi
#
#--- Sanety Check
if [ ${RUNSTAT} -ne 0 ]
then
echo "${COMMAND}: ${VMACHINE} still running .. now trying to kill!"
VM_Kill
if [ ${RUNSTAT} -ne 0 ]
then
echo "${COMMAND}: ${VMACHINE} can not be stopped (Status ${RUNSTAT}) "
rm -f ${PID}
exit
fi
echo "${COMMAND}: ${VMACHINE} Killed .. "
fi
#
#--- And now where we came for ..
cd ${VMPATH}/${SUBDIR}
echo "${COMMAND}: Start Copying...."
/bin/cp -pv * ${BKPATH}/${SUBDIR}/${BDAT}/
echo "${COMMAND}: Copyed!"
#
#--- If OldState was "Powered on" then start VM
if [ `echo "${OLDSTATE}" | grep -i 'Powered on' | wc -l` -gt 0 ]
then
VM_Start;
if [ ${RUNSTAT} -ne 0 ]
then
echo "${COMMAND}: ${VMACHINE} can not be started (Status ${RUNSTAT}) "
fi
fi
#
#--- Now check for BNUM file and read number of backups to keep
cd ${BKPATH}/${SUBDIR}
if [ -f BNUM ]
then
BNUM=`cat BNUM`
echo "${COMMAND}: read file BNUM with [${BNUM}]"
else
echo "${COMMAND}: create file BNUM with [${BNUM}]"
echo ${BNUM} > BNUM
fi
#
#--- List all Backup Dirs with a name starting with '20'
BDIRS=`ls -td 20*`
#
#--- Loop thru the names
I=0
for BDIR in ${BDIRS}
do
let I=I+1
if [ ${I} -gt ${BNUM} ]
then
# #--- remove if more than BNUM
echo "[${I}] rm -rf ${BDIR}"
rm -rf ${BDIR}
else
echo "[${I}] ${BDIR}"
fi
done
#
cd ${pwd}
#
rm -f ${PID}
echo "${COMMAND}: Done"
#