Skip to content

Commit

Permalink
linstor: cleanup diskless nodes on disconnect
Browse files Browse the repository at this point in the history
If disconnect is running on a diskless node, try to cleanup the resource.

Also fix a bug with the return value of disconnectPhysicalDiskByPath
that was introduced with 56f0448
  • Loading branch information
rp- committed Mar 25, 2024
1 parent f8fd22c commit af48a83
Showing 1 changed file with 79 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@
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;
import com.linbit.linstor.api.model.ApiCallRc;
import com.linbit.linstor.api.model.ApiCallRcList;
import com.linbit.linstor.api.model.Properties;
import com.linbit.linstor.api.model.ProviderKind;
import com.linbit.linstor.api.model.Resource;
import com.linbit.linstor.api.model.ResourceDefinition;
import com.linbit.linstor.api.model.ResourceDefinitionModify;
import com.linbit.linstor.api.model.ResourceGroup;
Expand Down Expand Up @@ -102,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 @@ -302,26 +308,89 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
return true;
}

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

private boolean tryDisconnectLinstor(String volumePath, KVMStoragePool pool)
{
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);
return true;
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)))
.findFirst();
}

/**
* disconnectPhysicalDiskByPath is called after e.g. a live migration.
* The problem is we have no idea just from the path to which linstor-controller
Expand All @@ -339,43 +408,9 @@ 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);

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

Optional<ResourceWithVolumes> rsc = getResourceByPath(resources, localPath);

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

return true;
}
s_logger.warn("Linstor: Couldn't find resource for this path: " + localPath);
} catch (ApiException apiEx) {
s_logger.error(apiEx.getBestMessage());
// do not fail here as removing allow-two-primaries property isn't fatal
}
return tryDisconnectLinstor(localPath, pool);
}
return true;
return false;
}

@Override
Expand Down

0 comments on commit af48a83

Please sign in to comment.