private static VDSReturnValue runVdsCommand(
      VDSCommandType vdsCommandType,
      VdsIdVDSCommandParametersBase params,
      Guid storagePoolId,
      CommandBase<?> cmd,
      boolean performFailover) {
    Set<Guid> executedHosts = new HashSet<>();
    VDSReturnValue returnValue = null;
    if (params.getVdsId() == null) {
      chooseHostForExecution(params, storagePoolId, cmd, Collections.emptyList());
      if (params.getVdsId() == null) {
        throw new EngineException(
            EngineError.RESOURCE_MANAGER_VDS_NOT_FOUND,
            "No host was found to perform the operation");
      }
    }

    int attempts = 0;
    while (attempts <= Config.<Integer>getValue(ConfigValues.HsmCommandFailOverRetries)) {
      try {
        attempts++;
        returnValue = getBackend().getResourceManager().runVdsCommand(vdsCommandType, params);
        if (returnValue != null && returnValue.getSucceeded()) {
          return returnValue;
        }
      } catch (EngineException e) {
        returnValue = e.getVdsReturnValue();
      }

      executedHosts.add(params.getVdsId());

      if (!performFailover || (returnValue != null && !returnValue.isCanTryOnDifferentVds())) {
        break;
      }

      chooseHostForExecution(params, storagePoolId, cmd, executedHosts);

      if (params.getVdsId() == null) {
        break;
      }
    }

    return VdsHandler.handleVdsResult(returnValue);
  }
  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);
    }
  }