<commit_before>/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package com.cloud.template;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ejb.Local;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DetachIsoCmd;
import com.cloud.api.commands.ExtractIsoCmd;
import com.cloud.api.commands.ExtractTemplateCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventState;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.Upload;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.UserAccount;
import com.cloud.user.UserContext;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

@Local(value=TemplateManager.class)
public class TemplateManagerImpl implements TemplateManager {
    private final static Logger s_logger = Logger.getLogger(TemplateManagerImpl.class);
    String _name;
    @Inject VMTemplateDao _tmpltDao;
    @Inject VMTemplateHostDao _tmpltHostDao;
    @Inject VMTemplatePoolDao _tmpltPoolDao;
    @Inject VMTemplateZoneDao _tmpltZoneDao;
    @Inject VMInstanceDao _vmInstanceDao;
    @Inject StoragePoolDao _poolDao;
    @Inject StoragePoolHostDao _poolHostDao;
    @Inject EventDao _eventDao;
    @Inject DownloadMonitor _downloadMonitor;
    @Inject UploadMonitor _uploadMonitor;
    @Inject UserAccountDao _userAccountDao;
    @Inject AccountDao _accountDao;
    @Inject UserDao _userDao;
    @Inject AgentManager _agentMgr;
    @Inject AccountManager _accountMgr;
    @Inject HostDao _hostDao;
    @Inject DataCenterDao _dcDao;
    @Inject UserVmDao _userVmDao;
    @Inject VolumeDao _volumeDao;
    @Inject SnapshotDao _snapshotDao;
    @Inject DomainDao _domainDao;
    @Inject UploadDao _uploadDao;
    long _routerTemplateId = -1;
    @Inject StorageManager _storageMgr;
    @Inject UserVmManager _vmMgr;
    @Inject ConfigurationDao _configDao;
    protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch;
    
    @Override
    public VMTemplateVO registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException{
        Account ctxAccount = UserContext.current().getAccount();
        Long userId = UserContext.current().getUserId();
        String name = cmd.getIsoName();
        String displayText = cmd.getDisplayText();
        String url = cmd.getUrl();
        Boolean isPublic = cmd.isPublic();
        Boolean featured = cmd.isFeatured();
        Long guestOSId = cmd.getOsTypeId();
        Boolean bootable = cmd.isBootable();
        Long zoneId = cmd.getZoneId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account resourceAccount = null;
        Long accountId = null;
        
        if (isPublic == null) {
            isPublic = Boolean.FALSE;
        }
        
        if (zoneId.longValue() == -1) {
        	zoneId = null;
        }        
        
        if ( (accountName == null) ^ (domainId == null) ){// XOR - Both have to be passed or don't pass any of them 
        	throw new InvalidParameterValueException("Please specify both account and domainId or dont specify any of them");
        }
        
        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to register ISO, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                	resourceAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (resourceAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = resourceAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }
        
        if (null == accountId && null == accountName && null == domainId && null == ctxAccount){
        	accountId = 1L;
        }
        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for registering an ISO.");
        }
        
        boolean isAdmin = _accountDao.findById(accountId).getType() == Account.ACCOUNT_TYPE_ADMIN;
        
        if (!isAdmin && zoneId == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid zone Id.");
        }
        
        if((!url.toLowerCase().endsWith("iso"))&&(!url.toLowerCase().endsWith("iso.zip"))&&(!url.toLowerCase().endsWith("iso.bz2"))
        		&&(!url.toLowerCase().endsWith("iso.gz"))){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid iso");
        }
        
        boolean allowPublicUserTemplates = Boolean.parseBoolean(_configDao.getValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private ISOs can be created.");
        }
        
        if (!isAdmin || featured == null) {
        	featured = Boolean.FALSE;
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }
        
        if (bootable == null) {
        	bootable = Boolean.TRUE;
        }

