// Copyright 2016 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.

/*
The makemac command starts OS X VMs for the builders.
It is currently just a thin wrapper around govc.

See https://github.com/vmware/govmomi/tree/master/govc

Usage:

  $ makemac <osx_minor_version>  # e.g, 8, 9, 10, 11, 12

*/
package main

import (
	"bufio"
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	"golang.org/x/build/types"
)

func usage() {
	fmt.Fprintf(os.Stderr, `Usage:
    makemac <osx_minor_version>
    makemac -status
    makemac -auto
`)
	os.Exit(1)
}

var (
	flagStatus   = flag.Bool("status", false, "print status only")
	flagAuto     = flag.Bool("auto", false, "Automatically create & destroy as needed, reacting to https://farmer.golang.org/status/reverse.json status.")
	flagListen   = flag.String("listen", ":8713", "HTTP status port; used by auto mode only")
	flagNuke     = flag.Bool("destroy-all", false, "immediately destroy all running Mac VMs")
	flagBaseDisk = flag.Int("base-disk", 0, "debug mode: if non-zero, print base disk of macOS 10.<value> VM and exit")
)

func main() {
	flag.Parse()
	numArg := flag.NArg()
	ctx := context.Background()
	if *flagBaseDisk != 0 {
		baseDisk, err := findBaseDisk(ctx, *flagBaseDisk)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(baseDisk)
		return
	}
	if *flagStatus {
		numArg++
	}
	if *flagAuto {
		numArg++
	}
	if *flagNuke {
		numArg++
	}
	if numArg != 1 {
		usage()
	}
	if *flagAuto {
		autoLoop()
		return
	}
	if *flagNuke {
		state, err := getState(ctx)
		if err != nil {
			log.Fatal(err)
		}
		if err := state.DestroyAllMacs(ctx); err != nil {
			log.Fatal(err)
		}
		return
	}
	minor, err := strconv.Atoi(flag.Arg(0))
	if err != nil && !*flagStatus {
		usage()
	}

	state, err := getState(ctx)
	if err != nil {
		log.Fatal(err)
	}

	if *flagStatus {
		stj, _ := json.MarshalIndent(state, "", "  ")
		fmt.Printf("%s\n", stj)
		return
	}

	_, err = state.CreateMac(ctx, minor)
	if err != nil {
		log.Fatal(err)
	}
}

// State is the state of the world.
type State struct {
	mu sync.Mutex

	Hosts  map[string]int    // IP address -> running Mac VM count (including 0)
	VMHost map[string]string // "mac_10_8_host02b" => "10.0.0.0"
	HostIP map[string]string // "host-5" -> "10.0.0.0"
	VMInfo map[string]VMInfo // "mac_10_8_host02b" => ...

	// VMOfSlot maps from a "slot name" to the VMWare VM name.
	//
	// A slot name is a tuple of (host number, "a"|"b"), where "a"
	// and "b" are the two possible guests that can run per host.
	// This slot name of the form "macstadium_host02b" is what's
	// reported as the host name to the coordinator.
	//
	// The map value is the VMWare vm name, such as "mac_10_8_host02b",
	// and is the map key of VMHost and VMInfo above.
	VMOfSlot map[string]string // "macstadium_host02b" => "mac_10_8_host02b"
}

type VMInfo struct {
	IP       string
	BootTime time.Time

	// SlotName is the name of a place where we can run a VM.
	// As of 2017-08-04 we have 20 slots total over 10 physical
	// machines. (Two VMs per physical Mac Mini running ESXi)
	// We use slot names of the form "macstadium_host02b"
	// with a %02d digit host number and suffix 'a' and 'b'
	// for which VM it is on that host.
	//
	// This slot name is also the name passed to the build
	// coordinator as the coordinator's "host name". (which exists
	// both for debugging, and for monitoring last-seen/uptime of
	// dedicated builders.)
	SlotName string
}

// NumCreatableVMs returns the number of VMs that can be created given
// the current capacity.
func (st *State) NumCreatableVMs() int {
	st.mu.Lock()
	defer st.mu.Unlock()
	n := 0
	for _, cur := range st.Hosts {
		if cur < 2 {
			n += 2 - cur
		}
	}
	return n
}

// NumMacVMsOfVersion reports how many VMs are running Mac OS X 10.<ver>.
func (st *State) NumMacVMsOfVersion(ver int) int {
	st.mu.Lock()
	defer st.mu.Unlock()
	prefix := fmt.Sprintf("mac_10_%v_", ver)
	n := 0
	for name := range st.VMInfo {
		if strings.HasPrefix(name, prefix) {
			n++
		}
	}
	return n
}

