cmd/coordinator: make basepin disk creation automatic

Fixes golang/go#21305

Change-Id: I40f2ebf1bed234bbac7c7ef200ed5a4bafe35fee
Reviewed-on: https://go-review.googlesource.com/c/build/+/179419
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/cmd/coordinator/buildongce/create.go b/cmd/coordinator/buildongce/create.go
index d9de48f..c9a1ff8 100644
--- a/cmd/coordinator/buildongce/create.go
+++ b/cmd/coordinator/buildongce/create.go
@@ -26,7 +26,6 @@
 
 var (
 	makeClusters = flag.String("make-clusters", "go,buildlets", "comma-separated list of clusters to create. Empty means none.")
-	makeDisks    = flag.Bool("make-basepin", false, "Create the basepin disk images for all builders, then stop. Does not create the VM.")
 	makeMetrics  = flag.Bool("make-metrics", false, "Create the Stackdriver metrics for buildlet monitoring.")
 )
 
@@ -83,13 +82,6 @@
 		log.Fatalf("could not create client: %v", err)
 	}
 
-	if *makeDisks {
-		if err := bgc.MakeBasepinDisks(ctx); err != nil {
-			log.Fatalf("could not create basepin disks: %v", err)
-		}
-		return
-	}
-
 	for _, c := range []*buildenv.KubeConfig{&buildEnv.KubeBuild, &buildEnv.KubeTools} {
 		err := createCluster(bgc, c)
 		if err != nil {
diff --git a/cmd/coordinator/gce.go b/cmd/coordinator/gce.go
index 49692ad..c16d779 100644
--- a/cmd/coordinator/gce.go
+++ b/cmd/coordinator/gce.go
@@ -36,6 +36,7 @@
 	"golang.org/x/build/cmd/coordinator/spanlog"
 	"golang.org/x/build/dashboard"
 	"golang.org/x/build/gerrit"
+	"golang.org/x/build/internal/buildgo"
 	"golang.org/x/build/internal/buildstats"
 	"golang.org/x/build/internal/lru"
 	"golang.org/x/oauth2"
@@ -190,6 +191,7 @@
 	}
 
 	go gcePool.pollQuotaLoop()
+	go createBasepinDisks()
 	return nil
 }
 
@@ -698,3 +700,30 @@
 		<-ticker.C
 	}
 }
+
+// createBasepinDisks runs in the background on start-up and does a
+// best effort creation of zone-local copies of VM disk images, to
+// speed up VM creations in the future.
+//
+// Other than a list call, this a no-op unless new VM images were
+// added or updated recently.
+func createBasepinDisks() {
+	if !metadata.OnGCE() || (buildEnv != buildenv.Production && buildEnv != buildenv.Staging) {
+		return
+	}
+	t0 := time.Now()
+	ctx := context.Background()
+	bgc, err := buildgo.NewClient(ctx, buildEnv)
+	if err != nil {
+		log.Printf("basepin: NewClient: %v", err)
+		return
+	}
+	log.Printf("basepin: creating basepin disks...")
+	err = bgc.MakeBasepinDisks(ctx)
+	d := time.Since(t0).Round(time.Second) / 10
+	if err != nil {
+		log.Printf("basepin: error creating basepin disks, after %v: %v", d, err)
+		return
+	}
+	log.Printf("basepin: created basepin disks after %v", d)
+}