/** Handle service periodic maintenance calls. */
  @Override
  public void handleMaintenance(Operation post) {
    post.complete();

    Operation.CompletionHandler handler =
        (Operation op, Throwable failure) -> {
          if (null != failure) {
            // query failed so abort and retry next time
            logFailure(failure);
            return;
          }

          NodeSelectorService.SelectOwnerResponse rsp =
              op.getBody(NodeSelectorService.SelectOwnerResponse.class);
          if (!getHost().getId().equals(rsp.ownerNodeId)) {
            ServiceUtils.logInfo(
                TaskTriggerService.this,
                "Host[%s]: Not owner of scheduler [%s] (Owner Info [%s])",
                getHost().getId(),
                getSelfLink(),
                Utils.toJson(rsp));
            return;
          }

          State state = new State();
          sendSelfPatch(state);
        };

    Operation selectOwnerOp =
        Operation.createPost(null)
            .setExpiration(ServiceUtils.computeExpirationTime(OWNER_SELECTION_TIMEOUT_MILLIS))
            .setCompletion(handler);
    getHost().selectOwner(null, getSelfLink(), selectOwnerOp);
  }
 @Test(dataProvider = "ValidStartStages")
 public void testValidStartState(TaskState.TaskStage startStage) throws Throwable {
   CreateContainerSpecTaskService.State startState = buildValidStartState(startStage);
   Operation startOperation =
       testHost.startServiceSynchronously(createContainerSpecTaskService, startState);
   assertThat(startOperation.getStatusCode(), is(200));
 }
  @Override
  public void handleStart(Operation startOperation) {
    ServiceUtils.logInfo(this, "Starting service %s", getSelfLink());
    State startState = startOperation.getBody(State.class);
    InitializationUtils.initialize(startState);

    if (null == startState.taskPollDelay) {
      startState.taskPollDelay = HostUtils.getDeployerContext(this).getTaskPollDelay();
    }

    validateState(startState);

    if (TaskState.TaskStage.CREATED == startState.taskState.stage) {
      startState.taskState.stage = TaskState.TaskStage.STARTED;
    }

    startOperation.setBody(startState).complete();

    try {
      if (ControlFlags.isOperationProcessingDisabled(startState.controlFlags)) {
        ServiceUtils.logInfo(this, "Skipping start operation processing (disabled)");
      } else if (TaskState.TaskStage.STARTED == startState.taskState.stage) {
        sendStageProgressPatch(startState.taskState.stage);
      }
    } catch (Throwable t) {
      failTask(t);
    }
  }
 @Override
 public void handleStart(Operation startOperation) {
   ServiceUtils.logInfo(this, "Starting service %s", getSelfLink());
   State startState = startOperation.getBody(State.class);
   InitializationUtils.initialize(startState);
   ValidationUtils.validateState(startState);
   startOperation.complete();
 }
Example #5
0
 @Override
 public void handleStart(Operation start) {
   try {
     validateState(start);
     start.complete();
   } catch (Exception e) {
     start.fail(e);
   }
 }
 @Override
 public void handlePatch(Operation patchOperation) {
   ServiceUtils.logInfo(this, "Handling patch for service %s", getSelfLink());
   State currentState = getState(patchOperation);
   State patchState = patchOperation.getBody(State.class);
   ValidationUtils.validatePatch(currentState, patchState);
   PatchUtils.patchState(currentState, patchState);
   ValidationUtils.validateState(currentState);
   patchOperation.complete();
 }
Example #7
0
  private void validateState(Operation start) {
    if (!start.hasBody()) {
      throw new IllegalArgumentException("attempt to initialize service with an empty state");
    }

    BankAccountServiceState state = start.getBody(BankAccountServiceState.class);
    if (state.balance < 0) {
      throw new IllegalArgumentException("balance cannot be negative");
    }
  }
