cmd/runqemubuildlet: select windows support with a flag

Subsequent CLs will add support for running darwin guests. To support
differences between the guests, move windows support to a new file and
selected by -guest-os=windows.

This CL has no functional change. Windows remains the default for
compatibility with existing scripts.

For golang/go#48945.

Change-Id: Iec2827b216f7c6b72c53a61b125d132beb44a779
Reviewed-on: https://go-review.googlesource.com/c/build/+/449876
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/cmd/runqemubuildlet/main.go b/cmd/runqemubuildlet/main.go
index 2b67ad8..e7baeff 100644
--- a/cmd/runqemubuildlet/main.go
+++ b/cmd/runqemubuildlet/main.go
@@ -16,15 +16,18 @@
 	"os"
 	"os/exec"
 	"os/signal"
-	"path/filepath"
 	"time"
 
 	"golang.org/x/build/internal"
 )
 
 var (
+	// Common flags
+	guestOS    = flag.String("guest-os", "windows", "Guest OS to run (one of: windows)")
+	healthzURL = flag.String("buildlet-healthz-url", "http://localhost:8080/healthz", "URL to buildlet /healthz endpoint.")
+
+	// -guest-os=windows flags
 	windows10Path = flag.String("windows-10-path", defaultWindowsDir(), "Path to Windows image and QEMU dependencies.")
-	healthzURL    = flag.String("buildlet-healthz-url", "http://localhost:8080/healthz", "URL to buildlet /healthz endpoint.")
 )
 
 func main() {
@@ -34,7 +37,15 @@
 	defer stop()
 
 	for ctx.Err() == nil {
-		if err := runWindows10(ctx); err != nil {
+		var cmd *exec.Cmd
+		switch *guestOS {
+		case "windows":
+			cmd = windows10Cmd(*windows10Path)
+		default:
+			log.Fatalf("Unknown guest OS %q", *guestOS)
+		}
+
+		if err := runGuest(ctx, cmd); err != nil {
 			log.Printf("runWindows10() = %v. Retrying in 10 seconds.", err)
 			time.Sleep(10 * time.Second)
 			continue
@@ -42,8 +53,7 @@
 	}
 }
 
-func runWindows10(ctx context.Context) error {
-	cmd := windows10Cmd(*windows10Path)
+func runGuest(ctx context.Context, cmd *exec.Cmd) error {
 	log.Printf("Starting VM: %s", cmd.String())
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
@@ -59,50 +69,3 @@
 	}
 	return nil
 }
-
-// defaultWindowsDir returns a default path for a Windows VM.
-//
-// The directory should contain the Windows VM image, and UTM
-// components (UTM.app and sysroot-macos-arm64).
-func defaultWindowsDir() string {
-	home, err := os.UserHomeDir()
-	if err != nil {
-		log.Printf("os.UserHomeDir() = %q, %v", home, err)
-		return ""
-	}
-	return filepath.Join(home, "macmini-windows")
-}
-
-// windows10Cmd returns a qemu command for running a Windows VM, ready
-// to be started.
-func windows10Cmd(base string) *exec.Cmd {
-	c := exec.Command(filepath.Join(base, "sysroot-macos-arm64/bin/qemu-system-aarch64"),
-		"-L", filepath.Join(base, "UTM.app/Contents/Resources/qemu"),
-		"-cpu", "max",
-		"-smp", "cpus=8,sockets=1,cores=8,threads=1", // This works well with M1 Mac Minis.
-		"-machine", "virt,highmem=off",
-		"-accel", "hvf",
-		"-accel", "tcg,tb-size=1536",
-		"-boot", "menu=on",
-		"-m", "12288",
-		"-name", "Virtual Machine",
-		"-device", "qemu-xhci,id=usb-bus",
-		"-device", "ramfb",
-		"-device", "usb-tablet,bus=usb-bus.0",
-		"-device", "usb-mouse,bus=usb-bus.0",
-		"-device", "usb-kbd,bus=usb-bus.0",
-		"-device", "virtio-net-pci,netdev=net0",
-		"-netdev", "user,id=net0,hostfwd=tcp:127.0.0.1:8080-:8080",
-		"-bios", filepath.Join(base, "Images/QEMU_EFI.fd"),
-		"-device", "nvme,drive=drive0,serial=drive0,bootindex=0",
-		"-drive", fmt.Sprintf("if=none,media=disk,id=drive0,file=%s,cache=writethrough", filepath.Join(base, "Images/win10.qcow2")),
-		"-device", "usb-storage,drive=drive2,removable=true,bootindex=1",
-		"-drive", fmt.Sprintf("if=none,media=cdrom,id=drive2,file=%s,cache=writethrough", filepath.Join(base, "Images/virtio.iso")),
-		"-snapshot", // critical to avoid saving state between runs.
-		"-vnc", ":3",
-	)
-	c.Env = append(os.Environ(),
-		fmt.Sprintf("DYLD_LIBRARY_PATH=%s", filepath.Join(base, "sysroot-macos-arm64/lib")),
-	)
-	return c
-}
diff --git a/cmd/runqemubuildlet/windows.go b/cmd/runqemubuildlet/windows.go
new file mode 100644
index 0000000..0ee88eb
--- /dev/null
+++ b/cmd/runqemubuildlet/windows.go
@@ -0,0 +1,63 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.16
+// +build go1.16
+
+package main
+
+import (
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+)
+
+// defaultWindowsDir returns a default path for a Windows VM.
+//
+// The directory should contain the Windows VM image, and UTM
+// components (UTM.app and sysroot-macos-arm64).
+func defaultWindowsDir() string {
+	home, err := os.UserHomeDir()
+	if err != nil {
+		log.Printf("os.UserHomeDir() = %q, %v", home, err)
+		return ""
+	}
+	return filepath.Join(home, "macmini-windows")
+}
+
+// windows10Cmd returns a qemu command for running a Windows VM, ready
+// to be started.
+func windows10Cmd(base string) *exec.Cmd {
+	c := exec.Command(filepath.Join(base, "sysroot-macos-arm64/bin/qemu-system-aarch64"),
+		"-L", filepath.Join(base, "UTM.app/Contents/Resources/qemu"),
+		"-cpu", "max",
+		"-smp", "cpus=8,sockets=1,cores=8,threads=1", // This works well with M1 Mac Minis.
+		"-machine", "virt,highmem=off",
+		"-accel", "hvf",
+		"-accel", "tcg,tb-size=1536",
+		"-boot", "menu=on",
+		"-m", "12288",
+		"-name", "Virtual Machine",
+		"-device", "qemu-xhci,id=usb-bus",
+		"-device", "ramfb",
+		"-device", "usb-tablet,bus=usb-bus.0",
+		"-device", "usb-mouse,bus=usb-bus.0",
+		"-device", "usb-kbd,bus=usb-bus.0",
+		"-device", "virtio-net-pci,netdev=net0",
+		"-netdev", "user,id=net0,hostfwd=tcp:127.0.0.1:8080-:8080",
+		"-bios", filepath.Join(base, "Images/QEMU_EFI.fd"),
+		"-device", "nvme,drive=drive0,serial=drive0,bootindex=0",
+		"-drive", fmt.Sprintf("if=none,media=disk,id=drive0,file=%s,cache=writethrough", filepath.Join(base, "Images/win10.qcow2")),
+		"-device", "usb-storage,drive=drive2,removable=true,bootindex=1",
+		"-drive", fmt.Sprintf("if=none,media=cdrom,id=drive2,file=%s,cache=writethrough", filepath.Join(base, "Images/virtio.iso")),
+		"-snapshot", // critical to avoid saving state between runs.
+		"-vnc", ":3",
+	)
+	c.Env = append(os.Environ(),
+		fmt.Sprintf("DYLD_LIBRARY_PATH=%s", filepath.Join(base, "sysroot-macos-arm64/lib")),
+	)
+	return c
+}