Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions test/integration/plugins/ontap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ for the deployment, health-gate, and artifact contracts.
test/integration/plugins/ontap/
├── ontap.cfg # Environment config (IPs, credentials, zone info)
├── ontap_test_base.py # Shared base class and ONTAP REST client
├── TEST_CASES.md # Full test case reference table (72 tests)
├── TEST_CASES.md # Full test case reference table (93 tests)
├── README.md # This file
│
├── nfs3/
Expand Down Expand Up @@ -84,7 +84,7 @@ The ONTAP plugin (`plugins/storage/volume/ontap/`) integrates CloudStack's prima

| Aspect | NFS3 | iSCSI |
|--------|------|-------|
| ONTAP object per pool | FlexVol + export policy | FlexVol + igroup per KVM host |
| ONTAP object per pool | FlexVol + export policy | FlexVol; igroups are shared per KVM host and SVM |
| ONTAP object per CS volume | None (FlexVol is shared) | One LUN inside the FlexVol |
| Host connectivity | NFS mount | iSCSI login (IQN-based) |
| Volume detach from running VM | Works via virtio hot-unplug | Requires KVM guest to support SCSI hot-unplug |
Expand Down Expand Up @@ -270,14 +270,16 @@ pool = self.__class__.pool
self.pool = pool
```

**Guard assertion at the start of every test (except test_01)**
**Guard assertion at the start of every test that depends on a previous one**

Every test after the first starts with an assertion that the previous step's resource exists. This produces a clear, readable failure message instead of a confusing `AttributeError`:
Every test in a sequential workflow starts with an assertion that the previous step's resource exists. This produces a clear, readable failure message instead of a confusing `AttributeError`:
```python
def test_03_enable_storage_pool(self):
self.assertIsNotNone(self.__class__.pool, "Pool absent — test_01 must pass first")
def test_05_enable_storage_pool(self):
self.assertIsNotNone(self.__class__.pool, "Pool absent — test_03 must pass first")
```

Isolated negative tests own everything they create, so they carry no such guard. In the pool lifecycle and zone-scoped suites the two create-rejection negatives are numbered `test_01` and `test_02` so that a misconfigured SVM fails within a minute rather than after the full workflow.

**Creating a storage pool — always use indexed `details[N].key` syntax**

The CloudStack API for `createStoragePool` requires plugin details to be passed as indexed parameters. **Never call `StoragePool.create()` directly** — it does not support this syntax:
Expand All @@ -296,6 +298,15 @@ result = self._poll_pool_state(pool.id, "Maintenance", timeout=120)
self.assertEqual(result.state, "Maintenance")
```

**Shared iSCSI igroups**

iSCSI igroups are named from the host UUID and SVM, not from the storage pool.
Each iSCSI suite snapshots existing host igroups during `setUpClass()` and
checks that pool-only operations preserve that baseline. Tests may therefore
run while another ONTAP iSCSI pool uses the same SVM. The negative tests that
deliberately delete igroups still require exclusive SVM use and skip when
another ONTAP pool is present.

---

## Shared base — `ontap_test_base.py`
Expand All @@ -321,7 +332,7 @@ self.assertEqual(result.state, "Maintenance")
| `get_data_lifs(svm_name)` | NFS data LIF count | NFS3 pool lifecycle |
| `get_igroup(svm_name, name)` | iSCSI igroup existence and initiator list | iSCSI suites |
| `list_luns_in_volume(svm_name, vol_name)` | LUNs present in a FlexVol | iSCSI volume/instance suites |
| `list_lun_maps_for_volume(svm_name, vol_name)` | Active LUN-maps for a volume | iSCSI instance suite |
| `list_lun_maps_for_volume(svm_name, vol_name)` | Active LUN-maps for a volume | iSCSI pool-with-volumes/instance suites |
| `list_files_in_volume(svm_name, vol_name)` | Files inside a FlexVol | NFS3 instance suite |

---
Expand All @@ -330,15 +341,15 @@ self.assertEqual(result.state, "Maintenance")

| Suite | File | Tests | What it covers |
|-------|------|-------|---------------|
| NFS3 Pool Lifecycle | `nfs3/pool/test_pool_lifecycle.py` | 8 | Create, disable, enable, maintenance, delete |
| NFS3 Pool with Volumes | `nfs3/pool/test_pool_with_volumes.py` | 7 | Same + live volume present; negative delete guard |
| NFS3 Zone-Scoped Pool | `nfs3/pool/test_zone_scoped_pool.py` | 4 | Zone scope — all hosts connected via `attachZone` |
| NFS3 Pool Lifecycle | `nfs3/pool/test_pool_lifecycle.py` | 12 | Existing lifecycle plus duplicate-name and aggregate-space create rejects, and empty-pool deletion with pre-deleted FlexVol/export policy |
| NFS3 Pool with Volumes | `nfs3/pool/test_pool_with_volumes.py` | 12 | Existing lifecycle plus deletion with pre-deleted FlexVol/export policy, and host cases for an inactive libvirt pool, a read-only NFS mount, and a deleted mount point |
| NFS3 Zone-Scoped Pool | `nfs3/pool/test_zone_scoped_pool.py` | 4 | Zone-scoped pool create, disable, enable, and delete |
| NFS3 Volume Lifecycle | `nfs3/volume/test_volume_lifecycle.py` | 5 | Volume is metadata-only; FlexVol unchanged on delete |
| NFS3 VM + Volume Attach | `nfs3/instance/test_vm_volume_attach.py` | 10 | Full VM lifecycle with hot-plug/detach; ROOT on tagged pool seeds/reuses template cache, which survives VM delete |
| NFS3 Template Cache Negative | `nfs3/template/test_template_cache_negative.py` | 3 | Tag mismatch; undersized pool; out-of-band cache delete |
| iSCSI Pool Lifecycle | `iscsi/pool/test_pool_lifecycle.py` | 8 | Create, disable, enable, maintenance, delete + igroups |
| iSCSI Pool with Volumes | `iscsi/pool/test_pool_with_volumes.py` | 7 | Same + live LUN present; negative delete guard |
| iSCSI Zone-Scoped Pool | `iscsi/pool/test_zone_scoped_pool.py` | 4 | Zone scope |
| iSCSI Pool Lifecycle | `iscsi/pool/test_pool_lifecycle.py` | 12 | Existing lifecycle plus duplicate-name and aggregate-space create rejects, and empty-pool deletion with pre-deleted FlexVol/igroups |
| iSCSI Pool with Volumes | `iscsi/pool/test_pool_with_volumes.py` | 13 | Existing lifecycle plus deletion with pre-deleted FlexVol/igroups, maintenance with pre-deleted LUN maps, and host cases for a logged-out iSCSI session, an existing session during volume delete, and a replaced by-path symlink |
| iSCSI Zone-Scoped Pool | `iscsi/pool/test_zone_scoped_pool.py` | 4 | Zone-scoped pool create, disable, enable, and delete |
| iSCSI Volume Lifecycle | `iscsi/volume/test_volume_lifecycle.py` | 5 | LUN created per CS volume; LUN removed on delete |
| iSCSI VM + Volume Attach | `iscsi/instance/test_vm_volume_attach.py` | 10 | Full VM lifecycle; LUN-maps on VM start/stop/detach; ROOT on tagged pool seeds/reuses `cs_tmpl_*` LUN cache |
| iSCSI Template Cache Negative | `iscsi/template/test_template_cache_negative.py` | 3 | Tag mismatch; undersized pool; out-of-band cache delete |
Expand Down
Loading
Loading