Liron Aravot has uploaded a new change for review. Change subject: core: Extracting OvfDataUpdater logic to commands ......................................................................
core: Extracting OvfDataUpdater logic to commands This patch moves the ovf update logic resides within the OvfDataUpdater to BLL commands, so that it can be executed easily by other flows as well. The logic was mainly moved to ProcessOvfUpdateForStoragePoolCommand, tests were added accordingly. Change-Id: I6780aedf2d215d08c4bed0ff4f7520c45f753f66 Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1138124 Signed-off-by: Liron Aravot <[email protected]> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmTemplateCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfDataUpdater.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfUpdateProcessHelper.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommand.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/OvfDataUpdaterTest.java A backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommandTest.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/auditloghandling/AuditLogableBase.java 10 files changed, 1,390 insertions(+), 1,398 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/15/35815/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmCommand.java index d69ff8e..7973010 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmCommand.java @@ -512,13 +512,14 @@ } protected boolean updateVmInSpm() { + OvfUpdateProcessHelper ovfHelper = new OvfUpdateProcessHelper(); Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary = new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>(); - OvfDataUpdater.getInstance().loadVmData(getVm()); - OvfDataUpdater.getInstance().buildMetadataDictionaryForVm(getVm(), + ovfHelper.loadVmData(getVm()); + ovfHelper.buildMetadataDictionaryForVm(getVm(), metaDictionary, - OvfDataUpdater.getInstance().getVmImagesFromDb(getVm())); - return OvfDataUpdater.getInstance().executeUpdateVmInSpmCommand(getVm().getStoragePoolId(), + ovfHelper.getVmImagesFromDb(getVm())); + return ovfHelper.executeUpdateVmInSpmCommand(getVm().getStoragePoolId(), metaDictionary, getParameters().getStorageDomainId()); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmTemplateCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmTemplateCommand.java index 662c1df..25770bb 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmTemplateCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ExportVmTemplateCommand.java @@ -181,11 +181,12 @@ if (getParameters().getTaskGroupSuccess()) { Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary = new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>(); - OvfDataUpdater.getInstance().loadTemplateData(getVmTemplate()); + OvfUpdateProcessHelper ovfUpdateProcessHelper = new OvfUpdateProcessHelper(); + ovfUpdateProcessHelper.loadTemplateData(getVmTemplate()); VmTemplateHandler.updateDisksFromDb(getVmTemplate()); // update the target (export) domain - OvfDataUpdater.getInstance().buildMetadataDictionaryForTemplate(getVmTemplate(), metaDictionary); - OvfDataUpdater.getInstance().executeUpdateVmInSpmCommand(getVmTemplate().getStoragePoolId(), + ovfUpdateProcessHelper.buildMetadataDictionaryForTemplate(getVmTemplate(), metaDictionary); + ovfUpdateProcessHelper.executeUpdateVmInSpmCommand(getVmTemplate().getStoragePoolId(), metaDictionary, getParameters().getStorageDomainId()); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfDataUpdater.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfDataUpdater.java index 4cb75ce..4e31c59 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfDataUpdater.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfDataUpdater.java @@ -1,71 +1,23 @@ package org.ovirt.engine.core.bll; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; import java.util.List; -import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; -import org.ovirt.engine.core.bll.utils.ClusterUtils; -import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.FeatureSupported; import org.ovirt.engine.core.common.action.StorageDomainParametersBase; +import org.ovirt.engine.core.common.action.StoragePoolParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; -import org.ovirt.engine.core.common.businessentities.Disk; -import org.ovirt.engine.core.common.businessentities.DiskImage; -import org.ovirt.engine.core.common.businessentities.ImageStatus; -import org.ovirt.engine.core.common.businessentities.Snapshot; -import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotStatus; -import org.ovirt.engine.core.common.businessentities.StorageDomain; -import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfo; -import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfoStatus; -import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; +import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; -import org.ovirt.engine.core.common.businessentities.VM; -import org.ovirt.engine.core.common.businessentities.VMStatus; -import org.ovirt.engine.core.common.businessentities.VmBase; -import org.ovirt.engine.core.common.businessentities.VmDevice; -import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; -import org.ovirt.engine.core.common.businessentities.VmTemplate; -import org.ovirt.engine.core.common.businessentities.VmTemplateStatus; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; -import org.ovirt.engine.core.common.constants.StorageConstants; -import org.ovirt.engine.core.common.errors.VdcBllMessages; -import org.ovirt.engine.core.common.locks.LockingGroup; -import org.ovirt.engine.core.common.utils.Pair; -import org.ovirt.engine.core.common.vdscommands.RemoveVMVDSCommandParameters; -import org.ovirt.engine.core.common.vdscommands.UpdateVMVDSCommandParameters; -import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.compat.Guid; -import org.ovirt.engine.core.compat.KeyValuePairCompat; import org.ovirt.engine.core.dal.dbbroker.DbFacade; -import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; -import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase; -import org.ovirt.engine.core.dao.SnapshotDao; -import org.ovirt.engine.core.dao.StorageDomainDAO; -import org.ovirt.engine.core.dao.StorageDomainOvfInfoDao; import org.ovirt.engine.core.dao.StoragePoolDAO; -import org.ovirt.engine.core.dao.StoragePoolIsoMapDAO; -import org.ovirt.engine.core.dao.VmAndTemplatesGenerationsDAO; -import org.ovirt.engine.core.dao.VmDAO; -import org.ovirt.engine.core.dao.VmStaticDAO; -import org.ovirt.engine.core.dao.VmTemplateDAO; -import org.ovirt.engine.core.dao.network.VmNetworkInterfaceDao; -import org.ovirt.engine.core.utils.linq.Function; -import org.ovirt.engine.core.utils.linq.LinqUtils; -import org.ovirt.engine.core.utils.lock.EngineLock; -import org.ovirt.engine.core.utils.lock.LockManager; -import org.ovirt.engine.core.utils.lock.LockManagerFactory; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; -import org.ovirt.engine.core.utils.ovf.OvfManager; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; import org.ovirt.engine.core.utils.timer.SchedulerUtil; import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl; @@ -73,18 +25,8 @@ public class OvfDataUpdater { private static final Log log = LogFactory.getLog(OvfDataUpdater.class); private static final OvfDataUpdater INSTANCE = new OvfDataUpdater(); - private int itemsCountPerUpdate; - - private List<Guid> proccessedIdsInfo; - private List<Long> proccessedOvfGenerationsInfo; - private List<String> proccessedOvfConfigurationsInfo; - private HashSet<Guid> proccessedDomains; - private List<Guid> removedOvfIdsInfo; - - private OvfManager ovfManager; private OvfDataUpdater() { - ovfManager = new OvfManager(); } public static OvfDataUpdater getInstance() { @@ -103,509 +45,43 @@ log.info("Initialization of OvfDataUpdater completed successfully."); } - protected int reloadConfigValue() { - return Config.<Integer> getValue(ConfigValues.OvfItemsCountPerUpdate); - } - - private LockManager getLockManager() { - return LockManagerFactory.getLockManager(); - } - - protected boolean acquireLock(EngineLock engineLock) { - return LockManagerFactory.getLockManager().acquireLock(engineLock).getFirst(); - } - - protected void releaseLock(EngineLock engineLock) { - LockManagerFactory.getLockManager().releaseLock(engineLock); - } - - private void logInfoIfNeeded(StoragePool pool, String message, Object... args) { - // if supported, the info would be logged when executing for each domain - if (!ovfOnAnyDomainSupported(pool)) { - log.infoFormat(message, args); - } - } - - protected void proceedPoolOvfUpdate(StoragePool pool) { - proccessedDomains = new HashSet<>(); - if (ovfOnAnyDomainSupported(pool)) { - proccessDomainsForOvfUpdate(pool); - } - - logInfoIfNeeded(pool, "Attempting to update VM OVFs in Data Center {0}", - pool.getName()); - initProcessedInfoLists(); - - updateOvfForVmsOfStoragePool(pool); - - logInfoIfNeeded(pool, "Successfully updated VM OVFs in Data Center {0}", - pool.getName()); - logInfoIfNeeded(pool, "Attempting to update template OVFs in Data Center {0}", - pool.getName()); - - updateOvfForTemplatesOfStoragePool(pool); - - logInfoIfNeeded(pool, "Successfully updated templates OVFs in Data Center {0}", - pool.getName()); - logInfoIfNeeded(pool, "Attempting to remove unneeded template/vm OVFs in Data Center {0}", - pool.getName()); - - removeOvfForTemplatesAndVmsOfStoragePool(pool); - - logInfoIfNeeded(pool, "Successfully removed unneeded template/vm OVFs in Data Center {0}", - pool.getName()); - } - protected void performOvfUpdateForDomain(Guid storagePoolId, Guid domainId) { Backend.getInstance().runInternalAction(VdcActionType.ProcessOvfUpdateForStorageDomain, new StorageDomainParametersBase(storagePoolId, domainId)); } - private EngineLock buildPoolEngineLock(StoragePool pool) { - Map<String, Pair<String, String>> exclusiveLocks = - Collections.singletonMap(pool.getId().toString(), - LockMessagesMatchUtil.makeLockingPair(LockingGroup.OVF_UPDATE, - VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED)); - return new EngineLock(exclusiveLocks, null); + protected VdcReturnValueBase performOvfUpdateForStoragePool(Guid storagePoolId) { + return Backend.getInstance().runInternalAction(VdcActionType.ProcessOvfUpdateForStoragePool, new StoragePoolParametersBase(storagePoolId)); } @OnTimerMethodAnnotation("ovfUpdate_timer") public void ovfUpdate_timer() { - itemsCountPerUpdate = reloadConfigValue(); - log.info("Attempting to update VMs/Templates Ovf."); List<StoragePool> storagePools = getStoragePoolDao().getAllByStatus(StoragePoolStatus.Up); + updateOvfData(storagePools); + } + + + public void updateOvfData(List<StoragePool> storagePools) { + log.info("Attempting to update VMs/Templates Ovf."); for (StoragePool pool : storagePools) { - EngineLock poolLock = buildPoolEngineLock(pool); - if (!acquireLock(poolLock)) { - log.errorFormat("Failed to update OVFs in Data Center {0} as there is a related operation in progress.", pool.getName()); - continue; + VdcReturnValueBase returnValueBase = performOvfUpdateForStoragePool(pool.getId()); + if (!returnValueBase.getSucceeded()) { + log.errorFormat("Exception while trying to update or remove VMs/Templates ovf in Data Center {0}.", pool.getName()); } - boolean lockReleased = false; + if (ovfOnAnyDomainSupported(pool)) { + log.debugFormat("Attempting to update ovfs in domain in Data Center {0}", + pool.getName()); - try { - proceedPoolOvfUpdate(pool); - if (ovfOnAnyDomainSupported(pool)) { - logInfoIfNeeded(pool, "Attempting to update ovfs in domain in Data Center {0}", - pool.getName()); - - releaseLock(poolLock); - lockReleased = true; - - for (Guid id : proccessedDomains) { + Set<Guid> domainsToUpdate = (Set<Guid>) returnValueBase.getActionReturnValue(); + if (domainsToUpdate != null) { + for (Guid id : domainsToUpdate) { performOvfUpdateForDomain(pool.getId(), id); } - } - } catch (Exception ex) { - addAuditLogError(pool.getName()); - log.errorFormat("Exception while trying to update or remove VMs/Templates ovf in Data Center {0}.", pool.getName(), ex); - } finally { - if (!lockReleased) { - releaseLock(poolLock); + } else { + log.error("Data Center {0} domains list for OVF update returned as NULL"); } } } - proccessedIdsInfo = null; - removedOvfIdsInfo = null; - proccessedOvfGenerationsInfo = null; - proccessedOvfConfigurationsInfo = null; - proccessedDomains = null; - } - - - protected void proccessDomainsForOvfUpdate(StoragePool pool) { - List<StorageDomain> domainsInPool = getStorageDomainDao().getAllForStoragePool(pool.getId()); - for (StorageDomain domain : domainsInPool) { - if (!domain.getStorageDomainType().isDataDomain() || domain.getStatus() != StorageDomainStatus.Active) { - continue; - } - - Integer ovfStoresCountForDomain = Config.<Integer> getValue(ConfigValues.StorageDomainOvfStoreCount); - List<StorageDomainOvfInfo> storageDomainOvfInfos = getStorageDomainOvfInfoDao().getAllForDomain(domain.getId()); - - if (storageDomainOvfInfos.size() < ovfStoresCountForDomain) { - proccessedDomains.add(domain.getId()); - continue; - } - - for (StorageDomainOvfInfo storageDomainOvfInfo : storageDomainOvfInfos) { - if (storageDomainOvfInfo.getStatus() == StorageDomainOvfInfoStatus.OUTDATED) { - proccessedDomains.add(storageDomainOvfInfo.getStorageDomainId()); - break; - } - } - } - } - - /** - * Update ovfs for updated/newly vms since last run for the given storage pool - * - */ - protected void updateOvfForVmsOfStoragePool(StoragePool pool) { - Guid poolId = pool.getId(); - List<Guid> vmsIdsForUpdate = getVmAndTemplatesGenerationsDao().getVmsIdsForOvfUpdate(poolId); - int i = 0; - while (i < vmsIdsForUpdate.size()) { - int size = Math.min(itemsCountPerUpdate, vmsIdsForUpdate.size() - i); - List<Guid> idsToProcess = vmsIdsForUpdate.subList(i, i + size); - i += size; - - Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = - populateVmsMetadataForOvfUpdate(idsToProcess); - if (!vmsAndTemplateMetadata.isEmpty()) { - performOvfUpdate(pool, vmsAndTemplateMetadata); - } - } - } - - /** - * Removes from the storage ovf files of vm/templates that were removed from the db since the last OvfDataUpdater - * run. - * - */ - protected void removeOvfForTemplatesAndVmsOfStoragePool(StoragePool pool) { - Guid poolId = pool.getId(); - removedOvfIdsInfo = getVmAndTemplatesGenerationsDao().getIdsForOvfDeletion(poolId); - - if (!ovfOnAnyDomainSupported(pool)) { - for (Guid id : removedOvfIdsInfo) { - executeRemoveVmInSpm(poolId, id, Guid.Empty); - } - } - - markDomainsWithOvfsForOvfUpdate(removedOvfIdsInfo); - getVmAndTemplatesGenerationsDao().deleteOvfGenerations(removedOvfIdsInfo); - } - - protected void markDomainsWithOvfsForOvfUpdate(Collection<Guid> ovfIds) { - List<Guid> relevantDomains = getStorageDomainOvfInfoDao().loadStorageDomainIdsForOvfIds(ovfIds); - proccessedDomains.addAll(relevantDomains); - getStorageDomainOvfInfoDao().updateOvfUpdatedInfo(proccessedDomains, StorageDomainOvfInfoStatus.OUTDATED, StorageDomainOvfInfoStatus.DISABLED); - } - - /** - * Perform vdsm call which performs ovf update for the given metadata map - * - */ - protected void performOvfUpdate(StoragePool pool, - Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata) { - if (!ovfOnAnyDomainSupported(pool)) { - executeUpdateVmInSpmCommand(pool.getId(), vmsAndTemplateMetadata, Guid.Empty); - } else { - markDomainsWithOvfsForOvfUpdate(vmsAndTemplateMetadata.keySet()); - } - - int i = 0; - while (i < proccessedIdsInfo.size()) { - int sizeToUpdate = Math.min(StorageConstants.OVF_MAX_ITEMS_PER_SQL_STATEMENT, proccessedIdsInfo.size() - i); - List<Guid> guidsForUpdate = proccessedIdsInfo.subList(i, i + sizeToUpdate); - List<Long> ovfGenerationsForUpdate = proccessedOvfGenerationsInfo.subList(i, i + sizeToUpdate); - List<String> ovfConfigurationsInfo = proccessedOvfConfigurationsInfo.subList(i, i + sizeToUpdate); - getVmAndTemplatesGenerationsDao().updateOvfGenerations(guidsForUpdate, ovfGenerationsForUpdate, ovfConfigurationsInfo); - i += sizeToUpdate; - initProcessedInfoLists(); - } - } - - /** - * Creates and returns a map containing valid templates metadata - */ - protected Map<Guid, KeyValuePairCompat<String, List<Guid>>> populateTemplatesMetadataForOvfUpdate(List<Guid> idsToProcess) { - Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = - new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>(); - List<VmTemplate> templates = getVmTemplateDao().getVmTemplatesByIds(idsToProcess); - - for (VmTemplate template : templates) { - if (VmTemplateStatus.Locked != template.getStatus()) { - updateTemplateDisksFromDb(template); - boolean verifyDisksNotLocked = verifyImagesStatus(template.getDiskList()); - if (verifyDisksNotLocked) { - loadTemplateData(template); - Long currentDbGeneration = getVmStaticDao().getDbGeneration(template.getId()); - // currentDbGeneration can be null in case that the template was deleted during the run of OvfDataUpdater. - if (currentDbGeneration != null && template.getDbGeneration() == currentDbGeneration) { - proccessedOvfConfigurationsInfo.add(buildMetadataDictionaryForTemplate(template, vmsAndTemplateMetadata)); - proccessedIdsInfo.add(template.getId()); - proccessedOvfGenerationsInfo.add(template.getDbGeneration()); - proccessDisksDomains(template.getDiskList()); - } - } - } - } - - return vmsAndTemplateMetadata; - } - - protected void updateTemplateDisksFromDb(VmTemplate template) { - VmTemplateHandler.updateDisksFromDb(template); - } - - protected void updateVmDisksFromDb(VM vm) { - VmHandler.updateDisksFromDb(vm); - } - - /** - * Update ovfs for updated/added templates since last for the given storage pool - */ - protected void updateOvfForTemplatesOfStoragePool(StoragePool pool) { - Guid poolId = pool.getId(); - List<Guid> templateIdsForUpdate = - getVmAndTemplatesGenerationsDao().getVmTemplatesIdsForOvfUpdate(poolId); - int i = 0; - while (i < templateIdsForUpdate.size()) { - int size = Math.min(templateIdsForUpdate.size() - i, itemsCountPerUpdate); - List<Guid> idsToProcess = templateIdsForUpdate.subList(i, i + size); - i += size; - - Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = - populateTemplatesMetadataForOvfUpdate(idsToProcess); - if (!vmsAndTemplateMetadata.isEmpty()) { - performOvfUpdate(pool, vmsAndTemplateMetadata); - } - } - } - - /** - * Create and returns map contains valid vms metadata - */ - protected Map<Guid, KeyValuePairCompat<String, List<Guid>>> populateVmsMetadataForOvfUpdate(List<Guid> idsToProcess) { - Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = - new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>(); - List<VM> vms = getVmDao().getVmsByIds(idsToProcess); - for (VM vm : vms) { - if (VMStatus.ImageLocked != vm.getStatus()) { - updateVmDisksFromDb(vm); - if (!verifyImagesStatus(vm.getDiskList())) { - continue; - } - ArrayList<DiskImage> vmImages = getVmImagesFromDb(vm); - if (!verifyImagesStatus(vmImages)) { - continue; - } - vm.setSnapshots(getSnapshotDao().getAllWithConfiguration(vm.getId())); - if (!verifySnapshotsStatus(vm.getSnapshots())) { - continue; - } - - loadVmData(vm); - Long currentDbGeneration = getVmStaticDao().getDbGeneration(vm.getId()); - if (currentDbGeneration == null) { - log.warnFormat("currentDbGeneration of VM (name: {0}, id: {1}) is null, probably because the VM was deleted during the run of OvfDataUpdater.", - vm.getName(), - vm.getId()); - continue; - } - if (vm.getStaticData().getDbGeneration() == currentDbGeneration) { - proccessedOvfConfigurationsInfo.add(buildMetadataDictionaryForVm(vm, vmsAndTemplateMetadata, vmImages)); - proccessedIdsInfo.add(vm.getId()); - proccessedOvfGenerationsInfo.add(vm.getStaticData().getDbGeneration()); - proccessDisksDomains(vm.getDiskList()); - } - } - } - return vmsAndTemplateMetadata; - } - - protected ArrayList<DiskImage> getVmImagesFromDb(VM vm) { - ArrayList<DiskImage> allVmImages = new ArrayList<>(); - List<DiskImage> filteredDisks = ImagesHandler.filterImageDisks(vm.getDiskList(), false, true, true); - - for (DiskImage diskImage : filteredDisks) { - allVmImages.addAll(getAllImageSnapshots(diskImage)); - } - return allVmImages; - } - - protected void proccessDisksDomains(List<DiskImage> disks) { - for (DiskImage disk : disks) { - proccessedDomains.addAll(disk.getStorageIds()); - } - } - - /** - * Returns true if all snapshots have a valid status to use in the OVF. - */ - protected boolean verifySnapshotsStatus(List<Snapshot> snapshots) { - for (Snapshot snapshot : snapshots) { - if (snapshot.getStatus() != SnapshotStatus.OK) { - return false; - } - } - return true; - } - - /** - * Returns true if none of the given disks is in status 'LOCKED', otherwise false. - */ - protected boolean verifyImagesStatus(List<DiskImage> diskImages) { - for (DiskImage diskImage : diskImages) { - if (diskImage.getImageStatus() == ImageStatus.LOCKED) { - return false; - } - } - return true; - } - - protected String generateVmTemplateMetadata(VmTemplate template, List<DiskImage> allTemplateImages) { - return ovfManager.ExportTemplate(template, allTemplateImages, ClusterUtils.getCompatibilityVersion(template)); - } - - /** - * Adds the given template metadata to the given map - */ - protected String buildMetadataDictionaryForTemplate(VmTemplate template, - Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary) { - List<DiskImage> allTemplateImages = template.getDiskList(); - String templateMeta = generateVmTemplateMetadata(template, allTemplateImages); - metaDictionary.put(template.getId(), new KeyValuePairCompat<String, List<Guid>>( - templateMeta, LinqUtils.transformToList(allTemplateImages, new Function<DiskImage, Guid>() { - @Override - public Guid eval(DiskImage diskImage) { - return diskImage.getId(); - } - }))); - return templateMeta; - } - - /** - * Loads additional need template data for it's ovf - */ - protected void loadTemplateData(VmTemplate template) { - setManagedVideoDevices(template); - if (template.getInterfaces() == null || template.getInterfaces().isEmpty()) { - template.setInterfaces(getVmNetworkInterfaceDao() - .getAllForTemplate(template.getId())); - } - } - - /** - * Loads additional need vm data for it's ovf - */ - protected void loadVmData(VM vm) { - setManagedVideoDevices(vm.getStaticData()); - if (vm.getInterfaces().isEmpty()) { - vm.setInterfaces(getVmNetworkInterfaceDao().getAllForVm(vm.getId())); - } - if (StringUtils.isEmpty(vm.getVmtName())) { - if (!Guid.Empty.equals(vm.getVmtGuid())) { - VmTemplate t = getVmTemplateDao().get(vm.getVmtGuid()); - vm.setVmtName(t.getName()); - } else { - vm.setVmtName(VmTemplateHandler.BLANK_VM_TEMPLATE_NAME); - } - } - } - - private void setManagedVideoDevices(VmBase vmBase) { - Map<Guid, VmDevice> managedDeviceMap = vmBase.getManagedDeviceMap(); - if (managedDeviceMap == null) { - managedDeviceMap = new HashMap<Guid, VmDevice>(); - } - List<VmDevice> devices = - DbFacade.getInstance() - .getVmDeviceDao() - .getVmDeviceByVmIdAndType(vmBase.getId(), VmDeviceGeneralType.VIDEO); - for (VmDevice device : devices) { - managedDeviceMap.put(device.getDeviceId(), device); - } - } - - protected List<DiskImage> getAllImageSnapshots(DiskImage diskImage) { - return ImagesHandler.getAllImageSnapshots(diskImage.getImageId()); - } - - protected String generateVmMetadata(VM vm, ArrayList<DiskImage> AllVmImages) { - return ovfManager.ExportVm(vm, AllVmImages, ClusterUtils.getCompatibilityVersion(vm)); - } - - /** - * Adds the given vm metadata to the given map - */ - protected String buildMetadataDictionaryForVm(VM vm, - Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary, - ArrayList<DiskImage> allVmImages) { - String vmMeta = generateVmMetadata(vm, allVmImages); - metaDictionary.put( - vm.getId(), - new KeyValuePairCompat<String, List<Guid>>(vmMeta, LinqUtils.transformToList(vm.getDiskMap().values(), - new Function<Disk, Guid>() { - @Override - public Guid eval(Disk a) { - return a.getId(); - } - }))); - return vmMeta; - } - - protected VmDAO getVmDao() { - return DbFacade.getInstance().getVmDao(); - } - - protected VmTemplateDAO getVmTemplateDao() { - return DbFacade.getInstance().getVmTemplateDao(); - } - - protected StoragePoolIsoMapDAO getSoragePoolIsoMapDao() { - return DbFacade.getInstance().getStoragePoolIsoMapDao(); - } - - protected StorageDomainDAO getStorageDomainDao() { - return DbFacade.getInstance().getStorageDomainDao(); - } - - protected VmNetworkInterfaceDao getVmNetworkInterfaceDao() { - return DbFacade.getInstance().getVmNetworkInterfaceDao(); - } - - protected VmAndTemplatesGenerationsDAO getVmAndTemplatesGenerationsDao() { - return DbFacade.getInstance().getVmAndTemplatesGenerationsDao(); - } - - protected StorageDomainOvfInfoDao getStorageDomainOvfInfoDao() { - return DbFacade.getInstance().getStorageDomainOvfInfoDao(); - } - - protected VmStaticDAO getVmStaticDao() { - return DbFacade.getInstance().getVmStaticDao(); - } - - protected SnapshotDao getSnapshotDao() { - return DbFacade.getInstance().getSnapshotDao(); - } - - /** - * Init the lists contain the processed info. - */ - private void initProcessedInfoLists() { - proccessedIdsInfo = new LinkedList<Guid>(); - proccessedOvfGenerationsInfo = new LinkedList<Long>(); - proccessedOvfConfigurationsInfo = new LinkedList<>(); - removedOvfIdsInfo = null; - } - - /** - * Update the information contained in the given meta dictionary table in the given storage pool/storage domain. - */ - protected boolean executeUpdateVmInSpmCommand(Guid storagePoolId, - Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary, - Guid storageDomainId) { - UpdateVMVDSCommandParameters tempVar = new UpdateVMVDSCommandParameters(storagePoolId, metaDictionary); - tempVar.setStorageDomainId(storageDomainId); - return Backend.getInstance().getResourceManager().RunVdsCommand(VDSCommandType.UpdateVM, tempVar) - .getSucceeded(); - } - - /** - * Removes the ovf of the vm/template with the given id from the given storage pool/storage domain. - */ - protected boolean executeRemoveVmInSpm(Guid storagePoolId, Guid id, Guid storageDomainId) { - return Backend.getInstance().getResourceManager().RunVdsCommand(VDSCommandType.RemoveVM, - new RemoveVMVDSCommandParameters(storagePoolId, id, storageDomainId)).getSucceeded(); - } - - protected void addAuditLogError(String storagePoolName) { - AuditLogableBase logable = new AuditLogableBase(); - logable.addCustomValue("StoragePoolName", storagePoolName); - AuditLogDirector.log(logable, AuditLogType.UPDATE_OVF_FOR_STORAGE_POOL_FAILED); } protected boolean ovfOnAnyDomainSupported(StoragePool pool) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfUpdateProcessHelper.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfUpdateProcessHelper.java new file mode 100644 index 0000000..63ddf2d --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/OvfUpdateProcessHelper.java @@ -0,0 +1,186 @@ +package org.ovirt.engine.core.bll; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.ovirt.engine.core.bll.utils.ClusterUtils; +import org.ovirt.engine.core.common.businessentities.Disk; +import org.ovirt.engine.core.common.businessentities.DiskImage; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VmBase; +import org.ovirt.engine.core.common.businessentities.VmDevice; +import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; +import org.ovirt.engine.core.common.businessentities.VmTemplate; +import org.ovirt.engine.core.common.vdscommands.RemoveVMVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.UpdateVMVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.VDSCommandType; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.compat.KeyValuePairCompat; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.dao.SnapshotDao; +import org.ovirt.engine.core.dao.StorageDomainDAO; +import org.ovirt.engine.core.dao.VmDAO; +import org.ovirt.engine.core.dao.VmStaticDAO; +import org.ovirt.engine.core.dao.VmTemplateDAO; +import org.ovirt.engine.core.dao.network.VmNetworkInterfaceDao; +import org.ovirt.engine.core.utils.linq.Function; +import org.ovirt.engine.core.utils.linq.LinqUtils; +import org.ovirt.engine.core.utils.ovf.OvfManager; + +public class OvfUpdateProcessHelper { + private OvfManager ovfManager; + + public OvfUpdateProcessHelper() { + ovfManager = new OvfManager(); + } + + /** + * Adds the given vm metadata to the given map + */ + protected String buildMetadataDictionaryForVm(VM vm, + Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary, + ArrayList<DiskImage> allVmImages) { + String vmMeta = generateVmMetadata(vm, allVmImages); + metaDictionary.put( + vm.getId(), + new KeyValuePairCompat<String, List<Guid>>(vmMeta, LinqUtils.transformToList(vm.getDiskMap().values(), + new Function<Disk, Guid>() { + @Override + public Guid eval(Disk a) { + return a.getId(); + } + }))); + return vmMeta; + } + + protected String generateVmTemplateMetadata(VmTemplate template, List<DiskImage> allTemplateImages) { + return ovfManager.ExportTemplate(template, allTemplateImages, ClusterUtils.getCompatibilityVersion(template)); + } + + /** + * Adds the given template metadata to the given map + */ + protected String buildMetadataDictionaryForTemplate(VmTemplate template, + Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary) { + List<DiskImage> allTemplateImages = template.getDiskList(); + String templateMeta = generateVmTemplateMetadata(template, allTemplateImages); + metaDictionary.put(template.getId(), new KeyValuePairCompat<String, List<Guid>>( + templateMeta, LinqUtils.transformToList(allTemplateImages, new Function<DiskImage, Guid>() { + @Override + public Guid eval(DiskImage diskImage) { + return diskImage.getId(); + } + }))); + return templateMeta; + } + + /** + * Loads additional need vm data for it's ovf + */ + protected void loadVmData(VM vm) { + setManagedVideoDevices(vm.getStaticData()); + if (vm.getInterfaces().isEmpty()) { + vm.setInterfaces(getVmNetworkInterfaceDao().getAllForVm(vm.getId())); + } + if (StringUtils.isEmpty(vm.getVmtName())) { + if (!Guid.Empty.equals(vm.getVmtGuid())) { + VmTemplate t = getVmTemplateDao().get(vm.getVmtGuid()); + vm.setVmtName(t.getName()); + } else { + vm.setVmtName(VmTemplateHandler.BLANK_VM_TEMPLATE_NAME); + } + } + } + + private void setManagedVideoDevices(VmBase vmBase) { + Map<Guid, VmDevice> managedDeviceMap = vmBase.getManagedDeviceMap(); + if (managedDeviceMap == null) { + managedDeviceMap = new HashMap<Guid, VmDevice>(); + } + List<VmDevice> devices = + DbFacade.getInstance() + .getVmDeviceDao() + .getVmDeviceByVmIdAndType(vmBase.getId(), VmDeviceGeneralType.VIDEO); + for (VmDevice device : devices) { + managedDeviceMap.put(device.getDeviceId(), device); + } + } + + protected List<DiskImage> getAllImageSnapshots(DiskImage diskImage) { + return ImagesHandler.getAllImageSnapshots(diskImage.getImageId()); + } + + + protected ArrayList<DiskImage> getVmImagesFromDb(VM vm) { + ArrayList<DiskImage> allVmImages = new ArrayList<>(); + List<DiskImage> filteredDisks = ImagesHandler.filterImageDisks(vm.getDiskList(), false, true, true); + + for (DiskImage diskImage : filteredDisks) { + allVmImages.addAll(getAllImageSnapshots(diskImage)); + } + return allVmImages; + } + + /** + * Loads additional need template data for it's ovf + */ + protected void loadTemplateData(VmTemplate template) { + setManagedVideoDevices(template); + if (template.getInterfaces() == null || template.getInterfaces().isEmpty()) { + template.setInterfaces(getVmNetworkInterfaceDao() + .getAllForTemplate(template.getId())); + } + } + + protected String generateVmMetadata(VM vm, ArrayList<DiskImage> AllVmImages) { + return ovfManager.ExportVm(vm, AllVmImages, ClusterUtils.getCompatibilityVersion(vm)); + } + + protected VmDAO getVmDao() { + return DbFacade.getInstance().getVmDao(); + } + + protected StorageDomainDAO getStorageDomainDao() { + return DbFacade.getInstance().getStorageDomainDao(); + } + + + protected VmTemplateDAO getVmTemplateDao() { + return DbFacade.getInstance().getVmTemplateDao(); + } + + protected VmNetworkInterfaceDao getVmNetworkInterfaceDao() { + return DbFacade.getInstance().getVmNetworkInterfaceDao(); + } + + protected VmStaticDAO getVmStaticDao() { + return DbFacade.getInstance().getVmStaticDao(); + } + + protected SnapshotDao getSnapshotDao() { + return DbFacade.getInstance().getSnapshotDao(); + } + + /** + * Update the information contained in the given meta dictionary table in the given storage pool/storage domain. + */ + protected boolean executeUpdateVmInSpmCommand(Guid storagePoolId, + Map<Guid, KeyValuePairCompat<String, List<Guid>>> metaDictionary, + Guid storageDomainId) { + UpdateVMVDSCommandParameters tempVar = new UpdateVMVDSCommandParameters(storagePoolId, metaDictionary); + tempVar.setStorageDomainId(storageDomainId); + return Backend.getInstance().getResourceManager().RunVdsCommand(VDSCommandType.UpdateVM, tempVar) + .getSucceeded(); + } + + /** + * Removes the ovf of the vm/template with the given id from the given storage pool/storage domain. + */ + protected boolean executeRemoveVmInSpm(Guid storagePoolId, Guid id, Guid storageDomainId) { + return Backend.getInstance().getResourceManager().RunVdsCommand(VDSCommandType.RemoveVM, + new RemoveVMVDSCommandParameters(storagePoolId, id, storageDomainId)).getSucceeded(); + } +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java index 1a7071b..de86b6d 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java @@ -27,7 +27,6 @@ import org.ovirt.engine.core.common.utils.VmDeviceType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; -import org.ovirt.engine.core.dao.SnapshotDao; import org.ovirt.engine.core.dao.VmPoolDAO; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; @@ -106,10 +105,6 @@ private VmPoolDAO getVmPoolDAO() { return DbFacade.getInstance().getVmPoolDao(); - } - - private SnapshotDao getSnapshotDAO() { - return DbFacade.getInstance().getSnapshotDao(); } @Override diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommand.java new file mode 100644 index 0000000..4770c88 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommand.java @@ -0,0 +1,363 @@ +package org.ovirt.engine.core.bll; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.ovirt.engine.core.bll.context.CommandContext; +import org.ovirt.engine.core.bll.storage.StorageHandlingCommandBase; +import org.ovirt.engine.core.common.AuditLogType; +import org.ovirt.engine.core.common.FeatureSupported; +import org.ovirt.engine.core.common.action.LockProperties; +import org.ovirt.engine.core.common.action.StoragePoolParametersBase; +import org.ovirt.engine.core.common.businessentities.DiskImage; +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.StorageDomainOvfInfo; +import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfoStatus; +import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; +import org.ovirt.engine.core.common.businessentities.StoragePool; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VMStatus; +import org.ovirt.engine.core.common.businessentities.VmTemplate; +import org.ovirt.engine.core.common.businessentities.VmTemplateStatus; +import org.ovirt.engine.core.common.config.Config; +import org.ovirt.engine.core.common.config.ConfigValues; +import org.ovirt.engine.core.common.constants.StorageConstants; +import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.locks.LockingGroup; +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.compat.KeyValuePairCompat; + +@NonTransactiveCommandAttribute +@InternalCommandAttribute +public class ProcessOvfUpdateForStoragePoolCommand <T extends StoragePoolParametersBase> extends StorageHandlingCommandBase<T> { + + private int itemsCountPerUpdate; + private List<Guid> proccessedIdsInfo; + private List<Long> proccessedOvfGenerationsInfo; + private List<String> proccessedOvfConfigurationsInfo; + private HashSet<Guid> proccessedDomains; + private List<Guid> removedOvfIdsInfo; + private OvfUpdateProcessHelper ovfUpdateProcessHelper; + + public ProcessOvfUpdateForStoragePoolCommand(T parameters) { + this(parameters, null); + } + + public ProcessOvfUpdateForStoragePoolCommand(T parameters, CommandContext commandContext) { + super(parameters, commandContext); + setStoragePoolId(parameters.getStoragePoolId()); + ovfUpdateProcessHelper = new OvfUpdateProcessHelper(); + } + + protected OvfUpdateProcessHelper getOvfUpdateProcessHelper() { + return ovfUpdateProcessHelper; + } + + protected int loadConfigValue() { + return Config.<Integer> getValue(ConfigValues.OvfItemsCountPerUpdate); + } + + @Override + protected void executeCommand() { + itemsCountPerUpdate = loadConfigValue(); + proccessedDomains = new HashSet<>(); + StoragePool pool = getStoragePool(); + if (ovfOnAnyDomainSupported(pool)) { + proccessDomainsForOvfUpdate(pool); + } + + logInfoIfNeeded(pool, "Attempting to update VM OVFs in Data Center {0}", + pool.getName()); + initProcessedInfoLists(); + + updateOvfForVmsOfStoragePool(pool); + + logInfoIfNeeded(pool, "Successfully updated VM OVFs in Data Center {0}", + pool.getName()); + logInfoIfNeeded(pool, "Attempting to update template OVFs in Data Center {0}", + pool.getName()); + + updateOvfForTemplatesOfStoragePool(pool); + + logInfoIfNeeded(pool, "Successfully updated templates OVFs in Data Center {0}", + pool.getName()); + logInfoIfNeeded(pool, "Attempting to remove unneeded template/vm OVFs in Data Center {0}", + pool.getName()); + + removeOvfForTemplatesAndVmsOfStoragePool(pool); + + logInfoIfNeeded(pool, "Successfully removed unneeded template/vm OVFs in Data Center {0}", + pool.getName()); + + getReturnValue().setActionReturnValue(proccessedDomains); + setSucceeded(true); + } + + @Override + protected Map<String, Pair<String, String>> getExclusiveLocks() { + return Collections.singletonMap(getParameters().getStoragePoolId().toString(), + LockMessagesMatchUtil.makeLockingPair(LockingGroup.OVF_UPDATE, + VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED)); + } + + private void logInfoIfNeeded(StoragePool pool, String message, Object... args) { + // if supported, the info would be logged when executing for each domain + if (!ovfOnAnyDomainSupported(pool)) { + log.infoFormat(message, args); + } + } + + protected void proccessDomainsForOvfUpdate(StoragePool pool) { + List<StorageDomain> domainsInPool = getStorageDomainDAO().getAllForStoragePool(pool.getId()); + for (StorageDomain domain : domainsInPool) { + if (!domain.getStorageDomainType().isDataDomain() || domain.getStatus() != StorageDomainStatus.Active) { + continue; + } + + Integer ovfStoresCountForDomain = Config.<Integer> getValue(ConfigValues.StorageDomainOvfStoreCount); + List<StorageDomainOvfInfo> storageDomainOvfInfos = getStorageDomainOvfInfoDAO().getAllForDomain(domain.getId()); + + if (storageDomainOvfInfos.size() < ovfStoresCountForDomain) { + proccessedDomains.add(domain.getId()); + continue; + } + + for (StorageDomainOvfInfo storageDomainOvfInfo : storageDomainOvfInfos) { + if (storageDomainOvfInfo.getStatus() == StorageDomainOvfInfoStatus.OUTDATED) { + proccessedDomains.add(storageDomainOvfInfo.getStorageDomainId()); + break; + } + } + } + } + + /** + * Update ovfs for updated/newly vms since last run for the given storage pool + * + */ + protected void updateOvfForVmsOfStoragePool(StoragePool pool) { + Guid poolId = pool.getId(); + List<Guid> vmsIdsForUpdate = getVmAndTemplatesGenerationsDAO().getVmsIdsForOvfUpdate(poolId); + int i = 0; + while (i < vmsIdsForUpdate.size()) { + int size = Math.min(itemsCountPerUpdate, vmsIdsForUpdate.size() - i); + List<Guid> idsToProcess = vmsIdsForUpdate.subList(i, i + size); + i += size; + + Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = + populateVmsMetadataForOvfUpdate(idsToProcess); + if (!vmsAndTemplateMetadata.isEmpty()) { + performOvfUpdate(pool, vmsAndTemplateMetadata); + } + } + } + + /** + * Removes from the storage ovf files of vm/templates that were removed from the db since the last OvfDataUpdater + * run. + * + */ + protected void removeOvfForTemplatesAndVmsOfStoragePool(StoragePool pool) { + Guid poolId = pool.getId(); + removedOvfIdsInfo = getVmAndTemplatesGenerationsDAO().getIdsForOvfDeletion(poolId); + + if (!ovfOnAnyDomainSupported(pool)) { + for (Guid id : removedOvfIdsInfo) { + getOvfUpdateProcessHelper().executeRemoveVmInSpm(poolId, id, Guid.Empty); + } + } + + markDomainsWithOvfsForOvfUpdate(removedOvfIdsInfo); + getVmAndTemplatesGenerationsDAO().deleteOvfGenerations(removedOvfIdsInfo); + } + + protected void markDomainsWithOvfsForOvfUpdate(Collection<Guid> ovfIds) { + List<Guid> relevantDomains = getStorageDomainOvfInfoDAO().loadStorageDomainIdsForOvfIds(ovfIds); + proccessedDomains.addAll(relevantDomains); + getStorageDomainOvfInfoDAO().updateOvfUpdatedInfo(proccessedDomains, StorageDomainOvfInfoStatus.OUTDATED, StorageDomainOvfInfoStatus.DISABLED); + } + + /** + * Perform vdsm call which performs ovf update for the given metadata map + * + */ + protected void performOvfUpdate(StoragePool pool, + Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata) { + if (!ovfOnAnyDomainSupported(pool)) { + getOvfUpdateProcessHelper().executeUpdateVmInSpmCommand(pool.getId(), vmsAndTemplateMetadata, Guid.Empty); + } else { + markDomainsWithOvfsForOvfUpdate(vmsAndTemplateMetadata.keySet()); + } + + int i = 0; + while (i < proccessedIdsInfo.size()) { + int sizeToUpdate = Math.min(StorageConstants.OVF_MAX_ITEMS_PER_SQL_STATEMENT, proccessedIdsInfo.size() - i); + List<Guid> guidsForUpdate = proccessedIdsInfo.subList(i, i + sizeToUpdate); + List<Long> ovfGenerationsForUpdate = proccessedOvfGenerationsInfo.subList(i, i + sizeToUpdate); + List<String> ovfConfigurationsInfo = proccessedOvfConfigurationsInfo.subList(i, i + sizeToUpdate); + getVmAndTemplatesGenerationsDAO().updateOvfGenerations(guidsForUpdate, ovfGenerationsForUpdate, ovfConfigurationsInfo); + i += sizeToUpdate; + initProcessedInfoLists(); + } + } + + /** + * Creates and returns a map containing valid templates metadata + */ + protected Map<Guid, KeyValuePairCompat<String, List<Guid>>> populateTemplatesMetadataForOvfUpdate(List<Guid> idsToProcess) { + Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = + new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>(); + List<VmTemplate> templates = getVmTemplateDAO().getVmTemplatesByIds(idsToProcess); + + for (VmTemplate template : templates) { + if (VmTemplateStatus.Locked != template.getStatus()) { + updateTemplateDisksFromDb(template); + boolean verifyDisksNotLocked = verifyImagesStatus(template.getDiskList()); + if (verifyDisksNotLocked) { + getOvfUpdateProcessHelper().loadTemplateData(template); + Long currentDbGeneration = getVmStaticDAO().getDbGeneration(template.getId()); + // currentDbGeneration can be null in case that the template was deleted during the run of OvfDataUpdater. + if (currentDbGeneration != null && template.getDbGeneration() == currentDbGeneration) { + proccessedOvfConfigurationsInfo.add(getOvfUpdateProcessHelper().buildMetadataDictionaryForTemplate(template, vmsAndTemplateMetadata)); + proccessedIdsInfo.add(template.getId()); + proccessedOvfGenerationsInfo.add(template.getDbGeneration()); + proccessDisksDomains(template.getDiskList()); + } + } + } + } + + return vmsAndTemplateMetadata; + } + + protected void updateTemplateDisksFromDb(VmTemplate template) { + VmTemplateHandler.updateDisksFromDb(template); + } + + protected void updateVmDisksFromDb(VM vm) { + VmHandler.updateDisksFromDb(vm); + } + + public AuditLogType getAuditLogTypeValue() { + return getSucceeded() ? super.getAuditLogTypeValue() : AuditLogType.UPDATE_OVF_FOR_STORAGE_POOL_FAILED; + } + + /** + * Update ovfs for updated/added templates since last for the given storage pool + */ + protected void updateOvfForTemplatesOfStoragePool(StoragePool pool) { + Guid poolId = pool.getId(); + List<Guid> templateIdsForUpdate = + getVmAndTemplatesGenerationsDAO().getVmTemplatesIdsForOvfUpdate(poolId); + int i = 0; + while (i < templateIdsForUpdate.size()) { + int size = Math.min(templateIdsForUpdate.size() - i, itemsCountPerUpdate); + List<Guid> idsToProcess = templateIdsForUpdate.subList(i, i + size); + i += size; + + Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = + populateTemplatesMetadataForOvfUpdate(idsToProcess); + if (!vmsAndTemplateMetadata.isEmpty()) { + performOvfUpdate(pool, vmsAndTemplateMetadata); + } + } + } + + + /** + * Returns true if none of the given disks is in status 'LOCKED', otherwise false. + */ + protected boolean verifyImagesStatus(List<DiskImage> diskImages) { + for (DiskImage diskImage : diskImages) { + if (diskImage.getImageStatus() == ImageStatus.LOCKED) { + return false; + } + } + return true; + } + + /** + * Returns true if all snapshots have a valid status to use in the OVF. + */ + protected boolean verifySnapshotsStatus(List<Snapshot> snapshots) { + for (Snapshot snapshot : snapshots) { + if (snapshot.getStatus() != Snapshot.SnapshotStatus.OK) { + return false; + } + } + return true; + } + + /** + * Create and returns map contains valid vms metadata + */ + protected Map<Guid, KeyValuePairCompat<String, List<Guid>>> populateVmsMetadataForOvfUpdate(List<Guid> idsToProcess) { + Map<Guid, KeyValuePairCompat<String, List<Guid>>> vmsAndTemplateMetadata = + new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>(); + List<VM> vms = getVmDAO().getVmsByIds(idsToProcess); + for (VM vm : vms) { + if (VMStatus.ImageLocked != vm.getStatus()) { + updateVmDisksFromDb(vm); + if (!verifyImagesStatus(vm.getDiskList())) { + continue; + } + ArrayList<DiskImage> vmImages = getOvfUpdateProcessHelper().getVmImagesFromDb(vm); + if (!verifyImagesStatus(vmImages)) { + continue; + } + vm.setSnapshots(getSnapshotDAO().getAllWithConfiguration(vm.getId())); + if (!verifySnapshotsStatus(vm.getSnapshots())) { + continue; + } + + getOvfUpdateProcessHelper().loadVmData(vm); + Long currentDbGeneration = getVmStaticDAO().getDbGeneration(vm.getId()); + if (currentDbGeneration == null) { + log.warnFormat("currentDbGeneration of VM (name: {0}, id: {1}) is null, probably because the VM was deleted during the run of OvfDataUpdater.", + vm.getName(), + vm.getId()); + continue; + } + if (vm.getStaticData().getDbGeneration() == currentDbGeneration) { + proccessedOvfConfigurationsInfo.add(getOvfUpdateProcessHelper().buildMetadataDictionaryForVm(vm, vmsAndTemplateMetadata, vmImages)); + proccessedIdsInfo.add(vm.getId()); + proccessedOvfGenerationsInfo.add(vm.getStaticData().getDbGeneration()); + proccessDisksDomains(vm.getDiskList()); + } + } + } + return vmsAndTemplateMetadata; + } + + protected void proccessDisksDomains(List<DiskImage> disks) { + for (DiskImage disk : disks) { + proccessedDomains.addAll(disk.getStorageIds()); + } + } + + /** + * Init the lists contain the processed info. + */ + private void initProcessedInfoLists() { + proccessedIdsInfo = new LinkedList<>(); + proccessedOvfGenerationsInfo = new LinkedList<>(); + proccessedOvfConfigurationsInfo = new LinkedList<>(); + } + + protected boolean ovfOnAnyDomainSupported(StoragePool pool) { + return FeatureSupported.ovfStoreOnAnyDomain(pool.getcompatibility_version()); + } + + protected LockProperties applyLockProperties(LockProperties lockProperties) { + return lockProperties.withScope(LockProperties.Scope.Execution).withWait(true); + } +} diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/OvfDataUpdaterTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/OvfDataUpdaterTest.java index 8597a74..026311f 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/OvfDataUpdaterTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/OvfDataUpdaterTest.java @@ -1,900 +1,107 @@ package org.ovirt.engine.core.bll; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyList; -import static org.mockito.Matchers.anyMap; -import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; import java.util.Map; +import java.util.Set; -import org.apache.commons.collections.CollectionUtils; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.exceptions.base.MockitoException; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; -import org.ovirt.engine.core.common.businessentities.DiskImage; -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.StorageDomainOvfInfo; -import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfoStatus; -import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; +import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.StoragePool; -import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; -import org.ovirt.engine.core.common.businessentities.VM; -import org.ovirt.engine.core.common.businessentities.VMStatus; -import org.ovirt.engine.core.common.businessentities.VmStatic; -import org.ovirt.engine.core.common.businessentities.VmTemplate; -import org.ovirt.engine.core.common.businessentities.VmTemplateStatus; -import org.ovirt.engine.core.common.config.ConfigValues; -import org.ovirt.engine.core.common.constants.StorageConstants; -import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; -import org.ovirt.engine.core.compat.KeyValuePairCompat; -import org.ovirt.engine.core.dao.SnapshotDao; -import org.ovirt.engine.core.dao.StorageDomainDAO; -import org.ovirt.engine.core.dao.StorageDomainOvfInfoDao; import org.ovirt.engine.core.dao.StoragePoolDAO; -import org.ovirt.engine.core.dao.VmAndTemplatesGenerationsDAO; -import org.ovirt.engine.core.dao.VmDAO; -import org.ovirt.engine.core.dao.VmStaticDAO; -import org.ovirt.engine.core.dao.VmTemplateDAO; -import org.ovirt.engine.core.utils.MockConfigRule; -import org.ovirt.engine.core.utils.lock.EngineLock; -/** A test class for the {@link OvfDataUpdater} class */ @RunWith(MockitoJUnitRunner.class) public class OvfDataUpdaterTest { - private final int ITEMS_COUNT_PER_UPDATE = 100; - OvfDataUpdater updater; + private OvfDataUpdater ovfDataUpdater; + private Map<Guid, Map<Guid, Boolean>> map; + private StoragePool pool1; + private StoragePool pool2; @Mock private StoragePoolDAO storagePoolDAO; - @Mock - private VmAndTemplatesGenerationsDAO vmAndTemplatesGenerationsDAO; - - @Mock - private VmDAO vmDAO; - - @Mock - private VmStaticDAO vmStaticDAO; - - @Mock - private SnapshotDao snapshotDAO; - - @Mock - private VmTemplateDAO vmTemplateDAO; - - @Mock - private StorageDomainDAO storageDomainDAO; - - @Mock - private StorageDomainOvfInfoDao storageDomainOvfInfoDao; - - private StoragePool pool1; - private StoragePool pool2; - private Map<Guid, VM> vms; - private Map<Guid, VmTemplate> templates; - // those members are used to save the executed data during a run of the ovf data updater and are used for comprasion with the expected data needed to be executed - // in the end of each test. - private Guid executedUpdateStoragePoolId; - private Map<Guid, Map<Guid, KeyValuePairCompat<String, List<Guid>>>> executedUpdatedMetadataForStoragePool; - private Map<Guid, Map<Guid, Long>> executedUpdatedOvfGenerationIdsInDb; - private Guid executedUpdateStorageDomainId; - private Map<Guid, List<Guid>> executedRemovedIds; - private Map<Guid, List<Guid>> executedOvfUpdatedDomainForPool; - private Map<Guid, Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>>> poolDomainsOvfInfo; - private Guid executedRemoveStoragePoolId; - private Guid executedRemoveStorageDomainId; - - @ClassRule - public static MockConfigRule mcr = new MockConfigRule( - mockConfig(ConfigValues.StorageDomainOvfStoreCount, 1) - ); - - @Before public void setUp() { - updater = Mockito.spy(OvfDataUpdater.getInstance()); - doReturn(ITEMS_COUNT_PER_UPDATE).when(updater).reloadConfigValue(); - doReturn(new ArrayList<DiskImage>()).when(updater).getAllImageSnapshots(any(DiskImage.class)); - doReturn(false).when(updater).ovfOnAnyDomainSupported(any(StoragePool.class)); - doCallRealMethod().when(updater).ovfUpdate_timer(); - // init members - initMembers(); - - //init daos - doReturn(storagePoolDAO).when(updater).getStoragePoolDao(); - doReturn(vmAndTemplatesGenerationsDAO).when(updater).getVmAndTemplatesGenerationsDao(); - doReturn(vmDAO).when(updater).getVmDao(); - doReturn(vmStaticDAO).when(updater).getVmStaticDao(); - doReturn(snapshotDAO).when(updater).getSnapshotDao(); - doReturn(vmTemplateDAO).when(updater).getVmTemplateDao(); - doReturn(storageDomainOvfInfoDao).when(updater).getStorageDomainOvfInfoDao(); - doReturn(storageDomainDAO).when(updater).getStorageDomainDao(); - - - // mock ovf data updater methods - doNothing().when(updater).loadTemplateData(any(VmTemplate.class)); - doNothing().when(updater).loadVmData(any(VM.class)); - doNothing().when(updater).updateVmDisksFromDb(any(VM.class)); - doNothing().when(updater).addAuditLogError(anyString()); - doNothing().when(updater).updateTemplateDisksFromDb(any(VmTemplate.class)); - doReturn(true).when(updater).acquireLock(any(EngineLock.class)); - doNothing().when(updater).releaseLock(any(EngineLock.class)); - - // dao related mocks. - doReturn(1L).when(vmStaticDAO).getDbGeneration(any(Guid.class)); - List<Snapshot> snapshots = new ArrayList<Snapshot>(); - doReturn(snapshots).when(snapshotDAO).getAllWithConfiguration(any(Guid.class)); + ovfDataUpdater = Mockito.spy(OvfDataUpdater.getInstance()); + map = new HashMap<>(); + doReturn(storagePoolDAO).when(ovfDataUpdater).getStoragePoolDao(); mockAnswers(); - } - private void initMembers() { - executedUpdatedMetadataForStoragePool = new HashMap<Guid, Map<Guid, KeyValuePairCompat<String, List<Guid>>>>(); - executedRemovedIds = new HashMap<Guid, List<Guid>>(); - executedUpdatedOvfGenerationIdsInDb = new HashMap<Guid, Map<Guid, Long>>(); - vms = new HashMap<Guid, VM>(); - templates = new HashMap<Guid, VmTemplate>(); pool1 = new StoragePool(); pool1.setId(Guid.newGuid()); - pool1.setStatus(StoragePoolStatus.Maintenance); pool2 = new StoragePool(); pool2.setId(Guid.newGuid()); - pool2.setStatus(StoragePoolStatus.Maintenance); - poolDomainsOvfInfo = new HashMap<>(); - performStoragePoolInitOps(pool1); - performStoragePoolInitOps(pool2); + + doReturn(Arrays.asList(pool1, pool2)).when(storagePoolDAO).getAllByStatus(StoragePoolStatus.Up); } - private void performStoragePoolInitOps(StoragePool pool) { - executedUpdatedMetadataForStoragePool.put(pool.getId(), - new HashMap<Guid, KeyValuePairCompat<String, List<Guid>>>()); - executedRemovedIds.put(pool.getId(), new LinkedList<Guid>()); - executedOvfUpdatedDomainForPool = new HashMap<>(); - executedUpdatedOvfGenerationIdsInDb.put(pool.getId(), new HashMap<Guid, Long>()); + @Test + public void poolUpdateOvfStoreOnAnyDomainSupported() throws Exception { + doReturn(true).when(ovfDataUpdater).ovfOnAnyDomainSupported(any(StoragePool.class)); + ovfDataUpdater.ovfUpdate_timer(); + verify(Boolean.TRUE); + } - Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>> domainOvfInfos = new HashMap<>(); - - for (int i=0; i<2; i++) { - Guid domainId = Guid.newGuid(); - StorageDomainOvfInfo ovfInfo = new StorageDomainOvfInfo(domainId, null, null, StorageDomainOvfInfoStatus.UPDATED, null); - StorageDomain domain = new StorageDomain(); - domain.setId(domainId); - domain.setStoragePoolIsoMapData(new StoragePoolIsoMap(domainId, pool.getId(), StorageDomainStatus.Active)); - domainOvfInfos.put(domainId, new Pair<>(Arrays.asList(ovfInfo), domain)); - } - poolDomainsOvfInfo.put(pool.getId(), domainOvfInfos); + @Test + public void poolUpdateOvfStoreOnAnyDomainUnsupported() throws Exception { + doReturn(false).when(ovfDataUpdater).ovfOnAnyDomainSupported(any(StoragePool.class)); + ovfDataUpdater.ovfUpdate_timer(); + verify(Boolean.FALSE); } private void mockAnswers() { - doAnswer(new Answer<String>() { + doAnswer(new Answer<VdcReturnValueBase>() { @Override - public String answer(InvocationOnMock invocation) throws Throwable { - VM vm = (VM) invocation.getArguments()[0]; - return vm.getId().toString(); - } - - }).when(updater).generateVmMetadata(any(VM.class), any(ArrayList.class)); - - doAnswer(new Answer<String>() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - VmTemplate template = (VmTemplate) invocation.getArguments()[0]; - return template.getId().toString(); - } - - }).when(updater).generateVmTemplateMetadata(any(VmTemplate.class), anyList()); - - doAnswer(new Answer<List<VM>>() { - @Override - public List<VM> answer(InvocationOnMock invocation) throws Throwable { - List<Guid> neededIds = (List<Guid>) invocation.getArguments()[0]; - List<VM> toReturn = new LinkedList<VM>(); - for (Guid id : neededIds) { - toReturn.add(vms.get(id)); + public VdcReturnValueBase answer(InvocationOnMock invocation) throws Throwable { + VdcReturnValueBase returnValueBase = new VdcReturnValueBase(); + Map<Guid, Boolean> domains = new HashMap<>(); + Set<Guid> domainIds = new HashSet<>(); + domainIds.add(Guid.newGuid()); + domainIds.add(Guid.newGuid()); + for (Guid domainId : domainIds) { + domains.put(domainId, Boolean.FALSE); } - return toReturn; + returnValueBase.setActionReturnValue(domainIds); + Guid storagePoolId = (Guid) invocation.getArguments()[0]; + map.put(storagePoolId, domains); + return returnValueBase; } - }).when(vmDAO).getVmsByIds(anyList()); - - doAnswer(new Answer<List<VmTemplate>>() { - @Override - public List<VmTemplate> answer(InvocationOnMock invocation) throws Throwable { - List<Guid> neededIds = (List<Guid>) invocation.getArguments()[0]; - List<VmTemplate> toReturn = new LinkedList<VmTemplate>(); - for (Guid id : neededIds) { - toReturn.add(templates.get(id)); - } - return toReturn; - } - - }).when(vmTemplateDAO).getVmTemplatesByIds(anyList()); - - doAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - executedUpdateStoragePoolId = (Guid) invocation.getArguments()[0]; - Map<Guid, KeyValuePairCompat<String, List<Guid>>> updateMap = - (Map<Guid, KeyValuePairCompat<String, List<Guid>>>) invocation.getArguments()[1]; - executedUpdatedMetadataForStoragePool.get(executedUpdateStoragePoolId).putAll(updateMap); - executedUpdateStorageDomainId = (Guid) invocation.getArguments()[2]; - assertTrue("too many ovfs were sent in one vdsm call", updateMap.size() <= ITEMS_COUNT_PER_UPDATE); - return true; - } - - }).when(updater).executeUpdateVmInSpmCommand(any(Guid.class), anyMap(), any(Guid.class)); - - doAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - executedUpdateStoragePoolId = ((StoragePool) invocation.getArguments()[0]).getId(); - return (Boolean) invocation.callRealMethod(); - } - - }).when(updater).proceedPoolOvfUpdate(any(StoragePool.class)); - - doAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Guid poolId = (Guid) invocation.getArguments()[0]; - Guid domainId = (Guid) invocation.getArguments()[1]; - List<Guid> executedDomains = executedOvfUpdatedDomainForPool.get(poolId); - if (executedDomains == null) { - executedDomains = new LinkedList<>(); - executedOvfUpdatedDomainForPool.put(poolId, executedDomains); - } - executedDomains.add(domainId); - return true; - } - - }).when(updater).performOvfUpdateForDomain(any(Guid.class), any(Guid.class)); - - doAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - executedRemoveStoragePoolId = (Guid) invocation.getArguments()[0]; - executedRemovedIds.get(executedRemoveStoragePoolId).add((Guid) invocation.getArguments()[1]); - executedRemoveStorageDomainId = (Guid) invocation.getArguments()[2]; - return true; - } - - }).when(updater).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + }).when(ovfDataUpdater).performOvfUpdateForStoragePool(any(Guid.class)); doAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { - List<Guid> ids = (List<Guid>) invocation.getArguments()[0]; - List<Long> values = (List<Long>) invocation.getArguments()[1]; - assertFalse("update of ovf version in db shouldn't be called with an empty value list", - values.isEmpty()); - assertTrue("update of ovf version in db shouldn't be called with more items then MAX_ITEMS_PER_SQL_STATEMENT", - values.size() <= StorageConstants.OVF_MAX_ITEMS_PER_SQL_STATEMENT); - assertEquals("the size of the list of ids for update is not the same as the size of the " + - "list with the new ovf values", values.size(), ids.size()); - Guid[] ids_array = ids.toArray(new Guid[ids.size()]); - Long[] values_array = values.toArray(new Long[values.size()]); - for (int i = 0; i < ids_array.length; i++) { - executedUpdatedOvfGenerationIdsInDb.get(executedUpdateStoragePoolId).put(ids_array[i], - values_array[i]); - } + Guid storagePoolId = (Guid) invocation.getArguments()[0]; + Guid storageDomainId = (Guid) invocation.getArguments()[1]; + map.get(storagePoolId).put(storageDomainId, Boolean.TRUE); return null; } - }).when(vmAndTemplatesGenerationsDAO).updateOvfGenerations(anyList(), anyList(), anyList()); - - doAnswer(new Answer<Object>() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - StoragePoolStatus desiredStatus = (StoragePoolStatus) invocation.getArguments()[0]; - List<StoragePool> toReturn = new LinkedList<>(); - for (StoragePool pool : buildStoragePoolsList()) { - if (desiredStatus.equals(pool.getStatus())) { - toReturn.add(pool); - } - } - - return toReturn; - } - - }).when(storagePoolDAO).getAllByStatus(any(StoragePoolStatus.class)); - - doAnswer(new Answer<Object>() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Guid poolId = (Guid) invocation.getArguments()[0]; - List<StorageDomain> toReturn = new LinkedList<>(); - Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>> domainsMap = poolDomainsOvfInfo.get(poolId); - for (Pair<List<StorageDomainOvfInfo>, StorageDomain> pair : domainsMap.values()) { - toReturn.add(pair.getSecond()); - } - - return toReturn; - } - - }).when(storageDomainDAO).getAllForStoragePool(any(Guid.class)); - - doAnswer(new Answer<Object>() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Guid domainId = (Guid) invocation.getArguments()[0]; - for (Map.Entry<Guid, Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>>> entry : poolDomainsOvfInfo.entrySet()) { - Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>> domainsInfo = entry.getValue(); - Pair<List<StorageDomainOvfInfo>, StorageDomain> pair = domainsInfo.get(domainId); - if (pair != null) { - return pair.getFirst(); - } - - } - return null; - } - - }).when(storageDomainOvfInfoDao).getAllForDomain(any(Guid.class)); + }).when(ovfDataUpdater).performOvfUpdateForDomain(any(Guid.class), any(Guid.class)); } - private List<StoragePool> buildStoragePoolsList() { - return Arrays.asList(pool1, pool2); - } - - private VM createVm(Guid id, VMStatus status) { - VM vm = new VM(); - vm.setStatus(status); - vm.setStaticData(createVmStatic()); - vm.setId(id); - return vm; - } - - public VmStatic createVmStatic() { - VmStatic vms = new VmStatic(); - vms.setDbGeneration(1L); - return vms; - } - - private VmTemplate createVmTemplate(Guid id, VmTemplateStatus templateStatus) { - VmTemplate template = new VmTemplate(); - template.setStatus(templateStatus); - template.setDbGeneration(1L); - template.setId(id); - return template; - } - - private List<Guid> generateGuidList(int size) { - List<Guid> toReturn = new LinkedList<Guid>(); - for (int i = 0; i < size; i++) { - toReturn.add(Guid.newGuid()); - } - return toReturn; - } - - private Map<Guid, VM> generateVmsMapByGuids(List<Guid> ids, - int diskCount, - VMStatus vmStatus, - ImageStatus diskStatus, - Guid poolId) { - Map<Guid, VM> toReturn = new HashMap<Guid, VM>(); - for (Guid id : ids) { - VM vm = createVm(id, vmStatus); - for (int i = 0; i < diskCount; i++) { - DiskImage image = createDiskImage(diskStatus, poolId); - vm.getDiskMap().put(image.getId(), image); - vm.getDiskList().add(image); - } - toReturn.put(vm.getId(), vm); - } - return toReturn; - } - - private Map<Guid, VmTemplate> generateVmTemplatesMapByGuids(List<Guid> ids, - int diskCount, - VmTemplateStatus templateStatus, - ImageStatus diskStatus, Guid poolId) { - Map<Guid, VmTemplate> toReturn = new HashMap<Guid, VmTemplate>(); - for (Guid id : ids) { - VmTemplate template = createVmTemplate(id, templateStatus); - for (int i = 0; i < diskCount; i++) { - DiskImage image = createDiskImage(diskStatus, poolId); - template.getDiskTemplateMap().put(image.getId(), image); - template.getDiskList().add(image); - } - toReturn.put(template.getId(), template); - } - return toReturn; - } - - private DiskImage createDiskImage(ImageStatus status, Guid poolId) { - DiskImage disk = new DiskImage(); - disk.setId(Guid.newGuid()); - disk.setImageStatus(status); - ArrayList<Guid> storageIds = new ArrayList<>(); - Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>> domains = poolDomainsOvfInfo.get(poolId); - storageIds.add(domains.keySet().iterator().next()); - disk.setStorageIds(storageIds); - return disk; - } - - private void initTestForPool(StoragePool pool, List<Guid> vmGuids, List<Guid> templatesGuids, List<Guid> removedGuids) { - Guid poolId = pool.getId(); - doReturn(vmGuids).when(vmAndTemplatesGenerationsDAO).getVmsIdsForOvfUpdate(poolId); - doReturn(templatesGuids).when(vmAndTemplatesGenerationsDAO).getVmTemplatesIdsForOvfUpdate(poolId); - doReturn(removedGuids).when(vmAndTemplatesGenerationsDAO).getIdsForOvfDeletion(poolId); - pool.setStatus(StoragePoolStatus.Up); - } - - private void verifyCorrectOvfDataUpdaterRun(StoragePool storagePool, - Collection<Guid> needToBeUpdated, - Collection<Guid> removedGuids) { - Guid storagePoolId = storagePool.getId(); - Map<Guid, KeyValuePairCompat<String, List<Guid>>> storagePoolMetadataUpdatedMap = - executedUpdatedMetadataForStoragePool.get(storagePoolId); - Map<Guid, Long> storagePoolUpdateOvfGenerationsInDb = executedUpdatedOvfGenerationIdsInDb.get(storagePoolId); - if (!updater.ovfOnAnyDomainSupported(storagePool)) { - assertTrue("not all needed vms/templates were updated in vdsm", - CollectionUtils.isEqualCollection(storagePoolMetadataUpdatedMap.keySet(), - needToBeUpdated)); - for (Map.Entry<Guid, KeyValuePairCompat<String, List<Guid>>> entry : storagePoolMetadataUpdatedMap - .entrySet()) { - assertEquals("wrong ovf data stored in storage for vm/template", - entry.getKey().toString(), - entry.getValue().getKey()); + private void verify(Boolean expected) { + for (Map<Guid, Boolean> map1 : map.values()) { + for (Boolean b : map1.values()) { + assertEquals(expected, b); } } - assertTrue("not all needed vms/templates were updated in db", - CollectionUtils.isEqualCollection(storagePoolUpdateOvfGenerationsInDb.keySet(), - needToBeUpdated)); - - for (Map.Entry<Guid, Long> storagePoolGenerationEntry : storagePoolUpdateOvfGenerationsInDb.entrySet()) { - boolean isCorrectVersion = false; - if (vms.get(storagePoolGenerationEntry.getKey()) != null) { - isCorrectVersion = - storagePoolGenerationEntry.getValue() - .equals(vms.get(storagePoolGenerationEntry.getKey()).getDbGeneration()); - } else if (templates.get(storagePoolGenerationEntry.getKey()) != null) { - isCorrectVersion = - storagePoolGenerationEntry.getValue() - .equals(templates.get(storagePoolGenerationEntry.getKey()).getDbGeneration()); - } - assertTrue("wrong new ovf version persisted for vm/template", isCorrectVersion); - } - - if (!updater.ovfOnAnyDomainSupported(storagePool)) { - assertTrue("not all needed vms/templates were removed from vdsm", - CollectionUtils.isEqualCollection(removedGuids, executedRemovedIds.get(storagePoolId))); - } - } - - private void addVms(List<Guid> vmGuids, int diskCount, VMStatus vmStatus, ImageStatus vmImageStatus, Guid poolId) { - vms.putAll(generateVmsMapByGuids(vmGuids, diskCount, vmStatus, vmImageStatus, poolId)); - - } - - private void verifyOvfUpdatedForSupportedPools(List<Guid> poolsRequiredUpdate, - Map<Guid, List<Guid>> domainsRequiredUpdateForPool) { - assertTrue("wrong number of pools was updated", - executedOvfUpdatedDomainForPool.keySet().size() == poolsRequiredUpdate.size()); - for (Guid storagePoolId : poolsRequiredUpdate) { - List<Guid> updatedDomainsForPool = executedOvfUpdatedDomainForPool.get(storagePoolId); - Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>> domainOfPool = poolDomainsOvfInfo.get(storagePoolId); - for (Guid updatedDomainForPool : updatedDomainsForPool) { - assertTrue("ovf update for domain has been executed with wrong pool", - domainOfPool.containsKey(updatedDomainForPool)); - if (domainsRequiredUpdateForPool.get(storagePoolId) != null) { - assertTrue("ovf updated hasn't been executed on needed domain", - domainsRequiredUpdateForPool.get(storagePoolId).contains(updatedDomainForPool)); - } - } - } - } - - private void addTemplates(List<Guid> templatesGuids, - int diskCount, - VmTemplateStatus templateStatus, - ImageStatus templateImageStatus, Guid poolId) { - templates.putAll(generateVmTemplatesMapByGuids(templatesGuids, - diskCount, - templateStatus, - templateImageStatus, - poolId)); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountTwoPoolsOvfOnAnyDomainSupported() { - testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountTwoPools(true); - verifyOvfUpdatedForSupportedPools(Arrays.asList(pool1.getId(), pool2.getId()), - Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountTwoPoolsOvfOnAnyDomainUnsupported() { - testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountTwoPools(false); - } - - public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountTwoPools(boolean ovfOnAnyDomainSupported) { - int size = 3 * ITEMS_COUNT_PER_UPDATE + 10; - - doReturn(ovfOnAnyDomainSupported).when(updater).ovfOnAnyDomainSupported(any(StoragePool.class)); - List<Guid> vmGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - List<Guid> removedGuids = generateGuidList(size); - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - - List<Guid> vmGuids2 = generateGuidList(size); - List<Guid> templatesGuids2 = generateGuidList(size); - List<Guid> removedGuids2 = generateGuidList(size); - addVms(vmGuids2, 2, VMStatus.Down, ImageStatus.OK, pool2.getId()); - addTemplates(templatesGuids2, 2, VmTemplateStatus.OK, ImageStatus.OK, pool2.getId()); - initTestForPool(pool2, vmGuids2, templatesGuids2, removedGuids2); - - updater.ovfUpdate_timer(); - - verify(updater, times(numberOfTimesToBeCalled(size, true) * 2)).performOvfUpdate(any(StoragePool.class), - anyMap()); - - if (!ovfOnAnyDomainSupported) { - verify(updater, times(size * 2)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - - List<Guid> idsThatNeededToBeUpdated = new LinkedList<Guid>(vmGuids); - idsThatNeededToBeUpdated.addAll(templatesGuids); - - List<Guid> idsThatNeededToBeUpdated2 = new LinkedList<Guid>(vmGuids2); - idsThatNeededToBeUpdated2.addAll(templatesGuids2); - - verifyCorrectOvfDataUpdaterRun(pool1, idsThatNeededToBeUpdated, removedGuids); - verifyCorrectOvfDataUpdaterRun(pool2, idsThatNeededToBeUpdated2, removedGuids2); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveExceptionInOnePool() { - int size = 3 * ITEMS_COUNT_PER_UPDATE + 10; - - List<Guid> vmGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - List<Guid> removedGuids = generateGuidList(size); - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - - List<Guid> vmGuids2 = generateGuidList(size); - List<Guid> templatesGuids2 = generateGuidList(size); - List<Guid> removedGuids2 = generateGuidList(size); - addVms(vmGuids2, 2, VMStatus.Down, ImageStatus.OK, pool2.getId()); - addTemplates(templatesGuids2, 2, VmTemplateStatus.OK, ImageStatus.OK, pool2.getId()); - initTestForPool(pool2, vmGuids2, templatesGuids2, removedGuids2); - - doAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - executedUpdateStoragePoolId = (Guid) invocation.getArguments()[0]; - if (executedUpdateStoragePoolId.equals(pool1.getId())) { - throw new MockitoException("testOvfDataUpdaterRunWithUpdateAndRemoveExceptionInOnePool: intendent exception"); - } - Map<Guid, KeyValuePairCompat<String, List<Guid>>> updateMap = - (Map<Guid, KeyValuePairCompat<String, List<Guid>>>) invocation.getArguments()[1]; - executedUpdatedMetadataForStoragePool.get(executedUpdateStoragePoolId).putAll(updateMap); - executedUpdateStorageDomainId = (Guid) invocation.getArguments()[2]; - assertTrue("too many ovfs were sent in one vdsm call", updateMap.size() <= ITEMS_COUNT_PER_UPDATE); - return true; - } - - }).when(updater).executeUpdateVmInSpmCommand(any(Guid.class), anyMap(), any(Guid.class)); - - updater.ovfUpdate_timer(); - - // + 1 as the exception is thrown during the first call to this method during first update execution for the - // first pool. - int numOfExpectedRuns = numberOfTimesToBeCalled(size, true) + 1; - verify(updater, times(numOfExpectedRuns)).performOvfUpdate(any(StoragePool.class), - anyMap()); - verify(updater, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - - List<Guid> idsToBeUpdated = new LinkedList<Guid>(vmGuids2); - idsToBeUpdated.addAll(templatesGuids2); - verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), Collections.<Guid> emptyList()); - verifyCorrectOvfDataUpdaterRun(pool2, idsToBeUpdated, removedGuids2); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePoolOvfOnAnyDomainSupported() { - testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePool(true); - verifyOvfUpdatedForSupportedPools(Arrays.asList(pool1.getId()), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePoolOvfOnAnyDomainUnsupported() { - testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePool(false); - } - - public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePool(boolean ovfOnAnyDomainSupported) { - int size = 3 * ITEMS_COUNT_PER_UPDATE + 10; - doReturn(ovfOnAnyDomainSupported).when(updater).ovfOnAnyDomainSupported(any(StoragePool.class)); - List<Guid> vmGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - List<Guid> removedGuids = generateGuidList(size); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - updater.ovfUpdate_timer(); - - verify(updater, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - - List<Guid> idsThatNeededToBeUpdated = new LinkedList<Guid>(vmGuids); - idsThatNeededToBeUpdated.addAll(templatesGuids); - - verifyCorrectOvfDataUpdaterRun(pool1, idsThatNeededToBeUpdated, removedGuids); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCountOvfOnAnyDomainSupported() { - testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCount(true); - verifyOvfUpdatedForSupportedPools(Arrays.asList(pool1.getId()), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCountOvfOnAnyDomainUnupported() { - testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCount(false); - } - - public void testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCount(boolean ovfOnAnyDomainSupported) { - int size = ITEMS_COUNT_PER_UPDATE - 1; - - doReturn(ovfOnAnyDomainSupported).when(updater).ovfOnAnyDomainSupported(any(StoragePool.class)); - List<Guid> vmGuids = generateGuidList(size); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - List<Guid> templatesGuids = generateGuidList(size); - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - List<Guid> removedGuids = generateGuidList(size); - - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - updater.ovfUpdate_timer(); - verify(updater, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - List<Guid> needToBeUpdated = new LinkedList<Guid>(vmGuids); - needToBeUpdated.addAll(templatesGuids); - verifyCorrectOvfDataUpdaterRun(pool1, needToBeUpdated, removedGuids); - } - - @Test - public void testOvfDataUpdaterAllDisksAreLockedNonToRemoveOvfOnAnyDomainSupported() { - testOvfDataUpdaterAllDisksAreLockedNonToRemove(true); - verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterAllDisksAreLockedNonToRemoveOvfOnAnyDomainUnupported() { - testOvfDataUpdaterAllDisksAreLockedNonToRemove(false); - } - - public void testOvfDataUpdaterAllDisksAreLockedNonToRemove(boolean ovfOnAnyDomainSupported) { - int size = ITEMS_COUNT_PER_UPDATE - 1; - - doReturn(ovfOnAnyDomainSupported).when(updater).ovfOnAnyDomainSupported(any(StoragePool.class)); - List<Guid> vmGuids = generateGuidList(size); - List<Guid> removedGuids = Collections.emptyList(); - List<Guid> templatesGuids = generateGuidList(size); - - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.LOCKED, pool1.getId()); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.LOCKED, pool1.getId()); - - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - updater.ovfUpdate_timer(); - verify(updater, never()).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, never()).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), removedGuids); - } - - @Test - public void testOvfDataUpdaterPartOfDisksAreLockedOvfOnAnyDomainSupported() { - testOvfDataUpdaterAllDisksAreLockedNonToRemove(true); - verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterPartOfDisksAreLockedOvfOnAnyDomainUnupported() { - testOvfDataUpdaterAllDisksAreLockedNonToRemove(false); - } - - public void testOvfDataUpdaterPartOfDisksAreLocked(boolean ovfOnAnyDomainSupported) { - int size = ITEMS_COUNT_PER_UPDATE - 1; - // unlocked vms/templates - List<Guid> vmGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - - // locked vms/templates - List<Guid> lockedVmGuids = generateGuidList(size); - List<Guid> lockedTemplatesGuids = generateGuidList(size); - addVms(lockedVmGuids, 2, VMStatus.Down, ImageStatus.LOCKED, pool1.getId()); - addTemplates(lockedTemplatesGuids, 2, VmTemplateStatus.OK, ImageStatus.LOCKED, pool1.getId()); - // ids for removal - List<Guid> removedGuids = generateGuidList(size); - - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - updater.ovfUpdate_timer(); - verify(updater, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - // list of ids that should have been updated. - List<Guid> needToBeUpdated = new LinkedList<Guid>(vmGuids); - needToBeUpdated.addAll(templatesGuids); - verifyCorrectOvfDataUpdaterRun(pool1, needToBeUpdated, removedGuids); - } - - private int numberOfTimesToBeCalled(int size, boolean isBothVmAndTemplates) { - int toReturn = 0; - if (size % ITEMS_COUNT_PER_UPDATE != 0) { - toReturn++; - } - toReturn += size / ITEMS_COUNT_PER_UPDATE; - if (isBothVmAndTemplates) { - toReturn = toReturn * 2; - } - return toReturn; - } - - @Test - public void testOvfDataUpdaterAllVmsAndTemplatesAreLockedOvfOnAnyDomainSupported() { - testOvfDataUpdaterAllVmsAndTemplatesAreLocked(true); - verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterAllVmsAndTemplatesAreLockedOvfOnAnyDomainUnupported() { - testOvfDataUpdaterAllVmsAndTemplatesAreLocked(false); - } - - public void testOvfDataUpdaterAllVmsAndTemplatesAreLocked(boolean ovfOnAnyDomainSupported) { - int size = ITEMS_COUNT_PER_UPDATE - 1; - List<Guid> vmGuids = generateGuidList(size); - addVms(vmGuids, 2, VMStatus.ImageLocked, ImageStatus.OK, pool1.getId()); - List<Guid> removedGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - addTemplates(templatesGuids, 2, VmTemplateStatus.Locked, ImageStatus.OK, pool1.getId()); - - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - updater.ovfUpdate_timer(); - verify(updater, never()).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), removedGuids); - } - - @Test - public void testOvfDataUpdaterPartOfVmsAndTemplatesAreLockedOvfOnAnyDomainSupported() { - testOvfDataUpdaterPartOfVmsAndTemplatesAreLocked(true); - verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testOvfDataUpdaterPartOfVmsAndTemplatesAreLockedOvfOnAnyDomainUnupported() { - testOvfDataUpdaterPartOfVmsAndTemplatesAreLocked(false); - } - - public void testOvfDataUpdaterPartOfVmsAndTemplatesAreLocked(boolean ovfOnAnyDomainSupported) { - int size = ITEMS_COUNT_PER_UPDATE; - List<Guid> vmGuids = generateGuidList(size); - List<Guid> removedGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - - addVms(vmGuids, 2, VMStatus.ImageLocked, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuids, 2, VmTemplateStatus.Locked, ImageStatus.OK, pool1.getId()); - - List<Guid> vmGuidsUnlocked = generateGuidList(size); - List<Guid> templatesGuidsUnlocked = generateGuidList(size); - - addVms(vmGuidsUnlocked, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuidsUnlocked, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - - vmGuids.addAll(vmGuidsUnlocked); - templatesGuids.addAll(templatesGuidsUnlocked); - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - updater.ovfUpdate_timer(); - - List<Guid> neededToBeUpdated = new LinkedList<Guid>(vmGuidsUnlocked); - neededToBeUpdated.addAll(templatesGuidsUnlocked); - verify(updater, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - verifyCorrectOvfDataUpdaterRun(pool1, neededToBeUpdated, removedGuids); - } - - @Test - public void testUpdatedDbGenerationOvfOnAnyDomainSupported() { - testUpdatedDbGeneration(true); - verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); - } - - @Test - public void testUpdatedDbGenerationOvfOnAnyDomainUnupported() { - testUpdatedDbGeneration(false); - } - - public void testUpdatedDbGeneration(boolean ovfOnAnyDomainSupported) { - int size = 3 * ITEMS_COUNT_PER_UPDATE + 10; - List<Guid> vmGuids = generateGuidList(size); - List<Guid> templatesGuids = generateGuidList(size); - List<Guid> removedGuids = Collections.emptyList(); - addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); - addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); - - initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); - - doReturn(2L).when(vmStaticDAO).getDbGeneration(any(Guid.class)); - - updater.ovfUpdate_timer(); - - verify(updater, never()).performOvfUpdate(any(StoragePool.class), anyMap()); - if (!ovfOnAnyDomainSupported) { - verify(updater, never()).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); - } - - List<Guid> idsThatNeededToBeUpdated = new LinkedList<Guid>(vmGuids); - idsThatNeededToBeUpdated.addAll(templatesGuids); - - verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), removedGuids); - } - - @Test - public void testUpdateCalledForUnupdatedDomain() { - Guid poolId = pool1.getId(); - StorageDomainOvfInfo ovfInfo = poolDomainsOvfInfo.get(poolId).entrySet().iterator().next().getValue().getFirst().get(0); - ovfInfo.setStatus(StorageDomainOvfInfoStatus.OUTDATED); - doReturn(true).when(updater).ovfOnAnyDomainSupported(any(StoragePool.class)); - initTestForPool(pool1, - Collections.<Guid> emptyList(), - Collections.<Guid> emptyList(), - Collections.<Guid> emptyList()); - updater.ovfUpdate_timer(); - verify(updater, never()).performOvfUpdate(any(StoragePool.class), anyMap()); - Map<Guid, List<Guid>> domainsRequiredUpdateForPool = - Collections.singletonMap(poolId, Arrays.asList(ovfInfo.getStorageDomainId())); - verifyOvfUpdatedForSupportedPools(Arrays.asList(poolId), domainsRequiredUpdateForPool); } } diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommandTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommandTest.java new file mode 100644 index 0000000..7f11a1e --- /dev/null +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/ProcessOvfUpdateForStoragePoolCommandTest.java @@ -0,0 +1,748 @@ +package org.ovirt.engine.core.bll; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyList; +import static org.mockito.Matchers.anyMap; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; +import org.ovirt.engine.core.common.action.StoragePoolParametersBase; +import org.ovirt.engine.core.common.businessentities.DiskImage; +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.StorageDomainOvfInfo; +import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfoStatus; +import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; +import org.ovirt.engine.core.common.businessentities.StoragePool; +import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap; +import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VMStatus; +import org.ovirt.engine.core.common.businessentities.VmStatic; +import org.ovirt.engine.core.common.businessentities.VmTemplate; +import org.ovirt.engine.core.common.businessentities.VmTemplateStatus; +import org.ovirt.engine.core.common.config.ConfigValues; +import org.ovirt.engine.core.common.constants.StorageConstants; +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.compat.KeyValuePairCompat; +import org.ovirt.engine.core.dao.SnapshotDao; +import org.ovirt.engine.core.dao.StorageDomainDAO; +import org.ovirt.engine.core.dao.StorageDomainOvfInfoDao; +import org.ovirt.engine.core.dao.StoragePoolDAO; +import org.ovirt.engine.core.dao.VmAndTemplatesGenerationsDAO; +import org.ovirt.engine.core.dao.VmDAO; +import org.ovirt.engine.core.dao.VmStaticDAO; +import org.ovirt.engine.core.dao.VmTemplateDAO; +import org.ovirt.engine.core.utils.MockConfigRule; + +@RunWith(MockitoJUnitRunner.class) +public class ProcessOvfUpdateForStoragePoolCommandTest { + private final static int ITEMS_COUNT_PER_UPDATE = 100; + private ProcessOvfUpdateForStoragePoolCommand<StoragePoolParametersBase> command; + + @Mock + private StoragePoolDAO storagePoolDAO; + + @Mock + private VmAndTemplatesGenerationsDAO vmAndTemplatesGenerationsDAO; + + @Mock + private VmDAO vmDAO; + + @Mock + private VmStaticDAO vmStaticDAO; + + @Mock + private SnapshotDao snapshotDAO; + + @Mock + private VmTemplateDAO vmTemplateDAO; + + @Mock + private StorageDomainDAO storageDomainDAO; + + @Mock + private StorageDomainOvfInfoDao storageDomainOvfInfoDao; + + private OvfUpdateProcessHelper ovfUpdateProcessHelper; + + private StoragePool pool1; + private Map<Guid, VM> vms; + private Map<Guid, VmTemplate> templates; + private Map<Guid, KeyValuePairCompat<String, List<Guid>>> executedUpdatedMetadataForStoragePool; + private Map<Guid, Long> executedUpdatedOvfGenerationIdsInDb; + private Set<Guid> executedRemovedIds; + private Set<Guid> executedOvfUpdatedDomains; + private Map<Guid, Pair<List<StorageDomainOvfInfo>, StorageDomain>> poolDomainsOvfInfo; + + @ClassRule + public static MockConfigRule mcr = new MockConfigRule( + mockConfig(ConfigValues.StorageDomainOvfStoreCount, 1) + ); + + + @Before + public void setUp() { + command = Mockito.spy(new ProcessOvfUpdateForStoragePoolCommand<>(new StoragePoolParametersBase())); + ovfUpdateProcessHelper = Mockito.spy(new OvfUpdateProcessHelper()); + doReturn(ITEMS_COUNT_PER_UPDATE).when(command).loadConfigValue(); + doReturn(new ArrayList<DiskImage>()).when(ovfUpdateProcessHelper).getAllImageSnapshots(any(DiskImage.class)); + doReturn(false).when(command).ovfOnAnyDomainSupported(any(StoragePool.class)); + doCallRealMethod().when(command).executeCommand(); + // init members + initMembers(); + + //init daos + doReturn(storagePoolDAO).when(command).getStoragePoolDAO(); + doReturn(vmAndTemplatesGenerationsDAO).when(command).getVmAndTemplatesGenerationsDAO(); + doReturn(vmDAO).when(command).getVmDAO(); + doReturn(vmStaticDAO).when(command).getVmStaticDAO(); + doReturn(snapshotDAO).when(command).getSnapshotDAO(); + doReturn(vmTemplateDAO).when(command).getVmTemplateDAO(); + doReturn(storageDomainOvfInfoDao).when(command).getStorageDomainOvfInfoDAO(); + doReturn(storageDomainDAO).when(command).getStorageDomainDAO(); + + doReturn(ovfUpdateProcessHelper).when(command).getOvfUpdateProcessHelper(); + + + // mock ovf data updater methods + doNothing().when(ovfUpdateProcessHelper).loadTemplateData(any(VmTemplate.class)); + doNothing().when(ovfUpdateProcessHelper).loadVmData(any(VM.class)); + doNothing().when(command).updateVmDisksFromDb(any(VM.class)); + doNothing().when(command).updateTemplateDisksFromDb(any(VmTemplate.class)); + + // dao related mocks. + doReturn(1L).when(vmStaticDAO).getDbGeneration(any(Guid.class)); + doReturn(pool1).when(command).getStoragePool(); + List<Snapshot> snapshots = new ArrayList<>(); + doReturn(snapshots).when(snapshotDAO).getAllWithConfiguration(any(Guid.class)); + mockAnswers(); + } + + private void initMembers() { + executedUpdatedMetadataForStoragePool = new HashMap<>(); + executedRemovedIds = new HashSet<>(); + executedUpdatedOvfGenerationIdsInDb = new HashMap<>(); + poolDomainsOvfInfo = new HashMap<>(); + vms = new HashMap<Guid, VM>(); + templates = new HashMap<Guid, VmTemplate>(); + pool1 = new StoragePool(); + pool1.setId(Guid.newGuid()); + pool1.setStatus(StoragePoolStatus.Maintenance); + + performStoragePoolInitOps(pool1); + } + + private void performStoragePoolInitOps(StoragePool pool) { + executedUpdatedMetadataForStoragePool = new HashMap<>(); + executedRemovedIds = new HashSet<>(); + executedUpdatedOvfGenerationIdsInDb = new HashMap<>(); + + for (int i = 0; i < 2; i++) { + Guid domainId = Guid.newGuid(); + StorageDomainOvfInfo ovfInfo = new StorageDomainOvfInfo(domainId, null, null, StorageDomainOvfInfoStatus.UPDATED, null); + StorageDomain domain = new StorageDomain(); + domain.setId(domainId); + domain.setStoragePoolIsoMapData(new StoragePoolIsoMap(domainId, pool.getId(), StorageDomainStatus.Active)); + poolDomainsOvfInfo.put(domainId, new Pair<>(Arrays.asList(ovfInfo), domain)); + } + } + + private void mockAnswers() { + doAnswer(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + VM vm = (VM) invocation.getArguments()[0]; + return vm.getId().toString(); + } + + }).when(ovfUpdateProcessHelper).generateVmMetadata(any(VM.class), any(ArrayList.class)); + + doAnswer(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + VmTemplate template = (VmTemplate) invocation.getArguments()[0]; + return template.getId().toString(); + } + + }).when(ovfUpdateProcessHelper).generateVmTemplateMetadata(any(VmTemplate.class), anyList()); + + doAnswer(new Answer<List<VM>>() { + @Override + public List<VM> answer(InvocationOnMock invocation) throws Throwable { + List<Guid> neededIds = (List<Guid>) invocation.getArguments()[0]; + List<VM> toReturn = new LinkedList<VM>(); + for (Guid id : neededIds) { + toReturn.add(vms.get(id)); + } + return toReturn; + } + + }).when(vmDAO).getVmsByIds(anyList()); + + doAnswer(new Answer<List<VmTemplate>>() { + @Override + public List<VmTemplate> answer(InvocationOnMock invocation) throws Throwable { + List<Guid> neededIds = (List<Guid>) invocation.getArguments()[0]; + List<VmTemplate> toReturn = new LinkedList<VmTemplate>(); + for (Guid id : neededIds) { + toReturn.add(templates.get(id)); + } + return toReturn; + } + + }).when(vmTemplateDAO).getVmTemplatesByIds(anyList()); + + doAnswer(new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + Map<Guid, KeyValuePairCompat<String, List<Guid>>> updateMap = + (Map<Guid, KeyValuePairCompat<String, List<Guid>>>) invocation.getArguments()[1]; + executedUpdatedMetadataForStoragePool.putAll(updateMap); + assertTrue("too many ovfs were sent in one vdsm call", updateMap.size() <= ITEMS_COUNT_PER_UPDATE); + return true; + } + + }).when(ovfUpdateProcessHelper).executeUpdateVmInSpmCommand(any(Guid.class), anyMap(), any(Guid.class)); + + doAnswer(new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + executedRemovedIds.add((Guid) invocation.getArguments()[1]); + return true; + } + + }).when(ovfUpdateProcessHelper).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + + doAnswer(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + List<Guid> ids = (List<Guid>) invocation.getArguments()[0]; + List<Long> values = (List<Long>) invocation.getArguments()[1]; + assertFalse("update of ovf version in db shouldn't be called with an empty value list", + values.isEmpty()); + assertTrue("update of ovf version in db shouldn't be called with more items then MAX_ITEMS_PER_SQL_STATEMENT", + values.size() <= StorageConstants.OVF_MAX_ITEMS_PER_SQL_STATEMENT); + assertEquals("the size of the list of ids for update is not the same as the size of the " + + "list with the new ovf values", values.size(), ids.size()); + Guid[] ids_array = ids.toArray(new Guid[ids.size()]); + Long[] values_array = values.toArray(new Long[values.size()]); + for (int i = 0; i < ids_array.length; i++) { + executedUpdatedOvfGenerationIdsInDb.put(ids_array[i], + values_array[i]); + } + return null; + } + + }).when(vmAndTemplatesGenerationsDAO).updateOvfGenerations(anyList(), anyList(), anyList()); + + doAnswer(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + StoragePoolStatus desiredStatus = (StoragePoolStatus) invocation.getArguments()[0]; + List<StoragePool> toReturn = new LinkedList<>(); + for (StoragePool pool : buildStoragePoolsList()) { + if (desiredStatus.equals(pool.getStatus())) { + toReturn.add(pool); + } + } + + return toReturn; + } + + }).when(storagePoolDAO).getAllByStatus(any(StoragePoolStatus.class)); + + doAnswer(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Guid poolId = (Guid) invocation.getArguments()[0]; + List<StorageDomain> toReturn = new LinkedList<>(); + for (Pair<List<StorageDomainOvfInfo>, StorageDomain> pair : poolDomainsOvfInfo.values()) { + toReturn.add(pair.getSecond()); + } + + return toReturn; + } + + }).when(storageDomainDAO).getAllForStoragePool(any(Guid.class)); + + doAnswer(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Guid domainId = (Guid) invocation.getArguments()[0]; + Pair<List<StorageDomainOvfInfo>, StorageDomain> pair = poolDomainsOvfInfo.get(domainId); + if (pair != null) { + return pair.getFirst(); + } + return null; + } + + }).when(storageDomainOvfInfoDao).getAllForDomain(any(Guid.class)); + } + + private List<StoragePool> buildStoragePoolsList() { + return Arrays.asList(pool1); + } + + private VM createVm(Guid id, VMStatus status) { + VM vm = new VM(); + vm.setStatus(status); + vm.setStaticData(createVmStatic()); + vm.setId(id); + return vm; + } + + public VmStatic createVmStatic() { + VmStatic vms = new VmStatic(); + vms.setDbGeneration(1L); + return vms; + } + + private VmTemplate createVmTemplate(Guid id, VmTemplateStatus templateStatus) { + VmTemplate template = new VmTemplate(); + template.setStatus(templateStatus); + template.setDbGeneration(1L); + template.setId(id); + return template; + } + + private List<Guid> generateGuidList(int size) { + List<Guid> toReturn = new LinkedList<Guid>(); + for (int i = 0; i < size; i++) { + toReturn.add(Guid.newGuid()); + } + return toReturn; + } + + private Map<Guid, VM> generateVmsMapByGuids(List<Guid> ids, + int diskCount, + VMStatus vmStatus, + ImageStatus diskStatus, + Guid poolId) { + Map<Guid, VM> toReturn = new HashMap<Guid, VM>(); + for (Guid id : ids) { + VM vm = createVm(id, vmStatus); + for (int i = 0; i < diskCount; i++) { + DiskImage image = createDiskImage(diskStatus, poolId); + vm.getDiskMap().put(image.getId(), image); + vm.getDiskList().add(image); + } + toReturn.put(vm.getId(), vm); + } + return toReturn; + } + + private Map<Guid, VmTemplate> generateVmTemplatesMapByGuids(List<Guid> ids, + int diskCount, + VmTemplateStatus templateStatus, + ImageStatus diskStatus, Guid poolId) { + Map<Guid, VmTemplate> toReturn = new HashMap<Guid, VmTemplate>(); + for (Guid id : ids) { + VmTemplate template = createVmTemplate(id, templateStatus); + for (int i = 0; i < diskCount; i++) { + DiskImage image = createDiskImage(diskStatus, poolId); + template.getDiskTemplateMap().put(image.getId(), image); + template.getDiskList().add(image); + } + toReturn.put(template.getId(), template); + } + return toReturn; + } + + private DiskImage createDiskImage(ImageStatus status, Guid poolId) { + DiskImage disk = new DiskImage(); + disk.setId(Guid.newGuid()); + disk.setImageStatus(status); + ArrayList<Guid> storageIds = new ArrayList<>(); + storageIds.add(poolDomainsOvfInfo.keySet().iterator().next()); + disk.setStorageIds(storageIds); + return disk; + } + + private void initTestForPool(StoragePool pool, List<Guid> vmGuids, List<Guid> templatesGuids, List<Guid> removedGuids) { + Guid poolId = pool.getId(); + doReturn(vmGuids).when(vmAndTemplatesGenerationsDAO).getVmsIdsForOvfUpdate(poolId); + doReturn(templatesGuids).when(vmAndTemplatesGenerationsDAO).getVmTemplatesIdsForOvfUpdate(poolId); + doReturn(removedGuids).when(vmAndTemplatesGenerationsDAO).getIdsForOvfDeletion(poolId); + pool.setStatus(StoragePoolStatus.Up); + } + + private void verifyCorrectOvfDataUpdaterRun(StoragePool storagePool, + Collection<Guid> needToBeUpdated, + Collection<Guid> removedGuids) { + + if (!command.ovfOnAnyDomainSupported(storagePool)) { + assertTrue("not all needed vms/templates were updated in vdsm", + CollectionUtils.isEqualCollection(executedUpdatedMetadataForStoragePool.keySet(), + needToBeUpdated)); + for (Map.Entry<Guid, KeyValuePairCompat<String, List<Guid>>> entry : executedUpdatedMetadataForStoragePool + .entrySet()) { + assertEquals("wrong ovf data stored in storage for vm/template", + entry.getKey().toString(), + entry.getValue().getKey()); + } + } + assertTrue("not all needed vms/templates were updated in db", + CollectionUtils.isEqualCollection(executedUpdatedOvfGenerationIdsInDb.keySet(), + needToBeUpdated)); + + for (Map.Entry<Guid, Long> storagePoolGenerationEntry : executedUpdatedOvfGenerationIdsInDb.entrySet()) { + boolean isCorrectVersion = false; + if (vms.get(storagePoolGenerationEntry.getKey()) != null) { + isCorrectVersion = + storagePoolGenerationEntry.getValue() + .equals(vms.get(storagePoolGenerationEntry.getKey()).getDbGeneration()); + } else if (templates.get(storagePoolGenerationEntry.getKey()) != null) { + isCorrectVersion = + storagePoolGenerationEntry.getValue() + .equals(templates.get(storagePoolGenerationEntry.getKey()).getDbGeneration()); + } + assertTrue("wrong new ovf version persisted for vm/template", isCorrectVersion); + } + + if (!command.ovfOnAnyDomainSupported(storagePool)) { + assertTrue("not all needed vms/templates were removed from vdsm", + CollectionUtils.isEqualCollection(removedGuids, executedRemovedIds)); + } + } + + private void addVms(List<Guid> vmGuids, int diskCount, VMStatus vmStatus, ImageStatus vmImageStatus, Guid poolId) { + vms.putAll(generateVmsMapByGuids(vmGuids, diskCount, vmStatus, vmImageStatus, poolId)); + + } + + private void verifyOvfUpdatedForSupportedPools(List<Guid> poolsRequiredUpdate, + Map<Guid, List<Guid>> domainsRequiredUpdateForPool) { + for (Guid storagePoolId : poolsRequiredUpdate) { + for (Guid updatedDomainForPool : executedOvfUpdatedDomains) { + assertTrue("ovf update for domain has been executed with wrong pool", + poolDomainsOvfInfo.containsKey(updatedDomainForPool)); + if (domainsRequiredUpdateForPool.get(storagePoolId) != null) { + assertTrue("ovf updated hasn't been executed on needed domain", + domainsRequiredUpdateForPool.get(storagePoolId).contains(updatedDomainForPool)); + } + } + } + } + + private void addTemplates(List<Guid> templatesGuids, + int diskCount, + VmTemplateStatus templateStatus, + ImageStatus templateImageStatus, Guid poolId) { + templates.putAll(generateVmTemplatesMapByGuids(templatesGuids, + diskCount, + templateStatus, + templateImageStatus, + poolId)); + } + + @Test + public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePoolOvfOnAnyDomainSupported() { + testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePool(true); + verifyOvfUpdatedForSupportedPools(Arrays.asList(pool1.getId()), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePoolOvfOnAnyDomainUnsupported() { + testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePool(false); + } + + public void testOvfDataUpdaterRunWithUpdateAndRemoveHigherThanCountOnePool(boolean ovfOnAnyDomainSupported) { + int size = 3 * ITEMS_COUNT_PER_UPDATE + 10; + doReturn(ovfOnAnyDomainSupported).when(command).ovfOnAnyDomainSupported(any(StoragePool.class)); + List<Guid> vmGuids = generateGuidList(size); + List<Guid> templatesGuids = generateGuidList(size); + List<Guid> removedGuids = generateGuidList(size); + addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); + addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); + + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + executeCommand(); + verify(command, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + + List<Guid> idsThatNeededToBeUpdated = new LinkedList<Guid>(vmGuids); + idsThatNeededToBeUpdated.addAll(templatesGuids); + + verifyCorrectOvfDataUpdaterRun(pool1, idsThatNeededToBeUpdated, removedGuids); + } + + private void executeCommand() { + command.executeCommand(); + executedOvfUpdatedDomains = (Set<Guid>)command.getActionReturnValue(); + } + + @Test + public void testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCountOvfOnAnyDomainSupported() { + testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCount(true); + verifyOvfUpdatedForSupportedPools(Arrays.asList(pool1.getId()), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCountOvfOnAnyDomainUnupported() { + testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCount(false); + } + + public void testOvfDataUpdaterRunWithUpdateAndRemoveLowerThanCount(boolean ovfOnAnyDomainSupported) { + int size = ITEMS_COUNT_PER_UPDATE - 1; + + doReturn(ovfOnAnyDomainSupported).when(command).ovfOnAnyDomainSupported(any(StoragePool.class)); + List<Guid> vmGuids = generateGuidList(size); + addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); + List<Guid> templatesGuids = generateGuidList(size); + addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); + List<Guid> removedGuids = generateGuidList(size); + + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + + executeCommand(); + verify(command, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + List<Guid> needToBeUpdated = new LinkedList<Guid>(vmGuids); + needToBeUpdated.addAll(templatesGuids); + verifyCorrectOvfDataUpdaterRun(pool1, needToBeUpdated, removedGuids); + } + + @Test + public void testOvfDataUpdaterAllDisksAreLockedNonToRemoveOvfOnAnyDomainSupported() { + testOvfDataUpdaterAllDisksAreLockedNonToRemove(true); + verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testOvfDataUpdaterAllDisksAreLockedNonToRemoveOvfOnAnyDomainUnupported() { + testOvfDataUpdaterAllDisksAreLockedNonToRemove(false); + } + + public void testOvfDataUpdaterAllDisksAreLockedNonToRemove(boolean ovfOnAnyDomainSupported) { + int size = ITEMS_COUNT_PER_UPDATE - 1; + + doReturn(ovfOnAnyDomainSupported).when(command).ovfOnAnyDomainSupported(any(StoragePool.class)); + List<Guid> vmGuids = generateGuidList(size); + List<Guid> removedGuids = Collections.emptyList(); + List<Guid> templatesGuids = generateGuidList(size); + + addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.LOCKED, pool1.getId()); + addVms(vmGuids, 2, VMStatus.Down, ImageStatus.LOCKED, pool1.getId()); + + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + + executeCommand(); + verify(command, never()).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, never()).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), removedGuids); + } + + @Test + public void testOvfDataUpdaterPartOfDisksAreLockedOvfOnAnyDomainSupported() { + testOvfDataUpdaterAllDisksAreLockedNonToRemove(true); + verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testOvfDataUpdaterPartOfDisksAreLockedOvfOnAnyDomainUnupported() { + testOvfDataUpdaterAllDisksAreLockedNonToRemove(false); + } + + public void testOvfDataUpdaterPartOfDisksAreLocked(boolean ovfOnAnyDomainSupported) { + int size = ITEMS_COUNT_PER_UPDATE - 1; + // unlocked vms/templates + List<Guid> vmGuids = generateGuidList(size); + List<Guid> templatesGuids = generateGuidList(size); + addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); + addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); + + // locked vms/templates + List<Guid> lockedVmGuids = generateGuidList(size); + List<Guid> lockedTemplatesGuids = generateGuidList(size); + addVms(lockedVmGuids, 2, VMStatus.Down, ImageStatus.LOCKED, pool1.getId()); + addTemplates(lockedTemplatesGuids, 2, VmTemplateStatus.OK, ImageStatus.LOCKED, pool1.getId()); + // ids for removal + List<Guid> removedGuids = generateGuidList(size); + + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + + executeCommand(); + verify(command, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + // list of ids that should have been updated. + List<Guid> needToBeUpdated = new LinkedList<Guid>(vmGuids); + needToBeUpdated.addAll(templatesGuids); + verifyCorrectOvfDataUpdaterRun(pool1, needToBeUpdated, removedGuids); + } + + private int numberOfTimesToBeCalled(int size, boolean isBothVmAndTemplates) { + int toReturn = 0; + if (size % ITEMS_COUNT_PER_UPDATE != 0) { + toReturn++; + } + toReturn += size / ITEMS_COUNT_PER_UPDATE; + if (isBothVmAndTemplates) { + toReturn = toReturn * 2; + } + return toReturn; + } + + @Test + public void testOvfDataUpdaterAllVmsAndTemplatesAreLockedOvfOnAnyDomainSupported() { + testOvfDataUpdaterAllVmsAndTemplatesAreLocked(true); + verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testOvfDataUpdaterAllVmsAndTemplatesAreLockedOvfOnAnyDomainUnupported() { + testOvfDataUpdaterAllVmsAndTemplatesAreLocked(false); + } + + public void testOvfDataUpdaterAllVmsAndTemplatesAreLocked(boolean ovfOnAnyDomainSupported) { + int size = ITEMS_COUNT_PER_UPDATE - 1; + List<Guid> vmGuids = generateGuidList(size); + addVms(vmGuids, 2, VMStatus.ImageLocked, ImageStatus.OK, pool1.getId()); + List<Guid> removedGuids = generateGuidList(size); + List<Guid> templatesGuids = generateGuidList(size); + addTemplates(templatesGuids, 2, VmTemplateStatus.Locked, ImageStatus.OK, pool1.getId()); + + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + + command.executeCommand(); + verify(command, never()).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), removedGuids); + } + + @Test + public void testOvfDataUpdaterPartOfVmsAndTemplatesAreLockedOvfOnAnyDomainSupported() { + testOvfDataUpdaterPartOfVmsAndTemplatesAreLocked(true); + verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testOvfDataUpdaterPartOfVmsAndTemplatesAreLockedOvfOnAnyDomainUnupported() { + testOvfDataUpdaterPartOfVmsAndTemplatesAreLocked(false); + } + + public void testOvfDataUpdaterPartOfVmsAndTemplatesAreLocked(boolean ovfOnAnyDomainSupported) { + int size = ITEMS_COUNT_PER_UPDATE; + List<Guid> vmGuids = generateGuidList(size); + List<Guid> removedGuids = generateGuidList(size); + List<Guid> templatesGuids = generateGuidList(size); + + addVms(vmGuids, 2, VMStatus.ImageLocked, ImageStatus.OK, pool1.getId()); + addTemplates(templatesGuids, 2, VmTemplateStatus.Locked, ImageStatus.OK, pool1.getId()); + + List<Guid> vmGuidsUnlocked = generateGuidList(size); + List<Guid> templatesGuidsUnlocked = generateGuidList(size); + + addVms(vmGuidsUnlocked, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); + addTemplates(templatesGuidsUnlocked, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); + + vmGuids.addAll(vmGuidsUnlocked); + templatesGuids.addAll(templatesGuidsUnlocked); + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + + executeCommand(); + + List<Guid> neededToBeUpdated = new LinkedList<Guid>(vmGuidsUnlocked); + neededToBeUpdated.addAll(templatesGuidsUnlocked); + verify(command, times(numberOfTimesToBeCalled(size, true))).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, times(size)).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + verifyCorrectOvfDataUpdaterRun(pool1, neededToBeUpdated, removedGuids); + } + + @Test + public void testUpdatedDbGenerationOvfOnAnyDomainSupported() { + testUpdatedDbGeneration(true); + verifyOvfUpdatedForSupportedPools(Collections.<Guid> emptyList(), Collections.<Guid, List<Guid>> emptyMap()); + } + + @Test + public void testUpdatedDbGenerationOvfOnAnyDomainUnupported() { + testUpdatedDbGeneration(false); + } + + public void testUpdatedDbGeneration(boolean ovfOnAnyDomainSupported) { + int size = 3 * ITEMS_COUNT_PER_UPDATE + 10; + List<Guid> vmGuids = generateGuidList(size); + List<Guid> templatesGuids = generateGuidList(size); + List<Guid> removedGuids = Collections.emptyList(); + addVms(vmGuids, 2, VMStatus.Down, ImageStatus.OK, pool1.getId()); + addTemplates(templatesGuids, 2, VmTemplateStatus.OK, ImageStatus.OK, pool1.getId()); + + initTestForPool(pool1, vmGuids, templatesGuids, removedGuids); + + doReturn(2L).when(vmStaticDAO).getDbGeneration(any(Guid.class)); + + executeCommand(); + + verify(command, never()).performOvfUpdate(any(StoragePool.class), anyMap()); + if (!ovfOnAnyDomainSupported) { + verify(ovfUpdateProcessHelper, never()).executeRemoveVmInSpm(any(Guid.class), any(Guid.class), any(Guid.class)); + } + + List<Guid> idsThatNeededToBeUpdated = new LinkedList<Guid>(vmGuids); + idsThatNeededToBeUpdated.addAll(templatesGuids); + + verifyCorrectOvfDataUpdaterRun(pool1, Collections.<Guid> emptyList(), removedGuids); + } + + @Test + public void testUpdateCalledForUnupdatedDomain() { + Guid poolId = pool1.getId(); + StorageDomainOvfInfo ovfInfo = poolDomainsOvfInfo.entrySet().iterator().next().getValue().getFirst().get(0); + ovfInfo.setStatus(StorageDomainOvfInfoStatus.OUTDATED); + doReturn(true).when(command).ovfOnAnyDomainSupported(any(StoragePool.class)); + initTestForPool(pool1, + Collections.<Guid> emptyList(), + Collections.<Guid> emptyList(), + Collections.<Guid> emptyList()); + executeCommand(); + verify(command, never()).performOvfUpdate(any(StoragePool.class), anyMap()); + Map<Guid, List<Guid>> domainsRequiredUpdateForPool = + Collections.singletonMap(poolId, Arrays.asList(ovfInfo.getStorageDomainId())); + verifyOvfUpdatedForSupportedPools(Arrays.asList(poolId), domainsRequiredUpdateForPool); + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java index 920deef..f3c1437 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java @@ -362,6 +362,7 @@ CreateOvfVolumeForStorageDomain(1903, QuotaDependency.NONE), CreateOvfStoresForStorageDomain(1904, QuotaDependency.NONE), RetrieveImageData(1905, QuotaDependency.NONE), + ProcessOvfUpdateForStoragePool(1906, QuotaDependency.NONE), // Affinity Groups AddAffinityGroup(1950, ActionGroup.MANIPULATE_AFFINITY_GROUPS, false, QuotaDependency.NONE), diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/auditloghandling/AuditLogableBase.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/auditloghandling/AuditLogableBase.java index 31ed560..da45e68 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/auditloghandling/AuditLogableBase.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/auditloghandling/AuditLogableBase.java @@ -4,7 +4,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.transaction.Transaction; import org.apache.commons.lang.StringUtils; @@ -29,13 +28,16 @@ import org.ovirt.engine.core.dao.PermissionDAO; import org.ovirt.engine.core.dao.RoleDAO; import org.ovirt.engine.core.dao.RoleGroupMapDAO; +import org.ovirt.engine.core.dao.SnapshotDao; import org.ovirt.engine.core.dao.StepDao; import org.ovirt.engine.core.dao.StorageDomainDAO; +import org.ovirt.engine.core.dao.StorageDomainOvfInfoDao; import org.ovirt.engine.core.dao.StorageDomainStaticDAO; import org.ovirt.engine.core.dao.StoragePoolDAO; import org.ovirt.engine.core.dao.VdsDAO; import org.ovirt.engine.core.dao.VdsDynamicDAO; import org.ovirt.engine.core.dao.VdsGroupDAO; +import org.ovirt.engine.core.dao.VmAndTemplatesGenerationsDAO; import org.ovirt.engine.core.dao.VmDAO; import org.ovirt.engine.core.dao.VmDynamicDAO; import org.ovirt.engine.core.dao.VmStaticDAO; @@ -596,6 +598,18 @@ return getDbFacade().getVmStaticDao(); } + public SnapshotDao getSnapshotDAO() { + return getDbFacade().getSnapshotDao(); + } + + public VmAndTemplatesGenerationsDAO getVmAndTemplatesGenerationsDAO() { + return DbFacade.getInstance().getVmAndTemplatesGenerationsDao(); + } + + public StorageDomainOvfInfoDao getStorageDomainOvfInfoDAO() { + return DbFacade.getInstance().getStorageDomainOvfInfoDao(); + } + public VmDynamicDAO getVmDynamicDAO() { return getDbFacade().getVmDynamicDao(); } @@ -633,7 +647,7 @@ } public VmNetworkInterfaceDao getVmNetworkInterfaceDao() { - return getDbFacade().getVmNetworkInterfaceDao(); + return DbFacade.getInstance().getVmNetworkInterfaceDao(); } protected VmNicDao getVmNicDao() { -- To view, visit http://gerrit.ovirt.org/35815 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6780aedf2d215d08c4bed0ff4f7520c45f753f66 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Liron Aravot <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
