private static ComputeDescriptionService.ComputeDescription createComputeDescription(
     TestHost host, String instanceAdapterLink, String bootAdapterLink) throws Throwable {
   // Create ComputeDescription
   ComputeDescriptionService.ComputeDescription cd =
       new ComputeDescriptionService.ComputeDescription();
   cd.environmentName = ComputeDescriptionService.ComputeDescription.ENVIRONMENT_NAME_ON_PREMISE;
   cd.costPerMinute = 1;
   cd.cpuMhzPerCore = 1000;
   cd.cpuCount = 2;
   cd.gpuCount = 1;
   cd.currencyUnit = "USD";
   cd.totalMemoryBytes = Integer.MAX_VALUE;
   cd.id = UUID.randomUUID().toString();
   cd.name = "friendly-name";
   cd.regionId = "provider-specific-regions";
   cd.zoneId = "provider-specific-zone";
   // disable periodic maintenance for tests by default.
   cd.healthAdapterReference = null;
   if (instanceAdapterLink != null) {
     cd.instanceAdapterReference = UriUtils.buildUri(host, instanceAdapterLink);
     cd.powerAdapterReference = URI.create("http://powerAdapter");
   }
   if (bootAdapterLink != null) {
     cd.bootAdapterReference = UriUtils.buildUri(host, bootAdapterLink);
   }
   return host.postServiceSynchronously(
       ComputeDescriptionFactoryService.SELF_LINK,
       cd,
       ComputeDescriptionService.ComputeDescription.class);
 }
