@Test
  public void testAddingPCILunExceedsSlotLimit() {
    mockInterfaceList();
    LunDisk disk = createISCSILunDisk();
    disk.setDiskInterface(DiskInterface.VirtIO);
    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);
    initializeCommand(Guid.newGuid(), parameters);
    when(diskLunMapDao.getDiskIdByLunId(disk.getLun().getLUNId())).thenReturn(null);
    VM vm = mockVm();
    mockMaxPciSlots();

    // use maximum slots for PCI. canDo expected to succeed.
    fillDiskMap(disk, vm, MAX_PCI_SLOTS - 2);
    CanDoActionTestUtils.runAndAssertCanDoActionSuccess(command);

    vm.getDiskMap().put(Guid.newGuid(), disk);
    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.ACTION_TYPE_FAILED_EXCEEDED_MAX_PCI_SLOTS);
  }
  @Test
  public void testCanDoFailOnAddFloatingDiskWithPlugSet() {
    DiskImage disk = createDiskImage(1);

    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);
    parameters.setVmId(Guid.Empty);
    parameters.setPlugDiskToVm(true);

    initializeCommand(null, parameters);

    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.CANNOT_ADD_FLOATING_DISK_WITH_PLUG_VM_SET);
  }
  @Test
  public void testCanDoSuccessOnAddFloatingDiskWithPlugUnset() {
    DiskImage disk = createDiskImage(1);

    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);
    parameters.setVmId(Guid.Empty);
    parameters.setPlugDiskToVm(false);
    Guid storageId = Guid.newGuid();
    initializeCommand(storageId, parameters);
    mockStorageDomain(storageId);
    mockStoragePoolIsoMap();

    CanDoActionTestUtils.runAndAssertCanDoActionSuccess(command);
  }
  @Test
  public void testCanDoFailReadOnlyOnInterface() {
    AddDiskParameters parameters = createParameters();
    initializeCommand(Guid.newGuid(), parameters);
    mockVm();

    doReturn(true).when(command).isDiskPassPciAndIdeLimit(any(Disk.class));
    doReturn(
            new ValidationResult(
                EngineMessage.ACTION_TYPE_FAILED_INTERFACE_DOES_NOT_SUPPORT_READ_ONLY_ATTR))
        .when(diskValidator)
        .isReadOnlyPropertyCompatibleWithInterface();
    doReturn(diskValidator).when(command).getDiskValidator(any(Disk.class));

    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.ACTION_TYPE_FAILED_INTERFACE_DOES_NOT_SUPPORT_READ_ONLY_ATTR);
  }
  @Test
  public void testCanDoSucceedReadOnly() {
    Guid storageId = Guid.newGuid();
    initializeCommand(storageId);

    mockVm();
    mockEntities(storageId);

    doReturn(true).when(command).isDiskPassPciAndIdeLimit(any(Disk.class));
    doReturn(true)
        .when(command)
        .checkIfImageDiskCanBeAdded(any(VM.class), any(DiskValidator.class));
    doReturn(ValidationResult.VALID)
        .when(diskValidator)
        .isReadOnlyPropertyCompatibleWithInterface();
    doReturn(diskValidator).when(command).getDiskValidator(any(Disk.class));

    CanDoActionTestUtils.runAndAssertCanDoActionSuccess(command);
  }
  @Test
  public void testVirtioScsiDiskWithoutControllerCantBeAdded() {
    DiskImage disk = createVirtIoScsiDiskImage();
    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);

    Guid storageId = Guid.newGuid();
    initializeCommand(storageId, parameters);
    mockStorageDomain(storageId);
    mockStoragePoolIsoMap();

    VM vm = mockVm();
    vm.setVdsGroupCompatibilityVersion(Version.v3_3);
    mockMaxPciSlots();

    DiskValidator diskValidator = spyDiskValidator(disk);
    doReturn(false).when(diskValidator).isVirtioScsiControllerAttached(any(Guid.class));

    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.CANNOT_PERFORM_ACTION_VIRTIO_SCSI_IS_DISABLED);
  }
  @Test
  public void testLunDiskValid() {
    VDS vds = mockVds();
    LunDisk disk = createISCSILunDisk();
    disk.setDiskInterface(DiskInterface.VirtIO);

    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);
    parameters.setVdsId(vds.getId());
    initializeCommand(Guid.newGuid(), parameters);
    command.setVds(vds);

    mockVm();
    mockMaxPciSlots();
    mockInterfaceList();

    List<LUNs> luns = Collections.singletonList(disk.getLun());
    doReturn(luns)
        .when(command)
        .executeGetDeviceList(any(Guid.class), any(StorageType.class), (any(String.class)));
    CanDoActionTestUtils.runAndAssertCanDoActionSuccess(command);
  }
  @Test
  public void testDiskImageWithSgioCantBeAdded() {
    DiskImage disk = createVirtIoScsiDiskImage();
    disk.setSgio(ScsiGenericIO.UNFILTERED);

    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);

    Guid storageId = Guid.newGuid();
    initializeCommand(storageId, parameters);
    mockStorageDomain(storageId);
    mockStoragePoolIsoMap();

    VM vm = mockVm();
    vm.setVdsGroupCompatibilityVersion(Version.v3_3);
    mockMaxPciSlots();

    DiskValidator diskValidator = spyDiskValidator(disk);
    doReturn(true).when(diskValidator).isVirtioScsiControllerAttached(any(Guid.class));

    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.SCSI_GENERIC_IO_IS_NOT_SUPPORTED_FOR_IMAGE_DISK);
  }
  @Test
  public void testLunDiskInvalid() {
    VDS vds = mockVds();
    LunDisk disk = createISCSILunDisk();
    disk.setDiskInterface(DiskInterface.VirtIO);

    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);
    parameters.setVdsId(vds.getId());
    initializeCommand(Guid.newGuid(), parameters);
    command.setVds(vds);

    mockVm();
    mockMaxPciSlots();
    mockInterfaceList();

    List<LUNs> luns = Collections.emptyList();
    doReturn(luns)
        .when(command)
        .executeGetDeviceList(any(Guid.class), any(StorageType.class), any(String.class));
    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.ACTION_TYPE_FAILED_DISK_LUN_INVALID);
  }
  @Test
  public void testLunDiskWithSgioCanBeAdded() {
    LunDisk disk = createISCSILunDisk();
    disk.setDiskInterface(DiskInterface.VirtIO_SCSI);
    disk.setSgio(ScsiGenericIO.UNFILTERED);

    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);
    initializeCommand(Guid.newGuid(), parameters);

    VM vm = mockVm();
    vm.setVdsGroupCompatibilityVersion(Version.v3_3);
    mockMaxPciSlots();

    when(osRepository.getDiskInterfaces(any(Integer.class), any(Version.class)))
        .thenReturn(new ArrayList<>(Arrays.asList("VirtIO_SCSI")));

    DiskValidator diskValidator = spyDiskValidator(disk);
    doReturn(true).when(diskValidator).isVirtioScsiControllerAttached(any(Guid.class));

    mockInterfaceList();

    CanDoActionTestUtils.runAndAssertCanDoActionSuccess(command);
  }
  @Test
  public void testVirtIoScsiNotSupportedByOs() {
    DiskImage disk = createVirtIoScsiDiskImage();
    AddDiskParameters parameters = createParameters();
    parameters.setDiskInfo(disk);

    Guid storageId = Guid.newGuid();
    initializeCommand(storageId, parameters);
    mockStorageDomain(storageId);
    mockStoragePoolIsoMap();

    VM vm = mockVm();
    vm.setVdsGroupCompatibilityVersion(Version.v3_3);
    mockMaxPciSlots();

    when(osRepository.getDiskInterfaces(any(Integer.class), any(Version.class)))
        .thenReturn(new ArrayList<>(Arrays.asList("VirtIO")));

    DiskValidator diskValidator = spyDiskValidator(disk);
    doReturn(true).when(diskValidator).isVirtioScsiControllerAttached(any(Guid.class));

    CanDoActionTestUtils.runAndAssertCanDoActionFailure(
        command, EngineMessage.ACTION_TYPE_FAILED_GUEST_OS_VERSION_IS_NOT_SUPPORTED);
  }