veyron/tools/playground: add "no-shutdown" mode to compilerd; update README

Change-Id: I935fc049be5b465afd58d6e0a072fa761ff4befa
diff --git a/tools/playground/README.md b/tools/playground/README.md
index 4bfb1ea..30d1d50 100644
--- a/tools/playground/README.md
+++ b/tools/playground/README.md
@@ -1,14 +1,18 @@
 # Running the playground compile server locally
 
-WARNING: Currently, this will cause your machine to power down after one hour,
-so you probably don't want to do this!
+Install Docker for Linux:
 
-TODO(ribrdb): Provide some simple way to run the Docker image locally for
-development purposes.
+TODO(sadovsky): These instructions don't seem to work, and furthermore, adding
+docker.list to sources.list.d may pose a security risk.
 
-Install Docker:
+  $ sudo sh -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
+  $ sudo apt-get update
+  $ sudo apt-get install lxc-docker
+  $ aptitude versions lxc-docker
 
-  $ sudo apt-get install lxc-docker-1.1.0
+Or for OS X, from this site:
+
+  https://github.com/boot2docker/osx-installer/releases
 
 Build the playground Docker image (this will take a while...):
 
@@ -22,10 +26,7 @@
 
 Run the compiler binary as root:
 
-  $ sudo compilerd
+  $ sudo go/bin/compilerd --shutdown=false --address=localhost:8181
 
-The server should now be running at http://localhost:8181, and responding to
+The server should now be running at http://localhost:8181 and responding to
 compile requests at http://localhost:8181/compile.
-
-Note that the server will automatically power down the machine after one hour.
-(It will tell you this when it starts.)
diff --git a/tools/playground/compilerd/main.go b/tools/playground/compilerd/main.go
index fceef3b..d2bcf02 100644
--- a/tools/playground/compilerd/main.go
+++ b/tools/playground/compilerd/main.go
@@ -3,6 +3,7 @@
 import (
 	"bytes"
 	"encoding/json"
+	"flag"
 	"fmt"
 	"math/rand"
 	"net/http"
@@ -23,9 +24,16 @@
 	Events []Event
 }
 
-// This channel is closed when the server begins shutting down.
-// No values are ever sent to it.
-var lameduck chan bool = make(chan bool)
+var (
+	// This channel is closed when the server begins shutting down.
+	// No values are ever sent to it.
+	lameduck chan bool = make(chan bool)
+
+	address = flag.String("address", ":8181", "address to listen on")
+
+	// Note, shutdown triggers on SIGTERM or when the time limit is hit.
+	shutdown = flag.Bool("shutdown", true, "whether to ever shutdown the machine")
+)
 
 func healthz(w http.ResponseWriter, r *http.Request) {
 	select {
@@ -62,7 +70,7 @@
 	buf := new(bytes.Buffer)
 	cmd.Stdout = buf
 	cmd.Stderr = buf
-	// Arbitrary deadline: 2s to compile/start, 1s to run, .5s to shutdown
+	// Arbitrary deadline: 2s to compile/start, 1s to run, .5s to shutdown.
 	timeout := time.After(3500 * time.Millisecond)
 	exit := make(chan error)
 
@@ -100,34 +108,40 @@
 }
 
 func main() {
-	limit_min := 60
-	delay_min := limit_min/2 + rand.Intn(limit_min/2)
+	flag.Parse()
 
-	// VMs will be periodically killed to prevent any owned vms from
-	// causing damage. We want to shutdown cleanly before then so
-	// we don't cause requests to fail.
-	go WaitForShutdown(time.Minute * time.Duration(delay_min))
+	if *shutdown {
+		limit_min := 60
+		delay_min := limit_min/2 + rand.Intn(limit_min/2)
+
+		// VMs will be periodically killed to prevent any owned VMs from causing
+		// damage. We want to shutdown cleanly before then so we don't cause
+		// requests to fail.
+		go WaitForShutdown(time.Minute * time.Duration(delay_min))
+	}
 
 	http.HandleFunc("/compile", handler)
 	http.HandleFunc("/healthz", healthz)
-	http.ListenAndServe(":8181", nil)
+
+	fmt.Printf("Serving %s\n", *address)
+	http.ListenAndServe(*address, nil)
 }
 
 func WaitForShutdown(limit time.Duration) {
 	var beforeExit func() error
 
-	// Shutdown if we get a SIGTERM
+	// Shutdown if we get a SIGTERM.
 	term := make(chan os.Signal, 1)
 	signal.Notify(term, syscall.SIGTERM)
 
-	// Or if the time limit expires
+	// Or if the time limit expires.
 	deadline := time.After(limit)
 	fmt.Println("Shutting down at", time.Now().Add(limit))
 Loop:
 	for {
 		select {
 		case <-deadline:
-			// Shutdown the vm.
+			// Shutdown the VM.
 			fmt.Println("Deadline expired, shutting down.")
 			beforeExit = exec.Command("sudo", "halt").Run
 			break Loop