lmn-client/roles/lmn_vm/files/vm-run
2024-01-20 14:38:02 +01:00

174 lines
6 KiB
Bash
Executable file

#!/usr/bin/bash
# create and run clone
set -eu
show_help() {
cat << EOF >&2
Usage: $(basename "$0") [-n] vmname"
Create a new clone, start the vm (if not yet running) and run virt-viewer.
Squid-Proxy will be started too.
-n new clone will be created, even if exists
-p new clone will be created persistent, so available after reboot too
-s qemu:///system instead of default qemu:///session
EOF
}
exit_script() {
echo "run-vm.sh ${VM_NAME} terminated by trap!" >> "/tmp/${UID}/exit-run-vm.log"
virsh --connect="${QEMU}" destroy "${VM_NAME}-clone"
trap - SIGHUP SIGINT SIGTERM # clear the trap
kill -- -$$ # Sends SIGTERM to child/sub processes
}
check_images() {
# sync vm-torrents and machine definition file
sudo -u lmnsynci /usr/local/bin/vm-sync get_file "${VM_NAME}.xml" "${VM_NAME}.qcow2.torrent"
[[ -f "${VM_NAME}" ]] && sudo -u lmnsynci /usr/local/bin/vm-sync delete_outdated_image "${VM_NAME}.qcow2"
BACKINGARRAY=()
imgfile="${VM_SYSDIR}/${VM_NAME}.qcow2" && [[ -f "${VM_DIR}/${VM_NAME}.qcow2" ]] && imgfile="${VM_DIR}/${VM_NAME}.qcow2"
BACKINGARRAY+=("${imgfile}")
echo "Imgfile=$imgfile"
if [[ ! -f "${imgfile}" ]] || ! qemu-img info -U "${imgfile}" | grep "file format: qcow2"; then
if [[ ! -f "${VM_SYSDIR}/${VM_NAME}.qcow2.torrent" ]]; then
echo "no base VM disk '${VM_NAME}.qcow2' found and/or ${VM_NAME} not found on server" >&2
exit 1
fi
# sync vm-disk image by torrent
echo "Try to sync VM ${VM_NAME} by torrent"
sudo -u lmnsynci /usr/local/bin/vm-sync get_image "${VM_NAME}"
fi
backingfile=$(qemu-img info -U "${imgfile}" | grep "^backing file:" | cut -d ' ' -f 3)
while [[ -n "${backingfile}" ]]; do
echo "Backingfile required: ${backingfile}"
imgfile="${VM_SYSDIR}/${backingfile}" && [[ -f "${VM_DIR}/${backingfile}" ]] && imgfile="${VM_DIR}/${backingfile}"
BACKINGARRAY+=("${imgfile}")
if [[ ! -f "${imgfile}" ]] || ! qemu-img info -U "${imgfile}" | grep "file format: qcow2"; then
# sync vm-disk image by torrent
echo "Try to sync backingfile ${backingfile} by torrent"
sudo -u lmnsynci /usr/local/bin/vm-sync get_file "${backingfile}.torrent"
[[ -f "${backingfile}" ]] && sudo -u lmnsynci /usr/local/bin/vm-sync delete_outdated_image "${backingfile}"
sudo -u lmnsynci /usr/local/bin/vm-sync get_image "${backingfile%.qcow2}"
fi
backingfile=$(qemu-img info -U "${imgfile}" | grep "^backing file:" | cut -d ' ' -f 3)
done
echo "VM-Image and required backingfiles available"
echo "Now, let's check the images."
# Check VM-Images in reverse order
for ((i=${#BACKINGARRAY[@]}-1; i>=0; i--))
do
echo "Checking ${BACKINGARRAY[$i]}"
if ! qemu-img check -U "${BACKINGARRAY[$i]}" 2>/dev/null; then
echo "check failed!"
echo "sync ${BACKINGARRAY[$i]} again"
sudo -u lmnsynci /usr/local/bin/vm-sync get_image "$(basename "${BACKINGARRAY[$i]}" .qcow2)"
fi
done
echo "VM-Image and required backingfiles available and checked"
}
create_clone() {
local VM_NAME="$1"
local VM_XML="${VM_DIR}/${VM_NAME}-clone.xml"
if ! [[ -f "${VM_SYSDIR}/${VM_NAME}.xml" && -f "${VM_SYSDIR}/${VM_NAME}.qcow2" ]] && ! [[ -f "${VM_DIR}/${VM_NAME}.xml" && -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then
echo "xml or qcow2 File does not exists." >&2
exit 1
fi
# Create User-VM-Dir and link system VM-Images
[[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}"
if [[ "${PERSISTENT}" -eq 1 ]]; then
sudo /usr/local/bin/vm-link-images -p
else
sudo /usr/local/bin/vm-link-images
fi
# Create backing file
cd "${VM_DIR}"
qemu-img create -f qcow2 -F qcow2 -b "${VM_NAME}.qcow2" "${VM_NAME}-clone.qcow2"
# Create machine-definition-file
cp "${VM_DIR}/${VM_NAME}.xml" "${VM_XML}"
# set VM_DIR:
sed -i "s:VMIMAGEDIR:${VM_DIR}:" "${VM_XML}"
# and actually rename the vm (this also updates part of the storage path):
sed -i "s/${VM_NAME}/${VM_NAME}-clone/" "${VM_XML}"
# set virtiofs-Socket
sed -i "s:VIRTIOFSSOCKET:/run/user/${UID}/virtiofs-${VM_NAME}.sock:" "${VM_XML}"
# find macvtap interface MAC address:
MAC="$(ip link | grep -A1 "vm-macvtap" |
sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")"
sed -i -E -e "s/MACMACVTAP/$MAC/" "${VM_XML}"
}
QEMU='qemu:///session'
NEWCLONE=0
PERSISTENT=0
source /etc/lmn/vm.conf
while getopts ':pns' OPTION; do
case "$OPTION" in
p)
PERSISTENT=1
VM_DIR="${VM_DIR_PERSISTENT}"
;;
n)
NEWCLONE=1
;;
s)
QEMU='qemu:///system'
;;
?)
show_help
exit 1
;;
esac
done
shift "$((OPTIND -1))"
# if less than one arguments supplied, display usage
if [[ $# -ne 1 ]] ; then
show_help
exit 1
fi
VM_NAME=$1
# check, if we have to start squid
if ! killall -s 0 squid; then
echo "starting squid."
/usr/sbin/squid -f /etc/squid/squid-usermode.conf
fi
# because virsh has problems with long pathnames, using diffent configdir
export XDG_CONFIG_HOME="/tmp/${UID}/.config"
if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
echo "VM not yet running."
sudo /usr/local/bin/desktop-sync
check_images
if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then
create_clone "${VM_NAME}"
fi
# delete the old vm
virsh --connect=qemu:///session undefine "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist"
# finally, create the new vm
virsh --connect=qemu:///session define "${VM_DIR}/${VM_NAME}-clone.xml"
#trap exit_script SIGHUP SIGINT SIGTERM
[[ "${QEMU}" = 'qemu:///session' ]] && sudo /usr/local/bin/vm-virtiofsd "${VM_NAME}"
virsh --connect="${QEMU}" start "${VM_NAME}-clone"
fi
echo "starting viewer"
trap exit_script SIGHUP SIGINT SIGTERM
virt-viewer --connect="${QEMU}" --full-screen "${VM_NAME}-clone"