package org.ovirt.engine.core.bll; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.action.VmTemplateParametersBase; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.DiskImageTemplate; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmTemplate; import org.ovirt.engine.core.common.businessentities.image_group_storage_domain_map; import org.ovirt.engine.core.common.businessentities.storage_domain_static; import org.ovirt.engine.core.common.vdscommands.IrsBaseVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.LogCompat; import org.ovirt.engine.core.compat.LogFactoryCompat; import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.transaction.TransactionMethod; import org.ovirt.engine.core.utils.transaction.TransactionSupport; @NonTransactiveCommandAttribute(forceCompensation = true) public class RemoveVmTemplateCommand<T extends VmTemplateParametersBase> extends VmTemplateCommand<T> { public RemoveVmTemplateCommand(T parameters) { super(parameters); super.setVmTemplateId(parameters.getVmTemplateId()); parameters.setEntityId(getVmTemplateId()); } @Override protected boolean canDoAction() { Guid vmTemplateId = getVmTemplateId(); VmTemplate template = getVmTemplate(); // add command specific can do action variables addCanDoActionMessage(VdcBllMessages.VAR__ACTION__REMOVE); addCanDoActionMessage(VdcBllMessages.VAR__TYPE__VM_TEMPLATE); // check template exists if (template == null) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST); return false; } // check not blank template if (VmTemplateHandler.BlankVmTemplateId.equals(vmTemplateId)) { addCanDoActionMessage(VdcBllMessages.VMT_CANNOT_REMOVE_BLANK_TEMPLATE); return false; } // check storage pool valid if (template.getstorage_pool_id() != null && !((Boolean) Backend .getInstance() .getResourceManager() .RunVdsCommand(VDSCommandType.IsValid, new IrsBaseVDSCommandParameters(template.getstorage_pool_id().getValue())) .getReturnValue()).booleanValue()) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_IMAGE_REPOSITORY_NOT_FOUND); return false; } List<Guid> storageDomainsList = getParameters().getStorageDomainsList(); List<Guid> allDomainsList = getAllTemplateDoamins(); // if null or empty list sent, get all template domains for deletion if (storageDomainsList == null || storageDomainsList.isEmpty()) { // populate all the domains of the template getParameters().setStorageDomainsList(allDomainsList); getParameters().setRemoveTemplateFromDb(true); } else { // if some domains sent, check that the sent domains are part of all domains ArrayList<String> problematicDomains = new ArrayList<String>(); for (Guid domainId : storageDomainsList) { if (!allDomainsList.contains(domainId)) { storage_domain_static domain = DbFacade.getInstance().getStorageDomainStaticDAO().get(domainId); if (domain == null) { problematicDomains.add(domainId.toString()); } else { problematicDomains.add(domain.getstorage_name()); } } } if (!problematicDomains.isEmpty()) { addCanDoActionMessage(VdcBllMessages.VMT_CANNOT_REMOVE_DOMAINS_LIST_MISMATCH); addCanDoActionMessage(String.format("$domainsList %1$s", StringUtils.join(problematicDomains, ","))); return false; } getParameters().setRemoveTemplateFromDb(allDomainsList.size() == storageDomainsList.size()); } // check template images for selected domains ArrayList<String> canDoActionMessages = getReturnValue().getCanDoActionMessages(); for (Guid domainId : getParameters().getStorageDomainsList()) { if (!isVmTemplateImagesReady(vmTemplateId, domainId, canDoActionMessages, getParameters().getCheckDisksExists(), true, false, true)) { return false; } } // check no vms from this template on selected domains List<VM> vms = DbFacade.getInstance().getVmDAO().getAllWithTemplate(vmTemplateId); ArrayList<String> problematicVmNames = new ArrayList<String>(); for (VM vm : vms) { if (getParameters().isRemoveTemplateFromDb()) { problematicVmNames.add(vm.getvm_name()); } else { List<DiskImage> vmDIsks = DbFacade.getInstance().getDiskImageDAO().getAllForVm(vm.getvm_guid()); if (vmDIsks != null && !vmDIsks.isEmpty() && storageDomainsList.contains(vmDIsks.get(0).getstorage_id())) { problematicVmNames.add(vm.getvm_name()); } } } if (!problematicVmNames.isEmpty()) { addCanDoActionMessage(VdcBllMessages.VMT_CANNOT_REMOVE_DETECTED_DERIVED_VM); addCanDoActionMessage(String.format("$vmsList %1$s", StringUtils.join(problematicVmNames, ","))); return false; } return true; } /** * Get a list of all domains id that the template is on */ private List<Guid> getAllTemplateDoamins() { ArrayList<Guid> domainsList = new ArrayList<Guid>(); List<DiskImageTemplate> imageTemplates = DbFacade.getInstance().getDiskImageTemplateDAO().getAllByVmTemplate(getVmTemplateId()); if (imageTemplates != null && !imageTemplates.isEmpty()) { DiskImage disk = DbFacade.getInstance() .getDiskImageDAO() .getSnapshotById(imageTemplates.get(0).getId()); // populate storages list domainsList.add(disk.getstorage_id().getValue()); for (image_group_storage_domain_map map : DbFacade.getInstance() .getStorageDomainDAO() .getAllImageGroupStorageDomainMapsForImage(disk.getimage_group_id().getValue())) { domainsList.add(map.getstorage_domain_id()); } } return domainsList; } public RemoveVmTemplateCommand(Guid vmTemplateId) { super.setVmTemplateId(vmTemplateId); } @Override protected void executeCommand() { if (VmTemplateHandler.isTemplateStatusIsNotLocked(getVmTemplateId())) { // Set VM to lock status immediately, for reducing race condition. VmTemplateHandler.lockVmTemplateInTransaction(getVmTemplateId(), getCompensationContext()); // if for some reason template doesn't have images, remove it now and not in end action final boolean hasImanges = DbFacade.getInstance().getDiskImageTemplateDAO().getAllByVmTemplate(getVmTemplateId()).size() > 0; if (RemoveTemplateInSpm(getVmTemplate().getstorage_pool_id().getValue(), getVmTemplateId())) { TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { @Override public Void runInTransaction() { if (RemoveVmTemplateImages()) { if (!hasImanges) { RemoveTemplateFromDb(); } setSucceeded(true); } return null; } }); } } } private void RemoveTemplateFromDb() { RemoveNetwork(); DbFacade.getInstance().getVmTemplateDAO().remove(getVmTemplate().getId()); } protected boolean RemoveVmTemplateImages() { getParameters().setEntityId(getParameters().getEntityId()); VdcReturnValueBase vdcReturnValue = Backend.getInstance().runInternalAction( VdcActionType.RemoveAllVmTemplateImageTemplates, getParameters()); if (!vdcReturnValue.getSucceeded()) { setSucceeded(false); getReturnValue().setFault(vdcReturnValue.getFault()); return false; } getReturnValue().getTaskIdList().addAll(vdcReturnValue.getInternalTaskIdList()); return true; } @Override public AuditLogType getAuditLogTypeValue() { switch (getActionState()) { case EXECUTE: return getSucceeded() ? AuditLogType.USER_REMOVE_VM_TEMPLATE : AuditLogType.USER_FAILED_REMOVE_VM_TEMPLATE; case END_FAILURE: case END_SUCCESS: default: return AuditLogType.USER_REMOVE_VM_TEMPLATE_FINISHED; } } @Override protected void EndSuccessfully() { HandleEndAction(); } @Override protected void EndWithFailure() { HandleEndAction(); } private void HandleEndAction() { try { if (getParameters().isRemoveTemplateFromDb()) { RemoveTemplateFromDb(); } else { // unlock template VmTemplateHandler.UnLockVmTemplate(getVmTemplateId()); } setSucceeded(true); } catch (RuntimeException e) { // Set the try again of task to false, to prevent log spam and audit log spam. getReturnValue().setEndActionTryAgain(false); log.errorFormat("Encounter a problem removing template from DB, Setting the action, not to try again."); } } private static LogCompat log = LogFactoryCompat.getLog(RemoveVmTemplateCommand.class); }