Skip to content

Commit

Permalink
Linstor fix migration while node offline (apache#8610)
Browse files Browse the repository at this point in the history
* linstor: Add util method getBestErrorMessage from main

* linstor: failed remove of allow-two-primaries is no fatal error

* linstor: Fix failure if a Linstor node is down while migrating

If a Linstor node is down while migrating resource, allow-two-primaries
setting will fail because we can't reach the downed node. But it will
still set the property on the other nodes and migration should work.
We now just report an error instead of completely failing.
  • Loading branch information
rp- authored Feb 8, 2024
1 parent 3fa052c commit 56f0448
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -269,27 +269,35 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
}

final DevelopersApi api = getLinstorAPI(pool);
String rscName;
try
{
final String rscName = getLinstorRscName(volumePath);
rscName = getLinstorRscName(volumePath);

ResourceMakeAvailable rma = new ResourceMakeAvailable();
ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, localNodeName, rma);
checkLinstorAnswersThrow(answers);

} catch (ApiException apiEx) {
s_logger.error(apiEx);
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
}

try
{
// allow 2 primaries for live migration, should be removed by disconnect on the other end
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
Properties props = new Properties();
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
rdm.setOverrideProps(props);
answers = api.resourceDefinitionModify(rscName, rdm);
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
if (answers.hasError()) {
s_logger.error("Unable to set 'allow-two-primaries' on " + rscName);
throw new CloudRuntimeException(answers.get(0).getMessage());
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
}
} catch (ApiException apiEx) {
s_logger.error(apiEx);
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
}
return true;
}
Expand Down Expand Up @@ -353,19 +361,21 @@ public boolean disconnectPhysicalDiskByPath(String localPath)
ApiCallRcList answers = api.resourceDefinitionModify(rsc.get().getName(), rdm);
if (answers.hasError())
{
s_logger.error("Failed to remove 'allow-two-primaries' on " + rsc.get().getName());
throw new CloudRuntimeException(answers.get(0).getMessage());
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);
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
s_logger.error(apiEx.getBestMessage());
// do not fail here as removing allow-two-primaries property isn't fatal
}
}
return false;
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
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.ProviderKind;
import com.linbit.linstor.api.model.ResourceGroup;
import com.linbit.linstor.api.model.StoragePool;
Expand Down Expand Up @@ -47,6 +49,15 @@ public static DevelopersApi getLinstorAPI(String linstorUrl) {
return new DevelopersApi(client);
}

public static String getBestErrorMessage(ApiCallRcList answers) {
return answers != null && !answers.isEmpty() ?
answers.stream()
.filter(ApiCallRc::isError)
.findFirst()
.map(ApiCallRc::getMessage)
.orElse((answers.get(0)).getMessage()) : null;
}

public static long getCapacityBytes(String linstorUrl, String rscGroupName) {
DevelopersApi linstorApi = getLinstorAPI(linstorUrl);
try {
Expand Down

0 comments on commit 56f0448

Please sign in to comment.