Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 6A1EF200B68 for ; Thu, 4 Aug 2016 11:54:01 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 68B8D160AAE; Thu, 4 Aug 2016 09:54:01 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 42633160A7C for ; Thu, 4 Aug 2016 11:54:00 +0200 (CEST) Received: (qmail 19793 invoked by uid 500); 4 Aug 2016 09:53:59 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 19779 invoked by uid 99); 4 Aug 2016 09:53:59 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Aug 2016 09:53:59 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 47EF9E1170; Thu, 4 Aug 2016 09:53:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: akuznetsov@apache.org To: commits@ignite.apache.org Date: Thu, 04 Aug 2016 09:53:59 -0000 Message-Id: <98dd6379a8eb4cc885e40b5319c53ef5@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/5] ignite git commit: IGNITE-3408 - Provided basic implementation of AddressResolver archived-at: Thu, 04 Aug 2016 09:54:01 -0000 Repository: ignite Updated Branches: refs/heads/ignite-3443 8033f119e -> d8b92b4b4 IGNITE-3408 - Provided basic implementation of AddressResolver Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a90d05b3 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a90d05b3 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a90d05b3 Branch: refs/heads/ignite-3443 Commit: a90d05b30f39da001156fdd4053790f8cd352406 Parents: ae23dab Author: Valentin Kulichenko Authored: Wed Aug 3 22:00:15 2016 -0700 Committer: Valentin Kulichenko Committed: Wed Aug 3 22:00:15 2016 -0700 ---------------------------------------------------------------------- .../configuration/BasicAddressResolver.java | 146 ++++++++++++ .../spi/GridTcpSpiForwardingSelfTest.java | 237 +++++++++++++++++-- 2 files changed, 364 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/a90d05b3/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java b/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java new file mode 100644 index 0000000..d29689f --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java @@ -0,0 +1,146 @@ +/* + * 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.configuration; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.U; + +/** + * Basic implementation of {@link AddressResolver}. + *

+ * Allows to provide simple mapping between different address, which is useful + * different parts of the cluster are located in different subnetworks and port + * forwarding on the router is used for communication between them. Another + * common case is Docker environment which can create a pair of public and private + * address per container. + *

+ * There are two different types of mapping supported by this implementation of + * {@link AddressResolver}. + *

+ * First type maps specific socket addresses (host and port pairs) are mapped to + * each other. This is useful for port forwarding, where multiple nodes will + * typically map to the same external address (router), but with different port + * numbers. Here is the example: + *

+ * <property name="addressResolver">
+ *     <bean class="org.apache.ignite.configuration.BasicAddressResolver">
+ *         <constructor-arg>
+ *             <map>
+ *                 <entry key="10.0.0.1:47100" value="123.123.123.123:1111"/>
+ *                 <entry key="10.0.0.2:47100" value="123.123.123.123:2222"/>
+ *                 <entry key="10.0.0.3:47100" value="123.123.123.123:3333"/>
+ *             </map>
+ *         </constructor-arg>
+ *     </bean>
+ * </property>
+ * 
+ *

+ * Second type maps one host to another. In this case any internal address a node + * is bound to will be mapped to the corresponding external host with the same + * host number. Here is the example: + *

+ * <property name="addressResolver">
+ *     <bean class="org.apache.ignite.configuration.BasicAddressResolver">
+ *         <constructor-arg>
+ *             <map>
+ *                 <entry key="10.0.0.1" value="123.123.123.123"/>
+ *             </map>
+ *         </constructor-arg>
+ *     </bean>
+ * </property>
+ * 
+ * Here any port on {@code 10.0.0.1} will be mapped to the same port number on {@code 123.123.123.123}. + * E.g., {@code 10.0.0.1:47100} will be mapped to {@code 123.123.123.123:47100}, and {@code 10.0.0.1:47500} + * will be mapped to {@code 123.123.123.123:47500}. + *

+ * Two types of mappings described above can be mixed within one address resolver. + */ +public class BasicAddressResolver implements AddressResolver { + /** Address map. */ + private final Map inetAddrMap; + + /** Socket address map. */ + private final Map inetSockAddrMap; + + /** + * Created the address resolver. + * + * @param addrMap Address mappings. + * @throws UnknownHostException If any of the hosts can't be resolved. + */ + public BasicAddressResolver(Map addrMap) throws UnknownHostException { + if (addrMap == null || addrMap.isEmpty()) + throw new IllegalArgumentException("At least one address mapping is required."); + + inetAddrMap = U.newHashMap(addrMap.size()); + inetSockAddrMap = U.newHashMap(addrMap.size()); + + for (Map.Entry e : addrMap.entrySet()) { + String from = e.getKey(); + String to = e.getValue(); + + if (F.isEmpty(from) || F.isEmpty(to)) + throw new IllegalArgumentException("Invalid address mapping: " + e); + + String[] fromArr = from.split(":"); + String[] toArr = to.split(":"); + + assert fromArr.length > 0; + assert toArr.length > 0; + + if (fromArr.length == 1) { + if (toArr.length != 1) + throw new IllegalArgumentException("Invalid address mapping: " + e); + + inetAddrMap.put(InetAddress.getByName(fromArr[0]), InetAddress.getByName(toArr[0])); + } + else if (fromArr.length == 2) { + if (toArr.length != 2) + throw new IllegalArgumentException("Invalid address mapping: " + e); + + inetSockAddrMap.put(new InetSocketAddress(fromArr[0], Integer.parseInt(fromArr[1])), + new InetSocketAddress(toArr[0], Integer.parseInt(toArr[1]))); + } + else + throw new IllegalArgumentException("Invalid address mapping: " + e); + } + } + + /** {@inheritDoc} */ + @Override public Collection getExternalAddresses(InetSocketAddress addr) + throws IgniteCheckedException { + InetSocketAddress inetSockAddr = inetSockAddrMap.get(addr); + + if (inetSockAddr != null) + return Collections.singletonList(inetSockAddr); + + InetAddress inetAddr = inetAddrMap.get(addr.getAddress()); + + if (inetAddr != null) + return Collections.singletonList(new InetSocketAddress(inetAddr, addr.getPort())); + + return Collections.emptyList(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/a90d05b3/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java index 0c3ae12..652e47f 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java @@ -23,10 +23,12 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Callable; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.configuration.AddressResolver; +import org.apache.ignite.configuration.BasicAddressResolver; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.nio.GridCommunicationClient; import org.apache.ignite.internal.util.typedef.F; @@ -35,10 +37,11 @@ import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; /** - * Test for {@link org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi} and {@link org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi}. + * Test for {@link TcpDiscoverySpi} and {@link TcpCommunicationSpi}. */ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest { /** */ @@ -65,30 +68,34 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest { /** */ private static final int commExtPort2 = 20100; + /** */ + private AddressResolver resolver; + + /** */ + private boolean ipFinderUseLocPorts; + /** {@inheritDoc} */ @SuppressWarnings({"IfMayBeConditional", "deprecation"}) @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder(); - ipFinder.setAddresses(Arrays.asList("127.0.0.1:" + extPort1, "127.0.0.1:" + extPort2)); + + if (ipFinderUseLocPorts) + ipFinder.setAddresses(Arrays.asList("127.0.0.1:" + locPort1, "127.0.0.1:" + locPort2)); + else + ipFinder.setAddresses(Arrays.asList("127.0.0.1:" + extPort1, "127.0.0.1:" + extPort2)); TcpDiscoverySpi spi = new TcpDiscoverySpi(); final int locPort; - final int extPort; - final int commExtPort; final int commLocPort; if (getTestGridName(0).equals(gridName)) { locPort = locPort1; - extPort = extPort1; commLocPort = commLocPort1; - commExtPort = commExtPort1; } else if (getTestGridName(1).equals(gridName)) { locPort = locPort2; - extPort = extPort2; commLocPort = commLocPort2; - commExtPort = commExtPort2; } else throw new IllegalArgumentException("Unknown grid name"); @@ -106,6 +113,7 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest { TcpCommunicationSpi commSpi = new TcpCommunicationSpi() { @Override protected GridCommunicationClient createTcpClient(ClusterNode node) throws IgniteCheckedException { Map attrs = new HashMap<>(node.attributes()); + attrs.remove(createSpiAttributeName(ATTR_PORT)); ((TcpDiscoveryNode)node).setAttributes(attrs); @@ -121,16 +129,9 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest { cfg.setCommunicationSpi(commSpi); - final Map> mp = F.asMap( - new InetSocketAddress("127.0.0.1", locPort), F.asList(new InetSocketAddress("127.0.0.1", extPort)), - new InetSocketAddress("127.0.0.1", commLocPort), F.asList(new InetSocketAddress("127.0.0.1", commExtPort)) - ); + assert resolver != null; - cfg.setAddressResolver(new AddressResolver() { - @Override public Collection getExternalAddresses(InetSocketAddress addr) { - return mp.get(addr); - } - }); + cfg.setAddressResolver(resolver); return cfg; } @@ -138,8 +139,206 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest { /** * @throws Exception If any error occurs. */ + public void testCustomResolver() throws Exception { + final Map> map = new HashMap<>(); + + map.put(new InetSocketAddress("127.0.0.1", locPort1), F.asList(new InetSocketAddress("127.0.0.1", extPort1))); + map.put(new InetSocketAddress("127.0.0.1", commLocPort1), F.asList(new InetSocketAddress("127.0.0.1", commExtPort1))); + map.put(new InetSocketAddress("127.0.0.1", locPort2), F.asList(new InetSocketAddress("127.0.0.1", extPort2))); + map.put(new InetSocketAddress("127.0.0.1", commLocPort2), F.asList(new InetSocketAddress("127.0.0.1", commExtPort2))); + + resolver = new AddressResolver() { + @Override public Collection getExternalAddresses(InetSocketAddress addr) { + return map.get(addr); + } + }; + + doTestForward(); + } + + /** + * @throws Exception If failed. + */ + public void testBasicResolverMapPorts() throws Exception { + Map map = new HashMap<>(); + + map.put("127.0.0.1:" + locPort1, "127.0.0.1:" + extPort1); + map.put("127.0.0.1:" + commLocPort1, "127.0.0.1:" + commExtPort1); + map.put("127.0.0.1:" + locPort2, "127.0.0.1:" + extPort2); + map.put("127.0.0.1:" + commLocPort2, "127.0.0.1:" + commExtPort2); + + resolver = new BasicAddressResolver(map); + + doTestForward(); + } + + /** + * @throws Exception If failed. + */ + public void testBasicResolverMapAddress() throws Exception { + Map map = new HashMap<>(); + + map.put("127.0.0.1", "127.0.0.1"); + + resolver = new BasicAddressResolver(map); + + ipFinderUseLocPorts = true; + + doTestForward(); + } + + /** + * @throws Exception If failed. + */ + public void testBasicResolverErrors() throws Exception { + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + return new BasicAddressResolver(null); + } + }, + IllegalArgumentException.class, + "At least one address mapping is required." + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + return new BasicAddressResolver(new HashMap()); + } + }, + IllegalArgumentException.class, + "At least one address mapping is required." + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("from", null); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: from=null" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("from", ""); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: from=" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put(null, "to"); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: null=to" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("", "to"); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: =to" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("from", "to:1111"); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: from=to:1111" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("from:1111", "to"); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: from:1111=to" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("from:1111:2222", "to:1111"); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: from:1111:2222=to:1111" + ); + + GridTestUtils.assertThrows( + log, + new Callable() { + @Override public Object call() throws Exception { + Map map = new HashMap<>(); + + map.put("from:1111", "to:1111:2222"); + + return new BasicAddressResolver(map); + } + }, + IllegalArgumentException.class, + "Invalid address mapping: from:1111=to:1111:2222" + ); + } + + /** + * @throws Exception If failed. + */ @SuppressWarnings("UnusedDeclaration") - public void testForward() throws Exception { + private void doTestForward() throws Exception { InetAddress locHost = InetAddress.getByName("127.0.0.1"); try ( @@ -163,4 +362,4 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest { assertEquals(F.asList(13, 13), t); } } -} \ No newline at end of file +}