public static List<LunDisk> filterDiskBasedOnLuns(
     Collection<? extends Disk> listOfDisks, boolean allowShareableDisks) {
   List<LunDisk> lunDisks = new ArrayList<>();
   for (Disk disk : listOfDisks) {
     if (disk.getDiskStorageType() == DiskStorageType.LUN
         && (allowShareableDisks || !disk.isShareable())) {
       lunDisks.add((LunDisk) disk);
     }
   }
   return lunDisks;
 }
 /**
  * Filter image disks by attributes.
  *
  * @param listOfDisks - The list of disks to be filtered.
  * @param allowOnlyNotShareableDisks - Indication whether to allow only disks that are not
  *     shareable
  * @param allowOnlySnapableDisks - Indication whether to allow only disks which are allowed to be
  *     snapshoted.
  * @param allowOnlyActiveDisks - Indication whether to allow only disks that are not disk
  *     snapshots.
  * @return - List filtered of disk images according to the given filters.
  */
 public static List<DiskImage> filterImageDisks(
     Collection<? extends Disk> listOfDisks,
     boolean allowOnlyNotShareableDisks,
     boolean allowOnlySnapableDisks,
     boolean allowOnlyActiveDisks) {
   List<DiskImage> diskImages = new ArrayList<>();
   for (Disk disk : listOfDisks) {
     if (disk.getDiskStorageType() == DiskStorageType.IMAGE
         && (!allowOnlyNotShareableDisks || !disk.isShareable())
         && (!allowOnlySnapableDisks || disk.isAllowSnapshot())
         && (!allowOnlyActiveDisks || Boolean.TRUE.equals(((DiskImage) disk).getActive()))) {
       diskImages.add((DiskImage) disk);
     }
   }
   return diskImages;
 }
  @Override
  protected Map<String, Pair<String, String>> getExclusiveLocks() {
    if (disk == null) {
      return null;
    }

    Map<String, Pair<String, String>> locks = new HashMap<>();
    if (!disk.isShareable()) {
      locks.put(
          disk.getId().toString(),
          LockMessagesMatchUtil.makeLockingPair(
              LockingGroup.DISK, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));
    }

    if (disk.isBoot()) {
      locks.put(
          getParameters().getVmId().toString(),
          LockMessagesMatchUtil.makeLockingPair(
              LockingGroup.VM_DISK_BOOT, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));
    }

    return locks;
  }
  @Override
  protected boolean canDoAction() {
    if (disk == null) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_IMAGE_DOES_NOT_EXIST);
    }

    DiskValidator oldDiskValidator = new DiskValidator(disk);
    ValidationResult isHostedEngineDisk = oldDiskValidator.validateNotHostedEngineDisk();
    if (!isHostedEngineDisk.isValid()) {
      return validate(isHostedEngineDisk);
    }

    disk.setReadOnly(getParameters().isReadOnly());
    DiskValidator diskValidator = getDiskValidator(disk);

    if (!checkDiskUsedAsOvfStore(diskValidator)) {
      return false;
    }

    if (isOperationPerformedOnDiskSnapshot()
        && (!validate(getSnapshotsValidator().snapshotExists(getSnapshot()))
            || !validate(
                getSnapshotsValidator()
                    .snapshotTypeSupported(
                        getSnapshot(), Collections.singletonList(SnapshotType.REGULAR))))) {
      return false;
    }

    boolean isImageDisk = disk.getDiskStorageType().isInternal();

    if (isImageDisk) {
      // TODO : this load and check of the active disk will be removed
      // after inspecting upgrade
      Disk activeDisk = loadActiveDisk(disk.getId());

      if (((DiskImage) activeDisk).getImageStatus() == ImageStatus.ILLEGAL) {
        return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_ILLEGAL_DISK_OPERATION);
      }

      if (((DiskImage) disk).getImageStatus() == ImageStatus.LOCKED) {
        addCanDoActionMessage(EngineMessage.ACTION_TYPE_FAILED_DISKS_LOCKED);
        addCanDoActionMessageVariable("diskAliases", disk.getDiskAlias());
        return false;
      }
    }

    if (!isVmExist() || !isVmInUpPausedDownStatus()) {
      return false;
    }

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

    updateDisksFromDb();
    if (!isDiskCanBeAddedToVm(disk, getVm()) || !isDiskPassPciAndIdeLimit(disk)) {
      return false;
    }

    if (getVmDeviceDao().exists(new VmDeviceId(disk.getId(), getVmId()))) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_DISK_ALREADY_ATTACHED);
    }

    if (disk.isShareable()
        && !isVersionSupportedForShareable(
            disk,
            getStoragePoolDao()
                .get(getVm().getStoragePoolId())
                .getCompatibilityVersion()
                .getValue())) {
      return failCanDoAction(EngineMessage.ACTION_NOT_SUPPORTED_FOR_CLUSTER_POOL_LEVEL);
    }

    if (!isOperationPerformedOnDiskSnapshot() && !disk.isShareable() && disk.getNumberOfVms() > 0) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_NOT_SHAREABLE_DISK_ALREADY_ATTACHED);
    }

    if (isImageDisk
        && getStoragePoolIsoMapDao()
                .get(
                    new StoragePoolIsoMapId(
                        ((DiskImage) disk).getStorageIds().get(0), getVm().getStoragePoolId()))
            == null) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_NOT_MATCH);
    }
    if (isImageDisk) {
      StorageDomain storageDomain =
          getStorageDomainDao()
              .getForStoragePool(
                  ((DiskImage) disk).getStorageIds().get(0), ((DiskImage) disk).getStoragePoolId());
      StorageDomainValidator storageDomainValidator = getStorageDomainValidator(storageDomain);
      if (!validate(storageDomainValidator.isDomainExistAndActive())) {
        return false;
      }
    }

    if (!validate(diskValidator.isReadOnlyPropertyCompatibleWithInterface())) {
      return false;
    }

    if (!validate(diskValidator.isVirtIoScsiValid(getVm()))) {
      return false;
    }

    if (!validate(diskValidator.isDiskInterfaceSupported(getVm()))) {
      return false;
    }

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

    if (getParameters().isPlugUnPlug() && getVm().getStatus() != VMStatus.Down) {
      return canPerformDiskHotPlug(disk);
    }
    return true;
  }