<commit_before>package org.ovirt.engine.core.bll;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.job.ExecutionHandler;
import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter;
import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter;
import org.ovirt.engine.core.bll.quota.QuotaStorageDependent;
import org.ovirt.engine.core.bll.storage.StoragePoolValidator;
import org.ovirt.engine.core.bll.validator.DiskImagesValidator;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.VdcObjectType;
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.asynctasks.EntityInfo;
import org.ovirt.engine.core.common.businessentities.DiskImage;
import org.ovirt.engine.core.common.businessentities.StorageDomainStatic;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VmEntityType;
import org.ovirt.engine.core.common.businessentities.VmTemplate;
import org.ovirt.engine.core.common.locks.LockingGroup;
import org.ovirt.engine.core.common.errors.VdcBllMessages;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.utils.collections.MultiValueMapUtils;
import org.ovirt.engine.core.utils.transaction.TransactionMethod;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;

@DisableInPrepareMode
@NonTransactiveCommandAttribute(forceCompensation = true)
@LockIdNameAttribute(isReleaseAtEndOfExecute = false)
public class RemoveVmTemplateCommand<T extends VmTemplateParametersBase> extends VmTemplateCommand<T>
        implements QuotaStorageDependent {

    private List<DiskImage> imageTemplates;
    private final Map<Guid, List<DiskImage>> storageToDisksMap = new HashMap<Guid, List<DiskImage>>();

    public RemoveVmTemplateCommand(T parameters) {
        super(parameters);
        super.setVmTemplateId(parameters.getVmTemplateId());
        parameters.setEntityInfo(new EntityInfo(VdcObjectType.VmTemplate, getVmTemplateId()));
        if (getVmTemplate() != null) {
            setStoragePoolId(getVmTemplate().getStoragePoolId());
        }
    }

    public RemoveVmTemplateCommand(Guid vmTemplateId) {
        super.setVmTemplateId(vmTemplateId);
    }

    @Override
    protected void setActionMessageParameters() {
        addCanDoActionMessage(VdcBllMessages.VAR__ACTION__REMOVE);
        addCanDoActionMessage(VdcBllMessages.VAR__TYPE__VM_TEMPLATE);
    }

    @Override
    protected boolean canDoAction() {
        Guid vmTemplateId = getVmTemplateId();
        VmTemplate template = getVmTemplate();

        if (!super.canDoAction()) {
            return false;
        }

        boolean isInstanceType = getVmTemplate().getTemplateType() == VmEntityType.INSTANCE_TYPE;

        if (getVdsGroup() == null && !isInstanceType) {
            addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY);
            return false;
        }

        // check template exists
        if (!validate(templateExists())) {
            return false;
        }
        // check not blank template
        if (VmTemplateHandler.BLANK_VM_TEMPLATE_ID.equals(vmTemplateId)) {
            return failCanDoAction(VdcBllMessages.VMT_CANNOT_REMOVE_BLANK_TEMPLATE);
        }

        // check storage pool valid
        if (!isInstanceType && !validate(new StoragePoolValidator(getStoragePool()).isUp())) {
            return false;
        }

        // check if delete protected
        if (template.isDeleteProtected()) {
            return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_DELETE_PROTECTION_ENABLED);
        }

        if (!isInstanceType) {
            fetchImageTemplates();
        }

        List<Guid> storageDomainsList = getParameters().getStorageDomainsList();
        Set<Guid> allDomainsList = getStorageDomainsByDisks(imageTemplates, true);

        // 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(new ArrayList<Guid>(allDomainsList));
            getParameters().setRemoveTemplateFromDb(true);
        } else {
            // if some domains sent, check that the sent domains are part of all domains
            List<String> problematicDomains = new ArrayList<String>();
            for (Guid domainId : storageDomainsList) {
                if (!allDomainsList.contains(domainId)) {
                    StorageDomainStatic domain = getDbFacade().getStorageDomainStaticDao().get(domainId);
                    problematicDomains.add(domain == null ? domainId.toString() : domain.getStorageName());
                }
            }
            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(getVmTemplate(),
                    domainId,
                    canDoActionMessages,
                    getParameters().getCheckDisksExists(),
                    true,
                    false,
                    true,
                    storageToDisksMap.get(domainId))) {
                return false;
            }
        }

        // check no vms from this template on selected domains
        List<VM> vms = getVmDAO().getAllWithTemplate(vmTemplateId);
        List<String> problematicVmNames = new ArrayList<String>();
        for (VM vm : vms) {
            if (getParameters().isRemoveTemplateFromDb()) {
                problematicVmNames.add(vm.getName());
            } else {
                List<DiskImage> vmDIsks =
                        ImagesHandler.filterImageDisks(getDbFacade().getDiskDao().getAllForVm(vm.getId()),
                                false,
                                false,
                                true);
                Set<Guid> domainsIds = getStorageDomainsByDisks(vmDIsks, false);
                for (Guid domainId : domainsIds) {
                    if (!getParameters().getStorageDomainsList().contains(domainId)) {
                        problematicVmNames.add(vm.getName());
                    }
                }
            }
        }

        if (!problematicVmNames.isEmpty()) {
            addCanDoActionMessage(VdcBllMessages.VMT_CANNOT_REMOVE_DETECTED_DERIVED_VM);
            addCanDoActionMessage(String.format("$vmsList %1$s", StringUtils.join(problematicVmNames, ",")));
            return false;
        }

        // for base templates, make sure it has no versions that need to be removed first
        if (getParameters().isRemoveTemplateFromDb() && vmTemplateId.equals(template.getBaseTemplateId())) {
            List<VmTemplate> templateVersions = getVmTemplateDAO().getTemplateVersionsForBaseTemplate(vmTemplateId);
            if (!templateVersions.isEmpty()) {
                List<String> templateVersionsNames = new ArrayList<>();
                for (VmTemplate version : templateVersions) {
                    templateVersionsNames.add(version.getName());
                }

            addCanDoActionMessage(VdcBllMessages.VMT_CANNOT_REMOVE_BASE_WITH_VERSIONS);
            addCanDoActionMessage(String.format("$versionsList %1$s", StringUtils.join(templateVersionsNames, ",")));
            return false;
            }
        }

        if (isInstanceType) {
            return true;
        } else {
            return validate(checkNoDisksBasedOnTemplateDisks());
        }
    }

    private ValidationResult checkNoDisksBasedOnTemplateDisks() {
        return new DiskImagesValidator(imageTemplates).diskImagesHaveNoDerivedDisks(null);
    }

    private void fetchImageTemplates() {
        if (imageTemplates == null) {
            imageTemplates =
                    ImagesHandler.filterImageDisks(DbFacade.getInstance().getDiskDao().getAllForVm(getVmTemplateId()),
                            false,
                            false,
                            true);
        }
    }

    /**
     * Get a list of all domains id that the template is on
     */
    private Set<Guid> getStorageDomainsByDisks(List<DiskImage> disks, boolean isFillStorageTodDiskMap) {
        Set<Guid> domainsList = new HashSet<Guid>();
        if (disks != null) {
            for (DiskImage disk : disks) {
                domainsList.addAll(disk.getStorageIds());
                if (isFillStorageTodDiskMap) {
                    for (Guid storageDomainId : disk.getStorageIds()) {
                        MultiValueMapUtils.addToMap(storageDomainId, disk, storageToDisksMap);
                    }
                }
            }
        }
        return domainsList;
    }

    @Override
    protected void executeCommand() {
        // 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 hasImages = imageTemplates.size() > 0;
        if (hasImages) {
            TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() {

                @Override
                public Void runInTransaction() {
                    if (removeVmTemplateImages()) {
                        VmHandler.removeVmInitFromDB(getVmTemplate());
                        setSucceeded(true);
                    }
                    return null;
                }
            });
        } else {
            HandleEndAction();
        }
    }

    @Override
    protected Map<String, Pair<String, String>> getExclusiveLocks() {
        if (getVmTemplate() != null) {
            return Collections.singletonMap(getVmTemplateId().toString(),
                    LockMessagesMatchUtil.makeLockingPair(LockingGroup.TEMPLATE, getTemplateExclusiveLockMessage()));
        }
        return null;
    }

    private String getTemplateExclusiveLockMessage() {
        return new StringBuilder(VdcBllMessages.ACTION_TYPE_FAILED_TEMPLATE_IS_BEING_REMOVED.name())
        .append(String.format("$TemplateName %1$s", getVmTemplate().getName()))
        .toString();
    }

    private void removeTemplateFromDb() {
        removeNetwork();
        DbFacade.getInstance().getVmTemplateDao().remove(getVmTemplate().getId());
    }

    protected boolean removeVmTemplateImages() {
        getParameters().setEntityInfo(getParameters().getEntityInfo());
        getParameters().setParentCommand(getActionType());
        getParameters().setParentParameters(getParameters());
        VdcReturnValueBase vdcReturnValue = Backend.getInstance().runInternalAction(
                VdcActionType.RemoveAllVmTemplateImageTemplates,
                getParameters(),
                ExecutionHandler.createDefaultContexForTasks(getExecutionContext()));

        if (!vdcReturnValue.getSucceeded()) {
            setSucceeded(false);
            getReturnValue().setFault(vdcReturnValue.getFault());
            return false;
        }

        getReturnValue().getVdsmTaskIdList().addAll(vdcReturnValue.getInternalVdsmTaskIdList());
        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.error("Encountered a problem removing template from DB, setting the action not to retry.");
        }
    }

    @Override
    public List<QuotaConsumptionParameter> getQuotaStorageConsumptionParameters() {
        List<QuotaConsumptionParameter> list = new ArrayList<QuotaConsumptionParameter>();
        fetchImageTemplates();
        if (imageTemplates != null) {
            for (DiskImage disk : imageTemplates) {
                if (disk.getQuotaId() != null && !Guid.Empty.equals(disk.getQuotaId())) {
                    for (Guid storageId : disk.getStorageIds()) {
                        list.add(new QuotaStorageConsumptionParameter(
                                disk.getQuotaId(),
                                null,
                                QuotaStorageConsumptionParameter.QuotaAction.RELEASE,
                                storageId,
                                (double) disk.getSizeInGigabytes()));
                    }
                }
            }
        }
        return list;
    }
}
<commit_msg>core: minor refactoring in RemoveVmTemplateCommand<commit_after>package org.ovirt.engine.core.bll;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.job.ExecutionHandler;
import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter;
import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter;
import org.ovirt.engine.core.bll.quota.QuotaStorageDependent;
import org.ovirt.engine.core.bll.storage.StoragePoolValidator;
import org.ovirt.engine.core.bll.validator.DiskImagesValidator;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.VdcObjectType;
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.asynctasks.EntityInfo;
import org.ovirt.engine.core.common.businessentities.DiskImage;
import org.ovirt.engine.core.common.businessentities.StorageDomainStatic;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VmEntityType;
import org.ovirt.engine.core.common.businessentities.VmTemplate;
import org.ovirt.engine.core.common.locks.LockingGroup;
import org.ovirt.engine.core.common.errors.VdcBllMessages;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.utils.collections.MultiValueMapUtils;
import org.ovirt.engine.core.utils.transaction.TransactionMethod;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;

