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 2014/01/09 04:54:54 UTC

git commit: updated refs/heads/4.3 to 2efe61d

Updated Branches:
  refs/heads/4.3 ce9760f4c -> 2efe61ddb


CLOUDSTACK-4810: Enable hypervisor snapshots for CloudStack-managed storage (for XenServer and VMware)


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

Branch: refs/heads/4.3
Commit: 2efe61ddbc57316348bc0fa328a09fe4dadb08d2
Parents: ce9760f
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Tue Jan 7 22:52:11 2014 -0700
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Wed Jan 8 20:53:53 2014 -0700

----------------------------------------------------------------------
 .../driver/SolidfirePrimaryDataStoreDriver.java | 108 ++++++++++++++++---
 .../storage/datastore/util/SolidFireUtil.java   |  54 ++++++++--
 2 files changed, 141 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2efe61dd/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 ff3e33b..0bf9c50 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
@@ -133,18 +133,15 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         return new SolidFireConnection(mVip, mPort, clusterAdminUsername, clusterAdminPassword);
     }
 
-    private SolidFireUtil.SolidFireAccount createSolidFireAccount(String sfAccountName,
-            SolidFireConnection sfConnection) {
+    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);
+        long accountNumber = SolidFireUtil.createSolidFireAccount(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfAccountName);
 
-        return SolidFireUtil.getSolidFireAccountById(mVip, mPort,
-                clusterAdminUsername, clusterAdminPassword, accountNumber);
+        return SolidFireUtil.getSolidFireAccountById(mVip, mPort, clusterAdminUsername, clusterAdminPassword, accountNumber);
     }
 
     private void updateCsDbWithAccountInfo(long csAccountId, SolidFireUtil.SolidFireAccount sfAccount) {
@@ -185,8 +182,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         private final String _targetUsername;
         private final String _targetSecret;
 
-        public ChapInfoImpl(String initiatorUsername, String initiatorSecret,
-                String targetUsername, String targetSecret) {
+        public ChapInfoImpl(String initiatorUsername, String initiatorSecret, String targetUsername, String targetSecret) {
             _initiatorUsername = initiatorUsername;
             _initiatorSecret = initiatorSecret;
             _targetUsername = targetUsername;
@@ -269,16 +265,39 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
             SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
                 sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), 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(),
-                getIqnsFromHosts(hosts), volumeIds);
+                hostIqns, volumeIds);
         }
         else {
-            long lVagId = SolidFireUtil.createSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
-                sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), "CloudStack-" + UUID.randomUUID().toString(),
-                getIqnsFromHosts(hosts), new long[] { sfVolumeId });
+            long lVagId;
+
+            try {
+                lVagId = SolidFireUtil.createSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+                    sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), "CloudStack-" + UUID.randomUUID().toString(),
+                    getIqnsFromHosts(hosts), new long[] { sfVolumeId });
+            }
+            catch (Exception ex) {
+                String iqnInVagAlready = "Exceeded maximum number of Volume Access Groups per initiator";
+
+                if (!ex.getMessage().contains(iqnInVagAlready)) {
+                    throw new CloudRuntimeException(ex.getMessage());
+                }
+
+                // getCompatibleVag throws an exception if an existing VAG can't be located
+                SolidFireUtil.SolidFireVag sfVag = getCompatibleVag(hosts, sfConnection);
+
+                long[] volumeIds = getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, true);
+
+                SolidFireUtil.modifySolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+                    sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), sfVag.getId(),
+                    sfVag.getInitiators(), volumeIds);
+
+                lVagId = sfVag.getId();
+            }
 
             clusterDetail = new ClusterDetailsVO(clusterId, getVagKey(storagePoolId), String.valueOf(lVagId));
 
@@ -288,6 +307,48 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         return true;
     }
 
+    // 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());
+
+        if (sfVags != null) {
+            List<String> hostIqns = new ArrayList<String>();
+
+            // where the method we're in is called, hosts should not be null
+            for (HostVO host : hosts) {
+                // where the method we're in is called, host.getStorageUrl() should not be null (it actually should start with "iqn")
+                hostIqns.add(host.getStorageUrl().toLowerCase());
+            }
+
+            for (SolidFireUtil.SolidFireVag sfVag : sfVags) {
+                List<String> lstInitiators = getStringArrayAsLowerCaseStringList(sfVag.getInitiators());
+
+                // lstInitiators should not be returned from getStringArrayAsLowerCaseStringList as null
+                if (lstInitiators.containsAll(hostIqns)) {
+                    return sfVag;
+                }
+            }
+        }
+
+        throw new CloudRuntimeException("Unable to locate the appropriate SolidFire Volume Access Group");
+    }
+
+    private List<String> getStringArrayAsLowerCaseStringList(String[] aString) {
+        List<String> lstLowerCaseString = new ArrayList<String>();
+
+        if (aString != null) {
+            for (String str : aString) {
+                if (str != null) {
+                    lstLowerCaseString.add(str.toLowerCase());
+                }
+            }
+        }
+
+        return lstLowerCaseString;
+      }
+
     // get the VAG associated with volumeInfo's cluster, if any (ListVolumeAccessGroups) // might not exist if using CHAP
     // if the VAG exists
     //     remove the ID of volumeInfo from the VAG (ModifyVolumeAccessGroup)
