From b09e5a17eff9e0a926c77070b1718db6350e5d70 Mon Sep 17 00:00:00 2001 From: Aaron Chung Date: Fri, 20 Mar 2026 11:44:04 +0900 Subject: [PATCH] Move checkRoleEscalation outside DB transaction in createAccount The read-only role escalation check iterates all API commands and does not need a write transaction open. Using a transient AccountVO for the check avoids holding the DB connection during the permission scan, reducing connection pool pressure and API latency. --- .../java/com/cloud/user/AccountManagerImpl.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index e01137cffbc2..c485aae87ec9 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -1341,20 +1341,19 @@ public UserAccount createUserAccount(final String userName, final String passwor final String accountNameFinal = accountName; final Long domainIdFinal = domainId; - final String accountUUIDFinal = accountUUID; + final String resolvedAccountUUID = accountUUID != null ? accountUUID : UUID.randomUUID().toString(); + + // Check role escalation before the transaction — this is a read-only check + // that iterates all API commands and doesn't need a write transaction open. + AccountVO requestedAccount = new AccountVO(accountNameFinal, domainIdFinal, networkDomain, accountType, roleId, resolvedAccountUUID); + checkRoleEscalation(getCurrentCallingAccount(), requestedAccount); + Pair pair = Transaction.execute(new TransactionCallback<>() { @Override public Pair doInTransaction(TransactionStatus status) { - // create account - String accountUUID = accountUUIDFinal; - if (accountUUID == null) { - accountUUID = UUID.randomUUID().toString(); - } - AccountVO account = createAccount(accountNameFinal, accountType, roleId, domainIdFinal, networkDomain, details, accountUUID); + AccountVO account = createAccount(accountNameFinal, accountType, roleId, domainIdFinal, networkDomain, details, resolvedAccountUUID); long accountId = account.getId(); - checkRoleEscalation(getCurrentCallingAccount(), account); - // create the first user for the account UserVO user = createUser(accountId, userName, password, firstName, lastName, email, timezone, userUUID, source);