#!/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. ### remove, old ### User Home will be mounted on /media/USERNAME/home -n new clone will be created, even if exists -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/sync-vm.sh -t BACKINGARRAY=() imgfile="/lmn/vm/${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 "/lmn/vm/${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/sync-vm.sh "${VM_NAME}" fi backingfile=$(qemu-img info -U "${imgfile}" | grep "^backing file:" | cut -d ' ' -f 3) while [[ ! -z "${backingfile}" ]]; do echo "Backingfile required: ${backingfile}" imgfile="/lmn/vm/${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/sync-vm.sh "${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/sync-vm.sh $(basename "${BACKINGARRAY[$i]}" .qcow2) fi done echo "VM-Image and required backingfiles available and checked" } create-clone() { local VM_NAME="$1" local VM_DIR="/tmp/${UID}/vm" local VM_XML="${VM_DIR}/${VM_NAME}-clone.xml" local VM_SYSDIR="/lmn/vm" 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}" sudo /usr/local/bin/link-images.sh # 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 while getopts ':ns' OPTION; do case "$OPTION" in 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 VM_DIR="/tmp/${UID}/vm" # 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." 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/start-virtiofsd.sh "${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"