ofri masad has uploaded a new change for review. Change subject: core: Quota Monitors - backend ......................................................................
core: Quota Monitors - backend This patch is the 1st out of 3. It sets the backend support for adding Quota Monitoring to the UI. a new entity is defined "QuotaPerUserUsageEntity" - to allow passing usage data to the UI. Two new methods are added to the QuotaManager API in order to allow using the QuotaManager cache for the monitoring in the UI. Two Querier are also changed to support the new data and API Change-Id: I67770aefec191832d0c5bb69fbaba82cd0e6febb Bug-Url: https://bugzilla.redhat.com/876903 Signed-off-by: Ofri Masad <oma...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetQuotasByAdElementIdQuery.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SearchQuery.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/quota/QuotaManager.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/QuotaPerUserUsageEntity.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmBase.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/GetQuotasByAdElementIdQueryParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java 7 files changed, 427 insertions(+), 6 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/20/10120/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetQuotasByAdElementIdQuery.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetQuotasByAdElementIdQuery.java index 5cf80e4..02794a2 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetQuotasByAdElementIdQuery.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetQuotasByAdElementIdQuery.java @@ -1,6 +1,13 @@ package org.ovirt.engine.core.bll; +import org.ovirt.engine.core.bll.quota.QuotaManager; +import org.ovirt.engine.core.common.businessentities.Quota; import org.ovirt.engine.core.common.queries.GetQuotasByAdElementIdQueryParameters; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.utils.GuidUtils; + +import java.util.ArrayList; +import java.util.List; public class GetQuotasByAdElementIdQuery<P extends GetQuotasByAdElementIdQueryParameters> extends QueriesCommandBase<P> { public GetQuotasByAdElementIdQuery(P parameters) { @@ -9,8 +16,22 @@ @Override protected void executeQueryCommand() { - getQueryReturnValue().setReturnValue(getDbFacade() - .getQuotaDao() - .getQuotaByAdElementId(getParameters().getAdElementId(), getParameters().getStoragePoolId())); + if (getParameters().isIncludeUsageData()) { + List<Guid> ids = new ArrayList<Guid>(); + ids.add(getUser().getUserId()); + ids.addAll(GuidUtils.getGuidListFromString(getUser().getGroupIds())); + List<Quota> quotaList = new ArrayList<Quota>(); + for (Guid id : ids) { + quotaList.addAll(getDbFacade() + .getQuotaDao() + .getQuotaByAdElementId(id, getParameters().getStoragePoolId())); + } + getQueryReturnValue().setReturnValue(QuotaManager.getInstance().getPerUserUsageReport(quotaList, + getParameters().getVms())); + } else { + getQueryReturnValue().setReturnValue(getDbFacade() + .getQuotaDao() + .getQuotaByAdElementId(getParameters().getAdElementId(), getParameters().getStoragePoolId())); + } } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SearchQuery.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SearchQuery.java index 0a6a398..3c2c59f 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SearchQuery.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SearchQuery.java @@ -13,6 +13,7 @@ import org.ovirt.engine.core.bll.adbroker.LdapQueryDataImpl; import org.ovirt.engine.core.bll.adbroker.LdapQueryType; import org.ovirt.engine.core.bll.adbroker.LdapSearchByQueryParameters; +import org.ovirt.engine.core.bll.quota.QuotaManager; import org.ovirt.engine.core.common.businessentities.AdUser; import org.ovirt.engine.core.common.businessentities.AuditLog; import org.ovirt.engine.core.common.businessentities.DbUser; @@ -252,7 +253,9 @@ } private List<Quota> searchQuota() { - return genericSearch(getDbFacade().getQuotaDao(), true, null); + List<Quota> quotaList = genericSearch(getDbFacade().getQuotaDao(), true, null); + QuotaManager.getInstance().updateUsage(quotaList); + return quotaList; } private List<Disk> searchDisk() { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/quota/QuotaManager.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/quota/QuotaManager.java index b37ff43..1dbabf1 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/quota/QuotaManager.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/quota/QuotaManager.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.ArrayList; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.ovirt.engine.core.common.AuditLogType; @@ -12,7 +13,10 @@ import org.ovirt.engine.core.common.businessentities.QuotaStorage; import org.ovirt.engine.core.common.businessentities.QuotaVdsGroup; import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VMStatus; +import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.storage_pool; +import org.ovirt.engine.core.common.businessentities.QuotaPerUserUsageEntity; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.VdcBllMessages; @@ -740,4 +744,207 @@ } return quota; } + + /** + * REturn a list of QuotaPerUserUsageEntity representing the status of all the quotas in quotaIdsList + * + * @param quotaList + * quota list + * @return - list of QuotaPerUserUsageEntity + */ + public void updateUsage(List<Quota> quotaList) { + lock.writeLock().lock(); + try { + for (Quota quotaExternal : quotaList) { + Quota quota = null; + // look for the quota in the cache + for (Map<Guid, Quota> quotaMap : storagePoolQuotaMap.values()) { + quota = quotaMap.get(quotaExternal.getId()); + if (quota != null) { + break; + } + } + + // if quota not in cache look for it in DB and add it to cache + if (quota == null) { + quota = getQuotaDAO().getById(quotaExternal.getId()); + if (quota != null) { + if (!storagePoolQuotaMap.containsKey(quota.getStoragePoolId())) { + storagePoolQuotaMap.put(quota.getStoragePoolId(), new HashMap<Guid, Quota>()); + } + storagePoolQuotaMap.get(quota.getStoragePoolId()).put(quota.getId(), quota); + } + } + copyUsageData(quota, quotaExternal); + } + } finally { + lock.writeLock().unlock(); + } + } + + private void copyUsageData(Quota quota, Quota quotaExternal) { + if (quota.getGlobalQuotaStorage() != null) { + quotaExternal.setGlobalQuotaStorage(copyQuotaStorageUsage(quota.getGlobalQuotaStorage())); + } + if (quota.getGlobalQuotaVdsGroup() != null) { + quotaExternal.setGlobalQuotaVdsGroup(copyQuotaVdsGroupUsage(quota.getGlobalQuotaVdsGroup())); + } + + if (quota.getQuotaStorages() != null) { + quotaExternal.setQuotaStorages(new ArrayList<QuotaStorage>()); + for (QuotaStorage quotaStorage : quota.getQuotaStorages()) { + quotaExternal.getQuotaStorages().add(copyQuotaStorageUsage(quotaStorage)); + } + } + + if (quota.getQuotaVdsGroups() != null) { + quotaExternal.setQuotaVdsGroups(new ArrayList<QuotaVdsGroup>()); + for (QuotaVdsGroup quotaVdsGroup : quota.getQuotaVdsGroups()) { + quotaExternal.getQuotaVdsGroups().add(copyQuotaVdsGroupUsage(quotaVdsGroup)); + } + } + } + + private QuotaStorage copyQuotaStorageUsage(QuotaStorage quotaStorage) { + return new QuotaStorage(null, null, null, + quotaStorage.getStorageSizeGB(), + quotaStorage.getStorageSizeGBUsage()); + } + + private QuotaVdsGroup copyQuotaVdsGroupUsage(QuotaVdsGroup quotaVdsGroup) { + return new QuotaVdsGroup(null, null, null, + quotaVdsGroup.getVirtualCpu(), + quotaVdsGroup.getVirtualCpuUsage(), + quotaVdsGroup.getMemSizeMB(), + quotaVdsGroup.getMemSizeMBUsage()); + } + + /** + * Return a list of QuotaPerUserUsageEntity representing the status of all the quotas available for a specific user + * + * @param quotaIdsList + * - quotas available for user + * @param vms + * - vm available for user + * @return - list of QuotaPerUserUsageEntity + */ + public List<QuotaPerUserUsageEntity> getPerUserUsageReport(List<Quota> quotaIdsList, List<VM> vms) { + Map<Guid, QuotaPerUserUsageEntity> quotaPerUserUsageEntityMap = new HashMap<Guid, QuotaPerUserUsageEntity>(); + + lock.writeLock().lock(); + try { + for (Quota externalQuota : quotaIdsList) { + Guid quotaId = externalQuota.getId(); + Quota quota = null; + // look for the quota in the cache + for (Map<Guid, Quota> quotaMap : storagePoolQuotaMap.values()) { + + quota = quotaMap.get(quotaId); + if (quota != null) { + break; + } + } + + // if quota not in cache look for it in DB and add it to cache + if (quota == null) { + quota = getQuotaDAO().getById(quotaId); + if (quota != null) { + if (!storagePoolQuotaMap.containsKey(quota.getStoragePoolId())) { + storagePoolQuotaMap.put(quota.getStoragePoolId(), new HashMap<Guid, Quota>()); + } + storagePoolQuotaMap.get(quota.getStoragePoolId()).put(quota.getId(), quota); + } + } + QuotaPerUserUsageEntity newEntity = addQuotaEntry(quota); + if (newEntity != null) { + quotaPerUserUsageEntityMap.put(quotaId, newEntity); + } + } + } finally { + lock.writeLock().unlock(); + } + + countPersonalUsage(vms, quotaPerUserUsageEntityMap); + + return new ArrayList<QuotaPerUserUsageEntity>(quotaPerUserUsageEntityMap.values()); + } + + private void countPersonalUsage(List<VM> vms, Map<Guid, QuotaPerUserUsageEntity> quotaPerUserUsageEntityMap) { + for (VM vm : vms) { + // if vm is running and have a quota + if (vm.getStatus() != VMStatus.Down + && vm.getStatus() != VMStatus.Suspended + && vm.getStatus() != VMStatus.ImageIllegal + && vm.getStatus() != VMStatus.ImageLocked + && vm.getStatus() != VMStatus.PoweringDown + && vm.getQuotaId() != null) { + QuotaPerUserUsageEntity quotaPerUserUsageEntity = quotaPerUserUsageEntityMap.get(vm.getQuotaId()); + // add the vm cpu and mem to the user quota consumption + if (quotaPerUserUsageEntity != null) { + quotaPerUserUsageEntity.setMemoryUsageForUser(quotaPerUserUsageEntity.getMemoryUsageForUser() + + vm.getMemSizeMb()); + quotaPerUserUsageEntity.setVcpuUsageForUser(quotaPerUserUsageEntity.getVcpuUsageForUser() + + vm.getCpuPerSocket() * vm.getNumOfSockets()); + } + } + // for each image of each disk of the vm - if it has a quota + for (DiskImage image : vm.getDiskList()) { + QuotaPerUserUsageEntity quotaPerUserUsageEntity = quotaPerUserUsageEntityMap.get(image.getQuotaId()); + double imageSize = image.getImage().isActive() ? image.getSizeInGigabytes() : image.getActualSize(); + // add the disk size to the user storage consumption + if (quotaPerUserUsageEntity != null) { + quotaPerUserUsageEntity.setStorageUsageForUser(quotaPerUserUsageEntity.getStorageUsageForUser() + + imageSize); + } + } + } + } + + private QuotaPerUserUsageEntity addQuotaEntry(Quota quota) { + // if quota is not null (found in cache or DB) - add entry to quotaPerUserUsageEntityMap + if (quota != null) { + double storageLimit = 0; + double storageUsage = 0; + int cpuLimit = 0; + int cpuUsage = 0; + long memLimit = 0; + long memUsage = 0; + + // calc storage + if (quota.getGlobalQuotaStorage() != null) { + storageLimit = quota.getGlobalQuotaStorage().getStorageSizeGB(); + storageUsage = quota.getGlobalQuotaStorage().getStorageSizeGBUsage(); + } else { + for (QuotaStorage quotaStorage : quota.getQuotaStorages()) { + storageLimit += quotaStorage.getStorageSizeGB(); + storageUsage += quotaStorage.getStorageSizeGBUsage(); + } + } + + // calc cpu and mem + if (quota.getGlobalQuotaVdsGroup() != null) { + memLimit = quota.getGlobalQuotaVdsGroup().getMemSizeMB(); + memUsage = quota.getGlobalQuotaVdsGroup().getMemSizeMBUsage(); + cpuLimit = quota.getGlobalQuotaVdsGroup().getVirtualCpu(); + cpuUsage = quota.getGlobalQuotaVdsGroup().getVirtualCpuUsage(); + } else { + for (QuotaVdsGroup quotaVdsGroup : quota.getQuotaVdsGroups()) { + memLimit += quotaVdsGroup.getMemSizeMB(); + memUsage += quotaVdsGroup.getMemSizeMBUsage(); + cpuLimit += quotaVdsGroup.getVirtualCpu(); + cpuUsage += quotaVdsGroup.getVirtualCpuUsage(); + } + } + + return new QuotaPerUserUsageEntity(quota.getId(), + quota.getQuotaName(), + storageLimit, + storageUsage, + cpuLimit, + cpuUsage, + memLimit, + memUsage); + } + return null; + } } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/QuotaPerUserUsageEntity.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/QuotaPerUserUsageEntity.java new file mode 100644 index 0000000..e9fd99d --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/QuotaPerUserUsageEntity.java @@ -0,0 +1,168 @@ +package org.ovirt.engine.core.common.businessentities; +import org.ovirt.engine.core.compat.Guid; + +import java.io.Serializable; + +public class QuotaPerUserUsageEntity extends IVdcQueryable implements Serializable { + + private Guid quotaId; + private String quotaName; + private double storageLimit; + private double storageTotalUsage; + private double storageUsageForUserGB = 0; + private int vcpuLimit; + private int vcpuTotalUsage; + private int vcpuUsageForUser = 0; + private long memoryLimit; + private long memoryTotalUsage; + private long memoryUsageForUser = 0; + + public QuotaPerUserUsageEntity(){ + + } + + public QuotaPerUserUsageEntity(Guid quotaId, String quotaName, double storageLimit, double storageTotalUsage, int vcpuLimit, int vcpuTotalUsage, long memoryLimit, long memoryTotalUsage) { + this.quotaId = quotaId; + this.quotaName = quotaName; + this.storageLimit = storageLimit; + this.storageTotalUsage = storageTotalUsage; + this.vcpuLimit = vcpuLimit; + this.vcpuTotalUsage = vcpuTotalUsage; + this.memoryLimit = memoryLimit; + this.memoryTotalUsage = memoryTotalUsage; + } + + + public double getStorageUsageForUser() { + return storageUsageForUserGB; + } + + public void setStorageUsageForUser(double storageUsageForUserGB) { + this.storageUsageForUserGB = storageUsageForUserGB; + } + + public int getVcpuUsageForUser() { + return vcpuUsageForUser; + } + + public void setVcpuUsageForUser(int vcpuUsageForUser) { + this.vcpuUsageForUser = vcpuUsageForUser; + } + + public long getMemoryUsageForUser() { + return memoryUsageForUser; + } + + public void setMemoryUsageForUser(long memoryUsageForUser) { + this.memoryUsageForUser = memoryUsageForUser; + } + + public Guid getQuotaId() { + return quotaId; + } + + public double getStorageLimit() { + return storageLimit; + } + + public double getStorageTotalUsage() { + return storageTotalUsage; + } + + public int getVcpuLimit() { + return vcpuLimit; + } + + public int getVcpuTotalUsage() { + return vcpuTotalUsage; + } + + public long getMemoryLimit() { + return memoryLimit; + } + + public long getMemoryTotalUsage() { + return memoryTotalUsage; + } + + public double getUserStorageUsagePercentage() { + return storageUsageForUserGB*100/storageLimit; + } + + public double getUserVcpuUsagePercentage() { + return (double)vcpuUsageForUser*100/vcpuLimit; + } + + public double getUserMemoryUsagePercentage() { + return (double)memoryUsageForUser*100/memoryLimit; + } + + public double getOthersStorageUsagePercentage() { + return (storageTotalUsage-storageUsageForUserGB)*100/storageLimit; + } + + public double getOthersVcpuUsagePercentage() { + return (double)(vcpuTotalUsage-vcpuUsageForUser)*100/vcpuLimit; + } + + public double getOthersMemoryUsagePercentage() { + return (double)(memoryTotalUsage-memoryUsageForUser)*100/memoryLimit; + } + + public int getFreeVcpu() { + return vcpuLimit-vcpuTotalUsage; + } + + public long getFreeMemory() { + return memoryLimit-memoryTotalUsage; + } + + public double getFreeStorage() { + return storageLimit-storageTotalUsage; + } + + @Override + public Object getQueryableId() { + return getQuotaId(); + } + + public String getQuotaName() { + return quotaName; + } + + public void setStorageLimit(double storageLimit) { + this.storageLimit = storageLimit; + } + + public void setStorageTotalUsage(double storageTotalUsage) { + this.storageTotalUsage = storageTotalUsage; + } + + public void setVcpuLimit(int vcpuLimit) { + this.vcpuLimit = vcpuLimit; + } + + public void setVcpuTotalUsage(int vcpuTotalUsage) { + this.vcpuTotalUsage = vcpuTotalUsage; + } + + public void setMemoryLimit(long memoryLimit) { + this.memoryLimit = memoryLimit; + } + + public void setMemoryTotalUsage(long memoryTotalUsage) { + this.memoryTotalUsage = memoryTotalUsage; + } + + public boolean isUnlimitedVcpu() { + return vcpuLimit == QuotaVdsGroup.UNLIMITED_VCPU; + } + + public boolean isUnlimitedMemory() { + return memoryLimit == QuotaVdsGroup.UNLIMITED_MEM; + } + + public boolean isUnlimitedStorage() { + return storageLimit == QuotaStorage.UNLIMITED; + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmBase.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmBase.java index 398decb..371fe71 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmBase.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmBase.java @@ -29,7 +29,7 @@ public class VmBase extends IVdcQueryable implements INotifyPropertyChanged, BusinessEntity<Guid> { private static final long serialVersionUID = 1078548170257965614L; private ArrayList<DiskImage> images; - private final ArrayList<DiskImage> diskList = new ArrayList<DiskImage>(); + private ArrayList<DiskImage> diskList = new ArrayList<DiskImage>(); private List<VmNetworkInterface> interfaces; private Map<Guid, VmDevice> vmManagedDeviceMap = new HashMap<Guid, VmDevice>(); private List<VmDevice> vmUnManagedDeviceList = new ArrayList<VmDevice>(); diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/GetQuotasByAdElementIdQueryParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/GetQuotasByAdElementIdQueryParameters.java index c1bea94..149ce6a 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/GetQuotasByAdElementIdQueryParameters.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/GetQuotasByAdElementIdQueryParameters.java @@ -1,6 +1,9 @@ package org.ovirt.engine.core.common.queries; +import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.compat.Guid; + +import java.util.List; public class GetQuotasByAdElementIdQueryParameters extends VdcQueryParametersBase { @@ -10,6 +13,8 @@ private static final long serialVersionUID = 4072642442090555682L; private Guid adElementId; private Guid storagePoolId; + private boolean includeUsageData; + private List<VM> vms; public void setAdElementId(Guid adElementId) { this.adElementId = adElementId; @@ -26,4 +31,21 @@ public void setStoragePoolId(Guid storagePoolId) { this.storagePoolId = storagePoolId; } + + + public boolean isIncludeUsageData() { + return includeUsageData; + } + + public void setIncludeUsageData(boolean includeUsageData) { + this.includeUsageData = includeUsageData; + } + + public List<VM> getVms() { + return vms; + } + + public void setVms(List<VM> vms) { + this.vms = vms; + } } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java index b783d5b..bf63110 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java @@ -262,7 +262,7 @@ GetVmsRelatedToQuotaId, GetTemplatesRelatedToQuotaId, GetPermissionsToConsumeQuotaByQuotaId, - GetQuotasByAdElementId, + GetQuotasByAdElementId(VdcQueryAuthType.User), GetAllRelevantQuotasForStorage(VdcQueryAuthType.User), GetAllRelevantQuotasForVdsGroup(VdcQueryAuthType.User), -- To view, visit http://gerrit.ovirt.org/10120 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I67770aefec191832d0c5bb69fbaba82cd0e6febb Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: ofri masad <oma...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches