mirror of
https://github.com/oSoWoSo/DistroHopper.git
synced 2024-08-14 22:46:53 +00:00
70b5d8148c
Actually, `gl=on` and `virgil=on` are both required to enable full acceleration. `virgil=on` is not currently working with GTK, so set to off if GTK is used.
355 lines
No EOL
9.6 KiB
Bash
Executable file
355 lines
No EOL
9.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
function disk_delete() {
|
|
if [ -e "${disk_img}" ]; then
|
|
rm "${disk_img}"
|
|
echo "SUCCESS! Deleted ${disk_img}"
|
|
else
|
|
echo "NOTE! ${disk_img} not found. Doing nothing."
|
|
fi
|
|
}
|
|
|
|
function snapshot_apply() {
|
|
local snapshot_tag="${1}"
|
|
if [ -z "${snapshot_tag}" ]; then
|
|
echo "ERROR! No snapshot tag provided."
|
|
exit
|
|
fi
|
|
|
|
if [ -e "${disk_img}" ]; then
|
|
${QEMU_IMG} snapshot -q -a "${snapshot_tag}" "${disk_img}"
|
|
if [ $? -eq 0 ]; then
|
|
echo "SUCCESS! Applied snapshot ${snapshot_tag} to ${disk_img}"
|
|
else
|
|
echo "ERROR! Failed to apply snapshot ${snapshot_id} to ${disk_img}"
|
|
fi
|
|
else
|
|
echo "NOTE! ${disk_img} not found. Doing nothing."
|
|
fi
|
|
}
|
|
|
|
function snapshot_create() {
|
|
local snapshot_tag="${1}"
|
|
if [ -z "${snapshot_tag}" ]; then
|
|
echo "ERROR! No snapshot tag provided."
|
|
exit
|
|
fi
|
|
|
|
if [ -e "${disk_img}" ]; then
|
|
${QEMU_IMG} snapshot -q -c "${snapshot_tag}" "${disk_img}"
|
|
if [ $? -eq 0 ]; then
|
|
echo "SUCCESS! Created snapshot ${snapshot_tag} of ${disk_img}"
|
|
else
|
|
echo "ERROR! Failed to create snapshot ${snapshot_tag} of ${disk_img}"
|
|
fi
|
|
else
|
|
echo "NOTE! ${disk_img} not found. Doing nothing."
|
|
fi
|
|
}
|
|
|
|
function snapshot_delete() {
|
|
local snapshot_tag="${1}"
|
|
if [ -z "${snapshot_tag}" ]; then
|
|
echo "ERROR! No snapshot tag provided."
|
|
exit
|
|
fi
|
|
|
|
if [ -e "${disk_img}" ]; then
|
|
${QEMU_IMG} snapshot -q -d "${snapshot_tag}" "${disk_img}"
|
|
if [ $? -eq 0 ]; then
|
|
echo "SUCCESS! Deleted snapshot ${snapshot_tag} of ${disk_img}"
|
|
else
|
|
echo "ERROR! Failed to delete snapshot ${snapshot_tag} of ${disk_img}"
|
|
fi
|
|
else
|
|
echo "NOTE! ${disk_img} not found. Doing nothing."
|
|
fi
|
|
}
|
|
|
|
function snapshot_info() {
|
|
if [ -e "${disk_img}" ]; then
|
|
${QEMU_IMG} info "${disk_img}"
|
|
fi
|
|
}
|
|
|
|
function get_port() {
|
|
local PORT_START=22220
|
|
local PORT_RANGE=9
|
|
while true; do
|
|
local CANDIDATE=$[${PORT_START} + (${RANDOM} % ${PORT_RANGE})]
|
|
(echo "" >/dev/tcp/127.0.0.1/${CANDIDATE}) >/dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
echo "${CANDIDATE}"
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
function vm_boot() {
|
|
local VMNAME=$(basename ${VM} .conf)
|
|
local VMDIR=$(dirname ${disk_img})
|
|
local BIOS=""
|
|
local GL="on"
|
|
local VIRGL="on"
|
|
local UI="sdl"
|
|
local QEMU_VER=$(${QEMU} -version | head -n1 | cut -d' ' -f4 | cut -d'(' -f1)
|
|
echo "Starting ${VM}"
|
|
echo " - QEMU: ${QEMU} v${QEMU_VER}"
|
|
|
|
readonly disk_min_size=$((197632 * 8))
|
|
if [ -z "${disk}" ]; then
|
|
disk="64G"
|
|
fi
|
|
|
|
if [ ${ENABLE_EFI} -eq 1 ]; then
|
|
if [ -e /snap/qemu-virgil/current/usr/share/qemu/edk2-x86_64-code.fd ] ; then
|
|
if [ ! -e ${VMDIR}/${VMNAME}-vars.fd ]; then
|
|
cp /snap/qemu-virgil/current/usr/share/qemu/edk2-i386-vars.fd ${VMDIR}/${VMNAME}-vars.fd
|
|
fi
|
|
BIOS="-drive if=pflash,format=raw,readonly,file=/snap/qemu-virgil/current/usr/share/qemu/edk2-x86_64-code.fd -drive if=pflash,format=raw,file=${VMDIR}/${VMNAME}-vars.fd"
|
|
else
|
|
echo " - EFI: Booting requested but no EFI firmware found."
|
|
echo " Booting from Legacy BIOS."
|
|
fi
|
|
echo " - BIOS: EFI"
|
|
else
|
|
echo " - BIOS: Legacy"
|
|
fi
|
|
|
|
echo " - Disk: ${disk_img} (${disk})"
|
|
if [ ! -f "${disk_img}" ]; then
|
|
# If there is no disk image, create a new image.
|
|
${QEMU_IMG} create -q -f qcow2 "${disk_img}" "${disk}"
|
|
echo " Just created, booting from ${iso}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR! Failed to create ${disk_img} of ${disk}. Stopping here."
|
|
exit 1
|
|
fi
|
|
elif [ -e ${disk_img} ]; then
|
|
# Check there isn't already a process attached to the disk image.
|
|
QEMU_LOCK_TEST=$(${QEMU_IMG} info ${disk_img} 2>/dev/null)
|
|
if [ $? -ne 0 ]; then
|
|
echo " Failed to get "write" lock. Is another process using the disk?"
|
|
exit 1
|
|
else
|
|
disk_curr_size=$(stat -c%s "${disk_img}")
|
|
if [ ${disk_curr_size} -le ${disk_min_size} ]; then
|
|
echo " Looks unused, booting from ${iso}"
|
|
else
|
|
# If there is a disk image, that appears to have an install
|
|
# then do not boot from the iso
|
|
iso=""
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Has the status quo been requested?
|
|
if [ "${STATUSQUO}" == "-snapshot" ] && [ -z "${iso}" ]; then
|
|
echo " Existing disk state will be preserved, no writes will be committed."
|
|
fi
|
|
|
|
local cores="1"
|
|
local allcores=$(nproc --all)
|
|
if [ ${allcores} -ge 8 ]; then
|
|
cores="4"
|
|
elif [ ${allcores} -ge 4 ]; then
|
|
cores="2"
|
|
fi
|
|
echo " - CPU: ${cores} Core(s)"
|
|
|
|
local ram="2G"
|
|
local allram=$(free --mega -h | grep Mem | cut -d':' -f2 | cut -d'G' -f1 | sed 's/ //g')
|
|
if [ ${allram} -ge 64 ]; then
|
|
ram="4G"
|
|
elif [ ${allram} -ge 16 ]; then
|
|
ram="3G"
|
|
fi
|
|
echo " - RAM: ${ram}"
|
|
|
|
local xres=1152
|
|
local yres=648
|
|
if [ "${XDG_SESSION_TYPE}" == "x11" ]; then
|
|
local LOWEST_WIDTH=$(xrandr --listmonitors | grep -v Monitors | cut -d' ' -f4 | cut -d'/' -f1 | sort | head -n1)
|
|
if [ ${LOWEST_WIDTH} -ge 3840 ]; then
|
|
xres=3200
|
|
yres=1800
|
|
elif [ ${LOWEST_WIDTH} -ge 2560 ]; then
|
|
xres=2048
|
|
yres=1152
|
|
elif [ ${LOWEST_WIDTH} -ge 1920 ]; then
|
|
xres=1664
|
|
yres=936
|
|
elif [ ${LOWEST_WIDTH} -ge 1280 ]; then
|
|
xres=1152
|
|
yres=648
|
|
fi
|
|
fi
|
|
|
|
# GL is not working with GTK currently
|
|
if [ "${UI}" == "gtk" ]; then
|
|
GL="off"
|
|
else
|
|
echo " - Display: ${xres}x${yres}"
|
|
fi
|
|
echo " - GL: ${GL}"
|
|
echo " - Virgil3D: ${VIRGL}"
|
|
echo " - Output: ${UI^^}"
|
|
|
|
|
|
# Set the hostname of the VM
|
|
local NET="user,hostname=${VMNAME}"
|
|
|
|
# If smbd is available, export $HOME to the guest via samba
|
|
if [ -e /snap/qemu-virgil/current/usr/sbin/smbd ]; then
|
|
NET="${NET},smb=${HOME}"
|
|
fi
|
|
|
|
if [[ ${NET} == *"smb"* ]]; then
|
|
echo " - smbd: ${HOME} will be exported to the guest via smb://10.0.2.4/qemu"
|
|
else
|
|
echo " - smbd: ${HOME} will not be exported to the guest. 'smbd' not found."
|
|
fi
|
|
|
|
# Find a free port to expose ssh to the guest
|
|
local PORT=$(get_port)
|
|
if [ -n "${PORT}" ]; then
|
|
NET="${NET},hostfwd=tcp::${PORT}-:22"
|
|
echo " - ssh: ${PORT}/tcp is connected. Login via 'ssh user@localhost -p ${PORT}'"
|
|
else
|
|
echo " - ssh: All ports for exposing ssh have been exhausted."
|
|
fi
|
|
|
|
# Boot the iso image
|
|
${QEMU} -name ${VMNAME},process=${VMNAME} \
|
|
${BIOS} \
|
|
-cdrom "${iso}" \
|
|
-drive id=disk,file=${disk_img},format=qcow2,if=virtio,aio=native,cache.direct=on \
|
|
-enable-kvm \
|
|
-machine q35,accel=kvm \
|
|
-cpu host,kvm=on \
|
|
-m ${ram} \
|
|
-smp ${cores} \
|
|
-netdev ${NET},id=nic \
|
|
-device virtio-net,netdev=nic \
|
|
-rtc base=localtime,clock=host \
|
|
-serial mon:stdio \
|
|
-audiodev pa,id=pa,server=unix:$XDG_RUNTIME_DIR/pulse/native,out.stream-name=${LAUNCHER}-${VMNAME},in.stream-name=${LAUNCHER}-${VMNAME} \
|
|
-device intel-hda -device hda-duplex,audiodev=pa \
|
|
-device qemu-xhci,id=xhci,p2=8,p3=8 -device usb-kbd -device usb-tablet \
|
|
-object rng-random,id=rng0,filename=/dev/urandom \
|
|
-device virtio-rng-pci,rng=rng0 \
|
|
-device virtio-vga,virgl=${VIRGL},xres=${xres},yres=${yres} \
|
|
-display ${UI},gl=${GL} ${STATUSQUO} \
|
|
"$@"
|
|
}
|
|
|
|
function usage() {
|
|
echo
|
|
echo "Usage"
|
|
echo " ${LAUNCHER} --vm ubuntu.conf"
|
|
echo
|
|
echo "You can also pass optional parameters"
|
|
echo " --delete : Delete the disk image."
|
|
echo " --efi : Enable EFI BIOS."
|
|
echo " --snapshot apply <tag> : Apply/restore a snapshot."
|
|
echo " --snapshot create <tag> : Create a snapshot."
|
|
echo " --snapshot delete <tag> : Delete a snapshot."
|
|
echo " --snapshot info : Show disk/snapshot info."
|
|
echo " --status-quo : Do not commit any changes to disk/snapshot."
|
|
exit 1
|
|
}
|
|
|
|
DELETE=0
|
|
ENABLE_EFI=0
|
|
readonly QEMU="/snap/bin/qemu-virgil"
|
|
readonly QEMU_IMG="/snap/bin/qemu-virgil.qemu-img"
|
|
readonly LAUNCHER=$(basename $0)
|
|
SNAPSHOT_ACTION=""
|
|
SNAPSHOT_TAG=""
|
|
STATUSQUO=""
|
|
VM=""
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "${1}" in
|
|
-efi|--efi)
|
|
ENABLE_EFI=1
|
|
shift;;
|
|
-delete|--delete)
|
|
DELETE=1
|
|
shift;;
|
|
-snapshot|--snapshot)
|
|
SNAPSHOT_ACTION="${2}"
|
|
if [ -z "${SNAPSHOT_ACTION}" ]; then
|
|
echo "ERROR! No snapshot action provided."
|
|
exit 1
|
|
fi
|
|
shift
|
|
SNAPSHOT_TAG="${2}"
|
|
if [ -z "${SNAPSHOT_TAG}" ] && [ "${SNAPSHOT_ACTION}" != "info" ]; then
|
|
echo "ERROR! No snapshot tag provided."
|
|
exit 1
|
|
fi
|
|
shift
|
|
shift;;
|
|
-status-quo|--status-quo)
|
|
STATUSQUO="-snapshot"
|
|
shift;;
|
|
-vm|--vm)
|
|
VM="$2"
|
|
shift
|
|
shift;;
|
|
-h|--h|-help|--help)
|
|
usage;;
|
|
*)
|
|
echo "ERROR! \"${1}\" is not a supported parameter."
|
|
usage;;
|
|
esac
|
|
done
|
|
|
|
# Check we have qemu-virgil available
|
|
if [ ! -e "${QEMU}" ] && [ ! -e "${QEMU_IMG}" ]; then
|
|
echo "ERROR! qemu-virgil not found. Please install the qemu-virgil snap."
|
|
echo " https://snapcraft.io/qemu-virgil"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "${VM}" ] || [ -e "${VM}" ]; then
|
|
source "${VM}"
|
|
if [ -z "${disk_img}" ]; then
|
|
echo "ERROR! No disk_img defined."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "ERROR! Virtual machine configuration not found."
|
|
usage
|
|
fi
|
|
|
|
if [ ${DELETE} -eq 1 ]; then
|
|
disk_delete
|
|
exit
|
|
fi
|
|
|
|
if [ -n "${SNAPSHOT_ACTION}" ]; then
|
|
case ${SNAPSHOT_ACTION} in
|
|
apply)
|
|
snapshot_apply "${SNAPSHOT_TAG}"
|
|
snapshot_info
|
|
exit;;
|
|
create)
|
|
snapshot_create "${SNAPSHOT_TAG}"
|
|
snapshot_info
|
|
exit;;
|
|
delete)
|
|
snapshot_delete "${SNAPSHOT_TAG}"
|
|
snapshot_info
|
|
exit;;
|
|
info)
|
|
snapshot_info
|
|
exit;;
|
|
*)
|
|
echo "ERROR! \"${SNAPSHOT_ACTION}\" is not a supported snapshot action."
|
|
usage;;
|
|
esac
|
|
fi
|
|
|
|
vm_boot |