bug 9419: implement api to reset resource count

added a command to reset resource count for account/domain based on real usage of resources
This commit is contained in:
Murali Reddy 2011-06-13 10:55:57 +05:30
parent 9470c36644
commit aa4f654929
26 changed files with 402 additions and 27 deletions

View File

@ -45,6 +45,7 @@ import com.cloud.api.response.NetworkResponse;
import com.cloud.api.response.PodResponse;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.api.response.ResourceLimitResponse;
import com.cloud.api.response.ResourceCountResponse;
import com.cloud.api.response.SecurityGroupResponse;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.api.response.SnapshotPolicyResponse;
@ -63,6 +64,7 @@ import com.cloud.async.AsyncJob;
import com.cloud.capacity.Capacity;
import com.cloud.configuration.Configuration;
import com.cloud.configuration.ResourceLimit;
import com.cloud.configuration.ResourceCount;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Pod;
import com.cloud.dc.Vlan;
@ -108,6 +110,8 @@ public interface ResponseGenerator {
ResourceLimitResponse createResourceLimitResponse(ResourceLimit limit);
ResourceCountResponse createResourceCountResponse(ResourceCount resourceCount);
ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering);
ConfigurationResponse createConfigurationResponse(Configuration cfg);

View File

@ -41,10 +41,10 @@ public class UpdateResourceCountCmd extends BaseCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="Update resource for a specified account. Must be used with the domainId parameter.")
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="Update resource count for a specified account. Must be used with the domainId parameter.")
private String accountName;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="Update resource limits for all accounts in specified domain. If used with the account parameter, updates resource limits for a specified account in specified domain.")
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="Update resource counts for all accounts & child domains in specified domain. If used with the account parameter, updates resource counts for a specified account in specified domain.")
private Long domainId;
@Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.INTEGER, required=true, description="Type of resource to update. Values are 0, 1, 2, 3, and 4. 0 - Instance. Number of instances a user can create. " +

View File