Example #2
0
 private NodeState buildLocalNodeState(NodeState body) {
   if (body == null) {
     body = new NodeState();
   }
   body.id = getHost().getId();
   body.status = NodeStatus.SYNCHRONIZING;
   body.groupReference = UriUtils.buildPublicUri(getHost(), getSelfLink());
   body.documentSelfLink = UriUtils.buildUriPath(getSelfLink(), body.id);
   body.documentKind = Utils.buildKind(NodeState.class);
   body.documentUpdateTimeMicros = Utils.getNowMicrosUtc();
   return body;
 }
  private void startTaskSchedulerService(
      final String selfLink, TaskSchedulerServiceStateBuilder builder)
      throws IllegalAccessException, InstantiationException {
    TaskSchedulerService.State state = builder.build();
    state.documentSelfLink = TaskSchedulerServiceStateBuilder.getSuffixFromSelfLink(selfLink);

    URI uri =
        UriUtils.buildUri(
            HousekeeperDcpServiceHost.this, TaskSchedulerServiceFactory.SELF_LINK, null);
    Operation post = Operation.createPost(uri).setBody(state);
    post.setReferer(UriUtils.buildUri(HousekeeperDcpServiceHost.this, HOUSEKEEPER_URI));
    sendRequest(post);
  }
  /**
   * This method performs document state updates in response to an operation which sets the state to
   * STARTED.
   *
   * @param currentState Supplies the current state object.
   */
  private void processStartedStage(final State currentState) throws Throwable {

    Operation.CompletionHandler completionHandler =
        new Operation.CompletionHandler() {
          @Override
          public void handle(Operation operation, Throwable throwable) {
            if (null != throwable) {
              failTask(throwable);
              return;
            }

            try {
              VmService.State vmState = operation.getBody(VmService.State.class);
              processStartedStage(currentState, vmState);

            } catch (Throwable t) {
              failTask(t);
            }
          }
        };

    Operation getOperation =
        Operation.createGet(UriUtils.buildUri(getHost(), currentState.vmServiceLink))
            .setCompletion(completionHandler);
    sendRequest(getOperation);
  }
    @Test(dataProvider = "ImmutableFieldNames", expectedExceptions = DcpRuntimeException.class)
    public void testInvalidPatchImmutableFieldChanged(String fieldName) throws Throwable {
      InitializeDeploymentMigrationWorkflowService.State startState =
          buildValidStartState(null, null);
      Operation startOperation =
          testHost.startServiceSynchronously(
              initializeDeploymentMigrationWorkflowService, startState);
      assertThat(startOperation.getStatusCode(), is(200));
      serviceCreated = true;

      InitializeDeploymentMigrationWorkflowService.State patchState =
          buildValidPatchState(
              TaskState.TaskStage.STARTED,
              InitializeDeploymentMigrationWorkflowService.TaskState.SubStage
                  .PAUSE_DESTINATION_SYSTEM);

      Field declaredField = patchState.getClass().getDeclaredField(fieldName);
      if (declaredField.getType() == Integer.class) {
        declaredField.set(patchState, new Integer(0));
      } else if (declaredField.getType() == Set.class) {
        declaredField.set(patchState, new HashSet<>());
      } else {
        declaredField.set(patchState, declaredField.getType().newInstance());
      }

      Operation patchOperation =
          Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI))
              .setBody(patchState);

      testHost.sendRequestAndWait(patchOperation);
    }
  /**
   * This method retrieves the vmId from the vm service link.
   *
   * @param currentState Supplies the current state object.
   * @param metadata Supplies the metadata map for vm.
   */
  private void getVmId(final State currentState, final Map<String, String> metadata) {
    final Operation.CompletionHandler completionHandler =
        new Operation.CompletionHandler() {
          @Override
          public void handle(Operation operation, Throwable throwable) {
            if (null != throwable) {
              failTask(throwable);
              return;
            }

            try {
              VmService.State vmState = operation.getBody(VmService.State.class);
              setVmMetadata(currentState, vmState.vmId, metadata);
            } catch (Throwable t) {
              failTask(t);
            }
          }
        };

    Operation getOperation =
        Operation.createGet(UriUtils.buildUri(getHost(), currentState.vmServiceLink))
            .setCompletion(completionHandler);

    sendRequest(getOperation);
  }
    @Test(dataProvider = "ValidStageUpdates")
    public void testValidStageUpdates(
        InitializeDeploymentMigrationWorkflowService.TaskState.TaskStage startStage,
        InitializeDeploymentMigrationWorkflowService.TaskState.SubStage startSubStage,
        InitializeDeploymentMigrationWorkflowService.TaskState.TaskStage patchStage,
        InitializeDeploymentMigrationWorkflowService.TaskState.SubStage patchSubStage)
        throws Throwable {
      InitializeDeploymentMigrationWorkflowService.State startState =
          buildValidStartState(startStage, startSubStage);
      Operation startOperation =
          testHost.startServiceSynchronously(
              initializeDeploymentMigrationWorkflowService, startState);
      assertThat(startOperation.getStatusCode(), is(200));
      serviceCreated = true;

      Operation patchOperation =
          Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI))
              .setBody(buildValidPatchState(patchStage, patchSubStage));

      Operation result = testHost.sendRequestAndWait(patchOperation);
      assertThat(result.getStatusCode(), is(200));

      InitializeDeploymentMigrationWorkflowService.State serviceState =
          testHost.getServiceState(InitializeDeploymentMigrationWorkflowService.State.class);

      assertThat(serviceState.taskState.stage, is(patchStage));
      assertThat(serviceState.taskState.subStage, is(patchSubStage));
    }
 public NodeSelectorReplicationService(Service parent) {
   this.parent = parent;
   super.setHost(parent.getHost());
   super.setSelfLink(
       UriUtils.buildUriPath(parent.getSelfLink(), ServiceHost.SERVICE_URI_SUFFIX_REPLICATION));
   super.setProcessingStage(ProcessingStage.AVAILABLE);
 }
  /**
   * Triggers an ImageCopyService for the datastore passed as a parameter.
   *
   * @param current
   * @param datastore
   */
  protected void triggerCopyService(final State current, String datastore) {
    // build completion handler
    Operation.CompletionHandler handler =
        new Operation.CompletionHandler() {
          @Override
          public void handle(Operation acknowledgeOp, Throwable failure) {
            if (failure != null) {
              // we could not start an ImageCopyService task. Something went horribly wrong. Fail
              // the current task and stop processing.
              RuntimeException e =
                  new RuntimeException(String.format("Failed to send copy request %s", failure));
              failTask(e);
            }
          }
        };

    // build start state
    ImageCopyService.State copyState = new ImageCopyService.State();
    copyState.image = current.image;
    copyState.sourceImageDataStoreName = current.datastore;
    copyState.destinationDataStoreId = datastore;
    copyState.parentLink = getSelfLink();
    copyState.documentExpirationTimeMicros = current.documentExpirationTimeMicros;

    // start service
    Operation copyOperation =
        Operation.createPost(UriUtils.buildUri(getHost(), ImageCopyServiceFactory.SELF_LINK))
            .setBody(copyState)
            .setCompletion(handler);
    this.sendRequest(copyOperation);
  }
  private void setupRemainingSlaves(final KubernetesClusterCreateTask currentState) {
    // Maintenance task should be singleton for any cluster.
    ClusterMaintenanceTaskService.State startState = new ClusterMaintenanceTaskService.State();
    startState.batchExpansionSize = currentState.slaveBatchExpansionSize;
    startState.documentSelfLink = currentState.clusterId;

    Operation postOperation =
        Operation.createPost(
                UriUtils.buildUri(getHost(), ClusterMaintenanceTaskFactoryService.SELF_LINK))
            .setBody(startState)
            .setCompletion(
                (Operation operation, Throwable throwable) -> {
                  if (null != throwable) {
                    failTaskAndPatchDocument(currentState, NodeType.KubernetesSlave, throwable);
                    return;
                  }

                  // The handleStart method of the maintenance task does not push itself to STARTED
                  // automatically.
                  // We need to patch the maintenance task manually to start the task immediately.
                  // Otherwise
                  // the task will wait for one interval to start.
                  startMaintenance(currentState);
                });
    sendRequest(postOperation);
  }
  private Collection<Operation> createClearTransactionRequests(
      SimpleTransactionServiceState currentState,
      String transactionId,
      EndTransactionRequest.TransactionOutcome transactionOutcome) {
    if (currentState.enrolledServices.isEmpty()) {
      return null;
    }

    Collection<Operation> requests = new ArrayList<>(currentState.enrolledServices.size());
    for (String serviceSelfLink : currentState.enrolledServices.keySet()) {
      EnrollmentInfo enrollmentInfo = currentState.enrolledServices.get(serviceSelfLink);
      ClearTransactionRequest body = new ClearTransactionRequest();
      body.kind = ClearTransactionRequest.KIND;
      body.transactionOutcome = transactionOutcome;
      body.isUpdated = enrollmentInfo.isUpdated;
      body.originalVersion = enrollmentInfo.originalVersion;
      Operation op =
          Operation.createPatch(UriUtils.buildUri(getHost(), serviceSelfLink))
              .setTransactionId(transactionId)
              .setBody(body);
      requests.add(op);
    }

    return requests;
  }
    private void handleEnrollInTransaction(Operation request) {
      String serviceSelfLink = this.service.getSelfLink();
      if (Action.POST == request.getAction()) {
        ServiceDocument body = request.getBody(this.service.getStateType());
        if (body.documentSelfLink == null) {
          body.documentSelfLink = UUID.randomUUID().toString();
          request.setBody(body);
        }
        serviceSelfLink = UriUtils.buildUriPath(serviceSelfLink, body.documentSelfLink);
      }

      long servicePreviousVersion =
          this.service.getState(request) == null
              ? -1
              : this.service.getState(request).documentVersion;
      Operation enrollRequest =
          SimpleTransactionService.TxUtils.buildEnrollRequest(
                  this.service.getHost(),
                  request.getTransactionId(),
                  serviceSelfLink,
                  request.getAction(),
                  servicePreviousVersion)
              .setCompletion(
                  (o, e) -> {
                    if (e != null) {
                      request.fail(e);
                      return;
                    }
                    this.service
                        .getOperationProcessingChain()
                        .resumeProcessingRequest(request, this);
                  });
      this.service.sendRequest(enrollRequest);
    }
  private void startImageCleanerTriggerService() {
    registerForServiceAvailability(
        (Operation operation, Throwable throwable) -> {
          ImageCleanerTriggerService.State state = new ImageCleanerTriggerService.State();
          state.documentSelfLink = TRIGGER_CLEANER_SERVICE_SUFFIX;

          URI uri =
              UriUtils.buildUri(
                  HousekeeperDcpServiceHost.this,
                  ImageCleanerTriggerServiceFactory.SELF_LINK,
                  null);
          Operation post = Operation.createPost(uri).setBody(state);
          post.setReferer(UriUtils.buildUri(HousekeeperDcpServiceHost.this, HOUSEKEEPER_URI));
          sendRequest(post);
        },
        ImageCleanerTriggerServiceFactory.SELF_LINK);
  }
  /**
   * This method retrieves the container templates of all the containers that are running on this
   * VM.
   *
   * @param currentState Supplies the current state object.
   */
  private void queryContainers(final State currentState) {

    QueryTask.Query kindClause =
        new QueryTask.Query()
            .setTermPropertyName(ServiceDocument.FIELD_NAME_KIND)
            .setTermMatchValue(Utils.buildKind(ContainerService.State.class));

    QueryTask.Query nameClause =
        new QueryTask.Query()
            .setTermPropertyName(ContainerService.State.FIELD_NAME_VM_SERVICE_LINK)
            .setTermMatchValue(currentState.vmServiceLink);

    QueryTask.QuerySpecification querySpecification = new QueryTask.QuerySpecification();
    querySpecification.query.addBooleanClause(kindClause);
    querySpecification.query.addBooleanClause(nameClause);
    QueryTask queryTask = QueryTask.create(querySpecification).setDirect(true);

    sendRequest(
        Operation.createPost(
                UriUtils.buildBroadcastRequestUri(
                    UriUtils.buildUri(getHost(), ServiceUriPaths.CORE_LOCAL_QUERY_TASKS),
                    ServiceUriPaths.DEFAULT_NODE_SELECTOR))
            .setBody(queryTask)
            .setCompletion(
                new Operation.CompletionHandler() {
                  @Override
                  public void handle(Operation operation, Throwable throwable) {
                    if (null != throwable) {
                      failTask(throwable);
                      return;
                    }

                    try {
                      Collection<String> documentLinks =
                          QueryTaskUtils.getBroadcastQueryDocumentLinks(operation);
                      QueryTaskUtils.logQueryResults(
                          CreateManagementVmTaskService.this, documentLinks);
                      checkState(documentLinks.size() > 0);
                      getContainerTemplates(currentState, documentLinks);
                    } catch (Throwable t) {
                      failTask(t);
                    }
                  }
                }));
  }
  /**
   * Triggers a query task with the spec passed as parameters.
   *
   * @param spec
   */
  private void sendQuery(QueryTask.QuerySpecification spec, Operation.CompletionHandler handler) {
    QueryTask task = QueryTask.create(spec).setDirect(true);

    Operation queryPost =
        Operation.createPost(UriUtils.buildUri(getHost(), LuceneQueryTaskFactoryService.SELF_LINK))
            .setBody(task)
            .setCompletion(handler);
    sendRequest(queryPost);
  }
