private void processDisconnectAndTimeout(VMOperationListener listener, String resultMessage) {
    UserVmVO vm = listener.getVm();
    VMOperationParam param = listener.getParam();
    AsyncJobManager asyncMgr = getAsyncJobMgr();

    EventVO event = new EventVO();
    event.setUserId(param.getUserId());
    event.setAccountId(vm.getAccountId());
    event.setType(EventTypes.EVENT_VM_STOP);
    event.setParameters(
        "id="
            + vm.getId()
            + "\nvmName="
            + vm.getName()
            + "\nsoId="
            + vm.getServiceOfferingId()
            + "\ntId="
            + vm.getTemplateId()
            + "\ndcId="
            + vm.getDataCenterId());
    event.setDescription(
        "failed to stop VM instance : " + vm.getName() + " due to " + resultMessage);
    event.setLevel(EventVO.LEVEL_ERROR);

    asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 0, resultMessage);
    asyncMgr.getExecutorContext().getEventDao().persist(event);

    asyncMgr.releaseSyncSource(this);
  }
  public void processAnswer(VMOperationListener listener, long agentId, long seq, Answer answer) {

    UserVmVO vm = listener.getVm();
    VMOperationParam param = listener.getParam();
    AsyncJobManager asyncMgr = getAsyncJobMgr();
    ManagementServer managementServer = asyncMgr.getExecutorContext().getManagementServer();
    String params =
        "id="
            + vm.getId()
            + "\nvmName="
            + vm.getName()
            + "\nsoId="
            + vm.getServiceOfferingId()
            + "\ntId="
            + vm.getTemplateId()
            + "\ndcId="
            + vm.getDataCenterId();
    if (s_logger.isDebugEnabled())
      s_logger.debug(
          "Execute asynchronize stop VM command: received answer, " + vm.getHostId() + "-" + seq);

    boolean stopped = false;
    if (answer != null && answer.getResult()) stopped = true;

    boolean jobStatusUpdated = false;
    try {
      if (stopped) {
        // completeStopCommand will log the event, if we log it here we will end up with duplicated
        // stop event
        asyncMgr
            .getExecutorContext()
            .getVmMgr()
            .completeStopCommand(
                param.getUserId(), vm, Event.OperationSucceeded, param.getEventId());
        asyncMgr.completeAsyncJob(
            getJob().getId(),
            AsyncJobResult.STATUS_SUCCEEDED,
            0,
            VMExecutorHelper.composeResultObject(
                asyncMgr.getExecutorContext().getManagementServer(), vm, null));
        jobStatusUpdated = true;
      } else {
        asyncMgr
            .getExecutorContext()
            .getItMgr()
            .stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
        asyncMgr.completeAsyncJob(
            getJob().getId(),
            AsyncJobResult.STATUS_FAILED,
            BaseCmd.INTERNAL_ERROR,
            "Agent failed to stop VM");
        jobStatusUpdated = true;

        EventUtils.saveEvent(
            param.getUserId(),
            param.getAccountId(),
            EventVO.LEVEL_ERROR,
            EventTypes.EVENT_VM_STOP,
            "Failed to stop VM instance : " + vm.getName(),
            params,
            param.getEventId());
      }
    } catch (Exception e) {
      s_logger.error("Unexpected exception " + e.getMessage(), e);
      if (!jobStatusUpdated) {
        if (stopped) {
          asyncMgr.completeAsyncJob(
              getJob().getId(),
              AsyncJobResult.STATUS_SUCCEEDED,
              0,
              VMExecutorHelper.composeResultObject(
                  asyncMgr.getExecutorContext().getManagementServer(), vm, null));
        } else {
          asyncMgr.completeAsyncJob(
              getJob().getId(),
              AsyncJobResult.STATUS_FAILED,
              BaseCmd.INTERNAL_ERROR,
              "Agent failed to stop VM");
          EventUtils.saveEvent(
              param.getUserId(),
              param.getAccountId(),
              EventVO.LEVEL_ERROR,
              EventTypes.EVENT_VM_STOP,
              "Failed to stop VM instance : " + vm.getName(),
              params,
              param.getEventId());
        }
      }
    } finally {
      asyncMgr.releaseSyncSource(this);
    }
  }
  public boolean execute() {
    Gson gson = GsonHelper.getBuilder().create();
    AsyncJobManager asyncMgr = getAsyncJobMgr();
    AsyncJobVO job = getJob();
    ManagementServer managementServer = asyncMgr.getExecutorContext().getManagementServer();
    VMOperationParam param = gson.fromJson(job.getCmdInfo(), VMOperationParam.class);
    VmOp oper = param.getOperation();
    VMInstanceVO vm;
    if (getSyncSource() == null) {
      asyncMgr.syncAsyncJobExecution(job.getId(), "SystemVm", param.getVmId());
      return true;
    } else {
      try {
        switch (oper) {
          case Destroy:
            asyncMgr.completeAsyncJob(
                getJob().getId(),
                AsyncJobResult.STATUS_FAILED,
                BaseCmd.UNSUPPORTED_ACTION_ERROR,
                "operation not allowed");
            break;
          case Noop:
            asyncMgr.completeAsyncJob(
                getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, "noop operation");
            break;
          case Start:
            vm = managementServer.startSystemVM(param.getVmId(), param.getEventId());
            if (vm != null)
              asyncMgr.completeAsyncJob(
                  getJob().getId(),
                  AsyncJobResult.STATUS_SUCCEEDED,
                  0,
                  composeResultObject(managementServer, vm));
            else
              asyncMgr.completeAsyncJob(
                  getJob().getId(),
                  AsyncJobResult.STATUS_FAILED,
                  BaseCmd.INTERNAL_ERROR,
                  "operation failed");
            break;
          case Stop:
            boolean result = managementServer.stopSystemVM(param.getVmId(), param.getEventId());
            if (result) {
              vm = managementServer.findSystemVMById(param.getVmId());
              asyncMgr.completeAsyncJob(
                  getJob().getId(),
                  AsyncJobResult.STATUS_SUCCEEDED,
                  0,
                  composeResultObject(managementServer, vm));
            } else {
              asyncMgr.completeAsyncJob(
                  getJob().getId(),
                  AsyncJobResult.STATUS_FAILED,
                  BaseCmd.INTERNAL_ERROR,
                  "operation failed");
            }
            break;
          case Reboot:
            result = managementServer.rebootSystemVM(param.getVmId(), param.getEventId());
            if (result) {
              vm = managementServer.findSystemVMById(param.getVmId());
              asyncMgr.completeAsyncJob(
                  getJob().getId(),
                  AsyncJobResult.STATUS_SUCCEEDED,
                  0,
                  composeResultObject(managementServer, vm));
            } else {
              asyncMgr.completeAsyncJob(
                  getJob().getId(),
                  AsyncJobResult.STATUS_FAILED,
                  BaseCmd.INTERNAL_ERROR,
                  "operation failed");
            }
            break;
          default:
            assert false : "Unknown vm operation";
        }

      } catch (InternalErrorException e) {
        asyncMgr.completeAsyncJob(
            getJob().getId(), AsyncJobResult.STATUS_FAILED, BaseCmd.INTERNAL_ERROR, e.getMessage());
      } catch (Exception e) {
        s_logger.warn("Unable to start console vm " + param.getVmId() + ":" + e.getMessage(), e);
        asyncMgr.completeAsyncJob(
            getJob().getId(), AsyncJobResult.STATUS_FAILED, BaseCmd.INTERNAL_ERROR, e.getMessage());
      }
      return true;
    }
  }