From e790d1174ff534a01c319c84f1634a1979f4e5ca Mon Sep 17 00:00:00 2001 From: "tian.huang" Date: Wed, 25 Mar 2026 15:50:13 +0800 Subject: [PATCH] [compute]: fix VM clone quota check fail 1.Clone a tenant VM using admin account, quota check didn't base on current role. 2.quota error is overwritten during exception handling. Resolves: ZSTAC-83646 Change-Id: I706f6d6b726b6864746867727269716a796e7677 --- .../zstack/compute/allocator/HostAllocatorChain.java | 3 +++ .../zstack/compute/allocator/QuotaAllocatorFlow.java | 7 +++++++ .../org/zstack/header/allocator/AllocateHostMsg.java | 9 +++++++++ .../org/zstack/header/allocator/HostAllocatorSpec.java | 10 ++++++++++ 4 files changed, 29 insertions(+) diff --git a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChain.java b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChain.java index 371d1dfd355..875999883e3 100755 --- a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChain.java +++ b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChain.java @@ -9,6 +9,7 @@ import org.zstack.core.db.Q; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.header.allocator.*; +import org.zstack.header.apimediator.ApiMessageInterceptionException; import org.zstack.header.core.ReturnValueCompletion; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.OperationFailureException; @@ -144,6 +145,8 @@ private void runFlow(AbstractHostAllocatorFlow flow) { } else { fail(ofe.getErrorCode()); } + } catch (ApiMessageInterceptionException e) { + fail(e.getError()); } catch (Throwable t) { logger.warn("unhandled throwable", t); String errMsg = t != null ? t.toString() : "unknown error"; diff --git a/compute/src/main/java/org/zstack/compute/allocator/QuotaAllocatorFlow.java b/compute/src/main/java/org/zstack/compute/allocator/QuotaAllocatorFlow.java index 4d9d469c796..f8d887f3bac 100644 --- a/compute/src/main/java/org/zstack/compute/allocator/QuotaAllocatorFlow.java +++ b/compute/src/main/java/org/zstack/compute/allocator/QuotaAllocatorFlow.java @@ -52,6 +52,13 @@ public void allocate() { throwExceptionIfIAmTheFirstFlow(); + // skip quota check if the operator is admin + String sessionAccountUuid = spec.getSessionAccountUuid(); + if (sessionAccountUuid != null && AccountConstant.isAdminPermission(sessionAccountUuid)) { + next(candidates); + return; + } + final String vmInstanceUuid = spec.getVmInstance().getUuid(); final String accountUuid = Account.getAccountUuidOfResource(vmInstanceUuid); if (accountUuid == null || AccountConstant.isAdminPermission(accountUuid)) { diff --git a/header/src/main/java/org/zstack/header/allocator/AllocateHostMsg.java b/header/src/main/java/org/zstack/header/allocator/AllocateHostMsg.java index 23869aa1327..c742b06e090 100755 --- a/header/src/main/java/org/zstack/header/allocator/AllocateHostMsg.java +++ b/header/src/main/java/org/zstack/header/allocator/AllocateHostMsg.java @@ -31,6 +31,7 @@ public class AllocateHostMsg extends NeedReplyMessage { private long oldMemoryCapacity = 0; private AllocationScene allocationScene; private String architecture; + private String sessionAccountUuid; public List> getOptionalPrimaryStorageUuids() { return optionalPrimaryStorageUuids; @@ -211,4 +212,12 @@ public String getArchitecture() { public void setArchitecture(String architecture) { this.architecture = architecture; } + + public String getSessionAccountUuid() { + return sessionAccountUuid; + } + + public void setSessionAccountUuid(String sessionAccountUuid) { + this.sessionAccountUuid = sessionAccountUuid; + } } diff --git a/header/src/main/java/org/zstack/header/allocator/HostAllocatorSpec.java b/header/src/main/java/org/zstack/header/allocator/HostAllocatorSpec.java index c8d8ddc3af8..5d6f5b0b915 100755 --- a/header/src/main/java/org/zstack/header/allocator/HostAllocatorSpec.java +++ b/header/src/main/java/org/zstack/header/allocator/HostAllocatorSpec.java @@ -37,6 +37,7 @@ public class HostAllocatorSpec { private long oldMemoryCapacity = 0; private AllocationScene allocationScene; private String architecture; + private String sessionAccountUuid; public AllocationScene getAllocationScene() { return allocationScene; @@ -222,6 +223,14 @@ public void setArchitecture(String architecture) { this.architecture = architecture; } + public String getSessionAccountUuid() { + return sessionAccountUuid; + } + + public void setSessionAccountUuid(String sessionAccountUuid) { + this.sessionAccountUuid = sessionAccountUuid; + } + public static HostAllocatorSpec fromAllocationMsg(AllocateHostMsg msg) { HostAllocatorSpec spec = new HostAllocatorSpec(); spec.setAllocatorStrategy(msg.getAllocatorStrategy()); @@ -250,6 +259,7 @@ public static HostAllocatorSpec fromAllocationMsg(AllocateHostMsg msg) { msg.getOptionalPrimaryStorageUuids().forEach(spec::addOptionalPrimaryStorageUuids); spec.setAllocationScene(msg.getAllocationScene()); spec.setArchitecture(msg.getArchitecture()); + spec.setSessionAccountUuid(msg.getSessionAccountUuid()); if (msg.getSystemTags() != null && !msg.getSystemTags().isEmpty()){ spec.setSystemTags(new ArrayList(msg.getSystemTags())); }