@DisableInPrepareMode
@NonTransactiveCommandAttribute(forceCompensation = true)
@LockIdNameAttribute(isReleaseAtEndOfExecute = false)
public class RemoveVmTemplateCommand<T extends VmTemplateParametersBase> extends VmTemplateCommand<T>
        implements QuotaStorageDependent {

    private List<DiskImage> imageTemplates;
    private final Map<Guid, List<DiskImage>> storageToDisksMap = new HashMap<Guid, List<DiskImage>>();

    public RemoveVmTemplateCommand(T parameters) {
        super(parameters);
        super.setVmTemplateId(parameters.getVmTemplateId());
        parameters.setEntityInfo(new EntityInfo(VdcObjectType.VmTemplate, getVmTemplateId()));
        if (getVmTemplate() != null) {
            setStoragePoolId(getVmTemplate().getStoragePoolId());
        }
    }

    public RemoveVmTemplateCommand(Guid vmTemplateId) {
        super.setVmTemplateId(vmTemplateId);
    }

    @Override
    protected void setActionMessageParameters() {
        addCanDoActionMessage(VdcBllMessages.VAR__ACTION__REMOVE);
        addCanDoActionMessage(VdcBllMessages.VAR__TYPE__VM_TEMPLATE);
    }

    @Override
    protected boolean canDoAction() {
        Guid vmTemplateId = getVmTemplateId();
        VmTemplate template = getVmTemplate();

        if (!super.canDoAction()) {
            return false;
        }

        boolean isInstanceType = getVmTemplate().getTemplateType() == VmEntityType.INSTANCE_TYPE;

        if (getVdsGroup() == null && !isInstanceType) {
            addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY);
            return false;
        }

        // check template exists
        if (!validate(templateExists())) {
            return false;
        }
        // check not blank template
        if (VmTemplateHandler.BLANK_VM_TEMPLATE_ID.equals(vmTemplateId)) {
            return failCanDoAction(VdcBllMessages.VMT_CANNOT_REMOVE_BLANK_TEMPLATE);
        }

        // check storage pool valid
        if (!isInstanceType && !validate(new StoragePoolValidator(getStoragePool()).isUp())) {
            return false;
        }

        // check if delete protected
        if (template.isDeleteProtected()) {
            return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_DELETE_PROTECTION_ENABLED);
        }

        if (!isInstanceType) {
            fetchImageTemplates();
        }

        List<Guid> storageDomainsList = getParameters().getStorageDomainsList();
        Set<Guid> allDomainsList = getStorageDomainsByDisks(imageTemplates, true);

        // 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(new ArrayList<Guid>(allDomainsList));
            getParameters().setRemoveTemplateFromDb(true);
        } else {
            // if some domains sent, check that the sent domains are part of all domains
            List<String> problematicDomains = new ArrayList<String>();
            for (Guid domainId : storageDomainsList) {
                if (!allDomainsList.contains(domainId)) {
                    StorageDomainStatic domain = getDbFacade().getStorageDomainStaticDao().get(domainId);
                    problematicDomains.add(domain == null ? domainId.toString() : domain.getStorageName());
                }
            }
            if (!problematicDomains.isEmpty()) {
                return failCanDoAction(VdcBllMessages.VMT_CANNOT_REMOVE_DOMAINS_LIST_MISMATCH,
                        String.format("$domainsList %1$s", StringUtils.join(problematicDomains, ",")));
            }
            getParameters().setRemoveTemplateFromDb(allDomainsList.size() == storageDomainsList.size());
        }

        // check template images for selected domains
        ArrayList<String> canDoActionMessages = getReturnValue().getCanDoActionMessages();
        for (Guid domainId : getParameters().getStorageDomainsList()) {
            if (!isVmTemplateImagesReady(getVmTemplate(),
                    domainId,
                    canDoActionMessages,
                    getParameters().getCheckDisksExists(),
                    true,
                    false,
                    true,
                    storageToDisksMap.get(domainId))) {
                return false;
            }
        }

        // check no vms from this template on selected domains
        List<VM> vms = getVmDAO().getAllWithTemplate(vmTemplateId);
        List<String> problematicVmNames = new ArrayList<String>();
        for (VM vm : vms) {
            if (getParameters().isRemoveTemplateFromDb()) {
                problematicVmNames.add(vm.getName());
            } else {
                List<DiskImage> vmDIsks =
                        ImagesHandler.filterImageDisks(getDbFacade().getDiskDao().getAllForVm(vm.getId()),
                                false,
                                false,
                                true);
                Set<Guid> domainsIds = getStorageDomainsByDisks(vmDIsks, false);
                for (Guid domainId : domainsIds) {
                    if (!getParameters().getStorageDomainsList().contains(domainId)) {
                        problematicVmNames.add(vm.getName());
                    }
                }
            }
        }

        if (!problematicVmNames.isEmpty()) {
            return failCanDoAction(VdcBllMessages.VMT_CANNOT_REMOVE_DETECTED_DERIVED_VM,
                    String.format("$vmsList %1$s", StringUtils.join(problematicVmNames, ",")));
        }

        // for base templates, make sure it has no versions that need to be removed first
        if (getParameters().isRemoveTemplateFromDb() && vmTemplateId.equals(template.getBaseTemplateId())) {
            List<VmTemplate> templateVersions = getVmTemplateDAO().getTemplateVersionsForBaseTemplate(vmTemplateId);
            if (!templateVersions.isEmpty()) {
                List<String> templateVersionsNames = new ArrayList<>();
                for (VmTemplate version : templateVersions) {
                    templateVersionsNames.add(version.getName());
                }

                return failCanDoAction(VdcBllMessages.VMT_CANNOT_REMOVE_BASE_WITH_VERSIONS,
                        String.format("$versionsList %1$s", StringUtils.join(templateVersionsNames, ",")));
            }
        }

        if (!isInstanceType && !validate(checkNoDisksBasedOnTemplateDisks())) {
            return false;
        }

        return true;
    }

    private ValidationResult checkNoDisksBasedOnTemplateDisks() {
        return new DiskImagesValidator(imageTemplates).diskImagesHaveNoDerivedDisks(null);
    }

    private void fetchImageTemplates() {
        if (imageTemplates == null) {
            imageTemplates =
                    ImagesHandler.filterImageDisks(DbFacade.getInstance().getDiskDao().getAllForVm(getVmTemplateId()),
                            false,
                            false,
                            true);
        }
    }

    /**
     * Get a list of all domains id that the template is on
     */
    private Set<Guid> getStorageDomainsByDisks(List<DiskImage> disks, boolean isFillStorageTodDiskMap) {
        Set<Guid> domainsList = new HashSet<Guid>();
        if (disks != null) {
            for (DiskImage disk : disks) {
                domainsList.addAll(disk.getStorageIds());
                if (isFillStorageTodDiskMap) {
                    for (Guid storageDomainId : disk.getStorageIds()) {
                        MultiValueMapUtils.addToMap(storageDomainId, disk, storageToDisksMap);
                    }
                }
            }
        }
        return domainsList;
    }

    @Override
    protected void executeCommand() {
        // Set VM to lock status immediately, for reducing race condition.
        VmTemplateHandler.lockVmTemplateInTransaction(getVmTemplateId(), getCompensationContext());

        if (!imageTemplates.isEmpty()) {
            TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() {

                @Override
                public Void runInTransaction() {
                    if (removeVmTemplateImages()) {
                        VmHandler.removeVmInitFromDB(getVmTemplate());
                        setSucceeded(true);
                    }
                    return null;
                }
            });
        } else {
            // if for some reason template doesn't have images, remove it now and not in end action
            HandleEndAction();
        }
    }

    @Override
    protected Map<String, Pair<String, String>> getExclusiveLocks() {
        if (getVmTemplate() != null) {
            return Collections.singletonMap(getVmTemplateId().toString(),
                    LockMessagesMatchUtil.makeLockingPair(LockingGroup.TEMPLATE, getTemplateExclusiveLockMessage()));
        }
        return null;
    }

    private String getTemplateExclusiveLockMessage() {
        return new StringBuilder(VdcBllMessages.ACTION_TYPE_FAILED_TEMPLATE_IS_BEING_REMOVED.name())
        .append(String.format("$TemplateName %1$s", getVmTemplate().getName()))
        .toString();
    }

    private void removeTemplateFromDb() {
        removeNetwork();
        DbFacade.getInstance().getVmTemplateDao().remove(getVmTemplate().getId());
    }

    protected boolean removeVmTemplateImages() {
        getParameters().setEntityInfo(getParameters().getEntityInfo());
        getParameters().setParentCommand(getActionType());
        getParameters().setParentParameters(getParameters());
        VdcReturnValueBase vdcReturnValue = Backend.getInstance().runInternalAction(
                VdcActionType.RemoveAllVmTemplateImageTemplates,
                getParameters(),
                ExecutionHandler.createDefaultContexForTasks(getExecutionContext()));

        if (!vdcReturnValue.getSucceeded()) {
            setSucceeded(false);
            getReturnValue().setFault(vdcReturnValue.getFault());
            return false;
        }

        getReturnValue().getVdsmTaskIdList().addAll(vdcReturnValue.getInternalVdsmTaskIdList());
        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.error("Encountered a problem removing template from DB, setting the action not to retry.");
        }
    }

    @Override
    public List<QuotaConsumptionParameter> getQuotaStorageConsumptionParameters() {
        List<QuotaConsumptionParameter> list = new ArrayList<QuotaConsumptionParameter>();
        fetchImageTemplates();
        if (imageTemplates != null) {
            for (DiskImage disk : imageTemplates) {
                if (disk.getQuotaId() != null && !Guid.Empty.equals(disk.getQuotaId())) {
                    for (Guid storageId : disk.getStorageIds()) {
                        list.add(new QuotaStorageConsumptionParameter(
                                disk.getQuotaId(),
                                null,
                                QuotaStorageConsumptionParameter.QuotaAction.RELEASE,
                                storageId,
                                (double) disk.getSizeInGigabytes()));
                    }
                }
            }
        }
        return list;
    }
}

{'fraction_non_alphanumeric': 0.09356313753077734, 'fraction_numerical': 0.00031656700668308125, 'mean_word_length': 2.387062187276626, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 66, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7064601', 'n_tokens_mistral': 7673, 'n_tokens_neox': 7447, 'n_words': 1274}