// DestroyAllMacs runs "govc vm.destroy" on each running Mac VM.
func (st *State) DestroyAllMacs(ctx context.Context) error {
	st.mu.Lock()
	defer st.mu.Unlock()
	var ret error
	for name := range st.VMInfo {
		log.Printf("destroying %s ...", name)
		err := govc(ctx, "vm.destroy", name)
		log.Printf("vm.destroy(%q) = %v", name, err)
		if err != nil && ret == nil {
			ret = err
		}
	}
	return ret
}

// CreateMac creates an Mac VM running OS X 10.<minor>.
func (st *State) CreateMac(ctx context.Context, minor int) (slotName string, err error) {
	// TODO(bradfitz): return VM name, update state, etc.

	st.mu.Lock()
	defer st.mu.Unlock()

	var guestType string
	switch minor {
	case 8:
		guestType = "darwin12_64Guest"
	case 9:
		guestType = "darwin13_64Guest"
	case 10:
		guestType = "darwin14_64Guest"
	case 11:
		guestType = "darwin15_64Guest"
	case 12:
		guestType = "darwin16_64Guest"
	case 13:
		// High Sierra. Requires vSphere 6.7.
		// https://www.virtuallyghetto.com/2018/04/new-vsphere-6-7-apis-worth-checking-out.html
		guestType = "darwin17_64Guest"
	case 14:
		// Mojave. Requires vSphere 6.7.
		// https://www.virtuallyghetto.com/2018/04/new-vsphere-6-7-apis-worth-checking-out.html
		guestType = "darwin18_64Guest"
	default:
		return "", fmt.Errorf("unsupported makemac minor OS X version %d", minor)
	}

	builderType := fmt.Sprintf("darwin-amd64-10_%d", minor)

	// Up to 10.12 we used the deprecated buildlet --reverse mode, instead of --reverse-type.
	// Starting with 10.14 (and 10.13 if we ever make a High Sierra image), we're switching
	// to the non-deprecated mode.
	if minor >= 13 {
		builderType = fmt.Sprintf("host-darwin-10_%d", minor)
	}

	key, err := ioutil.ReadFile(filepath.Join(os.Getenv("HOME"), "keys", builderType))
	if err != nil {
		return "", err
	}

	baseDisk, err := findBaseDisk(ctx, minor)
	if err != nil {
		return "", fmt.Errorf("failed to find osx_%d_frozen base disk: %v", minor, err)
	}

	hostNum, hostWhich, err := st.pickHost()
	if err != nil {
		return "", err
	}
	name := fmt.Sprintf("mac_10_%v_host%02d%s", minor, hostNum, hostWhich)
	slotName = fmt.Sprintf("macstadium_host%02d%s", hostNum, hostWhich)

	if err := govc(ctx, "vm.create",
		"-m", "4096",
		"-c", "6",
		"-on=false",
		"-net", "dvPortGroup-Private", // 10.50.0.0/16
		"-g", guestType,
		// Put the config on the host's datastore, which
		// forces the VM to run on that host:
		"-ds", fmt.Sprintf("BOOT_%d", hostNum),
		name,
	); err != nil {
		return "", err
	}
	defer func() {
		if err != nil {
			err := govc(ctx, "vm.destroy", name)
			if err != nil {
				log.Printf("failed to destroy %v: %v", name, err)
			}
		}
	}()

	if err := govc(ctx, "vm.change",
		"-e", "smc.present=TRUE",
		"-e", "ich7m.present=TRUE",
		"-e", "firmware=efi",
		"-e", fmt.Sprintf("guestinfo.key-%s=%s", builderType, strings.TrimSpace(string(key))),
		"-e", "guestinfo.name="+name,
		"-vm", name,
	); err != nil {
		return "", err
	}

	if err := govc(ctx, "device.usb.add", "-vm", name); err != nil {
		return "", err
	}

	if err := govc(ctx, "vm.disk.attach",
		"-vm", name,
		"-link=true",
		"-persist=false",
		"-ds=Pure1-1",
		"-disk", baseDisk,
	); err != nil {
		return "", err
	}

	if err := govc(ctx, "vm.power", "-on", name); err != nil {
		return "", err
	}
	log.Printf("Success.")
	return slotName, nil
}

