handle resourceallocationexception

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2026-01-06 13:31:47 +05:30
parent 1036df831f
commit 6878f49d97
6 changed files with 78 additions and 24 deletions

View File

@ -22,32 +22,34 @@ public interface Resource {
String UNLIMITED = "Unlimited";
enum ResourceType { // All storage type resources are allocated_storage and not the physical storage.
user_vm("user_vm", 0),
public_ip("public_ip", 1),
volume("volume", 2),
snapshot("snapshot", 3),
template("template", 4),
project("project", 5),
network("network", 6),
vpc("vpc", 7),
cpu("cpu", 8),
memory("memory", 9),
primary_storage("primary_storage", 10),
secondary_storage("secondary_storage", 11),
backup("backup", 12),
backup_storage("backup_storage", 13),
bucket("bucket", 14),
object_storage("object_storage", 15),
gpu("gpu", 16);
user_vm("user_vm", "Instance", 0),
public_ip("public_ip", "Public IP", 1),
volume("volume", "Volume", 2),
snapshot("snapshot", "Snapshot", 3),
template("template", "Template", 4),
project("project", "Project", 5),
network("network", "Network", 6),
vpc("vpc", "VPC", 7),
cpu("cpu", "CPU", 8),
memory("memory", "Memory", 9),
primary_storage("primary_storage", "Primary Storage", 10),
secondary_storage("secondary_storage", "Secondary Storage", 11),
backup("backup", "Backup", 12),
backup_storage("backup_storage", "Backup Storage", 13),
bucket("bucket", "Bucket", 14),
object_storage("object_storage", "Object Storage", 15),
gpu("gpu", "GPU", 16);
private String name;
private String displayName;
private int ordinal;
public static final long bytesToKiB = 1024;
public static final long bytesToMiB = bytesToKiB * 1024;
public static final long bytesToGiB = bytesToMiB * 1024;
ResourceType(String name, int ordinal) {
ResourceType(String name, String displayName, int ordinal) {
this.name = name;
this.displayName = displayName;
this.ordinal = ordinal;
}
@ -55,6 +57,10 @@ public interface Resource {
return name;
}
public String getDisplayName() {
return displayName;
}
public int getOrdinal() {
return ordinal;
}

View File

@ -17,6 +17,9 @@
package org.apache.cloudstack.api;
import java.util.ArrayList;
import java.util.Map;
import org.apache.cloudstack.context.ErrorMessageResolver;
import com.cloud.exception.CloudException;
import com.cloud.utils.exception.CSExceptionErrorCode;
@ -34,6 +37,14 @@ public class ServerApiException extends CloudRuntimeException {
setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ServerApiException.class.getName()));
}
public ServerApiException(ApiErrorCode errorCode, String messageKey, Map<String, Object> errorMetadata) {
_errorCode = errorCode;
this.messageKey = messageKey;
this.metadata = errorMetadata;
_description = ErrorMessageResolver.getMessage(messageKey, errorMetadata);
setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ServerApiException.class.getName()));
}
public ServerApiException(ApiErrorCode errorCode, String description) {
_errorCode = errorCode;
_description = description;

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.api.command.user.vm;
import java.util.Collections;
import java.util.Objects;
import java.util.stream.Stream;
@ -157,7 +158,18 @@ public class DeployVMCmd extends BaseDeployVMCmd {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
} catch (ResourceAllocationException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
handleCreateResourceAllocationException(ex);
}
}
protected void handleCreateResourceAllocationException(ResourceAllocationException ex) {
if (ex.getMessage() != null && ex.getMessage().startsWith("Maximum amount")) {
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR,
"vm.deploy.resourcelimit.exceeded.account", Collections.emptyMap());
} else if (ex.getMessage() != null && ex.getMessage().startsWith("Maximum domain resource limits")) {
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR,
"vm.deploy.resourcelimit.exceeded.domain", Collections.emptyMap());
}
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
}
}

View File

