You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mt...@apache.org on 2015/10/24 06:12:47 UTC

[2/2] git commit: updated refs/heads/sf-4.3.2 to 5ef3288

Adding support for the SolidFireShared plug-in


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/5ef32886
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/5ef32886
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/5ef32886

Branch: refs/heads/sf-4.3.2
Commit: 5ef328860b45f5302f0ccd535367d614b0cd8839
Parents: ebf9897
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Tue Dec 16 15:33:43 2014 -0700
Committer: CloudStack <cloudstack@cloudstack-virtual-machine.(none)>
Committed: Fri Oct 23 22:06:17 2015 -0600

----------------------------------------------------------------------
 plugins/storage/volume/solidfire/pom.xml        |    5 +
 .../spring-storage-volume-solidfire-context.xml |    4 +-
 .../SolidFireSharedPrimaryDataStoreDriver.java  |   20 +
 .../driver/SolidfirePrimaryDataStoreDriver.java |  205 +---
 ...olidFireSharedPrimaryDataStoreLifeCycle.java |  535 +++++++++
 .../provider/SolidFireSharedHostListener.java   |   92 ++
 ...SolidFireSharedPrimaryDataStoreProvider.java |   83 ++
 .../storage/datastore/util/SolidFireUtil.java   | 1083 ++++++++++++++----
 8 files changed, 1655 insertions(+), 372 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/pom.xml b/plugins/storage/volume/solidfire/pom.xml
index 052fdf7..112e4ad 100644
--- a/plugins/storage/volume/solidfire/pom.xml
+++ b/plugins/storage/volume/solidfire/pom.xml
@@ -22,6 +22,11 @@
   <dependencies>
     <dependency>
       <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-plugin-storage-volume-default</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
       <artifactId>cloud-engine-storage-volume</artifactId>
       <version>${project.version}</version>
     </dependency>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/resources/META-INF/cloudstack/storage-volume-solidfire/spring-storage-volume-solidfire-context.xml
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/resources/META-INF/cloudstack/storage-volume-solidfire/spring-storage-volume-solidfire-context.xml b/plugins/storage/volume/solidfire/resources/META-INF/cloudstack/storage-volume-solidfire/spring-storage-volume-solidfire-context.xml
index a83e3ca..df32f1e 100644
--- a/plugins/storage/volume/solidfire/resources/META-INF/cloudstack/storage-volume-solidfire/spring-storage-volume-solidfire-context.xml
+++ b/plugins/storage/volume/solidfire/resources/META-INF/cloudstack/storage-volume-solidfire/spring-storage-volume-solidfire-context.xml
@@ -29,5 +29,7 @@
 
     <bean id="solidFireDataStoreProvider"
         class="org.apache.cloudstack.storage.datastore.provider.SolidfirePrimaryDataStoreProvider" />
-    
+    <bean id="solidFireSharedDataStoreProvider"
+        class="org.apache.cloudstack.storage.datastore.provider.SolidFireSharedPrimaryDataStoreProvider" />
+
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
new file mode 100644
index 0000000..365533c
--- /dev/null
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidFireSharedPrimaryDataStoreDriver.java
@@ -0,0 +1,20 @@
+// 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 org.apache.cloudstack.storage.datastore.driver;
+
+public class SolidFireSharedPrimaryDataStoreDriver extends CloudStackPrimaryDataStoreDriverImpl {
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
index 6a180ad..f83c86c 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
@@ -82,66 +82,10 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         return null;
     }
 
-    private static class SolidFireConnection {
-        private final String _managementVip;
-        private final int _managementPort;
-        private final String _clusterAdminUsername;
-        private final String _clusterAdminPassword;
+    private SolidFireUtil.SolidFireAccount createSolidFireAccount(String sfAccountName, SolidFireUtil.SolidFireConnection sfConnection) {
+        long accountNumber = SolidFireUtil.createSolidFireAccount(sfConnection, sfAccountName);
 
-        public SolidFireConnection(String managementVip, int managementPort,
-                String clusterAdminUsername, String clusterAdminPassword) {
-            _managementVip = managementVip;
-            _managementPort = managementPort;
-            _clusterAdminUsername = clusterAdminUsername;
-            _clusterAdminPassword = clusterAdminPassword;
-        }
-
-        public String getManagementVip() {
-            return _managementVip;
-        }
-
-        public int getManagementPort() {
-            return _managementPort;
-        }
-
-        public String getClusterAdminUsername() {
-            return _clusterAdminUsername;
-        }
-
-        public String getClusterAdminPassword() {
-            return _clusterAdminPassword;
-        }
-    }
-
-    private SolidFireConnection getSolidFireConnection(long storagePoolId) {
-        StoragePoolDetailVO storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, SolidFireUtil.MANAGEMENT_VIP);
-
-        String mVip = storagePoolDetail.getValue();
-
-        storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, SolidFireUtil.MANAGEMENT_PORT);
-
-        int mPort = Integer.parseInt(storagePoolDetail.getValue());
-
-        storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, SolidFireUtil.CLUSTER_ADMIN_USERNAME);
-
-        String clusterAdminUsername = storagePoolDetail.getValue();
-
-        storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, SolidFireUtil.CLUSTER_ADMIN_PASSWORD);
-
-        String clusterAdminPassword = storagePoolDetail.getValue();
-
-        return new SolidFireConnection(mVip, mPort, clusterAdminUsername, clusterAdminPassword);
-    }
-
-    private SolidFireUtil.SolidFireAccount createSolidFireAccount(String sfAccountName, SolidFireConnection sfConnection) {
-        String mVip = sfConnection.getManagementVip();
-        int mPort = sfConnection.getManagementPort();
-        String clusterAdminUsername = sfConnection.getClusterAdminUsername();
-        String clusterAdminPassword = sfConnection.getClusterAdminPassword();
-
-        long accountNumber = SolidFireUtil.createSolidFireAccount(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfAccountName);
-
-        return SolidFireUtil.getSolidFireAccountById(mVip, mPort, clusterAdminUsername, clusterAdminPassword, accountNumber);
+        return SolidFireUtil.getSolidFireAccountById(sfConnection, accountNumber);
     }
 
     private void updateCsDbWithAccountInfo(long csAccountId, SolidFireUtil.SolidFireAccount sfAccount) {
@@ -176,77 +120,18 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         _accountDetailsDao.persist(accountDetail);
     }
 
