From 7b562550817d6d955d73218e4d3a4afa6b720e3d Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Tue, 12 May 2026 19:55:53 +0530 Subject: [PATCH 1/2] bugfix/CSTACKEX-155: Fix cancel maintain for vm provisioning --- .../OntapPrimaryDatastoreLifecycle.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java index b055dad425a8..070c77805bd7 100755 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java @@ -450,8 +450,31 @@ public boolean maintain(DataStore store) { @Override public boolean cancelMaintain(DataStore store) { logger.info("Cancelling storage pool maintenance for {}", store); + + // Save capacity before the generic cancelMaintain path overwrites it. + // The generic flow sends ModifyStoragePoolCommand to agents. For managed iSCSI pools, + // IscsiAdmStoragePool returns capacityBytes=0 (it doesn't track real ONTAP capacity), + // which causes updateStoragePoolHostVOAndBytes to overwrite the real capacity set during + // pool initialization. With capacity=0, the deployment planner's checkPoolforSpace + // divides by zero and rejects the pool ("No destination found"). + StoragePoolVO poolVO = storagePoolDao.findById(store.getId()); + long savedCapacityBytes = poolVO.getCapacityBytes(); + long savedUsedBytes = poolVO.getUsedBytes(); + if (_dataStoreHelper.cancelMaintain(store)) { - return _storagePoolAutomation.cancelMaintain(store); + boolean result = _storagePoolAutomation.cancelMaintain(store); + + // Restore capacity if the generic path zeroed it out + poolVO = storagePoolDao.findById(store.getId()); + if (poolVO.getCapacityBytes() == 0 && savedCapacityBytes > 0) { + logger.info("Restoring storage pool {} capacity to {} bytes (agent returned 0 during cancelMaintain)", + poolVO.getName(), savedCapacityBytes); + poolVO.setCapacityBytes(savedCapacityBytes); + poolVO.setUsedBytes(savedUsedBytes); + storagePoolDao.update(poolVO.getId(), poolVO); + } + + return result; } else { return false; } From 6e94d3403dfd7aadea692cd14c129d47b9aa7405 Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Tue, 12 May 2026 20:16:34 +0530 Subject: [PATCH 2/2] bugfix/CSTACKEX-155: Fix cancel maintain for vm provisioning update comments --- .../lifecycle/OntapPrimaryDatastoreLifecycle.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java index 070c77805bd7..e9ba46a4333e 100755 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java @@ -453,10 +453,8 @@ public boolean cancelMaintain(DataStore store) { // Save capacity before the generic cancelMaintain path overwrites it. // The generic flow sends ModifyStoragePoolCommand to agents. For managed iSCSI pools, - // IscsiAdmStoragePool returns capacityBytes=0 (it doesn't track real ONTAP capacity), - // which causes updateStoragePoolHostVOAndBytes to overwrite the real capacity set during - // pool initialization. With capacity=0, the deployment planner's checkPoolforSpace - // divides by zero and rejects the pool ("No destination found"). + // IscsiAdmStoragePool returns capacityBytes=0 , With capacity=0, + // the deployment planner's checkPoolforSpace rejects the pool ("No destination found"). StoragePoolVO poolVO = storagePoolDao.findById(store.getId()); long savedCapacityBytes = poolVO.getCapacityBytes(); long savedUsedBytes = poolVO.getUsedBytes(); @@ -464,10 +462,10 @@ public boolean cancelMaintain(DataStore store) { if (_dataStoreHelper.cancelMaintain(store)) { boolean result = _storagePoolAutomation.cancelMaintain(store); - // Restore capacity if the generic path zeroed it out + // Restore capacity poolVO = storagePoolDao.findById(store.getId()); if (poolVO.getCapacityBytes() == 0 && savedCapacityBytes > 0) { - logger.info("Restoring storage pool {} capacity to {} bytes (agent returned 0 during cancelMaintain)", + logger.info("Restoring storage pool {} capacity to {} bytes", poolVO.getName(), savedCapacityBytes); poolVO.setCapacityBytes(savedCapacityBytes); poolVO.setUsedBytes(savedUsedBytes);