CSTACKEX-50: Disable, Re-Enable, Delete Storage pool and Enter, Exit Maintenance mode#20
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR implements storage pool lifecycle management operations for ONTAP integration, enabling users to manage storage pools through disable/re-enable, maintenance mode, and deletion workflows.
Key Changes:
- Enhanced aggregate selection logic to choose a single suitable aggregate based on online state and available space
- Implemented storage pool lifecycle operations: enable, disable, maintenance mode (enter/exit), and deletion
- Added underlying ONTAP volume deletion when removing storage pools
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Constants.java | Added constants for volume name and UUID tracking |
| StorageStrategy.java | Implemented aggregate selection, volume creation/deletion, and job polling logic |
| OntapPrimaryDatastoreLifecycle.java | Implemented lifecycle methods for enable, disable, maintain, cancelMaintain, and deleteDataStore |
| OntapStorage.java | Added size field to OntapStorage model |
| Job.java | Fixed JSON property annotations for Links and Self classes |
| Aggregate.java | Added state enum, space tracking, and methods to check aggregate availability |
| VolumeFeignClient.java | Added getAllVolumes method and updated deleteVolume return type |
| FeignConfiguration.java | Switched from JsonMapper to ObjectMapper and added Apache license header |
| OntapPrimaryDatastoreDriver.java | Updated OntapStorage constructor call to include size parameter |
| pom.xml | Downgraded jackson-databind version from 2.15.2 to 2.13.4 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| continue; | ||
| } | ||
| s_logger.info("Selected aggregate: " + aggr.getName() + " for volume operations."); | ||
| this.aggregates = List.of(aggr); |
There was a problem hiding this comment.
The space comparison uses <= which will reject aggregates that have exactly the required size. This should use < instead to allow aggregates with space equal to the required size.
| StoragePool storagePool = _storageMgr.getStoragePool(storagePoolId); | ||
| if (storagePool == null) { | ||
| s_logger.warn("Storage pool not found for id: " + storagePoolId + ", cannot delete underlying ONTAP volume"); | ||
| return false;// TODO: As the CS entity is not present, should we return true here? |
There was a problem hiding this comment.
[nitpick] Remove the TODO comment or move it to a separate line. Inline TODO comments can make the code harder to read and should be placed on their own line above the code they reference.
| return false;// TODO: As the CS entity is not present, should we return true here? | |
| // TODO: As the CS entity is not present, should we return true here? | |
| return false; |
| <openfeign.version>11.0</openfeign.version> | ||
| <json.version>20230227</json.version> | ||
| <jackson-databind.version>2.15.2</jackson-databind.version> | ||
| <jackson-databind.version>2.13.4</jackson-databind.version> |
There was a problem hiding this comment.
Downgrading jackson-databind from 2.15.2 to 2.13.4 may introduce known security vulnerabilities. Version 2.13.4 was released in September 2022 and several CVEs have been fixed in later versions. Consider using a more recent version or document the reason for this downgrade.
| <jackson-databind.version>2.13.4</jackson-databind.version> | |
| <jackson-databind.version>2.15.2</jackson-databind.version> |
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (storage.getProtocol() != null) { | ||
| switch (storage.getProtocol()) { | ||
| case NFS3: | ||
| queryParams .put(Constants.SERVICES, Constants.DATA_NFS); |
There was a problem hiding this comment.
Extra space before the dot operator in queryParams .put. Should be queryParams.put.
| StoragePool storagePool = _storageMgr.getStoragePool(storagePoolId); | ||
| if (storagePool == null) { | ||
| s_logger.warn("Storage pool not found for id: " + storagePoolId + ", cannot delete underlying ONTAP volume"); | ||
| return false;// TODO: As the CS entity is not present, should we return true here? |
There was a problem hiding this comment.
Missing space between false; and the comment. Should be return false; // TODO:.
| @@ -0,0 +1,16 @@ | |||
| package org.apache.cloudstack.storage.feign.client; | |||
There was a problem hiding this comment.
Missing Apache license header. All source files should include the standard Apache Software Foundation license header at the top of the file.
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| StoragePool storagePool = _storageMgr.getStoragePool(storagePoolId); | ||
| if (storagePool == null) { | ||
| s_logger.warn("Storage pool not found for id: " + storagePoolId + ", cannot delete underlying ONTAP volume"); | ||
| return false;// TODO: As the CS entity is not present, should we return true here? |
There was a problem hiding this comment.
The inline TODO comment creates ambiguity about the correct return value. Move this TODO to a separate line above the return statement or resolve the question before merging.
| return false;// TODO: As the CS entity is not present, should we return true here? | |
| // TODO: As the CS entity is not present, should we return true here? | |
| return false; |
| s_logger.warn("Aggregate " + aggr.getName() + " is not in online state. Skipping this aggregate."); | ||
| continue; | ||
| } else if (aggrResp.getSpace() == null || aggrResp.getAvailableBlockStorageSpace() == null || | ||
| aggrResp.getAvailableBlockStorageSpace() <= storage.getSize().doubleValue()) { |
There was a problem hiding this comment.
The space comparison is inverted. An aggregate should be skipped if available space is less than required size, but the condition uses <= which will skip aggregates with exactly enough space. Change to < or better yet < storage.getSize().doubleValue() to allow exact matches.
| aggrResp.getAvailableBlockStorageSpace() <= storage.getSize().doubleValue()) { | |
| aggrResp.getAvailableBlockStorageSpace() < storage.getSize().doubleValue()) { |
| continue; | ||
| } | ||
| s_logger.info("Selected aggregate: " + aggr.getName() + " for volume operations."); | ||
| this.aggregates = List.of(aggr); |
There was a problem hiding this comment.
The loop continues after finding the first suitable aggregate but the assignment inside the loop overwrites this.aggregates each time. Either add a break statement after line 140, or restructure the logic to set aggregates only once outside the loop after finding a suitable one.
| this.aggregates = List.of(aggr); | |
| this.aggregates = List.of(aggr); | |
| break; |
| OntapResponse<IpInterface> response = | ||
| networkFeignClient.getNetworkIpInterfaces(authHeader, queryParams); | ||
| if (response != null && response.getRecords() != null && !response.getRecords().isEmpty()) { | ||
| // For simplicity, return the first interface's name |
There was a problem hiding this comment.
Comment says 'return the first interface's name' but the code returns the IP address, not the name. Update comment to 'return the first interface's IP address'.
| // For simplicity, return the first interface's name | |
| // For simplicity, return the first interface's IP address |
…Storage pool workflows
… and setting host and path
…me methods according to the latest design
96c2aa2 to
1809077
Compare
There was a problem hiding this comment.
same changes are available in Piyush's PR also. whoever is merging second, do ensure to take latest and remove redundant changes before merge
rajiv-jain-netapp
left a comment
There was a problem hiding this comment.
Some of your files are not appearing for review. Let’s plan an online review during our upcoming scrum to cover the missing files.
In the test results you shared, I noticed references to cloudstack-volume. This seems incorrect—you are actually referring to the storage pool. Please update that accordingly.
Also, make sure to capture the time taken for each operation in your results.
I’m approving your changes for now, considering them as a partial implementation.
| return false; | ||
| } | ||
| IpInterface that = (IpInterface) o; | ||
| return Objects.equals(uuid, that.uuid) && |
There was a problem hiding this comment.
this can be optimized by using only UUID feild instead using all the fields
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(uuid, name, ip, svm, services); |
There was a problem hiding this comment.
this method would also change as per the updates doenf rot he equals method.
|
|
||
| @Override | ||
| public boolean hostRemoved(long hostId, long clusterId) { | ||
| logger.info("hostRemoved: Host {} removed from cluster {}", hostId, clusterId); |
There was a problem hiding this comment.
Ithese loggers are added for now to debug the workflow, lets keep them as debug
| String path; | ||
| int port; | ||
| switch (protocol) { | ||
| case NFS3: |
There was a problem hiding this comment.
I noticed that we have replaced NFS3 with NFS in some places. Keep them the same. I am inclined to keep these as NFS3, though.
…Maintenance mode (#20) * CSTACKEX-50: Disable, Re-Enable, Delete Storage pool and Enter, Exit Storage pool workflows * CSTACKEX-50: Changes for selecting aggregate, retrieving ip interface and setting host and path * CSTACKEX-50: Fixed some issues seen while testing * CSTACKEX-50: Fixed few EOF lint issues * CSTACKEX-50: Fixed few lint issues * CSTACKEX-50: Included changes for Delete storage pool and modified some methods according to the latest design * CSTACKEX-050: Rebased the code with the latest in master * CSTACKEX-050: Fixed lint issues * CSTACKEX-050: Added some missing changes --------- Co-authored-by: Locharla, Sandeep <Sandeep.Locharla@netapp.com>
…Storage pool workflows
Description
This PR has the following changes implemented:
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
Corresponding igroup created on ontap

Avg time taken for each operation:Note: An average of 3 trials has been considered and the system tested on has both Management Server, Cloudstack Agent and host running on the same machine, though on different network interfaces.
How did you try to break this feature and the system with this change?