-    private class ChapInfoImpl implements ChapInfo {
-        private final String _initiatorUsername;
-        private final String _initiatorSecret;
-        private final String _targetUsername;
-        private final String _targetSecret;
-
-        public ChapInfoImpl(String initiatorUsername, String initiatorSecret, String targetUsername, String targetSecret) {
-            _initiatorUsername = initiatorUsername;
-            _initiatorSecret = initiatorSecret;
-            _targetUsername = targetUsername;
-            _targetSecret = targetSecret;
-        }
-
-        @Override
-        public String getInitiatorUsername() {
-            return _initiatorUsername;
-        }
-
-        @Override
-        public String getInitiatorSecret() {
-            return _initiatorSecret;
-        }
-
-        @Override
-        public String getTargetUsername() {
-            return _targetUsername;
-        }
-
-        @Override
-        public String getTargetSecret() {
-            return _targetSecret;
-        }
-    }
-
     @Override
     public ChapInfo getChapInfo(VolumeInfo volumeInfo) {
         return null;
     }
 
-    /*
-    @Override
-    public ChapInfo getChapInfo(VolumeInfo volumeInfo) {
-        long accountId = volumeInfo.getAccountId();
-
-        AccountDetailVO accountDetail = _accountDetailsDao.findDetail(accountId, SolidFireUtil.CHAP_INITIATOR_USERNAME);
-
-        String chapInitiatorUsername = accountDetail.getValue();
-
-        accountDetail = _accountDetailsDao.findDetail(accountId, SolidFireUtil.CHAP_INITIATOR_SECRET);
-
-        String chapInitiatorSecret = accountDetail.getValue();
-
-        accountDetail = _accountDetailsDao.findDetail(accountId, SolidFireUtil.CHAP_TARGET_USERNAME);
-
-        String chapTargetUsername = accountDetail.getValue();
-
-        accountDetail = _accountDetailsDao.findDetail(accountId, SolidFireUtil.CHAP_TARGET_SECRET);
-
-        String chapTargetSecret = accountDetail.getValue();
-
-        return new ChapInfoImpl(chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
-    }
-    */
-
     // get the VAG associated with volumeInfo's cluster, if any (ListVolumeAccessGroups)
     // if the VAG exists
     //     update the VAG to contain all IQNs of the hosts (ModifyVolumeAccessGroup)
     //     if the ID of volumeInfo in not in the VAG, add it (ModifyVolumeAccessGroup)
     // if the VAG doesn't exist, create it with the IQNs of the hosts and the ID of volumeInfo (CreateVolumeAccessGroup)
     @Override
-    public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore)
+    public synchronized boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore)
     {
         if (volumeInfo == null || host == null || dataStore == null) {
             return false;
@@ -266,25 +151,21 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
             return false;
         }
 
-        SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);
+        SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
 
         if (vagId != null) {
-            SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), Long.parseLong(vagId));
+            SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection, Long.parseLong(vagId));
 
             String[] hostIqns = getNewHostIqns(sfVag.getInitiators(), getIqnsFromHosts(hosts));
             long[] volumeIds = getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, true);
 
-            SolidFireUtil.modifySolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), sfVag.getId(),
-                hostIqns, volumeIds);
+            SolidFireUtil.modifySolidFireVag(sfConnection, sfVag.getId(), hostIqns, volumeIds);
         }
         else {
             long lVagId;
 
             try {
-                lVagId = SolidFireUtil.createSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                    sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), "CloudStack-" + UUID.randomUUID().toString(),
+                lVagId = SolidFireUtil.createSolidFireVag(sfConnection, "CloudStack-" + UUID.randomUUID().toString(),
                     getIqnsFromHosts(hosts), new long[] { sfVolumeId });
             }
             catch (Exception ex) {
@@ -299,9 +180,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
 
                 long[] volumeIds = getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, true);
 
-                SolidFireUtil.modifySolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                    sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), sfVag.getId(),
-                    sfVag.getInitiators(), volumeIds);
+                SolidFireUtil.modifySolidFireVag(sfConnection, sfVag.getId(), sfVag.getInitiators(), volumeIds);
 
                 lVagId = sfVag.getId();
             }
@@ -316,9 +195,8 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
 
     // this method takes in a collection of hosts and tries to find an existing VAG that has all three of them in it
     // if successful, the VAG is returned; else, a CloudRuntimeException is thrown and this issue should be corrected by an admin