@ -21,13 +21,13 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class ResourceCountResponse extends BaseResponse {
@SerializedName("account") @Param(description="the account of the resource count")
@SerializedName("account") @Param(description="the account for which resource count's are updated")
private String accountName;
@SerializedName("domainid") @Param(description="the domain ID of the resource count")
@SerializedName("domainid") @Param(description="the domain ID for which resource count's are updated")
private Long domainId;
@SerializedName("domain") @Param(description="the domain name of the resource count")
@SerializedName("domain") @Param(description="the domain name for which resource count's are updated")
private String domainName;
@SerializedName("resourcetype") @Param(description="resource type. Values include 0, 1, 2, 3, 4. See the resourceType parameter for more information on these values.")

View File

@ -32,8 +32,10 @@ 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.UpdateResourceCountCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.configuration.ResourceLimit;
import com.cloud.configuration.ResourceCount;
import com.cloud.domain.Domain;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ResourceUnavailableException;
@ -141,6 +143,16 @@ public interface AccountService {
*/
ResourceLimit updateResourceLimit(UpdateResourceLimitCmd cmd);
/**
* Updates an existing resource count details for the account/domain
*
* @param cmd
* the command that wraps the domainId, accountId, resource type parameters
* @return the updated/created resource count
*/
ResourceCount updateResourceCount(UpdateResourceCountCmd cmd);
/**
* Search for resource limits for the given id and/or account and/or type and/or domain.
*

View File

@ -32,6 +32,7 @@ getCloudIdentifier=com.cloud.api.commands.GetCloudIdentifierCmd;15
#### Limit commands
updateResourceLimit=com.cloud.api.commands.UpdateResourceLimitCmd;7
updateResourceCount=com.cloud.api.commands.UpdateResourceCountCmd;7
listResourceLimits=com.cloud.api.commands.ListResourceLimitsCmd;15
#### VM commands

View File

@ -59,6 +59,7 @@ import com.cloud.api.response.NicResponse;
import com.cloud.api.response.PodResponse;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.api.response.ResourceLimitResponse;
import com.cloud.api.response.ResourceCountResponse;
import com.cloud.api.response.SecurityGroupResponse;
import com.cloud.api.response.SecurityGroupResultObject;
import com.cloud.api.response.ServiceOfferingResponse;
@ -82,6 +83,7 @@ import com.cloud.capacity.CapacityVO;
import com.cloud.configuration.Configuration;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimit;
import com.cloud.configuration.ResourceCount;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
@ -396,6 +398,28 @@ public class ApiResponseHelper implements ResponseGenerator {
return resourceLimitResponse;
}
@Override
public ResourceCountResponse createResourceCountResponse(ResourceCount resourceCount) {
ResourceCountResponse resourceCountResponse = new ResourceCountResponse();
if (resourceCount.getAccountId() != null) {
Account accountTemp = ApiDBUtils.findAccountById(resourceCount.getAccountId());
if (accountTemp != null) {
resourceCountResponse.setAccountName(accountTemp.getAccountName());
resourceCountResponse.setDomainId(accountTemp.getDomainId());
resourceCountResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
}
} else if (resourceCount.getDomainId() != null) {
resourceCountResponse.setDomainId(resourceCount.getDomainId());
resourceCountResponse.setDomainName(ApiDBUtils.findDomainById(resourceCount.getDomainId()).getName());
}
resourceCountResponse.setResourceType(Integer.valueOf(resourceCount.getType().ordinal()).toString());
resourceCountResponse.setResourceCount(resourceCount.getCount());
resourceCountResponse.setObjectName("resourcecount");
return resourceCountResponse;
}
@Override
public ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering) {
ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();

View File

@ -40,6 +40,22 @@ public interface ResourceCountDao extends GenericDao<ResourceCountVO, Long> {
*/
public long getDomainCount(long domainId, ResourceType type);
/**
* Set the count of in use resources for an account by type
* @param accountId the id of the account to set the resource count
* @param type the type of resource (e.g. user_vm, public_ip, volume)
* @param the count of resources in use for the given type and account
*/
public void setAccountCount(long accountId, ResourceType type, long count);
/**
* Get the count of in use resources for a domain by type
* @param domainId the id of the domain to set the resource count
* @param type the type of resource (e.g. user_vm, public_ip, volume)
* @param the count of resources in use for the given type and domain
*/
public void setDomainCount(long domainId, ResourceType type, long count);
/**
* Update the count of resources in use for the given account and given resource type
* @param accountId the id of the account to update resource count

View File

@ -79,6 +79,34 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
return (resourceCountVO != null) ? resourceCountVO.getCount() : 0;
}
@Override
public void setAccountCount(long accountId, ResourceType type, long count) {
ResourceCountVO resourceCountVO = findByAccountIdAndType(accountId, type);
if (resourceCountVO == null) {
if (count != 0) {
resourceCountVO = new ResourceCountVO(accountId, null, type, count);
persist(resourceCountVO);
}
} else {
resourceCountVO.setCount(count);
update(resourceCountVO.getId(), resourceCountVO);
}
}
@Override
public void setDomainCount(long domainId, ResourceType type, long count) {
ResourceCountVO resourceCountVO = findByDomainIdAndType(domainId, type);
if (resourceCountVO == null) {
if (count != 0) {
resourceCountVO = new ResourceCountVO(null, domainId, type, count);
persist(resourceCountVO);
}
} else {
resourceCountVO.setCount(count);
update(resourceCountVO.getId(), resourceCountVO);
}
}
@Override
public void updateAccountCount(long accountId, ResourceType type, boolean increment, long delta) {
delta = increment ? delta : delta * -1;

View File

@ -29,5 +29,6 @@ public interface DomainDao extends GenericDao<DomainVO, Long> {
public DomainVO findDomainByPath(String domainPath);
public boolean isChildDomain(Long parentId, Long childId);
DomainVO findImmediateChildForParent(Long parentId);
List<DomainVO> findImmediateChildrenForParent(Long parentId);
List<DomainVO> findAllChildren(String path, Long parentId);
}

View File

@ -66,7 +66,8 @@ public class DomainDaoImpl extends GenericDaoBase<DomainVO, Long> implements Dom
FindAllChildrenSearch = createSearchBuilder();
FindAllChildrenSearch.and("path", FindAllChildrenSearch.entity().getPath(), SearchCriteria.Op.LIKE);
FindAllChildrenSearch.and("id", FindAllChildrenSearch.entity().getId(), SearchCriteria.Op.NEQ);
FindAllChildrenSearch.done();
FindAllChildrenSearch.done();
}
public void update(Long id, String domainName, String domainPath) {
@ -196,14 +197,21 @@ public class DomainDaoImpl extends GenericDaoBase<DomainVO, Long> implements Dom
sc.addAnd("path", SearchCriteria.Op.EQ, domainPath);
return findOneBy(sc);
}
@Override
public DomainVO findImmediateChildForParent(Long parentId){
SearchCriteria<DomainVO> sc = ImmediateChildDomainSearch.create();
sc.setParameters("parent", parentId);
return (listBy(sc).size() > 0 ? listBy(sc).get(0) : null);//may need to revisit for multiple children case
}
@Override
public List<DomainVO> findImmediateChildrenForParent(Long parentId){
SearchCriteria<DomainVO> sc = ImmediateChildDomainSearch.create();
sc.setParameters("parent", parentId);
return listBy(sc);
}
@Override
public List<DomainVO> findAllChildren(String path, Long parentId){
SearchCriteria<DomainVO> sc = FindAllChildrenSearch.create();

View File

@ -42,7 +42,9 @@ public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
int countIPs(long dcId, long vlanDbId, boolean onlyCountAllocated);
int countIPs(long dcId, Long accountId, String vlanId, String vlanGateway, String vlanNetmask);
int countIPs(long dcId, Long accountId, String vlanId, String vlanGateway, String vlanNetmask);
long countAllocatedIPsForAccount(long accountId);
boolean mark(long dcId, Ip ip);

View File

@ -40,6 +40,7 @@ import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.vm.VirtualMachine;
@Local(value = { IPAddressDao.class })
@DB
@ -52,7 +53,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
protected final GenericSearchBuilder<IPAddressVO, Integer> AllocatedIpCount;
protected final GenericSearchBuilder<IPAddressVO, Integer> AllIpCountForDashboard;
protected final GenericSearchBuilder<IPAddressVO, Integer> AllocatedIpCountForDashboard;
protected final GenericSearchBuilder<IPAddressVO, Long> AllocatedIpCountForAccount;
@ -98,7 +99,12 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
AllocatedIpCountForDashboard.and("dc", AllocatedIpCountForDashboard.entity().getDataCenterId(), Op.EQ);
AllocatedIpCountForDashboard.and("allocated", AllocatedIpCountForDashboard.entity().getAllocatedTime(), Op.NNULL);
AllocatedIpCountForDashboard.done();
AllocatedIpCountForAccount = createSearchBuilder(Long.class);
AllocatedIpCountForAccount.select(null, Func.COUNT, AllocatedIpCountForAccount.entity().getAddress());
AllocatedIpCountForAccount.and("account", AllocatedIpCountForAccount.entity().getAllocatedToAccountId(), Op.EQ);
AllocatedIpCountForAccount.and("allocated", AllocatedIpCountForAccount.entity().getAllocatedTime(), Op.NNULL);
AllocatedIpCountForAccount.done();
}
@Override
@ -278,5 +284,11 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
return findOneBy(sc);
}
@Override
public long countAllocatedIPsForAccount(long accountId) {
SearchCriteria<Long> sc = AllocatedIpCountForAccount.create();
sc.setParameters("account", accountId);
return customSearch(sc, null).get(0);
}
}

View File

@ -39,5 +39,5 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long> {
long updateSnapshotSecHost(long dcId, long secHostId);
List<SnapshotVO> listByHostId(Filter filter, long hostId);
List<SnapshotVO> listByHostId(long hostId);
public Long countSnapshotsForAccount(long accountId);
}

View File

@ -31,9 +31,14 @@ import com.cloud.storage.Snapshot.Type;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
@Local (value={SnapshotDao.class})
public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements SnapshotDao {
@ -49,7 +54,9 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
private final SearchBuilder<SnapshotVO> backupUuidSearch;
private final SearchBuilder<SnapshotVO> VolumeIdVersionSearch;
private final SearchBuilder<SnapshotVO> HostIdSearch;
private final SearchBuilder<SnapshotVO> AccountIdSearch;
private final GenericSearchBuilder<SnapshotVO, Long> CountSnapshotsByAccount;
@Override
public SnapshotVO findNextSnapshot(long snapshotId) {
SearchCriteria<SnapshotVO> sc = ParentIdSearch.create();
@ -99,7 +106,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
sc.setParameters("status", Status.DOWNLOADED);
return listBy(sc, filter);
}
@Override
public List<SnapshotVO> listByVolumeIdIncludingRemoved(long volumeId) {
SearchCriteria<SnapshotVO> sc = VolumeIdSearch.create();
@ -148,7 +155,16 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
backupUuidSearch = createSearchBuilder();
backupUuidSearch.and("backupUuid", backupUuidSearch.entity().getBackupSnapshotId(), SearchCriteria.Op.EQ);
backupUuidSearch.done();
AccountIdSearch = createSearchBuilder();
AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountIdSearch.done();
CountSnapshotsByAccount = createSearchBuilder(Long.class);
CountSnapshotsByAccount.select(null, Func.COUNT, null);
CountSnapshotsByAccount.and("account", CountSnapshotsByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
CountSnapshotsByAccount.and("removed", CountSnapshotsByAccount.entity().getRemoved(), SearchCriteria.Op.NNULL);
CountSnapshotsByAccount.done();
}
@Override
@ -221,4 +237,11 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
}
return 0;
}
@Override
public Long countSnapshotsForAccount(long accountId) {
SearchCriteria<Long> sc = CountSnapshotsByAccount.create();
sc.setParameters("account", accountId);
return customSearch(sc, null).get(0);
}
}

View File

@ -72,5 +72,6 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long> {
VMTemplateVO findRoutingTemplate(HypervisorType type);
List<Long> listPrivateTemplatesByHost(Long hostId);
public Long countTemplatesForAccount(long accountId);
}

View File

@ -46,6 +46,7 @@ import com.cloud.info.RunningHostCountInfo;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
@ -56,10 +57,12 @@ import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
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.db.SearchCriteria.Func;
@Local(value={VMTemplateDao.class})
public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implements VMTemplateDao {
@ -90,7 +93,8 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
private SearchBuilder<VMTemplateVO> PublicSearch;
private SearchBuilder<VMTemplateVO> NameAccountIdSearch;
private SearchBuilder<VMTemplateVO> PublicIsoSearch;
private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount;
private String routerTmpltName;
private String consoleProxyTmpltName;
@ -278,7 +282,13 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
TmpltsInZoneSearch.join("tmpltzone", tmpltZoneSearch, tmpltZoneSearch.entity().getTemplateId(), TmpltsInZoneSearch.entity().getId(), JoinBuilder.JoinType.INNER);
tmpltZoneSearch.done();
TmpltsInZoneSearch.done();
CountTemplatesByAccount = createSearchBuilder(Long.class);
CountTemplatesByAccount.select(null, Func.COUNT, null);
CountTemplatesByAccount.and("account", CountTemplatesByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
CountTemplatesByAccount.and("removed", CountTemplatesByAccount.entity().getRemoved(), SearchCriteria.Op.NNULL);
CountTemplatesByAccount.done();
return result;
}
@ -534,5 +544,12 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
} else {
return null;
}
}
}
@Override
public Long countTemplatesForAccount(long accountId) {
SearchCriteria<Long> sc = CountTemplatesByAccount.create();
sc.setParameters("account", accountId);
return customSearch(sc, null).get(0);
}
}

View File

@ -44,7 +44,7 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long> {
List<VolumeVO> findByPoolId(long poolId);
List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId);
List<VolumeVO> findUsableVolumesForInstance(long instanceId);
Long countAllocatedVolumesForAccount(long accountId);
/**
* Updates the volume only if the state in memory matches the state in the database.
* @param vol Volume to be updated.

View File

@ -45,6 +45,8 @@ import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.UpdateBuilder;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine.State;
@Local(value=VolumeDao.class) @DB(txn=false)
public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements VolumeDao {
@ -55,7 +57,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
protected final GenericSearchBuilder<VolumeVO, Long> ActiveTemplateSearch;
protected final SearchBuilder<VolumeVO> InstanceStatesSearch;
protected final SearchBuilder<VolumeVO> AllFieldsSearch;
protected GenericSearchBuilder<VolumeVO, Long> CountByAccount;
protected final Attribute _stateAttr;
protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?";
@ -73,7 +75,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
public List<VolumeVO> findByAccount(long accountId) {
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("notDestroyed", Volume.State.Destroy);
sc.setParameters("state", Volume.State.Ready);
return listBy(sc);
}
@ -305,6 +307,12 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), Op.IN);
InstanceStatesSearch.done();
CountByAccount = createSearchBuilder(Long.class);
CountByAccount.select(null, Func.COUNT, null);
CountByAccount.and("account", CountByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
CountByAccount.and("state", CountByAccount.entity().getState(), SearchCriteria.Op.NIN);
CountByAccount.done();
_stateAttr = _allAttributes.get("state");
assert _stateAttr != null : "Couldn't get the state attribute";
}
@ -317,7 +325,15 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
SumCount sumCount = results.get(0);
return new Pair<Long, Long>(sumCount.count, sumCount.sum);
}
@Override
public Long countAllocatedVolumesForAccount(long accountId) {
SearchCriteria<Long> sc = CountByAccount.create();
sc.setParameters("account", accountId);
sc.setParameters("state", new Object[] {Volume.State.Destroy, State.Expunging});
return customSearch(sc, null).get(0);
}
public static class SumCount {
public long sum;
public long count;

View File

@ -63,6 +63,19 @@ public interface AccountManager extends AccountService {
*/
public long findCorrectResourceLimit(DomainVO domain, ResourceType type);
/**
* Updates the resource count of an account to reflect current usage by account
* @param accountId
* @param type
*/
public long updateAccountResourceCount(long accountId, ResourceType type);
/**
* Updates the resource count of the domain to reflect current usage in the domain
* @param domainId
* @param type
*/
public long updateDomainResourceCount(long domainId, ResourceType type);
/**
* Increments the resource count
* @param accountId

View File

@ -47,12 +47,15 @@ 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.UpdateResourceCountCmd;
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.ResourceCount;
import com.cloud.configuration.ResourceCountVO;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceCountDao;
import com.cloud.configuration.dao.ResourceLimitDao;
@ -67,6 +70,7 @@ 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.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.PermissionDeniedException;
@ -75,6 +79,7 @@ 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.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.VpnUserDao;
@ -86,6 +91,7 @@ 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.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
@ -113,6 +119,7 @@ import com.cloud.vm.ReservationContextImpl;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.UserVmDao;
@ -151,6 +158,12 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
private SecurityGroupDao _securityGroupDao;
@Inject
private VMInstanceDao _vmDao;
@Inject
private IPAddressDao _ipAddressDao;
@Inject
protected SnapshotDao _snapshotDao;
@Inject
protected VMTemplateDao _vmTemplateDao;
@Inject
private SecurityGroupManager _networkGroupMgr;
@ -730,6 +743,130 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
}
}
@Override
public long updateAccountResourceCount(long accountId, ResourceType type) {
long count=0;
// this lock guards against the updates to user_vm, volume, snapshot, public _ip and template
// table as any resource creation precedes with the resourceLimitExceeded check which needs this lock too
if (m_resourceCountLock.lock(120)) { // 2 minutes
try {
switch (type) {
case user_vm:
count = _userVmDao.countAllocatedVMsForAccount(accountId);
break;
case volume:
count = _volumeDao.countAllocatedVolumesForAccount(accountId);
long virtualRouterCount = _vmDao.countAllocatedVirtualRoutersForAccount(accountId);
count = count - virtualRouterCount; // don't count the volumes of virtual router
break;
case snapshot:
count = _snapshotDao.countSnapshotsForAccount(accountId);
break;
case public_ip:
count = _ipAddressDao.countAllocatedIPsForAccount(accountId);
break;
case template:
count = _vmTemplateDao.countTemplatesForAccount(accountId);
break;
}
_resourceCountDao.setAccountCount(accountId, type, count);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to update resource count for account with Id" + accountId);
} finally {
m_resourceCountLock.unlock();
}
}
return count;
}
@Override
public long updateDomainResourceCount(long domainId, ResourceType type) {
long count=0;
Domain domain =_domainDao.findById(domainId);
if (m_resourceCountLock.lock(120)) { // 2 minutes
try {
List<DomainVO> domainChildren = _domainDao.findImmediateChildrenForParent(domain.getId());
// for each child domain update the resource count
for (DomainVO domainChild : domainChildren) {
long domainCount = updateDomainResourceCount(domainChild.getId(), type);
count = count + domainCount; // add the child domain count to parent domain count
List<AccountVO> accounts = _accountDao.findActiveAccountsForDomain(domainChild.getId());
for (AccountVO account : accounts) {
long accountCount = updateAccountResourceCount(account.getId(), type);
count = count + accountCount; // add account's resource count to parent domain count
}
}
_resourceCountDao.setDomainCount(domainId, type, count);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to update resource count for domain with Id " + domainId);
} finally {
m_resourceCountLock.unlock();
}
}
return count;
}
@Override
public ResourceCountVO updateResourceCount(UpdateResourceCountCmd cmd) throws InvalidParameterValueException, CloudRuntimeException, PermissionDeniedException{
Account currentAccount = UserContext.current().getCaller();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long accountId = null;
long count=0;
ResourceType resourceType;
Integer type = cmd.getResourceType();
try {
resourceType = ResourceType.values()[type];
} catch (ArrayIndexOutOfBoundsException e) {
throw new InvalidParameterValueException("Please specify a valid resource type.");
}
// Either a domainId or an account name with domainId must be passed in
if ((domainId == null) && (accountName == null)) {
throw new InvalidParameterValueException("Either a domainId or account name with domainId must be passed in.");
}
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.");
}
checkAccess(currentAccount, domain);
}
if (accountName != null) {
if (domainId == null) {
throw new InvalidParameterValueException("domainId parameter is required if account name is specified");
}
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount == null) {
throw new InvalidParameterValueException("unable to find account by name " + accountName + " in domain with id " + domainId);
}
accountId = userAccount.getId();
checkAccess(currentAccount, userAccount);
}
try {
if (accountId != null) {
count = updateAccountResourceCount(accountId, resourceType);
} else {
count = updateDomainResourceCount(domainId, resourceType);
}
} catch (Exception e) {
throw new CloudRuntimeException(e.getMessage());
}
return new ResourceCountVO(accountId, domainId, resourceType, count);
}
@Override
public AccountVO getSystemAccount() {
if (_systemAccount == null) {
@ -1657,6 +1794,14 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
return _userDao.remove(id);
}
public class ResourceCountCalculateTask implements Runnable {
@Override
public void run() {
}
}
protected class AccountCleanupTask implements Runnable {
@Override
public void run() {

View File

@ -39,6 +39,7 @@ public interface AccountDao extends GenericDao<AccountVO, Long> {
List<AccountVO> findNewAccounts(Long minAccountId, Filter filter);
List<AccountVO> findCleanups();
List<AccountVO> findAdminAccountsForDomain(Long domainId);
List<AccountVO> findActiveAccountsForDomain(Long domain);
void markForCleanup(long accountId);
List<AccountVO> listAccounts(String accountName, Long domainId, Filter filter);
}

View File

@ -50,6 +50,7 @@ public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements A
protected final SearchBuilder<AccountVO> AccountNameSearch;
protected final SearchBuilder<AccountVO> AccountTypeSearch;
protected final SearchBuilder<AccountVO> DomainAccountsSearch;
protected final SearchBuilder<AccountVO> CleanupSearch;
@ -62,6 +63,11 @@ public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements A
AccountTypeSearch.and("domainId", AccountTypeSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
AccountTypeSearch.and("type", AccountTypeSearch.entity().getType(), SearchCriteria.Op.EQ);
AccountTypeSearch.done();
DomainAccountsSearch = createSearchBuilder();
DomainAccountsSearch.and("domainId", DomainAccountsSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
DomainAccountsSearch.and("removed", DomainAccountsSearch.entity().getRemoved(), SearchCriteria.Op.NNULL);
DomainAccountsSearch.done();
CleanupSearch = createSearchBuilder();
CleanupSearch.and("cleanup", CleanupSearch.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);
@ -190,6 +196,13 @@ public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements A
sc.addAnd("type", Op.IN, Account.ACCOUNT_TYPE_ADMIN, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, Account.ACCOUNT_TYPE_READ_ONLY_ADMIN, Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN);
return null;
}
@Override
public List<AccountVO> findActiveAccountsForDomain(Long domain) {
SearchCriteria<AccountVO> sc = DomainAccountsSearch.create();
sc.addAnd("domainId", Op.EQ, domain);
return listBy(sc);
}
@Override
public void markForCleanup(long accountId) {

View File

@ -66,5 +66,5 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> {
void saveDetails(UserVmVO vm);
List<Long> listPodIdsHavingVmsforAccount(long zoneId, long accountId);
public Long countAllocatedVMsForAccount(long accountId);
}

View File

@ -41,6 +41,7 @@ import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
@Local(value={UserVmDao.class})
@ -60,6 +61,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
protected final SearchBuilder<UserVmVO> DestroySearch;
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch;
protected GenericSearchBuilder<UserVmVO, Long> CountByAccountPod;
protected GenericSearchBuilder<UserVmVO, Long> CountByAccount;
protected GenericSearchBuilder<UserVmVO, Long> PodsHavingVmsForAccount;
protected SearchBuilder<UserVmVO> UserVmSearch;
@ -128,6 +130,13 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
CountByAccountPod.and("pod", CountByAccountPod.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ);
CountByAccountPod.done();
CountByAccount = createSearchBuilder(Long.class);
CountByAccount.select(null, Func.COUNT, null);
CountByAccount.and("account", CountByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
CountByAccount.and("type", CountByAccount.entity().getType(), SearchCriteria.Op.EQ);
CountByAccount.and("state", CountByAccount.entity().getState(), SearchCriteria.Op.NIN);
CountByAccount.done();
_updateTimeAttr = _allAttributes.get("updateTime");
assert _updateTimeAttr != null : "Couldn't get this updateTime attribute";
}
@ -297,4 +306,13 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
throw new CloudRuntimeException("Caught: " + LIST_PODS_HAVING_VMS_FOR_ACCOUNT, e);
}
}
@Override
public Long countAllocatedVMsForAccount(long accountId) {
SearchCriteria<Long> sc = CountByAccount.create();
sc.setParameters("account", accountId);
sc.setParameters("type", VirtualMachine.Type.User);
sc.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging});
return customSearch(sc, null).get(0);
}
}

View File

@ -79,4 +79,5 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
List<VMInstanceVO> listByTypeAndState(State state, VirtualMachine.Type type);
List<VMInstanceVO> listByAccountId(long accountId);
public Long countAllocatedVirtualRoutersForAccount(long accountId);
}

View File

@ -28,10 +28,13 @@ import org.apache.log4j.Logger;
import com.cloud.utils.db.Attribute;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.UpdateBuilder;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Event;
@ -54,7 +57,8 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
protected final SearchBuilder<VMInstanceVO> HostIdTypesSearch;
protected final SearchBuilder<VMInstanceVO> HostIdUpTypesSearch;
protected final SearchBuilder<VMInstanceVO> HostUpSearch;
protected final GenericSearchBuilder<VMInstanceVO, Long> CountVirtualRoutersByAccount;
protected final Attribute _updateTimeAttr;
protected VMInstanceDaoImpl() {
@ -119,7 +123,13 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
HostUpSearch.and("states", HostUpSearch.entity().getState(), Op.IN);
HostUpSearch.done();
CountVirtualRoutersByAccount = createSearchBuilder(Long.class);
CountVirtualRoutersByAccount.select(null, Func.COUNT, null);
CountVirtualRoutersByAccount.and("account", CountVirtualRoutersByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
CountVirtualRoutersByAccount.and("type", CountVirtualRoutersByAccount.entity().getType(), SearchCriteria.Op.EQ);
CountVirtualRoutersByAccount.and("state", CountVirtualRoutersByAccount.entity().getState(), SearchCriteria.Op.NIN);
CountVirtualRoutersByAccount.done();
_updateTimeAttr = _allAttributes.get("updateTime");
assert _updateTimeAttr != null : "Couldn't get this updateTime attribute";
}
@ -287,4 +297,13 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
sc.setParameters("state", State.Stopped);
return listBy(sc);
}
@Override
public Long countAllocatedVirtualRoutersForAccount(long accountId) {
SearchCriteria<Long> sc = CountVirtualRoutersByAccount.create();
sc.setParameters("account", accountId);
sc.setParameters("type", VirtualMachine.Type.DomainRouter);
sc.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging});
return customSearch(sc, null).get(0);
}
}