mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1771 lines
		
	
	
		
			76 KiB
		
	
	
	
		
			Java
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1771 lines
		
	
	
		
			76 KiB
		
	
	
	
		
			Java
		
	
	
		
			Executable File
		
	
	
	
	
| /**
 | |
|  *  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.user;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.HashMap;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.concurrent.Executors;
 | |
| import java.util.concurrent.ScheduledExecutorService;
 | |
| import java.util.concurrent.TimeUnit;
 | |
| 
 | |
| import javax.ejb.Local;
 | |
| import javax.naming.ConfigurationException;
 | |
| 
 | |
| import org.apache.log4j.Logger;
 | |
| 
 | |
| import com.cloud.acl.ControlledEntity;
 | |
| import com.cloud.acl.SecurityChecker;
 | |
| import com.cloud.api.commands.CreateAccountCmd;
 | |
| import com.cloud.api.commands.CreateUserCmd;
 | |
| import com.cloud.api.commands.DeleteAccountCmd;
 | |
| import com.cloud.api.commands.DeleteUserCmd;
 | |
| import com.cloud.api.commands.DisableAccountCmd;
 | |
| import com.cloud.api.commands.DisableUserCmd;
 | |
| import com.cloud.api.commands.EnableAccountCmd;
 | |
| import com.cloud.api.commands.EnableUserCmd;
 | |
| import com.cloud.api.commands.ListResourceLimitsCmd;
 | |
| import com.cloud.api.commands.LockUserCmd;
 | |
| import com.cloud.api.commands.UpdateAccountCmd;
 | |
| import com.cloud.api.commands.UpdateResourceLimitCmd;
 | |
| import com.cloud.api.commands.UpdateUserCmd;
 | |
| import com.cloud.configuration.Config;
 | |
| import com.cloud.configuration.ConfigurationManager;
 | |
| import com.cloud.configuration.ResourceCount.ResourceType;
 | |
| import com.cloud.configuration.ResourceLimitVO;
 | |
| import com.cloud.configuration.dao.ConfigurationDao;
 | |
| import com.cloud.configuration.dao.ResourceCountDao;
 | |
| import com.cloud.configuration.dao.ResourceLimitDao;
 | |
| import com.cloud.dc.DataCenterVO;
 | |
| import com.cloud.dc.dao.DataCenterDao;
 | |
| import com.cloud.domain.Domain;
 | |
| import com.cloud.domain.DomainVO;
 | |
| import com.cloud.domain.dao.DomainDao;
 | |
| import com.cloud.event.ActionEvent;
 | |
| import com.cloud.event.EventTypes;
 | |
| import com.cloud.event.UsageEventVO;
 | |
| import com.cloud.event.dao.UsageEventDao;
 | |
| import com.cloud.exception.AgentUnavailableException;
 | |
| import com.cloud.exception.ConcurrentOperationException;
 | |
| import com.cloud.exception.InvalidParameterValueException;
 | |
| import com.cloud.exception.OperationTimedoutException;
 | |
| import com.cloud.exception.PermissionDeniedException;
 | |
| import com.cloud.exception.ResourceUnavailableException;
 | |
| import com.cloud.network.NetworkManager;
 | |
| import com.cloud.network.NetworkVO;
 | |
| import com.cloud.network.RemoteAccessVpnVO;
 | |
| import com.cloud.network.VpnUserVO;
 | |
| import com.cloud.network.dao.NetworkDao;
 | |
| import com.cloud.network.dao.RemoteAccessVpnDao;
 | |
| import com.cloud.network.dao.VpnUserDao;
 | |
| import com.cloud.network.security.SecurityGroupManager;
 | |
| import com.cloud.network.security.dao.SecurityGroupDao;
 | |
| import com.cloud.network.vpn.RemoteAccessVpnService;
 | |
| import com.cloud.server.Criteria;
 | |
| import com.cloud.storage.StorageManager;
 | |
| import com.cloud.storage.VMTemplateVO;
 | |
| import com.cloud.storage.Volume;
 | |
| import com.cloud.storage.VolumeVO;
 | |
| import com.cloud.storage.dao.VMTemplateDao;
 | |
| import com.cloud.storage.dao.VolumeDao;
 | |
| import com.cloud.storage.snapshot.SnapshotManager;
 | |
| import com.cloud.template.TemplateManager;
 | |
| import com.cloud.user.Account.State;
 | |
| import com.cloud.user.dao.AccountDao;
 | |
| import com.cloud.user.dao.UserAccountDao;
 | |
| import com.cloud.user.dao.UserDao;
 | |
| import com.cloud.utils.NumbersUtil;
 | |
| import com.cloud.utils.Pair;
 | |
| import com.cloud.utils.component.Adapters;
 | |
| import com.cloud.utils.component.ComponentLocator;
 | |
| import com.cloud.utils.component.Inject;
 | |
| import com.cloud.utils.component.Manager;
 | |
| import com.cloud.utils.concurrency.NamedThreadFactory;
 | |
| import com.cloud.utils.db.Filter;
 | |
| import com.cloud.utils.db.GlobalLock;
 | |
| 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.InstanceGroupVO;
 | |
| import com.cloud.vm.ReservationContext;
 | |
| import com.cloud.vm.ReservationContextImpl;
 | |
| import com.cloud.vm.UserVmManager;
 | |
| import com.cloud.vm.UserVmVO;
 | |
| import com.cloud.vm.VMInstanceVO;
 | |
| import com.cloud.vm.VirtualMachineManager;
 | |
| import com.cloud.vm.dao.InstanceGroupDao;
 | |
| import com.cloud.vm.dao.UserVmDao;
 | |
| import com.cloud.vm.dao.VMInstanceDao;
 | |
| 
 | |
| @Local(value = { AccountManager.class, AccountService.class })
 | |
| public class AccountManagerImpl implements AccountManager, AccountService, Manager {
 | |
|     public static final Logger s_logger = Logger.getLogger(AccountManagerImpl.class);
 | |
| 
 | |
|     private String _name;
 | |
|     @Inject
 | |
|     private AccountDao _accountDao;
 | |
|     @Inject
 | |
|     ConfigurationDao _configDao;
 | |
|     @Inject
 | |
|     private DomainDao _domainDao;
 | |
|     @Inject
 | |
|     private ResourceLimitDao _resourceLimitDao;
 | |
|     @Inject
 | |
|     private ResourceCountDao _resourceCountDao;
 | |
|     @Inject
 | |
|     private UserDao _userDao;
 | |
|     @Inject
 | |
|     private InstanceGroupDao _vmGroupDao;
 | |
|     @Inject
 | |
|     private UserAccountDao _userAccountDao;
 | |
|     @Inject
 | |
|     private VolumeDao _volumeDao;
 | |
|     @Inject
 | |
|     private UserVmDao _userVmDao;
 | |
|     @Inject
 | |
|     private VMTemplateDao _templateDao;
 | |
|     @Inject
 | |
|     private NetworkDao _networkDao;
 | |
|     @Inject
 | |
|     private SecurityGroupDao _securityGroupDao;
 | |
|     @Inject
 | |
|     private VMInstanceDao _vmDao;
 | |
| 
 | |
|     @Inject
 | |
|     private SecurityGroupManager _networkGroupMgr;
 | |
|     @Inject
 | |
|     private NetworkManager _networkMgr;
 | |
|     @Inject
 | |
|     private SnapshotManager _snapMgr;
 | |
|     @Inject
 | |
|     private UserVmManager _vmMgr;
 | |
|     @Inject
 | |
|     private StorageManager _storageMgr;
 | |
|     @Inject
 | |
|     private TemplateManager _tmpltMgr;
 | |
|     @Inject
 | |
|     private ConfigurationManager _configMgr;
 | |
|     @Inject
 | |
|     private VirtualMachineManager _itMgr;
 | |
|     @Inject
 | |
|     private UsageEventDao _usageEventDao;
 | |
|     @Inject
 | |
|     private RemoteAccessVpnDao _remoteAccessVpnDao;
 | |
|     @Inject
 | |
|     private RemoteAccessVpnService _remoteAccessVpnMgr;
 | |
|     @Inject
 | |
|     private VpnUserDao _vpnUser;
 | |
|     @Inject
 | |
|     private DataCenterDao _dcDao;
 | |
| 
 | |
|     private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
 | |
| 
 | |
|     private final GlobalLock m_resourceCountLock = GlobalLock.getInternLock("resource.count");
 | |
| 
 | |
|     UserVO _systemUser;
 | |
|     AccountVO _systemAccount;
 | |
|     @Inject(adapter = SecurityChecker.class)
 | |
|     Adapters<SecurityChecker> _securityCheckers;
 | |
|     int _cleanupInterval;
 | |
| 
 | |
|     @Override
 | |
|     public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
 | |
|         _name = name;
 | |
| 
 | |
|         _systemAccount = _accountDao.findById(AccountVO.ACCOUNT_ID_SYSTEM);
 | |
|         if (_systemAccount == null) {
 | |
|             throw new ConfigurationException("Unable to find the system account using " + Account.ACCOUNT_ID_SYSTEM);
 | |
|         }
 | |
| 
 | |
|         _systemUser = _userDao.findById(UserVO.UID_SYSTEM);
 | |
|         if (_systemUser == null) {
 | |
|             throw new ConfigurationException("Unable to find the system user using " + User.UID_SYSTEM);
 | |
|         }
 | |
| 
 | |
|         ComponentLocator locator = ComponentLocator.getCurrentLocator();
 | |
|         ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
 | |
|         Map<String, String> configs = configDao.getConfiguration(params);
 | |
| 
 | |
|         String value = configs.get(Config.AccountCleanupInterval.key());
 | |
|         _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public UserVO getSystemUser() {
 | |
|         return _systemUser;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public String getName() {
 | |
|         return _name;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean start() {
 | |
|         _executor.scheduleAtFixedRate(new AccountCleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean stop() {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void incrementResourceCount(long accountId, ResourceType type, Long... delta) {
 | |
|         long numToIncrement = (delta.length == 0) ? 1 : delta[0].longValue();
 | |
| 
 | |
|         if (m_resourceCountLock.lock(120)) { // 2 minutes
 | |
|             try {
 | |
|                 _resourceCountDao.updateAccountCount(accountId, type, true, numToIncrement);
 | |
| 
 | |
|                 // on a per-domain basis, increment the count
 | |
|                 // FIXME: can this increment be done on the database side in a custom update statement?
 | |
|                 Account account = _accountDao.findByIdIncludingRemoved(accountId);
 | |
|                 Long domainId = account.getDomainId();
 | |
|                 while (domainId != null) {
 | |
|                     _resourceCountDao.updateDomainCount(domainId, type, true, numToIncrement);
 | |
|                     DomainVO domain = _domainDao.findById(domainId);
 | |
|                     domainId = domain.getParent();
 | |
|                 }
 | |
|             } finally {
 | |
|                 m_resourceCountLock.unlock();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void decrementResourceCount(long accountId, ResourceType type, Long... delta) {
 | |
|         long numToDecrement = (delta.length == 0) ? 1 : delta[0].longValue();
 | |
| 
 | |
|         if (m_resourceCountLock.lock(120)) { // 2 minutes
 | |
|             try {
 | |
|                 assert ((_resourceCountDao.getAccountCount(accountId, type) - numToDecrement) >= 0) : "Resource counts can not be negative. Check where we skipped increment.";
 | |
|                 _resourceCountDao.updateAccountCount(accountId, type, false, numToDecrement);
 | |
| 
 | |
|                 // on a per-domain basis, decrement the count
 | |
|                 // FIXME: can this decrement be done on the database side in a custom update statement?
 | |
|                 Account account = _accountDao.findByIdIncludingRemoved(accountId); // find all accounts, even removed accounts
 | |
|                                                                                    // if this happens to be for an account
 | |
|                                                                                    // that's being deleted
 | |
|                 Long domainId = account.getDomainId();
 | |
|                 while (domainId != null) {
 | |
|                     assert ((_resourceCountDao.getDomainCount(domainId, type) - numToDecrement) >= 0) : "Resource counts can not be negative. Check where we skipped increment.";
 | |
|                     _resourceCountDao.updateDomainCount(domainId, type, false, numToDecrement);
 | |
|                     DomainVO domain = _domainDao.findByIdIncludingRemoved(domainId);
 | |
|                     domainId = domain.getParent();
 | |
|                 }
 | |
|             } finally {
 | |
|                 m_resourceCountLock.unlock();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public long findCorrectResourceLimit(AccountVO account, ResourceType type) {
 | |
|         long max = -1;
 | |
| 
 | |
|         ResourceLimitVO limit = _resourceLimitDao.findByAccountIdAndType(account.getId(), type);
 | |
| 
 | |
|         // Check if limit is configured for account
 | |
|         if (limit != null) {
 | |
|             max = limit.getMax().longValue();
 | |
|         } else {
 | |
|             // If the account has an no limit set, then return global default account limits
 | |
|             try {
 | |
|                 switch (type) {
 | |
|                 case public_ip:
 | |
|                     max = Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountPublicIPs.key()));
 | |
|                     break;
 | |
|                 case snapshot:
 | |
|                     max = Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountSnapshots.key()));
 | |
|                     break;
 | |
|                 case template:
 | |
|                     max = Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountTemplates.key()));
 | |
|                     break;
 | |
|                 case user_vm:
 | |
|                     max = Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountUserVms.key()));
 | |
|                     break;
 | |
|                 case volume:
 | |
|                     max = Long.parseLong(_configDao.getValue(Config.DefaultMaxAccountVolumes.key()));
 | |
|                     break;
 | |
|                 }
 | |
|             } catch (NumberFormatException nfe) {
 | |
|                 s_logger.error("Invalid value is set for the default account limit.");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return max;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public long findCorrectResourceLimit(DomainVO domain, ResourceType type) {
 | |
|         long max = -1;
 | |
| 
 | |
|         // Check account
 | |
|         ResourceLimitVO limit = _resourceLimitDao.findByDomainIdAndType(domain.getId(), type);
 | |
| 
 | |
|         if (limit != null) {
 | |
|             max = limit.getMax().longValue();
 | |
|         } else {
 | |
|             // check domain hierarchy
 | |
|             Long domainId = domain.getParent();
 | |
|             while ((domainId != null) && (limit == null)) {
 | |
|                 limit = _resourceLimitDao.findByDomainIdAndType(domainId, type);
 | |
|                 DomainVO tmpDomain = _domainDao.findById(domainId);
 | |
|                 domainId = tmpDomain.getParent();
 | |
|             }
 | |
| 
 | |
|             if (limit != null) {
 | |
|                 max = limit.getMax().longValue();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return max;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean resourceLimitExceeded(Account account, ResourceType type, long... count) {
 | |
|         long numResources = ((count.length == 0) ? 1 : count[0]);
 | |
| 
 | |
|         // Don't place any limits on system or admin accounts
 | |
|         long accountType = account.getType();
 | |
|         if (accountType == Account.ACCOUNT_TYPE_ADMIN || accountType == Account.ACCOUNT_ID_SYSTEM) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         if (m_resourceCountLock.lock(120)) { // 2 minutes
 | |
|             try {
 | |
|                 // Check account limits
 | |
|                 AccountVO accountVo = _accountDao.findById(account.getAccountId());
 | |
|                 long accountLimit = findCorrectResourceLimit(accountVo, type);
 | |
|                 long potentialCount = _resourceCountDao.getAccountCount(account.getId(), type) + numResources;
 | |
|                 if (potentialCount > accountLimit) {
 | |
|                     return true;
 | |
|                 }
 | |
| 
 | |
|                 // check all domains in the account's domain hierarchy
 | |
|                 Long domainId = account.getDomainId();
 | |
|                 while (domainId != null) {
 | |
|                     ResourceLimitVO domainLimit = _resourceLimitDao.findByDomainIdAndType(domainId, type);
 | |
|                     if (domainLimit != null) {
 | |
|                         long domainCount = _resourceCountDao.getDomainCount(domainId, type);
 | |
|                         if ((domainCount + numResources) > domainLimit.getMax().longValue()) {
 | |
|                             return true;
 | |
|                         }
 | |
|                     }
 | |
|                     DomainVO domain = _domainDao.findById(domainId);
 | |
|                     domainId = domain.getParent();
 | |
|                 }
 | |
|             } finally {
 | |
|                 m_resourceCountLock.unlock();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public long getResourceCount(AccountVO account, ResourceType type) {
 | |
|         return _resourceCountDao.getAccountCount(account.getId(), type);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public List<ResourceLimitVO> searchForLimits(Criteria c) {
 | |
|         Long id = (Long) c.getCriteria(Criteria.ID);
 | |
|         Long domainId = (Long) c.getCriteria(Criteria.DOMAINID);
 | |
|         Long accountId = (Long) c.getCriteria(Criteria.ACCOUNTID);
 | |
|         ResourceType type = (ResourceType) c.getCriteria(Criteria.TYPE);
 | |
| 
 | |
|         // For 2.0, we are just limiting the scope to having an user retrieve
 | |
|         // limits for himself and if limits don't exist, use the ROOT domain's limits.
 | |
|         // - Will
 | |
|         List<ResourceLimitVO> limits = new ArrayList<ResourceLimitVO>();
 | |
| 
 | |
|         if ((accountId != null) && (domainId != null)) {
 | |
|             // if domainId==ROOT_DOMAIN and account belongs to admin
 | |
|             // return all records for resource limits (bug 3778)
 | |
| 
 | |
|             if (domainId == DomainVO.ROOT_DOMAIN) {
 | |
|                 AccountVO account = _accountDao.findById(accountId);
 | |
| 
 | |
|                 if ((account != null) && (account.getType() == 1)) {
 | |
|                     // account belongs to admin return all limits
 | |
|                     limits = _resourceLimitDao.listAll();
 | |
|                     return limits;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (accountId != null) {
 | |
|             SearchBuilder<ResourceLimitVO> sb = _resourceLimitDao.createSearchBuilder();
 | |
|             sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
 | |
|             sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
 | |
|             sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
 | |
| 
 | |
|             SearchCriteria<ResourceLimitVO> sc = sb.create();
 | |
| 
 | |
|             if (accountId != null) {
 | |
|                 sc.setParameters("accountId", accountId);
 | |
|             }
 | |
| 
 | |
|             if (type != null) {
 | |
|                 sc.setParameters("type", type);
 | |
|             }
 | |
| 
 | |
|             if (id != null) {
 | |
|                 sc.setParameters("id", id);
 | |
|             }
 | |
| 
 | |
|             // Listing all limits for an account
 | |
|             if (type == null) {
 | |
|                 // List<ResourceLimitVO> userLimits = _resourceLimitDao.search(sc, searchFilter);
 | |
|                 List<ResourceLimitVO> userLimits = _resourceLimitDao.listByAccountId(accountId);
 | |
|                 List<ResourceLimitVO> rootLimits = _resourceLimitDao.listByDomainId(DomainVO.ROOT_DOMAIN);
 | |
|                 ResourceType resourceTypes[] = ResourceType.values();
 | |
| 
 | |
|                 for (ResourceType resourceType : resourceTypes) {
 | |
|                     boolean found = false;
 | |
|                     for (ResourceLimitVO userLimit : userLimits) {
 | |
|                         if (userLimit.getType() == resourceType) {
 | |
|                             limits.add(userLimit);
 | |
|                             found = true;
 | |
|                             break;
 | |
|                         }
 | |
|                     }
 | |
|                     if (!found) {
 | |
|                         // Check the ROOT domain
 | |
|                         for (ResourceLimitVO rootLimit : rootLimits) {
 | |
|                             if (rootLimit.getType() == resourceType) {
 | |
|                                 limits.add(rootLimit);
 | |
|                                 found = true;
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     if (!found) {
 | |
|                         limits.add(new ResourceLimitVO(domainId, accountId, resourceType, -1L));
 | |
|                     }
 | |
|                 }
 | |
|             } else {
 | |
|                 AccountVO account = _accountDao.findById(accountId);
 | |
|                 limits.add(new ResourceLimitVO(null, accountId, type, findCorrectResourceLimit(account, type)));
 | |
|             }
 | |
|         } else if (domainId != null) {
 | |
|             if (type == null) {
 | |
|                 ResourceType resourceTypes[] = ResourceType.values();
 | |
|                 List<ResourceLimitVO> domainLimits = _resourceLimitDao.listByDomainId(domainId);
 | |
|                 for (ResourceType resourceType : resourceTypes) {
 | |
|                     boolean found = false;
 | |
|                     for (ResourceLimitVO domainLimit : domainLimits) {
 | |
|                         if (domainLimit.getType() == resourceType) {
 | |
|                             limits.add(domainLimit);
 | |
|                             found = true;
 | |
|                             break;
 | |
|                         }
 | |
|                     }
 | |
|                     if (!found) {
 | |
|                         limits.add(new ResourceLimitVO(domainId, null, resourceType, -1L));
 | |
|                     }
 | |
|                 }
 | |
|             } else {
 | |
|                 limits.add(_resourceLimitDao.findByDomainIdAndType(domainId, type));
 | |
|             }
 | |
|         }
 | |
|         return limits;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public List<ResourceLimitVO> searchForLimits(ListResourceLimitsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         Long accountId = null;
 | |
|         Account account = UserContext.current().getCaller();
 | |
| 
 | |
|         if ((account == null) || isAdmin(account.getType())) {
 | |
|             if (accountName != null) {
 | |
|                 // Look up limits for the specified account
 | |
| 
 | |
|                 if (domainId == null) {
 | |
|                     throw new InvalidParameterValueException("Failed to list limits for account " + accountName + " no domain id specified.");
 | |
|                 }
 | |
| 
 | |
|                 Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
 | |
| 
 | |
|                 if (userAccount == null) {
 | |
|                     throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
 | |
|                 } else if (account != null
 | |
|                         && (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || account.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN || account.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
 | |
|                     // If this is a non-root admin, make sure that the admin and the user account belong in the same domain or
 | |
|                     // that the user account's domain is a child domain of the parent
 | |
|                     if (account.getDomainId() != userAccount.getDomainId() && !_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
 | |
|                         throw new PermissionDeniedException("You do not have permission to access limits for this account: " + accountName);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 accountId = userAccount.getId();
 | |
|                 domainId = null;
 | |
|             } else if (domainId != null) {
 | |
|                 // Look up limits for the specified domain
 | |
|                 accountId = null;
 | |
|             } else if (account == null) {
 | |
|                 // Look up limits for the ROOT domain
 | |
|                 domainId = DomainVO.ROOT_DOMAIN;
 | |
|             } else {
 | |
|                 // Look up limits for the admin's account
 | |
|                 accountId = account.getId();
 | |
|                 domainId = null;
 | |
|             }
 | |
|         } else {
 | |
|             // Look up limits for the user's account
 | |
|             accountId = account.getId();
 | |
|             domainId = null;
 | |
|         }
 | |
| 
 | |
|         // Map resource type
 | |
|         ResourceType resourceType = null;
 | |
|         Integer type = cmd.getResourceType();
 | |
|         try {
 | |
|             if (type != null) {
 | |
|                 resourceType = ResourceType.values()[type];
 | |
|             }
 | |
|         } catch (ArrayIndexOutOfBoundsException e) {
 | |
|             throw new InvalidParameterValueException("Invalid resource type " + type + " given.  Please specify a valid resource type.");
 | |
|         }
 | |
| 
 | |
|         Criteria c = new Criteria("id", Boolean.FALSE, cmd.getStartIndex(), cmd.getPageSizeVal());
 | |
|         c.addCriteria(Criteria.ID, cmd.getId());
 | |
|         c.addCriteria(Criteria.DOMAINID, domainId);
 | |
|         c.addCriteria(Criteria.ACCOUNTID, accountId);
 | |
|         c.addCriteria(Criteria.TYPE, resourceType);
 | |
|         return searchForLimits(c);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public ResourceLimitVO updateResourceLimit(UpdateResourceLimitCmd cmd) {
 | |
|         Account account = UserContext.current().getCaller();
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         Long max = cmd.getMax();
 | |
|         Integer type = cmd.getResourceType();
 | |
| 
 | |
|         // Validate input
 | |
|         Long accountId = null;
 | |
| 
 | |
|         if (max == null) {
 | |
|             max = new Long(-1);
 | |
|         } else if (max < -1) {
 | |
|             throw new InvalidParameterValueException("Please specify either '-1' for an infinite limit, or a limit that is at least '0'.");
 | |
|         }
 | |
| 
 | |
|         // Map resource type
 | |
|         ResourceType resourceType;
 | |
|         try {
 | |
|             resourceType = ResourceType.values()[type];
 | |
|         } catch (ArrayIndexOutOfBoundsException e) {
 | |
|             throw new InvalidParameterValueException("Please specify a valid resource type.");
 | |
|         }
 | |
| 
 | |
|         // Either a domainId or an accountId must be passed in, but not both.
 | |
|         if ((domainId == null) && (accountName == null)) {
 | |
|             throw new InvalidParameterValueException("Either a domainId or domainId/account must be passed in.");
 | |
|         }
 | |
| 
 | |
|         if (account != null) {
 | |
|             if (domainId != null) {
 | |
|                 if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
 | |
|                     throw new PermissionDeniedException("Unable to update resource limit for " + ((account.getAccountName() == null) ? "" : "account " + account.getAccountName() + " in ") + "domain "
 | |
|                             + domainId + ", permission denied");
 | |
|                 }
 | |
|             } else if (account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
 | |
|                 domainId = DomainVO.ROOT_DOMAIN; // for root admin, default to root domain if domain is not specified
 | |
|             }
 | |
| 
 | |
|             if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
 | |
|                 if ((domainId != null) && (accountName == null) && domainId.equals(account.getDomainId())) {
 | |
|                     // if the admin is trying to update their own domain, disallow...
 | |
|                     throw new PermissionDeniedException("Unable to update resource limit for domain " + domainId + ", permission denied");
 | |
|                 }
 | |
| 
 | |
|                 // If there is an existing ROOT domain limit, make sure its max isn't being exceeded
 | |
|                 Criteria c = new Criteria();
 | |
|                 c.addCriteria(Criteria.DOMAINID, DomainVO.ROOT_DOMAIN);
 | |
|                 c.addCriteria(Criteria.TYPE, resourceType);
 | |
|                 List<ResourceLimitVO> currentRootDomainLimits = searchForLimits(c);
 | |
|                 ResourceLimitVO currentRootDomainLimit = (currentRootDomainLimits.size() == 0) ? null : currentRootDomainLimits.get(0);
 | |
|                 if (currentRootDomainLimit != null) {
 | |
|                     long currentRootDomainMax = currentRootDomainLimits.get(0).getMax();
 | |
|                     if ((max == -1 && currentRootDomainMax != -1) || max > currentRootDomainMax) {
 | |
|                         throw new InvalidParameterValueException("The current ROOT domain limit for resource type " + resourceType + " is " + currentRootDomainMax + " and cannot be exceeded.");
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (accountName != null) {
 | |
|             if (domainId == null) {
 | |
|                 throw new InvalidParameterValueException("domainId parameter is required if account is specified");
 | |
|             }
 | |
|             Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
 | |
|             if (userAccount == null) {
 | |
|                 throw new InvalidParameterValueException("unable to find account by name " + account.getAccountName() + " in domain with id " + domainId);
 | |
|             }
 | |
|             accountId = userAccount.getId();
 | |
|         }
 | |
| 
 | |
|         if (accountId != null) {
 | |
|             domainId = null;
 | |
|         }
 | |
| 
 | |
|         // Check if the domain or account exists and is valid
 | |
|         if (accountId != null) {
 | |
|             AccountVO accountHandle = _accountDao.findById(accountId);
 | |
|             if (accountHandle == null) {
 | |
|                 throw new InvalidParameterValueException("Please specify a valid account ID.");
 | |
|             } else if (accountHandle.getRemoved() != null) {
 | |
|                 throw new InvalidParameterValueException("Please specify an active account.");
 | |
|             } else if (accountHandle.getType() == Account.ACCOUNT_TYPE_ADMIN || accountHandle.getType() == Account.ACCOUNT_ID_SYSTEM) {
 | |
|                 throw new InvalidParameterValueException("Please specify a non-admin account.");
 | |
|             }
 | |
| 
 | |
|             DomainVO domain = _domainDao.findById(accountHandle.getDomainId());
 | |
|             long parentMaximum = findCorrectResourceLimit(domain, resourceType);
 | |
|             if ((parentMaximum >= 0) && ((max.longValue() == -1) || (max.longValue() > parentMaximum))) {
 | |
|                 throw new InvalidParameterValueException("Account " + account.getAccountName() + "(id: " + accountId + ") has maximum allowed resource limit " + parentMaximum + " for " + type
 | |
|                         + ", please specify a value less that or equal to " + parentMaximum);
 | |
|             }
 | |
|         } else if (domainId != null) {
 | |
|             DomainVO domain = _domainDao.findById(domainId);
 | |
|             if (domain == null) {
 | |
|                 throw new InvalidParameterValueException("Please specify a valid domain ID.");
 | |
|             } else if (domain.getRemoved() != null) {
 | |
|                 throw new InvalidParameterValueException("Please specify an active domain.");
 | |
|             }
 | |
| 
 | |
|             Long parentDomainId = domain.getParent();
 | |
|             if (parentDomainId != null) {
 | |
|                 DomainVO parentDomain = _domainDao.findById(parentDomainId);
 | |
|                 long parentMaximum = findCorrectResourceLimit(parentDomain, resourceType);
 | |
|                 if ((parentMaximum >= 0) && (max.longValue() > parentMaximum)) {
 | |
|                     throw new InvalidParameterValueException("Domain " + domain.getName() + "(id: " + domainId + ") has maximum allowed resource limit " + parentMaximum + " for " + type
 | |
|                             + ", please specify a value less that or equal to " + parentMaximum);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // A valid limit type must be passed in
 | |
|         if (resourceType == null) {
 | |
|             throw new InvalidParameterValueException("A valid limit type must be passed in.");
 | |
|         }
 | |
| 
 | |
|         // Check if a limit with the specified domainId/accountId/type combo already exists
 | |
|         Filter searchFilter = new Filter(ResourceLimitVO.class, null, false, null, null);
 | |
|         SearchCriteria<ResourceLimitVO> sc = _resourceLimitDao.createSearchCriteria();
 | |
| 
 | |
|         if (domainId != null) {
 | |
|             sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
 | |
|         }
 | |
| 
 | |
|         if (accountId != null) {
 | |
|             sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
 | |
|         }
 | |
| 
 | |
|         if (resourceType != null) {
 | |
|             sc.addAnd("type", SearchCriteria.Op.EQ, resourceType);
 | |
|         }
 | |
| 
 | |
|         List<ResourceLimitVO> limits = _resourceLimitDao.search(sc, searchFilter);
 | |
|         if (limits.size() == 1) {
 | |
|             ResourceLimitVO limit = limits.get(0);
 | |
|             // if limit is set to -1, remove the record
 | |
|             if (max != null && max.longValue() == -1L) {
 | |
|                 // this parameter is needed by API as it expects the object to be returned and updates the UI with the object's
 | |
|                 // new "max" parameter
 | |
|                 ResourceLimitVO limitToReturn = limit;
 | |
|                 limitToReturn.setMax(-1L);
 | |
|                 _resourceLimitDao.remove(limit.getId());
 | |
|                 return limitToReturn;
 | |
|             } else {
 | |
|                 // Update the existing limit
 | |
|                 _resourceLimitDao.update(limit.getId(), max);
 | |
|                 return _resourceLimitDao.findById(limit.getId());
 | |
|             }
 | |
|         } else {
 | |
|             // Persist the new Limit
 | |
|             return _resourceLimitDao.persist(new ResourceLimitVO(domainId, accountId, resourceType, max));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public AccountVO getSystemAccount() {
 | |
|         if (_systemAccount == null) {
 | |
|             _systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM);
 | |
|         }
 | |
|         return _systemAccount;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean isAdmin(short accountType) {
 | |
|         return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean isRootAdmin(short accountType) {
 | |
|         return (accountType == Account.ACCOUNT_TYPE_ADMIN);
 | |
|     }
 | |
| 
 | |
|     public boolean isResourceDomainAdmin(short accountType) {
 | |
|         return (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void checkAccess(Account caller, Domain domain) throws PermissionDeniedException {
 | |
|         for (SecurityChecker checker : _securityCheckers) {
 | |
|             if (checker.checkAccess(caller, domain)) {
 | |
|                 if (s_logger.isDebugEnabled()) {
 | |
|                     s_logger.debug("Access granted to " + caller + " to " + domain + " by " + checker.getName());
 | |
|                 }
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         assert false : "How can all of the security checkers pass on checking this caller?";
 | |
|         throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + domain);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void checkAccess(Account caller, ControlledEntity... entities) {
 | |
|         HashMap<Long, List<ControlledEntity>> domains = new HashMap<Long, List<ControlledEntity>>();
 | |
| 
 | |
|         for (ControlledEntity entity : entities) {
 | |
|             if (entity.getAccountId() != -1 && entity.getDomainId() != -1) {
 | |
|                 List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
 | |
|                 if (toBeChecked == null) {
 | |
|                     toBeChecked = new ArrayList<ControlledEntity>();
 | |
|                     domains.put(entity.getDomainId(), toBeChecked);
 | |
|                 }
 | |
|                 toBeChecked.add(entity);
 | |
|             }
 | |
|             boolean granted = false;
 | |
|             for (SecurityChecker checker : _securityCheckers) {
 | |
|                 if (checker.checkAccess(caller, entity)) {
 | |
|                     if (s_logger.isDebugEnabled()) {
 | |
|                         s_logger.debug("Access to " + entity + " granted to " + caller + " by " + checker.getName());
 | |
|                     }
 | |
|                     granted = true;
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!granted) {
 | |
|                 assert false : "How can all of the security checkers pass on checking this check: " + entity;
 | |
|                 throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         for (Map.Entry<Long, List<ControlledEntity>> domain : domains.entrySet()) {
 | |
|             for (SecurityChecker checker : _securityCheckers) {
 | |
|                 Domain d = _domainDao.findById(domain.getKey());
 | |
|                 if (d == null || d.getRemoved() != null) {
 | |
|                     throw new PermissionDeniedException("Domain is not found.", caller, domain.getValue());
 | |
|                 }
 | |
|                 try {
 | |
|                     checker.checkAccess(caller, d);
 | |
|                 } catch (PermissionDeniedException e) {
 | |
|                     e.addDetails(caller, domain.getValue());
 | |
|                     throw e;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) {
 | |
|         // We just care for resource domain admin for now. He should be permitted to see only his zone.
 | |
|         if (isResourceDomainAdmin(caller.getType())) {
 | |
|             if (zoneId == null)
 | |
|                 return getZoneIdForAccount(caller);
 | |
|             else if (getZoneIdForAccount(caller) != zoneId)
 | |
|                 throw new PermissionDeniedException("Caller " + caller + "is not allowed to access the zone " + zoneId);
 | |
|             else
 | |
|                 return zoneId;
 | |
|         }
 | |
| 
 | |
|         else
 | |
|             return zoneId;
 | |
|     }
 | |
| 
 | |
|     private Long getZoneIdForAccount(Account account) {
 | |
| 
 | |
|         // Currently just for resource domain admin
 | |
|         List<DataCenterVO> dcList = _dcDao.findZonesByDomainId(account.getDomainId());
 | |
|         if (dcList != null && dcList.size() != 0)
 | |
|             return dcList.get(0).getId();
 | |
|         else
 | |
|             throw new CloudRuntimeException("Failed to find any private zone for Resource domain admin.");
 | |
| 
 | |
|     }
 | |
| 
 | |
|     private boolean doSetUserStatus(long userId, State state) {
 | |
|         UserVO userForUpdate = _userDao.createForUpdate();
 | |
|         userForUpdate.setState(state);
 | |
|         return _userDao.update(Long.valueOf(userId), userForUpdate);
 | |
|     }
 | |
| 
 | |
|     public boolean enableAccount(long accountId) {
 | |
|         boolean success = false;
 | |
|         AccountVO acctForUpdate = _accountDao.createForUpdate();
 | |
|         acctForUpdate.setState(State.enabled);
 | |
|         success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
 | |
|         return success;
 | |
|     }
 | |
| 
 | |
|     private boolean lockAccountInternal(long accountId) {
 | |
|         boolean success = false;
 | |
|         Account account = _accountDao.findById(accountId);
 | |
|         if (account != null) {
 | |
|             if (account.getState().equals(State.locked)) {
 | |
|                 return true; // already locked, no-op
 | |
|             } else if (account.getState().equals(State.enabled)) {
 | |
|                 AccountVO acctForUpdate = _accountDao.createForUpdate();
 | |
|                 acctForUpdate.setState(State.locked);
 | |
|                 success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
 | |
|             } else {
 | |
|                 if (s_logger.isInfoEnabled()) {
 | |
|                     s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             s_logger.warn("Failed to lock account " + accountId + ", account not found.");
 | |
|         }
 | |
|         return success;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean deleteAccount(AccountVO account, long callerUserId, Account caller) {
 | |
|         long accountId = account.getId();
 | |
| 
 | |
|         if (!_accountDao.remove(accountId)) {
 | |
|             s_logger.error("Unable to delete account " + accountId);
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         List<UserVO> users = _userDao.listByAccount(accountId);
 | |
| 
 | |
|         for (UserVO user : users) {
 | |
|             _userDao.remove(user.getId());
 | |
|         }
 | |
| 
 | |
|         if (s_logger.isDebugEnabled()) {
 | |
|             s_logger.debug("Remove account " + accountId);
 | |
|         }
 | |
| 
 | |
|         return cleanupAccount(account, callerUserId, caller);
 | |
| 
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) {
 | |
|         long accountId = account.getId();
 | |
|         boolean accountCleanupNeeded = false;
 | |
| 
 | |
|         try {
 | |
|             // delete all vm groups belonging to accont
 | |
|             List<InstanceGroupVO> groups = _vmGroupDao.listByAccountId(accountId);
 | |
|             for (InstanceGroupVO group : groups) {
 | |
|                 if (!_vmMgr.deleteVmGroup(group.getId())) {
 | |
|                     s_logger.error("Unable to delete group: " + group.getId());
 | |
|                     accountCleanupNeeded = true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
 | |
|             boolean success = _snapMgr.deleteSnapshotDirsForAccount(accountId);
 | |
|             if (success) {
 | |
|                 s_logger.debug("Successfully deleted snapshots directories for all volumes under account " + accountId + " across all zones");
 | |
|             }
 | |
| 
 | |
|             // clean up templates
 | |
|             List<VMTemplateVO> userTemplates = _templateDao.listByAccountId(accountId);
 | |
|             boolean allTemplatesDeleted = true;
 | |
|             for (VMTemplateVO template : userTemplates) {
 | |
|                 try {
 | |
|                     allTemplatesDeleted = _tmpltMgr.delete(callerUserId, template.getId(), null);
 | |
|                 } catch (Exception e) {
 | |
|                     s_logger.warn("Failed to delete template while removing account: " + template.getName() + " due to: ", e);
 | |
|                     allTemplatesDeleted = false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!allTemplatesDeleted) {
 | |
|                 s_logger.warn("Failed to delete templates while removing account id=" + accountId);
 | |
|                 accountCleanupNeeded = true;
 | |
|             }
 | |
| 
 | |
|             // Destroy the account's VMs
 | |
|             List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
 | |
|             if (s_logger.isDebugEnabled()) {
 | |
|                 s_logger.debug("Destroying # of vms (accountId=" + accountId + "): " + vms.size());
 | |
|             }
 | |
| 
 | |
|             for (UserVmVO vm : vms) {
 | |
|                 if (!_vmMgr.expunge(vm, callerUserId, caller)) {
 | |
|                     s_logger.error("Unable to destroy vm: " + vm.getId());
 | |
|                     accountCleanupNeeded = true;
 | |
|                 }
 | |
|                 UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getName(), vm.getServiceOfferingId(),
 | |
|                         vm.getTemplateId(), vm.getHypervisorType().toString());
 | |
|                 _usageEventDao.persist(usageEvent);
 | |
|             }
 | |
| 
 | |
|             // Mark the account's volumes as destroyed
 | |
|             List<VolumeVO> volumes = _volumeDao.findDetachedByAccount(accountId);
 | |
|             for (VolumeVO volume : volumes) {
 | |
|                 if (!volume.getState().equals(Volume.State.Destroy)) {
 | |
|                     try {
 | |
|                         _storageMgr.destroyVolume(volume);
 | |
|                         if (volume.getPoolId() != null) {
 | |
|                             UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName());
 | |
|                             _usageEventDao.persist(usageEvent);
 | |
|                         }
 | |
|                     } catch (ConcurrentOperationException ex) {
 | |
|                         s_logger.warn("Failed to cleanup volumes as a part of account id=" + accountId + " cleanup due to Exception: ", ex);
 | |
|                         accountCleanupNeeded = true;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // delete remote access vpns and associated users
 | |
|             List<RemoteAccessVpnVO> remoteAccessVpns = _remoteAccessVpnDao.findByAccount(accountId);
 | |
|             List<VpnUserVO> vpnUsers = _vpnUser.listByAccount(accountId);
 | |
| 
 | |
|             for (VpnUserVO vpnUser : vpnUsers) {
 | |
|                 _remoteAccessVpnMgr.removeVpnUser(accountId, vpnUser.getUsername());
 | |
|             }
 | |
| 
 | |
|             try {
 | |
|                 for (RemoteAccessVpnVO vpn : remoteAccessVpns) {
 | |
|                     _remoteAccessVpnMgr.destroyRemoteAccessVpn(vpn.getServerAddressId());
 | |
|                 }
 | |
|             } catch (ResourceUnavailableException ex) {
 | |
|                 s_logger.warn("Failed to cleanup remote access vpn resources as a part of account id=" + accountId + " cleanup due to Exception: ", ex);
 | |
|                 accountCleanupNeeded = true;
 | |
|             }
 | |
| 
 | |
|             // Cleanup security groups
 | |
|             int numRemoved = _securityGroupDao.removeByAccountId(accountId);
 | |
|             s_logger.info("deleteAccount: Deleted " + numRemoved + " network groups for account " + accountId);
 | |
| 
 | |
|             // Delete all the networks
 | |
|             boolean networksDeleted = true;
 | |
|             s_logger.debug("Deleting networks for account " + account.getId());
 | |
|             List<NetworkVO> networks = _networkDao.listByOwner(accountId);
 | |
|             if (networks != null) {
 | |
|                 for (NetworkVO network : networks) {
 | |
| 
 | |
|                     ReservationContext context = new ReservationContextImpl(null, null, getActiveUser(callerUserId), account);
 | |
| 
 | |
|                     if (!_networkMgr.destroyNetwork(network.getId(), context)) {
 | |
|                         s_logger.warn("Unable to destroy network " + network + " as a part of account id=" + accountId + " cleanup.");
 | |
|                         accountCleanupNeeded = true;
 | |
|                         networksDeleted = false;
 | |
|                     } else {
 | |
|                         s_logger.debug("Network " + network.getId() + " successfully deleted as a part of account id=" + accountId + " cleanup.");
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // delete account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned up
 | |
|             // successfully
 | |
|             if (networksDeleted) {
 | |
|                 if (!_configMgr.deleteAccountSpecificVirtualRanges(accountId)) {
 | |
|                     accountCleanupNeeded = true;
 | |
|                 } else {
 | |
|                     s_logger.debug("Account specific Virtual IP ranges " + " are successfully deleted as a part of account id=" + accountId + " cleanup.");
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         } finally {
 | |
|             s_logger.info("Cleanup for account " + account.getId() + (accountCleanupNeeded ? " is needed." : " is not needed."));
 | |
|             if (accountCleanupNeeded) {
 | |
|                 _accountDao.markForCleanup(accountId);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean disableAccount(long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         boolean success = false;
 | |
|         if (accountId <= 2) {
 | |
|             if (s_logger.isInfoEnabled()) {
 | |
|                 s_logger.info("disableAccount -- invalid account id: " + accountId);
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         AccountVO account = _accountDao.findById(accountId);
 | |
|         if ((account == null) || account.getState().equals(State.disabled)) {
 | |
|             success = true;
 | |
|         } else {
 | |
|             AccountVO acctForUpdate = _accountDao.createForUpdate();
 | |
|             acctForUpdate.setState(State.disabled);
 | |
|             success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
 | |
| 
 | |
|             success = (success && doDisableAccount(accountId));
 | |
|         }
 | |
|         return success;
 | |
|     }
 | |
| 
 | |
|     private boolean doDisableAccount(long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         List<VMInstanceVO> vms = _vmDao.listByAccountId(accountId);
 | |
|         boolean success = true;
 | |
|         for (VMInstanceVO vm : vms) {
 | |
|             try {
 | |
|                 try {
 | |
|                     success = (success && _itMgr.advanceStop(vm, true, getSystemUser(), getSystemAccount()));
 | |
|                 } catch (OperationTimedoutException ote) {
 | |
|                     s_logger.warn("Operation for stopping vm timed out, unable to stop vm " + vm.getName(), ote);
 | |
|                     success = false;
 | |
|                 }
 | |
|             } catch (AgentUnavailableException aue) {
 | |
|                 s_logger.warn("Agent running on host " + vm.getHostId() + " is unavailable, unable to stop vm " + vm.getName(), aue);
 | |
|                 success = false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return success;
 | |
|     }
 | |
| 
 | |
|     // ///////////////////////////////////////////////////
 | |
|     // ////////////// API commands /////////////////////
 | |
|     // ///////////////////////////////////////////////////
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account")
 | |
|     public UserAccount createAccount(CreateAccountCmd cmd) {
 | |
|         Long accountId = null;
 | |
|         String username = cmd.getUsername();
 | |
|         String password = cmd.getPassword();
 | |
|         String firstName = cmd.getFirstname();
 | |
|         String lastName = cmd.getLastname();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         String email = cmd.getEmail();
 | |
|         String timezone = cmd.getTimezone();
 | |
|         String accountName = cmd.getAccountName();
 | |
|         short userType = cmd.getAccountType().shortValue();
 | |
|         DomainVO domain = _domainDao.findById(domainId);
 | |
|         checkAccess(UserContext.current().getCaller(), domain);
 | |
|         try {
 | |
|             if (accountName == null) {
 | |
|                 accountName = username;
 | |
|             }
 | |
|             if (domainId == null) {
 | |
|                 domainId = DomainVO.ROOT_DOMAIN;
 | |
|             }
 | |
| 
 | |
|             Account account = _accountDao.findActiveAccount(accountName, domainId);
 | |
|             if (account != null) {
 | |
|                 throw new CloudRuntimeException("The specified account: " + account.getAccountName() + " already exists");
 | |
|             }
 | |
| 
 | |
|             if (domain == null) {
 | |
|                 throw new CloudRuntimeException("The domain " + domainId + " does not exist; unable to create account");
 | |
|             } else {
 | |
|                 if (domain.getState().equals(Domain.State.Inactive)) {
 | |
|                     throw new CloudRuntimeException("The account cannot be created as domain " + domain.getName() + " is being deleted");
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!_userAccountDao.validateUsernameInDomain(username, domainId)) {
 | |
|                 throw new CloudRuntimeException("The user " + username + " already exists in domain " + domainId);
 | |
|             }
 | |
| 
 | |
|             if (accountId == null) {
 | |
|                 if ((userType < Account.ACCOUNT_TYPE_NORMAL) || (userType > Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
 | |
|                     throw new CloudRuntimeException("Invalid account type " + userType + " given; unable to create user");
 | |
|                 }
 | |
| 
 | |
|                 // create a new account for the user
 | |
|                 AccountVO newAccount = new AccountVO();
 | |
|                 if (domainId == null) {
 | |
|                     // root domain is default
 | |
|                     domainId = DomainVO.ROOT_DOMAIN;
 | |
|                 }
 | |
| 
 | |
|                 if ((domainId != DomainVO.ROOT_DOMAIN) && (userType == Account.ACCOUNT_TYPE_ADMIN)) {
 | |
|                     throw new CloudRuntimeException("Invalid account type " + userType + " given for an account in domain " + domainId + "; unable to create user.");
 | |
|                 }
 | |
| 
 | |
|                 newAccount.setAccountName(accountName);
 | |
|                 newAccount.setDomainId(domainId);
 | |
|                 newAccount.setType(userType);
 | |
|                 newAccount.setState(State.enabled);
 | |
|                 newAccount = _accountDao.persist(newAccount);
 | |
|                 accountId = newAccount.getId();
 | |
|             }
 | |
| 
 | |
|             if (userType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
 | |
|                 List<DataCenterVO> dc = _dcDao.findZonesByDomainId(domainId);
 | |
|                 if (dc == null || dc.size() == 0) {
 | |
|                     throw new CloudRuntimeException("The account cannot be created as domain " + domain.getName() + " is not associated with any private Zone");
 | |
|                 }
 | |
|             }
 | |
|             if (accountId == null) {
 | |
|                 throw new CloudRuntimeException("Failed to create account for user: " + username + "; unable to create user");
 | |
|             }
 | |
| 
 | |
|             UserVO user = new UserVO();
 | |
|             user.setUsername(username);
 | |
|             user.setPassword(password);
 | |
|             user.setState(State.enabled);
 | |
|             user.setFirstname(firstName);
 | |
|             user.setLastname(lastName);
 | |
|             user.setAccountId(accountId.longValue());
 | |
|             user.setEmail(email);
 | |
|             user.setTimezone(timezone);
 | |
|             if (s_logger.isDebugEnabled()) {
 | |
|                 s_logger.debug("Creating user: " + username + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:" + timezone);
 | |
|             }
 | |
| 
 | |
|             UserVO dbUser = _userDao.persist(user);
 | |
| 
 | |
|             _networkGroupMgr.createDefaultSecurityGroup(accountId);
 | |
| 
 | |
|             if (!user.getPassword().equals(dbUser.getPassword())) {
 | |
|                 throw new CloudRuntimeException("The user " + username + " being creating is using a password that is different than what's in the db");
 | |
|             }
 | |
| 
 | |
|             return _userAccountDao.findById(dbUser.getId());
 | |
|         } catch (Exception e) {
 | |
|             if (e instanceof CloudRuntimeException) {
 | |
|                 s_logger.info("unable to create user: ", e);
 | |
|             } else {
 | |
|                 s_logger.warn("unknown exception creating user", e);
 | |
|             }
 | |
|             throw new CloudRuntimeException(e.getMessage());
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
 | |
|     public UserVO createUser(CreateUserCmd cmd) {
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         String userName = cmd.getUsername();
 | |
|         String password = cmd.getPassword();
 | |
|         String firstName = cmd.getFirstname();
 | |
|         String lastName = cmd.getLastname();
 | |
|         String email = cmd.getEmail();
 | |
|         String timeZone = cmd.getTimezone();
 | |
|         Long accountId = null;
 | |
| 
 | |
|         // default domain to ROOT if not specified
 | |
|         if (domainId == null) {
 | |
|             domainId = Domain.ROOT_DOMAIN;
 | |
|         }
 | |
|         DomainVO domain = _domainDao.findById(domainId);
 | |
|         checkAccess(UserContext.current().getCaller(), domain);
 | |
|         Account account = _accountDao.findActiveAccount(accountName, domainId);
 | |
| 
 | |
|         if (account == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain id=" + domainId + " to create user");
 | |
|         } else {
 | |
|             accountId = account.getAccountId();
 | |
|         }
 | |
| 
 | |
|         if (domain == null) {
 | |
|             throw new CloudRuntimeException("The domain " + domainId + " does not exist; unable to create user");
 | |
|         } else {
 | |
|             if (domain.getState().equals(Domain.State.Inactive)) {
 | |
|                 throw new CloudRuntimeException("The user cannot be created as domain " + domain.getName() + " is being deleted");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (!_userAccountDao.validateUsernameInDomain(userName, domainId)) {
 | |
|             throw new CloudRuntimeException("The user " + userName + " already exists in domain " + domainId);
 | |
|         }
 | |
| 
 | |
|         UserVO user = new UserVO();
 | |
|         user.setUsername(userName);
 | |
|         user.setPassword(password);
 | |
|         user.setState(State.enabled);
 | |
|         user.setFirstname(firstName);
 | |
|         user.setLastname(lastName);
 | |
|         user.setAccountId(accountId.longValue());
 | |
|         user.setEmail(email);
 | |
|         user.setTimezone(timeZone);
 | |
|         if (s_logger.isDebugEnabled()) {
 | |
|             s_logger.debug("Creating user: " + userName + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:" + timeZone);
 | |
|         }
 | |
| 
 | |
|         UserVO dbUser = _userDao.persist(user);
 | |
| 
 | |
|         if (!user.getPassword().equals(dbUser.getPassword())) {
 | |
|             throw new CloudRuntimeException("The user " + userName + " being creating is using a password that is different than what's in the db");
 | |
|         }
 | |
| 
 | |
|         return dbUser;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_USER_UPDATE, eventDescription = "updating User")
 | |
|     public UserAccount updateUser(UpdateUserCmd cmd) throws InvalidParameterValueException {
 | |
|         Long id = cmd.getId();
 | |
|         String apiKey = cmd.getApiKey();
 | |
|         String firstName = cmd.getFirstname();
 | |
|         String email = cmd.getEmail();
 | |
|         String lastName = cmd.getLastname();
 | |
|         String password = cmd.getPassword();
 | |
|         String secretKey = cmd.getSecretKey();
 | |
|         String timeZone = cmd.getTimezone();
 | |
|         String userName = cmd.getUsername();
 | |
| 
 | |
|         // Input validation
 | |
|         UserVO user = _userDao.getUser(id);
 | |
| 
 | |
|         if (user == null) {
 | |
|             throw new InvalidParameterValueException("unable to find user by id");
 | |
|         }
 | |
| 
 | |
|         if ((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
 | |
|             throw new InvalidParameterValueException("Please provide an api key/secret key pair");
 | |
|         }
 | |
| 
 | |
|         // If the account is an admin type, return an error. We do not allow this
 | |
|         Account account = _accountDao.findById(user.getAccountId());
 | |
| 
 | |
|         if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
 | |
|             throw new PermissionDeniedException("user id : " + id + " is system account, update is not allowed");
 | |
|         }
 | |
| 
 | |
|         checkAccess(UserContext.current().getCaller(), account);
 | |
| 
 | |
|         if (firstName == null) {
 | |
|             firstName = user.getFirstname();
 | |
|         }
 | |
|         if (lastName == null) {
 | |
|             lastName = user.getLastname();
 | |
|         }
 | |
|         if (userName == null) {
 | |
|             userName = user.getUsername();
 | |
|         }
 | |
|         if (password == null) {
 | |
|             password = user.getPassword();
 | |
|         }
 | |
|         if (email == null) {
 | |
|             email = user.getEmail();
 | |
|         }
 | |
|         if (timeZone == null) {
 | |
|             timeZone = user.getTimezone();
 | |
|         }
 | |
|         if (apiKey == null) {
 | |
|             apiKey = user.getApiKey();
 | |
|         }
 | |
|         if (secretKey == null) {
 | |
|             secretKey = user.getSecretKey();
 | |
|         }
 | |
| 
 | |
|         Long accountId = user.getAccountId();
 | |
| 
 | |
|         if (s_logger.isDebugEnabled()) {
 | |
|             s_logger.debug("updating user with id: " + id);
 | |
|         }
 | |
|         try {
 | |
|             // check if the apiKey and secretKey are globally unique
 | |
|             if (apiKey != null && secretKey != null) {
 | |
|                 Pair<User, Account> apiKeyOwner = _accountDao.findUserAccountByApiKey(apiKey);
 | |
| 
 | |
|                 if (apiKeyOwner != null) {
 | |
|                     User usr = apiKeyOwner.first();
 | |
|                     if (usr.getId() != id) {
 | |
|                         throw new InvalidParameterValueException("The api key:" + apiKey + " exists in the system for user id:" + id + " ,please provide a unique key");
 | |
|                     } else {
 | |
|                         // allow the updation to take place
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             _userDao.update(id, userName, password, firstName, lastName, email, accountId, timeZone, apiKey, secretKey);
 | |
|         } catch (Throwable th) {
 | |
|             s_logger.error("error updating user", th);
 | |
|             throw new CloudRuntimeException("Unable to update user " + id);
 | |
|         }
 | |
|         return _userAccountDao.findById(id);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_USER_DISABLE, eventDescription = "disabling User", async = true)
 | |
|     public UserAccount disableUser(DisableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
 | |
|         Long userId = cmd.getId();
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
| 
 | |
|         // Check if user exists in the system
 | |
|         User user = _userDao.findById(userId);
 | |
|         if ((user == null) || (user.getRemoved() != null)) {
 | |
|             throw new InvalidParameterValueException("Unable to find active user by id " + userId);
 | |
|         }
 | |
| 
 | |
|         // If the user is a System user, return an error
 | |
|         Account account = _accountDao.findById(user.getAccountId());
 | |
|         if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
 | |
|             throw new InvalidParameterValueException("User id : " + userId + " is a system user, disabling is not allowed");
 | |
|         }
 | |
| 
 | |
|         if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
 | |
|             throw new PermissionDeniedException("Failed to disable user " + userId + ", permission denied.");
 | |
|         }
 | |
| 
 | |
|         boolean success = doSetUserStatus(userId, State.disabled);
 | |
|         if (success) {
 | |
|             // user successfully disabled
 | |
|             return _userAccountDao.findById(userId);
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to disable user " + userId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_USER_ENABLE, eventDescription = "enabling User")
 | |
|     public UserAccount enableUser(EnableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
 | |
|         Long userId = cmd.getId();
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
|         boolean success = false;
 | |
| 
 | |
|         // Check if user exists in the system
 | |
|         User user = _userDao.findById(userId);
 | |
|         if ((user == null) || (user.getRemoved() != null)) {
 | |
|             throw new InvalidParameterValueException("Unable to find active user by id " + userId);
 | |
|         }
 | |
| 
 | |
|         // If the user is a System user, return an error
 | |
|         Account account = _accountDao.findById(user.getAccountId());
 | |
|         if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
 | |
|             throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed");
 | |
|         }
 | |
| 
 | |
|         if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
 | |
|             throw new PermissionDeniedException("Failed to enable user " + userId + ", permission denied.");
 | |
|         }
 | |
| 
 | |
|         success = doSetUserStatus(userId, State.enabled);
 | |
| 
 | |
|         // make sure the account is enabled too
 | |
|         success = (success && enableAccount(user.getAccountId()));
 | |
| 
 | |
|         if (success) {
 | |
|             return _userAccountDao.findById(userId);
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to enable user " + userId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public UserAccount lockUser(LockUserCmd cmd) {
 | |
|         boolean success = false;
 | |
| 
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
|         Long id = cmd.getId();
 | |
| 
 | |
|         // Check if user with id exists in the system
 | |
|         User user = _userDao.findById(id);
 | |
|         if (user == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find user by id");
 | |
|         } else if (user.getRemoved() != null) {
 | |
|             throw new InvalidParameterValueException("Unable to find user by id");
 | |
|         }
 | |
| 
 | |
|         // If the user is a System user, return an error. We do not allow this
 | |
|         Account account = _accountDao.findById(user.getAccountId());
 | |
|         if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
 | |
|             throw new PermissionDeniedException("user id : " + id + " is a system user, locking is not allowed");
 | |
|         }
 | |
| 
 | |
|         if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
 | |
|             throw new PermissionDeniedException("Failed to lock user " + id + ", permission denied.");
 | |
|         }
 | |
| 
 | |
|         // make sure the account is enabled too
 | |
|         // if the user is either locked already or disabled already, don't change state...only lock currently enabled users
 | |
|         if (user.getState().equals(State.locked)) {
 | |
|             // already locked...no-op
 | |
|             return _userAccountDao.findById(id);
 | |
|         } else if (user.getState().equals(State.enabled)) {
 | |
|             success = doSetUserStatus(user.getId(), State.locked);
 | |
| 
 | |
|             boolean lockAccount = true;
 | |
|             List<UserVO> allUsersByAccount = _userDao.listByAccount(user.getAccountId());
 | |
|             for (UserVO oneUser : allUsersByAccount) {
 | |
|                 if (oneUser.getState().equals(State.enabled)) {
 | |
|                     lockAccount = false;
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (lockAccount) {
 | |
|                 success = (success && lockAccountInternal(user.getAccountId()));
 | |
|             }
 | |
|         } else {
 | |
|             if (s_logger.isInfoEnabled()) {
 | |
|                 s_logger.info("Attempting to lock a non-enabled user, current state is " + user.getState() + " (userId: " + user.getId() + "), locking failed.");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (success) {
 | |
|             return _userAccountDao.findById(id);
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to lock user " + id);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DELETE, eventDescription = "deleting account", async = true)
 | |
|     // This method deletes the account
 | |
|     public boolean deleteUserAccount(DeleteAccountCmd cmd) {
 | |
| 
 | |
|         UserContext ctx = UserContext.current();
 | |
|         long callerUserId = ctx.getCallerUserId();
 | |
|         Account caller = ctx.getCaller();
 | |
| 
 | |
|         Long accountId = cmd.getId();
 | |
| 
 | |
|         // If the user is a System user, return an error. We do not allow this
 | |
|         AccountVO account = _accountDao.findById(accountId);
 | |
|         checkAccess(UserContext.current().getCaller(), account);
 | |
|         if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
 | |
|             throw new PermissionDeniedException("Account id : " + accountId + " is a system account, delete is not allowed");
 | |
|         }
 | |
| 
 | |
|         if (account == null) {
 | |
|             throw new InvalidParameterValueException("The specified account does not exist in the system");
 | |
|         }
 | |
| 
 | |
|         if (account.getRemoved() != null) {
 | |
|             s_logger.info("The account:" + account.getAccountName() + " is already removed");
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         return deleteAccount(account, callerUserId, caller);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public AccountVO enableAccount(EnableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         boolean success = false;
 | |
|         Account account = _accountDao.findActiveAccount(accountName, domainId);
 | |
| 
 | |
|         // Check if account exists
 | |
|         if (account == null) {
 | |
|             s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
 | |
|             throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
| 
 | |
|         // Don't allow to modify system account
 | |
|         if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
 | |
|             throw new InvalidParameterValueException("Can not modify system account");
 | |
|         }
 | |
| 
 | |
|         // Check if user performing the action is allowed to modify this account
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
|         if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
 | |
|             throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
 | |
|         }
 | |
| 
 | |
|         success = enableAccount(account.getId());
 | |
|         if (success) {
 | |
|             return _accountDao.findById(account.getId());
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to enable account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DISABLE, eventDescription = "locking account", async = true)
 | |
|     public AccountVO lockAccount(DisableAccountCmd cmd) {
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         String accountName = cmd.getAccountName();
 | |
| 
 | |
|         if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
 | |
|             throw new PermissionDeniedException("Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
 | |
|         }
 | |
| 
 | |
|         Account account = _accountDao.findActiveAccount(accountName, domainId);
 | |
|         if (account == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find active account with name " + accountName + " in domain " + domainId);
 | |
|         }
 | |
| 
 | |
|         // don't allow modify system account
 | |
|         if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
 | |
|             throw new InvalidParameterValueException("can not lock system account");
 | |
|         }
 | |
| 
 | |
|         if (lockAccountInternal(account.getId())) {
 | |
|             return _accountDao.findById(account.getId());
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to lock account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DISABLE, eventDescription = "disabling account", async = true)
 | |
|     public AccountVO disableAccount(DisableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ConcurrentOperationException, ResourceUnavailableException {
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Long domainId = cmd.getDomainId();
 | |
| 
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
|         if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
 | |
|             throw new PermissionDeniedException("Failed to disable account " + accountName + " in domain " + domainId + ", permission denied.");
 | |
|         }
 | |
| 
 | |
|         Account account = _accountDao.findActiveAccount(accountName, domainId);
 | |
|         if (account == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
|         if (disableAccount(account.getId())) {
 | |
|             return _accountDao.findById(account.getId());
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to update account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public AccountVO updateAccount(UpdateAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         String accountName = cmd.getAccountName();
 | |
|         String newAccountName = cmd.getNewName();
 | |
| 
 | |
|         boolean success = false;
 | |
|         Account account = _accountDao.findAccount(accountName, domainId);
 | |
| 
 | |
|         // Check if account exists
 | |
|         if (account == null) {
 | |
|             s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
 | |
|             throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
| 
 | |
|         // Don't allow to modify system account
 | |
|         if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
 | |
|             throw new InvalidParameterValueException("Can not modify system account");
 | |
|         }
 | |
| 
 | |
|         // Check if user performing the action is allowed to modify this account
 | |
|         Account adminAccount = UserContext.current().getCaller();
 | |
|         if ((adminAccount != null) && (adminAccount.getType() != Account.ACCOUNT_TYPE_ADMIN) && _domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
 | |
|             throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
 | |
|         }
 | |
| 
 | |
|         // check if the given account name is unique in this domain for updating
 | |
|         Account duplicateAcccount = _accountDao.findAccount(newAccountName, domainId);
 | |
|         if (duplicateAcccount != null && duplicateAcccount.getRemoved() == null && duplicateAcccount.getId() != account.getId()) {// allow
 | |
|                                                                                                                                   // same
 | |
|                                                                                                                                   // account
 | |
|                                                                                                                                   // to
 | |
|                                                                                                                                   // update
 | |
|                                                                                                                                   // itself
 | |
|             throw new PermissionDeniedException("There already exists an account with the name:" + newAccountName + " in the domain:" + domainId + " with existing account id:"
 | |
|                     + duplicateAcccount.getId());
 | |
|         }
 | |
| 
 | |
|         if (account.getAccountName().equals(newAccountName)) {
 | |
|             success = true;
 | |
|         } else {
 | |
|             AccountVO acctForUpdate = _accountDao.createForUpdate();
 | |
|             acctForUpdate.setAccountName(newAccountName);
 | |
|             success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate);
 | |
|         }
 | |
|         if (success) {
 | |
|             return _accountDao.findById(account.getId());
 | |
|         } else {
 | |
|             throw new CloudRuntimeException("Unable to update account " + accountName + " in domain " + domainId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_USER_DELETE, eventDescription = "deleting User")
 | |
|     public boolean deleteUser(DeleteUserCmd deleteUserCmd) {
 | |
|         long id = deleteUserCmd.getId();
 | |
| 
 | |
|         UserVO user = _userDao.findById(id);
 | |
| 
 | |
|         if (user == null) {
 | |
|             throw new InvalidParameterValueException("The specified user doesn't exist in the system");
 | |
|         }
 | |
| 
 | |
|         if ((user != null) && (user.getAccountId() == Account.ACCOUNT_ID_SYSTEM)) {
 | |
|             throw new InvalidParameterValueException("Account id : " + user.getAccountId() + " is a system account, delete for user associated with this account is not allowed");
 | |
|         }
 | |
|         checkAccess(UserContext.current().getCaller(), _accountDao.findById(user.getAccountId()));
 | |
|         return _userDao.remove(id);
 | |
|     }
 | |
| 
 | |
|     protected class AccountCleanupTask implements Runnable {
 | |
|         @Override
 | |
|         public void run() {
 | |
|             try {
 | |
|                 GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
 | |
|                 if (lock == null) {
 | |
|                     s_logger.debug("Couldn't get the global lock");
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 if (!lock.lock(30)) {
 | |
|                     s_logger.debug("Couldn't lock the db");
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 Transaction txn = null;
 | |
|                 try {
 | |
|                     txn = Transaction.open(Transaction.CLOUD_DB);
 | |
| 
 | |
|                     List<AccountVO> accounts = _accountDao.findCleanups();
 | |
|                     s_logger.info("Found " + accounts.size() + " accounts to cleanup");
 | |
|                     for (AccountVO account : accounts) {
 | |
|                         s_logger.debug("Cleaning up " + account.getId());
 | |
|                         try {
 | |
|                             cleanupAccount(account, getSystemUser().getId(), getSystemAccount());
 | |
|                         } catch (Exception e) {
 | |
|                             s_logger.error("Skipping due to error on account " + account.getId(), e);
 | |
|                         }
 | |
|                     }
 | |
|                 } catch (Exception e) {
 | |
|                     s_logger.error("Exception ", e);
 | |
|                 } finally {
 | |
|                     if (txn != null) {
 | |
|                         txn.close();
 | |
|                     }
 | |
| 
 | |
|                     lock.unlock();
 | |
|                 }
 | |
|             } catch (Exception e) {
 | |
|                 s_logger.error("Exception ", e);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Account finalizeOwner(Account caller, String accountName, Long domainId) {
 | |
|         // don't default the owner to the system account
 | |
|         if (caller.getId() == Account.ACCOUNT_ID_SYSTEM && (accountName == null || domainId == null)) {
 | |
|             throw new InvalidParameterValueException("Account and domainId are needed for resource creation");
 | |
|         }
 | |
| 
 | |
|         if (isAdmin(caller.getType()) && accountName != null && domainId != null) {
 | |
|             DomainVO domain = _domainDao.findById(domainId);
 | |
|             if (domain == null) {
 | |
|                 throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId);
 | |
|             }
 | |
| 
 | |
|             Account owner = _accountDao.findActiveAccount(accountName, domainId);
 | |
|             if (owner == null) {
 | |
|                 throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
 | |
|             }
 | |
|             checkAccess(caller, domain);
 | |
| 
 | |
|             return owner;
 | |
|         } else if (!isAdmin(caller.getType()) && accountName != null && domainId != null) {
 | |
|             if (!accountName.equals(caller.getAccountName()) || domainId.longValue() != caller.getDomainId()) {
 | |
|                 throw new PermissionDeniedException("Can't create/list resources for account " + accountName + " in domain " + domainId + ", permission denied");
 | |
|             } else {
 | |
|                 return caller;
 | |
|             }
 | |
|         } else {
 | |
|             if ((accountName == null && domainId != null) || (accountName != null && domainId == null)) {
 | |
|                 throw new InvalidParameterValueException("AccountName and domainId must be specified together");
 | |
|             }
 | |
|             // regular user can't create/list resources for other people
 | |
|             return caller;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Account getActiveAccount(String accountName, Long domainId) {
 | |
|         if (accountName == null || domainId == null) {
 | |
|             throw new InvalidParameterValueException("Both accountName and domainId are required for finding active account in the system");
 | |
|         } else {
 | |
|             return _accountDao.findActiveAccount(accountName, domainId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Account getActiveAccount(Long accountId) {
 | |
|         if (accountId == null) {
 | |
|             throw new InvalidParameterValueException("AccountId is required by account search");
 | |
|         } else {
 | |
|             return _accountDao.findById(accountId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Account getAccount(Long accountId) {
 | |
|         if (accountId == null) {
 | |
|             throw new InvalidParameterValueException("AccountId is required by account search");
 | |
|         } else {
 | |
|             return _accountDao.findByIdIncludingRemoved(accountId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public User getActiveUser(long userId) {
 | |
|         return _userDao.findById(userId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Domain getDomain(long domainId) {
 | |
|         return _domainDao.findById(domainId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Pair<String, Long> finalizeAccountDomainForList(Account caller, String accountName, Long domainId) {
 | |
|         if (isAdmin(caller.getType())) {
 | |
|             if (domainId == null && accountName != null) {
 | |
|                 throw new InvalidParameterValueException("accountName and domainId might be specified together");
 | |
|             } else if (domainId != null) {
 | |
|                 Domain domain = getDomain(domainId);
 | |
|                 if (domain == null) {
 | |
|                     throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId);
 | |
|                 }
 | |
| 
 | |
|                 checkAccess(caller, domain);
 | |
| 
 | |
|                 if (accountName != null) {
 | |
|                     Account owner = getActiveAccount(accountName, domainId);
 | |
|                     if (owner == null) {
 | |
|                         throw new InvalidParameterValueException("Unable to find account with name " + accountName + " in domain id=" + domainId);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         } else if (accountName != null && domainId != null) {
 | |
|             if (!accountName.equals(caller.getAccountName()) || domainId.longValue() != caller.getDomainId()) {
 | |
|                 throw new PermissionDeniedException("Can't list port forwarding rules for account " + accountName + " in domain " + domainId + ", permission denied");
 | |
|             }
 | |
|         } else {
 | |
|             accountName = caller.getAccountName();
 | |
|             domainId = caller.getDomainId();
 | |
|         }
 | |
| 
 | |
|         return new Pair<String, Long>(accountName, domainId);
 | |
|     }
 | |
| }
 |