/**
   * Prepares the monitoring objects for the command by the default behavior:
   *
   * <ul>
   *   <li>{@link ExecutionContext} determines how the command should be monitored. By default,
   *       non-internal commands will be associated with {@code Job} to represent the command
   *       execution. Internal commands will not be monitored by default, therefore the {@code
   *       ExecutionContext} is created as non-monitored context.
   *   <li>{@link Job} is created for monitored actions
   * </ul>
   *
   * @param command The created instance of the command (can't be <code>null</code>).
   * @param actionType The action type of the command
   * @param runAsInternal Indicates if the command should be run as internal action or not
   * @param hasCorrelationId Indicates if the current command was executed under a correlation-ID
   */
  public static void prepareCommandForMonitoring(
      CommandBase<?> command, VdcActionType actionType, boolean runAsInternal) {

    ExecutionContext context = command.getExecutionContext();
    if (context == null) {
      context = new ExecutionContext();
    }

    try {
      boolean isMonitored = shouldMonitorCommand(actionType, runAsInternal);

      // A monitored job is created for monitored external flows
      if (isMonitored || context.isJobRequired()) {
        Job job = getJob(command, actionType);
        context.setExecutionMethod(ExecutionMethod.AsJob);
        context.setJob(job);
        command.setExecutionContext(context);
        command.setJobId(job.getId());
        context.setMonitored(true);
      }
    } catch (Exception e) {
      log.errorFormat(
          "Failed to prepare command of type {0} for monitoring due to error {1}",
          actionType.name(), ExceptionUtils.getMessage(e), e);
    }
  }
  private static void chooseHostForExecution(
      VdsIdVDSCommandParametersBase parametersBase,
      Guid storagePoolId,
      CommandBase<?> cmd,
      Collection<Guid> executedHosts) {
    Guid vdsForExecution = getHostForExecution(storagePoolId, executedHosts);
    parametersBase.setVdsId(vdsForExecution);

    if (cmd != null) {
      cmd.getParameters().setVdsRunningOn(vdsForExecution);
      cmd.persistCommand(cmd.getParameters().getParentCommand(), cmd.getCallback() != null);
    }
  }
  /**
   * Creates and returns an instance of {@link Job} entity.
   *
   * @param actionType The action type the job entity represents.
   * @param command The {@code CommandBase} instance which the job entity describes.
   * @return An initialized {@code Job} instance.
   */
  public static Job createJob(VdcActionType actionType, CommandBase<?> command) {
    Job job = new Job();

    job.setId(Guid.newGuid());
    job.setActionType(actionType);
    job.setDescription(
        ExecutionMessageDirector.resolveJobMessage(actionType, command.getJobMessageProperties()));
    job.setJobSubjectEntities(getSubjectEntities(command.getPermissionCheckSubjects()));
    job.setOwnerId(command.getUserId());
    job.setStatus(JobExecutionStatus.STARTED);
    job.setStartTime(new Date());
    job.setCorrelationId(command.getCorrelationId());

    return job;
  }
 private static Job getJob(CommandBase<?> command, VdcActionType actionType) {
   VdcActionParametersBase params = command.getParameters();
   Job job;
   // if Job is external, we had already created the Job by AddExternalJobCommand, so just get it
   // from DB
   if (params.getJobId() != null) {
     job = DbFacade.getInstance().getJobDao().get((Guid) params.getJobId());
   } else {
     job = createJob(actionType, command);
     JobRepositoryFactory.getJobRepository().saveJob(job);
   }
   return job;
 }
 @Override
 public int compare(CommandBase x, CommandBase y) {
   return x.getStorageDomain().getStorageDomainType().getValue()
       - y.getStorageDomain().getStorageDomainType().getValue();
 }