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/10 07:37:13 UTC

git commit: updated refs/heads/master to 68fda5a

Updated Branches:
  refs/heads/master a354d969c -> 68fda5a8d


Merge from 4.3: 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/68fda5a8
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/68fda5a8
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/68fda5a8

Branch: refs/heads/master
Commit: 68fda5a8ddaa7817277ac740b1e4b6986dc710a8
Parents: a354d96
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Thu Jan 9 23:36:36 2014 -0700
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Thu Jan 9 23:36:36 2014 -0700

----------------------------------------------------------------------
 .../driver/SolidfirePrimaryDataStoreDriver.java | 96 +++++++++++++++++++-
 .../storage/datastore/util/SolidFireUtil.java   | 60 ++++++++++--
 2 files changed, 143 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68fda5a8/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 1212b60..7d305e0 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
@@ -272,16 +272,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));
 
@@ -291,6 +314,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)
@@ -317,11 +382,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);
         }
     }
 
@@ -339,6 +405,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/68fda5a8/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 8d023d6..3c457ba 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
@@ -267,7 +267,8 @@ 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();
 
         AccountToAdd accountToAdd = new AccountToAdd(strAccountName);
@@ -283,8 +284,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();
 
@@ -305,7 +305,8 @@ 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();
 
         AccountToGetByName accountToGetByName = new AccountToGetByName(strSfAccountName);
@@ -325,8 +326,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();
 
@@ -449,7 +449,35 @@ public class SolidFireUtil {
         return new SolidFireVag(lVagId, vagIqns, vagVolumeIds);
     }
 
-    public static void deleteSolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVagId) {
+    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();
 
         VagToDelete vagToDelete = new VagToDelete(lVagId);
@@ -817,7 +845,23 @@ public class SolidFireUtil {
     }
 
     @SuppressWarnings("unused")
-    private static final class VagToDelete {
+    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";
         private final VagToDeleteParams params;