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

This commit is contained in:
Mike Tutkowski 2014-01-09 23:36:36 -07:00
parent a354d969ce
commit 68fda5a8dd
2 changed files with 143 additions and 13 deletions

View File

@ -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);

View File

@ -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;