Example #16
0
  @Test
  public void systemUser() throws Throwable {
    URI uri = UriUtils.buildUri(this.host, SystemUserService.SELF_LINK);
    Operation get = Operation.createGet(uri).setCompletion(this.host.getCompletion());

    this.host.testStart(1);
    this.host.send(get);
    this.host.testWait();
  }
Example #17
0
  private void sendAvailableSelfPatch(NodeState local) {
    // mark self as available by issuing self PATCH
    NodeGroupState body = new NodeGroupState();
    body.config = null;
    body.documentOwner = getHost().getId();
    body.documentSelfLink = UriUtils.buildUriPath(getSelfLink(), body.documentOwner);
    local.status = NodeStatus.AVAILABLE;
    body.nodes.put(local.id, local);

    sendRequest(Operation.createPatch(getUri()).setBody(body));
  }
    @Test(expectedExceptions = XenonRuntimeException.class)
    public void testInvalidPatchStateVmServiceLinkFieldSet() throws Throwable {
      createContainerService();
      ContainerService.State patchState = new ContainerService.State();
      patchState.vmServiceLink = "VM_SERVICE_LINK";

      Operation patchOperation =
          Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI, null))
              .setBody(patchState);

      testHost.sendRequestAndWait(patchOperation);
    }
  @Test
  public void getDescriptionInJson() throws Throwable {
    host.testStart(1);

    Operation op =
        Operation.createGet(UriUtils.buildUri(host, SwaggerDescriptorService.SELF_LINK))
            .setReferer(host.getUri())
            .setCompletion(host.getSafeHandler(this::assertDescriptorJson));

    host.sendRequest(op);

    host.testWait();
  }
  private DeploymentService.State getState() {
    if (deploymentLink != null) {
      URI serviceUri = UriUtils.buildUri(xenonHost, deploymentLink);

      Operation getOperation =
          Operation.createGet(serviceUri).setUri(serviceUri).setReferer(this.xenonHost.getUri());
      OperationLatch operationLatch = new OperationLatch(getOperation);
      xenonHost.sendRequest(getOperation);
      Operation completedOperation = null;
      try {
        completedOperation = operationLatch.awaitOperationCompletion(TimeUnit.SECONDS.toMicros(90));
      } catch (Throwable e) {
        logger.error("SysConfig get failed!! ", e);
        throw new RuntimeException(e);
      }

      return completedOperation.getBody(DeploymentService.State.class);
    } else {
      QueryTask.Query kindClause =
          new QueryTask.Query()
              .setTermPropertyName(ServiceDocument.FIELD_NAME_KIND)
              .setTermMatchValue(Utils.buildKind(DeploymentService.State.class));

      QueryTask.QuerySpecification querySpecification = new QueryTask.QuerySpecification();
      querySpecification.query = kindClause;

      Operation broadcastOp =
          xenonHost
              .getCloudStoreHelper()
              .createBroadcastPost(
                  ServiceUriPaths.CORE_LOCAL_QUERY_TASKS, ServiceUriPaths.DEFAULT_NODE_SELECTOR)
              .setBody(QueryTask.create(querySpecification).setDirect(true));
      OperationLatch operationLatch = new OperationLatch(broadcastOp);
      xenonHost.sendRequest(broadcastOp);
      Operation completedOperation = null;
      try {
        completedOperation = operationLatch.awaitOperationCompletion(TimeUnit.SECONDS.toMicros(90));
      } catch (Throwable e) {
        logger.error("SysConfig broadcastquery failed!! ", e);
        throw new RuntimeException(e);
      }

      Collection<String> documentLinks =
          QueryTaskUtils.getBroadcastQueryDocumentLinks(completedOperation);
      if (documentLinks.size() == 0) {
        return null;
      }
      this.deploymentLink = documentLinks.iterator().next();
      return getState();
    }
  }
  @Test
  public void getDescriptionInYaml() throws Throwable {
    host.testStart(1);

    Operation op =
        Operation.createGet(UriUtils.buildUri(host, SwaggerDescriptorService.SELF_LINK))
            .addRequestHeader(Operation.ACCEPT_HEADER, "text/x-yaml")
            .setReferer(host.getUri())
            .setCompletion(host.getSafeHandler(this::assertDescriptorYaml));

    host.sendRequest(op);

    host.testWait();
  }
  @BeforeClass
  public static void setup() throws Throwable {
    host = VerificationHost.create(0);

    SwaggerDescriptorService swagger = new SwaggerDescriptorService();
    Info info = new Info();
    info.setDescription(INFO_DESCRIPTION);
    info.setTermsOfService(INFO_TERMS_OF_SERVICE);
    info.setTitle("title");
    info.setVersion("version");

    swagger.setInfo(info);
    swagger.setExcludedPrefixes("/core/authz/");
    host.start();

    host.startService(swagger);

    host.startService(
        Operation.createPost(UriUtils.buildFactoryUri(host, ExampleService.class)),
        ExampleService.createFactory());

    host.startService(
        Operation.createPost(UriUtils.buildFactoryUri(host, CarService.class)),
        CarService.createFactory());

    host.startService(
        Operation.createPost(UriUtils.buildUri(host, UiService.class)), new UiService());

    host.startService(
        Operation.createPost(UriUtils.buildFactoryUri(host, ExampleService.class)),
        new ExampleService());

    host.startService(
        Operation.createPost(UriUtils.buildUri(host, TokenService.class)), new TokenService());

    host.waitForServiceAvailable(SwaggerDescriptorService.SELF_LINK);
  }
  @Test
  public void testSwaggerUiAvailable() throws Throwable {
    host.testStart(1);

    URI uri =
        UriUtils.buildUri(
            host, SwaggerDescriptorService.SELF_LINK + ServiceUriPaths.UI_PATH_SUFFIX);
    Operation op =
        Operation.createGet(new URI(uri.toString() + "/"))
            .setReferer(host.getUri())
            .setCompletion(host.getSafeHandler(this::assertSwaggerUiAvailable));

    host.sendRequest(op);

    host.testWait();
  }
    @Test(expectedExceptions = XenonRuntimeException.class)
    public void testInvalidPatchStateOverwriteExistingContainerId() throws Throwable {
      ContainerService.State startState = TestHelper.getContainerServiceStartState();
      startState.containerId = "CONTAINER_ID";
      Operation startOperation = testHost.startServiceSynchronously(containerService, startState);
      assertThat(startOperation.getStatusCode(), is(200));

      ContainerService.State patchState = new ContainerService.State();
      patchState.containerId = "CONTAINER_ID";

      Operation patchOperation =
          Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI, null))
              .setBody(patchState);

      testHost.sendRequestAndWait(patchOperation);
    }
    @Test(dataProvider = "ValidContainerIdPatchValues")
    public void testValidPatchStateContainerIdFieldSet(String containerId) throws Throwable {
      createContainerService();
      ContainerService.State patchState = new ContainerService.State();
      patchState.containerId = containerId;

      Operation patchOperation =
          Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI, null))
              .setBody(patchState);

      Operation patchResult = testHost.sendRequestAndWait(patchOperation);
      assertThat(patchResult.getStatusCode(), is(200));

      ContainerService.State savedState = testHost.getServiceState(ContainerService.State.class);
      assertThat(savedState.containerId, is(containerId));
    }
