-
Notifications
You must be signed in to change notification settings - Fork 0
CSTACKEX-50: Disable, Re-Enable, Delete Storage pool and Enter, Exit Maintenance mode #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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? |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[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> |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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? |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space between false; and the comment. Should be return false; // TODO:.
| @@ -0,0 +1,16 @@ | |||
| package org.apache.cloudstack.storage.feign.client; | |||
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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? |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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()) { |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same changes are available in Piyush's PR also. whoever is merging second, do ensure to take latest and remove redundant changes before merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as earlier comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
file did not load
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File is still not loading
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
file did not load
rajiv-jain-netapp
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method would also change as per the updates doenf rot he equals method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File is still not loading
|
|
||
| @Override | ||
| public boolean hostRemoved(long hostId, long clusterId) { | ||
| logger.info("hostRemoved: Host {} removed from cluster {}", hostId, clusterId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
…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?