protected boolean validate() {
    VM vm = parentCommand.getVm();
    if (vm == null) {
      parentCommand.addCanDoActionMessage(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
      return false;
    } else {
      targetCluster = DbFacade.getInstance().getVdsGroupDao().get(targetClusterId);
      if (targetCluster == null) {
        parentCommand.addCanDoActionMessage(EngineMessage.VM_CLUSTER_IS_NOT_VALID);
        return false;
      }

      // Check that the target cluster is in the same data center.
      if (!targetCluster.getStoragePoolId().equals(vm.getStoragePoolId())) {
        parentCommand.addCanDoActionMessage(
            EngineMessage.VM_CANNOT_MOVE_TO_CLUSTER_IN_OTHER_STORAGE_POOL);
        return false;
      }

      List<VmNic> interfaces = DbFacade.getInstance().getVmNicDao().getAllForVm(vm.getId());

      Version clusterCompatibilityVersion = targetCluster.getCompatibilityVersion();
      if (!validateDestinationClusterContainsNetworks(interfaces)
          || !validateNics(interfaces, clusterCompatibilityVersion)) {
        return false;
      }

      // Check if VM static parameters are compatible for new cluster.
      boolean isCpuSocketsValid =
          AddVmCommand.checkCpuSockets(
              vm.getStaticData().getNumOfSockets(),
              vm.getStaticData().getCpuPerSocket(),
              vm.getStaticData().getThreadsPerCpu(),
              clusterCompatibilityVersion.getValue(),
              parentCommand.getReturnValue().getCanDoActionMessages());
      if (!isCpuSocketsValid) {
        return false;
      }

      // Check that the USB policy is legal
      if (!VmHandler.isUsbPolicyLegal(
          vm.getUsbPolicy(),
          vm.getOs(),
          targetCluster,
          parentCommand.getReturnValue().getCanDoActionMessages())) {
        return false;
      }

      // Check if the display type is supported
      if (!VmHandler.isGraphicsAndDisplaySupported(
          vm.getOs(),
          VmDeviceUtils.getGraphicsTypesOfEntity(vm.getId()),
          vm.getDefaultDisplayType(),
          parentCommand.getReturnValue().getCanDoActionMessages(),
          clusterCompatibilityVersion)) {
        return false;
      }

      if (VmDeviceUtils.hasVirtioScsiController(vm.getId())) {
        // Verify cluster compatibility
        if (!FeatureSupported.virtIoScsi(targetCluster.getCompatibilityVersion())) {
          return parentCommand.failCanDoAction(
              EngineMessage.VIRTIO_SCSI_INTERFACE_IS_NOT_AVAILABLE_FOR_CLUSTER_LEVEL);
        }

        // Verify OS compatibility
        if (!VmHandler.isOsTypeSupportedForVirtioScsi(
            vm.getOs(),
            targetCluster.getCompatibilityVersion(),
            parentCommand.getReturnValue().getCanDoActionMessages())) {
          return false;
        }
      }

      // A existing VM cannot be changed into a cluster without a defined architecture
      if (targetCluster.getArchitecture() == ArchitectureType.undefined) {
        return parentCommand.failCanDoAction(
            EngineMessage.ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE);
      } else if (targetCluster.getArchitecture() != vm.getClusterArch()) {
        return parentCommand.failCanDoAction(
            EngineMessage.ACTION_TYPE_FAILED_VM_CLUSTER_DIFFERENT_ARCHITECTURES);
      }
    }
    return true;
  }
  @Override
  protected boolean canDoAction() {
    if (getVdsGroup() == null) {
      return failCanDoAction(EngineMessage.VDS_CLUSTER_IS_NOT_VALID);
    }

    // A Pool cannot be added in a cluster without a defined architecture
    if (getVdsGroup().getArchitecture() == ArchitectureType.undefined) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE);
    }

    VmPool pool = getVmPoolDao().getByName(getParameters().getVmPool().getName());
    if (pool != null
        && (getActionType() == VdcActionType.AddVmPoolWithVms
            || !pool.getVmPoolId().equals(getParameters().getVmPoolId()))) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
    }

    setStoragePoolId(getVdsGroup().getStoragePoolId());
    if (!validate(new StoragePoolValidator(getStoragePool()).isUp())) {
      return false;
    }

    // check if the selected template is compatible with Cluster architecture.
    if (!getVmTemplate().getId().equals(VmTemplateHandler.BLANK_VM_TEMPLATE_ID)
        && getVdsGroup().getArchitecture() != getVmTemplate().getClusterArch()) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_IS_INCOMPATIBLE);
    }

    if (!verifyAddVM()) {
      return false;
    }

    if (getVmTemplate().getDiskTemplateMap().values().size() != diskInfoDestinationMap.size()) {
      log.error(
          "Can not found any default active domain for one of the disks of template with id '{}'",
          getVmTemplate().getId());
      addCanDoActionMessage(EngineMessage.ACTION_TYPE_FAILED_MISSED_STORAGES_FOR_SOME_DISKS);
      return false;
    }

    List<Guid> storageIds = new ArrayList<>();
    for (DiskImage diskImage : diskInfoDestinationMap.values()) {
      Guid storageId = diskImage.getStorageIds().get(0);
      if (!storageIds.contains(storageId) && !areTemplateImagesInStorageReady(storageId)) {
        return false;
      }
      storageIds.add(storageId);
    }

    if (getActionType() == VdcActionType.AddVmPoolWithVms && getParameters().getVmsCount() < 1) {
      return failCanDoAction(EngineMessage.VM_POOL_CANNOT_CREATE_WITH_NO_VMS);
    }

    if (getParameters().getVmStaticData().isStateless()) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_FROM_POOL_CANNOT_BE_STATELESS);
    }

    if (getParameters().getVmPool().getPrestartedVms()
        > getParameters().getVmPool().getAssignedVmsCount() + getParameters().getVmsCount()) {
      return failCanDoAction(
          EngineMessage.ACTION_TYPE_FAILED_PRESTARTED_VMS_CANNOT_EXCEED_VMS_COUNT);
    }

    if (Boolean.TRUE.equals(getParameters().isVirtioScsiEnabled())
        && !FeatureSupported.virtIoScsi(getVdsGroup().getCompatibilityVersion())) {
      return failCanDoAction(
          EngineMessage.VIRTIO_SCSI_INTERFACE_IS_NOT_AVAILABLE_FOR_CLUSTER_LEVEL);
    }
    if (!setAndValidateDiskProfiles()) {
      return false;
    }
    if (!setAndValidateCpuProfile()) {
      return false;
    }
    return checkDestDomains();
  }