Skip to content

Commit

Permalink
cmd/buildlet: support Windows ARM64 qemu guests
Browse files Browse the repository at this point in the history
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 <alex@golang.org>
Run-TryBot: Alexander Rakoczy <alex@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
  • Loading branch information
toothrot committed May 26, 2021
1 parent b9b91a1 commit 98da949
Showing 1 changed file with 25 additions and 9 deletions.
34 changes: 25 additions & 9 deletions cmd/buildlet/buildlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
}

Expand Down Expand Up @@ -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)
}
Expand All @@ -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 {
Expand All @@ -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))
Expand Down Expand Up @@ -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")
}
Expand Down

0 comments on commit 98da949

Please sign in to comment.