mirror of https://github.com/apache/cloudstack.git
create Volume Access Groups per cluster instead of CloudStack-RandomUUID() (#3794)
* create vags per cluster * vagname in solidfire utils vag object * fix string compare * refactor to make use of existing map * fix typos * rebuild vag to iqn map after creating cluster vag * refactor loop using java 8 stream api * update null entry in vag to iqn map * remove null vag to iqn mapping when creating cluster id vag * add initiator to sf vag when adding hosts * use cluster uuid instead of cluster id and refactor * update null entry in vagtoiqnmap * update sfvag list after creating new vag * pass clusterDao to handleVagForHost * check if initiator is not already added to the vag * factor logic into methods * fix typo and camel case * fix listing clusters by zone id Co-authored-by: Sid Kattoju <siddharthakattoju@gmail.com>
This commit is contained in:
parent
ec60e820f0
commit
8dd6cef9a6
|
|
@ -172,9 +172,11 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
|
|||
try {
|
||||
List<HostVO> hosts = hostDao.findByClusterId(clusterId);
|
||||
|
||||
String clusterUuId = clusterDao.findById(clusterId).getUuid();
|
||||
|
||||
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, storagePoolDetailsDao);
|
||||
|
||||
SolidFireUtil.placeVolumeInVolumeAccessGroups(sfConnection, sfVolumeId, hosts);
|
||||
SolidFireUtil.placeVolumeInVolumeAccessGroups(sfConnection, sfVolumeId, hosts, clusterUuId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,7 +285,9 @@ public class SolidFireSharedPrimaryDataStoreLifeCycle implements PrimaryDataStor
|
|||
// place the newly created volume in the Volume Access Group
|
||||
List<HostVO> hosts = hostDao.findByClusterId(clusterId);
|
||||
|
||||
SolidFireUtil.placeVolumeInVolumeAccessGroups(sfConnection, sfVolume.getId(), hosts);
|
||||
String clusterUuId = clusterDao.findById(clusterId).getUuid();
|
||||
|
||||
SolidFireUtil.placeVolumeInVolumeAccessGroups(sfConnection, sfVolume.getId(), hosts, clusterUuId);
|
||||
|
||||
SolidFireUtil.SolidFireAccount sfAccount = sfCreateVolume.getAccount();
|
||||
Account csAccount = CallContext.current().getCallingAccount();
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ public class SolidFireUtil {
|
|||
}
|
||||
}
|
||||
else {
|
||||
List<ClusterVO> clustersInZone = clusterDao.listByZoneId(storagePoolVO.getDataCenterId());
|
||||
List<ClusterVO> clustersInZone = clusterDao.listClustersByDcId(storagePoolVO.getDataCenterId());
|
||||
|
||||
if (clustersInZone != null) {
|
||||
for (ClusterVO clusterInZone : clustersInZone) {
|
||||
|
|
@ -497,7 +497,7 @@ public class SolidFireUtil {
|
|||
if (sfVag != null) {
|
||||
placeVolumeIdsInVag(sfConnection, sfVags, sfVag, hostVO, hostDao);
|
||||
} else {
|
||||
handleVagForHost(sfConnection, sfVags, hostVO, hostDao);
|
||||
handleVagForHost(sfConnection, sfVags, hostVO, hostDao, clusterDao);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -513,12 +513,14 @@ public class SolidFireUtil {
|
|||
// creating a new VAG won't exceed 4 VAGs for the computer cluster).
|
||||
// If none of the hosts in the cluster are in a VAG, then leave this host out of a VAG.
|
||||
// Place applicable volume IDs in VAG, if need be (account of volume starts with SF_CS_ACCOUNT_PREFIX).
|
||||
private static void handleVagForHost(SolidFireUtil.SolidFireConnection sfConnection, List<SolidFireUtil.SolidFireVag> sfVags, Host host, HostDao hostDao) {
|
||||
private static void handleVagForHost(SolidFireUtil.SolidFireConnection sfConnection, List<SolidFireUtil.SolidFireVag> sfVags, Host host, HostDao hostDao, ClusterDao clusterDao) {
|
||||
List<HostVO> hostVOs = hostDao.findByClusterId(host.getClusterId());
|
||||
|
||||
if (hostVOs != null) {
|
||||
int numVags = 0;
|
||||
|
||||
addInitiatorsToExistingVag(clusterDao, host, sfVags, sfConnection);
|
||||
|
||||
Collections.shuffle(hostVOs, RANDOM);
|
||||
|
||||
for (HostVO hostVO : hostVOs) {
|
||||
|
|
@ -544,8 +546,9 @@ public class SolidFireUtil {
|
|||
throw new CloudRuntimeException(errMsg);
|
||||
}
|
||||
|
||||
addInitiatorsToSolidFireVag(sfConnection, sfVag.getId(), new String[] { host.getStorageUrl() });
|
||||
|
||||
if(!isInitiatorInSfVag(host.getStorageUrl(),sfVag)) {
|
||||
addInitiatorsToSolidFireVag(sfConnection, sfVag.getId(), new String[]{host.getStorageUrl()});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -571,6 +574,14 @@ public class SolidFireUtil {
|
|||
}
|
||||
}
|
||||
|
||||
private static void addInitiatorsToExistingVag(ClusterDao clusterDao, Host host, List<SolidFireUtil.SolidFireVag> sfVags, SolidFireUtil.SolidFireConnection sfConnection){
|
||||
String clusterUuId = clusterDao.findById(host.getClusterId()).getUuid();
|
||||
SolidFireVag sfVagMatchingClusterId = sfVags.stream().filter(vag -> vag.getName().equals("CloudStack-"+clusterUuId)).findFirst().orElse(null);
|
||||
if (sfVagMatchingClusterId != null && sfVagMatchingClusterId.getInitiators().length < MAX_NUM_INITIATORS_PER_VAG) {
|
||||
addInitiatorsToSolidFireVag(sfConnection, sfVagMatchingClusterId.getId(), new String[]{host.getStorageUrl()});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make use of the volume access group (VAG) of a random host in the cluster. With this VAG, collect all of its volume IDs that are for
|
||||
* volumes that are in SolidFire accounts that are for CloudStack.
|
||||
|
|
@ -683,7 +694,7 @@ public class SolidFireUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void placeVolumeInVolumeAccessGroups(SolidFireConnection sfConnection, long sfVolumeId, List<HostVO> hosts) {
|
||||
public static void placeVolumeInVolumeAccessGroups(SolidFireConnection sfConnection, long sfVolumeId, List<HostVO> hosts, String clusterUuId) {
|
||||
if (!SolidFireUtil.hostsSupport_iScsi(hosts)) {
|
||||
String errMsg = "Not all hosts in the compute cluster support iSCSI.";
|
||||
|
||||
|
|
@ -691,11 +702,50 @@ public class SolidFireUtil {
|
|||
|
||||
throw new CloudRuntimeException(errMsg);
|
||||
}
|
||||
|
||||
List<SolidFireUtil.SolidFireVag> sfVags = SolidFireUtil.getAllVags(sfConnection);
|
||||
Map<SolidFireUtil.SolidFireVag, List<String>> sfVagToIqnsMap = buildVagToIQNMap(hosts, sfVags);
|
||||
if (sfVagToIqnsMap.size() > MAX_NUM_VAGS_PER_VOLUME) {
|
||||
throw new CloudRuntimeException("A SolidFire volume can be in at most four volume access groups simultaneously.");
|
||||
}
|
||||
if (sfVagToIqnsMap.containsKey(null)) {
|
||||
sfVagToIqnsMap = updateNullKeyInSfVagToIqnsMap(sfVagToIqnsMap, sfVags, sfConnection, clusterUuId, sfVolumeId);
|
||||
}
|
||||
addVolumestoVagIfNotPresent(sfVagToIqnsMap.keySet(), sfVolumeId, sfConnection);
|
||||
}
|
||||
|
||||
private static Map<SolidFireUtil.SolidFireVag, List<String>> updateNullKeyInSfVagToIqnsMap(Map<SolidFireUtil.SolidFireVag,List<String>> sfVagToIqnsMap, List <SolidFireUtil.SolidFireVag> sfVags, SolidFireConnection sfConnection, String clusterUuId, long sfVolumeId){
|
||||
SolidFireUtil.SolidFireVag sfVagMatchingClusterId = createClusterVagIfDoesntExist(sfVags, sfConnection, clusterUuId, sfVagToIqnsMap, sfVolumeId);
|
||||
sfVagToIqnsMap.put(sfVagMatchingClusterId, sfVagToIqnsMap.get(null));
|
||||
sfVagToIqnsMap.remove(null);
|
||||
return sfVagToIqnsMap;
|
||||
}
|
||||
|
||||
private static SolidFireVag createClusterVagIfDoesntExist(List<SolidFireUtil.SolidFireVag> sfVags, SolidFireConnection sfConnection, String clusterUuId, Map<SolidFireUtil.SolidFireVag, List<String>> sfVagToIqnsMap, long sfVolumeId) {
|
||||
SolidFireVag sfVagMatchingClusterId = sfVags.stream().filter(vag -> vag.getName().equals("CloudStack-" + clusterUuId)).findFirst().orElse(null);
|
||||
if (sfVagMatchingClusterId == null) {
|
||||
LOGGER.info("Creating volume access group CloudStack-" + clusterUuId);
|
||||
SolidFireUtil.createVag(sfConnection, "CloudStack-" + clusterUuId, sfVagToIqnsMap.get(null).toArray(new String[0]), new long[]{sfVolumeId});
|
||||
sfVags = SolidFireUtil.getAllVags(sfConnection);
|
||||
return sfVags.stream().filter(vag -> vag.getName().equals("CloudStack-" + clusterUuId)).findFirst().orElse(null);
|
||||
}else{
|
||||
return sfVagMatchingClusterId;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addVolumestoVagIfNotPresent(Set<SolidFireUtil.SolidFireVag> sfVagSet, long sfVolumeId, SolidFireConnection sfConnection){
|
||||
for (SolidFireUtil.SolidFireVag sfVag : sfVagSet) {
|
||||
if (sfVag != null) {
|
||||
if (!SolidFireUtil.isVolumeIdInSfVag(sfVolumeId, sfVag)) {
|
||||
SolidFireUtil.addVolumeIdsToSolidFireVag(sfConnection, sfVag.getId(), new Long[] { sfVolumeId });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Map<SolidFireVag,List<String>> buildVagToIQNMap(List<HostVO> hosts, List<SolidFireVag> sfVags) {
|
||||
|
||||
Map<SolidFireUtil.SolidFireVag, List<String>> sfVagToIqnsMap = new HashMap<>();
|
||||
|
||||
for (HostVO hostVO : hosts) {
|
||||
String iqn = hostVO.getStorageUrl();
|
||||
|
||||
|
|
@ -705,24 +755,8 @@ public class SolidFireUtil {
|
|||
|
||||
iqnsInVag.add(iqn);
|
||||
}
|
||||
return sfVagToIqnsMap;
|
||||
|
||||
if (sfVagToIqnsMap.size() > MAX_NUM_VAGS_PER_VOLUME) {
|
||||
throw new CloudRuntimeException("A SolidFire volume can be in at most four volume access groups simultaneously.");
|
||||
}
|
||||
|
||||
for (SolidFireUtil.SolidFireVag sfVag : sfVagToIqnsMap.keySet()) {
|
||||
if (sfVag != null) {
|
||||
if (!SolidFireUtil.isVolumeIdInSfVag(sfVolumeId, sfVag)) {
|
||||
SolidFireUtil.addVolumeIdsToSolidFireVag(sfConnection, sfVag.getId(), new Long[] { sfVolumeId });
|
||||
}
|
||||
}
|
||||
else {
|
||||
List<String> iqnsNotInVag = sfVagToIqnsMap.get(null);
|
||||
|
||||
SolidFireUtil.createVag(sfConnection, "CloudStack-" + UUID.randomUUID().toString(),
|
||||
iqnsNotInVag.toArray(new String[0]), new long[] { sfVolumeId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SolidFireUtil.SolidFireVag getVolumeAccessGroup(String hostIqn, List<SolidFireUtil.SolidFireVag> sfVags) {
|
||||
|
|
@ -777,6 +811,18 @@ public class SolidFireUtil {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static boolean isInitiatorInSfVag(String initiatorName, SolidFireUtil.SolidFireVag sfVag) {
|
||||
String[] initiatorsList = sfVag.getInitiators();
|
||||
|
||||
for (String initiator : initiatorsList) {
|
||||
if (initiatorName.equals(initiator)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hostSupports_iScsi(Host host) {
|
||||
return host != null && host.getStorageUrl() != null && host.getStorageUrl().trim().length() > 0 && host.getStorageUrl().startsWith("iqn");
|
||||
}
|
||||
|
|
@ -1245,7 +1291,7 @@ public class SolidFireUtil {
|
|||
|
||||
if (vags != null) {
|
||||
for (VolumeAccessGroup vag : vags) {
|
||||
SolidFireVag sfVag = new SolidFireVag(vag.getVolumeAccessGroupID(), vag.getInitiators(), toPrimitive(vag.getVolumes()));
|
||||
SolidFireVag sfVag = new SolidFireVag(vag.getVolumeAccessGroupID(), vag.getInitiators(), toPrimitive(vag.getVolumes()), vag.getName());
|
||||
|
||||
lstSolidFireVags.add(sfVag);
|
||||
}
|
||||
|
|
@ -1258,11 +1304,13 @@ public class SolidFireUtil {
|
|||
private final long _id;
|
||||
private final String[] _initiators;
|
||||
private final long[] _volumeIds;
|
||||
private final String _vagName;
|
||||
|
||||
SolidFireVag(long id, String[] initiators, long[] volumeIds) {
|
||||
SolidFireVag(long id, String[] initiators, long[] volumeIds, String name) {
|
||||
_id = id;
|
||||
_initiators = initiators;
|
||||
_volumeIds = volumeIds;
|
||||
_vagName = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
|
|
@ -1277,6 +1325,8 @@ public class SolidFireUtil {
|
|||
return _volumeIds;
|
||||
}
|
||||
|
||||
public String getName() { return _vagName; }
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return String.valueOf(_id).hashCode();
|
||||
|
|
|
|||
Loading…
Reference in New Issue