[KYUUBI #6499] Rewrite some utility methods in Java

# 🔍 Description

This PR rewrites some utility methods in Java, specifically,
```
Utils.isWindows
Utils.isMac
Utils.findLocalInetAddress
```

and moves them from `kyuubi-common`'s `Utils` to the `kyuubi-util`'s `JavaUtils`, so that they could be used in other modules that do not depend on `kyuubi-common`.

## Types of changes 🔖

- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Test Plan 🧪

Pass GHA.

---

# Checklist 📝

- [x] This patch was not authored or co-authored using [Generative Tooling](https://www.apache.org/legal/generative-tooling.html)

**Be nice. Be informative.**

Closes #6499 from pan3793/javautils.

Closes #6499

565936def [Cheng Pan] fix
f06a85e9f [Cheng Pan] Move some untiliy methods in Java

Authored-by: Cheng Pan <chengpan@apache.org>
Signed-off-by: Cheng Pan <chengpan@apache.org>
This commit is contained in:
Cheng Pan 2024-06-25 09:59:03 +08:00
parent 23a6ee15d2
commit 315adda353
No known key found for this signature in database
GPG Key ID: 8001952629BCC75D
16 changed files with 133 additions and 91 deletions

View File

@ -45,7 +45,7 @@ import org.apache.kyuubi.ha.HighAvailabilityConf._
import org.apache.kyuubi.ha.client.RetryPolicies import org.apache.kyuubi.ha.client.RetryPolicies
import org.apache.kyuubi.service.Serverable import org.apache.kyuubi.service.Serverable
import org.apache.kyuubi.session.SessionHandle import org.apache.kyuubi.session.SessionHandle
import org.apache.kyuubi.util.{SignalRegister, ThreadUtils} import org.apache.kyuubi.util.{JavaUtils, SignalRegister, ThreadUtils}
import org.apache.kyuubi.util.ThreadUtils.scheduleTolerableRunnableWithFixedDelay import org.apache.kyuubi.util.ThreadUtils.scheduleTolerableRunnableWithFixedDelay
case class SparkSQLEngine(spark: SparkSession) extends Serverable("SparkSQLEngine") { case class SparkSQLEngine(spark: SparkSession) extends Serverable("SparkSQLEngine") {
@ -296,7 +296,7 @@ object SparkSQLEngine extends Logging {
if (!isOnK8sClusterMode) { if (!isOnK8sClusterMode) {
// set driver host to ip instead of kyuubi pod name // set driver host to ip instead of kyuubi pod name
_sparkConf.setIfMissing("spark.driver.host", Utils.findLocalInetAddress.getHostAddress) _sparkConf.setIfMissing("spark.driver.host", JavaUtils.findLocalInetAddress.getHostAddress)
} }
} }

View File

@ -22,10 +22,11 @@ import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.hadoop.fs.permission.{FsAction, FsPermission} import org.apache.hadoop.fs.permission.{FsAction, FsPermission}
import org.apache.hadoop.net.NetUtils import org.apache.hadoop.net.NetUtils
import org.apache.kyuubi.{Utils, WithSimpleDFSService} import org.apache.kyuubi.WithSimpleDFSService
import org.apache.kyuubi.config.KyuubiConf.FRONTEND_THRIFT_BINARY_BIND_HOST import org.apache.kyuubi.config.KyuubiConf.FRONTEND_THRIFT_BINARY_BIND_HOST
import org.apache.kyuubi.kubernetes.test.WithKyuubiServerOnKubernetes import org.apache.kyuubi.kubernetes.test.WithKyuubiServerOnKubernetes
import org.apache.kyuubi.operation.SparkQueryTests import org.apache.kyuubi.operation.SparkQueryTests
import org.apache.kyuubi.util.JavaUtils
import org.apache.kyuubi.zookeeper.ZookeeperConf.ZK_CLIENT_PORT_ADDRESS import org.apache.kyuubi.zookeeper.ZookeeperConf.ZK_CLIENT_PORT_ADDRESS
/** /**
@ -109,7 +110,7 @@ class KyuubiOnKubernetesWithClientSparkTestsSuite
*/ */
class KyuubiOnKubernetesWithClusterSparkTestsSuite class KyuubiOnKubernetesWithClusterSparkTestsSuite
extends KyuubiOnKubernetesWithSparkTestsBase with WithSimpleDFSService with SparkQueryTests { extends KyuubiOnKubernetesWithSparkTestsBase with WithSimpleDFSService with SparkQueryTests {
private val localhostAddress = Utils.findLocalInetAddress.getHostAddress private val localhostAddress = JavaUtils.findLocalInetAddress.getHostAddress
private val driverTemplate = private val driverTemplate =
Thread.currentThread().getContextClassLoader.getResource("driver.yml") Thread.currentThread().getContextClassLoader.getResource("driver.yml")

View File

@ -34,6 +34,7 @@ import org.apache.kyuubi.engine.spark.SparkProcessBuilder
import org.apache.kyuubi.kubernetes.test.MiniKube import org.apache.kyuubi.kubernetes.test.MiniKube
import org.apache.kyuubi.operation.SparkQueryTests import org.apache.kyuubi.operation.SparkQueryTests
import org.apache.kyuubi.session.KyuubiSessionManager import org.apache.kyuubi.session.KyuubiSessionManager
import org.apache.kyuubi.util.JavaUtils
import org.apache.kyuubi.util.Validator.KUBERNETES_EXECUTOR_POD_NAME_PREFIX import org.apache.kyuubi.util.Validator.KUBERNETES_EXECUTOR_POD_NAME_PREFIX
import org.apache.kyuubi.zookeeper.ZookeeperConf.ZK_CLIENT_PORT_ADDRESS import org.apache.kyuubi.zookeeper.ZookeeperConf.ZK_CLIENT_PORT_ADDRESS
@ -96,7 +97,7 @@ class SparkClientModeOnKubernetesSuite extends SparkClientModeOnKubernetesSuiteB
*/ */
class SparkClusterModeOnKubernetesSuiteBase class SparkClusterModeOnKubernetesSuiteBase
extends SparkOnKubernetesSuiteBase with WithSimpleDFSService { extends SparkOnKubernetesSuiteBase with WithSimpleDFSService {
private val localhostAddress = Utils.findLocalInetAddress.getHostAddress private val localhostAddress = JavaUtils.findLocalInetAddress.getHostAddress
private val driverTemplate = private val driverTemplate =
Thread.currentThread().getContextClassLoader.getResource("driver.yml") Thread.currentThread().getContextClassLoader.getResource("driver.yml")

View File

@ -18,7 +18,6 @@
package org.apache.kyuubi package org.apache.kyuubi
import java.io._ import java.io._
import java.net.{Inet4Address, InetAddress, NetworkInterface}
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path, Paths, StandardCopyOption} import java.nio.file.{Files, Path, Paths, StandardCopyOption}
import java.security.PrivilegedAction import java.security.PrivilegedAction
@ -33,7 +32,6 @@ import scala.sys.process._
import scala.util.control.NonFatal import scala.util.control.NonFatal
import scala.util.matching.Regex import scala.util.matching.Regex
import org.apache.commons.lang3.SystemUtils
import org.apache.commons.lang3.time.DateFormatUtils import org.apache.commons.lang3.time.DateFormatUtils
import org.apache.hadoop.security.UserGroupInformation import org.apache.hadoop.security.UserGroupInformation
import org.apache.hadoop.util.ShutdownHookManager import org.apache.hadoop.util.ShutdownHookManager
@ -224,31 +222,6 @@ object Utils extends Logging {
}) })
} }
private val shortVersionRegex = """^(\d+\.\d+\.\d+)(.*)?$""".r
/**
* Given a Kyuubi/Spark/Hive version string, return the short version string.
* E.g., for 3.0.0-SNAPSHOT, return '3.0.0'.
*/
def shortVersion(version: String): String = {
shortVersionRegex.findFirstMatchIn(version) match {
case Some(m) => m.group(1)
case None =>
throw new IllegalArgumentException(s"Tried to parse '$version' as a project" +
s" version string, but it could not find the major/minor/maintenance version numbers.")
}
}
/**
* Whether the underlying operating system is Windows.
*/
val isWindows: Boolean = SystemUtils.IS_OS_WINDOWS
/**
* Whether the underlying operating system is MacOS.
*/
val isMac: Boolean = SystemUtils.IS_OS_MAC
/** /**
* Indicates whether Kyuubi is currently running unit tests. * Indicates whether Kyuubi is currently running unit tests.
*/ */
@ -274,34 +247,6 @@ object Utils extends Logging {
ShutdownHookManager.get().addShutdownHook(hook, priority) ShutdownHookManager.get().addShutdownHook(hook, priority)
} }
/**
* This block of code is based on Spark's Utils.findLocalInetAddress()
*/
def findLocalInetAddress: InetAddress = {
val address = InetAddress.getLocalHost
if (address.isLoopbackAddress) {
val activeNetworkIFs = NetworkInterface.getNetworkInterfaces.asScala.toSeq
val reOrderedNetworkIFs = if (isWindows) activeNetworkIFs else activeNetworkIFs.reverse
for (ni <- reOrderedNetworkIFs) {
val addresses = ni.getInetAddresses.asScala
.filterNot(addr => addr.isLinkLocalAddress || addr.isLoopbackAddress).toSeq
if (addresses.nonEmpty) {
val addr = addresses.find(_.isInstanceOf[Inet4Address]).getOrElse(addresses.head)
// because of Inet6Address.toHostName may add interface at the end if it knows about it
val strippedAddress = InetAddress.getByAddress(addr.getAddress)
// We've found an address that looks reasonable!
warn(s"${address.getHostName} was resolved to a loopback address: " +
s"${address.getHostAddress}, using ${strippedAddress.getHostAddress}")
return strippedAddress
}
}
warn(s"${address.getHostName} was resolved to a loopback address: ${address.getHostAddress}" +
" but we couldn't find any external IP address!")
}
address
}
/** /**
* return date of format yyyyMMdd * return date of format yyyyMMdd
*/ */

View File

@ -25,7 +25,7 @@ import scala.language.implicitConversions
import org.apache.hadoop.conf.Configuration import org.apache.hadoop.conf.Configuration
import org.apache.kyuubi.{KyuubiSQLException, Logging, Utils} import org.apache.kyuubi.{KyuubiSQLException, Logging}
import org.apache.kyuubi.Utils.stringifyException import org.apache.kyuubi.Utils.stringifyException
import org.apache.kyuubi.config.KyuubiConf.{FRONTEND_ADVERTISED_HOST, FRONTEND_CONNECTION_URL_USE_HOSTNAME, PROXY_USER, SESSION_CLOSE_ON_DISCONNECT} import org.apache.kyuubi.config.KyuubiConf.{FRONTEND_ADVERTISED_HOST, FRONTEND_CONNECTION_URL_USE_HOSTNAME, PROXY_USER, SESSION_CLOSE_ON_DISCONNECT}
import org.apache.kyuubi.config.KyuubiReservedKeys._ import org.apache.kyuubi.config.KyuubiReservedKeys._
@ -36,7 +36,7 @@ import org.apache.kyuubi.shaded.hive.service.rpc.thrift._
import org.apache.kyuubi.shaded.thrift.protocol.TProtocol import org.apache.kyuubi.shaded.thrift.protocol.TProtocol
import org.apache.kyuubi.shaded.thrift.server.{ServerContext, TServerEventHandler} import org.apache.kyuubi.shaded.thrift.server.{ServerContext, TServerEventHandler}
import org.apache.kyuubi.shaded.thrift.transport.TTransport import org.apache.kyuubi.shaded.thrift.transport.TTransport
import org.apache.kyuubi.util.{KyuubiHadoopUtils, NamedThreadFactory} import org.apache.kyuubi.util.{JavaUtils, KyuubiHadoopUtils, NamedThreadFactory}
/** /**
* Apache Thrift based hive-service-rpc base class * Apache Thrift based hive-service-rpc base class
@ -53,7 +53,7 @@ abstract class TFrontendService(name: String)
protected def serverHost: Option[String] protected def serverHost: Option[String]
protected def portNum: Int protected def portNum: Int
protected lazy val serverAddr: InetAddress = protected lazy val serverAddr: InetAddress =
serverHost.map(InetAddress.getByName).getOrElse(Utils.findLocalInetAddress) serverHost.map(InetAddress.getByName).getOrElse(JavaUtils.findLocalInetAddress)
protected lazy val serverSocket = new ServerSocket(portNum, -1, serverAddr) protected lazy val serverSocket = new ServerSocket(portNum, -1, serverAddr)
protected lazy val actualPort: Int = serverSocket.getLocalPort protected lazy val actualPort: Int = serverSocket.getLocalPort
protected lazy val authFactory: KyuubiAuthenticationFactory = protected lazy val authFactory: KyuubiAuthenticationFactory =

View File

@ -18,7 +18,6 @@
package org.apache.kyuubi package org.apache.kyuubi
import java.io.{File, IOException} import java.io.{File, IOException}
import java.net.InetAddress
import java.nio.file.{Files, Paths} import java.nio.file.{Files, Paths}
import java.security.PrivilegedExceptionAction import java.security.PrivilegedExceptionAction
import java.util.Properties import java.util.Properties
@ -118,15 +117,6 @@ class UtilsSuite extends KyuubiFunSuite {
}) })
} }
test("findLocalInetAddress") {
val address = InetAddress.getLocalHost
if (!address.isLoopbackAddress) {
assert(Utils.findLocalInetAddress === InetAddress.getLocalHost)
} else {
assert(Utils.findLocalInetAddress !== InetAddress.getLocalHost)
}
}
test("getAbsolutePathFromWork") { test("getAbsolutePathFromWork") {
val workDir = System.getenv("KYUUBI_WORK_DIR_ROOT") val workDir = System.getenv("KYUUBI_WORK_DIR_ROOT")
val path1 = "path1" val path1 = "path1"

View File

@ -25,6 +25,7 @@ import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.kyuubi.util.JavaUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -40,7 +41,7 @@ public class UserHS2ConnectionFileParser implements HS2ConnectionFileParser {
public static final String DEFAULT_BEELINE_USER_CONF_LOCATION = public static final String DEFAULT_BEELINE_USER_CONF_LOCATION =
System.getProperty("user.home") System.getProperty("user.home")
+ File.separator + File.separator
+ (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? "" : ".") + (JavaUtils.isWindows ? "" : ".")
+ "beeline" + "beeline"
+ File.separator; + File.separator;
public static final String ETC_HIVE_CONF_LOCATION = public static final String ETC_HIVE_CONF_LOCATION =

View File

@ -37,7 +37,7 @@ import org.apache.kyuubi.ha.HighAvailabilityConf
import org.apache.kyuubi.ha.HighAvailabilityConf.HA_ZK_ENGINE_AUTH_TYPE import org.apache.kyuubi.ha.HighAvailabilityConf.HA_ZK_ENGINE_AUTH_TYPE
import org.apache.kyuubi.ha.client.AuthTypes import org.apache.kyuubi.ha.client.AuthTypes
import org.apache.kyuubi.operation.log.OperationLog import org.apache.kyuubi.operation.log.OperationLog
import org.apache.kyuubi.util.{KubernetesUtils, Validator} import org.apache.kyuubi.util.{JavaUtils, KubernetesUtils, Validator}
import org.apache.kyuubi.util.command.CommandLineUtils._ import org.apache.kyuubi.util.command.CommandLineUtils._
class SparkProcessBuilder( class SparkProcessBuilder(
@ -359,7 +359,8 @@ object SparkProcessBuilder {
final private[spark] val PRINCIPAL = "spark.kerberos.principal" final private[spark] val PRINCIPAL = "spark.kerberos.principal"
final private[spark] val KEYTAB = "spark.kerberos.keytab" final private[spark] val KEYTAB = "spark.kerberos.keytab"
// Get the appropriate spark-submit file // Get the appropriate spark-submit file
final private val SPARK_SUBMIT_FILE = if (Utils.isWindows) "spark-submit.cmd" else "spark-submit" final private val SPARK_SUBMIT_FILE =
if (JavaUtils.isWindows) "spark-submit.cmd" else "spark-submit"
final private val SPARK_CONF_DIR = "SPARK_CONF_DIR" final private val SPARK_CONF_DIR = "SPARK_CONF_DIR"
final private val SPARK_CONF_FILE_NAME = "spark-defaults.conf" final private val SPARK_CONF_FILE_NAME = "spark-defaults.conf"

View File

@ -33,7 +33,7 @@ import org.apache.kyuubi.server.mysql._
import org.apache.kyuubi.server.mysql.NettyUtils._ import org.apache.kyuubi.server.mysql.NettyUtils._
import org.apache.kyuubi.server.mysql.authentication.MySQLAuthHandler import org.apache.kyuubi.server.mysql.authentication.MySQLAuthHandler
import org.apache.kyuubi.service.{AbstractFrontendService, Serverable, Service} import org.apache.kyuubi.service.{AbstractFrontendService, Serverable, Service}
import org.apache.kyuubi.util.NamedThreadFactory import org.apache.kyuubi.util.{JavaUtils, NamedThreadFactory}
/** /**
* A frontend service implement MySQL protocol. * A frontend service implement MySQL protocol.
@ -64,7 +64,7 @@ class KyuubiMySQLFrontendService(override val serverable: Serverable)
serverAddr = conf.get(FRONTEND_MYSQL_BIND_HOST) serverAddr = conf.get(FRONTEND_MYSQL_BIND_HOST)
.map(InetAddress.getByName) .map(InetAddress.getByName)
.getOrElse(Utils.findLocalInetAddress) .getOrElse(JavaUtils.findLocalInetAddress)
port = conf.get(FRONTEND_MYSQL_BIND_PORT) port = conf.get(FRONTEND_MYSQL_BIND_PORT)
val workerThreads = defaultNumThreads(conf.get(FRONTEND_MYSQL_NETTY_WORKER_THREADS)) val workerThreads = defaultNumThreads(conf.get(FRONTEND_MYSQL_NETTY_WORKER_THREADS))
val bossGroup = createEventLoop(1, "mysql-netty-boss") val bossGroup = createEventLoop(1, "mysql-netty-boss")

View File

@ -37,7 +37,7 @@ import org.apache.kyuubi.server.ui.{JettyServer, JettyUtils}
import org.apache.kyuubi.service.{AbstractFrontendService, Serverable, Service, ServiceUtils} import org.apache.kyuubi.service.{AbstractFrontendService, Serverable, Service, ServiceUtils}
import org.apache.kyuubi.service.authentication.{AuthTypes, AuthUtils} import org.apache.kyuubi.service.authentication.{AuthTypes, AuthUtils}
import org.apache.kyuubi.session.{KyuubiSessionManager, SessionHandle} import org.apache.kyuubi.session.{KyuubiSessionManager, SessionHandle}
import org.apache.kyuubi.util.ThreadUtils import org.apache.kyuubi.util.{JavaUtils, ThreadUtils}
import org.apache.kyuubi.util.ThreadUtils.scheduleTolerableRunnableWithFixedDelay import org.apache.kyuubi.util.ThreadUtils.scheduleTolerableRunnableWithFixedDelay
/** /**
@ -59,13 +59,13 @@ class KyuubiRestFrontendService(override val serverable: Serverable)
lazy val host: String = conf.get(FRONTEND_REST_BIND_HOST) lazy val host: String = conf.get(FRONTEND_REST_BIND_HOST)
.getOrElse { .getOrElse {
if (Utils.isWindows || Utils.isMac) { if (JavaUtils.isWindows || JavaUtils.isMac) {
warn(s"Kyuubi Server run in Windows or Mac environment, binding $getName to 0.0.0.0") warn(s"Kyuubi Server run in Windows or Mac environment, binding $getName to 0.0.0.0")
"0.0.0.0" "0.0.0.0"
} else if (conf.get(KyuubiConf.FRONTEND_CONNECTION_URL_USE_HOSTNAME)) { } else if (conf.get(KyuubiConf.FRONTEND_CONNECTION_URL_USE_HOSTNAME)) {
Utils.findLocalInetAddress.getCanonicalHostName JavaUtils.findLocalInetAddress.getCanonicalHostName
} else { } else {
Utils.findLocalInetAddress.getHostAddress JavaUtils.findLocalInetAddress.getHostAddress
} }
} }

View File

@ -19,12 +19,13 @@ package org.apache.kyuubi.server
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import org.apache.kyuubi.{KyuubiException, Utils} import org.apache.kyuubi.KyuubiException
import org.apache.kyuubi.config.KyuubiConf import org.apache.kyuubi.config.KyuubiConf
import org.apache.kyuubi.config.KyuubiConf.{FRONTEND_ADVERTISED_HOST, FRONTEND_TRINO_BIND_HOST, FRONTEND_TRINO_BIND_PORT, FRONTEND_TRINO_JETTY_STOP_TIMEOUT, FRONTEND_TRINO_MAX_WORKER_THREADS} import org.apache.kyuubi.config.KyuubiConf._
import org.apache.kyuubi.server.trino.api.v1.ApiRootResource import org.apache.kyuubi.server.trino.api.v1.ApiRootResource
import org.apache.kyuubi.server.ui.JettyServer import org.apache.kyuubi.server.ui.JettyServer
import org.apache.kyuubi.service.{AbstractFrontendService, Serverable, Service} import org.apache.kyuubi.service.{AbstractFrontendService, Serverable, Service}
import org.apache.kyuubi.util.JavaUtils
/** /**
* A frontend service based on RESTful api via HTTP protocol. * A frontend service based on RESTful api via HTTP protocol.
@ -40,9 +41,9 @@ class KyuubiTrinoFrontendService(override val serverable: Serverable)
lazy val host: String = conf.get(FRONTEND_TRINO_BIND_HOST) lazy val host: String = conf.get(FRONTEND_TRINO_BIND_HOST)
.getOrElse { .getOrElse {
if (conf.get(KyuubiConf.FRONTEND_CONNECTION_URL_USE_HOSTNAME)) { if (conf.get(KyuubiConf.FRONTEND_CONNECTION_URL_USE_HOSTNAME)) {
Utils.findLocalInetAddress.getCanonicalHostName JavaUtils.findLocalInetAddress.getCanonicalHostName
} else { } else {
Utils.findLocalInetAddress.getHostAddress JavaUtils.findLocalInetAddress.getHostAddress
} }
} }

View File

@ -22,7 +22,7 @@ import org.eclipse.jetty.server.handler.{ContextHandlerCollection, ErrorHandler}
import org.eclipse.jetty.util.component.LifeCycle import org.eclipse.jetty.util.component.LifeCycle
import org.eclipse.jetty.util.thread.{QueuedThreadPool, ScheduledExecutorScheduler} import org.eclipse.jetty.util.thread.{QueuedThreadPool, ScheduledExecutorScheduler}
import org.apache.kyuubi.Utils.isWindows import org.apache.kyuubi.util.JavaUtils
private[kyuubi] case class JettyServer( private[kyuubi] case class JettyServer(
server: Server, server: Server,
@ -105,7 +105,7 @@ object JettyServer {
new HttpConnectionFactory(httpConf)) new HttpConnectionFactory(httpConf))
connector.setHost(host) connector.setHost(host)
connector.setPort(port) connector.setPort(port)
connector.setReuseAddress(!isWindows) connector.setReuseAddress(!JavaUtils.isWindows)
connector.setAcceptQueueSize(math.min(connector.getAcceptors, 8)) connector.setAcceptQueueSize(math.min(connector.getAcceptors, 8))
new JettyServer(server, connector, collection) new JettyServer(server, connector, collection)

View File

@ -36,6 +36,11 @@
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -20,10 +20,23 @@
package org.apache.kyuubi.util; package org.apache.kyuubi.util;
import java.io.File; import java.io.File;
import java.net.URISyntaxException; import java.net.*;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavaUtils { public class JavaUtils {
private static final Logger LOG = LoggerFactory.getLogger(JavaUtils.class);
/** Whether the underlying operating system is Windows. */
public static final boolean isWindows = System.getProperty("os.name", "").startsWith("Windows");
/** Whether the underlying operating system is MacOS. */
public static final boolean isMac = System.getProperty("os.name", "").startsWith("Mac");
public static String getCodeSourceLocation(Class<?> clazz) { public static String getCodeSourceLocation(Class<?> clazz) {
try { try {
return new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI()).getPath(); return new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI()).getPath();
@ -31,4 +44,46 @@ public class JavaUtils {
throw new RuntimeException(rethrow); throw new RuntimeException(rethrow);
} }
} }
public static InetAddress findLocalInetAddress() throws UnknownHostException, SocketException {
InetAddress address = InetAddress.getLocalHost();
if (address.isLoopbackAddress()) {
List<NetworkInterface> activeNetworkIFs =
Collections.list(NetworkInterface.getNetworkInterfaces());
if (!isWindows) {
Collections.reverse(activeNetworkIFs);
}
for (NetworkInterface ni : activeNetworkIFs) {
List<InetAddress> addresses =
Collections.list(ni.getInetAddresses()).stream()
.filter(addr -> !addr.isLinkLocalAddress() && !addr.isLoopbackAddress())
.collect(Collectors.toList());
if (!addresses.isEmpty()) {
InetAddress addr =
addresses.stream()
.filter(a -> a instanceof Inet4Address)
.findFirst()
.orElse(addresses.get(0));
InetAddress strippedAddress = InetAddress.getByAddress(addr.getAddress());
// We've found an address that looks reasonable!
LOG.warn(
"{} was resolved to a loopback address: {}, using {}",
addr.getHostName(),
addr.getHostAddress(),
strippedAddress.getHostAddress());
return strippedAddress;
}
}
LOG.warn(
"{} was resolved to a loopback address: {} but we couldn't find any external IP address!",
address.getHostName(),
address.getHostAddress());
}
return address;
}
} }

