diff --git a/client/pom.xml b/client/pom.xml
index 605487404a87..997d530725da 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -121,6 +121,11 @@
cloud-plugin-storage-volume-adaptive
${project.version}
+
+ org.apache.cloudstack
+ cloud-plugin-storage-volume-ontap
+ ${project.version}
+
org.apache.cloudstack
cloud-plugin-storage-volume-solidfire
diff --git a/plugins/pom.xml b/plugins/pom.xml
index d665f90b623d..cc05cab121cd 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -129,6 +129,7 @@
storage/volume/default
storage/volume/nexenta
storage/volume/sample
+ storage/volume/ontap
storage/volume/solidfire
storage/volume/scaleio
storage/volume/linstor
diff --git a/plugins/storage/volume/ontap/pom.xml b/plugins/storage/volume/ontap/pom.xml
new file mode 100644
index 000000000000..decfb29743da
--- /dev/null
+++ b/plugins/storage/volume/ontap/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+ cloud-plugin-storage-volume-ontap
+ Apache CloudStack Plugin - Storage Volume ONTAP Provider
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.22.0.0-SNAPSHOT
+ ../../../pom.xml
+
+
+
+ org.apache.cloudstack
+ cloud-plugin-storage-volume-default
+ ${project.version}
+
+
+ org.json
+ json
+ 20230227
+
+
+ org.apache.cloudstack
+ cloud-engine-storage-volume
+ ${project.version}
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+ integration-test
+
+ test
+
+
+
+
+
+
+
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
new file mode 100644
index 000000000000..2209b3168090
--- /dev/null
+++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java
@@ -0,0 +1,190 @@
+package org.apache.cloudstack.storage.driver;
+
+
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.host.Host;
+import com.cloud.storage.Storage;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.Volume;
+import com.cloud.utils.Pair;
+import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.storage.command.CommandResult;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class OntapPrimaryDatastoreDriver implements PrimaryDataStoreDriver {
+
+ private static final Logger s_logger = (Logger)LogManager.getLogger(OntapPrimaryDatastoreDriver.class);
+ @Override
+ public Map getCapabilities() {
+ s_logger.trace("OntapPrimaryDatastoreDriver: getCapabilities: Called");
+ Map mapCapabilities = new HashMap<>();
+
+ mapCapabilities.put(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString(), Boolean.TRUE.toString());
+ mapCapabilities.put(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_SNAPSHOT.toString(), Boolean.TRUE.toString());
+
+ return mapCapabilities;
+ }
+
+ @Override
+ public DataTO getTO(DataObject data) {
+ return null;
+ }
+
+ @Override
+ public DataStoreTO getStoreTO(DataStore store) {
+ return null;
+ }
+
+ @Override
+ public void createAsync(DataStore store, DataObject data, AsyncCompletionCallback callback) {
+
+ s_logger.trace("OntapPrimaryDatastoreDriver: createAsync: Store: "+store+", data: "+data);
+ }
+
+ @Override
+ public void deleteAsync(DataStore store, DataObject data, AsyncCompletionCallback callback) {
+
+ }
+
+ @Override
+ public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) {
+
+ }
+
+ @Override
+ public void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback callback) {
+
+ }
+
+ @Override
+ public boolean canCopy(DataObject srcData, DataObject destData) {
+ return false;
+ }
+
+ @Override
+ public void resize(DataObject data, AsyncCompletionCallback callback) {
+
+ }
+
+ @Override
+ public ChapInfo getChapInfo(DataObject dataObject) {
+ return null;
+ }
+
+ @Override
+ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore) {
+ return true;
+ }
+
+ @Override
+ public void revokeAccess(DataObject dataObject, Host host, DataStore dataStore) {
+
+ }
+
+ @Override
+ public long getDataObjectSizeIncludingHypervisorSnapshotReserve(DataObject dataObject, StoragePool storagePool) {
+ return 0;
+ }
+
+ @Override
+ public long getBytesRequiredForTemplate(TemplateInfo templateInfo, StoragePool storagePool) {
+ return 0;
+ }
+
+ @Override
+ public long getUsedBytes(StoragePool storagePool) {
+ return 0;
+ }
+
+ @Override
+ public long getUsedIops(StoragePool storagePool) {
+ return 0;
+ }
+
+ @Override
+ public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) {
+
+ }
+
+ @Override
+ public void revertSnapshot(SnapshotInfo snapshotOnImageStore, SnapshotInfo snapshotOnPrimaryStore, AsyncCompletionCallback callback) {
+
+ }
+
+ @Override
+ public void handleQualityOfServiceForVolumeMigration(VolumeInfo volumeInfo, QualityOfServiceState qualityOfServiceState) {
+
+ }
+
+ @Override
+ public boolean canProvideStorageStats() {
+ return true;
+ }
+
+ @Override
+ public Pair getStorageStats(StoragePool storagePool) {
+ return null;
+ }
+
+ @Override
+ public boolean canProvideVolumeStats() {
+ return true;
+ }
+
+ @Override
+ public Pair getVolumeStats(StoragePool storagePool, String volumeId) {
+ return null;
+ }
+
+ @Override
+ public boolean canHostAccessStoragePool(Host host, StoragePool pool) {
+ return true;
+ }
+
+ @Override
+ public boolean isVmInfoNeeded() {
+ return true;
+ }
+
+ @Override
+ public void provideVmInfo(long vmId, long volumeId) {
+
+ }
+
+ @Override
+ public boolean isVmTagsNeeded(String tagKey) {
+ return true;
+ }
+
+ @Override
+ public void provideVmTags(long vmId, long volumeId, String tagValue) {
+
+ }
+
+ @Override
+ public boolean isStorageSupportHA(Storage.StoragePoolType type) {
+ return true;
+ }
+
+ @Override
+ public void detachVolumeFromAllStorageNodes(Volume volume) {
+
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 000000000000..d20ef863d841
--- /dev/null
+++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java
@@ -0,0 +1,91 @@
+package org.apache.cloudstack.storage.lifecycle;
+
+
+import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.storage.StoragePool;
+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.HostScope;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import java.util.Map;
+
+public class OntapPrimaryDatastoreLifecycle implements PrimaryDataStoreLifeCycle {
+
+ private static final Logger s_logger = (Logger)LogManager.getLogger(OntapPrimaryDatastoreLifecycle.class);
+
+ /**
+ * Creates primary storage on NetApp storage
+ * @param dsInfos
+ * @return
+ */
+ @Override
+ public DataStore initialize(Map dsInfos) {
+
+ return null;
+
+ }
+
+ @Override
+ public boolean attachCluster(DataStore store, ClusterScope scope) {
+ return false;
+ }
+
+ @Override
+ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
+ return false;
+ }
+
+ @Override
+ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.HypervisorType hypervisorType) {
+ return false;
+ }
+
+ @Override
+ public boolean maintain(DataStore store) {
+ return true;
+ }
+
+ @Override
+ public boolean cancelMaintain(DataStore store) {
+ return true;
+ }
+
+ @Override
+ public boolean deleteDataStore(DataStore store) {
+ return true;
+ }
+
+ @Override
+ public boolean migrateToObjectStore(DataStore store) {
+ return true;
+ }
+
+ @Override
+ public void updateStoragePool(StoragePool storagePool, Map details) {
+
+ }
+
+ @Override
+ public void enableStoragePool(DataStore store) {
+
+ }
+
+ @Override
+ public void disableStoragePool(DataStore store) {
+
+ }
+
+ @Override
+ public void changeStoragePoolScopeToZone(DataStore store, ClusterScope clusterScope, Hypervisor.HypervisorType hypervisorType) {
+
+ }
+
+ @Override
+ public void changeStoragePoolScopeToCluster(DataStore store, ClusterScope clusterScope, Hypervisor.HypervisorType hypervisorType) {
+
+ }
+}
\ No newline at end of file
diff --git a/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/provider/OntapPrimaryDatastoreProvider.java b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/provider/OntapPrimaryDatastoreProvider.java
new file mode 100644
index 000000000000..639b98506874
--- /dev/null
+++ b/plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/provider/OntapPrimaryDatastoreProvider.java
@@ -0,0 +1,65 @@
+package org.apache.cloudstack.storage.provider;
+
+
+import com.cloud.utils.component.ComponentContext;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle;
+import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
+import org.apache.cloudstack.storage.driver.OntapPrimaryDatastoreDriver;
+import org.apache.cloudstack.storage.lifecycle.OntapPrimaryDatastoreLifecycle;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Logger;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+@Component
+public class OntapPrimaryDatastoreProvider implements PrimaryDataStoreProvider {
+
+ private static final Logger s_logger = (Logger)LogManager.getLogger(OntapPrimaryDatastoreProvider.class);
+ private OntapPrimaryDatastoreDriver primaryDatastoreDriver;
+ private OntapPrimaryDatastoreLifecycle primaryDatastoreLifecycle;
+
+ public OntapPrimaryDatastoreProvider() {
+ s_logger.info("OntapPrimaryDatastoreProvider initialized");
+ }
+ @Override
+ public DataStoreLifeCycle getDataStoreLifeCycle() {
+ return primaryDatastoreLifecycle;
+ }
+
+ @Override
+ public DataStoreDriver getDataStoreDriver() {
+ return primaryDatastoreDriver;
+ }
+
+ @Override
+ public HypervisorHostListener getHostListener() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ s_logger.trace("OntapPrimaryDatastoreProvider: getName: Called");
+ return "ONTAP Primary Datastore Provider";
+ }
+
+ @Override
+ public boolean configure(Map params) {
+ s_logger.trace("OntapPrimaryDatastoreProvider: configure: Called");
+ primaryDatastoreDriver = ComponentContext.inject(OntapPrimaryDatastoreDriver.class);
+ primaryDatastoreLifecycle = ComponentContext.inject(OntapPrimaryDatastoreLifecycle.class);
+ return true;
+ }
+
+ @Override
+ public Set getTypes() {
+ s_logger.trace("OntapPrimaryDatastoreProvider: getTypes: Called");
+ Set typeSet = new HashSet();
+ typeSet.add(DataStoreProviderType.PRIMARY);
+ return typeSet;
+ }
+}
\ No newline at end of file
diff --git a/plugins/storage/volume/ontap/src/main/resources/META-INF/cloudstack/storage-volume-ontap/module.properties b/plugins/storage/volume/ontap/src/main/resources/META-INF/cloudstack/storage-volume-ontap/module.properties
new file mode 100644
index 000000000000..67fd086eba10
--- /dev/null
+++ b/plugins/storage/volume/ontap/src/main/resources/META-INF/cloudstack/storage-volume-ontap/module.properties
@@ -0,0 +1,18 @@
+# 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.
+name=storage-volume-ontap
+parent=storage
diff --git a/plugins/storage/volume/ontap/src/main/resources/META-INF/cloudstack/storage-volume-ontap/spring-storage-volume-ontap-context.xml b/plugins/storage/volume/ontap/src/main/resources/META-INF/cloudstack/storage-volume-ontap/spring-storage-volume-ontap-context.xml
new file mode 100644
index 000000000000..6ab9c46fcf9d
--- /dev/null
+++ b/plugins/storage/volume/ontap/src/main/resources/META-INF/cloudstack/storage-volume-ontap/spring-storage-volume-ontap-context.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+