@Test
    public void testPrepareVmDiskOperation() throws Throwable {
      com.vmware.photon.controller.api.Operation operation =
          com.vmware.photon.controller.api.Operation.DETACH_DISK;

      DiskService.State diskState = new DiskService.State();
      diskState.name = "test-vm-disk-1";
      diskState.projectId = projectId;
      diskState.flavorId =
          flavorDcpBackend.getEntityByNameAndKind("core-100", PersistentDisk.KIND).getId();
      diskState.capacityGb = 64;
      diskState.diskType = DiskType.PERSISTENT;
      diskState.state = DiskState.ATTACHED;

      Operation result = dcpClient.post(DiskServiceFactory.SELF_LINK, diskState);
      DiskService.State createdDiskState = result.getBody(DiskService.State.class);
      String diskId = ServiceUtils.getIDFromDocumentSelfLink(createdDiskState.documentSelfLink);

      List<String> disks = new ArrayList<>();
      disks.add(diskId);
      TaskEntity task = vmDcpBackend.prepareVmDiskOperation(vmId, disks, operation);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(1));
      assertThat(task.getSteps().get(0).getOperation(), is(operation));

      try {
        vmDcpBackend.prepareVmDiskOperation(
            vmId, disks, com.vmware.photon.controller.api.Operation.MOCK_OP);
        fail("vmDcpBackend.prepareVmOperation with invalid operation should have failed");
      } catch (NotImplementedException e) {
        // do nothing
      }
    }
    @Test
    public void testPrepareVmGetNetworks() throws Throwable {
      TaskEntity task = vmDcpBackend.prepareVmGetNetworks(vmId);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(1));
      assertThat(
          task.getSteps().get(0).getOperation(),
          is(com.vmware.photon.controller.api.Operation.GET_NETWORKS));
    }
    @Test
    public void testPrepareVmGetMksTicket() throws Throwable {
      vmDcpBackend.updateState(vmDcpBackend.findById(vmId), VmState.STARTED);
      TaskEntity task = vmDcpBackend.prepareVmGetMksTicket(vmId);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(1));
      assertThat(
          task.getSteps().get(0).getOperation(),
          is(com.vmware.photon.controller.api.Operation.GET_MKS_TICKET));
    }
    @Test
    public void testPrepareVmDetachIso() throws Throwable {
      TaskEntity task = vmDcpBackend.prepareVmDetachIso(vmId);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(1));
      assertThat(
          task.getSteps().get(0).getOperation(),
          is(com.vmware.photon.controller.api.Operation.DETACH_ISO));
      assertThat(task.getSteps().get(0).getTransientResourceEntities().get(0), is(vm));
    }
    @Test
    public void testPrepareVmDelete() throws Throwable {
      TaskEntity task = vmDcpBackend.prepareVmDelete(vmId);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(1));
      assertThat(
          task.getSteps().get(0).getOperation(),
          is(com.vmware.photon.controller.api.Operation.DELETE_VM));
      assertThat(task.getToBeLockedEntityIds().size(), is(1));
      assertThat(task.getToBeLockedEntityIds().get(0), is(vmId));
    }
    @Test(dataProvider = "IsoFileNames")
    public void testPrepareVmAttachIso(String isoFileName) throws Throwable {
      TaskEntity task = vmDcpBackend.prepareVmAttachIso(vmId, inputStream, isoFileName);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(2));
      assertThat(
          task.getSteps().get(0).getOperation(),
          is(com.vmware.photon.controller.api.Operation.UPLOAD_ISO));
      IsoEntity iso = (IsoEntity) task.getSteps().get(0).getTransientResourceEntities().get(1);
      assertThat(iso.getName(), is(isoName));

      assertThat(task.getToBeLockedEntityIds().size(), is(2));
      assertThat(task.getToBeLockedEntityIds().get(0), is(iso.getId()));
      assertThat(task.getToBeLockedEntityIds().get(1), is(vmId));
    }
    @Test
    public void testPrepareVmOperation() throws Throwable {
      com.vmware.photon.controller.api.Operation operation =
          VmOperation.VALID_OPERATIONS.iterator().next();
      TaskEntity task = vmDcpBackend.prepareVmOperation(vmId, operation);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(1));
      assertThat(task.getSteps().get(0).getOperation(), is(operation));

      try {
        vmDcpBackend.prepareVmOperation(vmId, com.vmware.photon.controller.api.Operation.MOCK_OP);
        fail("vmDcpBackend.prepareVmOperation with invalid operation should have failed");
      } catch (NotImplementedException e) {
        // do nothing
      }
    }
    @Test
    public void testPrepareSetMetadata() throws Throwable {
      Map<String, String> metadata = new HashMap<>();
      metadata.put("key", "value");

      TaskEntity task = vmDcpBackend.prepareSetMetadata(vmId, metadata);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.COMPLETED));
      assertThat(task.getSteps().size(), is(0));

      // check that metadata was saved
      VmEntity updatedVm = vmDcpBackend.findById(vmId);
      assertThat(updatedVm, notNullValue());
      assertThat(updatedVm.getMetadata(), is(metadata));

      // make sure that no other fields have changed
      updatedVm.setMetadata(this.vm.getMetadata());
      assertThat(this.vm, is(updatedVm));
    }
    @Test(dataProvider = "vmCreateImageReplicationType")
    public void testPrepareVmCreateImage(ImageReplicationType replicationType) throws Throwable {
      ImageCreateSpec imageCreateSpec = new ImageCreateSpec();
      imageCreateSpec.setName("i1");
      imageCreateSpec.setReplicationType(replicationType);

      TaskEntity task = vmDcpBackend.prepareVmCreateImage(vmId, imageCreateSpec);

      assertThat(task, is(notNullValue()));
      assertThat(task.getState(), is(TaskEntity.State.QUEUED));
      assertThat(task.getSteps().size(), is(2));
      StepEntity step = task.getSteps().get(0);
      assertThat(
          step.getOperation(), is(com.vmware.photon.controller.api.Operation.CREATE_VM_IMAGE));
      assertThat(step.getTransientResourceEntities().size(), is(3));
      assertThat(step.getTransientResourceEntities(Vm.KIND).size(), is(1));
      assertThat(step.getTransientResourceEntities(Image.KIND).size(), is(2));

      assertThat(step.getTransientResourceEntities(Vm.KIND).get(0).getId(), is(vm.getId()));

      ImageEntity image = (ImageEntity) step.getTransientResourceEntities(ImageEntity.KIND).get(0);
      assertThat(image.getName(), is(imageCreateSpec.getName()));
      assertThat(image.getReplicationType(), is(imageCreateSpec.getReplicationType()));
      assertThat(image.getState(), is(ImageState.CREATING));
      assertThat(image.getSize(), is(createdImageState.size));
      assertThat(
          image.getImageSettingsMap(),
          is((Map<String, String>) ImmutableMap.of("n1", "v1", "n2", "v2")));

      ImageEntity vmImage =
          (ImageEntity) step.getTransientResourceEntities(ImageEntity.KIND).get(1);
      assertThat(vmImage.getId(), is(vm.getImageId()));

      step = task.getSteps().get(1);
      assertThat(
          step.getOperation(), is(com.vmware.photon.controller.api.Operation.REPLICATE_IMAGE));
    }