-    private SolidFireUtil.SolidFireVag getCompatibleVag(List<HostVO> hosts, SolidFireConnection sfConnection) {
-        List<SolidFireUtil.SolidFireVag> sfVags = SolidFireUtil.getAllSolidFireVags(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword());
+    private SolidFireUtil.SolidFireVag getCompatibleVag(List<HostVO> hosts, SolidFireUtil.SolidFireConnection sfConnection) {
+        List<SolidFireUtil.SolidFireVag> sfVags = SolidFireUtil.getAllSolidFireVags(sfConnection);
 
         if (sfVags != null) {
             List<String> hostIqns = new ArrayList<String>();
@@ -360,7 +238,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
     // if the VAG exists
     //     remove the ID of volumeInfo from the VAG (ModifyVolumeAccessGroup)
     @Override
-    public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore)
+    public synchronized void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore)
     {
         if (volumeInfo == null || host == null || dataStore == null) {
             return;
@@ -377,17 +255,14 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         if (vagId != null) {
             List<HostVO> hosts = _hostDao.findByClusterId(clusterId);
 
-            SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);
+            SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
 
-            SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), Long.parseLong(vagId));
+            SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection, Long.parseLong(vagId));
 
             String[] hostIqns = getNewHostIqns(sfVag.getInitiators(), getIqnsFromHosts(hosts));
             long[] volumeIds = getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, false);
 
-            SolidFireUtil.modifySolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), sfVag.getId(),
-                hostIqns, volumeIds);
+            SolidFireUtil.modifySolidFireVag(sfConnection, sfVag.getId(), hostIqns, volumeIds);
         }
     }
 
@@ -525,13 +400,8 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         return (long)(maxIops * fClusterDefaultBurstIopsPercentOfMaxIops);
     }
 
-    private SolidFireUtil.SolidFireVolume createSolidFireVolume(VolumeInfo volumeInfo, SolidFireConnection sfConnection)
+    private SolidFireUtil.SolidFireVolume createSolidFireVolume(VolumeInfo volumeInfo, SolidFireUtil.SolidFireConnection sfConnection)
     {
-        String mVip = sfConnection.getManagementVip();
-        int mPort = sfConnection.getManagementPort();
-        String clusterAdminUsername = sfConnection.getClusterAdminUsername();
-        String clusterAdminPassword = sfConnection.getClusterAdminPassword();
-
         AccountDetailVO accountDetail = _accountDetailsDao.findDetail(volumeInfo.getAccountId(), SolidFireUtil.ACCOUNT_ID);
         long sfAccountId = Long.parseLong(accountDetail.getValue());
 
@@ -553,12 +423,12 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
 
         long volumeSize = getVolumeSizeIncludingHypervisorSnapshotReserve(volumeInfo, _storagePoolDao.findById(storagePoolId));
 
-        long sfVolumeId = SolidFireUtil.createSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword,
+        long sfVolumeId = SolidFireUtil.createSolidFireVolume(sfConnection,
                 getSolidFireVolumeName(volumeInfo.getName()), sfAccountId, volumeSize, true,
                 NumberFormat.getInstance().format(volumeInfo.getSize()),
                 iops.getMinIops(), iops.getMaxIops(), iops.getBurstIops());
 
-        return SolidFireUtil.getSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId);
+        return SolidFireUtil.getSolidFireVolume(sfConnection, sfVolumeId);
     }
 
     @Override
@@ -637,7 +507,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         }
     }
 
-    private SolidFireUtil.SolidFireVolume deleteSolidFireVolume(VolumeInfo volumeInfo, SolidFireConnection sfConnection)
+    private SolidFireUtil.SolidFireVolume deleteSolidFireVolume(VolumeInfo volumeInfo, SolidFireUtil.SolidFireConnection sfConnection)
     {
         Long storagePoolId = volumeInfo.getPoolId();
 
@@ -645,36 +515,15 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
             return null; // this volume was never assigned to a storage pool, so no SAN volume should exist for it
         }
 
-        String mVip = sfConnection.getManagementVip();
-        int mPort = sfConnection.getManagementPort();
-        String clusterAdminUsername = sfConnection.getClusterAdminUsername();
-        String clusterAdminPassword = sfConnection.getClusterAdminPassword();
-
         long sfVolumeId = Long.parseLong(volumeInfo.getFolder());
 
-        return SolidFireUtil.deleteSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId);
+        return SolidFireUtil.deleteSolidFireVolume(sfConnection, sfVolumeId);
     }
 
     private String getSfAccountName(String csAccountUuid, long csAccountId) {
         return "CloudStack_" + csAccountUuid + "_" + csAccountId;
     }
 
-    private boolean sfAccountExists(String sfAccountName, SolidFireConnection sfConnection) {
-        String mVip = sfConnection.getManagementVip();
-        int mPort = sfConnection.getManagementPort();
-        String clusterAdminUsername = sfConnection.getClusterAdminUsername();
-        String clusterAdminPassword = sfConnection.getClusterAdminPassword();
-
-        try {
-            SolidFireUtil.getSolidFireAccountByName(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfAccountName);
-        }
-        catch (Exception ex) {
-            return false;
-        }
-
-        return true;
-    }
-
     @Override
     public void createAsync(DataStore dataStore, DataObject dataObject,
             AsyncCompletionCallback<CreateCmdResult> callback) {
@@ -687,10 +536,16 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
             String sfAccountName = getSfAccountName(account.getUuid(), account.getAccountId());
 
             long storagePoolId = dataStore.getId();
-            SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);
+            SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
+
+            AccountDetailVO accountDetail = _accountDetailsDao.findDetail(volumeInfo.getAccountId(), SolidFireUtil.ACCOUNT_ID);
 
