veyron/services/mgmt/device/impl: implement per-instance updates

A suspended instance can now be updated to the latest version of its
installation.

This cl also include a couple minor unrelated cleanups that I noticed while
working on the update change:

- move the initialization of the instance and installation state to the very end
  of their respective setup methods

- change setupPrincipal to take the blessing extension as an arg, instead of
  letting it extract the title from the envelope and use that internally (it
  seems less obscure that way)

- update the state of instances recovered by the reaper to 'started'

Change-Id: I36baca769dd66749e84f9e6fb583d8be3c209eae
diff --git a/services/mgmt/device/impl/impl_test.go b/services/mgmt/device/impl/impl_test.go
index 6cda65a..82b6e51 100644
--- a/services/mgmt/device/impl/impl_test.go
+++ b/services/mgmt/device/impl/impl_test.go
@@ -752,14 +752,26 @@
 		t.Fatalf("Second endpoint should have been v1EP2: %v, %v", endpoints, v1EP2)
 	}
 
-	// Stop first instance.
-	stopApp(t, ctx, appID, instance1ID)
-	verifyAppWorkspace(t, root, appID, instance1ID)
-
-	// Only second instance is still running.
+	// Trying to update first instance while it's running should fail.
+	updateInstanceExpectError(t, ctx, appID, instance1ID, impl.ErrInvalidOperation.ID)
+	// Suspend first instance and try again.
+	suspendApp(t, ctx, appID, instance1ID)
+	// Only the second instance should still be running and mounted.
 	if want, got := v1EP2, resolve(t, ctx, "appV1", 1)[0]; want != got {
 		t.Fatalf("Resolve(%v): want: %v, got %v", "appV1", want, got)
 	}
+	// Update succeeds now.
+	updateInstance(t, ctx, appID, instance1ID)
+	// Resume the first instance and verify it's running v2 now.
+	resumeApp(t, ctx, appID, instance1ID)
+	verifyPingArgs(t, pingCh, userName(t), "flag-val-install", "env-val-envelope")
+	resolve(t, ctx, "appV1", 1)
+	resolve(t, ctx, "appV2", 1)
+
+	// Stop first instance.
+	stopApp(t, ctx, appID, instance1ID)
+	verifyAppWorkspace(t, root, appID, instance1ID)
+	resolveExpectNotFound(t, ctx, "appV2")
 
 	// Start a third instance.
 	instance3ID := startApp(t, ctx, appID)
@@ -1235,6 +1247,8 @@
 	}
 }
 
+// TODO(caprita): We need better test coverage for how updating/reverting apps
+// affects the package configured for the app.
 func TestDeviceManagerPackages(t *testing.T) {
 	ctx, shutdown := initForTest()
 	defer shutdown()