golang.org/x/build@v0.0.0-20240506185731-218518f32b70/cmd/runqemubuildlet/main.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Binary runqemubuildlet runs a single VM-based buildlet in a loop. 6 package main 7 8 import ( 9 "context" 10 "flag" 11 "fmt" 12 "log" 13 "os" 14 "os/exec" 15 "os/signal" 16 "time" 17 18 "golang.org/x/build/internal" 19 ) 20 21 var ( 22 // Common flags 23 guestOS = flag.String("guest-os", "windows", "Guest OS to run (one of: windows or darwin)") 24 healthzURL = flag.String("buildlet-healthz-url", "http://localhost:8080/healthz", "URL to buildlet /healthz endpoint.") 25 26 // -guest-os=windows flags 27 windows10Path = flag.String("windows-10-path", defaultWindowsDir(), "Path to Windows image and QEMU dependencies.") 28 29 // -guest-os=darwin flags 30 darwinPath = flag.String("darwin-path", defaultDarwinDir(), "Path to darwin image and QEMU dependencies.") 31 // Using an int for this isn't great, but the only thing we need to do 32 // is check if the version is >= 11. 33 macosVersion = flag.Int("macos-version", 0, "macOS major version of guest image (e.g., 10, 11, 12, or 13)") 34 guestIndex = flag.Int("guest-index", 1, "Index indicating which of the two instances on this host that this is (one of: 1 or 2)") 35 osk = flag.String("osk", "", "Apple OSK key value") 36 ) 37 38 func main() { 39 flag.Parse() 40 41 ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) 42 defer stop() 43 44 for ctx.Err() == nil { 45 var cmd *exec.Cmd 46 switch *guestOS { 47 case "darwin": 48 cmd = darwinCmd(*darwinPath) 49 case "windows": 50 cmd = windows10Cmd(*windows10Path) 51 default: 52 log.Fatalf("Unknown guest OS %q", *guestOS) 53 } 54 55 if err := runGuest(ctx, cmd); err != nil { 56 log.Printf("runGuest() = %v. Retrying in 10 seconds.", err) 57 time.Sleep(10 * time.Second) 58 continue 59 } 60 } 61 } 62 63 func runGuest(ctx context.Context, cmd *exec.Cmd) error { 64 log.Printf("Starting VM: %s", cmd.String()) 65 cmd.Stdout = os.Stdout 66 cmd.Stderr = os.Stderr 67 if err := cmd.Start(); err != nil { 68 return fmt.Errorf("cmd.Start() = %w", err) 69 } 70 ctx, cancel := heartbeatContext(ctx, 30*time.Second, 10*time.Minute, func(ctx context.Context) error { 71 return checkBuildletHealth(ctx, *healthzURL) 72 }) 73 defer cancel() 74 if err := internal.WaitOrStop(ctx, cmd, os.Interrupt, time.Minute); err != nil { 75 return fmt.Errorf("WaitOrStop(_, %v, %v, %v) = %w", cmd, os.Interrupt, time.Minute, err) 76 } 77 return nil 78 }