@@ -314,11 +375,12 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
             SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
                 sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), 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(),
-                getIqnsFromHosts(hosts), volumeIds);
+                hostIqns, volumeIds);
         }
     }
 
@@ -336,6 +398,26 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         return true;
     }
 
+    private String[] getNewHostIqns(String[] currentIqns, String[] newIqns) {
+        List<String> lstIqns = new ArrayList<String>();
+
+        if (currentIqns != null) {
+            for (String currentIqn : currentIqns) {
+                lstIqns.add(currentIqn);
+            }
+        }
+
+        if (newIqns != null) {
+            for (String newIqn : newIqns) {
+                if (!lstIqns.contains(newIqn)) {
+                    lstIqns.add(newIqn);
+                }
+            }
+        }
+
+        return lstIqns.toArray(new String[0]);
+    }
+
     private long[] getNewVolumeIds(long[] volumeIds, long volumeIdToAddOrRemove, boolean add) {
         if (add) {
             return getNewVolumeIdsAdd(volumeIds, volumeIdToAddOrRemove);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2efe61dd/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
index a372497..2d528ef 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
@@ -276,8 +276,7 @@ public class SolidFireUtil
         }
     }
 
-    public static long createSolidFireAccount(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword,
-            String strAccountName)
+    public static long createSolidFireAccount(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, String strAccountName)
     {
         final Gson gson = new GsonBuilder().create();
 
@@ -294,8 +293,7 @@ public class SolidFireUtil
         return accountAddResult.result.accountID;
     }
 
-    public static SolidFireAccount getSolidFireAccountById(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword,
-            long lSfAccountId)
+    public static SolidFireAccount getSolidFireAccountById(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lSfAccountId)
     {
         final Gson gson = new GsonBuilder().create();
 
@@ -316,8 +314,7 @@ public class SolidFireUtil
         return new SolidFireAccount(lSfAccountId, strSfAccountName, strSfAccountInitiatorSecret, strSfAccountTargetSecret);
     }
 
-    public static SolidFireAccount getSolidFireAccountByName(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword,
-            String strSfAccountName)
+    public static SolidFireAccount getSolidFireAccountByName(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, String strSfAccountName)
     {
         final Gson gson = new GsonBuilder().create();
 
@@ -338,8 +335,7 @@ public class SolidFireUtil
         return new SolidFireAccount(lSfAccountId, strSfAccountName, strSfAccountInitiatorSecret, strSfAccountTargetSecret);
     }
 
-    public static void deleteSolidFireAccount(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword,
-            long lAccountId)
+    public static void deleteSolidFireAccount(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lAccountId)
     {
         final Gson gson = new GsonBuilder().create();
 
@@ -467,6 +463,33 @@ public class SolidFireUtil
         return new SolidFireVag(lVagId, vagIqns, vagVolumeIds);
     }
 
+    public static List<SolidFireVag> getAllSolidFireVags(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword)
+    {
+        final Gson gson = new GsonBuilder().create();
+
+        AllVags allVags = new AllVags();
+
+        String strAllVagsJson = gson.toJson(allVags);
+
+        String strAllVagsGetResultJson = executeJsonRpc(strAllVagsJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
+
+        VagGetResult allVagsGetResult = gson.fromJson(strAllVagsGetResultJson, VagGetResult.class);
+
+        verifyResult(allVagsGetResult.result, strAllVagsGetResultJson, gson);
+
+        List<SolidFireVag> lstSolidFireVags = new ArrayList<SolidFireVag>();
+
+        if (allVagsGetResult.result.volumeAccessGroups != null ) {
+            for (VagGetResult.Result.Vag vag : allVagsGetResult.result.volumeAccessGroups) {
+                SolidFireVag sfVag = new SolidFireVag(vag.volumeAccessGroupID, vag.initiators, vag.volumes);
+
+                lstSolidFireVags.add(sfVag);
+            }
+        }
+
+        return lstSolidFireVags;
+    }
+
     public static void deleteSolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVagId)
     {
         final Gson gson = new GsonBuilder().create();
@@ -855,6 +878,21 @@ public class SolidFireUtil
     }
 
     @SuppressWarnings("unused")
+    private static final class AllVags
+    {
+        private final String method = "ListVolumeAccessGroups";
+        private final VagToGetParams params;
+
+        private AllVags()
+        {
+            params = new VagToGetParams();
+        }
+
+        private static final class VagToGetParams
+        {}
+    }
+
+    @SuppressWarnings("unused")
     private static final class VagToDelete
     {
         private final String method = "DeleteVolumeAccessGroup";