Skip to content

Commit c938bd1

Browse files
committed
framework,api,server,ui: improve error messaging
Framwork level improvements for for contextual and localized API error messages More details to be added Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent 8936e4c commit c938bd1

File tree

24 files changed

+473
-104
lines changed

24 files changed

+473
-104
lines changed

api/src/main/java/com/cloud/exception/InvalidParameterValueException.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
// under the License.
1717
package com.cloud.exception;
1818

19+
import java.util.Map;
20+
21+
import org.apache.cloudstack.context.ErrorMessageResolver;
22+
1923
import com.cloud.utils.exception.CloudRuntimeException;
2024

2125
public class InvalidParameterValueException extends CloudRuntimeException {
@@ -26,4 +30,8 @@ public InvalidParameterValueException(String message) {
2630
super(message);
2731
}
2832

33+
public InvalidParameterValueException(String key, Map<String, Object> metadata) {
34+
super(ErrorMessageResolver.getMessage(key, metadata), key, metadata);
35+
}
36+
2937
}

api/src/main/java/com/cloud/user/AccountService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22-
import com.cloud.utils.Pair;
2322
import org.apache.cloudstack.acl.ControlledEntity;
2423
import org.apache.cloudstack.acl.RoleType;
2524
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
2625
import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd;
2726
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
2827
import org.apache.cloudstack.api.command.admin.user.RegisterUserKeyCmd;
2928
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
29+
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
3030

3131
import com.cloud.dc.DataCenter;
3232
import com.cloud.domain.Domain;
@@ -35,7 +35,7 @@
3535
import com.cloud.offering.DiskOffering;
3636
import com.cloud.offering.NetworkOffering;
3737
import com.cloud.offering.ServiceOffering;
38-
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
38+
import com.cloud.utils.Pair;
3939

4040
public interface AccountService {
4141

@@ -85,6 +85,8 @@ User createUser(String userName, String password, String firstName, String lastN
8585

8686
boolean isRootAdmin(Long accountId);
8787

88+
boolean isRootAdmin(Account account);
89+
8890
boolean isDomainAdmin(Long accountId);
8991

9092
boolean isResourceDomainAdmin(Long accountId);

api/src/main/java/org/apache/cloudstack/api/command/user/vm/BaseDeployVMCmd.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,8 @@ private Long getNetworkIdFomIpMap(HashMap<String, String> ips) {
648648
try {
649649
networkId = Long.parseLong(networkid);
650650
} catch (NumberFormatException e) {
651-
throw new InvalidParameterValueException("Unable to translate and find entity with networkId: " + networkid);
651+
throw new InvalidParameterValueException("vm.deploy.network.not.found.ip.map",
652+
Map.of("networkId", networkid));
652653
}
653654
}
654655
return networkId;

api/src/main/java/org/apache/cloudstack/api/response/ExceptionResponse.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.List;
21-
22-
import com.google.gson.annotations.SerializedName;
21+
import java.util.Map;
2322

2423
import org.apache.cloudstack.api.BaseResponse;
2524

2625
import com.cloud.serializer.Param;
2726
import com.cloud.utils.exception.ExceptionProxyObject;
27+
import com.google.gson.annotations.SerializedName;
2828

2929
public class ExceptionResponse extends BaseResponse {
3030

@@ -44,6 +44,14 @@ public class ExceptionResponse extends BaseResponse {
4444
@Param(description = "the text associated with this error")
4545
private String errorText = "Command failed due to Internal Server Error";
4646

47+
@SerializedName("errortextkey")
48+
@Param(description = "the key for the text associated with this error")
49+
private String errorTextKey = "";
50+
51+
@SerializedName("errormetadata")
52+
@Param(description = "the metadata associated with this error")
53+
private Map<String, String> errorMetadata;
54+
4755
public ExceptionResponse() {
4856
idList = new ArrayList<ExceptionProxyObject>();
4957
}
@@ -64,6 +72,22 @@ public void setErrorText(String errorText) {
6472
this.errorText = errorText;
6573
}
6674

75+
public String getErrorTextKey() {
76+
return errorTextKey;
77+
}
78+
79+
public void setErrorTextKey(String errorTextKey) {
80+
this.errorTextKey = errorTextKey;
81+
}
82+
83+
public Map<String, String> getErrorMetadata() {
84+
return errorMetadata;
85+
}
86+
87+
public void setErrorMetadata(Map<String, String> errorMetadata) {
88+
this.errorMetadata = errorMetadata;
89+
}
90+
6791
public void addProxyObject(ExceptionProxyObject id) {
6892
idList.add(id);
6993
return;

api/src/main/java/org/apache/cloudstack/context/CallContext.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,20 @@
2323

2424
import org.apache.cloudstack.api.ApiCommandResourceType;
2525
import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal;
26-
import org.apache.logging.log4j.Logger;
2726
import org.apache.logging.log4j.LogManager;
27+
import org.apache.logging.log4j.Logger;
28+
import org.apache.logging.log4j.ThreadContext;
29+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
2830

2931
import com.cloud.exception.CloudAuthenticationException;
3032
import com.cloud.projects.Project;
3133
import com.cloud.user.Account;
34+
import com.cloud.user.AccountService;
3235
import com.cloud.user.User;
3336
import com.cloud.utils.UuidUtils;
37+
import com.cloud.utils.component.ComponentContext;
3438
import com.cloud.utils.db.EntityManager;
3539
import com.cloud.utils.exception.CloudRuntimeException;
36-
import org.apache.logging.log4j.ThreadContext;
3740

3841
/**
3942
* CallContext records information about the environment the call is made. This
@@ -53,6 +56,7 @@ protected Stack<CallContext> initialValue() {
5356
private String contextId;
5457
private Account account;
5558
private long accountId;
59+
private Boolean isAccountRootAdmin = null;
5660
private long startEventId = 0;
5761
private String eventDescription;
5862
private String eventDetails;
@@ -134,6 +138,21 @@ public Account getCallingAccount() {
134138
return account;
135139
}
136140

141+
public boolean isCallingAccountRootAdmin() {
142+
if (isAccountRootAdmin == null) {
143+
AccountService accountService;
144+
try {
145+
accountService = ComponentContext.getDelegateComponentOfType(AccountService.class);
146+
} catch (NoSuchBeanDefinitionException e) {
147+
LOGGER.warn("Falling back to account type check for isRootAdmin for account ID: {} as no AccountService bean found: {}", accountId, e.getMessage());
148+
Account caller = getCallingAccount();
149+
return caller != null && caller.getType() == Account.Type.ADMIN;
150+
}
151+
isAccountRootAdmin = accountService.isRootAdmin(getCallingAccount());
152+
}
153+
return Boolean.TRUE.equals(isAccountRootAdmin);
154+
}
155+
137156
public static CallContext current() {
138157
CallContext context = s_currentContext.get();
139158

0 commit comments

Comments
 (0)