Skip to content

Commit 9e27bfc

Browse files
committed
Grow and shrink storage pool in maintenance
1 parent 310fe5e commit 9e27bfc

4 files changed

Lines changed: 86 additions & 94 deletions

File tree

‎test/integration/plugins/ontap/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,13 @@ self.assertEqual(result.state, "Maintenance")
332332

333333
| Suite | File | Tests | What it covers |
334334
| ------- | ------ | ------- | --------------- |
335-
| NFS3 Pool Lifecycle | `nfs3/pool/test_pool_lifecycle.py` | 16 | Create, grow to 300 TiB, reject grow past 300 TiB, safe shrink, disable, resize while disabled, enable, maintenance, resize in maintenance, delete, then re-create with a volume, reject shrink below used capacity, deploy a VM and attach the volume, cleanup |
335+
| NFS3 Pool Lifecycle | `nfs3/pool/test_pool_lifecycle.py` | 16 | Create, grow to 300 TiB, reject grow past 300 TiB, safe shrink, disable, resize while disabled, enable, maintenance, grow and shrink in maintenance, delete, then re-create with a volume, reject shrink below used capacity, deploy a VM and attach the volume, cleanup |
336336
| NFS3 Pool with Volumes | `nfs3/pool/test_pool_with_volumes.py` | 7 | Same + live volume present; negative delete guard |
337337
| NFS3 Zone-Scoped Pool | `nfs3/pool/test_zone_scoped_pool.py` | 4 | Zone scope — all hosts connected via `attachZone` |
338338
| NFS3 Volume Lifecycle | `nfs3/volume/test_volume_lifecycle.py` | 5 | Volume is metadata-only; FlexVol unchanged on delete |
339339
| NFS3 VM + Volume Attach | `nfs3/instance/test_vm_volume_attach.py` | 13 | Full VM lifecycle with stopped-VM qcow2 grow; ROOT on tagged pool seeds/reuses template cache, which survives VM delete |
340340
| NFS3 Template Cache Negative | `nfs3/template/test_template_cache_negative.py` | 3 | Tag mismatch; undersized pool; out-of-band cache delete |
341-
| iSCSI Pool Lifecycle | `iscsi/pool/test_pool_lifecycle.py` | 16 | Create, grow to 300 TiB, reject grow past 300 TiB, safe shrink, disable, resize while disabled, enable, maintenance, resize in maintenance, delete + igroups, then re-create with a volume (LUN), reject shrink below used capacity, deploy a VM and attach the volume, cleanup |
341+
| iSCSI Pool Lifecycle | `iscsi/pool/test_pool_lifecycle.py` | 16 | Create, grow to 300 TiB, reject grow past 300 TiB, safe shrink, disable, resize while disabled, enable, maintenance, grow and shrink in maintenance, delete + igroups, then re-create with a volume (LUN), reject shrink below used capacity, deploy a VM and attach the volume, cleanup |
342342
| iSCSI Pool with Volumes | `iscsi/pool/test_pool_with_volumes.py` | 7 | Same + live LUN present; negative delete guard |
343343
| iSCSI Zone-Scoped Pool | `iscsi/pool/test_zone_scoped_pool.py` | 4 | Zone scope |
344344
| iSCSI Volume Lifecycle | `iscsi/volume/test_volume_lifecycle.py` | 5 | LUN created per CS volume; LUN removed on delete |