@ -39,7 +39,6 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import com.fasterxml.jackson.core.type.TypeReference;
@ -287,12 +286,15 @@ public class ErrorMessageResolver {
if (key == null) {
Throwable cause = cre.getCause();
if (!(cause instanceof InvalidParameterValueException)) {
if (!(cause instanceof CloudRuntimeException)) {
return;
}
InvalidParameterValueException ipve = (InvalidParameterValueException) cause;
key = ipve.getMessageKey();
map = ipve.getMetadata();
CloudRuntimeException causeEx = (CloudRuntimeException) cause;
key = causeEx.getMessageKey();
if (key == null) {
return;
}
map = causeEx.getMetadata();
}
response.setErrorTextKey(key);
String template = getTemplateForKey(key);

View File

@ -5,6 +5,10 @@
"vm.deploy.diskoffering.with.diskoffering.details": "Unable to deploy Instance as both a disk offering ID and data disk offering details were provided. Specify only one.",
"vm.deploy.hypervisor.volume.snapshot.not.supported": "Unable to deploy Instance because deployment from an existing volume or snapshot is supported only on the KVM hypervisor.",
"vm.deploy.network.not.found.ip.map": "The network selected {{networkId}} in IP to network map could not be found. It may have been removed or is no longer accessible.",
"vm.deploy.resourcelimit.exceeded.account": "Unable to deploy Instance because allocating {{resourceRequested}} more {{resourceTypeDisplay}} would exceed the {{resourceOwnerType}} limits. Current: {{resourceAmount}}, Reserved: {{resourceReserved}}, Limit: {{resourceLimit}}. Release unused resources, then retry.",
"vm.deploy.resourcelimit.exceeded.account.admin": "Unable to deploy Instance because allocating {{resourceRequested}} more {{resourceTypeDisplay}} would exceed the {{resourceOwnerType}} limits for {{resourceOwner}}. Current: {{resourceAmount}}, Reserved: {{resourceReserved}}, Limit: {{resourceLimit}}. Release unused resources or increase the limit, then retry.",
"vm.deploy.resourcelimit.exceeded.domain": "Unable to deploy Instance because allocating {{resourceRequested}} more {{resourceTypeDisplay}} would exceed the domain limits. Current: {{resourceAmount}}, Reserved: {{resourceReserved}}, Limit: {{resourceLimit}}. Release unused resources, then retry.",
"vm.deploy.resourcelimit.exceeded.domain.admin": "Unable to deploy Instance because allocating {{resourceRequested}} more {{resourceTypeDisplay}} would exceed the limits for domain {{resourceOwnerDomain}}. Current: {{resourceAmount}}, Reserved: {{resourceReserved}}, Limit: {{resourceLimit}}. Release unused resources or increase the limit, then retry.",
"vm.deploy.serviceoffering.fixed.parameters.not.allowed": "Unable to deploy the instance because the selected service offering {{serviceOffering}} does not allow specifying {{cpuNumberKey}}, {{cpuSpeedKey}}, or {{memory}}.",
"vm.deploy.serviceoffering.fixed.parameters.not.allowed.admin": "Unable to deploy the instance because the selected service offering {{serviceOffering}} is not a dynamic offering and it does not allow specifying {{cpuNumberKey}}, {{cpuSpeedKey}}, or {{memory}}.",
"vm.deploy.serviceoffering.inactive": "Unable to deploy Instance as the given service offering {{serviceOffering}} is inactive. Specify an active service offering.",

View File

@ -558,6 +558,16 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
if (domainResourceLimit != Resource.RESOURCE_UNLIMITED && requestedDomainResourceCount > domainResourceLimit) {
String message = "Maximum" + messageSuffix;
Map<Object, Object> details = new HashMap<>();
details.put("resourceTypeDisplay", StringUtils.isBlank(tag) ? type.getDisplayName() : type.getDisplayName() + " (tag: " + tag + ")");
details.put("resourceOwner", ObjectUtils.firstNonNull(project, account));
details.put("resourceOwnerDomain", domain);
details.put("resourceOwnerType", project == null ? "Account" : "Project");
details.put("resourceLimit", convDomainResourceLimit);
details.put("resourceAmount", convCurrentDomainResourceCount);
details.put("resourceReserved", convCurrentResourceReservation);
details.put("resourceRequested", convNumResources);
CallContext.current().putContextParameters(details);
ResourceAllocationException e = new ResourceAllocationException(message, type);
logger.error(message, e);
throw e;
@ -597,6 +607,15 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
if (accountResourceLimit != Resource.RESOURCE_UNLIMITED && requestedResourceCount > accountResourceLimit) {
String message = "Maximum" + messageSuffix;
Map<Object, Object> details = new HashMap<>();
details.put("resourceTypeDisplay", StringUtils.isBlank(tag) ? type.getDisplayName() : type.getDisplayName() + " (tag: " + tag + ")");
details.put("resourceOwner", ObjectUtils.firstNonNull(project, account));
details.put("resourceOwnerType", project == null ? "Account" : "Project");
details.put("resourceLimit", convertedAccountResourceLimit);
details.put("resourceAmount", convertedCurrentResourceCount);
details.put("resourceReserved", convertedCurrentResourceReservation);
details.put("resourceRequested", convertedNumResources);
CallContext.current().putContextParameters(details);
ResourceAllocationException e = new ResourceAllocationException(message, type);
logger.error(message, e);
throw e;