@Test
  public void testSimpleRegistration() throws Throwable {
    // Set up initial host state in cloudstore.
    String hostId = "host1";
    String link = service.getHostDocumentLink(hostId);
    DatastoreService.State ds1 = new DatastoreService.State();
    ds1.id = "ds1";
    ds1.name = "ds1";
    ds1.type = "SHARED_VMFS";
    ds1.tags = new LinkedHashSet<>();
    Datastore datastore1 = new Datastore(ds1.id);
    datastore1.setName(ds1.name);
    datastore1.setType(DatastoreType.SHARED_VMFS);
    datastore1.setTags(ds1.tags);
    datastores.add(datastore1);

    DatastoreService.State ds2 = new DatastoreService.State();
    ds2.id = "ds2";
    ds2.name = "ds2";
    ds2.type = "SHARED_VMFS";
    ds2.tags = new LinkedHashSet<>();
    Datastore datastore2 = new Datastore(ds2.id);
    datastore2.setName(ds2.name);
    datastore2.setType(DatastoreType.SHARED_VMFS);
    datastore2.setTags(ds2.tags);
    datastores.add(datastore2);

    String dsLink1 = DatastoreServiceFactory.getDocumentLink(ds1.id);
    String dsLink2 = DatastoreServiceFactory.getDocumentLink(ds2.id);
    HostService.State hostState = new HostService.State();
    hostState.agentState = AgentState.MISSING;
    Operation result = mock(Operation.class);
    when(result.getBody(HostService.State.class)).thenReturn(hostState);
    when(dcpRestClient.get(link)).thenReturn(result);

    // Non-VM networks should get filtered out.
    Network nw1 = new Network("nw1");
    nw1.setTypes(Arrays.asList(NetworkType.VM));
    networks.add(nw1);
    Network nw2 = new Network("nw2");
    nw2.setTypes(Arrays.asList(NetworkType.VM, NetworkType.VMOTION));
    networks.add(nw2);
    Network nw3 = new Network("nw3");
    nw3.setTypes(Arrays.asList(NetworkType.MANAGEMENT, NetworkType.VMOTION));
    networks.add(nw3);

    RegisterHostRequest request =
        createRegReq(datastores, networks, new LinkedHashSet<>(Arrays.asList("ds1", "ds2")));
    request.setId(hostId);
    request.getConfig().setAgent_id(hostId);
    RegisterHostResponse response = service.register_host(request);
    assertThat(response.getResult(), Matchers.is(RegisterHostResultCode.OK));

    verify(configDict).write(hostId, serialize(request.getConfig()));

    // Verify that patch gets called with "READY" state.
    ArgumentCaptor<String> arg1 = ArgumentCaptor.forClass(String.class);
    ArgumentCaptor<ServiceDocument> arg2 = ArgumentCaptor.forClass(ServiceDocument.class);
    verify(dcpRestClient, times(3)).patch(arg1.capture(), arg2.capture());
    assertThat(arg1.getAllValues().get(0), is(link));
    HostService.State newState = (HostService.State) (arg2.getAllValues().get(0));
    assertThat(newState.agentState, is(AgentState.ACTIVE));
    assertThat(newState.reportedDatastores, containsInAnyOrder("ds1", "ds2"));
    assertThat(newState.reportedNetworks, containsInAnyOrder("nw1", "nw2"));
    assertThat(newState.reportedImageDatastores, containsInAnyOrder("ds1", "ds2"));

    // Verify that the isImageDatastore flag gets set on ds1 and ds2.
    assertThat(arg1.getAllValues().get(1), is(dsLink1));
    DatastoreService.State newDsState = (DatastoreService.State) (arg2.getAllValues().get(1));
    assertThat(newDsState.isImageDatastore, is(true));
    assertThat(arg1.getAllValues().get(2), is(dsLink2));
    newDsState = (DatastoreService.State) (arg2.getAllValues().get(2));
    assertThat(newDsState.isImageDatastore, is(true));

    // Verify that chairman attempted to create datastore documents.
    arg1 = ArgumentCaptor.forClass(String.class);
    arg2 = ArgumentCaptor.forClass(ServiceDocument.class);
    verify(dcpRestClient, times(2)).post(arg1.capture(), arg2.capture());
    DatastoreService.State actualDs1 = (DatastoreService.State) (arg2.getAllValues().get(0));
    DatastoreService.State actualDs2 = (DatastoreService.State) (arg2.getAllValues().get(1));
    assertThat(
        arg1.getAllValues(),
        contains(DatastoreServiceFactory.SELF_LINK, DatastoreServiceFactory.SELF_LINK));
    verifyDatastore(ds1, actualDs1);
    verifyDatastore(ds2, actualDs2);
  }
 /**
  * Creates host documents in cloudstore.
  *
  * @param cloudstore CloudStore test environment to create documents in.
  * @param numHosts The number of host documents to create.
  * @param hostConfigurations A map from {@link HostConfiguration} to the probability that this
  *     host configuration is used in the deployment. The sum of all the values of this map must be
  *     1.
  * @param numDatastores The number of datastores.
  * @param numDatastoresDistribution Distribution for number of datastores on each host. This
  *     distribution is expected to generate samples in the range [0, numDatastores].
  * @throws Throwable
  */
 public static void loadHosts(
     TestEnvironment cloudstore,
     int numHosts,
     Map<HostConfiguration, Double> hostConfigurations,
     int numDatastores,
     IntegerDistribution numDatastoresDistribution)
     throws Throwable {
   int[] indices = new int[hostConfigurations.size()];
   HostConfiguration[] configs = new HostConfiguration[hostConfigurations.size()];
   double[] probabilities = new double[hostConfigurations.size()];
   int i = 0;
   for (Map.Entry<HostConfiguration, Double> entry : hostConfigurations.entrySet()) {
     indices[i] = i;
     configs[i] = entry.getKey();
     probabilities[i] = entry.getValue();
     i++;
   }
   EnumeratedIntegerDistribution configDistribution =
       new EnumeratedIntegerDistribution(indices, probabilities);
   for (i = 0; i < numHosts; i++) {
     HostService.State host = new HostService.State();
     host.hostAddress = "host" + i;
     host.state = HostState.READY;
     host.userName = "******";
     host.password = "******";
     host.reportedDatastores = new HashSet<>();
     int numDatastoresPerHost = numDatastoresDistribution.sample();
     assertThat(numDatastoresPerHost >= 0, is(true));
     assertThat(numDatastoresPerHost <= numDatastores, is(true));
     while (host.reportedDatastores.size() < numDatastoresPerHost) {
       int randomInt = random.nextInt(numDatastores);
       host.reportedDatastores.add(new UUID(0, randomInt).toString());
     }
     host.reportedNetworks = new HashSet<>();
     host.usageTags = new HashSet<>(Arrays.asList(UsageTag.CLOUD.name()));
     int configIndex = configDistribution.sample();
     host.cpuCount = configs[configIndex].numCpus;
     host.memoryMb = configs[configIndex].memoryMb;
     host.documentSelfLink = new UUID(0, i).toString();
     // TODO(mmutsuzaki) Support availability zones.
     Operation result = cloudstore.sendPostAndWait(HostServiceFactory.SELF_LINK, host);
     assertThat(result.getStatusCode(), is(200));
     logger.debug("Created a host document: {}", Utils.toJson(host));
   }
 }