Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions plugins/storage/volume/linstor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to Linstor CloudStack plugin will be documented in this file
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2024-12-13]

### Fixed

- Linstor heartbeat check now also ask linstor-controller if there is no connection between nodes

## [2024-10-28]

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
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.Node;
import com.linbit.linstor.api.model.Properties;
import com.linbit.linstor.api.model.ProviderKind;
import com.linbit.linstor.api.model.Resource;
Expand Down Expand Up @@ -712,4 +713,19 @@ public long getUsed(LinstorStoragePool pool) {
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
}
}

public boolean isNodeOnline(LinstorStoragePool pool, String nodeName) {
DevelopersApi linstorApi = getLinstorAPI(pool);
try {
List<Node> node = linstorApi.nodeList(Collections.singletonList(nodeName), Collections.emptyList(), null, null);
if (node == null || node.isEmpty()) {
return false;
}

return Node.ConnectionStatusEnum.ONLINE.equals(node.get(0).getConnectionStatus());
} catch (ApiException apiEx) {
s_logger.error(apiEx.getMessage());
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -279,22 +279,52 @@ private String executeDrbdSetupStatus(OutputInterpreter.AllLinesParser parser) {
return sc.execute(parser);
}

private boolean checkLinstorNodeOnline(String nodeName) {
return ((LinstorStorageAdaptor)_storageAdaptor).isNodeOnline(this, nodeName);
}

/**
* Checks output of drbdsetup status output if this node has any valid connection to the specified
* otherNodeName.
* If there is no connection, ask the Linstor controller if the node is seen online and return false if not.
* If there is a connection but not connected(valid) return false.
* @param output Output of the drbdsetup status --json command
* @param otherNodeName Name of the node to check against
* @return true if we could say that this node thinks the node in question is reachable, otherwise false.
*/
private boolean checkDrbdSetupStatusOutput(String output, String otherNodeName) {
JsonParser jsonParser = new JsonParser();
JsonArray jResources = (JsonArray) jsonParser.parse(output);
boolean connectionFound = false;
for (JsonElement jElem : jResources) {
JsonObject jRes = (JsonObject) jElem;
JsonArray jConnections = jRes.getAsJsonArray("connections");
for (JsonElement jConElem : jConnections) {
JsonObject jConn = (JsonObject) jConElem;
if (jConn.getAsJsonPrimitive("name").getAsString().equals(otherNodeName)
&& jConn.getAsJsonPrimitive("connection-state").getAsString().equalsIgnoreCase("Connected")) {
return true;
if (jConn.getAsJsonPrimitive("name").getAsString().equals(otherNodeName))
{
connectionFound = true;
if (jConn.getAsJsonPrimitive("connection-state").getAsString()
.equalsIgnoreCase("Connected")) {
return true;
}
}
}
}
s_logger.warn(String.format("checkDrbdSetupStatusOutput: no resource connected to %s.", otherNodeName));
return false;
boolean otherNodeOnline = false;
if (connectionFound) {
s_logger.warn(String.format(
"checkingHeartBeat: connection found, but not in state 'Connected' to %s", otherNodeName));
} else {
s_logger.warn(String.format(
"checkingHeartBeat: no resource connected to %s, checking LINSTOR", otherNodeName));
otherNodeOnline = checkLinstorNodeOnline(otherNodeName);
}
s_logger.info(String.format(
"checkingHeartBeat: other node %s is %s.",
otherNodeName,
otherNodeOnline ? "online on controller" : "down"));
return otherNodeOnline;
}

private String executeDrbdEventsNow(OutputInterpreter.AllLinesParser parser) {
Expand Down