From dd1844cc5c2ac19a7ea853816012926d5200df70 Mon Sep 17 00:00:00 2001 From: sr73318 Date: Fri, 7 Aug 2026 15:11:09 +0530 Subject: [PATCH 1/2] CSTACKEX-234: Enabling storage pool resize (grow and shrink) --- .../OntapPrimaryDatastoreLifecycle.java | 30 +++++++++++++++++++ .../storage/service/StorageStrategy.java | 23 +++++++++++--- .../com/cloud/storage/StorageManagerImpl.java | 2 +- 3 files changed, 50 insertions(+), 5 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 a206eaa053df..59852aa9bca9 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 @@ -526,7 +526,37 @@ public boolean migrateToObjectStore(DataStore store) { @Override public void updateStoragePool(StoragePool storagePool, Map details) { + StoragePoolVO poolVO = storagePoolDao.findById(storagePool.getId()); + if (poolVO == null) { + throw new CloudRuntimeException("updateStoragePool: storage pool not found: " + storagePool.getId()); + } + String strNewCapacityBytes = details.get(PrimaryDataStoreLifeCycle.CAPACITY_BYTES); + if (strNewCapacityBytes == null) { + logger.debug("updateStoragePool: no capacityBytes change requested, skipping ONTAP resize"); + return; + } + long newCapacityBytes = Long.parseLong(strNewCapacityBytes); + + Map poolDetails = storagePoolDetailsDao.listDetailsKeyPairs(storagePool.getId()); + StorageStrategy storageStrategy = OntapStorageUtils.getStrategyByStoragePoolDetails(poolDetails); + logger.info("updateStoragePool: resizing ONTAP FlexVolume for pool '{}'", storagePool.getId()); + Volume volume = new Volume(); + volume.setUuid(poolDetails.get(OntapStorageConstants.VOLUME_UUID)); + volume.setName(poolDetails.get(OntapStorageConstants.VOLUME_NAME)); + try { + if (volume.getUuid() == null || volume.getUuid().isEmpty() || volume.getName() == null || volume.getName().isEmpty()) { + logger.error("updateStoragePool: Volume UUID/Name not found in details for pool: {}, cannot resize", storagePool.getName()); + throw new CloudRuntimeException("Volume UUID/Name not found in details, cannot resize ONTAP FlexVolume"); + } + storageStrategy.updateStorageVolume(volume, newCapacityBytes); + logger.info("updateStoragePool: Successfully resized ONTAP FlexVolume '{}' (UUID: {}) for pool '{}'", + volume.getName(), volume.getUuid(), storagePool.getName()); + } catch (Exception e) { + logger.error("updateStoragePool: Exception while resizing FlexVolume for pool: {}. Error: {}", + storagePool.getName(), e.getMessage(), e); + throw new CloudRuntimeException("Failed to resize ONTAP FlexVolume for pool: " + storagePool.getName() + ". " + e.getMessage(), e); + } } @Override diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java index 0ef295418118..0e7dc9aebd5b 100644 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java @@ -367,11 +367,26 @@ public Volume createStorageVolume(String volumeName, Long size) { * @param volume the volume to update * @return the updated Volume object */ - public Volume updateStorageVolume(Volume volume) { - return null; + public Volume updateStorageVolume(Volume volume, Long newSizeBytes) { + logger.info("Resizing ONTAP volume by name: " + volume.getName() + " and uuid: " + volume.getUuid()); + String authHeader = OntapStorageUtils.generateAuthHeader(storage.getUsername(), storage.getPassword()); + Volume resizeRequest = new Volume(); + resizeRequest.setSize(newSizeBytes); + try { + JobResponse jobResponse = volumeFeignClient.updateVolumeRebalancing(authHeader, volume.getUuid(), resizeRequest); + Boolean jobSucceeded = jobPollForSuccess(jobResponse.getJob().getUuid(), 10, 1000); + if (!jobSucceeded) { + logger.error("resizeStorageVolume: resize job failed for FlexVolume: " + volume.getName()); + throw new CloudRuntimeException("resizeStorageVolume: resize job failed for FlexVolume: " + volume.getName()); + } + } catch (FeignException e) { + logger.error("Exception while resizing FlexVolume: " + volume.getName(), e); + throw new CloudRuntimeException("Failed to resize ONTAP FlexVolume: " + e.getMessage(), e); + } + logger.info("resizeStorageVolume: FlexVolume {} resized successfully to {} bytes", volume.getName(), newSizeBytes); + return volume; } - - /** + /** * Delete ONTAP Flex-Volume * Eligible only for Unified ONTAP storage * throw exception in case of disaggregated ONTAP storage diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index b25da50d4d92..475bbd257e54 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -1289,7 +1289,6 @@ public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) throws I StoragePoolVO storagePool = _storagePoolDao.findById(id); DataStoreProvider dataStoreProvider = _dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName()); DataStoreLifeCycle dataStoreLifeCycle = dataStoreProvider.getDataStoreLifeCycle(); - if (dataStoreLifeCycle instanceof PrimaryDataStoreLifeCycle) { if (updatedCapacityBytes != null) { details.put(PrimaryDataStoreLifeCycle.CAPACITY_BYTES, updatedCapacityBytes != null ? String.valueOf(updatedCapacityBytes) : null); @@ -1302,6 +1301,7 @@ public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) throws I if (cmd.getUrl() != null) { details.put("url", cmd.getUrl()); } + ((PrimaryDataStoreLifeCycle)dataStoreLifeCycle).updateStoragePool(pool, details); _storagePoolDao.update(id, storagePool); _storagePoolDao.updateDetails(id, details); } From 0ab1f6838324985bda3ecff6313cebe83bafbdad Mon Sep 17 00:00:00 2001 From: sr73318 Date: Sat, 8 Aug 2026 11:23:07 +0530 Subject: [PATCH 2/2] CSTACKEX-234: resolving comments --- .../OntapPrimaryDatastoreLifecycle.java | 22 +++++-------------- .../storage/service/StorageStrategy.java | 7 +++--- .../com/cloud/storage/StorageManagerImpl.java | 13 +++++------ 3 files changed, 15 insertions(+), 27 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 59852aa9bca9..5ed07b424695 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 @@ -526,34 +526,24 @@ public boolean migrateToObjectStore(DataStore store) { @Override public void updateStoragePool(StoragePool storagePool, Map details) { - StoragePoolVO poolVO = storagePoolDao.findById(storagePool.getId()); - if (poolVO == null) { - throw new CloudRuntimeException("updateStoragePool: storage pool not found: " + storagePool.getId()); - } - String strNewCapacityBytes = details.get(PrimaryDataStoreLifeCycle.CAPACITY_BYTES); - if (strNewCapacityBytes == null) { - logger.debug("updateStoragePool: no capacityBytes change requested, skipping ONTAP resize"); - return; - } - long newCapacityBytes = Long.parseLong(strNewCapacityBytes); - + long currentCapacityBytes = storagePool.getCapacityBytes(); + long newCapacityBytes = Long.parseLong(details.get(PrimaryDataStoreLifeCycle.CAPACITY_BYTES)); Map poolDetails = storagePoolDetailsDao.listDetailsKeyPairs(storagePool.getId()); StorageStrategy storageStrategy = OntapStorageUtils.getStrategyByStoragePoolDetails(poolDetails); - logger.info("updateStoragePool: resizing ONTAP FlexVolume for pool '{}'", storagePool.getId()); Volume volume = new Volume(); volume.setUuid(poolDetails.get(OntapStorageConstants.VOLUME_UUID)); volume.setName(poolDetails.get(OntapStorageConstants.VOLUME_NAME)); try { if (volume.getUuid() == null || volume.getUuid().isEmpty() || volume.getName() == null || volume.getName().isEmpty()) { - logger.error("updateStoragePool: Volume UUID/Name not found in details for pool: {}, cannot resize", storagePool.getName()); + logger.error("Volume UUID/Name not found in details for pool: {}, cannot resize", storagePool.getName()); throw new CloudRuntimeException("Volume UUID/Name not found in details, cannot resize ONTAP FlexVolume"); } storageStrategy.updateStorageVolume(volume, newCapacityBytes); - logger.info("updateStoragePool: Successfully resized ONTAP FlexVolume '{}' (UUID: {}) for pool '{}'", - volume.getName(), volume.getUuid(), storagePool.getName()); + logger.info("Successfully resized ONTAP FlexVolume '{}' (UUID: {}) for pool '{}' from {} bytes to {} bytes", + volume.getName(), volume.getUuid(), storagePool.getName(), currentCapacityBytes, newCapacityBytes); } catch (Exception e) { - logger.error("updateStoragePool: Exception while resizing FlexVolume for pool: {}. Error: {}", + logger.error(" Exception while resizing FlexVolume for pool: {}. Error: {}", storagePool.getName(), e.getMessage(), e); throw new CloudRuntimeException("Failed to resize ONTAP FlexVolume for pool: " + storagePool.getName() + ". " + e.getMessage(), e); } diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java index 0e7dc9aebd5b..cbb5c43d3779 100644 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java @@ -368,7 +368,6 @@ public Volume createStorageVolume(String volumeName, Long size) { * @return the updated Volume object */ public Volume updateStorageVolume(Volume volume, Long newSizeBytes) { - logger.info("Resizing ONTAP volume by name: " + volume.getName() + " and uuid: " + volume.getUuid()); String authHeader = OntapStorageUtils.generateAuthHeader(storage.getUsername(), storage.getPassword()); Volume resizeRequest = new Volume(); resizeRequest.setSize(newSizeBytes); @@ -376,14 +375,14 @@ public Volume updateStorageVolume(Volume volume, Long newSizeBytes) { JobResponse jobResponse = volumeFeignClient.updateVolumeRebalancing(authHeader, volume.getUuid(), resizeRequest); Boolean jobSucceeded = jobPollForSuccess(jobResponse.getJob().getUuid(), 10, 1000); if (!jobSucceeded) { - logger.error("resizeStorageVolume: resize job failed for FlexVolume: " + volume.getName()); - throw new CloudRuntimeException("resizeStorageVolume: resize job failed for FlexVolume: " + volume.getName()); + logger.error("resize job failed for FlexVolume: " + volume.getName()); + throw new CloudRuntimeException("resize job failed for FlexVolume: " + volume.getName()); } + logger.info("Volume is resized successfully for : " + volume.getName()); } catch (FeignException e) { logger.error("Exception while resizing FlexVolume: " + volume.getName(), e); throw new CloudRuntimeException("Failed to resize ONTAP FlexVolume: " + e.getMessage(), e); } - logger.info("resizeStorageVolume: FlexVolume {} resized successfully to {} bytes", volume.getName(), newSizeBytes); return volume; } /** diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 475bbd257e54..d4a0c0fe83f2 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -1286,23 +1286,22 @@ public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) throws I } if (changes) { - StoragePoolVO storagePool = _storagePoolDao.findById(id); - DataStoreProvider dataStoreProvider = _dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName()); + DataStoreProvider dataStoreProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); DataStoreLifeCycle dataStoreLifeCycle = dataStoreProvider.getDataStoreLifeCycle(); if (dataStoreLifeCycle instanceof PrimaryDataStoreLifeCycle) { if (updatedCapacityBytes != null) { - details.put(PrimaryDataStoreLifeCycle.CAPACITY_BYTES, updatedCapacityBytes != null ? String.valueOf(updatedCapacityBytes) : null); - _storagePoolDao.updateCapacityBytes(id, updatedCapacityBytes); + details.put(PrimaryDataStoreLifeCycle.CAPACITY_BYTES, String.valueOf(updatedCapacityBytes)); + pool.setCapacityBytes(updatedCapacityBytes); } if (updatedCapacityIops != null) { - details.put(PrimaryDataStoreLifeCycle.CAPACITY_IOPS, updatedCapacityIops != null ? String.valueOf(updatedCapacityIops) : null); - _storagePoolDao.updateCapacityIops(id, updatedCapacityIops); + details.put(PrimaryDataStoreLifeCycle.CAPACITY_IOPS, String.valueOf(updatedCapacityIops)); + pool.setCapacityIops(updatedCapacityIops); } if (cmd.getUrl() != null) { details.put("url", cmd.getUrl()); } ((PrimaryDataStoreLifeCycle)dataStoreLifeCycle).updateStoragePool(pool, details); - _storagePoolDao.update(id, storagePool); + _storagePoolDao.update(id, pool); _storagePoolDao.updateDetails(id, details); } }