-            if (!sfAccountExists(sfAccountName, sfConnection)) {
-                SolidFireUtil.SolidFireAccount sfAccount = createSolidFireAccount(sfAccountName, sfConnection);
+            if (accountDetail == null || accountDetail.getValue() == null) {
+                SolidFireUtil.SolidFireAccount sfAccount = SolidFireUtil.getSolidFireAccount(sfConnection, sfAccountName);
+
+                if (sfAccount == null) {
+                    sfAccount = createSolidFireAccount(sfAccountName, sfConnection);
+                }
 
                 updateCsDbWithAccountInfo(account.getId(), sfAccount);
             }
@@ -786,7 +641,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
             // long sfAccountId = Long.parseLong(accountDetails.getValue());
 
             long storagePoolId = dataStore.getId();
-            SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);
+            SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
 
             SolidFireUtil.SolidFireVolume sfVolume = deleteSolidFireVolume(volumeInfo, sfConnection);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
new file mode 100644
index 0000000..89d1fa9
--- /dev/null
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFireSharedPrimaryDataStoreLifeCycle.java
@@ -0,0 +1,535 @@
+/*
+ * 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 org.apache.cloudstack.storage.datastore.lifecycle;
+
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.context.CallContext;
+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.PrimaryDataStoreInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
+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.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
+import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
+
+import com.cloud.template.TemplateManager;
+import com.cloud.user.AccountDetailsDao;
+import com.cloud.user.AccountVO;
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CreateStoragePoolCommand;
+import com.cloud.agent.api.DeleteStoragePoolCommand;
+import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.dc.ClusterDetailsDao;
+import com.cloud.dc.ClusterDetailsVO;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceManager;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.dao.StoragePoolHostDao;
+import com.cloud.storage.StorageManager;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.StoragePoolAutomation;
+import com.cloud.storage.StoragePoolHostVO;
+import com.cloud.storage.VMTemplateStoragePoolVO;
+import com.cloud.user.Account;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeCycle {
+    private static final Logger s_logger = Logger.getLogger(SolidFireSharedPrimaryDataStoreLifeCycle.class);
+
+    @Inject private AccountDao _accountDao;
+    @Inject private AccountDetailsDao _accountDetailsDao;
+    @Inject private AgentManager _agentMgr;
+    @Inject private ClusterDao _clusterDao;
+    @Inject private ClusterDetailsDao _clusterDetailsDao;
+    @Inject private DataCenterDao _zoneDao;
+    @Inject private HostDao _hostDao;
+    @Inject private PrimaryDataStoreDao _primaryDataStoreDao;
+    @Inject private PrimaryDataStoreHelper _primaryDataStoreHelper;
+    @Inject private ResourceManager _resourceMgr;
+    @Inject private StorageManager _storageMgr;
+    @Inject private StoragePoolAutomation _storagePoolAutomation;
+    @Inject private StoragePoolDetailsDao _storagePoolDetailsDao;
+    @Inject private StoragePoolHostDao _storagePoolHostDao;
+    @Inject protected TemplateManager _tmpltMgr;
+
+    // invoked to add primary storage that is based on the SolidFire plug-in
+    @Override
+    public DataStore initialize(Map<String, Object> dsInfos) {
+        final String CAPACITY_IOPS = "capacityIops";
+
+        String url = (String)dsInfos.get("url");
+        Long zoneId = (Long)dsInfos.get("zoneId");
+        Long podId = (Long)dsInfos.get("podId");
+        Long clusterId = (Long)dsInfos.get("clusterId");
+        String storagePoolName = (String)dsInfos.get("name");
+        String providerName = (String)dsInfos.get("providerName");
+        Long capacityBytes = (Long)dsInfos.get("capacityBytes");
+        Long capacityIops = (Long)dsInfos.get(CAPACITY_IOPS);
+        String tags = (String)dsInfos.get("tags");
+        @SuppressWarnings("unchecked")
+        Map<String, String> details = (Map<String, String>)dsInfos.get("details");
+
+        if (podId == null) {
+            throw new CloudRuntimeException("The Pod ID must be specified.");
+        }
+
+        if (clusterId == null) {
+            throw new CloudRuntimeException("The Cluster ID must be specified.");
+        }
+
+        String storageVip = SolidFireUtil.getStorageVip(url);
+        int storagePort = SolidFireUtil.getStoragePort(url);
+
+        if (capacityBytes == null || capacityBytes <= 0) {
+            throw new IllegalArgumentException("'capacityBytes' must be present and greater than 0.");
+        }
+
+        if (capacityIops == null || capacityIops <= 0) {
+            throw new IllegalArgumentException("'capacityIops' must be present and greater than 0.");
+        }
+
+        HypervisorType hypervisorType = getHypervisorTypeForCluster(clusterId);
+
+        if (!isSupportedHypervisorType(hypervisorType)) {
+            throw new CloudRuntimeException(hypervisorType + " is not a supported hypervisor type.");
+        }
+
+        PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters();
+
+        parameters.setType(getStorageType(hypervisorType));
+        parameters.setZoneId(zoneId);
+        parameters.setPodId(podId);
+        parameters.setClusterId(clusterId);
+        parameters.setName(storagePoolName);
+        parameters.setProviderName(providerName);
+        parameters.setManaged(false);
+        parameters.setCapacityBytes(capacityBytes);
+        parameters.setUsedBytes(0);
+        parameters.setCapacityIops(capacityIops);
+        parameters.setHypervisorType(hypervisorType);
+        parameters.setTags(tags);
+        parameters.setDetails(details);
+
+        String managementVip = SolidFireUtil.getManagementVip(url);
+        int managementPort = SolidFireUtil.getManagementPort(url);
+
+        details.put(SolidFireUtil.MANAGEMENT_VIP, managementVip);
+        details.put(SolidFireUtil.MANAGEMENT_PORT, String.valueOf(managementPort));
+
+        String clusterAdminUsername = SolidFireUtil.getValue(SolidFireUtil.CLUSTER_ADMIN_USERNAME, url);
+        String clusterAdminPassword = SolidFireUtil.getValue(SolidFireUtil.CLUSTER_ADMIN_PASSWORD, url);
+
+        details.put(SolidFireUtil.CLUSTER_ADMIN_USERNAME, clusterAdminUsername);
+        details.put(SolidFireUtil.CLUSTER_ADMIN_PASSWORD, clusterAdminPassword);
+
+        long lMinIops = 100;
+        long lMaxIops = 15000;
+        long lBurstIops = 15000;
+
+        try {
+            String minIops = SolidFireUtil.getValue(SolidFireUtil.MIN_IOPS, url);
+
+            if (minIops != null && minIops.trim().length() > 0) {
+                lMinIops = Long.parseLong(minIops);
+            }
+        } catch (Exception ex) {
+        }
+
+        try {
+            String maxIops = SolidFireUtil.getValue(SolidFireUtil.MAX_IOPS, url);
+
+            if (maxIops != null && maxIops.trim().length() > 0) {
+                lMaxIops = Long.parseLong(maxIops);
+            }
+        } catch (Exception ex) {
+        }
+
+        try {
+            String burstIops = SolidFireUtil.getValue(SolidFireUtil.BURST_IOPS, url);
+
+            if (burstIops != null && burstIops.trim().length() > 0) {
+                lBurstIops = Long.parseLong(burstIops);
+            }
+        } catch (Exception ex) {
+        }
+
+        if (lMinIops > lMaxIops) {
+            throw new CloudRuntimeException("The parameter '" + SolidFireUtil.MIN_IOPS + "' must be less than or equal to the parameter '" + SolidFireUtil.MAX_IOPS + "'.");
+        }
+
+        if (lMaxIops > lBurstIops) {
+            throw new CloudRuntimeException("The parameter '" + SolidFireUtil.MAX_IOPS + "' must be less than or equal to the parameter '" + SolidFireUtil.BURST_IOPS + "'.");
+        }
+
+        if (lMinIops != capacityIops) {
+            throw new CloudRuntimeException("The parameter '" + CAPACITY_IOPS + "' must be equal to the parameter '" + SolidFireUtil.MIN_IOPS + "'.");
+        }
+
+        if (lMinIops > SolidFireUtil.MAX_IOPS_PER_VOLUME || lMaxIops > SolidFireUtil.MAX_IOPS_PER_VOLUME || lBurstIops > SolidFireUtil.MAX_IOPS_PER_VOLUME) {
+            throw new CloudRuntimeException("This volume cannot exceed " + NumberFormat.getInstance().format(SolidFireUtil.MAX_IOPS_PER_VOLUME) + " IOPS.");
+        }
+
+        details.put(SolidFireUtil.MIN_IOPS, String.valueOf(lMinIops));
+        details.put(SolidFireUtil.MAX_IOPS, String.valueOf(lMaxIops));
+        details.put(SolidFireUtil.BURST_IOPS, String.valueOf(lBurstIops));
+
+        SolidFireUtil.SolidFireConnection sfConnection = new SolidFireUtil.SolidFireConnection(managementVip, managementPort, clusterAdminUsername, clusterAdminPassword);
+
+        SolidFireCreateVolume sfCreateVolume = createSolidFireVolume(sfConnection, storagePoolName, capacityBytes, lMinIops, lMaxIops, lBurstIops);
+
+        SolidFireUtil.SolidFireVolume sfVolume = sfCreateVolume.getVolume();
+
+        String iqn = sfVolume.getIqn();
+
+        details.put(SolidFireUtil.VOLUME_ID, String.valueOf(sfVolume.getId()));
+
+        parameters.setUuid(iqn);
+
+        parameters.setHost(storageVip);
+        parameters.setPort(storagePort);
+        parameters.setPath(iqn);
+
+        // this adds a row in the cloud.storage_pool table for this SolidFire volume
+        DataStore dataStore = _primaryDataStoreHelper.createPrimaryDataStore(parameters);
+
+        // now that we have a DataStore (we need the id from the DataStore instance), we can create a Volume Access Group, if need be, and
+        // place the newly created volume in the Volume Access Group
+        try {
+            List<HostVO> hosts = _hostDao.findByClusterId(clusterId);
+            ClusterVO cluster = _clusterDao.findById(clusterId);
+
+            synchronized (this) {
+                SolidFireUtil.placeVolumeInVolumeAccessGroup(sfConnection, sfVolume.getId(), dataStore.getId(), cluster.getUuid(), hosts, _clusterDetailsDao);
+            }
+
+            SolidFireUtil.SolidFireAccount sfAccount = sfCreateVolume.getAccount();
+            Account csAccount = CallContext.current().getCallingAccount();
+
+            SolidFireUtil.updateCsDbWithSolidFireAccountInfo(csAccount.getId(), sfAccount, dataStore.getId(), _accountDetailsDao);
+        } catch (Exception ex) {
+            _primaryDataStoreDao.expunge(dataStore.getId());
+
+            throw new CloudRuntimeException(ex.getMessage());
+        }
+
+        return dataStore;
+    }
+
+    private HypervisorType getHypervisorTypeForCluster(long clusterId) {
+        ClusterVO cluster = _clusterDao.findById(clusterId);
+
+        if (cluster == null) {
+            throw new CloudRuntimeException("Cluster ID '" + clusterId + "' was not found in the database.");
+        }
+
+        return cluster.getHypervisorType();
+    }
+
+    private StoragePoolType getStorageType(HypervisorType hypervisorType) {
+        if (HypervisorType.XenServer.equals(hypervisorType)) {
+            return StoragePoolType.IscsiLUN;
+        }
+
+        throw new CloudRuntimeException("The 'hypervisor' parameter must be '" + HypervisorType.XenServer + "'.");
+    }
+
+    private class SolidFireCreateVolume {
+        private final SolidFireUtil.SolidFireVolume _sfVolume;
+        private final SolidFireUtil.SolidFireAccount _sfAccount;
+
+        public SolidFireCreateVolume(SolidFireUtil.SolidFireVolume sfVolume, SolidFireUtil.SolidFireAccount sfAccount) {
+            _sfVolume = sfVolume;
+            _sfAccount = sfAccount;
+        }
+
+        public SolidFireUtil.SolidFireVolume getVolume() {
+            return _sfVolume;
+        }
+
+        public SolidFireUtil.SolidFireAccount getAccount() {
+            return _sfAccount;
+        }
+    }
+
+    private SolidFireCreateVolume createSolidFireVolume(SolidFireUtil.SolidFireConnection sfConnection,
+            String volumeName, long volumeSize, long minIops, long maxIops, long burstIops) {
+        try {
+            Account csAccount = CallContext.current().getCallingAccount();
+            long csAccountId = csAccount.getId();
+            AccountVO accountVo = _accountDao.findById(csAccountId);
+
+            String sfAccountName = SolidFireUtil.getSolidFireAccountName(accountVo.getUuid(), csAccountId);
+
+            SolidFireUtil.SolidFireAccount sfAccount = SolidFireUtil.getSolidFireAccount(sfConnection, sfAccountName);
+
+            if (sfAccount == null) {
+                long accountNumber = SolidFireUtil.createSolidFireAccount(sfConnection, sfAccountName);
+
+                sfAccount = SolidFireUtil.getSolidFireAccountById(sfConnection, accountNumber);
+            }
+
+            long sfVolumeId = SolidFireUtil.createSolidFireVolume(sfConnection, SolidFireUtil.getSolidFireVolumeName(volumeName), sfAccount.getId(), volumeSize,
+                    true, null, minIops, maxIops, burstIops);
+            SolidFireUtil.SolidFireVolume sfVolume = SolidFireUtil.getSolidFireVolume(sfConnection, sfVolumeId);
+
+            return new SolidFireCreateVolume(sfVolume, sfAccount);
+        } catch (Throwable e) {
+            throw new CloudRuntimeException("Failed to create a SolidFire volume: " + e.toString());
+        }
+    }
+
+    @Override
+    public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
+        return true;
+    }
+
+    @Override
+    public boolean attachCluster(DataStore store, ClusterScope scope) {
+        PrimaryDataStoreInfo primaryDataStoreInfo = (PrimaryDataStoreInfo)store;
+
+        // check if there is at least one host up in this cluster
+        List<HostVO> allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primaryDataStoreInfo.getClusterId(),
+                primaryDataStoreInfo.getPodId(), primaryDataStoreInfo.getDataCenterId());
+
+        if (allHosts.isEmpty()) {
+            _primaryDataStoreDao.expunge(primaryDataStoreInfo.getId());
+
+            throw new CloudRuntimeException("No host up to associate a storage pool with in cluster " + primaryDataStoreInfo.getClusterId());
+        }
+
+        boolean success = false;
+
+        for (HostVO host : allHosts) {
+            success = createStoragePool(host, primaryDataStoreInfo);
+
+            if (success) {
+                break;
+            }
+        }
+
+        if (!success) {
+            throw new CloudRuntimeException("Unable to create storage in cluster " + primaryDataStoreInfo.getClusterId());
+        }
+
+        List<HostVO> poolHosts = new ArrayList<HostVO>();
+
+        for (HostVO host : allHosts) {
+            try {
+                _storageMgr.connectHostToSharedPool(host.getId(), primaryDataStoreInfo.getId());
+
+                poolHosts.add(host);
+            } catch (Exception e) {
+                s_logger.warn("Unable to establish a connection between " + host + " and " + primaryDataStoreInfo, e);
+            }
+        }
+
+        if (poolHosts.isEmpty()) {
+            s_logger.warn("No host can access storage pool '" + primaryDataStoreInfo + "' on cluster '" + primaryDataStoreInfo.getClusterId() + "'.");
+
+            _primaryDataStoreDao.expunge(primaryDataStoreInfo.getId());
+
+            throw new CloudRuntimeException("Failed to access storage pool");
+        }
+
+        _primaryDataStoreHelper.attachCluster(store);
+
+        return true;
+    }
+
+    private boolean createStoragePool(HostVO host, StoragePool storagePool) {
+        long hostId = host.getId();
+        CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, storagePool);
+
+        Answer answer = _agentMgr.easySend(hostId, cmd);
+
+        if (answer != null && answer.getResult()) {
+            return true;
+        } else {
+            _primaryDataStoreDao.expunge(storagePool.getId());
+
+            String msg = "";
+
+            if (answer != null) {
+                msg = "Cannot create storage pool through host '" + hostId + "' due to the following: " + answer.getDetails();
+            } else {
+                msg = "Cannot create storage pool through host '" + hostId + "' due to CreateStoragePoolCommand returns null";
+            }
+
+            s_logger.warn(msg);
+
+            throw new CloudRuntimeException(msg);
+        }
+    }
+
+    @Override
+    public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) {
+        return true;
+    }
+
+    @Override
+    public boolean maintain(DataStore dataStore) {
+        _storagePoolAutomation.maintain(dataStore);
+        _primaryDataStoreHelper.maintain(dataStore);
+
+        return true;
+    }
+
+    @Override
+    public boolean cancelMaintain(DataStore store) {
+        _primaryDataStoreHelper.cancelMaintain(store);
+        _storagePoolAutomation.cancelMaintain(store);
+
+        return true;
+    }
+
+    // invoked to delete primary storage that is based on the SolidFire plug-in
+    @Override
+    public boolean deleteDataStore(DataStore dataStore) {
+        List<StoragePoolHostVO> hostPoolRecords = _storagePoolHostDao.listByPoolId(dataStore.getId());
+
+        HypervisorType hypervisorType = null;
+
+        if (hostPoolRecords.size() > 0 ) {
+            hypervisorType = getHypervisorType(hostPoolRecords.get(0).getHostId());
+        }
+
+        if (!isSupportedHypervisorType(hypervisorType)) {
+            throw new CloudRuntimeException(hypervisorType + " is not a supported hypervisor type.");
+        }
+
+        StoragePool storagePool = (StoragePool)dataStore;
+        StoragePoolVO storagePoolVO = _primaryDataStoreDao.findById(storagePool.getId());
+        List<VMTemplateStoragePoolVO> unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(storagePoolVO);
+
+        for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) {
+            _tmpltMgr.evictTemplateFromStoragePool(templatePoolVO);
+        }
+
+        Long clusterId = null;
+
+        for (StoragePoolHostVO host : hostPoolRecords) {
+            DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand(storagePool);
+
+            final Answer answer = _agentMgr.easySend(host.getHostId(), deleteCmd);
+
+            if (answer != null && answer.getResult()) {
+                s_logger.info("Successfully deleted storage pool using Host ID " + host.getHostId());
+
+                HostVO hostVO = this._hostDao.findById(host.getHostId());
+
+                if (hostVO != null) {
+                    clusterId = hostVO.getClusterId();
+                }
+
+                break;
+            }
+            else {
+                s_logger.error("Failed to delete storage pool using Host ID " + host.getHostId() + ": " + answer.getResult());
+            }
+        }
+
+        if (clusterId != null) {
+            removeVolumeFromVag(storagePool.getId(), clusterId);
+        }
+
+        deleteSolidFireVolume(storagePool.getId());
+
+        return _primaryDataStoreHelper.deletePrimaryDataStore(dataStore);
+    }
+
+    private synchronized void removeVolumeFromVag(long storagePoolId, long clusterId) {
+        long sfVolumeId = getVolumeId(storagePoolId);
+        ClusterDetailsVO clusterDetail = _clusterDetailsDao.findDetail(clusterId, SolidFireUtil.getVagKey(storagePoolId));
+
+        String vagId = clusterDetail != null ? clusterDetail.getValue() : null;
+
+        if (vagId != null) {
+            List<HostVO> hosts = _hostDao.findByClusterId(clusterId);
+
+            SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
+
+            SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection, Long.parseLong(vagId));
+
+            String[] hostIqns = SolidFireUtil.getNewHostIqns(sfVag.getInitiators(), SolidFireUtil.getIqnsFromHosts(hosts));
+            long[] volumeIds = SolidFireUtil.getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, false);
+
+            SolidFireUtil.modifySolidFireVag(sfConnection, sfVag.getId(), hostIqns, volumeIds);
+        }
+    }
+
+    private void deleteSolidFireVolume(long storagePoolId) {
+        SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
+
+        long sfVolumeId = getVolumeId(storagePoolId);
+
+        SolidFireUtil.deleteSolidFireVolume(sfConnection, sfVolumeId);
+    }
+
+    private long getVolumeId(long storagePoolId) {
+        StoragePoolDetailVO storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, SolidFireUtil.VOLUME_ID);
+
+        String volumeId = storagePoolDetail.getValue();
+
+        return Long.parseLong(volumeId);
+    }
+
+    private static boolean isSupportedHypervisorType(HypervisorType hypervisorType) {
+        return HypervisorType.XenServer.equals(hypervisorType);
+    }
+
+    private HypervisorType getHypervisorType(long hostId) {
+        HostVO host = _hostDao.findById(hostId);
+
+        if (host != null) {
+            return host.getHypervisorType();
+        }
+
+        return HypervisorType.None;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle#migrateToObjectStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore)
+     */
+    @Override
+    public boolean migrateToObjectStore(DataStore store) {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedHostListener.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedHostListener.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedHostListener.java
new file mode 100644
index 0000000..9881d1d
--- /dev/null
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedHostListener.java
@@ -0,0 +1,92 @@
+/*
+ * 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 org.apache.cloudstack.storage.datastore.provider;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.alert.AlertManager;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.StoragePoolHostVO;
+import com.cloud.storage.dao.StoragePoolHostDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class SolidFireSharedHostListener implements HypervisorHostListener {
+    private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class);
+
+    @Inject private AgentManager agentMgr;
+    @Inject private DataStoreManager dataStoreMgr;
+    @Inject private AlertManager alertMgr;
+    @Inject private StoragePoolHostDao storagePoolHostDao;
+    @Inject private PrimaryDataStoreDao primaryStoreDao;
+
+    @Override
+    public boolean hostConnect(long hostId, long storagePoolId) {
+        StoragePoolHostVO storagePoolHost = storagePoolHostDao.findByPoolHost(storagePoolId, hostId);
+
+        if (storagePoolHost == null) {
+            storagePoolHost = new StoragePoolHostVO(storagePoolId, hostId, "");
+
+            storagePoolHostDao.persist(storagePoolHost);
+        }
+
+        StoragePool storagePool = (StoragePool)dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
+        ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, storagePool);
+        Answer answer = agentMgr.easySend(hostId, cmd);
+
+        if (answer == null) {
+            throw new CloudRuntimeException("Unable to get an answer to the modify storage pool command for storage pool: " + storagePool.getId());
+        }
+
+        if (!answer.getResult()) {
+            String msg = "Unable to attach storage pool " + storagePoolId + " to the host " + hostId;
+
+            alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, storagePool.getDataCenterId(), storagePool.getPodId(), msg, msg);
+
+            throw new CloudRuntimeException(msg);
+        }
+
+        assert (answer instanceof ModifyStoragePoolAnswer) : "ModifyStoragePoolAnswer not returned from ModifyStoragePoolCommand; Storage pool = " +
+            storagePool.getId() + "; Host=" + hostId;
+
+        s_logger.info("Connection established between storage pool " + storagePool + " and host + " + hostId);
+
+        return true;
+    }
+
+    @Override
+    public boolean hostDisconnected(long hostId, long storagePoolId) {
+        StoragePoolHostVO storagePoolHost = storagePoolHostDao.findByPoolHost(storagePoolId, hostId);
+
+        if (storagePoolHost != null) {
+            storagePoolHostDao.deleteStoragePoolHostDetails(hostId, storagePoolId);
+        }
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5ef32886/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedPrimaryDataStoreProvider.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedPrimaryDataStoreProvider.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedPrimaryDataStoreProvider.java
new file mode 100644
index 0000000..d5b82a1
--- /dev/null
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/provider/SolidFireSharedPrimaryDataStoreProvider.java
@@ -0,0 +1,83 @@
+/*
+ * 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 org.apache.cloudstack.storage.datastore.provider;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.stereotype.Component;
+
+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.PrimaryDataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
+import org.apache.cloudstack.storage.datastore.driver.SolidFireSharedPrimaryDataStoreDriver;
+import org.apache.cloudstack.storage.datastore.lifecycle.SolidFireSharedPrimaryDataStoreLifeCycle;
+import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
+
+import com.cloud.utils.component.ComponentContext;
+
+@Component
+public class SolidFireSharedPrimaryDataStoreProvider implements PrimaryDataStoreProvider {
+    private DataStoreLifeCycle lifecycle;
+    private PrimaryDataStoreDriver driver;
+    private HypervisorHostListener listener;
+
+    SolidFireSharedPrimaryDataStoreProvider() {
+    }
+
+    @Override
+    public String getName() {
+        return SolidFireUtil.SHARED_PROVIDER_NAME;
+    }
+
+    @Override
+    public DataStoreLifeCycle getDataStoreLifeCycle() {
+        return lifecycle;
+    }
+
+    @Override
+    public PrimaryDataStoreDriver getDataStoreDriver() {
+        return driver;
+    }
+
+    @Override
+    public HypervisorHostListener getHostListener() {
+        return listener;
+    }
+
+    @Override
+    public boolean configure(Map<String, Object> params) {
+        lifecycle = ComponentContext.inject(SolidFireSharedPrimaryDataStoreLifeCycle.class);
+        driver = ComponentContext.inject(SolidFireSharedPrimaryDataStoreDriver.class);
+        listener = ComponentContext.inject(SolidFireSharedHostListener.class);
+
+        return true;
+    }
+
+    @Override
+    public Set<DataStoreProviderType> getTypes() {
+        Set<DataStoreProviderType> types = new HashSet<DataStoreProviderType>();
+
+        types.add(DataStoreProviderType.PRIMARY);
+
+        return types;
+    }
+}