Search in sources :

Example 11 with IgniteNodeValidationResult

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;
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) DetachedClusterNode(org.apache.ignite.internal.cluster.DetachedClusterNode) IgniteNodeValidationResult(org.apache.ignite.spi.IgniteNodeValidationResult) RendezvousAffinityFunction(org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction) CacheConfiguration(org.apache.ignite.configuration.CacheConfiguration) Nullable(org.jetbrains.annotations.Nullable)

Example 12 with IgniteNodeValidationResult

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();
    }
}
Also used : IgniteNodeValidationResult(org.apache.ignite.spi.IgniteNodeValidationResult) Nullable(org.jetbrains.annotations.Nullable)

Example 13 with IgniteNodeValidationResult

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;
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) IgniteNodeValidationResult(org.apache.ignite.spi.IgniteNodeValidationResult) BinaryObject(org.apache.ignite.binary.BinaryObject) CacheObject(org.apache.ignite.internal.processors.cache.CacheObject) IncompleteCacheObject(org.apache.ignite.internal.processors.cache.IncompleteCacheObject) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject)

Example 14 with IgniteNodeValidationResult

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;
}
Also used : IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteNodeValidationResult(org.apache.ignite.spi.IgniteNodeValidationResult) Nullable(org.jetbrains.annotations.Nullable)

Example 15 with IgniteNodeValidationResult

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");
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) DataStorageConfiguration(org.apache.ignite.configuration.DataStorageConfiguration) IgniteNodeValidationResult(org.apache.ignite.spi.IgniteNodeValidationResult) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

IgniteNodeValidationResult (org.apache.ignite.spi.IgniteNodeValidationResult)15 Nullable (org.jetbrains.annotations.Nullable)11 ClusterNode (org.apache.ignite.cluster.ClusterNode)7 Map (java.util.Map)3 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)3 HashMap (java.util.HashMap)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 ConcurrentMap (java.util.concurrent.ConcurrentMap)2 IgniteException (org.apache.ignite.IgniteException)2 BinaryObject (org.apache.ignite.binary.BinaryObject)2 RendezvousAffinityFunction (org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction)2 CacheConfiguration (org.apache.ignite.configuration.CacheConfiguration)2 Event (org.apache.ignite.events.Event)2 NodeValidationFailedEvent (org.apache.ignite.events.NodeValidationFailedEvent)2 SecurityException (org.apache.ignite.plugin.security.SecurityException)2 DiscoveryDataBag (org.apache.ignite.spi.discovery.DiscoveryDataBag)2 Serializable (java.io.Serializable)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 IdentityHashMap (java.util.IdentityHashMap)1