mirror of https://github.com/apache/cloudstack.git
Linstor fix host picking (#12047)
This commit is contained in:
parent
2b373a4659
commit
8dcfc7c767
|
|
@ -63,6 +63,8 @@ import com.cloud.api.storage.LinstorBackupSnapshotCommand;
|
||||||
import com.cloud.api.storage.LinstorRevertBackupSnapshotCommand;
|
import com.cloud.api.storage.LinstorRevertBackupSnapshotCommand;
|
||||||
import com.cloud.configuration.Config;
|
import com.cloud.configuration.Config;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.Status;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.resource.ResourceState;
|
import com.cloud.resource.ResourceState;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
|
@ -921,9 +923,10 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
_backupsnapshotwait,
|
_backupsnapshotwait,
|
||||||
VirtualMachineManager.ExecuteInSequence.value());
|
VirtualMachineManager.ExecuteInSequence.value());
|
||||||
|
|
||||||
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(linstorApi, rscName);
|
final StoragePool pool = (StoragePool) volumeInfo.getDataStore();
|
||||||
|
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(linstorApi, pool, rscName);
|
||||||
if (optEP.isEmpty()) {
|
if (optEP.isEmpty()) {
|
||||||
optEP = getLinstorEP(linstorApi, rscName);
|
optEP = getLinstorEP(linstorApi, pool, rscName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optEP.isPresent()) {
|
if (optEP.isPresent()) {
|
||||||
|
|
@ -1063,13 +1066,29 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
Answer answer = copyVolume(srcData, dstData);
|
Answer answer = copyVolume(srcData, dstData);
|
||||||
res = new CopyCommandResult(null, answer);
|
res = new CopyCommandResult(null, answer);
|
||||||
} else {
|
} else {
|
||||||
Answer answer = new Answer(null, false, "noimpl");
|
throw new CloudRuntimeException("Not implemented for Linstor primary storage.");
|
||||||
res = new CopyCommandResult(null, answer);
|
|
||||||
res.setResult("Not implemented yet");
|
|
||||||
}
|
}
|
||||||
callback.complete(res);
|
callback.complete(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Host getEnabledClusterHost(StoragePool storagePool, List<String> linstorNodeNames) {
|
||||||
|
List<HostVO> csHosts;
|
||||||
|
if (storagePool.getClusterId() != null) {
|
||||||
|
csHosts = _hostDao.findByClusterId(storagePool.getClusterId());
|
||||||
|
} else {
|
||||||
|
csHosts = _hostDao.findByDataCenterId(storagePool.getDataCenterId());
|
||||||
|
}
|
||||||
|
Collections.shuffle(csHosts); // so we do not always pick the same host for operations
|
||||||
|
for (HostVO host : csHosts) {
|
||||||
|
if (host.getResourceState() == ResourceState.Enabled &&
|
||||||
|
host.getStatus() == Status.Up &&
|
||||||
|
linstorNodeNames.contains(host.getName())) {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to get a Linstor cloudstack end point, that is at least diskless.
|
* Tries to get a Linstor cloudstack end point, that is at least diskless.
|
||||||
*
|
*
|
||||||
|
|
@ -1078,49 +1097,39 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
* @return Optional RemoteHostEndPoint if one could get found.
|
* @return Optional RemoteHostEndPoint if one could get found.
|
||||||
* @throws ApiException
|
* @throws ApiException
|
||||||
*/
|
*/
|
||||||
private Optional<RemoteHostEndPoint> getLinstorEP(DevelopersApi api, String rscName) throws ApiException {
|
private Optional<RemoteHostEndPoint> getLinstorEP(DevelopersApi api, StoragePool storagePool, String rscName)
|
||||||
|
throws ApiException {
|
||||||
List<String> linstorNodeNames = LinstorUtil.getLinstorNodeNames(api);
|
List<String> linstorNodeNames = LinstorUtil.getLinstorNodeNames(api);
|
||||||
Collections.shuffle(linstorNodeNames); // do not always pick the first linstor node
|
Host host = getEnabledClusterHost(storagePool, linstorNodeNames);
|
||||||
|
if (host != null) {
|
||||||
Host host = null;
|
logger.info("Linstor: Make resource {} available on node {} ...", rscName, host.getName());
|
||||||
for (String nodeName : linstorNodeNames) {
|
ApiCallRcList answers = api.resourceMakeAvailableOnNode(
|
||||||
host = _hostDao.findByName(nodeName);
|
rscName, host.getName(), new ResourceMakeAvailable());
|
||||||
if (host != null && host.getResourceState() == ResourceState.Enabled) {
|
if (answers.hasError()) {
|
||||||
logger.info(String.format("Linstor: Make resource %s available on node %s ...", rscName, nodeName));
|
logger.error("Linstor: Unable to make resource {} on node {} available: {}",
|
||||||
ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, nodeName, new ResourceMakeAvailable());
|
rscName, host.getName(), LinstorUtil.getBestErrorMessage(answers));
|
||||||
if (!answers.hasError()) {
|
return Optional.empty();
|
||||||
break; // found working host
|
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
||||||
String.format("Linstor: Unable to make resource %s on node %s available: %s",
|
|
||||||
rscName,
|
|
||||||
nodeName,
|
|
||||||
LinstorUtil.getBestErrorMessage(answers)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host == null)
|
|
||||||
{
|
|
||||||
logger.error("Linstor: Couldn't create a resource on any cloudstack host.");
|
logger.error("Linstor: Couldn't create a resource on any cloudstack host.");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<RemoteHostEndPoint> getDiskfullEP(DevelopersApi api, String rscName) throws ApiException {
|
private Optional<RemoteHostEndPoint> getDiskfullEP(DevelopersApi api, StoragePool storagePool, String rscName)
|
||||||
|
throws ApiException {
|
||||||
List<com.linbit.linstor.api.model.StoragePool> linSPs = LinstorUtil.getDiskfulStoragePools(api, rscName);
|
List<com.linbit.linstor.api.model.StoragePool> linSPs = LinstorUtil.getDiskfulStoragePools(api, rscName);
|
||||||
if (linSPs != null) {
|
if (linSPs != null) {
|
||||||
for (com.linbit.linstor.api.model.StoragePool sp : linSPs) {
|
List<String> linstorNodeNames = linSPs.stream()
|
||||||
Host host = _hostDao.findByName(sp.getNodeName());
|
.map(com.linbit.linstor.api.model.StoragePool::getNodeName)
|
||||||
if (host != null && host.getResourceState() == ResourceState.Enabled) {
|
.collect(Collectors.toList());
|
||||||
|
Host host = getEnabledClusterHost(storagePool, linstorNodeNames);
|
||||||
|
if (host != null) {
|
||||||
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
logger.error("Linstor: No diskfull host found.");
|
logger.error("Linstor: No diskfull host found.");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
@ -1199,12 +1208,12 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
VirtualMachineManager.ExecuteInSequence.value());
|
VirtualMachineManager.ExecuteInSequence.value());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
|
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, pool, rscName);
|
||||||
if (optEP.isPresent()) {
|
if (optEP.isPresent()) {
|
||||||
answer = optEP.get().sendMessage(cmd);
|
answer = optEP.get().sendMessage(cmd);
|
||||||
} else {
|
} else {
|
||||||
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
|
|
||||||
deleteResourceDefinition(pool, rscName);
|
deleteResourceDefinition(pool, rscName);
|
||||||
|
throw new CloudRuntimeException("Unable to get matching Linstor endpoint.");
|
||||||
}
|
}
|
||||||
} catch (ApiException exc) {
|
} catch (ApiException exc) {
|
||||||
logger.error("copy template failed: ", exc);
|
logger.error("copy template failed: ", exc);
|
||||||
|
|
@ -1241,12 +1250,12 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
Answer answer;
|
Answer answer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
|
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, pool, rscName);
|
||||||
if (optEP.isPresent()) {
|
if (optEP.isPresent()) {
|
||||||
answer = optEP.get().sendMessage(cmd);
|
answer = optEP.get().sendMessage(cmd);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
|
throw new CloudRuntimeException("Unable to get matching Linstor endpoint.");
|
||||||
}
|
}
|
||||||
} catch (ApiException exc) {
|
} catch (ApiException exc) {
|
||||||
logger.error("copy volume failed: ", exc);
|
logger.error("copy volume failed: ", exc);
|
||||||
|
|
@ -1279,14 +1288,14 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
try {
|
try {
|
||||||
String devName = restoreResourceFromSnapshot(api, pool, rscName, snapshotName, restoreName);
|
String devName = restoreResourceFromSnapshot(api, pool, rscName, snapshotName, restoreName);
|
||||||
|
|
||||||
Optional<RemoteHostEndPoint> optEPAny = getLinstorEP(api, restoreName);
|
Optional<RemoteHostEndPoint> optEPAny = getLinstorEP(api, pool, restoreName);
|
||||||
if (optEPAny.isPresent()) {
|
if (optEPAny.isPresent()) {
|
||||||
// patch the src device path to the temporary linstor resource
|
// patch the src device path to the temporary linstor resource
|
||||||
snapshotObject.setPath(devName);
|
snapshotObject.setPath(devName);
|
||||||
origCmd.setSrcTO(snapshotObject.getTO());
|
origCmd.setSrcTO(snapshotObject.getTO());
|
||||||
answer = optEPAny.get().sendMessage(origCmd);
|
answer = optEPAny.get().sendMessage(origCmd);
|
||||||
} else{
|
} else {
|
||||||
answer = new Answer(origCmd, false, "Unable to get matching Linstor endpoint.");
|
throw new CloudRuntimeException("Unable to get matching Linstor endpoint.");
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// delete the temporary resource, noop if already gone
|
// delete the temporary resource, noop if already gone
|
||||||
|
|
@ -1348,7 +1357,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||||
VirtualMachineManager.ExecuteInSequence.value());
|
VirtualMachineManager.ExecuteInSequence.value());
|
||||||
cmd.setOptions(options);
|
cmd.setOptions(options);
|
||||||
|
|
||||||
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(api, rscName);
|
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(api, pool, rscName);
|
||||||
Answer answer;
|
Answer answer;
|
||||||
if (optEP.isPresent()) {
|
if (optEP.isPresent()) {
|
||||||
answer = optEP.get().sendMessage(cmd);
|
answer = optEP.get().sendMessage(cmd);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue