#!/bin/bash #Exit if run as root (( $(id -u) == 0 )) && { echo "Cannot run this script as root. Exiting."; exit; } source ~/.config/quickemu-bashscripts/quickemu-create.conf 2> /dev/null fullExit() { rm -rf "$VMDirectory"/.tmp exit } installQuickemu() { read -p 'Quickemu could not be found. Would you like to install it? [y/n] ' installInput [[ "$installInput" == "y" ]] || [[ "$installInput" == "yes" ]] && { command -v pacman > /dev/null && { command -v yay > /dev/null && yay -Sy quickemu || { echo 'Install quickemu from the AUR instead.'; fullExit; } } cat /proc/version | grep -q Ubuntu && { read -p 'Ubuntu detected. Would you like to install quickemu from the PPA or from Git? (Default: Git) ' UbuntuRepoInput; } if [[ "${UbuntuRepoInput,,}" == "ppa" ]] && sudo apt-add-repository ppa:flexiondotorg/quickemu && sudo apt update && sudo apt -y install quickemu; then echo 'Successfully installed quickemu from PPA.' && sleep 1 else [[ "${UbuntuRepoInput,,}" == "ppa" ]] && { echo 'Failed to install quickemu from PPA. Installing from Git instead.'; sleep 1; } git clone https://github.com/quickemu-project/quickemu ~/.local/bin/quickemu 2>&1 > /dev/null && echo Installed quickemu in /home/$(whoami)/.local/bin/quickemu || { echo 'Failed to install quickemu. Exiting.'; fullExit; } echo Attempting to install dependencies; sleep 1 command -v apt > /dev/null && sudo apt install qemu bash coreutils ovmf grep jq lsb-base procps python3 genisoimage usbutils util-linux sed spice-client-gtk libtss2-tcti-swtpm0 wget xdg-user-dirs zsync unzip socat command -v dnf > /dev/null && sudo dnf install qemu bash coreutils edk2-tools grep jq lsb procps python3 genisoimage usbutils util-linux sed spice-gtk-tools swtpm wget xdg-user-dirs xrandr unzip fi } [[ "$installInput" == "n" ]] || [[ "$installInput" == "no" ]] && { echo 'Exiting.'; fullExit; } } deleteVMDirectory() { rm -rf "$VMDirectory"/"$releaseString" fullExit } specInput() { read -p '(OPTIONAL) Enter the disk size for this VM (in GB): ' diskSize [ -z "$diskSize" ] || { diskSize=$(echo "$diskSize" | tr -d '[[:alpha:]]') && [[ $diskSize > 0 ]] || { echo 'Invalid disk size. Ignoring' && diskSize=""; }; } read -p '(OPTIONAL) Enter the amount of RAM you would like to allocate (in GB): ' ramSize [ -z "$ramSize" ] || { ramSize=$(echo "$ramSize" | tr -d '[[:alpha:]]') && [[ $ramSize > 0 ]] || { echo 'Invalid RAM amount. Ignoring.' && ramSize=""; }; } read -p '(OPTIONAL) Enter the number of CPU cores you would like to allocate: ' cpuCores [ -z "$cpuCores" ] || { [[ $cpuCores =~ ^[0-9]+$ && $cpuCores > 0 ]] || { echo 'CPU Core count must be a whole number. Ignoring.' && cpuCores=""; }; } } startVM() { quickemu --vm "$configFile" } configSpec() { [ -z "$cpuCores" ] || echo "cpu_cores=$cpuCores" >> "$configFile" [ -z "$ramSize" ] || echo "ram=$ramSize"G >> "$configFile" [ -z "$diskSize" ] || echo "disk_size=$diskSize"G >> "$configFile" } createCustom() { mkdir "$VMDirectory"/"$releaseString" && trap deleteVMDirectory SIGINT && cd "$VMDirectory"/"$releaseString" && mkdir "$VMDirectory"/"$releaseString"/"$customName" cat << EOF > "$configFile" #!$(which quickemu) --vm guest_os="${GuestOS,,}" disk_img="$customName/disk.qcow2" iso="$ISO" EOF chmod u+x "$configFile" } existingVMResponse() { echo -e "VM already exists.\n1. Create a new revision.\n2. Launch the preexisting VM.\n3. Delete the preexisting VM, create a new one in it's place." read -p 'Choose an option: ' input if [[ $input = 1 ]]; then num=2 while [[ -d "$VMDirectory"/"$releaseString - Revision $num" ]]; do num=$((num+1)) done releaseString="$releaseString - Revision $num" elif [[ $input = 2 ]]; then cd "$VMDirectory"/"$releaseString" startVM fullExit elif [[ $input = 3 ]]; then read -p 'Are you sure? This will delete the preexisting VM. [y/N] ' delinput if [[ "${delinput,,}" == "y" ]] || [[ "${delinput,,}" == "yes" ]]; then rm -rf "$VMDirectory"/"$releaseString" else echo Exiting. fullExit fi else echo Invalid selection. Exiting. fullExit fi } customInput() { read -p 'Enter a name for this custom VM: ' releaseString && [ -z "$releaseString" ] && { echo 'Failure. You must input a name.'; fullExit; } customName="${releaseString// /-}" && customName="${customName,,}" && configFile="${customName,,// /-}.conf" [[ -d "$VMDirectory"/"$releaseString" ]] && existingVMResponse read -p 'Enter the path to the ISO (or drag it into the terminal): ' ISO && ISO=$(realpath -e "$(echo "$ISO" | tr -d "'")" 2> /dev/null) || { echo 'Failure. Invalid path.'; fullExit; } echo 'Choose the Operating System - e.g., Windows, Linux, FreeBSD. Default: Linux' && read GuestOS && [ -z "$GuestOS" ] && GuestOS="Linux" } [[ -z "$VMDirectory" ]] && VMDirectory=~/Documents/VMs [[ -d ~/.local/bin/quickemu && "$SkipUpdate" != "true" ]] && { git -C ~/.local/bin/quickemu pull 2>&1 | grep -q "changed" && echo Updated quickemu.; } & trap fullExit SIGINT export PATH=$PATH:~/.local/bin/quickemu command -v quickemu > /dev/null || installQuickemu [ -d "$VMDirectory" ] || { mkdir "$VMDirectory" 2> /dev/null && echo Created VMs folder at "$VMDirectory". || { echo Failed to create VM Folder at "$VMDirectory". Exiting.; fullExit; }; } rm -rf "$VMDirectory"/.tmp; mkdir "$VMDirectory"/.tmp echo -e 'Available Operating Systems:\n' [[ "$WaitForUpdate" == "true" ]] && wait oslist=$((quickget PLACEHOLDER | tail -n +3; echo custom) | tr ' ' '\n' | sort | paste -sd ' ' -) echo $oslist read -p $'\nEnter an operating system: ' OS OSRemoveSpace=${OS// /} echo "$oslist" | grep -qw "${OSRemoveSpace,,}" || { echo "${oslist//-/}" | grep -qw "${OSRemoveSpace,,}" && OSRemoveSpace=${OS/ /-}; } [[ "${OSRemoveSpace,,}" == "custom" ]] && { customInput && specInput && createCustom && configSpec && startVM; fullExit; } #Wait for quickemu to finish updating, if applicable. wait osoutput=$(quickget $OSRemoveSpace 2> "$VMDirectory"/.tmp/erroroutput.txt) if [ -z "$OS" ] || cat "$VMDirectory"/.tmp/erroroutput.txt | grep -q "command not found" > /dev/null || ! echo $osoutput | grep -q ' - Releases: ' > /dev/null; then echo -e '\nFailure. Invalid OS.' fullExit fi echo "$osoutput" | grep ' - Releases: ' read -p 'Enter a release: ' Ver && echo "${osoutput,,}" | grep -qw "${Ver,,}" && correctVer=$(echo $osoutput | grep -io "$Ver" | awk '{print $1; exit}') || { echo 'Failure. Invalid release.'; fullExit; } echo "$osoutput" | grep -q ' - Editions: ' && { echo "$osoutput" | grep ' - Editions: ' && read -p 'Enter an edition: ' Edition; echo "${osoutput,,}" | grep -qw "${Edition,,}" && correctEdition=$(echo $osoutput | grep -io $Edition | awk '{print $1; exit}') || { echo 'Failure. Invalid edition.'; fullExit; }; } releaseString="$OS $Ver${Edition:+ $Edition}" configFile="${OSRemoveSpace,,}-$correctVer${correctEdition:+-$correctEdition}.conf" [[ -d "$VMDirectory"/"$releaseString" ]] && existingVMResponse specInput mkdir "$VMDirectory"/"$releaseString" && cd "$VMDirectory"/"$releaseString" && trap deleteVMDirectory SIGINT quickget ${OSRemoveSpace,,} ${correctVer,,} ${correctEdition:+$correctEdition} || { echo 'Could not download OS. Exiting.'; deleteVMDirectory; } configSpec startVM fullExit