        //removing support for file:// type urls (bug: 4239)
        if(url.toLowerCase().contains("file://")){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "File:// type urls are currently unsupported");
        }
        
        return createTemplateOrIso(userId, accountId, zoneId, name, displayText, isPublic.booleanValue(), featured.booleanValue(), ImageFormat.ISO.toString(), null, url, null, true, 64 /*bits*/, false, guestOSId, bootable, HypervisorType.None);
    }

    @Override
    public VMTemplateVO registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException{
    	
        Account ctxAccount = UserContext.current().getAccount();
        Long userId = UserContext.current().getUserId();
        String name = cmd.getTemplateName();
        String displayText = cmd.getDisplayText(); 
        Integer bits = cmd.getBits();
        Boolean passwordEnabled = cmd.isPasswordEnabled();
        Boolean requiresHVM = cmd.getRequiresHvm();
        String url = cmd.getUrl();
        Boolean isPublic = cmd.isPublic();
        Boolean featured = cmd.isFeatured();
        String format = cmd.getFormat();
        Long guestOSId = cmd.getOsTypeId();
        Long zoneId = cmd.getZoneId();
        HypervisorType hypervisorType = HypervisorType.valueOf(cmd.getHypervisor());
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account resourceAccount = null;
        Long accountId = null;

        //parameters verification
        if (bits == null) {
            bits = Integer.valueOf(64);
        }
        if (passwordEnabled == null) {
            passwordEnabled = false;
        }
        if (requiresHVM == null) {
            requiresHVM = true;
        }
        if (isPublic == null) {
            isPublic = Boolean.FALSE;
        }
        
        if (zoneId.longValue() == -1) {
        	zoneId = null;
        }
        
        if ( (accountName == null) ^ (domainId == null) ){// XOR - Both have to be passed or don't pass any of them 
        	throw new InvalidParameterValueException("Please specify both account and domainId or dont specify any of them");
        }
        
        // This complex logic is just for figuring out the template owning account because a user can register templates on other account's behalf.<commit_msg>RegisterTemplateCommand - ignore case in "hypervisor" parameter value - used to complain when "xen" was specified instead of "Xen"<commit_after>/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package com.cloud.template;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ejb.Local;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DetachIsoCmd;
import com.cloud.api.commands.ExtractIsoCmd;
import com.cloud.api.commands.ExtractTemplateCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventState;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.Upload;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.UserAccount;
import com.cloud.user.UserContext;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

@Local(value=TemplateManager.class)
public class TemplateManagerImpl implements TemplateManager {
    private final static Logger s_logger = Logger.getLogger(TemplateManagerImpl.class);
    String _name;
    @Inject VMTemplateDao _tmpltDao;
    @Inject VMTemplateHostDao _tmpltHostDao;
    @Inject VMTemplatePoolDao _tmpltPoolDao;
    @Inject VMTemplateZoneDao _tmpltZoneDao;
    @Inject VMInstanceDao _vmInstanceDao;
    @Inject StoragePoolDao _poolDao;
    @Inject StoragePoolHostDao _poolHostDao;
    @Inject EventDao _eventDao;
    @Inject DownloadMonitor _downloadMonitor;
    @Inject UploadMonitor _uploadMonitor;
    @Inject UserAccountDao _userAccountDao;
    @Inject AccountDao _accountDao;
    @Inject UserDao _userDao;
    @Inject AgentManager _agentMgr;
    @Inject AccountManager _accountMgr;
    @Inject HostDao _hostDao;
    @Inject DataCenterDao _dcDao;
    @Inject UserVmDao _userVmDao;
    @Inject VolumeDao _volumeDao;
    @Inject SnapshotDao _snapshotDao;
    @Inject DomainDao _domainDao;
    @Inject UploadDao _uploadDao;
    long _routerTemplateId = -1;
    @Inject StorageManager _storageMgr;
    @Inject UserVmManager _vmMgr;
    @Inject ConfigurationDao _configDao;
    protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch;
    
    @Override
    public VMTemplateVO registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException{
        Account ctxAccount = UserContext.current().getAccount();
        Long userId = UserContext.current().getUserId();
        String name = cmd.getIsoName();
        String displayText = cmd.getDisplayText();
        String url = cmd.getUrl();
        Boolean isPublic = cmd.isPublic();
        Boolean featured = cmd.isFeatured();
        Long guestOSId = cmd.getOsTypeId();
        Boolean bootable = cmd.isBootable();
        Long zoneId = cmd.getZoneId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account resourceAccount = null;
        Long accountId = null;
        
        if (isPublic == null) {
            isPublic = Boolean.FALSE;
        }
        
        if (zoneId.longValue() == -1) {
        	zoneId = null;
        }        
        
        if ( (accountName == null) ^ (domainId == null) ){// XOR - Both have to be passed or don't pass any of them 
        	throw new InvalidParameterValueException("Please specify both account and domainId or dont specify any of them");
        }
        
        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to register ISO, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                	resourceAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (resourceAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = resourceAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }
        
        if (null == accountId && null == accountName && null == domainId && null == ctxAccount){
        	accountId = 1L;
        }
        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for registering an ISO.");
        }
        
        boolean isAdmin = _accountDao.findById(accountId).getType() == Account.ACCOUNT_TYPE_ADMIN;
        
        if (!isAdmin && zoneId == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid zone Id.");
        }
        
        if((!url.toLowerCase().endsWith("iso"))&&(!url.toLowerCase().endsWith("iso.zip"))&&(!url.toLowerCase().endsWith("iso.bz2"))
        		&&(!url.toLowerCase().endsWith("iso.gz"))){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid iso");
        }
        
        boolean allowPublicUserTemplates = Boolean.parseBoolean(_configDao.getValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private ISOs can be created.");
        }
        
        if (!isAdmin || featured == null) {
        	featured = Boolean.FALSE;
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }
        
        if (bootable == null) {
        	bootable = Boolean.TRUE;
        }

        //removing support for file:// type urls (bug: 4239)
        if(url.toLowerCase().contains("file://")){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "File:// type urls are currently unsupported");
        }
        
        return createTemplateOrIso(userId, accountId, zoneId, name, displayText, isPublic.booleanValue(), featured.booleanValue(), ImageFormat.ISO.toString(), null, url, null, true, 64 /*bits*/, false, guestOSId, bootable, HypervisorType.None);
    }

    @Override
    public VMTemplateVO registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException{
    	
        Account ctxAccount = UserContext.current().getAccount();
        Long userId = UserContext.current().getUserId();
        String name = cmd.getTemplateName();
        String displayText = cmd.getDisplayText(); 
        Integer bits = cmd.getBits();
        Boolean passwordEnabled = cmd.isPasswordEnabled();
        Boolean requiresHVM = cmd.getRequiresHvm();
        String url = cmd.getUrl();
        Boolean isPublic = cmd.isPublic();
        Boolean featured = cmd.isFeatured();
        String format = cmd.getFormat();
        Long guestOSId = cmd.getOsTypeId();
        Long zoneId = cmd.getZoneId();
        HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account resourceAccount = null;
        Long accountId = null;

        //parameters verification
        if (bits == null) {
            bits = Integer.valueOf(64);
        }
        if (passwordEnabled == null) {
            passwordEnabled = false;
        }
        if (requiresHVM == null) {
            requiresHVM = true;
        }
        if (isPublic == null) {
            isPublic = Boolean.FALSE;
        }
        
        if (zoneId.longValue() == -1) {
        	zoneId = null;
        }
        
        if ( (accountName == null) ^ (domainId == null) ){// XOR - Both have to be passed or don't pass any of them 
        	throw new InvalidParameterValueException("Please specify both account and domainId or dont specify any of them");
        }
        
        // This complex logic is just for figuring out the template owning account because a user can register templates on other account's behalf.
{'fraction_non_alphanumeric': 0.10028618646458946, 'fraction_numerical': 0.0021766294489902857, 'mean_word_length': 3.2621542690259404, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5559382', 'n_tokens_mistral': 6935, 'n_tokens_neox': 7151, 'n_words': 1701}