コード例 #1
0
  public void proceedCommandExecution() {
    // Steps are executed such that:
    //  a) all logic before the command runs is idempotent
    //  b) the command is the last action in the step
    // This allows for recovery after a crash at any point during command execution.

    log.debug("Proceeding with execution of RemoveSnapshotSingleDiskLiveCommand");
    if (getParameters().getCommandStep() == null) {
      getParameters().setCommandStep(getInitialMergeStepForImage(getParameters().getImageId()));
      getParameters().setChildCommands(new HashMap<RemoveSnapshotSingleDiskLiveStep, Guid>());
    }

    // Upon recovery or after invoking a new child command, our map may be missing an entry
    syncChildCommandList();
    Guid currentChildId = getCurrentChildId();

    VdcReturnValueBase vdcReturnValue = null;
    if (currentChildId != null) {
      switch (CommandCoordinatorUtil.getCommandStatus(currentChildId)) {
        case ACTIVE:
        case NOT_STARTED:
          log.info(
              "Waiting on Live Merge command step '{}' to complete",
              getParameters().getCommandStep());
          return;

        case SUCCEEDED:
          CommandEntity cmdEntity = CommandCoordinatorUtil.getCommandEntity(currentChildId);
          if (cmdEntity.isCallbackEnabled() && !cmdEntity.isCallbackNotified()) {
            log.info(
                "Waiting on Live Merge command step '{}' to finalize",
                getParameters().getCommandStep());
            return;
          }

          vdcReturnValue = CommandCoordinatorUtil.getCommandReturnValue(currentChildId);
          if (vdcReturnValue != null && vdcReturnValue.getSucceeded()) {
            log.debug("Child command '{}' succeeded", getParameters().getCommandStep());
            getParameters().setCommandStep(getParameters().getNextCommandStep());
            break;
          } else {
            log.error(
                "Child command '{}' failed: {}",
                getParameters().getCommandStep(),
                (vdcReturnValue != null
                    ? vdcReturnValue.getExecuteFailedMessages()
                    : "null return value"));
            setCommandStatus(CommandStatus.FAILED);
            return;
          }

        case FAILED:
        case FAILED_RESTARTED:
          log.error("Failed child command status for step '{}'", getParameters().getCommandStep());
          setCommandStatus(CommandStatus.FAILED);
          return;

        case UNKNOWN:
          log.error("Unknown child command status for step '{}'", getParameters().getCommandStep());
          setCommandStatus(CommandStatus.FAILED);
          return;
      }
    }

    log.info("Executing Live Merge command step '{}'", getParameters().getCommandStep());

    Pair<VdcActionType, ? extends VdcActionParametersBase> nextCommand = null;
    switch (getParameters().getCommandStep()) {
      case EXTEND:
        nextCommand = new Pair<>(VdcActionType.MergeExtend, buildMergeParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.MERGE);
        break;
      case MERGE:
        nextCommand = new Pair<>(VdcActionType.Merge, buildMergeParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.MERGE_STATUS);
        break;
      case MERGE_STATUS:
        getParameters().setMergeCommandComplete(true);
        nextCommand = new Pair<>(VdcActionType.MergeStatus, buildMergeParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.DESTROY_IMAGE);
        break;
      case DESTROY_IMAGE:
        if (vdcReturnValue != null) {
          getParameters()
              .setMergeStatusReturnValue(
                  (MergeStatusReturnValue) vdcReturnValue.getActionReturnValue());
        } else if (getParameters().getMergeStatusReturnValue() == null) {
          // If the images were already merged, just add the orphaned image
          getParameters().setMergeStatusReturnValue(synthesizeMergeStatusReturnValue());
        }
        nextCommand = new Pair<>(VdcActionType.DestroyImage, buildDestroyImageParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.COMPLETE);
        break;
      case COMPLETE:
        getParameters().setDestroyImageCommandComplete(true);
        setCommandStatus(CommandStatus.SUCCEEDED);
        break;
    }

    persistCommand(getParameters().getParentCommand(), true);
    if (nextCommand != null) {
      CommandCoordinatorUtil.executeAsyncCommand(
          nextCommand.getFirst(), nextCommand.getSecond(), cloneContextAndDetachFromParent());
      // Add the child, but wait, it's a race!  child will start, task may spawn, get polled, and we
      // won't have the child id
    }
  }