# run-virt.include
# -----------------------------------------------------------------------------
# Copyright (c) 2009..2010 - RZ Uni Freiburg
# Copyright (c) 2009..2010 - OpenSLX GmbH
#
# This program/file is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your feedback to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org
# -----------------------------------------------------------------------------
# run-virt.include
# - Include script for running the VirtualBox on an OpenSLX client via the
# run-virt.sh or run-vmgrid.sh
################################################################################
################################################################################
### Include general configuration
################################################################################
if [ -f ${OPENSLX_DEFAULT_CONFDIR}/plugins/${self}/${self}.conf ]; then
. ${OPENSLX_DEFAULT_CONFDIR}/plugins/${self}/${self}.conf
else
writelog "Problems reading config file of ${self} plugin"
exit 1
fi
################################################################################
### Declaration of default variables
################################################################################
PLUGINCONFVIRTUALBOX="${PLUGINCONFROOT}/${self}"
PLUGINDIRVIRTUALBOX="${OPENSLX_DEFAULT_DIR}/plugin-repo/${self}"
# create TMPDIR for all users
TMPDIR=/tmp/${self}
mkdir -m 1777 ${TMPDIR} 2>/dev/null
# dir for configs
confdir="/tmp/${self}/${USER}/${VM_ID}"
# use alternate configuration directory instead of $HOME/.VirtualBox
export VBOX_USER_HOME=${confdir}
# define dirs and files which can be removed after exit, be carefull!
RMDIRS="${snapshotdir} ${confdir} /tmp/.vbox-${USER}-ipc"
rm -rf ${RMDIRS} 2>/dev/null
machfolder="${confdir}/Machines"
# use vm_shortname for VM name since vm_name can be very long
machconfig="${machfolder}/${vm_shortname}/${vm_shortname}.xml"
diskfolder="${confdir}/HardDisks"
snapshotdir=${machfolder}/${vm_shortname}/Snapshots
mkdir -p ${diskfolder} ${snapshotdir} 2>/dev/null
# configure our own rwimg, empty image which we support
if [ "${imgmode}" = "rwimg" ]; then
# what is our rwimg called?
imgname="${vm_shortname}.vdi"
vmpath=${imgpath}/${imgname}
if ! [ -e "${vmpath}" ]; then
cat ${PLUGINDIRVIRTUALBOX}/rwimg.vdi.gz | gunzip > "${vmpath}"
fi
fi
# link to image
diskfile="${diskfolder}/${imgname}"
[ ${diskless} -eq 0 ] && ln -sf ${vmpath} ${diskfile}
# check the file type
if echo ${imgname} | grep -iE "vdi|vmdk|vhd" && [ ${diskless} -eq 0 ]; then
imgfmt=$(echo ${imgname##*.} | tr [a-z] [A-Z])
elif [ ${diskless} -eq 0 ]; then
writelog "${imgname} is not a valid image format (vdi|vmdk|vhd), exiting!"
exit 1
fi
# TODO: maybe rewrite, to reduce checks, merge it with network option,
# so we can have a "compatibility to vmware config" section
case "${vmostype}" in
winxp*)
vmostype="WindowsXP"
;;
winvista*)
vmostype="WindowsVista"
;;
Windows7*)
vmostype="Windows7"
;;
linux*)
vmostype="Linux26"
;;
esac
writelog "Directories:"
writelog "\tConfig dir:\t\t$confdir"
writelog "\tMachines dir:\t\t$machfolder"
writelog "\tMachine config:\t\t$machconfig"
[ ${diskless} -eq 0 ] && writelog "\tHardDisks dir:\t\t$diskfolder"
################################################################################
### Hardware checks
################################################################################
# remove ':' from MAC addr for vbox
macaddr=$(echo ${macaddr} | sed 's/://g')
# machine UUID, MAC addr part of it
machineuuid="00000000-0000-0000-0000-${macaddr}"
# cosmetical, since UUID in lower case
machineuuid=$(echo ${machineuuid} | tr [A-Z] [a-z])
# get UUID of VBox image, if not diskless
[ ${diskless} -eq 0 ] && diskuuid=$(VBoxManage -q showvdiinfo ${diskfile} \
| grep UUID | awk '{print $2}')
# make disk immutable
imgtype="Immutable"
# snapshot UUID is static
snapshotuuid="88bc8b6d-f248-468a-95fe-318084904f8b"
# imageuuid in machine.include, dafault snapshotuuid
imageuuid=${snapshotuuid}
# check if rw image
# remove disk and add rwimg if set
if echo "${imgmode}" | grep -q rw; then
# lock existing?
if [ -e "${vmpath}.lock" ]; then
writelog "This rw image is already in use: ${vmpath}, exiting!"
writelog "Remove lock if you are shure that this is not the case"
exit 1
# image rw?
elif ! [ -w ${vmpath} ]; then
writelog "You defined mode rw, but image ${vmpath} is not rw! \c"
writelog "Please correct, exiting!"
exit 1
fi
# add lock
touch "${vmpath}.lock"
# remove lock after VM stopped
RMDIRS="${RMDIRS} ${vmpath}.lock"
imgtype="Normal"
# replace image uuid in machine config
imageuuid=${diskuuid}
elif [ ${diskless} -eq 0 ]; then
# use temp disk as snapshot
cat ${PLUGINDIRVIRTUALBOX}/empty-diff.vdi.gz \
| gunzip > "${snapshotdir}/{${snapshotuuid}}.vdi"
fi
# TODO: MEM muss noch angepasst werden. Maschine crasht wenn nehr als 50% MEM
# memory part equal to vmware plugin
# percentage of memory to use for virtualbox in standard case
if [ -n "${forcemem}" ]; then
mem="${forcemem}"
else
permem=30
if [ "${totalmem}" -ge "1600" ]; then
permem=40
fi
# check if /tmp is on harddisk
if grep -qe "/dev/.* /tmp " /proc/mounts ; then
permem=60
id44="1"
# Hack, if more than 2,5G RAM use 40% of Ram and write vmem into Ram as well
# (40% vmware | 40% confdir(vmem...) | 20% host
# VMplayer 2+ issue
# TODO: makes this sense for vbox?
#if [ "${totalmem}" -ge "2500" ]; then
#permem=40
#rmdir ${snapshotdir}
#snapshotdirold=${snapshotdir}
#snapshotdir=/dev/shm/${self}/${USER}/${VM_ID}
#mkdir -p ${snapshotdir}
#ln -sf ${snapshotdir} ${snapshotdirold}
#fi
fi
mem=$(expr ${totalmem} / 100 \* ${permem})
if [ "${id44}" = "1" ]; then
memhost=$(expr ${totalmem} - ${mem})
else
memhost=$(expr ${totalmem} - ${mem} - ${mem})
fi
#permem=40
#mem=$(expr ${totalmem} * ${permem})
if [ "${mem}" -lt "256" ] || [ "${memhost}" -lt "256" ]; then
writelog "Memory out of range: ${mem} MB (guest) / ${memhost} MB (host)!"
writelog "Min. 256 MB for host and guest!"
exit 1
fi
fi
# translate network cards
case "${network_card}" in
e1000)
vb_network_card="82540EM"
;;
virtio)
vb_network_card="virtio"
;;
*)
network_card="pcnet"
vb_network_card="Am79C973"
esac
# translate network kinds (nat, bridged, host-only)
case "${network_kind}" in
bridge*)
network_kind='BridgedInterface name="br0"'
;;
hostonly|host-only)
network_kind='HostOnlyInterface name="vboxnet0"'
;;
*)
network_kind="NAT"
esac
# translate boot, use if set else set to HardDisk
# usually support for a,c,d,n, stands for Floppy, HD, CD-ROM, Network
# support nfs and tftp as well
case ${boot} in
n*|tftp)
boot="Network"
if [ "${network_kind}" = "NAT" ] && [ -n "${virtualbox_tftpdir}" ]; then
# remove spaces from VM name to avoid Problems /w TFTP in NAT
vm_name=$(echo ${vm_name} | sed -e "s, ,-,g")
# link TFTP dir for NAT TFTP boots
mkdir -p ${confdir}/TFTP
cp ${virtualbox_tftpdir}/pxelinux.0 ${confdir}/TFTP/${vm_name}.pxe
for i in $(ls ${virtualbox_tftpdir}); do
ln -sf ${virtualbox_tftpdir}/${i} ${confdir}/TFTP/${i}
done
fi
;;
# later maybe c|disk|hd*|sd*) for HD and d|cd*) for CD-ROM
*)
boot="HardDisk"
;;
esac
# external GUI
vrdpport="590${VM_ID}"
# TODO: nur bei vmchooser
# TODO: most of the following does not make much sense yet ...
# virtual fd/cd/dvd and drive devices, floppy b: for configuration
# if $floppy_0 from run-virt.include set then fdtest="TRUE"
fdtest=
fdtest=${floppy_0:+"TRUE"}
# if $fdtest not set floppy0="FALSE", else "TRUE"
floppy0=${fdtest:-"FALSE"}
floppy1="TRUE"
floppy1name="/var/lib/virt/vmchooser/loopimg/fd.img"
# if $cdrom_0 from run-virt.include set then cdtest="TRUE"
cdtest=
cdtest=${cdrom_0:+"TRUE"}
# if $cdtest not set cdrom0="FALSE", else "TRUE"
cdrom0=${cdtest:-"FALSE"}
# if $cdrom_1 from run-virt.include set then cdtest="TRUE"
cdtest=
cdtest=${cdrom_1:+"TRUE"}
# if $cdtest not set cdrom1="FALSE", else "TRUE"
cdrom1=${cdtest:-"FALSE"}
# ide is expected default, test for the virtual disk image type should
# be done while creating the runscripts ...
ide="TRUE"
hddrv="ide"
[ ${diskless} -eq 0 ] && writelog "\tSnapshots dir:\t\t$snapshotdir"
writelog "Diskimage:"
[ ${diskless} -eq 0 ] && writelog "\tDisk file:\t\t$diskfile"
[ ${diskless} -eq 0 ] && writelog "\tDisk format:\t\t$imgfmt"
[ ${diskless} -eq 0 ] && writelog "\tDisk type:\t\t$imgtype"
writelog "\tVMostype:\t\t$vmostype"
writelog "\tMachine UUID:\t\t$machineuuid"
[ ${diskless} -eq 0 ] && writelog "\tDisk UUID:\t\t$diskuuid"
writelog "Virtual Hardware:"
writelog "\tGuest RAM:\t\t${mem} MB"
# echo nur wenn memhost gesetzt
[ -n "${memhost}" ] && writelog "\tHost RAM:\t\t${memhost} MB"
writelog "\tMAC address:\t\t$macaddr"
writelog "\tNetwork card:\t\t${vb_network_card}"
writelog "\tNetwork kind:\t\t${network_kind}"
writelog "\tBooting from:\t\t${boot}\c"
[ ${diskless} -eq 0 ] && writelog ""
[ ${diskless} -eq 1 ] && writelog " 'diskless'"
# TODO: server start activate via xml, etc...
#writelog "\tGuest VRDP port:\t${vrdpport}"
#writelog "\tCD-ROM1:\t${cdrom0}"
#writelog "\tCD-ROM2:\t${cdrom1}"
#writelog "\tFloppy_A:\t${floppy0}"
#writelog "\tFloppy_B:\t${floppy1}"
# defined in run-virt.sh and run-vmgrid.sh
writelog "\tShared Folders '${sharename}':\t${sharepath}"
################################################################################
### Pepare and configure virtual machine and disk image
################################################################################
# create Virtualbox.xml
. ${PLUGINCONFVIRTUALBOX}/virtualbox.include
# remove snapshot disk when using rw images
if [ "${imgtype}" != "Immutable" ]; then
sed -i "/${snapshotuuid}/d" "${confdir}/VirtualBox.xml"
fi
# TODO: add rawdisk if requested
#"raw.vmdk" format="VMDK" type="Writethrough"/>
# create machine.xml
. ${PLUGINCONFVIRTUALBOX}/machine.include
# if diskless remove all disks
if [ ${diskless} -eq 1 ]; then
sed -i "/<HardDisk/d;/<\/HardDisk/d" "${confdir}/VirtualBox.xml"
sed -i "/${imageuuid}/d" ${machconfig}
sed -i '/AttachedDevice type="HardDisk"/d' ${machconfig}
sed -i "/<!-- PLEASE DO NOT REMOVE THIS COMMENT!!! -->/d" ${machconfig}
fi
# add ssh port if linux and NAT
if [ "${vmostype}" = "Linux26" ] && [ "${network_kind}" = "NAT" ]; then
vmsshport="220${VM_ID}"
extradataitem='<ExtraDataItem name="VBoxInternal/Devices' \
extradataitem="${extradataitem}/${network_card}/0/LUN#0/Config/ssh/"
extradataguestport='GuestPort" value="22"/>'
extradatahostport="HostPort\" value=\"${vmsshport}\"/>"
extradataprotocol='Protocol" value="TCP"/>'
sed -i "s,</ExtraData>, ${extradataitem}${extradataguestport}\n\
${extradataitem}${extradatahostport}\n\
${extradataitem}${extradataprotocol}\n\
</ExtraData>," "${machconfig}"
writelog "\tGuest SSH port:\t\t${vmsshport}"
fi
################################################################################
### finally set env for run-virt.sh
################################################################################
# wait for a certain command to settle
# get the PID of the right process
# kill PID, seems to work
VBMANPID=$(pstree -p | grep VBoxXPCOMIPCD | grep -ivE "VirtualBox|VBoxHeadless"\
| sed -e "s/.*VBoxXPCOMIPCD(\(.*\)).*/\1/")
for i in $(echo ${VBMANPID}); do
kill -9 ${VBMANPID} >/dev/null 2>&1
done
# set the variables appropriately (several interfaces with different names)
VIRTCMD=$(which VirtualBox 2>/dev/null)
VIRTCMDOPTS="--startvm ${machineuuid} --start-running"
# set headless mode
VIRTCMDHL=$(which VBoxHeadless 2>/dev/null)
VIRTCMDOPTSHL="-s ${machineuuid}"