Last active
May 14, 2016 16:16
-
-
Save TilBlechschmidt/00c2d20fe3c66f75867662686e689d9d to your computer and use it in GitHub Desktop.
QEMU wrapper scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
. | |
├── cd_images | |
│ └── virtio.iso | |
├── OVMF | |
│ ├── OVMF_CODE-pure-efi.fd | |
│ └── OVMF_VARS-pure-efi-untouched.fd | |
├── qemu_manager.py | |
├── qemu_manager.sh | |
└── VM | |
└── windows_base_uefi | |
├── OVMF_VARS-pure-efi-win7.fd | |
├── vm.json | |
└── win7_hp_uefi_enUS_clean_unregistered.qcow2 | |
5 directories, 11 files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3.5 | |
from __future__ import print_function | |
from pprint import pprint | |
from os import path | |
import sys | |
import json | |
import psutil | |
OVMF_CODE_PATH = path.abspath("./OVMF/OVMF_CODE-pure-efi.fd") | |
def called_by_qmsh(): | |
me = psutil.Process() | |
parent = psutil.Process(me.ppid()) | |
grandparent = psutil.Process(parent.ppid()) | |
called_from_qm = False | |
for arg in grandparent.cmdline(): | |
if "qemu_manager.sh" in arg: | |
called_from_qm = True | |
return called_from_qm | |
def eprint(*args, **kwargs): | |
args = (" \033[93m*\033[39m",) + args | |
print(*args, file=sys.stderr, **kwargs) | |
def parse_vm(name): | |
vm_path = path.join(path.abspath("./VM"), name) | |
with open(path.join(vm_path, 'vm.json')) as data_file: | |
vm_config = json.load(data_file) | |
vm_config["vm_path"] = vm_path | |
return vm_config | |
def start_vm(vm_path=None, kvm=True, uefi=None, virtio=True, | |
mem=4086, cores=4, cpu="host", cpu_args=None, | |
vga=None, sound=None, | |
hdd=None, ide=None, scsi=None): | |
if vm_path is None: | |
exit("ERROR: No VM path passed") | |
if hdd is None: | |
hdd = [] | |
if ide is None: | |
ide = [] | |
if scsi is None: | |
scsi = [] | |
additional_options = "-nodefaults -nodefconfig -net nic,model=virtio -net vde" | |
cmdline = "qemu-system-x86_64 " | |
drive_id = 0 | |
# Enable KVM | |
cmdline += "-enable-kvm " if kvm else "" | |
# ------- Base hardware ------- | |
# Set the RAM allocation | |
cmdline += "-m " + str(mem) + " " | |
# Set the CPU options | |
cmdline += "-cpu " + (cpu + "," + cpu_args if cpu_args else cpu) + " " | |
# Set the CPU core/socket counts | |
cmdline += "-smp " + str(cores) + ",sockets=1,cores=" + str(cores) + ",threads=1 " | |
# Enable UEFI | |
if uefi: | |
uefi = path.join(vm_path, uefi) | |
cmdline += "-drive if=pflash,format=raw,readonly,file=" + OVMF_CODE_PATH + " " | |
cmdline += "-drive if=pflash,format=raw,file=" + uefi + " " | |
# cmdline += "-debugcon file:debug.log -global isa-debugcon.iobase=0x402 " | |
cmdline += "-spice port=5930,disable-ticketing " | |
cmdline += "-device virtio-serial " | |
cmdline += "-chardev spicevmc,id=vdagent,name=vdagent " | |
cmdline += "-device virtserialport,chardev=vdagent,name=com.redhat.spice.0 " | |
vga = "qxl" | |
eprint("WARNING: Overridden VGA with qxl since UEFI (and therefore the spice server) is enabled!") | |
# Set the VGA emulation | |
cmdline += "-vga " + (str(vga) + " -usb -usbdevice tablet" if vga else "none") + " " | |
# Set the sound device | |
if sound: | |
cmdline += "-soundhw " + str(sound) + " " | |
# ------- Drives ------- | |
def add_drive(file, d_id, opt=""): | |
return "-drive file=" + file + ",id=drive_" + str(d_id) + ",if=none" + ("," + opt + " " if opt != "" else " ") | |
if virtio: | |
cmdline += "-device virtio-scsi-pci,id=scsi " | |
# IDE | |
for dvd_image in ide: | |
dvd_image = dvd_image.replace("GLOBAL/", path.abspath("./cd_images") + "/", 1) | |
cmdline += add_drive(dvd_image, drive_id) + "-device ide-cd,bus=ide." + str(drive_id) + ",drive=drive_"\ | |
+ str(drive_id) + " " | |
drive_id += 1 | |
# SCSI | |
for dvd_image in scsi: | |
dvd_image = dvd_image.replace("GLOBAL/", path.abspath("./cd_images") + "/", 1) | |
cmdline += add_drive(dvd_image, drive_id) + "-device scsi-cd,drive=drive_" + str(drive_id) + " " | |
drive_id += 1 | |
# HDD | |
for (hdd_file, options) in hdd: | |
hdd_file = path.join(vm_path, hdd_file) | |
cmdline += add_drive(hdd_file, drive_id, options) + "-device scsi-hd,drive=drive_" + str(drive_id) + " " | |
drive_id += 1 | |
# TODO: Set up VFIO binding | |
# print("echo 1 > /sys/module/kvm/parameters/ignore_msrs") | |
print(cmdline + additional_options) | |
# -rtc base=localtime \ | |
# -net user,smb=/home/themegatb/ \ | |
# -net nic,model=virtio | |
def main(): | |
if not called_by_qmsh(): | |
eprint("This script shouldn't be called directly.") | |
exit(1) | |
vm_config = parse_vm(sys.argv[1]) | |
vm_config.pop("name", None) # eprint("Loaded " + vm_config.pop("name")) | |
start_vm(**vm_config) | |
if __name__ == '__main__': | |
main() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# TODO: Argument parsing and quiet flag for qemu | |
if [ "$EUID" -ne 0 ]; then | |
echo -e " \e[91m*\e[39m Please run as root" | |
exit | |
fi | |
if [ -z "$1" ]; then | |
echo -e " \e[91m*\e[39m Please provide a VM name" | |
exit | |
else | |
VM=$1 | |
fi | |
SPICE=0 | |
if [ ! -z "$2" ] && [ "$2" == "--spice" ] || [ "$2" == "-s" ]; then | |
SPICE=1 | |
fi | |
cols=$(tput cols) | |
function move_before_end_of_line { | |
tput el | |
for ((n=0;n<$1;n++)); do | |
tput cub1 | |
done | |
} | |
function begin { | |
echo -e " \e[92m*\e[39m $1 ..." | |
} | |
function end { | |
move_before_end_of_line 8 | |
if [ $1 -eq 0 ]; then | |
echo -e " \e[1;96m[\e[92m ok \e[96m]\e[39m\e[21m " | |
else | |
echo -e " \e[1m\e[96m[\e[91m !! \e[96m]\e[39m\e[21m" | |
fi | |
} | |
function try { | |
"$@" | |
local status=$? | |
if [ ${status} -ne 0 ]; then | |
# echo "error with $1" >&2 | |
end ${status} | |
exit ${status} | |
fi | |
return ${status} | |
} | |
begin "Exporting PulseAudio driver" | |
try export QEMU_PA_SAMPLES=128 | |
try export QEMU_AUDIO_DRV="pa" | |
end $? | |
begin "Setting up IP forwarding" | |
vde_switch -tap tap0 -mod 660 -group kvm >/dev/null 2>&1 & | |
TAP_PID=$! | |
while ! ip a | grep -F "tap0" > /dev/null; do | |
sleep 0.5 | |
done | |
try ip addr add 10.0.2.1/24 dev tap0 | |
try ip link set dev tap0 up | |
try sysctl -w net.ipv4.ip_forward=1 > /dev/null | |
try iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -j MASQUERADE | |
end $? | |
if [ ${SPICE} -eq 1 ]; then | |
begin "Launching spice" | |
try sh -c "(sleep 0.5 && i3-msg 'workspace '8: '; exec spicy -f -h 127.0.0.1 -p 5930')" > /dev/null & | |
end $? | |
fi | |
begin "Starting VM" | |
cmd=$(./qemu_manager.py ${VM}) | |
#echo ${cmd} | |
echo -e "\e[90m" | |
try ${cmd} | |
end $? | |
begin "Removing IP forwarding device" | |
ip link delete tap0 | |
kill ${TAP_PID} | |
end $? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment