diff --git a/cdap-app-fabric/src/main/java/io/cdap/cdap/internal/app/services/AppFabricServer.java b/cdap-app-fabric/src/main/java/io/cdap/cdap/internal/app/services/AppFabricServer.java index 3f6e6418a484..8f8993ce1ecc 100644 --- a/cdap-app-fabric/src/main/java/io/cdap/cdap/internal/app/services/AppFabricServer.java +++ b/cdap-app-fabric/src/main/java/io/cdap/cdap/internal/app/services/AppFabricServer.java @@ -53,8 +53,12 @@ import io.cdap.http.AbstractHandlerHook; import io.cdap.http.HttpHandler; import io.cdap.http.NettyHttpService; +import java.io.File; +import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -242,6 +246,9 @@ private Cancellable startHttpService(NettyHttpService httpService) throws Except ResolvingDiscoverable.of(uriScheme.createDiscoverable(serviceName, socketAddress)))); } + writeServerPortToFile(Constants.Service.APP_FABRIC_HTTP, announcePort); + LOG.debug("AppFabric HTTP server started."); + return () -> { LOG.debug("Stopping AppFabric HTTP service."); for (Cancellable cancellable : cancellables) { @@ -259,4 +266,12 @@ private Cancellable startHttpService(NettyHttpService httpService) throws Except LOG.info("AppFabric HTTP service stopped."); }; } + + private void writeServerPortToFile(String service, int port) throws IOException { + String dir = cConf.get(Constants.Service.SERVER_PORT_DIR); + String filename = service + ".port"; + File file = new File(dir, filename); + LOG.debug("Writing server port {} to file: {}", port, file.getAbsolutePath()); + Files.write(file.toPath(), String.valueOf(port).getBytes()); + } } diff --git a/cdap-app-fabric/src/test/java/io/cdap/cdap/internal/app/services/AppFabricServerTest.java b/cdap-app-fabric/src/test/java/io/cdap/cdap/internal/app/services/AppFabricServerTest.java index 6a1ca2f3cb01..dcb75d1a7a82 100644 --- a/cdap-app-fabric/src/test/java/io/cdap/cdap/internal/app/services/AppFabricServerTest.java +++ b/cdap-app-fabric/src/test/java/io/cdap/cdap/internal/app/services/AppFabricServerTest.java @@ -22,14 +22,17 @@ import io.cdap.cdap.common.conf.CConfiguration; import io.cdap.cdap.common.conf.Constants; import io.cdap.cdap.common.conf.SConfiguration; +import io.cdap.cdap.common.conf.StringUtils; import io.cdap.cdap.common.discovery.EndpointStrategy; import io.cdap.cdap.common.discovery.RandomEndpointStrategy; import io.cdap.cdap.common.discovery.URIScheme; import io.cdap.cdap.common.utils.Tasks; import io.cdap.cdap.internal.AppFabricTestHelper; import io.cdap.cdap.security.server.LdapLoginModule; +import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.file.Files; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import javax.net.ssl.SSLSocket; @@ -96,4 +99,35 @@ public void testSsl() throws IOException { AppFabricTestHelper.shutdown(); } } + + @Test + public void testServerPortFile() throws Exception { + Injector injector = AppFabricTestHelper.getInjector(); + try { + AppFabricServer server = injector.getInstance(AppFabricServer.class); + DiscoveryServiceClient discoveryServiceClient = injector.getInstance(DiscoveryServiceClient.class); + Service.State state = server.startAndWait(); + Assert.assertSame(state, Service.State.RUNNING); + + final EndpointStrategy endpointStrategy = new RandomEndpointStrategy( + () -> discoveryServiceClient.discover(Constants.Service.APP_FABRIC_HTTP)); + Assert.assertNotNull(endpointStrategy.pick(5, TimeUnit.SECONDS)); + + // Check file exists and port number is in range of 0 to 65535. + File file = new File("/tmp/appfabric.port"); + Assert.assertTrue("server port file doesn't exist", + file.exists() && !file.isDirectory()); + byte[] bytes = Files.readAllBytes(file.toPath()); + String content = new String(bytes); + Assert.assertTrue(Integer.valueOf(content) > 0); + Assert.assertTrue(Integer.valueOf(content) < 65535); + + state = server.stopAndWait(); + Assert.assertSame(state, Service.State.TERMINATED); + + Tasks.waitFor(true, () -> endpointStrategy.pick() == null, 5, TimeUnit.SECONDS, 100, TimeUnit.MILLISECONDS); + } finally { + AppFabricTestHelper.shutdown(); + } + } } diff --git a/cdap-common/src/main/java/io/cdap/cdap/common/conf/Constants.java b/cdap-common/src/main/java/io/cdap/cdap/common/conf/Constants.java index 5cf9f9c2dc95..54dfdbb41b27 100644 --- a/cdap-common/src/main/java/io/cdap/cdap/common/conf/Constants.java +++ b/cdap-common/src/main/java/io/cdap/cdap/common/conf/Constants.java @@ -158,6 +158,8 @@ public static final class Service { public static final String REMOTE_AGENT_SERVICE = "remote.agent.service"; public static final String ARTIFACT_CACHE_SERVICE = "artifact.cache.service"; public static final String RUNTIME_MONITOR_RETRY_PREFIX = "system.runtime.monitor."; + + public static final String SERVER_PORT_DIR = "system.services.server.dir"; } /** diff --git a/cdap-common/src/main/resources/cdap-default.xml b/cdap-common/src/main/resources/cdap-default.xml index ecd3b4cb884a..ed055eabe1a8 100644 --- a/cdap-common/src/main/resources/cdap-default.xml +++ b/cdap-common/src/main/resources/cdap-default.xml @@ -6563,4 +6563,12 @@ + + system.services.server.dir + /tmp + + Directory for storing files related to server for system services. + + +