Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.springframework.beans.factory.annotation.Configurable;
import org.zstack.compute.vm.VmQuotaOperator;
import org.zstack.header.allocator.AbstractHostAllocatorFlow;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.identity.AccountConstant;
import org.zstack.identity.Account;
import org.zstack.identity.QuotaUtil;
Expand Down Expand Up @@ -51,6 +53,12 @@ public void allocate() {
}

throwExceptionIfIAmTheFirstFlow();
// skip checkquota if the operator is admin
String currentAccountUuid = spec.getAccountUuid();
if (currentAccountUuid != null && AccountConstant.isAdminPermission(currentAccountUuid)) {
next(candidates);
return;
}

final String vmInstanceUuid = spec.getVmInstance().getUuid();
final String accountUuid = Account.getAccountUuidOfResource(vmInstanceUuid);
Expand All @@ -60,21 +68,27 @@ public void allocate() {
}

if (!spec.isFullAllocate()) {
new VmQuotaOperator().checkVmCupAndMemoryCapacity(accountUuid,
ErrorCode error = new VmQuotaOperator().checkVmCupAndMemoryCapacityWithResult(accountUuid,
accountUuid,
spec.getCpuCapacity(),
spec.getMemoryCapacity(),
new QuotaUtil().makeQuotaPairs(accountUuid));
if (error != null) {
throw new OperationFailureException(error);
}

next(candidates);
return;
}

new VmQuotaOperator().checkVmInstanceQuota(
ErrorCode error = new VmQuotaOperator().checkVmInstanceQuotaWithResult(
accountUuid,
accountUuid,
vmInstanceUuid,
new QuotaUtil().makeQuotaPairs(accountUuid));
if (error != null) {
throw new OperationFailureException(error);
}
next(candidates);
}
}
71 changes: 56 additions & 15 deletions compute/src/main/java/org/zstack/compute/vm/VmQuotaOperator.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.zstack.core.db.SimpleQuery;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.apimediator.ApiMessageInterceptionException;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.identity.APIChangeResourceOwnerMsg;
import org.zstack.header.identity.AccountType;
import org.zstack.header.identity.Quota;
Expand Down Expand Up @@ -151,12 +152,27 @@ private void checkTotalVMQuota(String currentAccountUuid,
String vmInstanceUuid,
long totalVmNumQuota,
long totalVmNum) {
ErrorCode error = checkTotalVMQuotaWithResult(currentAccountUuid,
resourceTargetOwnerAccountUuid,
vmInstanceUuid,
totalVmNumQuota,
totalVmNum);
if (error != null) {
throw new ApiMessageInterceptionException(error);
}
}