// govc runs "govc <args...>" and ignores its output, unless there's an error.
func govc(ctx context.Context, args ...string) error {
	fmt.Fprintf(os.Stderr, "$ govc %v\n", strings.Join(args, " "))
	out, err := exec.CommandContext(ctx, "govc", args...).CombinedOutput()
	if err != nil {
		if isFileSystemReadOnly() {
			out = append(out, "; filesystem is read-only"...)
		}
		return fmt.Errorf("govc %s ...: %v, %s", args[0], err, out)
	}
	return nil
}

const hostIPPrefix = "10.88.203." // with fourth octet starting at 10

var errNoHost = errors.New("no usable host found")

// st.mu must be held.
func (st *State) pickHost() (hostNum int, hostWhich string, err error) {
	for ip, inUse := range st.Hosts {
		if !strings.HasPrefix(ip, hostIPPrefix) {
			continue
		}
		if inUse >= 2 {
			// Apple policy.
			continue
		}
		hostNum, err = strconv.Atoi(strings.TrimPrefix(ip, hostIPPrefix))
		if err != nil {
			return 0, "", err
		}
		hostNum -= 10   // 10.88.203.11 is "BOOT_1" datastore.
		hostWhich = "a" // unless in use
		if st.whichAInUse(hostNum) {
			hostWhich = "b"
		}
		return
	}
	return 0, "", errNoHost
}

// whichAInUse reports whether a VM is running on the provided hostNum named
// with suffix "_host<%02d>a", hostnum.
//
// st.mu must be held
func (st *State) whichAInUse(hostNum int) bool {
	suffix := fmt.Sprintf("_host%02da", hostNum)
	for name := range st.VMHost {
		if strings.HasSuffix(name, suffix) {
			return true
		}
	}
	return false
}

// getStat queries govc to find the current state of the hosts and VMs.
func getState(ctx context.Context) (*State, error) {
	st := &State{
		VMHost:   make(map[string]string),
		Hosts:    make(map[string]int),
		HostIP:   make(map[string]string),
		VMInfo:   make(map[string]VMInfo),
		VMOfSlot: make(map[string]string),
	}

	var hosts elementList
	if err := govcJSONDecode(ctx, &hosts, "ls", "-json", "/MacStadium-ATL/host/MacMini_Cluster"); err != nil {
		return nil, fmt.Errorf("getState: reading /MacStadium-ATL/host/MacMini_Cluster: %v", err)
	}
	for _, h := range hosts.Elements {
		if h.Object.Self.Type == "HostSystem" {
			ip := path.Base(h.Path)
			st.Hosts[ip] = 0
			st.HostIP[h.Object.Self.Value] = ip
		}
	}

	var vms elementList
	if err := govcJSONDecode(ctx, &vms, "ls", "-json", "/MacStadium-ATL/vm"); err != nil {
		return nil, fmt.Errorf("getState: reading /MacStadium-ATL/vm: %v", err)
	}
	for _, h := range vms.Elements {
		if h.Object.Self.Type != "VirtualMachine" {
			continue
		}
		name := path.Base(h.Path)
		hostID := h.Object.Runtime.Host.Value
		hostIP := st.HostIP[hostID]
		st.VMHost[name] = hostIP
		if hostIP != "" && strings.HasPrefix(name, "mac_10_") {
			st.Hosts[hostIP]++
			var bootTime time.Time
			if bt := h.Object.Summary.Runtime.BootTime; bt != "" {
				bootTime, _ = time.Parse(time.RFC3339, bt)
			}

			var slotName string
			if p := strings.Index(name, "_host"); p != -1 {
				slotName = "macstadium" + name[p:] // macstadium_host02a

				if exist := st.VMOfSlot[slotName]; exist != "" {
					// Should never happen, but just in case.
					log.Printf("ERROR: existing VM %q found in slot %q; destroying later VM %q", exist, slotName, name)
					err := govc(ctx, "vm.destroy", name)
					log.Printf("vm.destroy(%q) = %v", name, err)
				} else {
					st.VMOfSlot[slotName] = name // macstadium_host02a => mac_10_8_host02a
				}
			}

			vi := VMInfo{
				IP:       hostIP,
				BootTime: bootTime,
				SlotName: slotName,
			}
			st.VMInfo[name] = vi
		}
	}

	return st, nil
}

// objRef is a VMWare "Managed Object Reference".
type objRef struct {
	Type  string // e.g. "VirtualMachine"
	Value string // e.g. "host-12"
}

type elementList struct {
	Elements []*elementJSON `json:"elements"`
}

type elementJSON struct {
	Path   string
	Object struct {
		Self    objRef
		Runtime struct {
			Host objRef // for VMs; not present otherwise
		}
		Summary struct {
			Runtime struct {
				BootTime string // time.RFC3339 format, or empty if not running
			}
		}
	}
}

// govcJSONDecode runs "govc <args...>" and decodes its JSON output into dst.
func govcJSONDecode(ctx context.Context, dst interface{}, args ...string) error {
	cmd := exec.CommandContext(ctx, "govc", args...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	err = json.NewDecoder(stdout).Decode(dst)
	if werr := cmd.Wait(); werr != nil && err == nil {
		err = werr
	}
	return err
}

// findBaseDisk returns the path of the vmdk of the most recent
// snapshot of the osx_$(minor)_frozen VM.
func findBaseDisk(ctx context.Context, minor int) (string, error) {
	vmName := fmt.Sprintf("osx_%d_frozen", minor)
	out, err := exec.CommandContext(ctx, "govc", "vm.info", "-json", vmName).Output()
	if err != nil {
		return "", err
	}
	var ret struct {
		VirtualMachines []struct {
			Layout struct {
				Snapshot []struct {
					SnapshotFile []string
				}
			}
		}
	}
	if err := json.Unmarshal(out, &ret); err != nil {
		return "", fmt.Errorf("failed to parse vm.info JSON to find base disk: %v", err)
	}
	if n := len(ret.VirtualMachines); n != 1 {
		if n == 0 {
			return "", fmt.Errorf("VM %s not found", vmName)
		}
		return "", fmt.Errorf("len(ret.VirtualMachines) = %d; want 1 in JSON to find base disk: %v", n, err)
	}
	vm := ret.VirtualMachines[0]
	if len(vm.Layout.Snapshot) < 1 {
		return "", fmt.Errorf("VM %s does not have any snapshots; needs at least one", vmName)
	}
	ss := vm.Layout.Snapshot[len(vm.Layout.Snapshot)-1] // most recent snapshot is last in list

	// Now find the first vmdk file, without its [datastore] prefix. The files are listed like:
	/*
	   "SnapshotFile": [
	     "[Pure1-1] osx_14_frozen/osx_14_frozen-Snapshot2.vmsn",
	     "[Pure1-1] osx_14_frozen/osx_14_frozen_15.vmdk",
	     "[Pure1-1] osx_14_frozen/osx_14_frozen_15-000001.vmdk"
	   ]
	*/
	for _, f := range ss.SnapshotFile {
		if strings.HasSuffix(f, ".vmdk") {
			i := strings.Index(f, "] ")
			if i == -1 {
				return "", fmt.Errorf("unexpected vmdk line %q in SnapshotFile", f)
			}
			return f[i+2:], nil
		}
	}
	return "", fmt.Errorf("no VMDK found in snapshot for %v", vmName)
}

const autoAdjustTimeout = 5 * time.Minute

var status struct {
	sync.Mutex
	lastCheck time.Time
	lastLog   string
	lastState *State
	warnings  []string
	errors    []string
}

func init() {
	http.HandleFunc("/stage0/", handleStage0)
	http.HandleFunc("/buildlet.darwin-amd64", handleBuildlet)
	http.Handle("/", onlyAtRoot{http.HandlerFunc(handleStatus)}) // legacy status location
	http.HandleFunc("/status", handleStatus)
}

func dedupLogf(format string, args ...interface{}) {
	s := fmt.Sprintf(format, args...)
	status.Lock()
	defer status.Unlock()
	if s == status.lastLog {
		return
	}
	status.lastLog = s
	log.Print(s)
}

func autoLoop() {
	if addr := *flagListen; addr != "" {
		go func() {
			if err := http.ListenAndServe(*flagListen, nil); err != nil {
				log.Fatalf("ListenAndServe: %v", err)
			}
		}()
	}
	for {
		timer := time.AfterFunc(autoAdjustTimeout, watchdogFail)
		autoAdjust()
		timer.Stop()
		time.Sleep(2 * time.Second)
	}
}

func watchdogFail() {
	stacks := make([]byte, 1<<20)
	stacks = stacks[:runtime.Stack(stacks, true)]
	log.Fatalf("timeout after %v waiting for autoAdjust(). stacks:\n%s",
		autoAdjustTimeout, stacks)
}

func autoAdjust() {
	status.Lock()
	status.lastCheck = time.Now()
	status.Unlock()

	ctx, cancel := context.WithTimeout(context.Background(), autoAdjustTimeout)
	defer cancel()

	st, err := getState(ctx)
	if err != nil {
		status.Lock()
		status.errors = []string{err.Error()}
		status.Unlock()
		log.Print(err)
		return
	}
	var warnings, errors []string
	defer func() {
		// Set status.lastState once we're now longer using it.
		if st != nil {
			status.Lock()
			status.lastState = st
			status.warnings = warnings
			status.errors = errors
			status.Unlock()
		}
	}()

	req, _ := http.NewRequest("GET", "https://farmer.golang.org/status/reverse.json", nil)
	req = req.WithContext(ctx)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		errors = append(errors, fmt.Sprintf("getting /status/reverse.json from coordinator: %v", err))
		log.Printf("getting reverse status: %v", err)
		return
	}
	defer res.Body.Close()
	var rstat types.ReverseBuilderStatus
	if err := json.NewDecoder(res.Body).Decode(&rstat); err != nil {
		errors = append(errors, fmt.Sprintf("decoding /status/reverse.json from coordinator: %v", err))
		log.Printf("decoding reverse.json: %v", err)
		return
	}

	revHost := make(map[string]*types.ReverseBuilder)
	for hostType, hostStatus := range rstat.HostTypes {
		if !strings.HasPrefix(hostType, "host-darwin-10") {
			continue
		}
		for name, revBuild := range hostStatus.Machines {
			revHost[name] = revBuild
		}
	}

	// Destroy running VMs that appear to be dead and not connected to the coordinator.
	// TODO: do these all concurrently.
	dirty := false
	for name, vi := range st.VMInfo {
		if vi.BootTime.After(time.Now().Add(-3 * time.Minute)) {
			// Recently created. It takes about a minute
			// to boot and connect to the coordinator, so
			// give it 3 minutes of grace before killing
			// it.
			continue
		}
		rh := revHost[name]
		if rh == nil {
			// Look it up by its slot name instead.
			rh = revHost[vi.SlotName]
		}
		if rh == nil {
			log.Printf("Destroying VM %q unknown to coordinator...", name)
			err := govc(ctx, "vm.destroy", name)
			log.Printf("vm.destroy(%q) = %v", name, err)
			dirty = true
			if err != nil {
				warnings = append(warnings, fmt.Sprintf("vm.destroy(%q) = %v", name, err))
			}
		}
	}
	for {
		if dirty {
			st, err = getState(ctx)
			if err != nil {
				errors = append(errors, err.Error())
				log.Print(err)
				return
			}
		}
		canCreate := st.NumCreatableVMs()
		if canCreate <= 0 {
			dedupLogf("All Mac VMs running.")
			return
		}
		ver := wantedMacVersionNext(st, &rstat)

		if ver == 0 {
			dedupLogf("Have capacity for %d more Mac VMs, but none requested by coordinator.", canCreate)
			return
		}
		dedupLogf("Have capacity for %d more Mac VMs; creating requested 10.%d ...", canCreate, ver)
		slotName, err := st.CreateMac(ctx, ver)
		if err != nil {
			errStr := fmt.Sprintf("Error creating 10.%d: %v", ver, err)
			errors = append(errors, errStr)
			log.Print(errStr)
			return
		}
		log.Printf("Created 10.%d VM on %q", ver, slotName)
		dirty = true
	}
}

// wantedMacVersionNext returns the macOS 10.x version to create next,
// or 0 to not make anything. It gets the latest reverse buildlet
// status from the coordinator.
func wantedMacVersionNext(st *State, rstat *types.ReverseBuilderStatus) int {
	// TODO: improve this logic at some point, probably when the
	// coordinator has a proper scheduler (Issue 19178) and when
	// the coordinator keeps 1 of each builder type ready to go.
	// For now just use the static configuration in
	// dashboard/builders.go of how many are expected, which ends
	// up in ReverseBuilderStatus.
	for hostType, hostStatus := range rstat.HostTypes {
		if !strings.HasPrefix(hostType, "host-darwin-10_") {
			continue
		}
		ver, err := strconv.Atoi(strings.TrimPrefix(hostType, "host-darwin-10_"))
		if err != nil {
			log.Printf("ERROR: unexpected host type %q", hostType)
			continue
		}
		want := hostStatus.Expect - st.NumMacVMsOfVersion(ver)
		if want > 0 {
			return ver
		}
	}
	return 0
}

func handleStatus(w http.ResponseWriter, r *http.Request) {
	status.Lock()
	defer status.Unlock()
	w.Header().Set("Content-Type", "application/json")

	// Locking the lastState shouldn't matter since we
	// currently only set status.lastState once the
	// *Status is no longer in use, but lock it anyway, in
	// case usage changes in the future.
	if st := status.lastState; st != nil {
		st.mu.Lock()
		defer st.mu.Unlock()
	}

	// TODO: probably more status, as needed.
	res := &struct {
		LastCheck string
		LastLog   string
		LastState *State
		Warnings  []string
		Errors    []string
	}{
		LastCheck: status.lastCheck.UTC().Format(time.RFC3339),
		LastLog:   status.lastLog,
		LastState: status.lastState,
		Warnings:  status.warnings,
		Errors:    status.errors,
	}
	j, _ := json.MarshalIndent(res, "", "\t")
	w.Write(j)
}

