Vered Volansky has uploaded a new change for review.

Change subject: core: ImportVmCommand storage allocation checks
......................................................................

core: ImportVmCommand storage allocation checks

This patch is a part of a series of patches, adding storage allocation
validations to the system when they're missing, and replacing old
verification usage with unified, new, correct and tested verification.
This patch did this for ImportVmCommand, while added new space allocation
validation to storage domain validators regarding snapshoted disks to be
cloned with the spnapshots. Tests were amended accordingly.

Change-Id: Ifbb1d985f9afa476452d1d2b78be1fd18c128c8f
Bug-Url: https://bugzilla.redhat.com/1053746
Signed-off-by: Vered Volansky <vvola...@redhat.com>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MoveOrCopyTemplateCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidator.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/StorageDomainValidator.java
M 
backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ImportVmCommandTest.java
M 
backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidatorTest.java
M 
backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/StorageDomainValidatorFreeSpaceTest.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/DiskImageBase.java
9 files changed, 322 insertions(+), 62 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/98/32898/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
index 8bfaf4e..d29ed85 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
@@ -816,4 +816,11 @@
         }
         return snapshot;
     }
+
+    public static DiskImage createDiskImageWithExcessData(DiskImage diskImage, 
Guid sdId) {
+        DiskImage dummy = DiskImage.copyOf(diskImage);
+        dummy.setStorageIds(new 
ArrayList<Guid>(Collections.singletonList(sdId)));
+        
dummy.getSnapshots().addAll(ImagesHandler.getAllImageSnapshots(dummy.getImageId()));
+        return dummy;
+    }
 }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java
index 79b902f..11bbfcc 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportVmCommand.java
@@ -417,16 +417,8 @@
         }
 
         if (!isImagesAlreadyOnTarget()) {
-            Map<StorageDomain, Integer> domainMap = 
getSpaceRequirementsForStorageDomains(imageList);
-
-            if (!setDomainsForMemoryImages(domainMap)) {
-                return 
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_NO_SUITABLE_DOMAIN_FOUND);
-            }
-
-            for (Map.Entry<StorageDomain, Integer> entry : 
domainMap.entrySet()) {
-                if (!doesStorageDomainhaveSpaceForRequest(entry.getKey(), 
entry.getValue())) {
-                    return false;
-                }
+            if (!handleDestStorageDomains()) {
+                return false;
             }
         }
 
@@ -457,16 +449,32 @@
         return true;
     }
 
+    protected boolean handleDestStorageDomains() {
+        List<DiskImage> dummiesDisksList = 
createDiskDummiesForSpaceValidations(imageList);
+        if (getParameters().getCopyCollapse()) {
+            Snapshot activeSnapshot = getActiveSnapshot();
+            if (activeSnapshot != null && activeSnapshot.containsMemory()) {
+                //Checking space for memory volume of the active image (if 
there is one)
+                StorageDomain storageDomain = 
updateStorageDomainInMemoryVolumes(dummiesDisksList);
+                if (storageDomain == null) {
+                    return 
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_NO_SUITABLE_DOMAIN_FOUND);
+                }
+            }
+        } else { //Check space for all the snapshot's memory volumes
+            if (!updateDomainsForMemoryImages(dummiesDisksList)) {
+                return false;
+            }
+        }
+        return validateSpaceRequirements(dummiesDisksList);
+    }
+
     /**
-     * This method fills the given map of domain to the required size for 
storing memory images
-     * within it, and also update the memory volume in each snapshot that has 
memory volume with
-     * the right storage pool and storage domain where it is going to be 
imported.
+     * For each snapshot that has memory volume, this method updates the 
memory volume with
+     * the storage pool and storage domain it's going to be imported to.
      *
-     * @param domain2requiredSize
-     *           Maps domain to size required for storing memory volumes in it
      * @return true if we managed to assign storage domain for every memory 
volume, false otherwise
      */
