From 464434bcbce8427e0c144eba284c6368adaa3cab Mon Sep 17 00:00:00 2001 From: Laurent Cohen Date: Tue, 21 May 2019 07:40:50 +0200 Subject: [PATCH] issue JPPF-589 fixing management host resolution --- JPPF/bin/docker/driver/jppf-driver.properties | 2 +- JPPF/bin/docker/node/jppf-node.properties | 8 ++-- JPPF/bin/docker/node/log4j-node.properties | 3 +- .../org/jppf/comm/discovery/IPFilter.java | 11 ++++- common/src/java/org/jppf/nio/NioHelper.java | 2 +- common/src/java/org/jppf/nio/NioServer.java | 10 ++--- .../jppf/nio/acceptor/AcceptorNioServer.java | 4 +- .../src/java/org/jppf/utils/NetworkUtils.java | 45 +++++++++++++++++-- .../java/org/jppf/server/node/JPPFNode.java | 14 +++++- .../async/AsyncNodeMessageHandler.java | 8 +++- 10 files changed, 85 insertions(+), 22 deletions(-) diff --git a/JPPF/bin/docker/driver/jppf-driver.properties b/JPPF/bin/docker/driver/jppf-driver.properties index 7fbb5175ea..678d173d7f 100644 --- a/JPPF/bin/docker/driver/jppf-driver.properties +++ b/JPPF/bin/docker/driver/jppf-driver.properties @@ -22,7 +22,7 @@ # to disable, specify a negative port number # #------------------------------------------------------------------------------# -jppf.resolve.node.host.from.sysinfo = true +#jppf.resolve.node.host.from.sysinfo = true jppf.server.port = 11111 #------------------------------------------------------------------------------# diff --git a/JPPF/bin/docker/node/jppf-node.properties b/JPPF/bin/docker/node/jppf-node.properties index dd4cf86fd8..edc7ddc842 100644 --- a/JPPF/bin/docker/node/jppf-node.properties +++ b/JPPF/bin/docker/node/jppf-node.properties @@ -307,7 +307,7 @@ jppf.length.buffer.pool.size = 100 # Network settings # #------------------------------------------------------------------------------# -jppf.bind.include.ipv4 = 172.16.238.0/24 -#jppf.bind.exclude.ipv4 = 192.168.1.128-; 192.168.1.0/25 -#jppf.bind.include.ipv6 = 1080:0:0:0:8:800:200C-20FF:-; ::1/80 -jppf.bind.exclude.ipv6 = - +jppf.management.host.include.ipv4 = 172.16.238.0/24 +#jppf.management.host.exclude.ipv4 = 192.168.1.128-; 192.168.1.0/25 +#jppf.management.host.include.ipv6 = 1080:0:0:0:8:800:200C-20FF:-; ::1/80 +jppf.management.host.exclude.ipv6 = - diff --git a/JPPF/bin/docker/node/log4j-node.properties b/JPPF/bin/docker/node/log4j-node.properties index 47fd863b91..b38a2871e1 100644 --- a/JPPF/bin/docker/node/log4j-node.properties +++ b/JPPF/bin/docker/node/log4j-node.properties @@ -67,7 +67,8 @@ log4j.logger.org.jppf.jmxremote.nio.JMXNioServer=INFO #log4j.logger.org.jppf.nio=DEBUG log4j.logger.org.jppf.nio.PlainNioObject=INFO #log4j.logger.org.jppf.nio.SelectorSynchronizerLock=TRACE -#log4j.logger.org.jppf.nio.StateTransitionTask=DEBUG +#log4j.logger.org.jppf.nio.acceptor=DEBUG +log4j.logger.org.jppf.nio.acceptor.AcceptorNioServer=DEBUG log4j.logger.org.jppf.node=DEBUG #log4j.logger.org.jppf.node.idle=DEBUG #log4j.logger.org.jppf.node.NodeRunner=DEBUG diff --git a/common/src/java/org/jppf/comm/discovery/IPFilter.java b/common/src/java/org/jppf/comm/discovery/IPFilter.java index e314d6743a..2e4dd923a2 100644 --- a/common/src/java/org/jppf/comm/discovery/IPFilter.java +++ b/common/src/java/org/jppf/comm/discovery/IPFilter.java @@ -42,11 +42,11 @@ public class IPFilter { /** * List of accepted IP address patterns. */ - private List includePatterns = new ArrayList<>(); + private final List includePatterns = new ArrayList<>(); /** * List of rejected IP address patterns. */ - private List excludePatterns = new ArrayList<>(); + private final List excludePatterns = new ArrayList<>(); /** * The loaded configuration. */ @@ -154,4 +154,11 @@ private static boolean matches(final int[] ipComps, final Listtrue if the server sockets should be initialized with SSL enabled, false otherwise. + * @param ssl {@code true} if the server sockets should be initialized with SSL enabled, {@code false} otherwise. * @throws Exception if any error occurs while initializing the server sockets. */ private void init(final int[] portsToInit, final boolean ssl) throws Exception { @@ -173,7 +173,7 @@ private void init(final int[] portsToInit, final boolean ssl) throws Exception { /** * Initialize the underlying server sockets for the spcified array of ports. * @param portToInit the array of ports to initiialize. - * @param ssl true if the server sockets should be initialized with SSL enabled, false otherwise. + * @param ssl {@code true} if the server sockets should be initialized with SSL enabled, {@code false} otherwise. * @param env optional map of parameters to associate with the server socket channel. * @param retryOnException whether to retry if an exception occurs when binding the server. * @throws Exception if any error occurs while initializing the server sockets. @@ -251,11 +251,11 @@ protected void doAccept(final SelectionKey key) { /** * Register an incoming connection with this server's selector. * The channel is registered with an empty set of initial interest operations, - * which means a call to the corresponding {@link SelectionKey}'s interestOps() method will return 0. + * which means a call to the corresponding {@link SelectionKey}'s {@code interestOps()} method will return 0. * @param serverSocketChannel the server socket channel accepting the connection. * @param channel the socket channel representing the connection. * @param sslHandler an sslEngine eventually passed on from a different server. - * @param ssl specifies whether an SSLHandler should be initialized for the channel. + * @param ssl specifies whether an {@code SSLHandler} should be initialized for the channel. * @param peer specifiies whether the channel is for a peer driver. * @param params optional parameters. * @throws Exception if any error occurs. @@ -266,7 +266,7 @@ public abstract void accept(final ServerSocketChannel serverSocketChannel, final /** * Define a context for a newly created channel. * @param params optional parameters. - * @return an NioContext instance. + * @return an {@code NioContext} instance. */ public abstract NioContext createNioContext(final Object...params); diff --git a/common/src/java/org/jppf/nio/acceptor/AcceptorNioServer.java b/common/src/java/org/jppf/nio/acceptor/AcceptorNioServer.java index 606b9cba7a..772a792e07 100644 --- a/common/src/java/org/jppf/nio/acceptor/AcceptorNioServer.java +++ b/common/src/java/org/jppf/nio/acceptor/AcceptorNioServer.java @@ -194,7 +194,9 @@ public void addServer(final int portToInit, final boolean ssl, final Map server.bind(addr)); if (debugEnabled) log.debug("server socket channel bound to address {}", addr); diff --git a/common/src/java/org/jppf/utils/NetworkUtils.java b/common/src/java/org/jppf/utils/NetworkUtils.java index 592cb340f5..a85decc966 100644 --- a/common/src/java/org/jppf/utils/NetworkUtils.java +++ b/common/src/java/org/jppf/utils/NetworkUtils.java @@ -21,6 +21,7 @@ import java.net.*; import java.util.*; +import org.jppf.comm.discovery.IPFilter; import org.jppf.utils.configuration.JPPFProperties; import org.slf4j.*; @@ -47,6 +48,10 @@ public final class NetworkUtils { * Constant for empty array of host/ip pairs. */ private static final HostIP[] NO_ADDRESS = new HostIP[0]; + /** + * The list on non-local IP addresses fgor the current host. + */ + private static final List nonLocalIPAddresses = new ArrayList<>(); /** * Instantiation opf this class is not permitted. @@ -147,10 +152,13 @@ private static List getIPAddresses(final InetAddressFilter filter) * @return a List of InetAddress instances, may be empty but never null. */ public static List getNonLocalIPAddresses() { - final List addresses = new ArrayList<>(); - addresses.addAll(getNonLocalIPV4Addresses()); - addresses.addAll(getNonLocalIPV6Addresses()); - return addresses; + synchronized(nonLocalIPAddresses) { + if (nonLocalIPAddresses.isEmpty()) { + nonLocalIPAddresses.addAll(getNonLocalIPV4Addresses()); + nonLocalIPAddresses.addAll(getNonLocalIPV6Addresses()); + } + return new ArrayList<>(nonLocalIPAddresses); + } } /** @@ -322,4 +330,33 @@ public static HostIP[] parseAddresses(final String addresses) { } return result; } + + /** + * @param propertyPrefix prefix for the properties deifining include and exclude IP address patterns. + * @return an {@link InetAddress} to bind to, or {@code null} to bind to all interfaces. + */ + public static InetAddress getInetAddress(final String propertyPrefix) { + return getInetAddress(JPPFConfiguration.getProperties(), propertyPrefix); + } + + /** + * @param config the config to use. + * @param propertyPrefix prefix for the properties deifining include and exclude IP address patterns. + * @return an {@link InetAddress} to bind to, or {@code null} to bind to all interfaces. + */ + public static InetAddress getInetAddress(final TypedProperties config, final String propertyPrefix) { + final IPFilter filter = new IPFilter(config, propertyPrefix); + if (!filter.hasPattern()) return null; + final List addresses = NetworkUtils.getNonLocalIPAddresses(); + if ((addresses != null) && !addresses.isEmpty()) { + final List accepted = new ArrayList<>(); + for (final InetAddress addr: addresses) { + if (filter.isAddressAccepted(addr)) accepted.add(addr); + } + if (debugEnabled) log.debug("accepted addresses for '{}' prefix: {}", propertyPrefix, accepted); + if (accepted.size() == addresses.size()) return null; + return accepted.isEmpty() ? null : accepted.get(0); + } + return null; + } } diff --git a/node/src/java/org/jppf/server/node/JPPFNode.java b/node/src/java/org/jppf/server/node/JPPFNode.java index f94b120c6a..440705e749 100644 --- a/node/src/java/org/jppf/server/node/JPPFNode.java +++ b/node/src/java/org/jppf/server/node/JPPFNode.java @@ -18,6 +18,7 @@ package org.jppf.server.node; import java.io.IOException; +import java.net.InetAddress; import java.util.*; import org.jppf.*; @@ -243,6 +244,8 @@ private void checkInitialBundle(final TaskBundle bundle) throws Exception { } } else { if (!throttlingHandler.check()) bundle.setParameter(BundleParameter.NODE_ACCEPTS_NEW_JOBS, false); + final String ip = getManagementAddress(); + if (ip != null) bundle.setParameter(BundleParameter.NODE_MANAGEMENT_HOST_PARAM, ip); throttlingHandler.start(); } if (isJmxEnabled()) setupBundleParameters(bundle); @@ -366,7 +369,7 @@ private boolean checkStopped() { if (isStopped()) throw new IllegalStateException("this node is shutting down"); return false; } - + /** * @return the slave node manager. * @exclude @@ -421,4 +424,13 @@ public JobWriter getJobWriter() { public List getHandshakeUuidPath() { return handshakeUuidPath; } + + + /** + * @return an {@link InetAddress} to bind to, or {@code null} to bind to all interfaces. + */ + private String getManagementAddress() { + final InetAddress addr = NetworkUtils.getInetAddress(getConfiguration(), "jppf.management.host."); + return (addr != null) ? addr.getHostAddress() : null; + } } diff --git a/server/src/java/org/jppf/server/nio/nodeserver/async/AsyncNodeMessageHandler.java b/server/src/java/org/jppf/server/nio/nodeserver/async/AsyncNodeMessageHandler.java index 43b3d041ab..fff9d8264f 100644 --- a/server/src/java/org/jppf/server/nio/nodeserver/async/AsyncNodeMessageHandler.java +++ b/server/src/java/org/jppf/server/nio/nodeserver/async/AsyncNodeMessageHandler.java @@ -136,8 +136,12 @@ public void handshakeReceived(final AsyncNodeContext context, final AbstractTask } else if (debugEnabled) log.debug("no system info received for node {}", context); final int port = bundle.getParameter(NODE_MANAGEMENT_PORT_PARAM, -1); if (debugEnabled) log.debug("management port = {} for node = {}", port, context); - String host = getChannelHost(context); - final HostIP hostIP = context.isLocal() ? new HostIP(host, host) : resolveHost(context); + String host = bundle.getParameter(NODE_MANAGEMENT_HOST_PARAM, null); + HostIP hostIP = null; + if (host == null) { + host = getChannelHost(context); + hostIP = context.isLocal() ? new HostIP(host, host) : resolveHost(context); + } else hostIP = NetworkUtils.getHostIP(host); final boolean sslEnabled = !context.isLocal() && context.getSSLHandler() != null; final boolean hasJmx = driver.getConfiguration().get(JPPFProperties.MANAGEMENT_ENABLED); final String masterUuid = bundle.getParameter(NODE_PROVISIONING_MASTER_UUID);