Example #8
0
  void handlePatchForDeposit(Operation patch) {
    BankAccountServiceState currentState = getState(patch);
    BankAccountServiceRequest body = patch.getBody(BankAccountServiceRequest.class);

    currentState.balance += body.amount;

    setState(patch, currentState);
    patch.setBody(currentState);
    patch.complete();
  }
    @Test
    public void testMinimalStartState() throws Throwable {
      CreateContainerSpecTaskService.State startState = buildValidStartState();
      Operation startOperation =
          testHost.startServiceSynchronously(createContainerSpecTaskService, startState);
      assertThat(startOperation.getStatusCode(), is(200));

      CreateContainerSpecTaskService.State savedState =
          testHost.getServiceState(CreateContainerSpecTaskService.State.class);

      assertThat(savedState.taskState.stage, is(TaskState.TaskStage.STARTED));
    }
  @Override
  public void handlePatch(Operation patch) {
    State currentState = getState(patch);
    State patchState = patch.getBody(State.class);

    this.validatePatch(currentState, patchState);
    this.applyPatch(currentState, patchState);
    this.validateState(currentState);
    patch.complete();

    this.processPatch(currentState);
  }
    @Test(dataProvider = "StartStagesWhichTransitionToStarted")
    public void testStartStateTransitionsToStarted(TaskState.TaskStage startStage)
        throws Throwable {
      CreateContainerSpecTaskService.State startState = buildValidStartState(startStage);
      Operation startOperation =
          testHost.startServiceSynchronously(createContainerSpecTaskService, startState);
      assertThat(startOperation.getStatusCode(), is(200));

      CreateContainerSpecTaskService.State savedState =
          testHost.getServiceState(CreateContainerSpecTaskService.State.class);

      assertThat(savedState.taskState.stage, is(TaskState.TaskStage.STARTED));
    }
    @Test(dataProvider = "FinalStartStages")
    public void testFinalStartState(TaskState.TaskStage startStage) throws Throwable {
      CreateContainerSpecTaskService.State startState = buildValidStartState(startStage);
      startState.controlFlags = 0;
      Operation startOperation =
          testHost.startServiceSynchronously(createContainerSpecTaskService, startState);
      assertThat(startOperation.getStatusCode(), is(200));

      CreateContainerSpecTaskService.State savedState =
          testHost.getServiceState(CreateContainerSpecTaskService.State.class);

      assertThat(savedState.taskState.stage, is(startStage));
    }
  @Override
  public void handleStart(Operation start) {
    ServiceUtils.logInfo(this, "Starting service %s", getSelfLink());

    State s = start.getBody(State.class);
    this.initializeState(s);
    this.validateState(s);

    // set the maintenance interval to match the value in the state.
    this.setMaintenanceIntervalMicros(TimeUnit.MILLISECONDS.toMicros(s.triggerIntervalMillis));

    start.complete();
  }
    @Test
    public void testGetServiceStateWithDefaultPath() throws Throwable {
      ExampleService exampleService = new ExampleService();
      ExampleService.ExampleServiceState exampleServiceState =
          new ExampleService.ExampleServiceState();
      exampleServiceState.name = UUID.randomUUID().toString();

      Operation post = host.startServiceSynchronously(exampleService, exampleServiceState);
      assertThat(post.getStatusCode(), is(200));

      ExampleService.ExampleServiceState result =
          host.getServiceState(ExampleService.ExampleServiceState.class);
      assertThat(result.name, is(exampleServiceState.name));
    }
Example #15
0
  void handlePatchForWithdraw(Operation patch) {
    BankAccountServiceState currentState = getState(patch);
    BankAccountServiceRequest body = patch.getBody(BankAccountServiceRequest.class);

    if (body.amount > currentState.balance) {
      patch.fail(new IllegalArgumentException("Not enough funds to withdraw"));
      return;
    }
    currentState.balance -= body.amount;

    setState(patch, currentState);
    patch.setBody(currentState);
    patch.complete();
  }
  private void createTenantEntity(final String tenantId) {

    final Service service = this;

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

            try {
              State patchState = buildPatch(TaskState.TaskStage.FINISHED, null);
              patchState.tenantServiceLink =
                  operation.getBody(TenantService.State.class).documentSelfLink;
              TaskUtils.sendSelfPatch(service, patchState);
            } catch (Throwable t) {
              failTask(t);
            }
          }
        };

    Operation op =
        Operation.createPost(UriUtils.buildUri(getHost(), TenantFactoryService.SELF_LINK))
            .setBody(createTenantServiceState(tenantId))
            .setCompletion(completionHandler);
    sendRequest(op);
  }
