From 98da9493a85e4082141b468e4721a62363a97b4c Mon Sep 17 00:00:00 2001 From: Alexander Rakoczy Date: Tue, 25 May 2021 17:08:01 -0400 Subject: [PATCH] cmd/buildlet: support Windows ARM64 qemu guests The Windows ARM builders on EC2 run on qemu via KVM. We use a userspace network device for simplicity, which also conveniently restricts which ports are exposed. In order to make a request to the metatadata service, which is routed in a different way than the public internet, we explicitly forward the port to the guest VM on a special ip/port. This introduces a hard-coded value for Windows ARM64 buildlets. We should be able to improve this code to detect it, but this will get the buildlet unblocked. The buildlet image also includes llvm-arm64 mingw rather than a gcc based distribution. This change also adds the correct directory to the path. For golang/go#42604 Change-Id: Ife2ebb900a08034d6e0dfa0982a24b312ee6d70a Reviewed-on: https://go-review.googlesource.com/c/build/+/322653 Trust: Alexander Rakoczy Run-TryBot: Alexander Rakoczy TryBot-Result: Go Bot Reviewed-by: Carlos Amedee --- cmd/buildlet/buildlet.go | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/cmd/buildlet/buildlet.go b/cmd/buildlet/buildlet.go index 9ccb5545b4..02a54a5b8e 100644 --- a/cmd/buildlet/buildlet.go +++ b/cmd/buildlet/buildlet.go @@ -41,6 +41,7 @@ import ( "time" "cloud.google.com/go/compute/metadata" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/ec2metadata" "github.com/aws/aws-sdk-go/aws/session" "golang.org/x/build/buildlet" @@ -334,12 +335,18 @@ func onEC2() bool { if ec2MdC != nil { return ec2MdC.Available() } - ses, err := session.NewSession() + cfg := aws.NewConfig() + // TODO(golang/go#42604) - Improve detection of our qemu forwarded + // metadata service for Windows ARM VMs running on EC2. + if runtime.GOOS == "windows" && runtime.GOARCH == "arm64" { + cfg = cfg.WithEndpoint("http://10.0.2.100:8173/latest") + } + ses, err := session.NewSession(cfg) if err != nil { log.Printf("unable to create aws session: %s", err) return false } - ec2MdC = ec2metadata.New(ses) + ec2MdC = ec2metadata.New(ses, cfg) return ec2MdC.Available() } @@ -1123,11 +1130,10 @@ func baseEnv(goarch string) []string { func windowsBaseEnv(goarch string) (e []string) { e = append(e, "GOBUILDEXIT=1") // exit all.bat with completion status - is64 := goarch != "386" for _, pair := range os.Environ() { const pathEq = "PATH=" if hasPrefixFold(pair, pathEq) { - e = append(e, "PATH="+windowsPath(pair[len(pathEq):], is64)) + e = append(e, "PATH="+windowsPath(pair[len(pathEq):], goarch)) } else { e = append(e, pair) } @@ -1143,15 +1149,18 @@ func hasPrefixFold(s, prefix string) bool { // windowsPath cleans the windows %PATH% environment. // is64Bit is whether this is a windows-amd64-* builder. // The PATH is assumed to be that of the image described in env/windows/README. -func windowsPath(old string, is64Bit bool) string { +func windowsPath(old string, goarch string) string { vv := filepath.SplitList(old) newPath := make([]string, 0, len(vv)) + is64Bit := goarch != "386" // for windows-buildlet-v2 images for _, v := range vv { // The base VM image has both the 32-bit and 64-bit gcc installed. // They're both in the environment, so scrub the one // we don't want (TDM-GCC-64 or TDM-GCC-32). + // + // This is not present in arm64 images. if strings.Contains(v, "TDM-GCC-") { gcc64 := strings.Contains(v, "TDM-GCC-64") if is64Bit != gcc64 { @@ -1161,11 +1170,13 @@ func windowsPath(old string, is64Bit bool) string { newPath = append(newPath, v) } - // for windows-amd64-* images - if is64Bit { - newPath = append(newPath, `C:\godep\gcc64\bin`) - } else { + switch goarch { + case "arm64": + newPath = append(newPath, `C:\godep\llvm-aarch64\bin`) + case "386": newPath = append(newPath, `C:\godep\gcc32\bin`) + default: + newPath = append(newPath, `C:\godep\gcc64\bin`) } return strings.Join(newPath, string(filepath.ListSeparator)) @@ -1227,6 +1238,11 @@ func doHalt() { } else { err = errors.New("not respecting -halt flag on macOS in unknown environment") } + case "windows": + err = errors.New("not respsecting -halt flag on windows in unknown environment") + if runtime.GOARCH == "arm64" { + err = exec.Command("shutdown /s").Run() + } default: err = errors.New("no system-specific halt command run; will just end buildlet process") }