#!/bin/bash # This file encapsulates the rather elaborate networking setup within Docker. # Furthermore, absent any Windows VM file, starts the Windows installation from a provided ISO file. set -eo pipefail if [[ ! -z ${debug+x} ]]; then set -x fi # Again, this is run within the Docker container. # Usually runtimes will replace /dev with a standardized set of devices. # That’s why we need to extend them: if [[ ! -c "/dev/kvm" ]]; then rm /dev/kvm || true set +e read -r NODNUM _ < <(grep '\' /proc/misc) mknod /dev/kvm c 10 "${NODNUM}" set -e else if ! dd if=/dev/kvm count=0 2>/dev/null; then >&2 printf "Cannot open /dev/kvm - please run this in a privileged context.\n" # see: /usr/include/sysexits.h: EX_OSFILE exit 72 fi fi if [[ ! -z "${BRIDGE_IF+x}" ]]; then printf "allow ${BRIDGE_IF}" >/etc/qemu/bridge.conf # Make sure we have the tun device node if [[ ! -c "/dev/net/tun" ]]; then rm /dev/net/tun || true mkdir -p /dev/net set +e read -r NODNUM _ < <(grep '\' /proc/misc) mknod /dev/net/tun c 10 "${NODNUM}" set -e fi fi # End of network plumbing. # Start of setting up, or setting up and starting the actual VM. # This script accepts some arguments (the first one must be "windows"; else this runs any supplied KVM), # which are referred to by shortcuts such as: # windows # example: # windows ${PUBLIC_IPV4} 5900 geheim 52:54:00:xx:xx:xx macvtap0 "windows-1" $((16 * 8 * 1024)) Windows-10-threshold-2-take-1.iso if (( $# >= 8 )) && [[ "$1" == "windows" ]]; then # No prior Windows installation? Create a fresh image: if [[ ! -e /var/vm/disks/"$7".img ]]; then mkdir -p /var/vm/disks chmod 0700 /var/vm/disks qemu-img create -f qcow2 /var/vm/disks/"$7".img 80G fi read MAJOR MINOR < <(cat /sys/devices/virtual/net/$6/tap*/dev | tr ':' ' ') mknod /dev/tap-vm c ${MAJOR} ${MINOR} # -device virtio-balloon,id=balloon0,bus=pci.0,addr=0x7 \ Windows 10 won't start with this if [[ -z ${ncores+x} ]]; then : ${ncores:="4"} if (( $(nproc) > 16 )); then # MCC or HCC cpu(s) if (( $(nproc) > 20)); then let ncores="$[ $(nproc --ignore 4)/2 ]" else let ncores="$(nproc --ignore 2)" fi fi fi drives=() drives+=("-drive" "file=/var/vm/disks/$7.img,if=virtio,index=0,media=disk") if [[ -s /var/cache/media/virtio-win.iso ]]; then drives+=("-drive" "file=/var/cache/media/virtio-win.iso,index=3,media=cdrom,readonly") else >&2 printf "Virtio drivers not found in: %s\n" "/var/cache/media/virtio-win.iso" >&2 printf "Probably okay if this is no Windows, else download them from here:\n" >&2 printf " https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n" fi # 9th argument is expected to be an ISO file to install a fresh Windows from. if (( $# >= 9 )); then if [[ -s "/var/cache/media/$9" ]]; then drives+=("-drive" "file=/var/cache/media/$9,index=2,media=cdrom,readonly") drives+=("-boot" "once=d") else >&2 printf "Ignored, because it is no file: %s\n" "$9" fi fi spice=() spice+=("-vga" "qxl") spice+=("-spice" "addr=$2,port=$3,password=$4") spice+=("-chardev" "spicevmc,id=vdagent,name=vdagent") spice+=("-device" "virtserialport,chardev=vdagent,name=com.redhat.spice.0") exec /usr/bin/qemu -enable-kvm -nographic -rtc base=utc \ -monitor unix:/run/kvm/"$7".monitor,server,nowait \ -cpu host -m $8 -smp ${ncores},sockets=1 -k de -usbdevice tablet \ -device virtio-serial \ ${spice[*]} \ -net nic,model=virtio,macaddr=$5 -net tap,fd=3 3<>/dev/tap-vm \ ${drives[*]} \ -name "$7" else exec /usr/bin/qemu -enable-kvm "$@" fi