View File

@ -0,0 +1,41 @@
/*
* 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.kyuubi.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import org.junit.Test;
public class JavaUtilsTest {
@Test
public void testFindLocalInetAddress() throws UnknownHostException, SocketException {
InetAddress address = InetAddress.getLocalHost();
if (!address.isLoopbackAddress()) {
assertEquals(InetAddress.getLocalHost(), JavaUtils.findLocalInetAddress());
} else {
assertNotEquals(InetAddress.getLocalHost(), JavaUtils.findLocalInetAddress());
}
}
}

View File

@ -25,6 +25,7 @@ import org.apache.kyuubi.Utils._
import org.apache.kyuubi.config.{ConfigEntry, KyuubiConf} import org.apache.kyuubi.config.{ConfigEntry, KyuubiConf}
import org.apache.kyuubi.service.{AbstractService, ServiceState} import org.apache.kyuubi.service.{AbstractService, ServiceState}
import org.apache.kyuubi.shaded.zookeeper.server.{NIOServerCnxnFactory, ZooKeeperServer} import org.apache.kyuubi.shaded.zookeeper.server.{NIOServerCnxnFactory, ZooKeeperServer}
import org.apache.kyuubi.util.JavaUtils
import org.apache.kyuubi.zookeeper.ZookeeperConf._ import org.apache.kyuubi.zookeeper.ZookeeperConf._
class EmbeddedZookeeper extends AbstractService("EmbeddedZookeeper") { class EmbeddedZookeeper extends AbstractService("EmbeddedZookeeper") {
@ -48,9 +49,9 @@ class EmbeddedZookeeper extends AbstractService("EmbeddedZookeeper") {
val maxSessionTimeout = conf.get(ZK_MAX_SESSION_TIMEOUT) val maxSessionTimeout = conf.get(ZK_MAX_SESSION_TIMEOUT)
host = conf.get(ZK_CLIENT_PORT_ADDRESS).getOrElse { host = conf.get(ZK_CLIENT_PORT_ADDRESS).getOrElse {
if (conf.get(ZK_CLIENT_USE_HOSTNAME)) { if (conf.get(ZK_CLIENT_USE_HOSTNAME)) {
findLocalInetAddress.getCanonicalHostName JavaUtils.findLocalInetAddress.getCanonicalHostName
} else { } else {
findLocalInetAddress.getHostAddress JavaUtils.findLocalInetAddress.getHostAddress
} }
} }