use of org.apache.ignite.spi.IgniteNodeValidationResult in project ignite by apache.
the class ValidationOnNodeJoinUtils method validateHashIdResolvers.
/**
* @param node Joining node.
* @param ctx Context.
* @param map Cache descriptors.
* @return Validation result or {@code null} in case of success.
*/
@Nullable
static IgniteNodeValidationResult validateHashIdResolvers(ClusterNode node, GridKernalContext ctx, Map<String, DynamicCacheDescriptor> map) {
if (!node.isClient()) {
for (DynamicCacheDescriptor desc : map.values()) {
CacheConfiguration cfg = desc.cacheConfiguration();
if (cfg.getAffinity() instanceof RendezvousAffinityFunction) {
RendezvousAffinityFunction aff = (RendezvousAffinityFunction) cfg.getAffinity();
Object nodeHashObj = aff.resolveNodeHash(node);
for (ClusterNode topNode : ctx.discovery().aliveServerNodes()) {
Object topNodeHashObj = aff.resolveNodeHash(topNode);
if (nodeHashObj.hashCode() == topNodeHashObj.hashCode()) {
String errMsg = "Failed to add node to topology because it has the same hash code for " + "partitioned affinity as one of existing nodes [cacheName=" + cfg.getName() + ", existingNodeId=" + topNode.id() + ']';
String sndMsg = "Failed to add node to topology because it has the same hash code for " + "partitioned affinity as one of existing nodes [cacheName=" + cfg.getName() + ", existingNodeId=" + topNode.id() + ']';
return new IgniteNodeValidationResult(topNode.id(), errMsg, sndMsg);
}
}
}
}
}
return null;
}
use of org.apache.ignite.spi.IgniteNodeValidationResult in project ignite by apache.
the class DistributedMetaStorageImpl method validateNode.
/**
* {@inheritDoc}
* <br/>
* If local node is client then method should do nothing. It is expected that this method is invoked on coordinator
* node, but there might be exceptions to this. Validation rules:
* <ul>
* <li>
* Do not join node that has no distributed metastorage if feature is supported in current topology and
* distributed metastorage has already been used ({@link #getUpdatesCount()} is not zero).
* </li>
* <li>
* Do not join node that has updates count greater then on local node and hasn't provided enough history
* to apply it to the cluster.
* </li>
* <li>
* Do not join node if its distributed metastorage version hash differs from the local one. In such cases
* node is probably from different cluster or has some inconsistent data.
* </li>
* </ul>
*/
@Override
@Nullable
public IgniteNodeValidationResult validateNode(ClusterNode node, JoiningNodeDiscoveryData discoData) {
if (isClient)
return null;
lock.readLock().lock();
try {
DistributedMetaStorageVersion locVer = ver;
if (!discoData.hasJoiningNodeData()) {
if (isSupported(ctx) && locVer.id() > 0 && !(node.isClient() || node.isDaemon())) {
String errorMsg = "Node not supporting distributed metastorage feature" + " is not allowed to join the cluster";
return new IgniteNodeValidationResult(node.id(), errorMsg);
} else
return null;
}
DistributedMetaStorageJoiningNodeData joiningData = getJoiningNodeData(discoData);
if (joiningData == null) {
String errorMsg = "Cannot unmarshal joining node data";
return new IgniteNodeValidationResult(node.id(), errorMsg);
}
if (!isPersistenceEnabled)
return null;
DistributedMetaStorageVersion remoteVer = joiningData.ver;
DistributedMetaStorageHistoryItem[] remoteHist = joiningData.hist;
int remoteHistSize = remoteHist.length;
int remoteBltId = joiningData.bltId;
boolean clusterIsActive = isActive();
String errorMsg;
int locBltId = getBaselineTopologyId();
int locHistSize = histCache.size();
if (remoteVer.id() < locVer.id() - locHistSize) {
// Remote node is too far behind.
// Technicaly this situation should be banned because there's no way to prove data consistency.
errorMsg = null;
} else if (remoteVer.id() < locVer.id()) {
// Remote node it behind the cluster version and there's enough history.
DistributedMetaStorageVersion newRemoteVer = remoteVer.nextVersion(this::historyItem, remoteVer.id() + 1, locVer.id());
if (newRemoteVer.equals(locVer))
errorMsg = null;
else
errorMsg = "Joining node has conflicting distributed metastorage data.";
} else if (remoteVer.id() == locVer.id()) {
// Remote and local versions match.
if (remoteVer.equals(locVer))
errorMsg = null;
else {
errorMsg = S.toString("Joining node has conflicting distributed metastorage data:", "clusterVersion", locVer, false, "joiningNodeVersion", remoteVer, false);
}
} else if (remoteVer.id() <= locVer.id() + remoteHistSize) {
// Remote node is ahead of the cluster and has enough history.
if (clusterIsActive) {
errorMsg = "Attempting to join node with larger distributed metastorage version id." + " The node is most likely in invalid state and can't be joined.";
} else if (remoteBltId < locBltId)
errorMsg = "Joining node has conflicting distributed metastorage data.";
else {
DistributedMetaStorageVersion newLocVer = locVer.nextVersion(remoteHist, remoteHistSize - (int) (remoteVer.id() - locVer.id()), remoteHistSize);
if (newLocVer.equals(remoteVer))
errorMsg = null;
else
errorMsg = "Joining node has conflicting distributed metastorage data.";
}
} else {
assert remoteVer.id() > locVer.id() + remoteHistSize;
// Remote node is too far ahead.
if (clusterIsActive) {
errorMsg = "Attempting to join node with larger distributed metastorage version id." + " The node is most likely in invalid state and can't be joined.";
} else if (remoteBltId < locBltId)
errorMsg = "Joining node has conflicting distributed metastorage data.";
else {
errorMsg = "Joining node doesn't have enough history items in distributed metastorage data." + " Please check the order in which you start cluster nodes.";
}
}
if (errorMsg == null)
errorMsg = validatePayload(joiningData);
return (errorMsg == null) ? null : new IgniteNodeValidationResult(node.id(), errorMsg);
} finally {
lock.readLock().unlock();
}
}
use of org.apache.ignite.spi.IgniteNodeValidationResult in project ignite by apache.
the class CacheObjectBinaryProcessorImpl method validateBinaryConfiguration.
/**
*/
private IgniteNodeValidationResult validateBinaryConfiguration(ClusterNode rmtNode) {
Object rmtBinaryCfg = rmtNode.attribute(IgniteNodeAttributes.ATTR_BINARY_CONFIGURATION);
ClusterNode locNode = ctx.discovery().localNode();
Object locBinaryCfg = locNode.attribute(IgniteNodeAttributes.ATTR_BINARY_CONFIGURATION);
if (!F.eq(locBinaryCfg, rmtBinaryCfg)) {
String msg = "Local node's binary configuration is not equal to remote node's binary configuration " + "[locNodeId=%s, rmtNodeId=%s, locBinaryCfg=%s, rmtBinaryCfg=%s]";
return new IgniteNodeValidationResult(rmtNode.id(), String.format(msg, locNode.id(), rmtNode.id(), locBinaryCfg, rmtBinaryCfg), String.format(msg, rmtNode.id(), locNode.id(), rmtBinaryCfg, locBinaryCfg));
}
return null;
}
use of org.apache.ignite.spi.IgniteNodeValidationResult in project ignite by apache.
the class GridClusterStateProcessor method validateNode.
/**
* {@inheritDoc}
*/
@Nullable
@Override
public IgniteNodeValidationResult validateNode(ClusterNode node, DiscoveryDataBag.JoiningNodeDiscoveryData discoData) {
if (node.isClient() || node.isDaemon())
return null;
if (globalState.state() == ACTIVE_READ_ONLY && !IgniteFeatures.nodeSupports(node, CLUSTER_READ_ONLY_MODE)) {
String msg = "Node not supporting cluster read-only mode is not allowed to join the cluster with enabled" + " read-only mode";
return new IgniteNodeValidationResult(node.id(), msg, msg);
}
if (discoData.joiningNodeData() == null) {
if (globalState.baselineTopology() != null) {
String msg = "Node not supporting BaselineTopology" + " is not allowed to join the cluster with BaselineTopology";
return new IgniteNodeValidationResult(node.id(), msg);
}
return null;
}
DiscoveryDataClusterState joiningNodeState;
try {
joiningNodeState = marsh.unmarshal((byte[]) discoData.joiningNodeData(), U.resolveClassLoader(ctx.config()));
} catch (IgniteCheckedException e) {
String msg = "Error on unmarshalling discovery data " + "from node " + node.consistentId() + ": " + e.getMessage() + "; node is not allowed to join";
return new IgniteNodeValidationResult(node.id(), msg);
}
if (joiningNodeState == null || joiningNodeState.baselineTopology() == null)
return null;
if (globalState == null || globalState.baselineTopology() == null) {
if (joiningNodeState != null && joiningNodeState.baselineTopology() != null) {
String msg = "Node with set up BaselineTopology is not allowed to join cluster without one: " + node.consistentId();
return new IgniteNodeValidationResult(node.id(), msg);
}
}
if (globalState.transition() && globalState.previousBaselineTopology() == null) {
// case when cluster is activating for the first time and other node with existing baseline topology
// tries to join
String msg = "Node with set up BaselineTopology is not allowed " + "to join cluster in the process of first activation: " + node.consistentId();
return new IgniteNodeValidationResult(node.id(), msg);
}
BaselineTopology clusterBlt;
if (globalState.transition())
clusterBlt = globalState.previousBaselineTopology();
else
clusterBlt = globalState.baselineTopology();
BaselineTopology joiningNodeBlt = joiningNodeState.baselineTopology();
String recommendation = " Consider cleaning persistent storage of the node and adding it to the cluster again.";
if (joiningNodeBlt.id() > clusterBlt.id()) {
String msg = "BaselineTopology of joining node (" + node.consistentId() + ") is not compatible with BaselineTopology in the cluster." + " Joining node BlT id (" + joiningNodeBlt.id() + ") is greater than cluster BlT id (" + clusterBlt.id() + ")." + " New BaselineTopology was set on joining node with set-baseline command." + recommendation;
return new IgniteNodeValidationResult(node.id(), msg);
}
if (joiningNodeBlt.id() == clusterBlt.id()) {
if (!clusterBlt.isCompatibleWith(joiningNodeBlt)) {
String msg = "BaselineTopology of joining node (" + node.consistentId() + ") is not compatible with BaselineTopology in the cluster." + " Branching history of cluster BlT (" + clusterBlt.branchingHistory() + ") doesn't contain branching point hash of joining node BlT (" + joiningNodeBlt.branchingPointHash() + ")." + recommendation;
return new IgniteNodeValidationResult(node.id(), msg);
}
} else if (joiningNodeBlt.id() < clusterBlt.id()) {
if (!bltHist.isCompatibleWith(joiningNodeBlt)) {
String msg = "BaselineTopology of joining node (" + node.consistentId() + ") is not compatible with BaselineTopology in the cluster." + " BlT id of joining node (" + joiningNodeBlt.id() + ") less than BlT id of cluster (" + clusterBlt.id() + ") but cluster's BaselineHistory doesn't contain branching point hash of joining node BlT (" + joiningNodeBlt.branchingPointHash() + ")." + recommendation;
return new IgniteNodeValidationResult(node.id(), msg);
}
}
return null;
}
use of org.apache.ignite.spi.IgniteNodeValidationResult in project ignite by apache.
the class GridClusterStateProcessor method validateNode.
/**
* {@inheritDoc}
*/
@Override
@Nullable
public IgniteNodeValidationResult validateNode(ClusterNode node) {
if (!isBaselineAutoAdjustEnabled() || baselineAutoAdjustTimeout() != 0)
return null;
Collection<ClusterNode> nodes = ctx.discovery().aliveServerNodes();
// Any node allowed to join if cluster has at least one persist node.
if (nodes.stream().anyMatch(serNode -> CU.isPersistenceEnabled(extractDataStorage(serNode, ctx.marshallerContext().jdkMarshaller(), U.resolveClassLoader(ctx.config())))))
return null;
DataStorageConfiguration crdDsCfg = extractDataStorage(node, ctx.marshallerContext().jdkMarshaller(), U.resolveClassLoader(ctx.config()));
if (!CU.isPersistenceEnabled(crdDsCfg))
return null;
return new IgniteNodeValidationResult(node.id(), "Joining persistence node to in-memory cluster couldn't be allowed " + "due to baseline auto-adjust is enabled and timeout equal to 0");
}
Aggregations