From 64474bf5751273178df4979bbc8be194be8909b8 Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Tue, 18 Aug 2026 15:14:55 +0530 Subject: [PATCH 1/5] pilot changes --- .../main/java/com/cloud/storage/Storage.java | 3 +- .../java/com/cloud/storage/StorageTest.java | 14 ++++ .../StorageSystemDataMotionStrategy.java | 4 +- .../kvm/storage/KVMStorageProcessor.java | 6 +- .../kvm/storage/OntapSanStorageAdaptor.java | 40 ++++++++++ .../storage/OntapSanStorageAdaptorTest.java | 78 +++++++++++++++++++ .../driver/OntapPrimaryDatastoreDriver.java | 43 ++++++++-- .../OntapPrimaryDatastoreLifecycle.java | 2 +- .../OntapPrimaryDatastoreDriverTest.java | 29 ++++++- .../OntapPrimaryDatastoreLifecycleTest.java | 48 ++++++++++++ .../main/java/com/cloud/api/ApiDBUtils.java | 5 +- test/integration/plugins/ontap/TEST_CASES.md | 4 +- .../iscsi/instance/test_vm_volume_attach.py | 6 +- .../ontap/iscsi/pool/test_pool_lifecycle.py | 12 +-- .../iscsi/pool/test_pool_with_volumes.py | 6 +- .../ontap/iscsi/pool/test_zone_scoped_pool.py | 6 +- 16 files changed, 272 insertions(+), 34 deletions(-) create mode 100644 plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptor.java create mode 100644 plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptorTest.java diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java index 3511b4e88cb9..6d5736883a89 100644 --- a/api/src/main/java/com/cloud/storage/Storage.java +++ b/api/src/main/java/com/cloud/storage/Storage.java @@ -185,7 +185,8 @@ public static enum StoragePoolType { Linstor(true, true, EncryptionSupport.Storage), DatastoreCluster(true, true, EncryptionSupport.Unsupported), // for VMware, to abstract pool of clusters StorPool(true, true, EncryptionSupport.Hypervisor), - FiberChannel(true, true, EncryptionSupport.Unsupported); // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-) + FiberChannel(true, true, EncryptionSupport.Unsupported), // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-) + OntapSAN(true, false, EncryptionSupport.Unsupported); // NetApp ONTAP SAN (iSCSI): one FlexVol per pool, one LUN per volume private final boolean shared; private final boolean overProvisioning; diff --git a/api/src/test/java/com/cloud/storage/StorageTest.java b/api/src/test/java/com/cloud/storage/StorageTest.java index 2bcc28e2b4b6..f431afd6dfd0 100644 --- a/api/src/test/java/com/cloud/storage/StorageTest.java +++ b/api/src/test/java/com/cloud/storage/StorageTest.java @@ -49,6 +49,7 @@ public void isSharedStoragePool() { Assert.assertTrue(StoragePoolType.ManagedNFS.isShared()); Assert.assertTrue(StoragePoolType.DatastoreCluster.isShared()); Assert.assertTrue(StoragePoolType.Linstor.isShared()); + Assert.assertTrue(StoragePoolType.OntapSAN.isShared()); } @Test @@ -73,6 +74,19 @@ public void supportsOverProvisioningTestAllStoragePoolTypes() { Assert.assertFalse(StoragePoolType.ManagedNFS.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.DatastoreCluster.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.Linstor.supportsOverProvisioning()); + Assert.assertFalse(StoragePoolType.OntapSAN.supportsOverProvisioning()); + } + + /** + * OntapSAN was split out of the shared Iscsi bucket and must stay attribute-identical to it, + * so that introducing the type changes no behaviour. Loosening either attribute is a + * deliberate decision that belongs in its own change. + */ + @Test + public void ontapSanMirrorsIscsiAttributes() { + Assert.assertEquals(StoragePoolType.Iscsi.isShared(), StoragePoolType.OntapSAN.isShared()); + Assert.assertEquals(StoragePoolType.Iscsi.supportsOverProvisioning(), StoragePoolType.OntapSAN.supportsOverProvisioning()); + Assert.assertEquals(StoragePoolType.Iscsi.encryptionSupportMode(), StoragePoolType.OntapSAN.encryptionSupportMode()); } @Test diff --git a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java index 7674f1ce25a1..ba11834a5fa8 100644 --- a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java +++ b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java @@ -616,8 +616,8 @@ private void handleVolumeMigrationFromManagedStorageToNonManagedStorage(VolumeIn private void verifyFormatWithPoolType(ImageFormat imageFormat, StoragePoolType poolType) { if (imageFormat != ImageFormat.VHD && imageFormat != ImageFormat.OVA && imageFormat != ImageFormat.QCOW2 && !(imageFormat == ImageFormat.RAW && (StoragePoolType.PowerFlex == poolType || - StoragePoolType.FiberChannel == poolType))) { - throw new CloudRuntimeException(String.format("Only the following image types are currently supported: %s, %s, %s, %s (for PowerFlex and FiberChannel)", + StoragePoolType.FiberChannel == poolType || StoragePoolType.OntapSAN == poolType))) { + throw new CloudRuntimeException(String.format("Only the following image types are currently supported: %s, %s, %s, %s (for PowerFlex, FiberChannel and OntapSAN)", ImageFormat.VHD.toString(), ImageFormat.OVA.toString(), ImageFormat.QCOW2.toString(), ImageFormat.RAW.toString())); } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index 11acb9546b53..c9eee5c5dbf2 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -415,7 +415,8 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) { StoragePoolType.PowerFlex, StoragePoolType.Linstor, StoragePoolType.FiberChannel, - StoragePoolType.CLVM).contains(primaryPool.getType())) { + StoragePoolType.CLVM, + StoragePoolType.OntapSAN).contains(primaryPool.getType())) { newTemplate.setFormat(ImageFormat.RAW); } else { newTemplate.setFormat(ImageFormat.QCOW2); @@ -3431,7 +3432,8 @@ private Storage.ImageFormat getFormat(StoragePoolType poolType) { StoragePoolType.PowerFlex, StoragePoolType.Linstor, StoragePoolType.FiberChannel, - StoragePoolType.CLVM).contains(poolType)) { + StoragePoolType.CLVM, + StoragePoolType.OntapSAN).contains(poolType)) { return ImageFormat.RAW; } else { return ImageFormat.QCOW2; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptor.java new file mode 100644 index 000000000000..c90bbcb19ae2 --- /dev/null +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptor.java @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.hypervisor.kvm.storage; + +import com.cloud.storage.Storage.StoragePoolType; + +/** + * Serves {@link StoragePoolType#OntapSAN} pools, which are ONTAP FlexVols exposed over iSCSI with one + * LUN per CloudStack volume. The host-side handling is identical to a generic iSCSI target, so the + * behaviour is inherited wholesale from {@link IscsiAdmStorageAdaptor}. + * + * The class exists so that ONTAP-specific host behaviour can diverge here without altering the storage + * path of the other vendors that register as {@link StoragePoolType#Iscsi} (SolidFire, Datera, Nexenta + * and CloudByte), which all share the superclass. + * + * This must stay in the {@code com.cloud.hypervisor.kvm.storage} package: {@link KVMStoragePoolManager} + * discovers adaptors by a Reflections scan of that package alone, and an unregistered type silently + * falls back to {@link LibvirtStorageAdaptor} rather than failing at startup. + */ +public class OntapSanStorageAdaptor extends IscsiAdmStorageAdaptor { + + @Override + public StoragePoolType getStoragePoolType() { + return StoragePoolType.OntapSAN; + } +} diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptorTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptorTest.java new file mode 100644 index 000000000000..147a555256a2 --- /dev/null +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptorTest.java @@ -0,0 +1,78 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.hypervisor.kvm.storage; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.junit.Test; +import org.reflections.Reflections; + +import com.cloud.storage.Storage.StoragePoolType; + +public class OntapSanStorageAdaptorTest { + + @Test + public void getStoragePoolTypeReturnsOntapSan() { + assertEquals(StoragePoolType.OntapSAN, new OntapSanStorageAdaptor().getStoragePoolType()); + } + + @Test + public void createdPoolCarriesOntapSanTypeAndRawFormat() { + OntapSanStorageAdaptor adaptor = new OntapSanStorageAdaptor(); + + KVMStoragePool pool = adaptor.createStoragePool("ontap-san-pool-uuid", "10.0.0.1", 3260, null, null, + StoragePoolType.OntapSAN, null, true); + + assertEquals(StoragePoolType.OntapSAN, pool.getType()); + // Attach builds a block-based disk off the physical disk format rather than the pool type, + // which is why splitting OntapSAN out of Iscsi leaves the generated domain XML unchanged. + assertEquals(PhysicalDiskFormat.RAW, pool.getDefaultFormat()); + assertSame(pool, adaptor.getStoragePool("ontap-san-pool-uuid")); + } + + /** + * KVMStoragePoolManager discovers adaptors by a Reflections scan of its own package, instantiating + * each concrete implementation through a no-arg constructor and keying it on getStoragePoolType(). + * A type with no adaptor silently falls back to LibvirtStorageAdaptor instead of failing at + * startup, so this reproduces the discovery preconditions rather than waiting for the symptom. + * The manager itself is not constructed here because doing so also instantiates + * MultipathSCSIAdapterBase, which requires agent scripts resolvable from the working directory. + */ + @Test + public void adaptorSatisfiesThePoolManagerDiscoveryContract() throws ReflectiveOperationException { + String scannedPackage = KVMStoragePoolManager.class.getPackage().getName(); + Set> discovered = + new Reflections(scannedPackage).getSubTypesOf(StorageAdaptor.class); + + assertTrue("OntapSanStorageAdaptor must live in " + scannedPackage + " to be discovered", + discovered.contains(OntapSanStorageAdaptor.class)); + assertFalse("An abstract adaptor is skipped by the scan", + Modifier.isAbstract(OntapSanStorageAdaptor.class.getModifiers())); + + StorageAdaptor adaptor = OntapSanStorageAdaptor.class.getDeclaredConstructor().newInstance(); + assertEquals(StoragePoolType.OntapSAN, adaptor.getStoragePoolType()); + assertEquals("The superclass must keep serving the other iSCSI vendors", + StoragePoolType.Iscsi, new IscsiAdmStorageAdaptor().getStoragePoolType()); + } +} diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java index d6b7b089d6bf..5a4c3bd58d0a 100644 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java @@ -160,8 +160,8 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet volumeVO.setPoolType(storagePool.getPoolType()); volumeVO.setPoolId(storagePool.getId()); - volumeVO.setFormat(getImageFormatByHypervisor(storagePool.getHypervisor())); - logger.info("createAsync: Volume format set to [{}] for hypervisor [{}]", volumeVO.getFormat(), storagePool.getHypervisor()); + volumeVO.setFormat(getImageFormat(storagePool)); + logger.info("createAsync: Volume format set to [{}] for pool type [{}]", volumeVO.getFormat(), storagePool.getPoolType()); if (ProtocolType.ISCSI.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL))) { String lunName = created != null && created.getLun() != null ? created.getLun().getName() : null; @@ -364,8 +364,26 @@ public boolean canCopy(DataObject srcData, DataObject destData) { return false; } + /** + * Resize is not implemented yet. + * + *

This reports the failure through the callback rather than throwing or returning silently. + * By the time the driver is called, {@code VolumeServiceImpl.resize} has already moved the volume + * to {@link com.cloud.storage.Volume.State#Resizing} and is blocked on {@code AsyncCallFuture.get()}, + * which takes no timeout. Returning without completing the callback parks that job thread forever + * and strands the volume in {@code Resizing}; throwing completes the future but leaves the state + * behind. Going through the callback lets {@code resizeVolumeCallback} fire + * {@code Event.OperationFailed}, which returns the volume to {@code Ready}.

+ */ @Override - public void resize(DataObject data, AsyncCompletionCallback callback) {} + public void resize(DataObject data, AsyncCompletionCallback callback) { + String errMsg = "Resizing a volume is not supported by the NetApp ONTAP storage plugin"; + logger.warn("resize: {} - volume [{}]", errMsg, data != null ? data.getId() : null); + + CreateCmdResult result = new CreateCmdResult(null, new Answer(null, false, errMsg)); + result.setResult(errMsg); + callback.complete(result); + } @Override public ChapInfo getChapInfo(DataObject dataObject) { @@ -988,11 +1006,22 @@ private String buildSnapshotName(String cloudStackSnapshotName, long snapshotId) } - private Storage.ImageFormat getImageFormatByHypervisor(HypervisorType hypervisorType) { - if (HypervisorType.KVM.equals(hypervisorType)) { - return Storage.ImageFormat.QCOW2; + /** + * Resolves the image format to record against a volume on the given pool. + * + *

The format is a property of the backing object, not of the hypervisor. An iSCSI volume is a + * bare ONTAP LUN that the guest sees as a block device, so it is {@link Storage.ImageFormat#RAW}; + * an NFS volume is a qcow2 file inside the FlexVol. Reporting RAW for a LUN is what lets core + * permit shrink and skip the qcow2-only host-side operations that do not apply to a block device.

+ */ + private Storage.ImageFormat getImageFormat(StoragePoolVO storagePool) { + HypervisorType hypervisorType = storagePool.getHypervisor(); + if (!HypervisorType.KVM.equals(hypervisorType)) { + throw new CloudRuntimeException("Unsupported hypervisor [" + hypervisorType + "] for ONTAP image format resolution"); } - throw new CloudRuntimeException("Unsupported hypervisor [" + hypervisorType + "] for ONTAP image format resolution"); + return Storage.StoragePoolType.OntapSAN.equals(storagePool.getPoolType()) + ? Storage.ImageFormat.RAW + : Storage.ImageFormat.QCOW2; } /** * Persists snapshot metadata in snapshot_details table. diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java index c002db728dd1..de94f6956a4c 100755 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java @@ -184,7 +184,7 @@ public DataStore initialize(Map dsInfos) { logger.info("Setting NFS path for storage pool: " + path + ", port: " + port + " with mount option: vers=3"); break; case ISCSI: - parameters.setType(Storage.StoragePoolType.Iscsi); + parameters.setType(Storage.StoragePoolType.OntapSAN); path = storageStrategy.getStoragePath(); port = OntapStorageConstants.ISCSI_PORT; logger.info("Setting iSCSI path for storage pool: " + path + ", port: " + port); diff --git a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java index bad8168ba86d..547e9bfee518 100644 --- a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java +++ b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java @@ -167,7 +167,7 @@ void testCreateAsync_VolumeWithISCSI_Success() { when(storagePoolDao.findById(1L)).thenReturn(storagePool); when(storagePool.getId()).thenReturn(1L); - when(storagePool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + when(storagePool.getPoolType()).thenReturn(Storage.StoragePoolType.OntapSAN); when(storagePool.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM); when(storagePoolDetailsDao.listDetailsKeyPairs(1L)).thenReturn(storagePoolDetails); @@ -204,7 +204,9 @@ void testCreateAsync_VolumeWithISCSI_Success() { verify(volumeDetailsDao).addDetail(eq(100L), eq(OntapStorageConstants.LUN_DOT_UUID), eq("lun-uuid-123"), eq(false)); verify(volumeDetailsDao).addDetail(eq(100L), eq(OntapStorageConstants.LUN_DOT_NAME), eq("/vol/vol1/lun1"), eq(false)); - verify(volumeVO).setFormat(Storage.ImageFormat.QCOW2); + // A LUN is a block device, not a qcow2 file. Recording RAW is what lets core permit shrink + // and skip the qcow2-only host-side operations. + verify(volumeVO).setFormat(Storage.ImageFormat.RAW); verify(volumeDao).update(eq(100L), any(VolumeVO.class)); } } @@ -248,11 +250,34 @@ void testCreateAsync_VolumeWithNFS_Success() { CreateCmdResult result = resultCaptor.getValue(); assertNotNull(result); assertTrue(result.isSuccess()); + // NFS volumes really are qcow2 files inside the FlexVol, so they keep QCOW2 while + // iSCSI LUNs on an OntapSAN pool are recorded as RAW. verify(volumeVO).setFormat(Storage.ImageFormat.QCOW2); verify(volumeDao).update(eq(100L), any(VolumeVO.class)); } } + /** + * Resize is unimplemented, but it must still answer. VolumeServiceImpl.resize has already moved the + * volume to Resizing and is blocked on a future with no timeout, so returning without completing the + * callback would park the job thread and strand the volume. Reporting the failure through the + * callback is what lets resizeVolumeCallback fire OperationFailed and restore the volume to Ready. + */ + @Test + void testResize_ReportsUnsupportedThroughTheCallback() { + when(volumeInfo.getId()).thenReturn(100L); + AsyncCompletionCallback resizeCallback = mock(AsyncCompletionCallback.class); + + driver.resize(volumeInfo, resizeCallback); + + ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(CreateCmdResult.class); + verify(resizeCallback).complete(resultCaptor.capture()); + + CreateCmdResult result = resultCaptor.getValue(); + assertTrue(result.isFailed()); + assertTrue(result.getResult().contains("not supported")); + } + @Test void testDeleteAsync_NullStore_ThrowsException() { ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(CommandResult.class); diff --git a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java index ed538de4a49c..e72ad029703a 100644 --- a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java +++ b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedStatic; @@ -36,10 +37,12 @@ import com.cloud.dc.ClusterVO; import com.cloud.host.HostVO; import com.cloud.resource.ResourceManager; +import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; import org.apache.cloudstack.storage.service.model.AccessGroup; @@ -57,6 +60,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.withSettings; import static org.mockito.ArgumentMatchers.contains; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -190,6 +194,50 @@ public void testInitialize_positive() { } } + private Map buildDsInfosForProtocol(String protocol) { + HashMap detailsMap = new HashMap(); + detailsMap.put(OntapStorageConstants.USERNAME, "testUser"); + detailsMap.put(OntapStorageConstants.PASSWORD, "testPassword"); + detailsMap.put(OntapStorageConstants.STORAGE_IP, "10.10.10.10"); + detailsMap.put(OntapStorageConstants.SVM_NAME, "vs0"); + detailsMap.put(OntapStorageConstants.PROTOCOL, protocol); + + Map dsInfos = new HashMap<>(); + dsInfos.put("zoneId", 1L); + dsInfos.put("podId", 1L); + dsInfos.put("clusterId", 1L); + dsInfos.put("name", "testStoragePool"); + dsInfos.put("providerName", "testProvider"); + dsInfos.put("capacityBytes", 200000L); + dsInfos.put("managed", true); + dsInfos.put("tags", "testTag"); + dsInfos.put("isTagARule", false); + dsInfos.put("details", detailsMap); + return dsInfos; + } + + private Storage.StoragePoolType initializeAndCapturePoolType(String protocol) { + try (MockedStatic storageProviderFactory = Mockito.mockStatic(StorageProviderFactory.class)) { + storageProviderFactory.when(() -> StorageProviderFactory.getStrategy(any())).thenReturn(storageStrategy); + ontapPrimaryDatastoreLifecycle.initialize(buildDsInfosForProtocol(protocol)); + } + ArgumentCaptor captor = ArgumentCaptor.forClass(PrimaryDataStoreParameters.class); + verify(_dataStoreHelper).createPrimaryDataStore(captor.capture()); + return captor.getValue().getType(); + } + + @Test + public void testInitialize_iscsiPoolUsesOntapSanType() { + when(storageStrategy.getStoragePath()).thenReturn("iqn.1992-08.com.netapp:sn.abc123"); + + assertEquals(Storage.StoragePoolType.OntapSAN, initializeAndCapturePoolType("ISCSI")); + } + + @Test + public void testInitialize_nfsPoolKeepsNetworkFilesystemType() { + assertEquals(Storage.StoragePoolType.NetworkFilesystem, initializeAndCapturePoolType("NFS3")); + } + @Test public void testInitialize_null_Arg() { Exception ex = assertThrows(CloudRuntimeException.class,() -> diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java index 934600eb2b61..7a615570dd91 100644 --- a/server/src/main/java/com/cloud/api/ApiDBUtils.java +++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java @@ -1338,7 +1338,7 @@ public static HypervisorType getHypervisorTypeFromFormat(long dcId, ImageFormat type = HypervisorType.Hyperv; } } if (format == ImageFormat.RAW) { - // Currently, KVM only supports RBD, PowerFlex, and FiberChannel images of type RAW. + // Currently, KVM only supports RBD, PowerFlex, FiberChannel and OntapSAN images of type RAW. // This results in a weird collision with OVM volumes which // can only be raw, thus making KVM RBD volumes show up as OVM // rather than RBD. This block of code can (hopefully) by checking to @@ -1355,7 +1355,8 @@ public static HypervisorType getHypervisorTypeFromFormat(long dcId, ImageFormat StoragePoolType.PowerFlex, StoragePoolType.CLVM, StoragePoolType.Linstor, - StoragePoolType.FiberChannel).contains(pool.getPoolType())) { + StoragePoolType.FiberChannel, + StoragePoolType.OntapSAN).contains(pool.getPoolType())) { // This case will note the presence of non-qcow2 primary stores, suggesting KVM without NFS. Otherwse, // If this check is not passed, the hypervisor type will remain OVM. type = HypervisorType.KVM; diff --git a/test/integration/plugins/ontap/TEST_CASES.md b/test/integration/plugins/ontap/TEST_CASES.md index 5ef8e8a1eb6d..7dc6ab06032a 100644 --- a/test/integration/plugins/ontap/TEST_CASES.md +++ b/test/integration/plugins/ontap/TEST_CASES.md @@ -138,7 +138,7 @@ Each suite is sequential — tests must run in numbered order; each step builds | # | Test method | Goal | Depends on | CloudStack success criteria | ONTAP success criteria | Type | |---|-------------|------|------------|-----------------------------|------------------------|------| -| 01 | `test_01_create_primary_storage_pool` | Create a cluster-scoped iSCSI primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "Iscsi"` | FlexVol `online`; one igroup per cluster host (named `cs_{svmName}_{hostShortName}`) with host IQN as initiator | positive | +| 01 | `test_01_create_primary_storage_pool` | Create a cluster-scoped iSCSI primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "OntapSAN"` | FlexVol `online`; one igroup per cluster host (named `cs_{svmName}_{hostShortName}`) with host IQN as initiator | positive | | 02 | `test_02_disable_storage_pool` | Disable the pool | test_01 (`pool`) | `pool.state == "Disabled"` | FlexVol still `online` | positive | | 03 | `test_03_enable_storage_pool` | Re-enable the pool | test_02 | `pool.state == "Up"` | FlexVol still `online` | positive | | 04 | `test_04_enter_maintenance_mode` | Put pool into maintenance | test_03 | `pool.state == "Maintenance"` | FlexVol still `online`; igroups unchanged | positive | @@ -210,7 +210,7 @@ Each suite is sequential — tests must run in numbered order; each step builds | # | Test method | Goal | Depends on | CloudStack success criteria | ONTAP success criteria | Type | |---|-------------|------|------------|-----------------------------|------------------------|------| -| 01 | `test_01_create_iscsi_pool` | Create iSCSI ONTAP primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "Iscsi"` | FlexVol `online`; igroup per cluster host with host IQN | positive | +| 01 | `test_01_create_iscsi_pool` | Create iSCSI ONTAP primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "OntapSAN"` | FlexVol `online`; igroup per cluster host with host IQN | positive | | 02 | `test_02_create_ontap_data_volume` | Allocate a CloudStack data volume (creates a LUN in the FlexVol) | test_01 (`pool`) | Volume non-None | ≥1 LUN in FlexVol | positive | | 03 | `test_03_deploy_vm` | Deploy VM using first ready KVM template; verify 0 LUN-maps exist before attach | test_02 (`volume`) | `vm.state == "Running"`; 0 LUN-maps on ONTAP | 0 LUN-maps (`list_lun_maps_for_volume` returns empty) | positive | | 04 | `test_04_attach_volume_to_vm` | Hot-attach the ONTAP iSCSI volume to the running VM — a LUN-map is created (TDS SN 27) | test_03 (`vm`, `volume`) | `volume.virtualmachineid == vm.id` | ≥1 LUN-map linking the LUN to the host's igroup | positive | diff --git a/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py b/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py index 716659b88c91..f5284499fa64 100644 --- a/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py +++ b/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py @@ -424,7 +424,7 @@ def test_01_create_iscsi_pool(self): """ Create an iSCSI primary storage pool on ONTAP. Verifies: - - Pool reaches 'Up' state; type is 'Iscsi' + - Pool reaches 'Up' state; type is 'OntapSAN' - ONTAP: FlexVol is online - ONTAP: igroup exists for every host in the cluster that has an IQN """ @@ -433,8 +433,8 @@ def test_01_create_iscsi_pool(self): self.assertEqual(pool.state, "Up", "Pool state should be 'Up', got '%s'" % pool.state) - self.assertEqual(pool.type, "Iscsi", - "Pool type should be 'Iscsi', got '%s'" % pool.type) + self.assertEqual(pool.type, "OntapSAN", + "Pool type should be 'OntapSAN', got '%s'" % pool.type) ontap_vol = self.ontap.get_volume(pool.name) self.assertIsNotNone( diff --git a/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py b/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py index 01abd239b0b7..45f3a81092b7 100644 --- a/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py +++ b/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py @@ -276,7 +276,7 @@ def _assert_pool_capacity(self, pool, label): def test_01_create_primary_storage_pool(self): """ Create an iSCSI primary storage pool and verify: - - CloudStack state is Up, type is Iscsi + - CloudStack state is Up, type is OntapSAN - ONTAP: FlexVol exists and is online - ONTAP: one igroup per cluster host exists with the correct IQN initiator """ @@ -288,8 +288,8 @@ def test_01_create_primary_storage_pool(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "Iscsi", - "Pool type should be 'Iscsi', got '%s'" % pool.type + pool.type, "OntapSAN", + "Pool type should be 'OntapSAN', got '%s'" % pool.type ) # ONTAP: FlexVol must be online @@ -502,7 +502,7 @@ def test_07_create_volume_on_pool(self): Create a new iSCSI pool and allocate a CloudStack data volume. For iSCSI, createAsync creates a LUN inside the pool's ONTAP FlexVol. Verifies: - - pool.state is Up, type is Iscsi + - pool.state is Up, type is OntapSAN - createVolume returns a non-None volume object - ONTAP: FlexVol is still online - ONTAP: at least one LUN is present in the FlexVol @@ -520,8 +520,8 @@ def test_07_create_volume_on_pool(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "Iscsi", - "Pool type should be 'Iscsi', got '%s'" % pool.type + pool.type, "OntapSAN", + "Pool type should be 'OntapSAN', got '%s'" % pool.type ) vol = self._create_volume(pool.id) diff --git a/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py b/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py index 03e332740f58..ace2be256ba7 100644 --- a/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py +++ b/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py @@ -311,7 +311,7 @@ def test_01_create_pool_and_volume(self): Create an iSCSI primary storage pool and allocate a CloudStack data volume on it. Verifies: - - Pool state is Up; pool type is Iscsi + - Pool state is Up; pool type is OntapSAN - ONTAP: FlexVol is online - ONTAP: at least one igroup exists (one per cluster host with IQN) - ONTAP: after createVolume, a LUN exists in the FlexVol @@ -324,8 +324,8 @@ def test_01_create_pool_and_volume(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "Iscsi", - "Pool type should be 'Iscsi', got '%s'" % pool.type + pool.type, "OntapSAN", + "Pool type should be 'OntapSAN', got '%s'" % pool.type ) # ONTAP: FlexVol must be online diff --git a/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py b/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py index c7ee726ef460..6ac20c70567f 100644 --- a/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py +++ b/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py @@ -249,7 +249,7 @@ def test_01_create_zone_scoped_pool(self): CloudStack calls attachZone(), which connects all eligible KVM hosts in the zone and creates igroups for each host's IQN. Verifies: - - pool.state is Up, type is Iscsi + - pool.state is Up, type is OntapSAN - ONTAP: FlexVol is online - ONTAP: igroup exists for each cluster host with the correct IQN """ @@ -261,8 +261,8 @@ def test_01_create_zone_scoped_pool(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "Iscsi", - "Pool type should be 'Iscsi', got '%s'" % pool.type + pool.type, "OntapSAN", + "Pool type should be 'OntapSAN', got '%s'" % pool.type ) # ONTAP: FlexVol must be online From d155487fcfe7aa1b5f4e58caa73bf340646d0b43 Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Fri, 21 Aug 2026 14:09:44 +0530 Subject: [PATCH 2/5] feature/CSTACKEX-251: Updated the type --- ...{OntapSanStorageAdaptor.java => OntapIscsiStorageAdaptor.java} | 0 ...nStorageAdaptorTest.java => OntapIscsiStorageAdaptorTest.java} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/{OntapSanStorageAdaptor.java => OntapIscsiStorageAdaptor.java} (100%) rename plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/{OntapSanStorageAdaptorTest.java => OntapIscsiStorageAdaptorTest.java} (100%) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java similarity index 100% rename from plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptor.java rename to plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptorTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptorTest.java similarity index 100% rename from plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapSanStorageAdaptorTest.java rename to plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptorTest.java From e7bebb3dce5d39dd1ac2af6aadb1a650517506c4 Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Fri, 21 Aug 2026 14:11:04 +0530 Subject: [PATCH 3/5] feature/CSTACKEX-251: Updated the type 1 --- .../main/java/com/cloud/storage/Storage.java | 2 +- .../java/com/cloud/storage/StorageTest.java | 14 ++++----- .../StorageSystemDataMotionStrategy.java | 4 +-- .../kvm/storage/KVMStorageProcessor.java | 4 +-- .../kvm/storage/OntapIscsiStorageAdaptor.java | 6 ++-- .../storage/OntapIscsiStorageAdaptorTest.java | 30 +++++++++---------- .../driver/OntapPrimaryDatastoreDriver.java | 2 +- .../OntapPrimaryDatastoreLifecycle.java | 2 +- .../OntapPrimaryDatastoreDriverTest.java | 4 +-- .../OntapPrimaryDatastoreLifecycleTest.java | 4 +-- .../main/java/com/cloud/api/ApiDBUtils.java | 4 +-- test/integration/plugins/ontap/TEST_CASES.md | 4 +-- .../iscsi/instance/test_vm_volume_attach.py | 6 ++-- .../ontap/iscsi/pool/test_pool_lifecycle.py | 12 ++++---- .../iscsi/pool/test_pool_with_volumes.py | 6 ++-- .../ontap/iscsi/pool/test_zone_scoped_pool.py | 6 ++-- 16 files changed, 55 insertions(+), 55 deletions(-) diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java index 6d5736883a89..2f05eb6a05a2 100644 --- a/api/src/main/java/com/cloud/storage/Storage.java +++ b/api/src/main/java/com/cloud/storage/Storage.java @@ -186,7 +186,7 @@ public static enum StoragePoolType { DatastoreCluster(true, true, EncryptionSupport.Unsupported), // for VMware, to abstract pool of clusters StorPool(true, true, EncryptionSupport.Hypervisor), FiberChannel(true, true, EncryptionSupport.Unsupported), // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-) - OntapSAN(true, false, EncryptionSupport.Unsupported); // NetApp ONTAP SAN (iSCSI): one FlexVol per pool, one LUN per volume + OntapiSCSI(true, true, EncryptionSupport.Unsupported); // NetApp ONTAP iSCSI: one FlexVol per pool, one LUN per volume private final boolean shared; private final boolean overProvisioning; diff --git a/api/src/test/java/com/cloud/storage/StorageTest.java b/api/src/test/java/com/cloud/storage/StorageTest.java index f431afd6dfd0..1d82b5ee5c66 100644 --- a/api/src/test/java/com/cloud/storage/StorageTest.java +++ b/api/src/test/java/com/cloud/storage/StorageTest.java @@ -49,7 +49,7 @@ public void isSharedStoragePool() { Assert.assertTrue(StoragePoolType.ManagedNFS.isShared()); Assert.assertTrue(StoragePoolType.DatastoreCluster.isShared()); Assert.assertTrue(StoragePoolType.Linstor.isShared()); - Assert.assertTrue(StoragePoolType.OntapSAN.isShared()); + Assert.assertTrue(StoragePoolType.OntapiSCSI.isShared()); } @Test @@ -74,19 +74,19 @@ public void supportsOverProvisioningTestAllStoragePoolTypes() { Assert.assertFalse(StoragePoolType.ManagedNFS.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.DatastoreCluster.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.Linstor.supportsOverProvisioning()); - Assert.assertFalse(StoragePoolType.OntapSAN.supportsOverProvisioning()); + Assert.assertFalse(StoragePoolType.OntapiSCSI.supportsOverProvisioning()); } /** - * OntapSAN was split out of the shared Iscsi bucket and must stay attribute-identical to it, + * OntapiSCSI was split out of the shared Iscsi bucket and must stay attribute-identical to it, * so that introducing the type changes no behaviour. Loosening either attribute is a * deliberate decision that belongs in its own change. */ @Test - public void ontapSanMirrorsIscsiAttributes() { - Assert.assertEquals(StoragePoolType.Iscsi.isShared(), StoragePoolType.OntapSAN.isShared()); - Assert.assertEquals(StoragePoolType.Iscsi.supportsOverProvisioning(), StoragePoolType.OntapSAN.supportsOverProvisioning()); - Assert.assertEquals(StoragePoolType.Iscsi.encryptionSupportMode(), StoragePoolType.OntapSAN.encryptionSupportMode()); + public void ontapIscsiMirrorsGenericIscsiAttributes() { + Assert.assertEquals(StoragePoolType.Iscsi.isShared(), StoragePoolType.OntapiSCSI.isShared()); + Assert.assertEquals(StoragePoolType.Iscsi.supportsOverProvisioning(), StoragePoolType.OntapiSCSI.supportsOverProvisioning()); + Assert.assertEquals(StoragePoolType.Iscsi.encryptionSupportMode(), StoragePoolType.OntapiSCSI.encryptionSupportMode()); } @Test diff --git a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java index ba11834a5fa8..76bbc9cac908 100644 --- a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java +++ b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java @@ -616,8 +616,8 @@ private void handleVolumeMigrationFromManagedStorageToNonManagedStorage(VolumeIn private void verifyFormatWithPoolType(ImageFormat imageFormat, StoragePoolType poolType) { if (imageFormat != ImageFormat.VHD && imageFormat != ImageFormat.OVA && imageFormat != ImageFormat.QCOW2 && !(imageFormat == ImageFormat.RAW && (StoragePoolType.PowerFlex == poolType || - StoragePoolType.FiberChannel == poolType || StoragePoolType.OntapSAN == poolType))) { - throw new CloudRuntimeException(String.format("Only the following image types are currently supported: %s, %s, %s, %s (for PowerFlex, FiberChannel and OntapSAN)", + StoragePoolType.FiberChannel == poolType || StoragePoolType.OntapiSCSI == poolType))) { + throw new CloudRuntimeException(String.format("Only the following image types are currently supported: %s, %s, %s, %s (for PowerFlex, FiberChannel and OntapiSCSI)", ImageFormat.VHD.toString(), ImageFormat.OVA.toString(), ImageFormat.QCOW2.toString(), ImageFormat.RAW.toString())); } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index c9eee5c5dbf2..883570e24e4b 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -416,7 +416,7 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) { StoragePoolType.Linstor, StoragePoolType.FiberChannel, StoragePoolType.CLVM, - StoragePoolType.OntapSAN).contains(primaryPool.getType())) { + StoragePoolType.OntapiSCSI).contains(primaryPool.getType())) { newTemplate.setFormat(ImageFormat.RAW); } else { newTemplate.setFormat(ImageFormat.QCOW2); @@ -3433,7 +3433,7 @@ private Storage.ImageFormat getFormat(StoragePoolType poolType) { StoragePoolType.Linstor, StoragePoolType.FiberChannel, StoragePoolType.CLVM, - StoragePoolType.OntapSAN).contains(poolType)) { + StoragePoolType.OntapiSCSI).contains(poolType)) { return ImageFormat.RAW; } else { return ImageFormat.QCOW2; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java index c90bbcb19ae2..461f0af51796 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java @@ -19,7 +19,7 @@ import com.cloud.storage.Storage.StoragePoolType; /** - * Serves {@link StoragePoolType#OntapSAN} pools, which are ONTAP FlexVols exposed over iSCSI with one + * Serves {@link StoragePoolType#OntapiSCSI} pools, which are ONTAP FlexVols exposed over iSCSI with one * LUN per CloudStack volume. The host-side handling is identical to a generic iSCSI target, so the * behaviour is inherited wholesale from {@link IscsiAdmStorageAdaptor}. * @@ -31,10 +31,10 @@ * discovers adaptors by a Reflections scan of that package alone, and an unregistered type silently * falls back to {@link LibvirtStorageAdaptor} rather than failing at startup. */ -public class OntapSanStorageAdaptor extends IscsiAdmStorageAdaptor { +public class OntapIscsiStorageAdaptor extends IscsiAdmStorageAdaptor { @Override public StoragePoolType getStoragePoolType() { - return StoragePoolType.OntapSAN; + return StoragePoolType.OntapiSCSI; } } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptorTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptorTest.java index 147a555256a2..c89094081d35 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptorTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptorTest.java @@ -30,25 +30,25 @@ import com.cloud.storage.Storage.StoragePoolType; -public class OntapSanStorageAdaptorTest { +public class OntapIscsiStorageAdaptorTest { @Test - public void getStoragePoolTypeReturnsOntapSan() { - assertEquals(StoragePoolType.OntapSAN, new OntapSanStorageAdaptor().getStoragePoolType()); + public void getStoragePoolTypeReturnsOntapIscsi() { + assertEquals(StoragePoolType.OntapiSCSI, new OntapIscsiStorageAdaptor().getStoragePoolType()); } @Test - public void createdPoolCarriesOntapSanTypeAndRawFormat() { - OntapSanStorageAdaptor adaptor = new OntapSanStorageAdaptor(); + public void createdPoolCarriesOntapIscsiTypeAndRawFormat() { + OntapIscsiStorageAdaptor adaptor = new OntapIscsiStorageAdaptor(); - KVMStoragePool pool = adaptor.createStoragePool("ontap-san-pool-uuid", "10.0.0.1", 3260, null, null, - StoragePoolType.OntapSAN, null, true); + KVMStoragePool pool = adaptor.createStoragePool("ontap-iscsi-pool-uuid", "10.0.0.1", 3260, null, null, + StoragePoolType.OntapiSCSI, null, true); - assertEquals(StoragePoolType.OntapSAN, pool.getType()); + assertEquals(StoragePoolType.OntapiSCSI, pool.getType()); // Attach builds a block-based disk off the physical disk format rather than the pool type, - // which is why splitting OntapSAN out of Iscsi leaves the generated domain XML unchanged. + // which is why splitting OntapiSCSI out of Iscsi leaves the generated domain XML unchanged. assertEquals(PhysicalDiskFormat.RAW, pool.getDefaultFormat()); - assertSame(pool, adaptor.getStoragePool("ontap-san-pool-uuid")); + assertSame(pool, adaptor.getStoragePool("ontap-iscsi-pool-uuid")); } /** @@ -65,13 +65,13 @@ public void adaptorSatisfiesThePoolManagerDiscoveryContract() throws ReflectiveO Set> discovered = new Reflections(scannedPackage).getSubTypesOf(StorageAdaptor.class); - assertTrue("OntapSanStorageAdaptor must live in " + scannedPackage + " to be discovered", - discovered.contains(OntapSanStorageAdaptor.class)); + assertTrue("OntapIscsiStorageAdaptor must live in " + scannedPackage + " to be discovered", + discovered.contains(OntapIscsiStorageAdaptor.class)); assertFalse("An abstract adaptor is skipped by the scan", - Modifier.isAbstract(OntapSanStorageAdaptor.class.getModifiers())); + Modifier.isAbstract(OntapIscsiStorageAdaptor.class.getModifiers())); - StorageAdaptor adaptor = OntapSanStorageAdaptor.class.getDeclaredConstructor().newInstance(); - assertEquals(StoragePoolType.OntapSAN, adaptor.getStoragePoolType()); + StorageAdaptor adaptor = OntapIscsiStorageAdaptor.class.getDeclaredConstructor().newInstance(); + assertEquals(StoragePoolType.OntapiSCSI, adaptor.getStoragePoolType()); assertEquals("The superclass must keep serving the other iSCSI vendors", StoragePoolType.Iscsi, new IscsiAdmStorageAdaptor().getStoragePoolType()); } diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java index 5a4c3bd58d0a..c06c36e4fedf 100644 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java @@ -1019,7 +1019,7 @@ private Storage.ImageFormat getImageFormat(StoragePoolVO storagePool) { if (!HypervisorType.KVM.equals(hypervisorType)) { throw new CloudRuntimeException("Unsupported hypervisor [" + hypervisorType + "] for ONTAP image format resolution"); } - return Storage.StoragePoolType.OntapSAN.equals(storagePool.getPoolType()) + return Storage.StoragePoolType.OntapiSCSI.equals(storagePool.getPoolType()) ? Storage.ImageFormat.RAW : Storage.ImageFormat.QCOW2; } diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java index de94f6956a4c..0e43562d4cc3 100755 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java @@ -184,7 +184,7 @@ public DataStore initialize(Map dsInfos) { logger.info("Setting NFS path for storage pool: " + path + ", port: " + port + " with mount option: vers=3"); break; case ISCSI: - parameters.setType(Storage.StoragePoolType.OntapSAN); + parameters.setType(Storage.StoragePoolType.OntapiSCSI); path = storageStrategy.getStoragePath(); port = OntapStorageConstants.ISCSI_PORT; logger.info("Setting iSCSI path for storage pool: " + path + ", port: " + port); diff --git a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java index 547e9bfee518..cf9778a59288 100644 --- a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java +++ b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriverTest.java @@ -167,7 +167,7 @@ void testCreateAsync_VolumeWithISCSI_Success() { when(storagePoolDao.findById(1L)).thenReturn(storagePool); when(storagePool.getId()).thenReturn(1L); - when(storagePool.getPoolType()).thenReturn(Storage.StoragePoolType.OntapSAN); + when(storagePool.getPoolType()).thenReturn(Storage.StoragePoolType.OntapiSCSI); when(storagePool.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM); when(storagePoolDetailsDao.listDetailsKeyPairs(1L)).thenReturn(storagePoolDetails); @@ -251,7 +251,7 @@ void testCreateAsync_VolumeWithNFS_Success() { assertNotNull(result); assertTrue(result.isSuccess()); // NFS volumes really are qcow2 files inside the FlexVol, so they keep QCOW2 while - // iSCSI LUNs on an OntapSAN pool are recorded as RAW. + // iSCSI LUNs on an OntapiSCSI pool are recorded as RAW. verify(volumeVO).setFormat(Storage.ImageFormat.QCOW2); verify(volumeDao).update(eq(100L), any(VolumeVO.class)); } diff --git a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java index e72ad029703a..68505a596d08 100644 --- a/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java +++ b/plugins/storage/volume/ontap/src/test/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycleTest.java @@ -227,10 +227,10 @@ private Storage.StoragePoolType initializeAndCapturePoolType(String protocol) { } @Test - public void testInitialize_iscsiPoolUsesOntapSanType() { + public void testInitialize_iscsiPoolUsesOntapIscsiType() { when(storageStrategy.getStoragePath()).thenReturn("iqn.1992-08.com.netapp:sn.abc123"); - assertEquals(Storage.StoragePoolType.OntapSAN, initializeAndCapturePoolType("ISCSI")); + assertEquals(Storage.StoragePoolType.OntapiSCSI, initializeAndCapturePoolType("ISCSI")); } @Test diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java index 7a615570dd91..00ff20b85258 100644 --- a/server/src/main/java/com/cloud/api/ApiDBUtils.java +++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java @@ -1338,7 +1338,7 @@ public static HypervisorType getHypervisorTypeFromFormat(long dcId, ImageFormat type = HypervisorType.Hyperv; } } if (format == ImageFormat.RAW) { - // Currently, KVM only supports RBD, PowerFlex, FiberChannel and OntapSAN images of type RAW. + // Currently, KVM only supports RBD, PowerFlex, FiberChannel and OntapiSCSI images of type RAW. // This results in a weird collision with OVM volumes which // can only be raw, thus making KVM RBD volumes show up as OVM // rather than RBD. This block of code can (hopefully) by checking to @@ -1356,7 +1356,7 @@ public static HypervisorType getHypervisorTypeFromFormat(long dcId, ImageFormat StoragePoolType.CLVM, StoragePoolType.Linstor, StoragePoolType.FiberChannel, - StoragePoolType.OntapSAN).contains(pool.getPoolType())) { + StoragePoolType.OntapiSCSI).contains(pool.getPoolType())) { // This case will note the presence of non-qcow2 primary stores, suggesting KVM without NFS. Otherwse, // If this check is not passed, the hypervisor type will remain OVM. type = HypervisorType.KVM; diff --git a/test/integration/plugins/ontap/TEST_CASES.md b/test/integration/plugins/ontap/TEST_CASES.md index 7dc6ab06032a..73dc1990a5b6 100644 --- a/test/integration/plugins/ontap/TEST_CASES.md +++ b/test/integration/plugins/ontap/TEST_CASES.md @@ -138,7 +138,7 @@ Each suite is sequential — tests must run in numbered order; each step builds | # | Test method | Goal | Depends on | CloudStack success criteria | ONTAP success criteria | Type | |---|-------------|------|------------|-----------------------------|------------------------|------| -| 01 | `test_01_create_primary_storage_pool` | Create a cluster-scoped iSCSI primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "OntapSAN"` | FlexVol `online`; one igroup per cluster host (named `cs_{svmName}_{hostShortName}`) with host IQN as initiator | positive | +| 01 | `test_01_create_primary_storage_pool` | Create a cluster-scoped iSCSI primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "OntapiSCSI"` | FlexVol `online`; one igroup per cluster host (named `cs_{svmName}_{hostShortName}`) with host IQN as initiator | positive | | 02 | `test_02_disable_storage_pool` | Disable the pool | test_01 (`pool`) | `pool.state == "Disabled"` | FlexVol still `online` | positive | | 03 | `test_03_enable_storage_pool` | Re-enable the pool | test_02 | `pool.state == "Up"` | FlexVol still `online` | positive | | 04 | `test_04_enter_maintenance_mode` | Put pool into maintenance | test_03 | `pool.state == "Maintenance"` | FlexVol still `online`; igroups unchanged | positive | @@ -210,7 +210,7 @@ Each suite is sequential — tests must run in numbered order; each step builds | # | Test method | Goal | Depends on | CloudStack success criteria | ONTAP success criteria | Type | |---|-------------|------|------------|-----------------------------|------------------------|------| -| 01 | `test_01_create_iscsi_pool` | Create iSCSI ONTAP primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "OntapSAN"` | FlexVol `online`; igroup per cluster host with host IQN | positive | +| 01 | `test_01_create_iscsi_pool` | Create iSCSI ONTAP primary storage pool | setUpClass | `pool.state == "Up"`, `pool.type == "OntapiSCSI"` | FlexVol `online`; igroup per cluster host with host IQN | positive | | 02 | `test_02_create_ontap_data_volume` | Allocate a CloudStack data volume (creates a LUN in the FlexVol) | test_01 (`pool`) | Volume non-None | ≥1 LUN in FlexVol | positive | | 03 | `test_03_deploy_vm` | Deploy VM using first ready KVM template; verify 0 LUN-maps exist before attach | test_02 (`volume`) | `vm.state == "Running"`; 0 LUN-maps on ONTAP | 0 LUN-maps (`list_lun_maps_for_volume` returns empty) | positive | | 04 | `test_04_attach_volume_to_vm` | Hot-attach the ONTAP iSCSI volume to the running VM — a LUN-map is created (TDS SN 27) | test_03 (`vm`, `volume`) | `volume.virtualmachineid == vm.id` | ≥1 LUN-map linking the LUN to the host's igroup | positive | diff --git a/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py b/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py index f5284499fa64..bd1d1cacaa93 100644 --- a/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py +++ b/test/integration/plugins/ontap/iscsi/instance/test_vm_volume_attach.py @@ -424,7 +424,7 @@ def test_01_create_iscsi_pool(self): """ Create an iSCSI primary storage pool on ONTAP. Verifies: - - Pool reaches 'Up' state; type is 'OntapSAN' + - Pool reaches 'Up' state; type is 'OntapiSCSI' - ONTAP: FlexVol is online - ONTAP: igroup exists for every host in the cluster that has an IQN """ @@ -433,8 +433,8 @@ def test_01_create_iscsi_pool(self): self.assertEqual(pool.state, "Up", "Pool state should be 'Up', got '%s'" % pool.state) - self.assertEqual(pool.type, "OntapSAN", - "Pool type should be 'OntapSAN', got '%s'" % pool.type) + self.assertEqual(pool.type, "OntapiSCSI", + "Pool type should be 'OntapiSCSI', got '%s'" % pool.type) ontap_vol = self.ontap.get_volume(pool.name) self.assertIsNotNone( diff --git a/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py b/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py index 45f3a81092b7..cc87bacf0e76 100644 --- a/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py +++ b/test/integration/plugins/ontap/iscsi/pool/test_pool_lifecycle.py @@ -276,7 +276,7 @@ def _assert_pool_capacity(self, pool, label): def test_01_create_primary_storage_pool(self): """ Create an iSCSI primary storage pool and verify: - - CloudStack state is Up, type is OntapSAN + - CloudStack state is Up, type is OntapiSCSI - ONTAP: FlexVol exists and is online - ONTAP: one igroup per cluster host exists with the correct IQN initiator """ @@ -288,8 +288,8 @@ def test_01_create_primary_storage_pool(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "OntapSAN", - "Pool type should be 'OntapSAN', got '%s'" % pool.type + pool.type, "OntapiSCSI", + "Pool type should be 'OntapiSCSI', got '%s'" % pool.type ) # ONTAP: FlexVol must be online @@ -502,7 +502,7 @@ def test_07_create_volume_on_pool(self): Create a new iSCSI pool and allocate a CloudStack data volume. For iSCSI, createAsync creates a LUN inside the pool's ONTAP FlexVol. Verifies: - - pool.state is Up, type is OntapSAN + - pool.state is Up, type is OntapiSCSI - createVolume returns a non-None volume object - ONTAP: FlexVol is still online - ONTAP: at least one LUN is present in the FlexVol @@ -520,8 +520,8 @@ def test_07_create_volume_on_pool(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "OntapSAN", - "Pool type should be 'OntapSAN', got '%s'" % pool.type + pool.type, "OntapiSCSI", + "Pool type should be 'OntapiSCSI', got '%s'" % pool.type ) vol = self._create_volume(pool.id) diff --git a/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py b/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py index ace2be256ba7..9dd49761c1dc 100644 --- a/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py +++ b/test/integration/plugins/ontap/iscsi/pool/test_pool_with_volumes.py @@ -311,7 +311,7 @@ def test_01_create_pool_and_volume(self): Create an iSCSI primary storage pool and allocate a CloudStack data volume on it. Verifies: - - Pool state is Up; pool type is OntapSAN + - Pool state is Up; pool type is OntapiSCSI - ONTAP: FlexVol is online - ONTAP: at least one igroup exists (one per cluster host with IQN) - ONTAP: after createVolume, a LUN exists in the FlexVol @@ -324,8 +324,8 @@ def test_01_create_pool_and_volume(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "OntapSAN", - "Pool type should be 'OntapSAN', got '%s'" % pool.type + pool.type, "OntapiSCSI", + "Pool type should be 'OntapiSCSI', got '%s'" % pool.type ) # ONTAP: FlexVol must be online diff --git a/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py b/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py index 6ac20c70567f..847a026a3bd5 100644 --- a/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py +++ b/test/integration/plugins/ontap/iscsi/pool/test_zone_scoped_pool.py @@ -249,7 +249,7 @@ def test_01_create_zone_scoped_pool(self): CloudStack calls attachZone(), which connects all eligible KVM hosts in the zone and creates igroups for each host's IQN. Verifies: - - pool.state is Up, type is OntapSAN + - pool.state is Up, type is OntapiSCSI - ONTAP: FlexVol is online - ONTAP: igroup exists for each cluster host with the correct IQN """ @@ -261,8 +261,8 @@ def test_01_create_zone_scoped_pool(self): "Pool state should be 'Up', got '%s'" % pool.state ) self.assertEqual( - pool.type, "OntapSAN", - "Pool type should be 'OntapSAN', got '%s'" % pool.type + pool.type, "OntapiSCSI", + "Pool type should be 'OntapiSCSI', got '%s'" % pool.type ) # ONTAP: FlexVol must be online From 00582995bb386617ced3d599208be9b23a7d7ff2 Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Fri, 21 Aug 2026 14:50:54 +0530 Subject: [PATCH 4/5] feature/CSTACKEX-251: Updated the type 2 --- api/src/main/java/com/cloud/storage/Storage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java index 2f05eb6a05a2..41fae6242934 100644 --- a/api/src/main/java/com/cloud/storage/Storage.java +++ b/api/src/main/java/com/cloud/storage/Storage.java @@ -186,7 +186,7 @@ public static enum StoragePoolType { DatastoreCluster(true, true, EncryptionSupport.Unsupported), // for VMware, to abstract pool of clusters StorPool(true, true, EncryptionSupport.Hypervisor), FiberChannel(true, true, EncryptionSupport.Unsupported), // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-) - OntapiSCSI(true, true, EncryptionSupport.Unsupported); // NetApp ONTAP iSCSI: one FlexVol per pool, one LUN per volume + OntapiSCSI(true, false, EncryptionSupport.Unsupported); // NetApp ONTAP iSCSI: one FlexVol per pool, one LUN per volume private final boolean shared; private final boolean overProvisioning; From 11085e9d14ba53e8541a22d268b62ec27893b967 Mon Sep 17 00:00:00 2001 From: "Srivastava, Piyush" Date: Fri, 21 Aug 2026 15:19:35 +0530 Subject: [PATCH 5/5] feature/CSTACKEX-251: removed comments --- .../hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java | 6 ++---- .../storage/driver/OntapPrimaryDatastoreDriver.java | 9 --------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java index 461f0af51796..73e8cb4026c7 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/OntapIscsiStorageAdaptor.java @@ -20,12 +20,10 @@ /** * Serves {@link StoragePoolType#OntapiSCSI} pools, which are ONTAP FlexVols exposed over iSCSI with one - * LUN per CloudStack volume. The host-side handling is identical to a generic iSCSI target, so the - * behaviour is inherited wholesale from {@link IscsiAdmStorageAdaptor}. + * LUN per CloudStack volume. The host-side handling is identical to a generic iSCSI target * * The class exists so that ONTAP-specific host behaviour can diverge here without altering the storage - * path of the other vendors that register as {@link StoragePoolType#Iscsi} (SolidFire, Datera, Nexenta - * and CloudByte), which all share the superclass. + * path of the other vendors that register as {@link StoragePoolType#Iscsi} which all share the superclass. * * This must stay in the {@code com.cloud.hypervisor.kvm.storage} package: {@link KVMStoragePoolManager} * discovers adaptors by a Reflections scan of that package alone, and an unregistered type silently diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java index 52203f9e315e..5d1749b6959e 100644 --- a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java +++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java @@ -987,15 +987,6 @@ private String buildSnapshotName(String cloudStackSnapshotName, long snapshotId) return OntapStorageUtils.buildOntapSnapshotName(cloudStackSnapshotName, OntapStorageConstants.CS + snapshotId); } - - /** - * Resolves the image format to record against a volume on the given pool. - * - *

The format is a property of the backing object, not of the hypervisor. An iSCSI volume is a - * bare ONTAP LUN that the guest sees as a block device, so it is {@link Storage.ImageFormat#RAW}; - * an NFS volume is a qcow2 file inside the FlexVol. Reporting RAW for a LUN is what lets core - * permit shrink and skip the qcow2-only host-side operations that do not apply to a block device.

- */ private Storage.ImageFormat getImageFormat(StoragePoolVO storagePool) { HypervisorType hypervisorType = storagePool.getHypervisor(); if (!HypervisorType.KVM.equals(hypervisorType)) {