private ErrorCode checkTotalVMQuotaWithResult(String currentAccountUuid,
String resourceTargetOwnerAccountUuid,
String vmInstanceUuid,
long totalVmNumQuota,
long totalVmNum) {
if (Q.New(VmInstanceVO.class)
.eq(VmInstanceVO_.uuid, vmInstanceUuid)
.notNull(VmInstanceVO_.lastHostUuid)
.isExists()) {
// Dirty hack - VM with last host UUID means existing VM.
return;
return null;
}

QuotaUtil.QuotaCompareInfo quotaCompareInfo;
Expand All @@ -167,18 +183,17 @@ private void checkTotalVMQuota(String currentAccountUuid,
quotaCompareInfo.quotaValue = totalVmNumQuota;
quotaCompareInfo.currentUsed = totalVmNum;
quotaCompareInfo.request = 1;
new QuotaUtil().CheckQuota(quotaCompareInfo);
return new QuotaUtil().checkQuotaAndReturn(quotaCompareInfo);
}

@Transactional(readOnly = true)
public void checkVmInstanceQuota(String currentAccountUuid,
String resourceTargetOwnerAccountUuid,
String vmInstanceUuid,
Map<String, Quota.QuotaPair> pairs) {
public ErrorCode checkVmInstanceQuotaWithResult(String currentAccountUuid,
String resourceTargetOwnerAccountUuid,
String vmInstanceUuid,
Map<String, Quota.QuotaPair> pairs) {
long vmNumQuota = pairs.get(VmQuotaConstant.VM_RUNNING_NUM).getValue();

VmQuotaUtil.VmQuota vmQuotaUsed = new VmQuotaUtil().getUsedVmCpuMemory(resourceTargetOwnerAccountUuid, null);
//
{
QuotaUtil.QuotaCompareInfo quotaCompareInfo;
quotaCompareInfo = new QuotaUtil.QuotaCompareInfo();
Expand All @@ -188,22 +203,38 @@ public void checkVmInstanceQuota(String currentAccountUuid,
quotaCompareInfo.quotaValue = vmNumQuota;
quotaCompareInfo.currentUsed = vmQuotaUsed.runningVmNum;
quotaCompareInfo.request = 1;
new QuotaUtil().CheckQuota(quotaCompareInfo);
ErrorCode error = new QuotaUtil().checkQuotaAndReturn(quotaCompareInfo);
if (error != null) {
return error;
}
}
//
checkTotalVMQuota(currentAccountUuid,

ErrorCode error = checkTotalVMQuotaWithResult(currentAccountUuid,
resourceTargetOwnerAccountUuid,
vmInstanceUuid,
pairs.get(VmQuotaConstant.VM_TOTAL_NUM).getValue(),
vmQuotaUsed.totalVmNum);
//
if (error != null) {
return error;
}

VmInstanceVO vm = dbf.getEntityManager().find(VmInstanceVO.class, vmInstanceUuid);

checkVmCupAndMemoryCapacity(currentAccountUuid, resourceTargetOwnerAccountUuid, vm.getCpuNum(), vm.getMemorySize(), pairs);
return checkVmCupAndMemoryCapacityWithResult(currentAccountUuid, resourceTargetOwnerAccountUuid, vm.getCpuNum(), vm.getMemorySize(), pairs);
}

public void checkVmInstanceQuota(String currentAccountUuid,
String resourceTargetOwnerAccountUuid,
String vmInstanceUuid,
Map<String, Quota.QuotaPair> pairs) {
ErrorCode error = checkVmInstanceQuotaWithResult(currentAccountUuid, resourceTargetOwnerAccountUuid, vmInstanceUuid, pairs);
if (error != null) {
throw new ApiMessageInterceptionException(error);
}
}

@Transactional(readOnly = true)
public void checkVmCupAndMemoryCapacity(String currentAccountUuid, String resourceTargetOwnerAccountUuid, long cpu, long memory, Map<String, Quota.QuotaPair> pairs) {
public ErrorCode checkVmCupAndMemoryCapacityWithResult(String currentAccountUuid, String resourceTargetOwnerAccountUuid, long cpu, long memory, Map<String, Quota.QuotaPair> pairs) {
VmQuotaUtil.VmQuota vmQuotaUsed = new VmQuotaUtil().getUsedVmCpuMemory(resourceTargetOwnerAccountUuid);
long cpuNumQuota = pairs.get(VmQuotaConstant.VM_RUNNING_CPU_NUM).getValue();
long memoryQuota = pairs.get(VmQuotaConstant.VM_RUNNING_MEMORY_SIZE).getValue();
Expand All @@ -217,7 +248,10 @@ public void checkVmCupAndMemoryCapacity(String currentAccountUuid, String resour
quotaCompareInfo.quotaValue = cpuNumQuota;
quotaCompareInfo.currentUsed = vmQuotaUsed.runningVmCpuNum;
quotaCompareInfo.request = cpu;
new QuotaUtil().CheckQuota(quotaCompareInfo);
ErrorCode error = new QuotaUtil().checkQuotaAndReturn(quotaCompareInfo);
if (error != null) {
return error;
}
}
{
QuotaUtil.QuotaCompareInfo quotaCompareInfo;
Expand All @@ -228,7 +262,14 @@ public void checkVmCupAndMemoryCapacity(String currentAccountUuid, String resour
quotaCompareInfo.quotaValue = memoryQuota;
quotaCompareInfo.currentUsed = vmQuotaUsed.runningVmMemorySize;
quotaCompareInfo.request = memory;
new QuotaUtil().CheckQuota(quotaCompareInfo);
return new QuotaUtil().checkQuotaAndReturn(quotaCompareInfo);
}
}

public void checkVmCupAndMemoryCapacity(String currentAccountUuid, String resourceTargetOwnerAccountUuid, long cpu, long memory, Map<String, Quota.QuotaPair> pairs) {
ErrorCode error = checkVmCupAndMemoryCapacityWithResult(currentAccountUuid, resourceTargetOwnerAccountUuid, cpu, memory, pairs);
if (error != null) {
throw new ApiMessageInterceptionException(error);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class AllocateHostMsg extends NeedReplyMessage {
private long oldMemoryCapacity = 0;
private AllocationScene allocationScene;
private String architecture;
private String accountUuid;

public List<Set<String>> getOptionalPrimaryStorageUuids() {
return optionalPrimaryStorageUuids;
Expand Down Expand Up @@ -211,4 +212,8 @@ public String getArchitecture() {
public void setArchitecture(String architecture) {
this.architecture = architecture;
}

public String getAccountUuid() { return accountUuid; }

public void setAccountUuid(String accountUuid) { this.accountUuid = accountUuid; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class HostAllocatorSpec {
private long oldMemoryCapacity = 0;
private AllocationScene allocationScene;
private String architecture;
private String accountUuid;

public AllocationScene getAllocationScene() {
return allocationScene;
Expand Down Expand Up @@ -161,7 +162,13 @@ public List<String> getL3NetworkUuids() {
}
return l3NetworkUuids;
}
public String getAccountUuid() {
return accountUuid;
}

public void setAccountUuid(String accountUuid) {
this.accountUuid = accountUuid;
}
public void setL3NetworkUuids(List<String> l3NetworkUuids) {
this.l3NetworkUuids = l3NetworkUuids;
}
Expand Down Expand Up @@ -250,6 +257,7 @@ public static HostAllocatorSpec fromAllocationMsg(AllocateHostMsg msg) {
msg.getOptionalPrimaryStorageUuids().forEach(spec::addOptionalPrimaryStorageUuids);
spec.setAllocationScene(msg.getAllocationScene());
spec.setArchitecture(msg.getArchitecture());
spec.setAccountUuid(msg.getAccountUuid());
if (msg.getSystemTags() != null && !msg.getSystemTags().isEmpty()){
spec.setSystemTags(new ArrayList<String>(msg.getSystemTags()));
}
Expand Down
15 changes: 12 additions & 3 deletions identity/src/main/java/org/zstack/identity/QuotaUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,31 @@ public String getResourceOwnerAccountUuid(String resourceUuid) {
}

@Transactional(readOnly = true)
public void CheckQuota(QuotaCompareInfo quotaCompareInfo) {
public ErrorCode checkQuotaAndReturn(QuotaCompareInfo quotaCompareInfo) {
logger.trace(String.format("dump quota QuotaCompareInfo: \n %s",
JSONObjectUtil.toJsonString(quotaCompareInfo)));
String accountName = Q.New(AccountVO.class)
.select(AccountVO_.name)
.eq(AccountVO_.uuid, quotaCompareInfo.resourceTargetOwnerAccountUuid)
.findValue();
if (quotaCompareInfo.currentUsed + quotaCompareInfo.request > quotaCompareInfo.quotaValue) {
throw new ApiMessageInterceptionException(err(ORG_ZSTACK_IDENTITY_10002, IdentityErrors.QUOTA_EXCEEDING,
return err(ORG_ZSTACK_IDENTITY_10002, IdentityErrors.QUOTA_EXCEEDING,
"quota exceeding." +
"The resource owner(or target resource owner) account[uuid: %s name: %s] exceeds a quota[name: %s, value: %s], " +
"Current used:%s, Request:%s. Please contact the administrator.",
quotaCompareInfo.resourceTargetOwnerAccountUuid, StringUtils.trimToEmpty(accountName),
quotaCompareInfo.quotaName, quotaCompareInfo.quotaValue,
quotaCompareInfo.currentUsed, quotaCompareInfo.request
));
);
}

return null;
}

public void CheckQuota(QuotaCompareInfo quotaCompareInfo) {
ErrorCode error = checkQuotaAndReturn(quotaCompareInfo);
if (error != null) {
throw new ApiMessageInterceptionException(error);
}
}

Expand Down