Example #17
0
 @Override
 public void handleGet(Operation get) {
   try {
     FileUtils.readFileAndComplete(get, this.file);
   } catch (IOException e) {
     get.fail(e);
   }
 }
    @Test(dataProvider = "ValidStageTransitions")
    public void testValidStageTransition(
        TaskState.TaskStage startStage, TaskState.TaskStage patchStage) throws Throwable {
      startService(startStage);
      CreateContainerSpecTaskService.State patchState =
          createContainerSpecTaskService.buildPatch(patchStage, null);

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

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

      CreateContainerSpecTaskService.State savedState =
          testHost.getServiceState(CreateContainerSpecTaskService.State.class);

      assertThat(savedState.taskState.stage, is(patchStage));
    }
  @Override
  public void handlePatch(Operation patchOperation) {
    ServiceUtils.logInfo(this, "Handling patch for service %s", getSelfLink());
    State startState = getState(patchOperation);
    State patchState = patchOperation.getBody(State.class);
    validatePatchState(startState, patchState);
    State currentState = applyPatch(startState, patchState);
    validateState(currentState);
    patchOperation.complete();

    try {
      if (ControlFlags.isOperationProcessingDisabled(currentState.controlFlags)) {
        ServiceUtils.logInfo(this, "Skipping patch operation processing (disabled)");
      } else if (TaskState.TaskStage.STARTED == currentState.taskState.stage) {
        createTenant(currentState);
      }
    } catch (Throwable t) {
      failTask(t);
    }
  }
  /**
   * Trigger image replication.
   *
   * @param request
   * @return
   * @throws Throwable
   */
  private String triggerReplication(ReplicateImageRequest request) throws Throwable {
    // Prepare replication service call.
    ImageReplicatorService.State postReq = new ImageReplicatorService.State();
    postReq.image = request.getImage();
    postReq.datastore = request.getDatastore();

    // Create the operation and call for replication.
    Operation postOperation =
        Operation.createPost(UriUtils.buildUri(dcpHost, ImageReplicatorServiceFactory.class))
            .setBody(postReq)
            .setReferer(UriUtils.buildUri(dcpHost, REFERRER_PATH))
            .setExpiration(Utils.getNowMicrosUtc() + dcpOperationTimeoutMicros)
            .setContextId(LoggingUtils.getRequestId());
    OperationLatch opLatch = new OperationLatch(postOperation);
    dcpHost.sendRequest(postOperation);
    Operation op = opLatch.await();

    // Return operation id.
    return op.getBody(ImageReplicatorService.State.class).documentSelfLink;
  }
  /**
   * Get service state by serviceLink.
   *
   * @param path
   * @return
   * @throws Throwable
   */
  private ImageReplicatorService.State getLatestState(String path) throws Throwable {
    Operation getOperation =
        Operation.createGet(UriUtils.buildUri(dcpHost, path))
            .setReferer(UriUtils.buildUri(dcpHost, REFERRER_PATH))
            .setExpiration(Utils.getNowMicrosUtc() + dcpOperationTimeoutMicros)
            .setContextId(LoggingUtils.getRequestId());
    OperationLatch opLatch = new OperationLatch(getOperation);

    dcpHost.sendRequest(getOperation);
    return opLatch.await().getBody(ImageReplicatorService.State.class);
  }
  public DcpException(
      Operation requestedOperation, OperationLatch.OperationResult operationResult) {
    super(
        operationResult.completedOperation == null
            ? requestedOperation.toString()
            : operationResult.completedOperation.toString(),
        operationResult.operationFailure);

    this.requestedOperation = requestedOperation;
    this.operationResult = operationResult;
  }
    @Test
    public void testWaitForState() throws Throwable {
      ExampleService exampleService = new ExampleService();
      final ExampleService.ExampleServiceState exampleServiceState =
          new ExampleService.ExampleServiceState();
      exampleServiceState.name = UUID.randomUUID().toString();

      Operation post = host.startServiceSynchronously(exampleService, exampleServiceState);
      assertThat(post.getStatusCode(), is(200));

      try {
        host.waitForState(
            ExampleService.ExampleServiceState.class,
            new Predicate<ExampleService.ExampleServiceState>() {
              @Override
              public boolean test(ExampleService.ExampleServiceState state) {
                return false;
              }
            });

        Assert.fail("this state transition should not have succeeded");
      } catch (TimeoutException e) {
        assertThat(
            e.getMessage(), is(equalToIgnoringCase("timeout waiting for state transition.")));
      }

      try {
        host.waitForState(
            ExampleService.ExampleServiceState.class,
            new Predicate<ExampleService.ExampleServiceState>() {
              @Override
              public boolean test(ExampleService.ExampleServiceState state) {
                return state.name.equals(exampleServiceState.name);
              }
            });
      } catch (RuntimeException runtimeException) {
        Assert.fail("failed to detect state transition");
      }
    }
  /**
   * Does any additional processing after the patch operation has been completed.
   *
   * @param current
   */
  private void processPatch(final State current) {
    try {
      Type stateType = Class.forName(current.triggerStateClassName);
      ServiceDocument postState = Utils.fromJson(current.serializedTriggerState, stateType);
      postState.documentExpirationTimeMicros =
          ServiceUtils.computeExpirationTime(current.taskExpirationAgeMillis);

      Operation post =
          Operation.createPost(UriUtils.buildUri(getHost(), current.factoryServiceLink))
              .setBody(postState);
      this.sendRequest(post);
    } catch (ClassNotFoundException ex) {
      logFailure(ex);
    }
  }
    @Test(
        dataProvider = "InvalidStageTransitions",
        expectedExceptions = IllegalStateException.class)
    public void testInvalidStageTransition(
        TaskState.TaskStage startStage, TaskState.TaskStage patchStage) throws Throwable {
      startService(startStage);
      CreateContainerSpecTaskService.State patchState =
          createContainerSpecTaskService.buildPatch(patchStage, null);

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

      testHost.sendRequestAndWait(patchOperation);
    }
    @Test(
        dataProvider = "InvalidPatchStateAttributes",
        expectedExceptions = IllegalStateException.class)
    public void testInvalidPatchStateInvalidAttributeSet(String attributeName, Object value)
        throws Throwable {
      startService(TaskState.TaskStage.CREATED);

      CreateContainerSpecTaskService.State patchState =
          createContainerSpecTaskService.buildPatch(TaskState.TaskStage.STARTED, null);

      patchState.getClass().getDeclaredField(attributeName).set(patchState, value);

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

      testHost.sendRequestAndWait(patchOperation);
    }
 private void startService(TaskState.TaskStage startStage) throws Throwable {
   CreateContainerSpecTaskService.State startState = buildValidStartState(startStage);
   Operation startOperation =
       testHost.startServiceSynchronously(createContainerSpecTaskService, startState);
   assertThat(startOperation.getStatusCode(), is(200));
 }
  public DcpException(Operation operation) {
    super(operation.toString());

    this.requestedOperation = operation;
  }
    @Test
    public void testWaitForQuery() throws Throwable {
      ExampleService exampleService = new ExampleService();
      final ExampleService.ExampleServiceState exampleServiceState =
          new ExampleService.ExampleServiceState();
      exampleServiceState.name = UUID.randomUUID().toString();

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

      QueryTask.Query nameClause =
          new QueryTask.Query()
              .setTermPropertyName("name")
              .setTermMatchValue(exampleServiceState.name);

      QueryTask.QuerySpecification spec = new QueryTask.QuerySpecification();
      spec.query.addBooleanClause(kindClause);
      spec.query.addBooleanClause(nameClause);
      spec.options = EnumSet.of(QueryTask.QuerySpecification.QueryOption.EXPAND_CONTENT);

      QueryTask query = QueryTask.create(spec).setDirect(true);

      try {
        host.waitForQuery(
            query,
            new Predicate<QueryTask>() {
              @Override
              public boolean test(QueryTask queryTask) {
                return queryTask.results.documentLinks.size() > 0;
              }
            });

        Assert.fail("waitForQuery should not have succeeded before documents are created");
      } catch (RuntimeException runtimeException) {
        assertThat(
            runtimeException.getMessage(),
            is(equalToIgnoringCase("timeout waiting for query result.")));
      }

      Operation post = host.startServiceSynchronously(exampleService, exampleServiceState);
      assertThat(post.getStatusCode(), is(200));

      ExampleService.ExampleServiceState result =
          host.getServiceState(ExampleService.ExampleServiceState.class);
      assertThat(result.name, is(exampleServiceState.name));

      QueryTask response =
          host.waitForQuery(
              query,
              new Predicate<QueryTask>() {
                @Override
                public boolean test(QueryTask queryTask) {
                  return queryTask.results.documentLinks.size() > 0;
                }
              });
      assertThat(response.results.documentLinks.size(), is(1));

      // verify fields are passed down correctly
      for (Map.Entry<String, Object> document : response.results.documents.entrySet()) {
        ExampleService.ExampleServiceState docState =
            Utils.fromJson(document.getValue(), ExampleService.ExampleServiceState.class);
        assertThat(docState.name, is(equalTo(exampleServiceState.name)));
      }
    }
 @Override
 public void handleStart(Operation startPost) {
   startPost.fail(new Exception(ERROR_MESSAGE));
 }