// handleStage0 serves the shell script for buildlets to run on boot, based
// on their macOS version.
//
// Starting with the macOS 10.14 (Mojave) image, their baked-in stage0.sh
// script does:
//
//    while true; do (curl http://10.50.0.2:8713/stage0/$(sw_vers -productVersion)| sh); sleep 5; done
func handleStage0(w http.ResponseWriter, r *http.Request) {
	// ver will be like "10.14.4"
	// Nothing currently uses this, but it might be useful in the future.
	ver := strings.TrimPrefix(r.RequestURI, "/stage0/")
	_ = ver

	fmt.Fprintf(w, "set -e\nset -x\n")
	fmt.Fprintf(w, "export GO_BUILDER_ENV=macstadium_vm\n")
	fmt.Fprintf(w, "curl -o buildlet http://10.50.0.2:8713/buildlet.darwin-amd64\n")
	fmt.Fprintf(w, "chmod +x buildlet; ./buildlet")
}

func handleBuildlet(w http.ResponseWriter, r *http.Request) {
	bin, err := getLatestMacBuildlet(r.Context())
	if err != nil {
		log.Printf("error getting buildlet from GCS: %v", err)
		http.Error(w, "error getting buildlet from GCS", 500)
	}
	w.Header().Set("Content-Length", fmt.Sprint(len(bin)))
	w.Write(bin)
}

// buildlet binary caching by its last seen ETag from HEAD responses
var (
	buildletMu   sync.Mutex
	lastEtag     string
	lastBuildlet []byte // last buildlet binary for lastEtag
)

func getLatestMacBuildlet(ctx context.Context) (bin []byte, err error) {
	req, _ := http.NewRequest("HEAD", "https://storage.googleapis.com/go-builder-data/buildlet.darwin-amd64", nil)
	req = req.WithContext(ctx)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, fmt.Errorf("%s from HEAD to %s", res.Status, req.URL)
	}
	etag := res.Header.Get("Etag")
	if etag == "" {
		return nil, fmt.Errorf("HEAD of %s lacked ETag", req.URL)
	}

	buildletMu.Lock()
	if etag == lastEtag {
		bin = lastBuildlet
		log.Printf("served cached buildlet of %s", etag)
		buildletMu.Unlock()
		return bin, nil
	}
	buildletMu.Unlock()

	log.Printf("fetching buildlet from GCS...")
	req, _ = http.NewRequest("GET", "https://storage.googleapis.com/go-builder-data/buildlet.darwin-amd64", nil)
	req = req.WithContext(ctx)
	res, err = http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return nil, fmt.Errorf("%s from GET to %s", res.Status, req.URL)
	}
	etag = res.Header.Get("Etag")
	log.Printf("fetched buildlet from GCS with etag %s", etag)
	if etag == "" {
		return nil, fmt.Errorf("GET of %s lacked ETag", req.URL)
	}
	slurp, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	buildletMu.Lock()
	defer buildletMu.Unlock()
	lastEtag = etag
	lastBuildlet = slurp
	return lastBuildlet, nil
}

// onlyAtRoot is an http.Handler wrapper that enforces that it's
// called at /, else it serves a 404.
type onlyAtRoot struct{ h http.Handler }

func (h onlyAtRoot) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	h.h.ServeHTTP(w, r)
}

func isFileSystemReadOnly() bool {
	f, err := os.Open("/proc/mounts")
	if err != nil {
		return false
	}
	defer f.Close()
	// Look for line:
	//    /dev/sda1 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
	bs := bufio.NewScanner(f)
	for bs.Scan() {
		f := strings.Fields(bs.Text())
		if len(f) < 4 {
			continue
		}
		mountPoint, state := f[1], f[3]
		if mountPoint == "/" {
			return strings.HasPrefix(state, "ro,")
		}
	}
	return false
}