-    private boolean setDomainsForMemoryImages(Map<StorageDomain, Integer> 
domain2requiredSize) {
+    private boolean updateDomainsForMemoryImages(List<DiskImage> disksList) {
         Map<String, String> handledMemoryVolumes = new HashMap<String, 
String>();
         for (Snapshot snapshot : getVm().getSnapshots()) {
             String memoryVolume = snapshot.getMemoryVolume();
@@ -480,17 +488,10 @@
                 continue;
             }
 
-            VM vm = getVmFromSnapshot(snapshot);
-            int requiredSizeForMemory = (int) 
Math.ceil((vm.getTotalMemorySizeInBytes() +
-                    MemoryUtils.META_DATA_SIZE_IN_BYTES) * 1.0 / BYTES_IN_GB);
-            StorageDomain storageDomain = VmHandler.findStorageDomainForMemory(
-                    getParameters().getStoragePoolId(), requiredSizeForMemory, 
domain2requiredSize);
+            StorageDomain storageDomain = 
updateStorageDomainInMemoryVolumes(disksList);
             if (storageDomain == null) {
-                return false;
+                return 
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_NO_SUITABLE_DOMAIN_FOUND);
             }
-            int requiredSizeInDomainIncludingMemoryVolumes = 
domain2requiredSize.containsKey(storageDomain) ?
-                    domain2requiredSize.get(storageDomain) + 
requiredSizeForMemory : requiredSizeForMemory;
-            domain2requiredSize.put(storageDomain, 
requiredSizeInDomainIncludingMemoryVolumes);
             String modifiedMemoryVolume = 
MemoryUtils.changeStorageDomainAndPoolInMemoryState(
                     memoryVolume, storageDomain.getId(), 
getParameters().getStoragePoolId());
             // replace the volume representation with the one with the correct 
domain & pool
@@ -499,6 +500,13 @@
             handledMemoryVolumes.put(memoryVolume, modifiedMemoryVolume);
         }
         return true;
