From 25641c393885de197a205bf8aa5e3ca5b98bc54b Mon Sep 17 00:00:00 2001 From: Eugenio Grosso Date: Wed, 22 Apr 2026 18:29:01 +0000 Subject: [PATCH 1/2] adaptive: honor user-provided capacityBytes when provider stats are unavailable AdaptiveDataStoreLifeCycleImpl.initialize() guarded the user-provided capacityBytes behind stats != null when computing the pool capacity to persist. As a consequence, any adaptive provider that could not report capacity yet (for example a FlashArray pod that has not been given a quota and has no footprint yet, or a transient probe failure) caused the whole pool registration to fail with "Capacity bytes not available from the storage provider, user provided capacity bytes must be specified" even when the operator had passed capacityBytes= on createStoragePool. Accept the user-supplied value unconditionally and use the provider stats only as an upper-bound sanity check when they are actually available. The "no user-provided capacity, no provider capacity" branch is preserved and still raises the same InvalidParameterValueException. Signed-off-by: Eugenio Grosso --- .../lifecycle/AdaptiveDataStoreLifeCycleImpl.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java index 771f79887e0f..b44e34425e1c 100644 --- a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java @@ -217,13 +217,14 @@ public DataStore initialize(Map dsInfos) { // validate the provided details are correct/valid for the provider api.validate(); - // if we have user-provided capacity bytes, validate they do not exceed the manaaged storage capacity bytes + // User-provided capacityBytes always wins; validate against storage stats only when + // the provider could actually report them. If the provider cannot (empty pod with no + // footprint, no quota set, transient probe failure), fall through and use what the + // user supplied rather than failing the whole registration. ProviderVolumeStorageStats stats = api.getManagedStorageStats(); - if (capacityBytes != null && capacityBytes != 0 && stats != null) { - if (stats.getCapacityInBytes() > 0) { - if (stats.getCapacityInBytes() < capacityBytes) { - throw new InvalidParameterValueException("Capacity bytes provided exceeds the capacity of the storage endpoint: provided by user: " + capacityBytes + ", storage capacity from storage provider: " + stats.getCapacityInBytes()); - } + if (capacityBytes != null && capacityBytes != 0) { + if (stats != null && stats.getCapacityInBytes() > 0 && stats.getCapacityInBytes() < capacityBytes) { + throw new InvalidParameterValueException("Capacity bytes provided exceeds the capacity of the storage endpoint: provided by user: " + capacityBytes + ", storage capacity from storage provider: " + stats.getCapacityInBytes()); } parameters.setCapacityBytes(capacityBytes); } From 0970c239c10afef6fb3b30d33458e181ca0127ca Mon Sep 17 00:00:00 2001 From: Eugenio Grosso Date: Thu, 23 Apr 2026 12:39:34 +0000 Subject: [PATCH 2/2] adaptive: address review on capacityBytes validation Address Copilot feedback on PR #13059: - The capacityBytes check now uses > 0 instead of != 0, so a negative value no longer slips through and gets persisted as a storage capacity. - Reworded the exception message for the exceeds-capacity check: Provided capacity bytes exceed ... (grammar). Signed-off-by: Eugenio Grosso --- .../datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java index b44e34425e1c..c8efc08c2892 100644 --- a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/AdaptiveDataStoreLifeCycleImpl.java @@ -222,9 +222,9 @@ public DataStore initialize(Map dsInfos) { // footprint, no quota set, transient probe failure), fall through and use what the // user supplied rather than failing the whole registration. ProviderVolumeStorageStats stats = api.getManagedStorageStats(); - if (capacityBytes != null && capacityBytes != 0) { + if (capacityBytes != null && capacityBytes > 0) { if (stats != null && stats.getCapacityInBytes() > 0 && stats.getCapacityInBytes() < capacityBytes) { - throw new InvalidParameterValueException("Capacity bytes provided exceeds the capacity of the storage endpoint: provided by user: " + capacityBytes + ", storage capacity from storage provider: " + stats.getCapacityInBytes()); + throw new InvalidParameterValueException("Provided capacity bytes exceed the capacity of the storage endpoint: provided by user: " + capacityBytes + ", storage capacity from storage provider: " + stats.getCapacityInBytes()); } parameters.setCapacityBytes(capacityBytes); }