Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.cloud.storage.Storage;
import com.cloud.utils.exception.CloudRuntimeException;
import com.linbit.linstor.api.ApiClient;
import com.linbit.linstor.api.ApiConsts;
import com.linbit.linstor.api.ApiException;
import com.linbit.linstor.api.Configuration;
import com.linbit.linstor.api.DevelopersApi;
Expand Down Expand Up @@ -103,6 +104,10 @@ private void logLinstorAnswer(@Nonnull ApiCallRc answer) {
}
}

private void logLinstorAnswers(@Nonnull ApiCallRcList answers) {
answers.forEach(this::logLinstorAnswer);
}

private void checkLinstorAnswersThrow(@Nonnull ApiCallRcList answers) {
answers.forEach(this::logLinstorAnswer);
if (answers.hasError())
Expand Down Expand Up @@ -303,23 +308,90 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
return true;
}

private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
{
if (volumePath == null) {
return false;
}

s_logger.debug("Linstor: Using storage pool: " + pool.getUuid());
final DevelopersApi api = getLinstorAPI(pool);

Optional<ResourceWithVolumes> optRsc;
try
{
List<ResourceWithVolumes> resources = api.viewResources(
Collections.singletonList(localNodeName),
null,
null,
null,
null,
null);

optRsc = getResourceByPath(resources, volumePath);
} catch (ApiException apiEx) {
// couldn't query linstor controller
s_logger.error(apiEx.getBestMessage());
return false;
}


if (optRsc.isPresent()) {
try {
Resource rsc = optRsc.get();

// if diskless resource remove it, in the worst case it will be transformed to a tiebreaker
if (rsc.getFlags() != null &&
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) &&
!rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) {
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName);
logLinstorAnswers(delAnswers);
}

// remove allow-two-primaries
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries"));
ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm);
if (answers.hasError()) {
s_logger.error(
String.format("Failed to remove 'allow-two-primaries' on %s: %s",
rsc.getName(), LinstorUtil.getBestErrorMessage(answers)));
// do not fail here as removing allow-two-primaries property isn't fatal
}
} catch (ApiException apiEx) {
s_logger.error(apiEx.getBestMessage());
// do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal
}

return true;
}

s_logger.warn("Linstor: Couldn't find resource for this path: " + volumePath);
return false;
}

@Override
public boolean disconnectPhysicalDisk(String volumePath, KVMStoragePool pool)
{
s_logger.debug("Linstor: disconnectPhysicalDisk " + pool.getUuid() + ":" + volumePath);
if (MapStorageUuidToStoragePool.containsValue(pool)) {
return tryDisconnectLinstor(volumePath, pool);
}
return false;
}

@Override
public boolean disconnectPhysicalDisk(Map<String, String> volumeToDisconnect)
{
// as of now this is only relevant for iscsi targets
s_logger.info("Linstor: disconnectPhysicalDisk(Map<String, String> volumeToDisconnect) called?");
return false;
}

private Optional<ResourceWithVolumes> getResourceByPath(final List<ResourceWithVolumes> resources, String path) {
return resources.stream()
.filter(rsc -> rsc.getVolumes().stream()
.anyMatch(v -> v.getDevicePath().equals(path)))
.anyMatch(v -> path.equals(v.getDevicePath())))
.findFirst();
}

Expand All @@ -340,46 +412,8 @@ public boolean disconnectPhysicalDiskByPath(String localPath)
s_logger.debug("Linstor: disconnectPhysicalDiskByPath " + localPath);
final KVMStoragePool pool = optFirstPool.get();

s_logger.debug("Linstor: Using storpool: " + pool.getUuid());
final DevelopersApi api = getLinstorAPI(pool);

Optional<ResourceWithVolumes> optRsc;
try {
List<ResourceWithVolumes> resources = api.viewResources(
Collections.singletonList(localNodeName),
null,
null,
null,
null,
null);

optRsc = getResourceByPath(resources, localPath);
} catch (ApiException apiEx) {
// couldn't query linstor controller
s_logger.error(apiEx.getBestMessage());
return false;
}

if (optRsc.isPresent()) {
try {
Resource rsc = optRsc.get();
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries"));
ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm);
if (answers.hasError()) {
s_logger.error(
String.format("Failed to remove 'allow-two-primaries' on %s: %s",
rsc.getName(), LinstorUtil.getBestErrorMessage(answers)));
// do not fail here as removing allow-two-primaries property isn't fatal
}
} catch(ApiException apiEx){
s_logger.error(apiEx.getBestMessage());
// do not fail here as removing allow-two-primaries property isn't fatal
}
return true;
}
return tryDisconnectLinstor(localPath, pool);
}
s_logger.info("Linstor: Couldn't find resource for this path: " + localPath);
return false;
}

Expand Down