This is an automated email from the ASF dual-hosted git repository.

sergeychugunov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 406c32244e8 IGNITE-26211 New node property to distinguish different 
DCs (#12303)
406c32244e8 is described below

commit 406c32244e83a0e75c495e6c2ed674b79e742644
Author: Sergey Chugunov <[email protected]>
AuthorDate: Wed Oct 15 16:55:01 2025 +0400

    IGNITE-26211 New node property to distinguish different DCs (#12303)
---
 .../jol/GridAffinityAssignmentJolBenchmark.java    |   1 +
 .../org/apache/ignite/IgniteSystemProperties.java  |   6 +
 .../org/apache/ignite/cluster/ClusterNode.java     |  20 +++
 .../ignite/spi/discovery/tcp/ServerImpl.java       |  43 +++++
 .../ignite/spi/discovery/tcp/TcpDiscoverySpi.java  |   3 +
 .../discovery/tcp/internal/TcpDiscoveryNode.java   |  16 +-
 .../affinity/GridAffinityAssignmentV2Test.java     |   1 +
 .../datacenter/MultiDataCenterDeploymentTest.java  | 192 +++++++++++++++++++++
 .../IgniteSpiDiscoverySelfTestSuite.java           |   5 +-
 .../spi/discovery/zk/ZookeeperDiscoverySpi.java    |  10 +-
 .../zk/internal/ZookeeperClusterNode.java          |  16 ++
 11 files changed, 309 insertions(+), 4 deletions(-)

diff --git 
a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jol/GridAffinityAssignmentJolBenchmark.java
 
b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jol/GridAffinityAssignmentJolBenchmark.java
index df474379073..d75f590be08 100644
--- 
a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jol/GridAffinityAssignmentJolBenchmark.java
+++ 
b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jol/GridAffinityAssignmentJolBenchmark.java
@@ -328,6 +328,7 @@ public class GridAffinityAssignmentJolBenchmark {
     private static ClusterNode node(int idx) {
         TcpDiscoveryNode node = new TcpDiscoveryNode(
             UUID.randomUUID(),
+            null,
             Collections.singletonList("127.0.0.1"),
             Collections.singletonList("127.0.0.1"),
             0,
diff --git 
a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java 
b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index b8be84ddb73..e0d75bafded 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -753,6 +753,12 @@ public final class IgniteSystemProperties extends 
IgniteCommonsSystemProperties
         defaults = "" + DFLT_DISCOVERY_HISTORY_SIZE)
     public static final String IGNITE_DISCOVERY_HISTORY_SIZE = 
"IGNITE_DISCOVERY_HISTORY_SIZE";
 
+    /** Human-readable ID of a data center where the node is running. */
+    @IgniteExperimental
+    @SystemProperty(value = "Data Center ID where local node is running. Not 
required for a single Data Center deployments",
+        type = String.class)
+    public static final String IGNITE_DATA_CENTER_ID = "IGNITE_DATA_CENTER_ID";
+
     /** Maximum number of discovery message history used to support client 
reconnect. */
     @SystemProperty(value = "Maximum number of discovery message history used 
to support client reconnect",
         type = Integer.class, defaults = "" + 
DFLT_DISCOVERY_CLIENT_RECONNECT_HISTORY_SIZE)
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cluster/ClusterNode.java 
b/modules/core/src/main/java/org/apache/ignite/cluster/ClusterNode.java
index f9f081c6f24..ff02b9704a0 100644
--- a/modules/core/src/main/java/org/apache/ignite/cluster/ClusterNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/cluster/ClusterNode.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.lang.IgniteExperimental;
 import org.apache.ignite.lang.IgniteProductVersion;
 import org.jetbrains.annotations.Nullable;
 
@@ -166,6 +167,25 @@ public interface ClusterNode extends BaselineNode {
      */
     @Override public Map<String, Object> attributes();
 
+    /**
+     * Gets the Data Center ID where the node is located. In a cluster 
deployed in only one data center, this method
+     * returns {@code null}.
+     * <p>
+     * The data center ID is resolved at node startup and is used for 
optimizing operations like:
+     * <ul>
+     *     <li>Minimizing cross-data center communication;</li>
+     *     <li>Improving fault tolerance and redundancy strategies;</li>
+     *     <li>Supporting affinity-based task execution within the same data 
center;</li>
+     *     <li>Providing input to discovery SPIs for topology-aware node 
grouping.</li>
+     * </ul>
+     *
+     * @return The Data Center ID of the node, or {@code null} if the cluster 
is deployed in a single DC.
+     */
+    @IgniteExperimental
+    @Nullable public default String dataCenterId() {
+        return null;
+    }
+
     /**
      * Gets collection of addresses this node is known by.
      * <p>
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
index e469d8572f3..7905a5a8ac0 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
@@ -4730,6 +4730,49 @@ class ServerImpl extends TcpDiscoveryImpl {
                     return;
                 }
 
+                if (!node.isClient()) {
+                    String locNodeDcId = locNode.dataCenterId();
+                    String rmtNodeDcId = node.dataCenterId();
+
+                    if (locNodeDcId == null && rmtNodeDcId != null
+                        || locNodeDcId != null && rmtNodeDcId == null) {
+                        utilityPool.execute(
+                            new Runnable() {
+                                @Override public void run() {
+                                    String locNodeHasDcId = "Data Center ID is 
specified for local node but not for remote node";
+                                    String rmtNodeHasDcId = "Data Center ID is 
specified for remote node but not for local node";
+
+                                    String errMsg = locNodeDcId == null ? 
locNodeHasDcId : rmtNodeHasDcId +
+                                        "[locNodeDcId=" + locNodeDcId +
+                                        ", rmtNodeDcId=" + rmtNodeDcId +
+                                        ", locNodeAddrs=" + 
U.addressesAsString(locNode) +
+                                        ", rmtNodeAddrs=" + 
U.addressesAsString(node) +
+                                        ", locNodeId=" + locNode.id() + ", 
rmtNodeId=" + msg.creatorNodeId() + ']';
+
+                                    String sndMsg = rmtNodeDcId == null ? 
rmtNodeHasDcId : locNodeHasDcId +
+                                        "[locNodeDcId=" + rmtNodeDcId +
+                                        ", rmtNodeDcId=" + locNodeDcId +
+                                        ", locNodeAddrs=" + 
U.addressesAsString(node) + ", locPort=" + node.discoveryPort() +
+                                        ", rmtNodeAddr=" + 
U.addressesAsString(locNode) + ", locNodeId=" + node.id() +
+                                        ", rmtNodeId=" + locNode.id() + ']';
+
+                                    nodeCheckError(
+                                        node,
+                                        errMsg,
+                                        sndMsg);
+                                }
+                            });
+
+                        // Ignore join request.
+                        msg.spanContainer().span()
+                            .addLog(() -> "Ignored")
+                            .setStatus(SpanStatus.ABORTED)
+                            .end();
+
+                        return;
+                    }
+                }
+
                 // Handle join.
                 node.internalOrder(ring.nextNodeOrder());
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
index 6df10d88a0f..f96a86a5860 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
@@ -111,7 +111,9 @@ import 
org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryEnsureDelivery;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
+import static org.apache.ignite.IgniteCommonsSystemProperties.getString;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_CONSISTENT_ID_BY_HOST_WITHOUT_PORT;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_CENTER_ID;
 import static org.apache.ignite.IgniteSystemProperties.getBoolean;
 import static org.apache.ignite.failure.FailureType.CRITICAL_ERROR;
 import static 
org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.DISCO_METRICS;
@@ -1168,6 +1170,7 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter 
implements IgniteDiscovery
 
         locNode = new TcpDiscoveryNode(
             ignite.configuration().getNodeId(),
+            getString(IGNITE_DATA_CENTER_ID),
             addrs.get1(),
             addrs.get2(),
             srvPort,
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
index c76e8a28adb..785ef9ac4ad 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
@@ -73,6 +73,9 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
     @GridToStringExclude
     private Map<String, Object> attrs;
 
+    /** Data center ID of the node. */
+    private String dcId;
+
     /** Internal discovery addresses as strings. */
     @GridToStringInclude
     private Collection<String> addrs;
@@ -155,6 +158,7 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
      * Constructor.
      *
      * @param id Node Id.
+     * @param dcId ID of a data center where this node is started ({@code 
null} if there is only one data center).
      * @param addrs Addresses.
      * @param hostNames Host names.
      * @param discPort Port.
@@ -163,6 +167,7 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
      * @param consistentId Node consistent ID.
      */
     public TcpDiscoveryNode(UUID id,
+        String dcId,
         Collection<String> addrs,
         Collection<String> hostNames,
         int discPort,
@@ -175,6 +180,7 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
         assert ver != null;
 
         this.id = id;
+        this.dcId = dcId;
 
         List<String> sortedAddrs = new ArrayList<>(addrs);
 
@@ -353,6 +359,11 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
         this.ver = ver;
     }
 
+    /** {@inheritDoc} */
+    @Override public @Nullable String dataCenterId() {
+        return dcId;
+    }
+
     /** {@inheritDoc} */
     @Override public Collection<String> addresses() {
         return addrs;
@@ -529,7 +540,7 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
      */
     public TcpDiscoveryNode clientReconnectNode(Map<String, Object> nodeAttrs) 
{
         TcpDiscoveryNode node = new TcpDiscoveryNode(
-            id, addrs, hostNames, discPort, metricsProvider, ver, null
+            id, dcId, addrs, hostNames, discPort, metricsProvider, ver, null
         );
 
         node.attrs = Collections.unmodifiableMap(new HashMap<>(nodeAttrs));
@@ -579,6 +590,7 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
         out.writeLong(intOrder);
         out.writeObject(ver);
         U.writeUuid(out, clientRouterNodeId);
+        out.writeObject(dcId);
     }
 
     /** {@inheritDoc} */
@@ -615,6 +627,8 @@ public class TcpDiscoveryNode extends 
GridMetadataAwareAdapter implements Ignite
             consistentId = consistentIdAttr != null ? consistentIdAttr : id;
         else
             consistentId = consistentIdAttr != null ? consistentIdAttr : 
U.consistentId(addrs, discPort);
+
+        dcId = (String)in.readObject();
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
index 5d8e966851c..7d3caae9f63 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
@@ -237,6 +237,7 @@ public class GridAffinityAssignmentV2Test {
     protected TcpDiscoveryNode node(DiscoveryMetricsProvider metrics, 
IgniteProductVersion v, String consistentId) {
         TcpDiscoveryNode node = new TcpDiscoveryNode(
             UUID.randomUUID(),
+            null,
             Collections.singletonList("127.0.0.1"),
             Collections.singletonList("127.0.0.1"),
             0,
diff --git 
a/modules/core/src/test/java/org/apache/ignite/spi/discovery/datacenter/MultiDataCenterDeploymentTest.java
 
b/modules/core/src/test/java/org/apache/ignite/spi/discovery/datacenter/MultiDataCenterDeploymentTest.java
new file mode 100644
index 00000000000..cc79f5bba9b
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/spi/discovery/datacenter/MultiDataCenterDeploymentTest.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.spi.discovery.datacenter;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ * Test scenarios for Data Center ID configuration variations.
+ */
+public class MultiDataCenterDeploymentTest extends GridCommonAbstractTest {
+    /** */
+    private static final String DC_ID_0 = "DC0";
+
+    /** */
+    private static final String DC_ID_1 = "DC1";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        // To speed up tests involving nodes shutting down.
+        TcpDiscoverySpi discoSpi = (TcpDiscoverySpi)cfg.getDiscoverySpi();
+        discoSpi.setNetworkTimeout(500);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        stopAllGrids();
+    }
+
+    /**
+     * Verifies that ClusterNode picks up Data Center ID from the 
corresponding system property.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    @WithSystemProperty(key = IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
value = DC_ID_0)
+    public void testAttributeSetLocallyFromSystemProperty() throws Exception {
+        IgniteEx testGrid = startGrid();
+
+        String dcId = testGrid.localNode().dataCenterId();
+
+        assertNotNull("Data Center ID of the node should not be null", dcId);
+
+        assertEquals(DC_ID_0, dcId);
+    }
+
+    /**
+     * Verifies that cluster with configured Data Center ID rejects server 
nodes without one and vise versa.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testMixedDcConfigurationIsProhibited() throws Exception {
+        System.setProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
DC_ID_0);
+
+        startGrid(0);
+
+        System.clearProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID);
+
+        try {
+            startGrid(1);
+
+            assertFalse("Expected exception hasn't been thrown", true);
+        }
+        catch (IgniteCheckedException e) {
+            Throwable cause = e.getCause();
+            assertNotNull(cause);
+            assertTrue(cause instanceof IgniteCheckedException);
+
+            cause = cause.getCause();
+            assertNotNull(cause);
+            assertTrue(cause instanceof IgniteSpiException);
+
+            String errMsg = cause.getMessage();
+            assertNotNull(errMsg);
+            assertTrue(errMsg.contains("Data Center ID is specified for remote 
node but not for local node"));
+        }
+
+        stopAllGrids();
+
+        startGrid(0);
+
+        System.setProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
DC_ID_0);
+
+        try {
+            startGrid(1);
+
+            assertFalse("Expected exception hasn't been thrown", true);
+        }
+        catch (IgniteCheckedException e) {
+            Throwable cause = e.getCause();
+            assertNotNull(cause);
+            assertTrue(cause instanceof IgniteCheckedException);
+
+            cause = cause.getCause();
+            assertNotNull(cause);
+            assertTrue(cause instanceof IgniteSpiException);
+
+            String errMsg = cause.getMessage();
+            assertNotNull(errMsg);
+            assertTrue(errMsg.contains("Data Center ID is specified for local 
node but not for remote node"));
+        }
+    }
+
+    /**
+     *  Verifies that servers from different Data Centers can form a single 
cluster.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testServersFromDifferentDcsFormACluster() throws Exception {
+        System.setProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
DC_ID_0);
+        IgniteEx srv0 = startGrid(0);
+
+        System.setProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
DC_ID_1);
+        IgniteEx srv1 = startGrid(1);
+
+        waitForTopology(2);
+
+        assertEquals(srv0.localNode().dataCenterId(), DC_ID_0);
+        assertEquals(srv1.localNode().dataCenterId(), DC_ID_1);
+    }
+
+    /**
+     * Verifies that client nodes with or without Data Center ID specified are 
allowed to join a cluster with a configured Data Center ID.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testClientWithoutDcIdIsAllowedToJoin() throws Exception {
+        System.setProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
DC_ID_0);
+        IgniteEx srv0 = startGrid(0);
+
+        System.setProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID, 
DC_ID_1);
+
+        IgniteEx client0 = null;
+
+        try {
+            client0 = startClientGrid(1);
+        }
+        catch (IgniteCheckedException e) {
+            assertFalse("Unexpected exception was thrown: " + e, true);
+        }
+
+        System.clearProperty(IgniteSystemProperties.IGNITE_DATA_CENTER_ID);
+
+        IgniteEx client1 = null;
+
+        try {
+            client1 = startClientGrid(2);
+        }
+        catch (IgniteCheckedException e) {
+            assertFalse("Unexpected exception was thrown: " + e, true);
+        }
+
+        assertEquals(srv0.localNode().dataCenterId(), DC_ID_0);
+
+        assertNotNull(client0);
+        assertEquals(client0.localNode().dataCenterId(), DC_ID_1);
+
+        assertNotNull(client1);
+        assertNull(client1.localNode().dataCenterId(), null);
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java
 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java
index f0b7fbf5ce8..a2f818b1111 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java
@@ -26,6 +26,7 @@ import 
org.apache.ignite.spi.discovery.FilterDataForClientNodeDiscoveryTest;
 import org.apache.ignite.spi.discovery.IgniteClientReconnectEventHandlingTest;
 import org.apache.ignite.spi.discovery.IgniteDiscoveryCacheReuseSelfTest;
 import org.apache.ignite.spi.discovery.LongClientConnectToClusterTest;
+import 
org.apache.ignite.spi.discovery.datacenter.MultiDataCenterDeploymentTest;
 import org.apache.ignite.spi.discovery.tcp.DiscoveryClientSocketTest;
 import org.apache.ignite.spi.discovery.tcp.DiscoveryUnmarshalVulnerabilityTest;
 import org.apache.ignite.spi.discovery.tcp.IgniteClientConnectSslTest;
@@ -181,7 +182,9 @@ import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_OVERRIDE_MCAST_GRP
 
     TcpDiscoveryIpFinderFailureTest.class,
 
-    TcpDiscoveryDeadNodeAddressResolvingTest.class
+    TcpDiscoveryDeadNodeAddressResolvingTest.class,
+
+    MultiDataCenterDeploymentTest.class
 })
 public class IgniteSpiDiscoverySelfTestSuite {
     /** */
diff --git 
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java
 
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java
index be157c62fce..2de06e9b025 100644
--- 
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java
+++ 
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi;
 import org.apache.ignite.internal.processors.metric.MetricRegistryImpl;
@@ -61,7 +62,9 @@ import 
org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryImpl;
 import 
org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryStatistics;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.IgniteCommonsSystemProperties.getString;
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_CONSISTENT_ID_BY_HOST_WITHOUT_PORT;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_CENTER_ID;
 import static org.apache.ignite.IgniteSystemProperties.getBoolean;
 import static 
org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.DISCO_METRICS;
 
@@ -520,15 +523,18 @@ public class ZookeeperDiscoverySpi extends 
IgniteSpiAdapter implements IgniteDis
 
         initAddresses();
 
+        IgniteConfiguration cfg = ignite.configuration();
+
         ZookeeperClusterNode locNode = new ZookeeperClusterNode(
-            ignite.configuration().getNodeId(),
+            cfg.getNodeId(),
+            getString(IGNITE_DATA_CENTER_ID),
             addrs.get1(),
             addrs.get2(),
             locNodeVer,
             locNodeAttrs,
             consistentId(),
             sesTimeout,
-            ignite.configuration().isClientMode(),
+            cfg.isClientMode(),
             metricsProvider);
 
         locNode.local(true);
diff --git 
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClusterNode.java
 
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClusterNode.java
index a608ba66424..ade81619947 100644
--- 
a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClusterNode.java
+++ 
b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClusterNode.java
@@ -71,6 +71,9 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
     /** Node attributes. */
     private Map<String, Object> attrs;
 
+    /** Data Center ID. */
+    private String dcId;
+
     /** Internal discovery addresses as strings. */
     private Collection<String> addrs;
 
@@ -103,6 +106,7 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
 
     /**
      * @param id Node ID.
+     * @param dcId Data Center ID.
      * @param addrs Node addresses.
      * @param hostNames Node host names.
      * @param ver Node version.
@@ -114,6 +118,7 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
      */
     public ZookeeperClusterNode(
         UUID id,
+        String dcId,
         Collection<String> addrs,
         Collection<String> hostNames,
         IgniteProductVersion ver,
@@ -128,6 +133,7 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
 
         this.id = id;
         this.ver = ver;
+        this.dcId = dcId;
         this.attrs = Collections.unmodifiableMap(attrs);
         this.addrs = addrs;
         this.hostNames = hostNames;
@@ -233,6 +239,11 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
         return F.view(attrs, new SecurityCredentialsAttrFilterPredicate());
     }
 
+    /** {{@inheritDoc} */
+    @Override public @Nullable String dataCenterId() {
+        return dcId;
+    }
+
     /** {@inheritDoc} */
     @Override public Collection<String> addresses() {
         return addrs;
@@ -329,6 +340,8 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
             mtr = ClusterMetricsSnapshot.serialize(metrics);
 
         U.writeByteArray(out, mtr);
+
+        out.writeObject(dcId);
     }
 
     /** {@inheritDoc} */
@@ -349,6 +362,8 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
 
         if (mtr != null)
             metrics = ClusterMetricsSnapshot.deserialize(mtr, 0);
+
+        dcId = (String)in.readObject();
     }
 
     /** {@inheritDoc} */
@@ -380,6 +395,7 @@ public class ZookeeperClusterNode implements 
IgniteClusterNode, Externalizable,
     /** {@inheritDoc} */
     @Override public String toString() {
         return "ZookeeperClusterNode [id=" + id +
+            ", dataCenterId=" + dcId +
             ", addrs=" + addrs +
             ", order=" + order +
             ", loc=" + loc +

Reply via email to