+    }
+
+    private StorageDomain updateStorageDomainInMemoryVolumes(List<DiskImage> 
disksList) {
+        List<DiskImage> memoryDisksList = 
MemoryUtils.createDiskDummies(getVm().getTotalMemorySizeInBytes(), 
MemoryUtils.META_DATA_SIZE_IN_BYTES);
+        StorageDomain storageDomain = 
VmHandler.findStorageDomainForMemory(getParameters().getStoragePoolId(), 
memoryDisksList);
+        disksList.addAll(memoryDisksList);
+        return storageDomain;
     }
 
     /**
@@ -959,12 +967,20 @@
     }
 
     private String getMemoryVolumeFromActiveSnapshotInExportDomain() {
+        Snapshot activeSnapshot = getActiveSnapshot();
+        if (activeSnapshot != null) {
+            return activeSnapshot.getMemoryVolume();
+        }
+        return StringUtils.EMPTY;
+    }
+
+    private Snapshot getActiveSnapshot() {
         for (Snapshot snapshot : getVm().getSnapshots()) {
             if (snapshot.getType() == SnapshotType.ACTIVE)
-                return snapshot.getMemoryVolume();
+                return snapshot;
         }
         log.warnFormat("VM {0} doesn't have active snapshot in export domain", 
getVmId());
-        return StringUtils.EMPTY;
+        return null;
     }
 
     /**
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MoveOrCopyTemplateCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MoveOrCopyTemplateCommand.java
index 727c329..f47c63e 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MoveOrCopyTemplateCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MoveOrCopyTemplateCommand.java
@@ -16,6 +16,7 @@
 import org.ovirt.engine.core.bll.storage.StorageDomainCommandBase;
 import org.ovirt.engine.core.bll.utils.PermissionSubject;
 import org.ovirt.engine.core.bll.utils.VmDeviceUtils;
+import org.ovirt.engine.core.bll.validator.MultipleStorageDomainsValidator;
 import org.ovirt.engine.core.bll.validator.StorageDomainValidator;
 import org.ovirt.engine.core.common.AuditLogType;
 import org.ovirt.engine.core.common.VdcObjectType;
@@ -360,6 +361,42 @@
         return 
StorageDomainValidator.getSpaceRequirementsForStorageDomains(spaceMap);
     }
 
+    /**
+     * Space Validations are done using data extracted from the disks. The 
disks in question in this command
+     * don't have all the needed data, and in order not to contaminate the 
command's data structures, as alter
+     * one is created specifically fo this validation - hence dummy.
+     * @param disksList
+     * @return
+     */
+    protected List<DiskImage> 
createDiskDummiesForSpaceValidations(List<DiskImage> disksList) {
+        List<DiskImage> dummies = new ArrayList<>(disksList.size());
+        for (DiskImage image : disksList) {
+            Guid targetSdId = imageToDestinationDomainMap.get(image.getId());
+            DiskImage dummy = 
ImagesHandler.createDiskImageWithExcessData(image, targetSdId);
+            dummies.add(dummy);
+        }
+        return dummies;
+    }
+
+    protected boolean validateSpaceRequirements(List<DiskImage> disksList) {
+        MultipleStorageDomainsValidator sdValidator = 
createMultipleStorageDomainsValidator(disksList);
+        if (!validate(sdValidator.allDomainsExistAndActive())
+                || !validate(sdValidator.allDomainsWithinThresholds())) {
+            return false;
+        }
+
+        if (getParameters().getCopyCollapse()) {
+            return 
validate(sdValidator.allDomainsHaveSpaceForClonedDisks(disksList));
+        }
+
+        return 
validate(sdValidator.allDomainsHaveSpaceForDisksWithSnapshots(disksList));
+    }
+
+    protected MultipleStorageDomainsValidator 
createMultipleStorageDomainsValidator( List<DiskImage> disksList) {
+        return new MultipleStorageDomainsValidator(getStoragePoolId(),
+                ImagesHandler.getAllStorageIdsForImageIds(disksList));
+    }
+
     protected void ensureDomainMap(Collection<DiskImage> images, Guid 
defaultDomainId) {
         if (imageToDestinationDomainMap == null) {
             imageToDestinationDomainMap = new HashMap<Guid, Guid>();
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidator.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidator.java
index 84407f9..cb72ce2 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidator.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidator.java
@@ -100,6 +100,23 @@
      * Validates that all the domains have enough space for the request
      * @return {@link ValidationResult#VALID} if all the domains have enough 
free space, or a {@link ValidationResult} with the first low-on-space domain 
encountered.
      */
+    public ValidationResult allDomainsHaveSpaceForClonedDisks(List<DiskImage> 
disksList) {
+        final Map<Guid, List<DiskImage>> disksMap = 
getDomainsDisksMap(disksList);
+
+        return validOrFirstFailure(new ValidatorPredicate() {
+            @Override
+            public ValidationResult evaluate(Map.Entry<Guid, 
StorageDomainValidator> entry) {
+                Guid sdId = entry.getKey();
+                List<DiskImage> disksList = disksMap.get(sdId);
+                return 
getStorageDomainValidator(entry).hasSpaceForClonedDisks(disksList);
+            }
+        });
+    }
+
+    /**
+     * Validates that all the domains have enough space for the request
+     * @return {@link ValidationResult#VALID} if all the domains have enough 
free space, or a {@link ValidationResult} with the first low-on-space domain 
encountered.
+     */
     public ValidationResult allDomainsHaveSpaceForAllDisks(List<DiskImage> 
newDisksList, List<DiskImage> clonedDisksList) {
         final Map<Guid, List<DiskImage>> domainsNewDisksMap = 
getDomainsDisksMap(newDisksList);
         final Map<Guid, List<DiskImage>> domainsClonedDisksMap = 
getDomainsDisksMap(clonedDisksList);
@@ -115,6 +132,23 @@
         });
     }
 
+    /**
+     * Validates that all the domains have enough space for the request
+     * @return {@link ValidationResult#VALID} if all the domains have enough 
free space, or a {@link ValidationResult} with the first low-on-space domain 
encountered.
+     */
+    public ValidationResult 
allDomainsHaveSpaceForDisksWithSnapshots(List<DiskImage> disksList) {
+        final Map<Guid, List<DiskImage>> disksMap = 
getDomainsDisksMap(disksList);
+
+        return validOrFirstFailure(new ValidatorPredicate() {
+            @Override
+            public ValidationResult evaluate(Map.Entry<Guid, 
StorageDomainValidator> entry) {
+                Guid sdId = entry.getKey();
+                List<DiskImage> disksList = disksMap.get(sdId);
+                return 
getStorageDomainValidator(entry).hasSpaceForDisksWithSnapshots(disksList);
+            }
+        });
+    }
+
     /** @return The lazy-loaded validator for the given map entry */
     protected StorageDomainValidator getStorageDomainValidator(Map.Entry<Guid, 
StorageDomainValidator> entry) {
         if (entry.getValue() == null) {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/StorageDomainValidator.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/StorageDomainValidator.java
index d7552de..1736afc 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/StorageDomainValidator.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/StorageDomainValidator.java
@@ -131,11 +131,10 @@
      *
      */
     private double getTotalSizeForNewDisks(Collection<DiskImage> diskImages) {
-        double totalSizeForDisks = 0.0;
-        if (diskImages != null) {
-            for (DiskImage diskImage : diskImages) {
-                double sizeForDisk = diskImage.getSize();
-
+        return getTotalSizeForDisksByMethod(diskImages, new SizeAssessment() {
+            @Override
+            public double getSizeForDisk(DiskImage diskImage) {
+                double sizeForDisk = diskImage.getCapacity();
                 if (diskImage.getVolumeFormat() == VolumeFormat.COW) {
                     if (storageDomain.getStorageType().isFileDomain()) {
                         sizeForDisk = EMPTY_QCOW_HEADER_SIZE;
@@ -145,10 +144,9 @@
                 } else if (diskImage.getVolumeType() == VolumeType.Sparse) {
                     sizeForDisk = EMPTY_QCOW_HEADER_SIZE;
                 }
-                totalSizeForDisks += sizeForDisk;
+                return sizeForDisk;
             }
-        }
-        return totalSizeForDisks;
+        });
     }
 
     /**
@@ -166,25 +164,53 @@
      *
      * */
     private double getTotalSizeForClonedDisks(Collection<DiskImage> 
diskImages) {
-        double totalSizeForDisks = 0.0;
-        if (diskImages != null) {
-            for (DiskImage diskImage : diskImages) {
-                double diskCapacity = diskImage.getSize();
-                double sizeForDisk = diskCapacity;
-
+        return getTotalSizeForDisksByMethod(diskImages, new SizeAssessment() {
+            @Override
+            public double getSizeForDisk(DiskImage diskImage) {
+                double sizeForDisk = diskImage.getCapacity();
                 if ((storageDomain.getStorageType().isFileDomain() && 
diskImage.getVolumeType() == VolumeType.Sparse) ||
                         storageDomain.getStorageType().isBlockDomain() && 
diskImage.getVolumeFormat() == VolumeFormat.COW) {
-                    double usedSapce = 
diskImage.getActualDiskWithSnapshotsSizeInBytes();
-                    sizeForDisk = Math.min(diskCapacity, usedSapce);
+                    double usedSpace = 
diskImage.getActualDiskWithSnapshotsSizeInBytes();
+                    sizeForDisk = Math.min(diskImage.getCapacity(), usedSpace);
                 }
 
                 if (diskImage.getVolumeFormat() == VolumeFormat.COW) {
                     sizeForDisk = Math.ceil(QCOW_OVERHEAD_FACTOR * 
sizeForDisk);
                 }
-                totalSizeForDisks += sizeForDisk;
+                return sizeForDisk;
             }
-        }
-        return totalSizeForDisks;
+        });
+    }
+
+    /**
+     * Verify there's enough space in the storage domain for creating cloned 
DiskImages with snapshots without collapse.
+     * Space should be allocated according to the volumes type and format, and 
allocation policy,
+     * according to the following table:
+     *
+     *      | File Domain                             | Block Domain
+     * -----|-----------------------------------------|----------------
+     * qcow | 1.1 * used space                        |1.1 * used space
+     * -----|-----------------------------------------|----------------
+     * raw  | preallocated: disk capacity             |disk capacity
+     *      | sparse: used space                      |
+     *
+     * */
+    private double getTotalSizeForDisksWithSnapshots(Collection<DiskImage> 
diskImages) {
+        return getTotalSizeForDisksByMethod(diskImages, new SizeAssessment() {
+            @Override
+            public double getSizeForDisk(DiskImage diskImage) {
+                double sizeForDisk = diskImage.getCapacity();
+                if ((storageDomain.getStorageType().isFileDomain() && 
diskImage.getVolumeType() == VolumeType.Sparse)
+                    || diskImage.getVolumeFormat() == VolumeFormat.COW) {
+                    sizeForDisk = 
diskImage.getActualDiskWithSnapshotsSizeInBytes();
+                }
+
+                if (diskImage.getVolumeFormat() == VolumeFormat.COW) {
+                    sizeForDisk = Math.ceil(QCOW_OVERHEAD_FACTOR * 
sizeForDisk);
+                }
+                return sizeForDisk;
+            }
+        });
     }
 
     public ValidationResult hasSpaceForNewDisks(Collection<DiskImage> 
diskImages) {
@@ -201,6 +227,13 @@
         return validateRequiredSpace(availableSize, totalSizeForDisks);
     }
 
+    public ValidationResult 
hasSpaceForDisksWithSnapshots(Collection<DiskImage> diskImages) {
+        double availableSize = storageDomain.getAvailableDiskSizeInBytes();
+        double totalSizeForDisks = 
getTotalSizeForDisksWithSnapshots(diskImages);
+
+        return validateRequiredSpace(availableSize, totalSizeForDisks);
+    }
+
     public ValidationResult hasSpaceForAllDisks(Collection<DiskImage> 
newDiskImages, Collection<DiskImage> clonedDiskImages) {
         double availableSize = storageDomain.getAvailableDiskSizeInBytes();
         double totalSizeForNewDisks = getTotalSizeForNewDisks(newDiskImages);
@@ -208,6 +241,10 @@
         double totalSizeForDisks = totalSizeForNewDisks + 
totalSizeForClonedDisks;
 
         return validateRequiredSpace(availableSize, totalSizeForDisks);
+    }
+
+    public ValidationResult hasSpaceForDiskWithSnapshots(DiskImage diskImage) {
+        return hasSpaceForDisksWithSnapshots(Collections.singleton(diskImage));
     }
 
     public ValidationResult hasSpaceForClonedDisk(DiskImage diskImage) {
@@ -289,4 +326,25 @@
 
         return isDomainHasSpaceForRequest(Math.min(maxVirtualSize, 
sumOfActualSizes), false);
     }
+
+    /**
+     * Validates all the storage domains by a given predicate.
+     *
+     * @return {@link ValidationResult#VALID} if all the domains are OK, or the
+     * first validation error if they aren't.
+     */
+    private double getTotalSizeForDisksByMethod(Collection<DiskImage> 
diskImages, SizeAssessment sizeAssessment) {
+        double totalSizeForDisks = 0.0;
+        if (diskImages != null) {
+            for (DiskImage diskImage : diskImages) {
+                double sizeForDisk = sizeAssessment.getSizeForDisk(diskImage);
+                totalSizeForDisks += sizeForDisk;
+            }
+        }
+        return totalSizeForDisks;
+    }
+
+    private static interface SizeAssessment {
+        public double getSizeForDisk(DiskImage diskImage);
+    }
 }
diff --git 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ImportVmCommandTest.java
 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ImportVmCommandTest.java
index e2a9ef3..6326ad3 100644
--- 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ImportVmCommandTest.java
+++ 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ImportVmCommandTest.java
@@ -6,10 +6,13 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyList;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig;
 
@@ -30,12 +33,14 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.ovirt.engine.core.bll.validator.MultipleStorageDomainsValidator;
 import org.ovirt.engine.core.common.action.ImportVmParameters;
 import 
org.ovirt.engine.core.common.businessentities.BusinessEntitiesDefinitions;
 import org.ovirt.engine.core.common.businessentities.Disk;
 import org.ovirt.engine.core.common.businessentities.DiskImage;
 import org.ovirt.engine.core.common.businessentities.DiskInterface;
 import org.ovirt.engine.core.common.businessentities.DisplayType;
+import org.ovirt.engine.core.common.businessentities.ImageStatus;
 import org.ovirt.engine.core.common.businessentities.Snapshot;
 import org.ovirt.engine.core.common.businessentities.StorageDomain;
 import org.ovirt.engine.core.common.businessentities.StorageDomainStatus;
@@ -70,6 +75,9 @@
     @Mock
     OsRepository osRepository;
 
+    @Mock
+    private MultipleStorageDomainsValidator multipleSdValidator;
+
     @Before
     public void setUp() {
         // init the injector with the osRepository instance
@@ -84,26 +92,52 @@
     }
 
     @Test
-    public void insufficientDiskSpace() {
-        final int lotsOfSpace = 1073741824;
-        final ImportVmCommand<ImportVmParameters> c = 
setupDiskSpaceTest(lotsOfSpace);
-        assertFalse(c.canDoAction());
-        assertTrue(c.getReturnValue()
-                .getCanDoActionMessages()
-                
.contains(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN.toString()));
+    public void insufficientDiskSpaceWithCollapse() {
+        final ImportVmCommand<ImportVmParameters> command = 
setupDiskSpaceTest(createParameters());
+        doReturn(new 
ValidationResult(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN)).
+                
when(multipleSdValidator).allDomainsHaveSpaceForClonedDisks(anyList());
+        CanDoActionTestUtils.runAndAssertCanDoActionFailure(command,
+                
VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN);
+        
verify(multipleSdValidator).allDomainsHaveSpaceForClonedDisks(anyList());
+        verify(multipleSdValidator, 
never()).allDomainsHaveSpaceForDisksWithSnapshots(anyList());
+        verify(multipleSdValidator, 
never()).allDomainsHaveSpaceForNewDisks(anyList());
+    }
+
+    @Test
+    public void insufficientDiskSpaceWithSnapshots() {
+        ImportVmParameters parameters = createParameters();
+        final ImportVmCommand<ImportVmParameters> command = 
setupDiskSpaceTest(parameters);
+        parameters.setCopyCollapse(false);
+        doReturn(new 
ValidationResult(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN)).
+                
when(multipleSdValidator).allDomainsHaveSpaceForDisksWithSnapshots(anyList());
+        CanDoActionTestUtils.runAndAssertCanDoActionFailure(command,
+                
VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN);
+        verify(multipleSdValidator, 
never()).allDomainsHaveSpaceForClonedDisks(anyList());
+        
verify(multipleSdValidator).allDomainsHaveSpaceForDisksWithSnapshots(anyList());
+        verify(multipleSdValidator, 
never()).allDomainsHaveSpaceForNewDisks(anyList());
     }
 
     @Test
     public void sufficientDiskSpace() {
-        final int extraDiskSpaceRequired = 0;
-        final ImportVmCommand<ImportVmParameters> c = 
setupDiskSpaceTest(extraDiskSpaceRequired);
-        assertTrue(c.canDoAction());
+        final ImportVmCommand<ImportVmParameters> command = 
setupDiskSpaceTest(createParameters());
+        CanDoActionTestUtils.runAndAssertCanDoActionSuccess(command);
+        
verify(multipleSdValidator).allDomainsHaveSpaceForClonedDisks(anyList());
+        verify(multipleSdValidator, 
never()).allDomainsHaveSpaceForDisksWithSnapshots(anyList());
+        verify(multipleSdValidator, 
never()).allDomainsHaveSpaceForNewDisks(anyList());
     }
 
-    private ImportVmCommand<ImportVmParameters> setupDiskSpaceTest(final int 
diskSpaceRequired) {
-        mcr.mockConfigValue(ConfigValues.FreeSpaceCriticalLowInGB, 
diskSpaceRequired);
+    @Test
+    public void lowThresholdStorageSpace() {
+        final ImportVmCommand<ImportVmParameters> command = 
setupDiskSpaceTest(createParameters());
+        doReturn(new 
ValidationResult(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN)).
+                when(multipleSdValidator).allDomainsWithinThresholds();
+        CanDoActionTestUtils.runAndAssertCanDoActionFailure(command,
+                
VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN);
+    }
 
-        ImportVmCommand<ImportVmParameters> cmd = spy(new 
ImportVmCommand<ImportVmParameters>(createParameters()));
+    private ImportVmCommand<ImportVmParameters> 
setupDiskSpaceTest(ImportVmParameters parameters) {
+        ImportVmCommand<ImportVmParameters> cmd = spy(new 
ImportVmCommand<ImportVmParameters>(parameters));
+        parameters.setCopyCollapse(true);
         doReturn(true).when(cmd).validateNoDuplicateVm();
         doReturn(true).when(cmd).validateVdsCluster();
         doReturn(true).when(cmd).validateUsbPolicy();
@@ -120,6 +154,17 @@
         doReturn(new StoragePool()).when(cmd).getStoragePool();
         doReturn(new VDSGroup()).when(cmd).getVdsGroup();
 
+        ArrayList<Guid> sdIds = new 
ArrayList<Guid>(Collections.singletonList(Guid.newGuid()));
+        for (DiskImage image : parameters.getVm().getImages()) {
+            image.setStorageIds(sdIds);
+        }
+
+        
doReturn(mockCreateDiskDummiesForSpaceValidations()).when(cmd).createDiskDummiesForSpaceValidations(anyList());
+        
doReturn(multipleSdValidator).when(cmd).createMultipleStorageDomainsValidator(anyList());
+        
doReturn(ValidationResult.VALID).when(multipleSdValidator).allDomainsHaveSpaceForClonedDisks(anyList());
+        
doReturn(ValidationResult.VALID).when(multipleSdValidator).allDomainsHaveSpaceForDisksWithSnapshots(anyList());
+        
doReturn(ValidationResult.VALID).when(multipleSdValidator).allDomainsWithinThresholds();
+        
doReturn(ValidationResult.VALID).when(multipleSdValidator).allDomainsExistAndActive();
         return cmd;
     }
 
@@ -169,6 +214,20 @@
         sd.setStatus(StorageDomainStatus.Active);
         sd.setAvailableDiskSize(2);
         return sd;
+    }
+
+    protected List<DiskImage> mockCreateDiskDummiesForSpaceValidations() {
+        List<DiskImage> disksList = new ArrayList<>();
+        for (int i = 0; i < 3; ++i) {
+            DiskImage diskImage = new DiskImage();
+            diskImage.setActive(false);
+            diskImage.setId(Guid.newGuid());
+            diskImage.setImageId(Guid.newGuid());
+            diskImage.setParentId(Guid.newGuid());
+            diskImage.setImageStatus(ImageStatus.OK);
+            disksList.add(diskImage);
+        }
+        return disksList;
     }
 
     @Test
@@ -325,7 +384,7 @@
 
     @Test
     public void testValidateClusterSupportForVirtioScsi() {
-        ImportVmCommand<ImportVmParameters> cmd = setupDiskSpaceTest(0);
+        ImportVmCommand<ImportVmParameters> cmd = 
setupDiskSpaceTest(createParameters());
         
cmd.getParameters().getVm().getDiskMap().values().iterator().next().setDiskInterface(DiskInterface.VirtIO_SCSI);
         cmd.getVdsGroup().setcompatibility_version(Version.v3_2);
         CanDoActionTestUtils.runAndAssertCanDoActionFailure(cmd,
diff --git 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidatorTest.java
 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidatorTest.java
index 56249af..1d0d0ef 100644
--- 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidatorTest.java
+++ 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/MultipleStorageDomainsValidatorTest.java
@@ -145,6 +145,36 @@
     }
 
     @Test
+    public void testAllDomainsHaveSpaceForClonedDisksSuccess(){
+        List<Guid> sdIds = Arrays.asList(sdId1, sdId2);
+        List<DiskImage> disksList = generateDisksList(NUM_DISKS, sdIds);
+
+        StorageDomainValidator storageDomainValidator = 
mock(StorageDomainValidator.class);
+        
doReturn(ValidationResult.VALID).when(storageDomainValidator).hasSpaceForClonedDisks(anyList());
+        
doReturn(storageDomainValidator).when(validator).getStorageDomainValidator(any(Map.Entry.class));
+
+        
assertTrue(validator.allDomainsHaveSpaceForClonedDisks(disksList).isValid());
+        verify(storageDomainValidator, 
times(NUM_DOMAINS)).hasSpaceForClonedDisks(anyList());
+    }
+
+    @Test
+    public void testAllDomainsHaveSpaceForClonedDisksFail(){
+        List<Guid> sdIds = Arrays.asList(sdId1, sdId2);
+        List<DiskImage> disksList = generateDisksList(NUM_DISKS, sdIds);
+
+        StorageDomainValidator storageDomainValidator = 
mock(StorageDomainValidator.class);
+        doReturn(new 
ValidationResult(VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN)).
+                when(storageDomainValidator).hasSpaceForClonedDisks(anyList());
+        
doReturn(storageDomainValidator).when(validator).getStorageDomainValidator(any(Map.Entry.class));
+
+        ValidationResult result = 
validator.allDomainsHaveSpaceForClonedDisks(disksList);
+        assertFalse(result.isValid());
+        assertEquals("Wrong validation error",
+                
VdcBllMessages.ACTION_TYPE_FAILED_DISK_SPACE_LOW_ON_STORAGE_DOMAIN,
+                result.getMessage());
+    }
+
+    @Test
     public void testAllDomainsHaveSpaceForAllDisksSuccess(){
         List<Guid> sdIdsForNew = Arrays.asList(sdId1, sdId2);
         List<Guid> sdIdsForCloned = Arrays.asList(sdId2, sdId3);
diff --git 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/StorageDomainValidatorFreeSpaceTest.java
 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/StorageDomainValidatorFreeSpaceTest.java
index eead8f8..c53f3cb 100644
--- 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/StorageDomainValidatorFreeSpaceTest.java
+++ 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/validator/StorageDomainValidatorFreeSpaceTest.java
@@ -25,15 +25,18 @@
 
     private boolean isValidForCloned;
     private boolean isValidForNew;
+    private boolean isValidForSnapshots;
 
     public StorageDomainValidatorFreeSpaceTest(DiskImage disk,
             StorageDomain sd,
             boolean isValidForCloned,
-            boolean isValidForNew) {
+            boolean isValidForNew,
+            boolean isValidForSnapshots) {
         this.disk = disk;
         this.sd = sd;
         this.isValidForCloned = isValidForCloned;
         this.isValidForNew = isValidForNew;
+        this.isValidForSnapshots = isValidForSnapshots;
     }
 
     @Parameters
@@ -60,7 +63,9 @@
 
                         params.add(new Object[] { disk, sd,
                                 volumeFormat == VolumeFormat.RAW && volumeType 
== VolumeType.Sparse,
-                                volumeFormat == VolumeFormat.COW || volumeType 
== VolumeType.Sparse });
+                                volumeFormat == VolumeFormat.COW || volumeType 
== VolumeType.Sparse,
+                                volumeFormat == VolumeFormat.RAW && volumeType 
== VolumeType.Sparse
+                        });
                     }
                 }
             }
@@ -70,6 +75,14 @@
     }
 
     @Test
+    public void testValidateDiskWithSnapshots() {
+        StorageDomainValidator sdValidator = new StorageDomainValidator(sd);
+        assertEquals(disk.getVolumeFormat() + ", " + disk.getVolumeType() + ", 
" + sd.getStorageType(),
+                isValidForSnapshots,
+                sdValidator.hasSpaceForDiskWithSnapshots(disk).isValid());
+    }
+
+    @Test
     public void testValidateClonedDisk() {
         StorageDomainValidator sdValidator = new StorageDomainValidator(sd);
         assertEquals(disk.getVolumeFormat() + ", " + disk.getVolumeType() + ", 
" + sd.getStorageType(),
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/DiskImageBase.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/DiskImageBase.java
index 9258685..c44810c 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/DiskImageBase.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/DiskImageBase.java
@@ -2,6 +2,7 @@
 
 import javax.validation.Valid;
 
+import org.codehaus.jackson.annotate.JsonIgnore;
 import org.ovirt.engine.core.compat.Guid;
 
 public class DiskImageBase extends Disk {
@@ -59,6 +60,11 @@
         getImage().setSize(size);
     }
 
+    @JsonIgnore
+    public long getCapacity() {
+        return getSize();
+    }
+
     /**
      * disk size in GB
      */


-- 
To view, visit http://gerrit.ovirt.org/32898
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifbb1d985f9afa476452d1d2b78be1fd18c128c8f
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: ovirt-engine-3.5
Gerrit-Owner: Vered Volansky <vvola...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to