‎test/integration/plugins/ontap/TEST_CASES.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,16 @@ Each suite is sequential — tests must run in numbered order; each step builds
5151
| 03 | `test_03_reject_grow_above_max_size` | Reject a grow past the 300 TiB ONTAP FlexVol maximum (overshoots by 1 GiB; asserts ONTAP's autosize-maximum error, not a generic failure such as aggregate space) | test_02 | `CloudstackAPIException`; `capacitybytes` stays at 300 TiB; pool stays `Up` | FlexVol `space.size` unchanged; export policy unchanged | negative |
5252
| 04 | `test_04_shrink_storage_pool` | Safely shrink the original empty pool to its initial capacity | test_02 | `capacitybytes` reaches the safe target; pool stays `Up` | FlexVol `space.size` reaches the safe target; remains `online`; export policy unchanged | positive |
5353
| 05 | `test_05_disable_storage_pool` | Disable the pool (admin operation) | test_04 | `pool.state == "Disabled"` | FlexVol still `online`; export policy still present | positive |
54-
| 06 | `test_06_resize_storage_pool_while_disabled` | Grow then shrink the pool back while it is Disabled | test_05 | Both `updateStoragePool` calls accepted; `capacitybytes` reaches each target; KVM hosts report each resized NFS capacity; `pool.state` stays `"Disabled"` throughout | FlexVol `space.size` reaches each target and stays `online`; export policy still present and still covers every host IP | positive |
54+
| 06 | `test_06_grow_and_shrink_storage_pool_while_disabled` | Grow then shrink the pool back while it is Disabled | test_05 | Both `updateStoragePool` calls accepted; `capacitybytes` reaches each target; KVM hosts report each resized NFS capacity; `pool.state` stays `"Disabled"` throughout | FlexVol `space.size` reaches each target and stays `online`; export policy still present and still covers every host IP | positive |
5555
| 07 | `test_07_enable_storage_pool` | Re-enable the pool | test_06 | `pool.state == "Up"` | FlexVol still `online`; export policy still present | positive |
5656
| 08 | `test_08_enter_maintenance_mode` | Put pool into maintenance (drains new volume allocations) | test_07 | `pool.state == "Maintenance"` | FlexVol still `online`; export policy still present (maintenance is CS-only state) | positive |
57-
| 09 | `test_09_resize_storage_pool_in_maintenance` | Grow the pool while it is in maintenance mode | test_08 | `updateStoragePool` accepted; `capacitybytes` reaches the requested size; `pool.state` stays `"Maintenance"` | FlexVol `space.size` reaches the requested size; remains `online`; export policy unchanged | positive |
57+
| 09 | `test_09_grow_and_shrink_storage_pool_in_maintenance` | Grow then shrink the pool back while it is in Maintenance | test_08 | Both `updateStoragePool` calls accepted; `capacitybytes` reaches each target; `pool.state` stays `"Maintenance"` throughout | FlexVol `space.size` reaches each target and stays `online`; export policy still present | positive |
5858
| 10 | `test_10_cancel_maintenance_mode` | Cancel maintenance, return pool to service | test_09 | `pool.state == "Up"` | FlexVol still `online`; export policy still present | positive |
5959
| 11 | `test_11_delete_pool_from_maintenance` | Enter maintenance then permanently delete the original pool | test_10 | Pool no longer returned by `listStoragePools` (CS 431 error expected on ID lookup) | FlexVol and export policy deleted | positive |
6060
| 12 | `test_12_create_volume_on_pool` | Create a fresh pool and allocate a CloudStack data volume | test_11 | New pool is `Up`; `createVolume` returns a volume | FlexVol `online`; export policy present | positive |
6161
| 13 | `test_13_create_vm_and_attach_volume` | Deploy a VM and attach the ONTAP data volume to it | test_12 | VM reaches `Running`; volume reports `virtualmachineid` equal to the VM id; VM still `Running` after attach; pool capacity unchanged | FlexVol still `online`; volume data file materialised in the FlexVol (NFS3 creates it lazily at attach) | positive |
6262
| 14 | `test_14_reject_shrink_below_used_capacity` | Reject shrink below the used space of the VM-attached volume, with the target held above the ONTAP FlexVol minimum. Writes incompressible data through the ONTAP files API when the VM-attached thin volume leaves used space under the minimum, and removes it before returning | test_13 (`pool`, `volume`, `vm`) | `CloudstackAPIException`; volume remains listed with unchanged `id`/`state`/`size`/`poolid`; pool capacity unchanged | FlexVol size and export policy unchanged; used space stays above the FlexVol minimum | negative |
63-
| 15 | `test_15_resize_pool_with_vm_attached` | Grow then shrink the pool back while the volume is attached to the running VM | test_13 (`vm`, `volume`) | Both resizes reach the requested capacity; pool stays `Up`; VM stays `Running` and keeps `virtualmachineid` on the volume | FlexVol reaches each size and stays `online`; export policy still covers every host IP | positive |
63+
| 15 | `test_15_grow_and_shrink_pool_with_vm_attached` | Grow then shrink the pool back while the volume is attached to the running VM | test_13 (`vm`, `volume`) | Both resizes reach the requested capacity; pool stays `Up`; VM stays `Running` and keeps `virtualmachineid` on the volume | FlexVol reaches each size and stays `online`; export policy still covers every host IP | positive |
6464
| 16 | `test_16_delete_volume_and_pool` | Detach and destroy the VM, delete the volume, then force-delete the pool | test_15 | VM destroyed; volume and pool no longer listed | FlexVol and export policy deleted | cleanup |
6565

6666
---
@@ -156,16 +156,16 @@ Each suite is sequential — tests must run in numbered order; each step builds
156156
| 03 | `test_03_reject_grow_above_max_size` | Reject a grow past the 300 TiB ONTAP FlexVol maximum (overshoots by 1 GiB; asserts ONTAP's autosize-maximum error, not a generic failure such as aggregate space) | test_02 | `CloudstackAPIException`; `capacitybytes` stays at 300 TiB; pool stays `Up` | FlexVol `space.size` unchanged; igroups unchanged | negative |
157157
| 04 | `test_04_shrink_storage_pool` | Safely shrink the original empty pool to its initial capacity | test_02 | `capacitybytes` reaches the safe target; pool stays `Up` | FlexVol reaches the safe target and remains `online`; igroups remain present | positive |
158158
| 05 | `test_05_disable_storage_pool` | Disable the pool | test_04 | `pool.state == "Disabled"` | FlexVol still `online` | positive |
159-
| 06 | `test_06_resize_storage_pool_while_disabled` | Grow then shrink the pool back while it is Disabled | test_05 | Both `updateStoragePool` calls accepted; `capacitybytes` reaches each target; `pool.state` stays `"Disabled"` throughout | FlexVol `space.size` reaches each target and stays `online`; per-host igroups still present | positive |
159+
| 06 | `test_06_grow_and_shrink_storage_pool_while_disabled` | Grow then shrink the pool back while it is Disabled | test_05 | Both `updateStoragePool` calls accepted; `capacitybytes` reaches each target; `pool.state` stays `"Disabled"` throughout | FlexVol `space.size` reaches each target and stays `online`; per-host igroups still present | positive |
160160
| 07 | `test_07_enable_storage_pool` | Re-enable the pool | test_06 | `pool.state == "Up"` | FlexVol still `online` | positive |
161161
| 08 | `test_08_enter_maintenance_mode` | Put pool into maintenance | test_07 | `pool.state == "Maintenance"` | FlexVol still `online`; igroups unchanged | positive |
162-
| 09 | `test_09_resize_storage_pool_in_maintenance` | Grow the pool while it is in maintenance mode | test_08 | `updateStoragePool` accepted; `capacitybytes` reaches the requested size; `pool.state` stays `"Maintenance"` | FlexVol reaches the requested size and remains `online`; igroups unchanged | positive |
162+
| 09 | `test_09_grow_and_shrink_storage_pool_in_maintenance` | Grow then shrink the pool back while it is in Maintenance | test_08 | Both `updateStoragePool` calls accepted; `capacitybytes` reaches each target; `pool.state` stays `"Maintenance"` throughout | FlexVol `space.size` reaches each target and stays `online`; per-host igroups still present | positive |
163163
| 10 | `test_10_cancel_maintenance_mode` | Cancel maintenance | test_09 | `pool.state == "Up"` | FlexVol still `online` | positive |
164164
| 11 | `test_11_enter_maintenance_and_delete_pool` | Enter maintenance then delete the original pool | test_10 | Pool no longer listed | FlexVol and all host igroups deleted | positive |
165165
| 12 | `test_12_create_volume_on_pool` | Create a fresh pool and allocate a CloudStack volume | test_11 | New pool is `Up`; `createVolume` returns a volume | FlexVol `online`; at least one LUN present | positive |
166166
| 13 | `test_13_create_vm_and_attach_volume` | Deploy a VM and attach the ONTAP data volume (LUN) to it | test_12 | VM reaches `Running`; volume reports `virtualmachineid` equal to the VM id; VM still `Running` after attach | FlexVol still `online`; LUN still present; per-host igroups unchanged | positive |
167167
| 14 | `test_14_reject_shrink_below_used_capacity` | Reject shrink below the used space of the VM-attached LUN, with the target held above the ONTAP FlexVol minimum. Writes incompressible data through the ONTAP files API when the VM-attached thin volume leaves used space under the minimum, and removes it before returning | test_13 (`pool`, `volume`, `vm`) | `CloudstackAPIException`; volume remains listed with unchanged `id`/`state`/`size`/`poolid`; pool capacity unchanged | FlexVol size and LUN uuid/name list unchanged; used space stays above the FlexVol minimum | negative |
168-
| 15 | `test_15_resize_pool_with_vm_attached` | Grow then shrink the pool back while the volume (LUN) is attached to the running VM | test_13 (`vm`, `volume`) | Both resizes reach the requested capacity; pool stays `Up`; VM stays `Running` and keeps `virtualmachineid` on the volume | FlexVol reaches each size and stays `online`; LUN still present | positive |
168+
| 15 | `test_15_grow_and_shrink_pool_with_vm_attached` | Grow then shrink the pool back while the volume (LUN) is attached to the running VM | test_13 (`vm`, `volume`) | Both resizes reach the requested capacity; pool stays `Up`; VM stays `Running` and keeps `virtualmachineid` on the volume | FlexVol reaches each size and stays `online`; LUN still present | positive |
169169
| 16 | `test_16_delete_volume_and_pool` | Detach and destroy the VM, delete the volume, then force-delete the pool | test_15 | VM destroyed; volume and pool no longer listed | LUN, FlexVol, and igroups deleted | cleanup |
170170

171171
---

‎test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py‎

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
06 Grow and shrink the pool while it is disabled
3232
07 Enable storage pool
3333
08 Enter maintenance mode
34-
09 Resize storage pool while in maintenance mode
34+
09 Grow and shrink the pool while it is in maintenance mode
3535
10 Cancel maintenance mode
3636
11 Enter maintenance mode and delete the storage pool
3737
12 Create a new pool and allocate a CloudStack data volume (LUN created)
@@ -565,11 +565,11 @@ def test_05_disable_storage_pool(self):
565565
)
566566

567567
# ------------------------------------------------------------------
568-
# Step 06 - Resize storage pool while disabled
568+
# Step 06 - Grow and shrink the pool while it is disabled
569569
# ------------------------------------------------------------------
570570

571571
@attr(tags=["iscsi_workflow"], required_hardware=True)
572-
def test_06_resize_storage_pool_while_disabled(self):
572+
def test_06_grow_and_shrink_storage_pool_while_disabled(self):
573573
"""
574574
Grow and shrink the disabled pool and verify:
575575
- Both capacity updates are accepted
@@ -695,19 +695,17 @@ def test_08_enter_maintenance_mode(self):
695695
)
696696

697697
# ------------------------------------------------------------------
698-
# Step 09 - Resize storage pool while in maintenance mode
698+
# Step 09 - Grow and shrink the pool while it is in maintenance mode
699699
# ------------------------------------------------------------------
700700

701701
@attr(tags=["iscsi_workflow"], required_hardware=True)
702-
def test_09_resize_storage_pool_in_maintenance(self):
702+
def test_09_grow_and_shrink_storage_pool_in_maintenance(self):
703703
"""
704-
Grow the pool while it is in maintenance mode and verify:
705-
- updateStoragePool is accepted while the pool is in Maintenance
706-
- CloudStack reports the new capacity
707-
- ONTAP: FlexVol is resized and still online
708-
- The pool stays in Maintenance throughout (resize must not
709-
implicitly return it to Up)
710-
- ONTAP: per-host igroups are unchanged
704+
Grow and shrink the pool while it is in maintenance mode and verify:
705+
- Both capacity updates are accepted
706+
- CloudStack and ONTAP reach each requested size
707+
- The pool remains in Maintenance throughout
708+
- The FlexVol remains online and per-host igroups are unchanged
711709
"""
712710
self.assertIsNotNone(
713711
self.__class__.pool, "Pool absent - test_01 must pass first"
@@ -719,44 +717,42 @@ def test_09_resize_storage_pool_in_maintenance(self):
719717
self.assertEqual(
720718
listed[0].state, "Maintenance",
721719
"Pool must be in Maintenance - test_08 must pass first, got '%s'"
722-
% listed[0].state
720+
% listed[0].state,
723721
)
724722

725723
ontap_vol = self.ontap.get_volume(pool.name)
726724
self.assertIsNotNone(
727725
ontap_vol, "ONTAP FlexVol missing before maintenance resize"
728726
)
729-
current_size = max(
727+
original_size = max(
730728
int(getattr(listed[0], "capacitybytes", 0) or 0),
731729
int(ontap_vol.get("space", {}).get("size", 0) or 0),
732730
)
733-
requested_size = current_size + TestData.ONTAP_MIN_VOLUME_SIZE
734-
735-
log_progress(
736-
logger, "info",
737-
"Resizing iSCSI pool '%s' while in Maintenance: current=%d B, "
738-
"requested=%d B",
739-
pool.name, current_size, requested_size,
740-
)
741-
742-
cmd = updateStoragePoolAPI.updateStoragePoolCmd()
743-
cmd.id = pool.id
744-
cmd.capacitybytes = requested_size
745-
self.apiClient.updateStoragePool(cmd)
731+
grow_target = original_size + TestData.ONTAP_MIN_VOLUME_SIZE
746732

747-
resized_pool = self._poll_pool_capacity(
748-
pool.id, requested_size, timeout=120
749-
)
750-
self.assertEqual(
751-
resized_pool.state, "Maintenance",
752-
"Pool should remain in Maintenance after resize, got '%s'"
753-
% resized_pool.state
754-
)
733+
for target, operation in (
734+
(grow_target, "grow"),
735+
(original_size, "shrink")):
736+
log_progress(
737+
logger, "info",
738+
"%s iSCSI pool '%s' while in Maintenance: target=%d B",
739+
operation.capitalize(), pool.name, target,
740+
)
741+
cmd = updateStoragePoolAPI.updateStoragePoolCmd()
742+
cmd.id = pool.id
743+
cmd.capacitybytes = target
744+
self.apiClient.updateStoragePool(cmd)
755745

756-
resized_ontap_vol = self._poll_ontap_volume_size(
757-
pool.name, requested_size, timeout=120
758-
)
759-
self.assertEqual(resized_ontap_vol.get("state"), "online")
746+
resized = self._poll_pool_capacity(pool.id, target, timeout=120)
747+
self.assertEqual(
748+
resized.state, "Maintenance",
749+
"Pool should remain in Maintenance after %s, got '%s'"
750+
% (operation, resized.state),
751+
)
752+
resized_ontap = self._poll_ontap_volume_size(
753+
pool.name, target, timeout=120
754+
)
755+
self.assertEqual(resized_ontap.get("state"), "online")
760756

761757
for host in self.cluster_hosts:
762758
iqn = (
@@ -767,7 +763,7 @@ def test_09_resize_storage_pool_in_maintenance(self):
767763
igroup_name = _igroup_name(self.svm_name, host.name)
768764
self.assertIsNotNone(
769765
self.ontap.get_igroup(self.svm_name, igroup_name),
770-
"ONTAP igroup '%s' disappeared after maintenance resize"
766+
"ONTAP igroup '%s' disappeared during maintenance resize"
771767
% igroup_name,
772768
)
773769

@@ -1130,11 +1126,11 @@ def test_14_reject_shrink_below_used_capacity(self):
11301126
self._delete_filler_file(pool.name, filler_name)
11311127

11321128
# ------------------------------------------------------------------
1133-
# Step 15 - Resize the pool while the VM holds the volume
1129+
# Step 15 - Grow and shrink the pool while the VM holds the volume
11341130
# ------------------------------------------------------------------
11351131

11361132
@attr(tags=["iscsi_workflow"], required_hardware=True)
1137-
def test_15_resize_pool_with_vm_attached(self):
1133+
def test_15_grow_and_shrink_pool_with_vm_attached(self):
11381134
"""
11391135
Grow the pool and shrink it straight back while the volume is
11401136
attached to the running VM from test_13, so resize is exercised

0 commit comments

Comments
 (0)