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  }