Example #26
0
  /**
   * Handles a POST to either join this service to a group using a peer existing member
   * (JoinPeerRequest as the body) or add a new local monitor service to track the state of a remote
   * peer
   *
   * @param post
   */
  @Override
  public void handlePost(Operation post) {
    if (!post.hasBody()) {
      post.fail(new IllegalArgumentException("body is required"));
      return;
    }

    CheckConvergenceRequest cr = post.getBody(CheckConvergenceRequest.class);
    if (CheckConvergenceRequest.KIND.equals(cr.kind)) {
      handleCheckConvergencePost(post, cr);
      return;
    }

    JoinPeerRequest joinBody = post.getBody(JoinPeerRequest.class);
    if (joinBody != null && joinBody.memberGroupReference != null) {
      handleJoinPost(joinBody, post, getState(post), null);
      return;
    }

    NodeState body = post.getBody(NodeState.class);
    if (body.id == null) {
      post.fail(new IllegalArgumentException("id is required"));
      return;
    }

    adjustStat(post.getAction() + STAT_NAME_REFERER_SEGMENT + body.id, 1);

    boolean isLocalNode = body.id.equals(getHost().getId());

    if (body.groupReference == null) {
      post.fail(new IllegalArgumentException("groupReference is required"));
      return;
    }

    if (isLocalNode) {
      // this is a node instance representing us
      buildLocalNodeState(body);
    } else {
      body.documentSelfLink = UriUtils.buildUriPath(getSelfLink(), body.id);
    }

    NodeGroupState localState = getState(post);
    localState.nodes.put(body.id, body);

    post.setBody(body).complete();
  }
  private void startMaintenance(final KubernetesClusterCreateTask currentState) {
    ClusterMaintenanceTaskService.State patchState = new ClusterMaintenanceTaskService.State();
    patchState.taskState = new TaskState();
    patchState.taskState.stage = TaskState.TaskStage.STARTED;

    // Start the maintenance task async without waiting for its completion so that the creation task
    // can finish immediately.
    Operation patchOperation =
        Operation.createPatch(
                UriUtils.buildUri(
                    getHost(),
                    ClusterMaintenanceTaskFactoryService.SELF_LINK + "/" + currentState.clusterId))
            .setBody(patchState)
            .setCompletion(
                (Operation operation, Throwable throwable) -> {
                  // We ignore the failure here since maintenance task will kick in eventually.
                  TaskUtils.sendSelfPatch(this, buildPatch(TaskState.TaskStage.FINISHED, null));
                });
    sendRequest(patchOperation);
  }
  private Collection<Operation> createDeleteRequests(
      SimpleTransactionServiceState currentState,
      EndTransactionRequest.TransactionOutcome transactionOutcome) {
    Set<String> servicesToBDeleted =
        transactionOutcome == TransactionOutcome.COMMIT
            ? currentState.deletedServicesLinks
            : currentState.createdServicesLinks;
    if (servicesToBDeleted.isEmpty()) {
      return null;
    }

    Collection<Operation> requests = new ArrayList<>(servicesToBDeleted.size());
    for (String serviceSelfLink : servicesToBDeleted) {
      Operation op = Operation.createDelete(UriUtils.buildUri(getHost(), serviceSelfLink));
      op.addPragmaDirective(PRAGMA_DIRECTIVE_DELETE_ON_TRANSACTION_END);
      requests.add(op);
      currentState.enrolledServices.remove(serviceSelfLink);
    }

    return requests;
  }
    @Test(dataProvider = "InvalidStageUpdates", expectedExceptions = DcpRuntimeException.class)
    public void testInvalidStageTransition(
        TaskState.TaskStage startStage,
        InitializeDeploymentMigrationWorkflowService.TaskState.SubStage startSubStage,
        TaskState.TaskStage patchStage,
        InitializeDeploymentMigrationWorkflowService.TaskState.SubStage patchSubStage)
        throws Throwable {
      InitializeDeploymentMigrationWorkflowService.State startState =
          buildValidStartState(startStage, startSubStage);
      Operation startOperation =
          testHost.startServiceSynchronously(
              initializeDeploymentMigrationWorkflowService, startState);
      assertThat(startOperation.getStatusCode(), is(200));
      serviceCreated = true;

      Operation patchOperation =
          Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI))
              .setBody(buildValidPatchState(patchStage, patchSubStage));

      testHost.sendRequestAndWait(patchOperation);
    }
  /**
   * Updates the vm associated to the vmServiceLink with the vm Identifier.
   *
   * @param currentState
   * @param vmId
   */
  private void updateVmId(final State currentState, String vmId) {
    Operation.CompletionHandler completionHandler =
        new Operation.CompletionHandler() {
          @Override
          public void handle(Operation operation, Throwable throwable) {
            if (null != throwable) {
              failTask(throwable);
              return;
            }
            queryContainers(currentState);
          }
        };

    VmService.State vmPatchState = new VmService.State();
    vmPatchState.vmId = vmId;
    Operation patchOperation =
        Operation.createPatch(UriUtils.buildUri(getHost(), currentState.vmServiceLink))
            .setBody(vmPatchState)
            .setCompletion(completionHandler);

    sendRequest(patchOperation);
  }