Skip to content

NetApp ONTAP Storage Pool resize - #14523

Open
sandeeplocharla wants to merge 2 commits into
apache:mainfrom
NetApp:netapp-pool-resize
Open

sandeeplocharla wants to merge 2 commits into
apache:mainfrom
NetApp:netapp-pool-resize

Conversation

@sandeeplocharla

@sandeeplocharla sandeeplocharla commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR enables the user to resize Primary StoragePool created using NetApp ONTAP storage plugin.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?


iSCSI type Primary StoragePool Resize

Create Primary StoragePool of iSCSI type and Cluster scoped of size 20GiB
Screenshot 2026-10-29 at 4 51 26 PM
Screenshot 2026-10-29 at 4 51 49 PM
On ONTAP - backing flexVol
Screenshot 2026-10-29 at 4 52 17 PM
Resizing the StoragePool to 30 GiB
Screenshot 2026-10-29 at 4 55 52 PM
Screenshot 2026-10-29 at 4 56 28 PM
On ONTAP - backing flexVol - resized
Screenshot 2026-10-29 at 4 56 46 PM

NFS3 type Primary StoragePool Resize

Create Primary StoragePool of NFS3 type and Cluster scoped of size 20GiB
Screenshot 2026-10-29 at 4 59 59 PM
Screenshot 2026-10-29 at 5 00 21 PM
On ONTAP - backing flexVol
Screenshot 2026-10-29 at 5 00 44 PM
Resizing the StoragePool to 30 GiB
Screenshot 2026-10-29 at 5 01 27 PM
On ONTAP - backing flexVol - resized
Screenshot 2026-10-29 at 5 02 00 PM

@sandeeplocharla

Copy link
Copy Markdown
Contributor Author

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@sandeeplocharla a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19835

public static final int ONTAP_SNAPSHOT_DELETE_JOB_POLL_INTERVAL_MS = 2000;
/** Retry settings for FlexVolume create/resize/delete job polling. */
public static final int ONTAP_VOLUME_JOB_MAX_RETRIES = 10;
public static final int ONTAP_VOLUME_JOB_POLL_INTERVAL_MS = 1000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this constant different from below constant ONTAP_FLEXVOL_JOB_POLL_INTERVAL_MS ? Check if it can be re-used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep makes sense, will reuse the existing constants. Thankyou!!!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*/
public Volume updateStorageVolume(Volume volume) {
return null;
logger.info("Resizing ONTAP FlexVolume '{}' (UUID: {}) to {} bytes", volume.getName(), volume.getUuid(), volume.getSize());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove keyword like resize for method to be generic update and also volume.getSize().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method gets called only to resize the flexVol. So, it should be alright to call it out this way

logger.info("Resizing ONTAP FlexVolume '{}' (UUID: {}) to {} bytes", volume.getName(), volume.getUuid(), volume.getSize());
String authHeader = OntapStorageUtils.generateAuthHeader(storage.getUsername(), storage.getPassword());
try {
Volume resizeRequest = new Volume();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename variable to be generic update request

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah! makes sense but given that this method's sole purpose is to resize the flexVol, I feel the name works along.

String authHeader = OntapStorageUtils.generateAuthHeader(storage.getUsername(), storage.getPassword());
try {
Volume resizeRequest = new Volume();
resizeRequest.setSize(volume.getSize());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have null check and set only if it not null for it be to generic update method

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateStoragePool(StoragePool storagePool, Map<String, String> details) already has a 'null' check on 'newCapacityStr', so, the call wouldn't even reach here if 'volume.getSize() == null'

logger.info("FlexVolume '{}' (UUID: {}) resized successfully to {} bytes", volume.getName(), volume.getUuid(), volume.getSize());
} catch (FeignException e) {
if (OntapStorageUtils.isOntapObjectNotFoundError(e)) {
String msg = String.format("Cannot resize FlexVolume '%s' (UUID: %s): volume not found on ONTAP (404). ", volume.getName(), volume.getUuid());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, remove all occurence of resize keyword.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as replied before, this method is currently used only for resizing the flexVol, so, until we come across an alternate usecase that uses this method, let's keep it the same.

@Override
public void updateStoragePool(StoragePool storagePool, Map<String, String> details) {
String newCapacityStr = details.get(PrimaryDataStoreLifeCycle.CAPACITY_BYTES);
if (newCapacityStr == null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is update storage pool only called for capacity bytes, if not we should skip throwing this error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, updateStoragePool gets called only to resize the capacity bytes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can also be called for iops change also. Since this method is generic update, instead of having null check , have not null check for changes fields.

sathvikaragi and others added 2 commits November 10, 2026 18:15
storage pool resize (Grow and shrink)

This PR...
<!--- Describe your changes in DETAIL - And how has behaviour
functionally changed. -->
[updateStoragePool] API now resizes the ONTAP FlexVolume backing the
pool. When called with a new [capacityBytes], StorageManagerImpl
(previously never called the lifecycle hook) now invokes
[OntapPrimaryDatastoreLifecycle.updateStoragePool()], which calls the
ONTAP REST API
(PATCH /api/storage/volumes/{uuid}) and polls the async job to
completion. No validation is applied — the new size is passed directly
to ONTAP, which enforces all constraints and returns any errors as-is.

This also includes UT's.

<!-- For new features, provide link to FS, dev ML discussion etc. -->
<!-- In case of bug fix, the expected and actual behaviours, steps to
reproduce. -->

<!-- When "Fixes: #<id>" is specified, the issue/PR will automatically
be closed when this PR gets merged -->
<!-- For addressing multiple issues/PRs, use multiple "Fixes: #<id>" -->
<!-- Fixes: # -->

<!---
*******************************************************************************
-->
<!--- NOTE: AUTOMATION USES THE DESCRIPTIONS TO SET LABELS AND PRODUCE
DOCUMENTATION. -->
<!--- PLEASE PUT AN 'X' in only **ONE** box -->
<!---
*******************************************************************************
-->

- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Enhancement (improves an existing feature and functionality)
- [ ] Cleanup (Code refactoring and cleanup, that may add test cases)
- [ ] Build/CI
- [ ] Test (unit or integration test code)

- [ ] Major
- [x] Minor

- [ ] BLOCKER
- [ ] Critical
- [ ] Major
- [ ] Minor
- [ ] Trivial

 the flex volume is created with size  20GiB:
<img width="1550" height="870" alt="Screenshot 2026-08-07 at 2 53 44 PM"
src="https://github.com/user-attachments/assets/b312f4ec-b4b7-420a-9b1e-81e392a882c4"
/>

case 1: when A valid input for resize is filled by user:

<img width="1458" height="681" alt="Screenshot 2026-08-07 at 2 54 17 PM"
src="https://github.com/user-attachments/assets/bb0caf98-df9b-4d6f-ae76-0ca4f7659a0f"
/>

<img width="1255" height="736" alt="Screenshot 2026-08-07 at 2 54 44 PM"
src="https://github.com/user-attachments/assets/7c0b8f49-213f-4163-971a-3a39c1d49936"
/>

after successful resize:
<img width="1555" height="836" alt="Screenshot 2026-08-07 at 3 23 15 PM"
src="https://github.com/user-attachments/assets/b7de8bfb-d8ca-4983-ae58-6c0c2503d943"
/>

case 2: capacity bytes given is smaller than ontap volume minimum size
<img width="1476" height="846" alt="Screenshot 2026-08-07 at 2 49 58 PM"
src="https://github.com/user-attachments/assets/a670be26-ab86-4e79-be50-86dd68bf39e9"
/>

case 3: capacity bytes given is smaller than ontap volume maximum size
<img width="1469" height="874" alt="Screenshot 2026-08-07 at 2 52 11 PM"
src="https://github.com/user-attachments/assets/da10b5c8-f9a3-4651-a1c2-404a908f4832"
/>

UT's for it :
Ran just the update storage pool tests in storagestrategytest and
primarydatastorelifecycletest
<img width="856" height="773" alt="Screenshot 2026-08-14 at 4 07 37 PM"
src="https://github.com/user-attachments/assets/b3d23c36-b635-48da-9403-aad5cd5685a6"
/>

Ran all tests in both the files:
<img width="868" height="788" alt="Screenshot 2026-08-14 at 4 09 12 PM"
src="https://github.com/user-attachments/assets/956e7c0c-190c-478f-be79-5a77623cb0bc"
/>

<!-- Please describe in detail how you tested your changes. -->
<!-- Include details of your testing environment, and the tests you ran
to -->

change?

<!-- see how your change affects other areas of the code, etc. -->

<!-- Please read the
[CONTRIBUTING](https://github.com/apache/cloudstack/blob/main/CONTRIBUTING.md)
document -->

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants