Gilad Chaplik has uploaded a new change for review. Change subject: core: Move RunVm validation logic to RunVmCommand (1/X) ......................................................................
core: Move RunVm validation logic to RunVmCommand (1/X) Curretly RunVm canDoAction logic is located both in the command and in VmRunHandler. This patch motivation is to concentrate all runVmCommand logic in a single place. The validation logic is used also in prestarted vm pools feature. RunVmCommandTest was changed appropriately. Change-Id: Id4f65185ac3c3e2b6d65dd772268dbccaf9168a8 Signed-off-by: Gilad Chaplik <gchap...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolCommandBase.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmRunHandler.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java 4 files changed, 331 insertions(+), 368 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/11/13111/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java index 67cf737..cba41fb 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java @@ -2,11 +2,14 @@ import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,10 +22,14 @@ import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaVdsDependent; import org.ovirt.engine.core.bll.quota.QuotaVdsGroupConsumptionParameter; +import org.ovirt.engine.core.bll.storage.StoragePoolValidator; import org.ovirt.engine.core.bll.utils.PermissionSubject; import org.ovirt.engine.core.bll.utils.VmDeviceUtils; +import org.ovirt.engine.core.bll.validator.StorageDomainValidator; +import org.ovirt.engine.core.bll.validator.VmValidator; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.FeatureSupported; +import org.ovirt.engine.core.common.VdcActionUtils; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.CreateAllSnapshotsFromVmParameters; import org.ovirt.engine.core.common.action.RunVmParams; @@ -31,6 +38,7 @@ import org.ovirt.engine.core.common.businessentities.ActionGroup; import org.ovirt.engine.core.common.businessentities.BootSequence; import org.ovirt.engine.core.common.businessentities.Disk; +import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.DisplayType; import org.ovirt.engine.core.common.businessentities.Entities; import org.ovirt.engine.core.common.businessentities.FileTypeExtension; @@ -40,24 +48,33 @@ import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StorageDomainType; import org.ovirt.engine.core.common.businessentities.VDS; +import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; +import org.ovirt.engine.core.common.businessentities.storage_pool; import org.ovirt.engine.core.common.businessentities.network.Network; import org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface; +import org.ovirt.engine.core.common.config.Config; +import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.errors.VdcBLLException; import org.ovirt.engine.core.common.errors.VdcBllErrors; import org.ovirt.engine.core.common.job.Job; import org.ovirt.engine.core.common.job.Step; import org.ovirt.engine.core.common.job.StepEnum; +import org.ovirt.engine.core.common.queries.GetAllIsoImagesListParameters; +import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; +import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.utils.VmDeviceType; import org.ovirt.engine.core.common.vdscommands.CreateVmVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.IrsBaseVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.IsVmDuringInitiatingVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.ResumeVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.core.dal.VdcBllMessages; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.job.ExecutionMessageDirector; import org.ovirt.engine.core.utils.NetworkUtils; @@ -517,7 +534,7 @@ // Clear the first user: getVm().setConsoleUserId(null); - getParameters().setRunAsStateless(getVmRunHandler().shouldVmRunAsStateless(getParameters(), getVm())); + getParameters().setRunAsStateless(shouldVmRunAsStateless(getParameters(), getVm())); getVm().setDisplayType(getParameters().getUseVnc() == null ? getVm().getDefaultDisplayType() : @@ -663,38 +680,290 @@ return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_VM_NOT_FOUND); } + // if VM is paused, it was already checked before that it is capable to run if (vm.getStatus() == VMStatus.Paused) { - // if VM is paused, it was already checked before that it is capable to run return true; } - else { - boolean canDoAction = canRunVm(vm) && validateNetworkInterfaces(); + /********* VmRunHandler.canRunVm START **********/ - // check for Vm Payload - if (canDoAction && getParameters().getVmPayload() != null) { - canDoAction = checkPayload(getParameters().getVmPayload(), - getParameters().getDiskPath()); + ArrayList<String> messages = getReturnValue().getCanDoActionMessages(); + boolean canDoAction = true; + List<VmPropertiesUtils.ValidationError> validationErrors = getVmPropertiesUtils().validateVMProperties( + vm.getVdsGroupCompatibilityVersion(), + vm.getStaticData()); - if (canDoAction && !StringUtils.isEmpty(getParameters().getFloppyPath()) && - getParameters().getVmPayload().getType() == VmDeviceType.FLOPPY) { - addCanDoActionMessage(VdcBllMessages.VMPAYLOAD_FLOPPY_EXCEEDED); + if (!validationErrors.isEmpty()) { + VmHandler.handleCustomPropertiesError(validationErrors, messages); + return false; + } else { + BootSequence boot_sequence = (getParameters().getBootSequence() != null) ? + getParameters().getBootSequence() : vm.getDefaultBootSequence(); + Guid storagePoolId = vm.getStoragePoolId(); + // Block from running a VM with no HDD when its first boot device is + // HD and no other boot devices are configured + List<Disk> vmDisks = getVmRunHandler().getPluggedDisks(vm); + if (boot_sequence == BootSequence.C && vmDisks.size() == 0) { + String messageStr = !vmDisks.isEmpty() ? + VdcBllMessages.VM_CANNOT_RUN_FROM_DISK_WITHOUT_PLUGGED_DISK.toString() : + VdcBllMessages.VM_CANNOT_RUN_FROM_DISK_WITHOUT_DISK.toString(); + + messages.add(messageStr); + canDoAction = false; + } else { + // If CD appears as first and there is no ISO in storage + // pool/ISO inactive - + // you cannot run this VM + + if (boot_sequence == BootSequence.CD && getVmRunHandler().findActiveISODomain(storagePoolId) == null) { + messages.add(VdcBllMessages.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO.toString()); canDoAction = false; - } - else { - getVm().setVmPayload(getParameters().getVmPayload()); + } else { + // if there is network in the boot sequence, check that the + // vm has network, + // otherwise the vm cannot be run in vdsm + if (boot_sequence == BootSequence.N + && DbFacade.getInstance().getVmNetworkInterfaceDao().getAllForVm(vm.getId()).size() == 0) { + messages.add(VdcBllMessages.VM_CANNOT_RUN_FROM_NETWORK_WITHOUT_NETWORK.toString()); + canDoAction = false; + } + + if (canDoAction) { + ValidationResult vmNotLockedResult = new VmValidator(vm).vmNotLocked(); + if (!vmNotLockedResult.isValid()) { + messages.add(vmNotLockedResult.getMessage().name()); + canDoAction = false; + } + } + + if (canDoAction) { + ValidationResult vmDuringSnapshotResult = + getSnapshotsValidator().vmNotDuringSnapshot(vm.getId()); + if (!vmDuringSnapshotResult.isValid()) { + messages.add(vmDuringSnapshotResult.getMessage().name()); + canDoAction = false; + } + } + + List<DiskImage> vmImages = ImagesHandler.filterImageDisks(vmDisks, true, false); + if (canDoAction && !vmImages.isEmpty()) { + storage_pool sp = getStoragePoolDAO().get(vm.getStoragePoolId()); + ValidationResult spUpResult = new StoragePoolValidator(sp).isUp(); + if (!spUpResult.isValid()) { + messages.add(spUpResult.getMessage().name()); + canDoAction = false; + } + + if (canDoAction) { + canDoAction = performImageChecksForRunningVm(vm, messages, getParameters(), vmImages); + } + + // Check if iso and floppy path exists + if (canDoAction && !vm.isAutoStartup() + && !validateIsoPath(getVmRunHandler().findActiveISODomain(vm.getStoragePoolId()), + getParameters(), + messages)) { + canDoAction = false; + } else if (canDoAction) { + boolean isVmDuringInit = ((Boolean) getBackend() + .getResourceManager() + .RunVdsCommand(VDSCommandType.IsVmDuringInitiating, + new IsVmDuringInitiatingVDSCommandParameters(vm.getId())) + .getReturnValue()).booleanValue(); + if (vm.isRunning() || (vm.getStatus() == VMStatus.NotResponding) || isVmDuringInit) { + canDoAction = false; + messages.add(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_RUNNING.toString()); + } else if (vm.getStatus() == VMStatus.Paused && vm.getRunOnVds() != null) { + VDS vds = DbFacade.getInstance().getVdsDao().get( + new Guid(vm.getRunOnVds().toString())); + if (vds.getStatus() != VDSStatus.Up) { + canDoAction = false; + messages.add(VdcBllMessages.VAR__HOST_STATUS__UP.toString()); + messages.add(VdcBllMessages.ACTION_TYPE_FAILED_VDS_STATUS_ILLEGAL.toString()); + } + } + + boolean isStatelessVm = shouldVmRunAsStateless(getParameters(), vm); + + if (canDoAction && isStatelessVm + && !getSnapshotsValidator().vmNotInPreview(vm.getId()).isValid()) { + canDoAction = false; + messages.add(VdcBllMessages.VM_CANNOT_RUN_STATELESS_WHILE_IN_PREVIEW.toString()); + } + + // if the VM itself is stateless or run once as stateless + if (canDoAction && isStatelessVm && vm.isAutoStartup()) { + canDoAction = false; + messages.add(VdcBllMessages.VM_CANNOT_RUN_STATELESS_HA.toString()); + } + + if (canDoAction && isStatelessVm && !hasSpaceForSnapshots(vm, messages)) { + return false; + } + } + } + + canDoAction = + canDoAction == false ? canDoAction : getVdsSelector().canFindVdsToRunOn(messages, false); + + /** + * only if can do action ok then check with actions matrix that status is valid for this + * action + */ + if (canDoAction + && !VdcActionUtils.CanExecute(Arrays.asList(vm), VM.class, + VdcActionType.RunVm)) { + canDoAction = false; + messages.add(VdcBllMessages.ACTION_TYPE_FAILED_VM_STATUS_ILLEGAL.toString()); + } } } - - return canDoAction; } + + /********* VmRunHandler.canRunVm END **********/ + canDoAction &= validateNetworkInterfaces(); + + // check for Vm Payload + if (canDoAction && getParameters().getVmPayload() != null) { + canDoAction = checkPayload(getParameters().getVmPayload(), + getParameters().getDiskPath()); + + if (canDoAction && !StringUtils.isEmpty(getParameters().getFloppyPath()) && + getParameters().getVmPayload().getType() == VmDeviceType.FLOPPY) { + addCanDoActionMessage(VdcBllMessages.VMPAYLOAD_FLOPPY_EXCEEDED); + canDoAction = false; + } + else { + getVm().setVmPayload(getParameters().getVmPayload()); + } + } + + return canDoAction; } - protected boolean canRunVm(VM vm) { - return getVmRunHandler().canRunVm(vm, - getReturnValue().getCanDoActionMessages(), - getParameters(), - getVdsSelector(), - getSnapshotsValidator(), getVmPropertiesUtils()); + /** + * Check isValid, storageDomain and diskSpace only if VM is not HA VM + */ + protected boolean performImageChecksForRunningVm + (VM vm, List<String> message, RunVmParams runParams, List<DiskImage> vmDisks) { + return ImagesHandler.PerformImagesChecks(message, + vm.getStoragePoolId(), Guid.Empty, !vm.isAutoStartup(), + true, false, false, + !vm.isAutoStartup() || !runParams.getIsInternal(), + !vm.isAutoStartup() || !runParams.getIsInternal(), + vmDisks); + } + + @SuppressWarnings("unchecked") + private boolean validateIsoPath(Guid storageDomainId, + RunVmParams runParams, + ArrayList<String> messages) { + if (!StringUtils.isEmpty(runParams.getDiskPath())) { + if (storageDomainId == null) { + messages.add(VdcBllMessages.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO.toString()); + return false; + } + boolean retValForIso = false; + VdcQueryReturnValue ret = + getBackend().runInternalQuery(VdcQueryType.GetAllIsoImagesList, + new GetAllIsoImagesListParameters(storageDomainId)); + if (ret != null && ret.getReturnValue() != null && ret.getSucceeded()) { + List<RepoFileMetaData> repoFileNameList = (List<RepoFileMetaData>) ret.getReturnValue(); + if (repoFileNameList != null) { + for (RepoFileMetaData isoFileMetaData : (List<RepoFileMetaData>) ret.getReturnValue()) { + if (isoFileMetaData.getRepoFileName().equals(runParams.getDiskPath())) { + retValForIso = true; + break; + } + } + } + } + if (!retValForIso) { + messages.add(VdcBllMessages.ERROR_CANNOT_FIND_ISO_IMAGE_PATH.toString()); + return false; + } + } + + if (!StringUtils.isEmpty(runParams.getFloppyPath())) { + boolean retValForFloppy = false; + VdcQueryReturnValue ret = + getBackend().runInternalQuery(VdcQueryType.GetAllFloppyImagesList, + new GetAllIsoImagesListParameters(storageDomainId)); + if (ret != null && ret.getReturnValue() != null && ret.getSucceeded()) { + List<RepoFileMetaData> repoFileNameList = (List<RepoFileMetaData>) ret.getReturnValue(); + if (repoFileNameList != null) { + + for (RepoFileMetaData isoFileMetaData : (List<RepoFileMetaData>) ret.getReturnValue()) { + if (isoFileMetaData.getRepoFileName().equals(runParams.getFloppyPath())) { + retValForFloppy = true; + break; + } + } + } + } + if (!retValForFloppy) { + messages.add(VdcBllMessages.ERROR_CANNOT_FIND_FLOPPY_IMAGE_PATH.toString()); + return false; + } + } + + return true; + } + + private boolean shouldVmRunAsStateless(RunVmParams param, VM vm) { + if (param.getRunAsStateless() != null) { + return param.getRunAsStateless(); + } + return vm.isStateless(); + } + + /** + * check that we can create snapshots for all disks + * + * @param vm + * @return true if all storage domains have enough space to create snapshots for this VM plugged disks + */ + private boolean hasSpaceForSnapshots(VM vm, ArrayList<String> message) { + Integer minSnapshotSize = Config.<Integer> GetValue(ConfigValues.InitStorageSparseSizeInGB); + for (Entry<StorageDomain, Integer> e : mapStorageDomainsToNumOfDisks(vm).entrySet()) { + if (!destinationHasSpace(e.getKey(), minSnapshotSize * e.getValue(), message)) { + return false; + } + } + return true; + } + + private boolean destinationHasSpace(StorageDomain storageDomain, long sizeRequested, ArrayList<String> message) { + return validate(new StorageDomainValidator(storageDomain).isDomainHasSpaceForRequest(sizeRequested), message); + } + + private boolean validate(ValidationResult validationResult, ArrayList<String> message) { + if (!validationResult.isValid()) { + message.add(validationResult.getMessage().name()); + if (validationResult.getVariableReplacements() != null) { + for (String variableReplacement : validationResult.getVariableReplacements()) { + message.add(variableReplacement); + } + } + } + return validationResult.isValid(); + } + + /** + * map the VM number of pluggable and snapable disks from their domain. + * + * @param vm + * @return + */ + private Map<StorageDomain, Integer> mapStorageDomainsToNumOfDisks(VM vm) { + Map<StorageDomain, Integer> map = new HashMap<StorageDomain, Integer>(); + for (Disk disk : getVmRunHandler().getPluggedDisks(vm)) { + if (disk.isAllowSnapshot()) { + for (StorageDomain domain : getStorageDomainDAO().getAllStorageDomainsByImageId(((DiskImage) disk).getImageId())) { + map.put(domain, map.containsKey(domain) ? Integer.valueOf(map.get(domain) + 1) : Integer.valueOf(1)); + } + } + } + return map; } protected VmPropertiesUtils getVmPropertiesUtils() { @@ -783,7 +1052,7 @@ /** * @return true if all VM network interfaces are valid */ - private boolean validateNetworkInterfaces() { + protected boolean validateNetworkInterfaces() { Map<String, VmNetworkInterface> interfaceNetworkMap = Entities.interfacesByNetworkName(getVm().getInterfaces()); Set<String> interfaceNetworkNames = interfaceNetworkMap.keySet(); List<Network> clusterNetworks = getNetworkDAO().getAllForCluster(getVm().getVdsGroupId()); diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolCommandBase.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolCommandBase.java index 9220603..38effeb 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolCommandBase.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolCommandBase.java @@ -266,12 +266,10 @@ true, new VdsFreeMemoryChecker(new NonWaitingDelayer())); - return VmRunHandler.getInstance().canRunVm(vm, - messages, - runVmParams, - vdsSelector, - new SnapshotsValidator(), - getVmPropertiesUtils()); + // TODO: temporary until this logic will be extracted. + RunVmCommand<RunVmParams> runVmCommand = new RunVmCommand<RunVmParams>(runVmParams); + runVmCommand.getReturnValue().setCanDoActionMessages(messages); + return runVmCommand.canDoAction(); } protected static VmPropertiesUtils getVmPropertiesUtils() { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmRunHandler.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmRunHandler.java index 273ad02..bb48440 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmRunHandler.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmRunHandler.java @@ -1,52 +1,22 @@ package org.ovirt.engine.core.bll; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import org.apache.commons.lang.StringUtils; -import org.ovirt.engine.core.bll.interfaces.BackendInternal; -import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator; -import org.ovirt.engine.core.bll.storage.StoragePoolValidator; -import org.ovirt.engine.core.bll.validator.StorageDomainValidator; -import org.ovirt.engine.core.bll.validator.VmValidator; -import org.ovirt.engine.core.common.VdcActionUtils; -import org.ovirt.engine.core.common.action.RunVmParams; -import org.ovirt.engine.core.common.action.VdcActionType; -import org.ovirt.engine.core.common.businessentities.BootSequence; import org.ovirt.engine.core.common.businessentities.Disk; -import org.ovirt.engine.core.common.businessentities.DiskImage; -import org.ovirt.engine.core.common.businessentities.RepoFileMetaData; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StorageDomainType; -import org.ovirt.engine.core.common.businessentities.VDS; -import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VM; -import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmDevice; -import org.ovirt.engine.core.common.businessentities.storage_pool; -import org.ovirt.engine.core.common.config.Config; -import org.ovirt.engine.core.common.config.ConfigValues; -import org.ovirt.engine.core.common.queries.GetAllIsoImagesListParameters; -import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; -import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.utils.VmDeviceType; -import org.ovirt.engine.core.common.vdscommands.IsVmDuringInitiatingVDSCommandParameters; -import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.compat.Guid; -import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.dao.DiskDao; import org.ovirt.engine.core.dao.StorageDomainDAO; -import org.ovirt.engine.core.dao.StoragePoolDAO; import org.ovirt.engine.core.dao.VmDeviceDAO; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; -import org.ovirt.engine.core.utils.vmproperties.VmPropertiesUtils; /** A utility class for verifying running a vm*/ public class VmRunHandler { @@ -55,215 +25,6 @@ public static VmRunHandler getInstance() { return instance; - } - - /** - * This method checks whether the given VM is capable to run. - * - * @param vm not null {@link VM} - * @param message - * @param runParams - * @param vdsSelector - * @param snapshotsValidator - * @param vmPropsUtils - * @return true if the given VM can run with the given properties, false otherwise - */ - public boolean canRunVm(VM vm, ArrayList<String> message, RunVmParams runParams, - VdsSelector vdsSelector, SnapshotsValidator snapshotsValidator, VmPropertiesUtils vmPropsUtils) { - boolean retValue = true; - - List<VmPropertiesUtils.ValidationError> validationErrors = vmPropsUtils.validateVMProperties( - vm.getVdsGroupCompatibilityVersion(), - vm.getStaticData()); - - if (!validationErrors.isEmpty()) { - VmHandler.handleCustomPropertiesError(validationErrors, message); - retValue = false; - } else { - BootSequence boot_sequence = (runParams.getBootSequence() != null) ? - runParams.getBootSequence() : vm.getDefaultBootSequence(); - Guid storagePoolId = vm.getStoragePoolId(); - // Block from running a VM with no HDD when its first boot device is - // HD and no other boot devices are configured - List<Disk> vmDisks = getPluggedDisks(vm); - if (boot_sequence == BootSequence.C && vmDisks.size() == 0) { - String messageStr = !vmDisks.isEmpty() ? - VdcBllMessages.VM_CANNOT_RUN_FROM_DISK_WITHOUT_PLUGGED_DISK.toString() : - VdcBllMessages.VM_CANNOT_RUN_FROM_DISK_WITHOUT_DISK.toString(); - - message.add(messageStr); - retValue = false; - } else { - // If CD appears as first and there is no ISO in storage - // pool/ISO inactive - - // you cannot run this VM - - if (boot_sequence == BootSequence.CD && findActiveISODomain(storagePoolId) == null) { - message.add(VdcBllMessages.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO.toString()); - retValue = false; - } else { - // if there is network in the boot sequence, check that the - // vm has network, - // otherwise the vm cannot be run in vdsm - if (boot_sequence == BootSequence.N - && DbFacade.getInstance().getVmNetworkInterfaceDao().getAllForVm(vm.getId()).size() == 0) { - message.add(VdcBllMessages.VM_CANNOT_RUN_FROM_NETWORK_WITHOUT_NETWORK.toString()); - retValue = false; - } - - if (retValue) { - ValidationResult vmNotLockedResult = new VmValidator(vm).vmNotLocked(); - if (!vmNotLockedResult.isValid()) { - message.add(vmNotLockedResult.getMessage().name()); - retValue = false; - } - } - - if (retValue) { - ValidationResult vmDuringSnapshotResult = - snapshotsValidator.vmNotDuringSnapshot(vm.getId()); - if (!vmDuringSnapshotResult.isValid()) { - message.add(vmDuringSnapshotResult.getMessage().name()); - retValue = false; - } - } - - List<DiskImage> vmImages = ImagesHandler.filterImageDisks(vmDisks, true, false); - if (retValue && !vmImages.isEmpty()) { - storage_pool sp = getStoragePoolDAO().get(vm.getStoragePoolId()); - ValidationResult spUpResult = new StoragePoolValidator(sp).isUp(); - if (!spUpResult.isValid()) { - message.add(spUpResult.getMessage().name()); - retValue = false; - } - - if (retValue) { - retValue = performImageChecksForRunningVm(vm, message, runParams, vmImages); - } - - // Check if iso and floppy path exists - if (retValue && !vm.isAutoStartup() - && !validateIsoPath(findActiveISODomain(vm.getStoragePoolId()), - runParams, - message)) { - retValue = false; - } else if (retValue) { - boolean isVmDuringInit = ((Boolean) getBackend() - .getResourceManager() - .RunVdsCommand(VDSCommandType.IsVmDuringInitiating, - new IsVmDuringInitiatingVDSCommandParameters(vm.getId())) - .getReturnValue()).booleanValue(); - if (vm.isRunning() || (vm.getStatus() == VMStatus.NotResponding) || isVmDuringInit) { - retValue = false; - message.add(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_RUNNING.toString()); - } else if (vm.getStatus() == VMStatus.Paused && vm.getRunOnVds() != null) { - VDS vds = DbFacade.getInstance().getVdsDao().get( - new Guid(vm.getRunOnVds().toString())); - if (vds.getStatus() != VDSStatus.Up) { - retValue = false; - message.add(VdcBllMessages.VAR__HOST_STATUS__UP.toString()); - message.add(VdcBllMessages.ACTION_TYPE_FAILED_VDS_STATUS_ILLEGAL.toString()); - } - } - - boolean isStatelessVm = shouldVmRunAsStateless(runParams, vm); - - if (retValue && isStatelessVm && !snapshotsValidator.vmNotInPreview(vm.getId()).isValid()) { - retValue = false; - message.add(VdcBllMessages.VM_CANNOT_RUN_STATELESS_WHILE_IN_PREVIEW.toString()); - } - - // if the VM itself is stateless or run once as stateless - if (retValue && isStatelessVm && vm.isAutoStartup()) { - retValue = false; - message.add(VdcBllMessages.VM_CANNOT_RUN_STATELESS_HA.toString()); - } - - if (retValue && isStatelessVm && !hasSpaceForSnapshots(vm, message)) { - return false; - } - } - } - - retValue = retValue == false ? retValue : vdsSelector.canFindVdsToRunOn(message, false); - - /** - * only if can do action ok then check with actions matrix that status is valid for this - * action - */ - if (retValue - && !VdcActionUtils.CanExecute(Arrays.asList(vm), VM.class, - VdcActionType.RunVm)) { - retValue = false; - message.add(VdcBllMessages.ACTION_TYPE_FAILED_VM_STATUS_ILLEGAL.toString()); - } - } - } - } - return retValue; - } - - /** - * check that we can create snapshots for all disks - * - * @param vm - * @return true if all storage domains have enough space to create snapshots for this VM plugged disks - */ - public boolean hasSpaceForSnapshots(VM vm, ArrayList<String> message) { - Integer minSnapshotSize = Config.<Integer> GetValue(ConfigValues.InitStorageSparseSizeInGB); - for (Entry<StorageDomain, Integer> e : mapStorageDomainsToNumOfDisks(vm).entrySet()) { - if (!destinationHasSpace(e.getKey(), minSnapshotSize * e.getValue(), message)) { - return false; - } - } - return true; - } - - private boolean destinationHasSpace(StorageDomain storageDomain, long sizeRequested, ArrayList<String> message) { - return validate(new StorageDomainValidator(storageDomain).isDomainHasSpaceForRequest(sizeRequested), message); - } - - protected boolean validate(ValidationResult validationResult, ArrayList<String> message) { - if (!validationResult.isValid()) { - message.add(validationResult.getMessage().name()); - if (validationResult.getVariableReplacements() != null) { - for (String variableReplacement : validationResult.getVariableReplacements()) { - message.add(variableReplacement); - } - } - } - return validationResult.isValid(); - } - - /** - * map the VM number of pluggable and snapable disks from their domain. - * - * @param vm - * @return - */ - public Map<StorageDomain, Integer> mapStorageDomainsToNumOfDisks(VM vm) { - Map<StorageDomain, Integer> map = new HashMap<StorageDomain, Integer>(); - for (Disk disk : getPluggedDisks(vm)) { - if (disk.isAllowSnapshot()) { - for (StorageDomain domain : getStorageDomainDAO().getAllStorageDomainsByImageId(((DiskImage) disk).getImageId())) { - map.put(domain, map.containsKey(domain) ? Integer.valueOf(map.get(domain) + 1) : Integer.valueOf(1)); - } - } - } - return map; - } - - /** - * Check isValid, storageDomain and diskSpace only if VM is not HA VM - */ - protected boolean performImageChecksForRunningVm - (VM vm, List<String> message, RunVmParams runParams, List<DiskImage> vmDisks) { - return ImagesHandler.PerformImagesChecks(message, - vm.getStoragePoolId(), Guid.Empty, !vm.isAutoStartup(), - true, false, false, - !vm.isAutoStartup() || !runParams.getIsInternal(), - !vm.isAutoStartup() || !runParams.getIsInternal(), - vmDisks); } /** @@ -315,73 +76,6 @@ return isoGuid; } - @SuppressWarnings("unchecked") - private boolean validateIsoPath(Guid storageDomainId, - RunVmParams runParams, - ArrayList<String> messages) { - if (!StringUtils.isEmpty(runParams.getDiskPath())) { - if (storageDomainId == null) { - messages.add(VdcBllMessages.VM_CANNOT_RUN_FROM_CD_WITHOUT_ACTIVE_STORAGE_DOMAIN_ISO.toString()); - return false; - } - boolean retValForIso = false; - VdcQueryReturnValue ret = - getBackend().runInternalQuery(VdcQueryType.GetAllIsoImagesList, - new GetAllIsoImagesListParameters(storageDomainId)); - if (ret != null && ret.getReturnValue() != null && ret.getSucceeded()) { - List<RepoFileMetaData> repoFileNameList = (List<RepoFileMetaData>) ret.getReturnValue(); - if (repoFileNameList != null) { - for (RepoFileMetaData isoFileMetaData : (List<RepoFileMetaData>) ret.getReturnValue()) { - if (isoFileMetaData.getRepoFileName().equals(runParams.getDiskPath())) { - retValForIso = true; - break; - } - } - } - } - if (!retValForIso) { - messages.add(VdcBllMessages.ERROR_CANNOT_FIND_ISO_IMAGE_PATH.toString()); - return false; - } - } - - if (!StringUtils.isEmpty(runParams.getFloppyPath())) { - boolean retValForFloppy = false; - VdcQueryReturnValue ret = - getBackend().runInternalQuery(VdcQueryType.GetAllFloppyImagesList, - new GetAllIsoImagesListParameters(storageDomainId)); - if (ret != null && ret.getReturnValue() != null && ret.getSucceeded()) { - List<RepoFileMetaData> repoFileNameList = (List<RepoFileMetaData>) ret.getReturnValue(); - if (repoFileNameList != null) { - - for (RepoFileMetaData isoFileMetaData : (List<RepoFileMetaData>) ret.getReturnValue()) { - if (isoFileMetaData.getRepoFileName().equals(runParams.getFloppyPath())) { - retValForFloppy = true; - break; - } - } - } - } - if (!retValForFloppy) { - messages.add(VdcBllMessages.ERROR_CANNOT_FIND_FLOPPY_IMAGE_PATH.toString()); - return false; - } - } - - return true; - } - - public boolean shouldVmRunAsStateless(RunVmParams param, VM vm) { - if (param.getRunAsStateless() != null) { - return param.getRunAsStateless(); - } - return vm.isStateless(); - } - - protected BackendInternal getBackend() { - return Backend.getInstance(); - } - protected DiskDao getDiskDao() { return DbFacade.getInstance().getDiskDao(); } @@ -394,7 +88,4 @@ return DbFacade.getInstance().getStorageDomainDao(); } - protected StoragePoolDAO getStoragePoolDAO() { - return DbFacade.getInstance().getStoragePoolDao(); - } } diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java index 802998c..e60ac94 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java @@ -36,13 +36,13 @@ import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.IVdsAsyncCommand; +import org.ovirt.engine.core.common.businessentities.StorageDomain; 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.VmDevice; import org.ovirt.engine.core.common.businessentities.VmDeviceId; import org.ovirt.engine.core.common.businessentities.VmStatic; -import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.storage_pool; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend; @@ -100,7 +100,6 @@ public void mockBackend() { doReturn(backend).when(command).getBackend(); - doReturn(backend).when(vmRunHandler).getBackend(); VDSReturnValue vdsReturnValue = new VDSReturnValue(); vdsReturnValue.setReturnValue(true); @@ -291,7 +290,7 @@ } private VM createVmForTesting(String initrd, String kernel) { - mockVm(command); + mockVm(); // Set parameter command.getVm().setInitrdUrl(initrd); @@ -304,50 +303,55 @@ } /** - * Mock a VM. + * Mock a VM with status. */ - private VM mockVm(RunVmCommand<RunVmParams> spyVmCommand) { + private VM mockVm(VMStatus status) { VM vm = new VM(); - vm.setStatus(VMStatus.Down); + vm.setStatus(status); + vm.setVdsGroupId(new Guid()); doReturn(vmDAO).when(command).getVmDAO(); when(vmDAO.get(command.getParameters().getVmId())).thenReturn(vm); return vm; + } + + /** + * Mock a VM. + */ + private VM mockVm() { + return mockVm(VMStatus.Down); } @Before public void createCommand() { RunVmParams param = new RunVmParams(Guid.NewGuid()); command = spy(new RunVmCommand<RunVmParams>(param)); - - mockVmRunHandler(); - mockSuccessfulSnapshotValidator(); - mockVmPropertiesUtils(); - mockBackend(); - } - - protected void mockVmRunHandler() { - storage_pool sp = new storage_pool(); - sp.setstatus(StoragePoolStatus.Up); - when(spDao.get(any(Guid.class))).thenReturn(sp); - doReturn(spDao).when(vmRunHandler).getStoragePoolDAO(); - - doReturn(vmRunHandler).when(command).getVmRunHandler(); - - doReturn(true).when(vmRunHandler).performImageChecksForRunningVm(any(VM.class), + doReturn(true).when(command).validateNetworkInterfaces(); + doReturn(true).when(command).performImageChecksForRunningVm(any(VM.class), anyListOf(String.class), any(RunVmParams.class), anyListOf(DiskImage.class)); + + doReturn(spDao).when(command).getStoragePoolDAO(); + storage_pool sp = new storage_pool(); + sp.setstatus(StoragePoolStatus.Up); + when(spDao.get(any(Guid.class))).thenReturn(sp); + + doReturn(vmRunHandler).when(command).getVmRunHandler(); + + mockSuccessfulSnapshotValidator(); + mockVmPropertiesUtils(); + mockBackend(); } @Test public void canRunVmFailNodisk() { initDAOMocks(Collections.<Disk> emptyList(), Collections.<VmDevice> emptyList()); - final VM vm = new VM(); + final VM vm = mockVm(); doReturn(new VdsSelector(vm, new Guid(), true, new VdsFreeMemoryChecker(command))).when(command) .getVdsSelector(); - assertFalse(command.canRunVm(vm)); + assertFalse(command.canDoAction()); assertTrue(command.getReturnValue().getCanDoActionMessages().contains("VM_CANNOT_RUN_FROM_DISK_WITHOUT_DISK")); } @@ -358,13 +362,14 @@ disks.add(diskImage); final VmDevice vmDevice = createDiskVmDevice(diskImage); initDAOMocks(disks, Collections.singletonList(vmDevice)); - final VM vm = new VM(); + final VM vm = mockVm(VMStatus.Up); vm.setStatus(VMStatus.Up); vm.setStoragePoolId(Guid.NewGuid()); + doReturn(new VdsSelector(vm, new NGuid(), true, new VdsFreeMemoryChecker(command))).when(command) .getVdsSelector(); - assertFalse(command.canRunVm(vm)); + assertFalse(command.canDoAction()); assertTrue(command.getReturnValue().getCanDoActionMessages().contains("ACTION_TYPE_FAILED_VM_IS_RUNNING")); } @@ -375,13 +380,13 @@ disks.add(diskImage); final VmDevice vmDevice = createDiskVmDevice(diskImage); initDAOMocks(disks, Collections.singletonList(vmDevice)); - final VM vm = new VM(); + final VM vm = mockVm(); SnapshotsValidator snapshotsValidator = mock(SnapshotsValidator.class); when(snapshotsValidator.vmNotDuringSnapshot(vm.getId())) .thenReturn(new ValidationResult(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_DURING_SNAPSHOT)); doReturn(snapshotsValidator).when(command).getSnapshotsValidator(); - assertFalse(command.canRunVm(vm)); + assertFalse(command.canDoAction()); assertTrue(command.getReturnValue() .getCanDoActionMessages() .contains(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_DURING_SNAPSHOT.name())); @@ -405,13 +410,13 @@ when(vdsBrokerFrontend.RunVdsCommand(eq(VDSCommandType.IsVmDuringInitiating), any(VDSParametersBase.class))).thenReturn(vdsReturnValue); initDAOMocks(disks, Collections.singletonList(vmDevice)); - final VM vm = new VM(); + final VM vm = mockVm(); // set stateless and HA vm.setStateless(isVmStateless); vm.setAutoStartup(autoStartUp); command.getParameters().setRunAsStateless(isStatelessParam); - boolean canRunVm = command.canRunVm(vm); + boolean canRunVm = command.canDoAction(); final List<String> messages = command.getReturnValue().getCanDoActionMessages(); assertEquals(shouldPass, canRunVm); -- To view, visit http://gerrit.ovirt.org/13111 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id4f65185ac3c3e2b6d65dd772268dbccaf9168a8 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Gilad Chaplik <gchap...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches