diff --git a/modules/ducktests/pom.xml b/modules/ducktests/pom.xml index 6d01a9c726847..e5756e7487298 100644 --- a/modules/ducktests/pom.xml +++ b/modules/ducktests/pom.xml @@ -163,16 +163,6 @@ - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven.javadoc.plugin.version} - - java:java.* - - - diff --git a/modules/ducktests/src/main/java/java/net/BlockingDnsInet4AddressImpl.java b/modules/ducktests/src/main/java/java/net/BlockingDnsInet4AddressImpl.java deleted file mode 100644 index 9e98aa37c8a15..0000000000000 --- a/modules/ducktests/src/main/java/java/net/BlockingDnsInet4AddressImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 java.net; - -/** */ -public class BlockingDnsInet4AddressImpl extends Inet4AddressImpl { - /** {@inheritDoc} */ - @Override public InetAddress[] lookupAllHostAddr(String hostname) throws UnknownHostException { - DnsBlocker.INSTANCE.onHostResolve(this, hostname); - - return super.lookupAllHostAddr(hostname); - } - - /** {@inheritDoc} */ - @Override public String getHostByAddr(byte[] addr) throws UnknownHostException { - DnsBlocker.INSTANCE.onAddrResolve(this, addr); - - return super.getHostByAddr(addr); - } -} diff --git a/modules/ducktests/src/main/java/java/net/BlockingDnsInet6AddressImpl.java b/modules/ducktests/src/main/java/java/net/BlockingDnsInet6AddressImpl.java deleted file mode 100644 index 47a0a02524158..0000000000000 --- a/modules/ducktests/src/main/java/java/net/BlockingDnsInet6AddressImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 java.net; - -/** */ -public class BlockingDnsInet6AddressImpl extends Inet6AddressImpl { - /** {@inheritDoc} */ - @Override public InetAddress[] lookupAllHostAddr(String hostname) throws UnknownHostException { - DnsBlocker.INSTANCE.onHostResolve(this, hostname); - - return super.lookupAllHostAddr(hostname); - } - - /** {@inheritDoc} */ - @Override public String getHostByAddr(byte[] addr) throws UnknownHostException { - DnsBlocker.INSTANCE.onAddrResolve(this, addr); - - return super.getHostByAddr(addr); - } -} diff --git a/modules/ducktests/src/main/java/java/net/DnsBlocker.java b/modules/ducktests/src/main/java/java/net/DnsBlocker.java deleted file mode 100644 index 8f93928122056..0000000000000 --- a/modules/ducktests/src/main/java/java/net/DnsBlocker.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 java.net; - -import java.io.File; -import java.io.FileNotFoundException; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.Scanner; - -/** */ -public class DnsBlocker { - /** */ - private static final String BLOCK_DNS_FILE = "/tmp/block_dns"; - - /** */ - public static final DnsBlocker INSTANCE = new DnsBlocker(); - - /** */ - private DnsBlocker() { - // No-op. - } - - /** - * Check and block hostname resolve request if needed. - * @param impl Implementation. - * @param hostname Hostname. - */ - public void onHostResolve(InetAddressImpl impl, String hostname) throws UnknownHostException { - if (!impl.loopbackAddress().getHostAddress().equals(hostname)) - check(hostname); - } - - /** - * Check and block address resolve request if needed. - * @param impl Implementation. - * @param addr Address. - */ - public void onAddrResolve(InetAddressImpl impl, byte[] addr) throws UnknownHostException { - if (!Arrays.equals(impl.loopbackAddress().getAddress(), addr)) - check(InetAddress.getByAddress(addr).toString()); - } - - /** */ - private void check(String req) throws UnknownHostException { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - File file = new File(BLOCK_DNS_FILE); - - if (file.exists()) { - try { - Scanner scanner = new Scanner(file); - if (!scanner.hasNextLong()) - throw new RuntimeException("Wrong " + BLOCK_DNS_FILE + " file format"); - - long timeout = scanner.nextLong(); - - if (!scanner.hasNextBoolean()) - throw new RuntimeException("Wrong " + BLOCK_DNS_FILE + " file format"); - - boolean fail = scanner.nextBoolean(); - - // Can't use logger here, because class need to be in bootstrap classloader. - System.out.println(sdf.format(new Date()) + " [" + Thread.currentThread().getName() + - "] DNS request " + req + " blocked for " + timeout + " ms"); - - Thread.dumpStack(); - - Thread.sleep(timeout); - - if (fail) - throw new UnknownHostException(); - } - catch (InterruptedException | FileNotFoundException e) { - throw new RuntimeException(e); - } - } - else { - System.out.println(sdf.format(new Date()) + " [" + Thread.currentThread().getName() + - "] Passed DNS request " + req); - - Thread.dumpStack(); - } - } -} diff --git a/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/dns_failure_test/BlockingNameService.java b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/dns_failure_test/BlockingNameService.java new file mode 100644 index 0000000000000..2c37056805d77 --- /dev/null +++ b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/dns_failure_test/BlockingNameService.java @@ -0,0 +1,176 @@ +/* + * 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.internal.ducktest.tests.dns_failure_test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Scanner; + +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.startup.cmdline.CommandLineStartup; + +/** */ +public class BlockingNameService implements NameServiceHandler { + /** */ + private static final String BLOCK_DNS_FILE = "/tmp/block_dns"; + + /** Private {@code NameService} class to proxy. */ + private static Class nameSrvcCls; + + /** */ + private final InetAddress loopback; + + /** Original {@code NameService}. */ + private final Object origNameSrvc; + + /** + * @param origNameSrvc Original {@code NameService}. + */ + private BlockingNameService(Object origNameSrvc) { + loopback = InetAddress.getLoopbackAddress(); + this.origNameSrvc = origNameSrvc; + } + + /** Installs {@code BlockingNameService} as main {@code NameService} to JVM11. */ + private static void installJdk11() throws Exception { + Field nameSrvcFld = InetAddress.class.getDeclaredField("nameService"); + nameSrvcFld.setAccessible(true); + + nameSrvcCls = Class.forName("java.net.InetAddress$NameService"); + + BlockingNameService blkNameSrvc = new BlockingNameService(nameSrvcFld.get(InetAddress.class)); + + nameSrvcFld.set( + InetAddress.class, + Proxy.newProxyInstance(nameSrvcCls.getClassLoader(), new Class[] { nameSrvcCls }, blkNameSrvc)); + + System.out.println("Installed DnsBlocker as main NameService to JVM"); + } + + /** Installs {@code BlockingNameService} as main {@code NameService} to JVM8. */ + private static void installJdk8() throws Exception { + Field nameSrvcFld = InetAddress.class.getDeclaredField("nameServices"); + nameSrvcFld.setAccessible(true); + + nameSrvcCls = Class.forName("sun.net.spi.nameservice.NameService"); + + BlockingNameService blkNameSrvc = new BlockingNameService(((List)nameSrvcFld.get(InetAddress.class)).get(0)); + + nameSrvcFld.set(InetAddress.class, F.asList( + Proxy.newProxyInstance(InetAddress.class.getClassLoader(), new Class[] { nameSrvcCls }, blkNameSrvc) + )); + } + + /** */ + public static void main(String[] args) throws Exception { + String jdkVer = U.jdkVersion(); + + if ("1.8".equals(jdkVer)) + installJdk8(); + else if ("11".equals(jdkVer)) + installJdk11(); + else + throw new IllegalArgumentException("Unsupported JDK version: " + jdkVer); + + System.out.println("Installed BlockingNameService as main NameService to JVM"); + + CommandLineStartup.main(args); + } + + /** */ + @Override public InetAddress[] lookupAllHostAddr(String hostname) throws UnknownHostException { + if (!loopback.getHostAddress().equals(hostname)) + check(hostname); + + try { + Method lookupAllHostAddr = nameSrvcCls.getDeclaredMethod("lookupAllHostAddr", String.class); + lookupAllHostAddr.setAccessible(true); + + return (InetAddress[])lookupAllHostAddr.invoke(origNameSrvc, hostname); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** */ + @Override public String getHostByAddr(byte[] addr) throws UnknownHostException { + if (!Arrays.equals(loopback.getAddress(), addr)) + check(InetAddress.getByAddress(addr).toString()); + + try { + Method getHostByAddr = nameSrvcCls.getDeclaredMethod("getHostByAddr", byte[].class); + getHostByAddr.setAccessible(true); + + return (String)getHostByAddr.invoke(origNameSrvc, addr); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** */ + private void check(String req) throws UnknownHostException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + File file = new File(BLOCK_DNS_FILE); + + if (file.exists()) { + try { + Scanner scanner = new Scanner(file); + if (!scanner.hasNextLong()) + throw new RuntimeException("Wrong " + BLOCK_DNS_FILE + " file format"); + + long timeout = scanner.nextLong(); + + if (!scanner.hasNextBoolean()) + throw new RuntimeException("Wrong " + BLOCK_DNS_FILE + " file format"); + + boolean fail = scanner.nextBoolean(); + + // Can't use logger here, because class need to be in bootstrap classloader. + System.out.println(sdf.format(new Date()) + " [" + Thread.currentThread().getName() + + "] DNS request " + req + " blocked for " + timeout + " ms"); + + Thread.dumpStack(); + + Thread.sleep(timeout); + + if (fail) + throw new UnknownHostException(); + } + catch (InterruptedException | FileNotFoundException e) { + throw new RuntimeException(e); + } + } + else { + System.out.println(sdf.format(new Date()) + " [" + Thread.currentThread().getName() + + "] Passed DNS request " + req); + + Thread.dumpStack(); + } + } +} diff --git a/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/dns_failure_test/NameServiceHandler.java b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/dns_failure_test/NameServiceHandler.java new file mode 100644 index 0000000000000..3b37605e3b82d --- /dev/null +++ b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/dns_failure_test/NameServiceHandler.java @@ -0,0 +1,44 @@ +/* + * 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.internal.ducktest.tests.dns_failure_test; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** Handler for {@code java.net.InetAddress$NameService}. */ +interface NameServiceHandler extends InvocationHandler { + /** Intercepts {@code NameService#lookupAllHostAddr}. */ + public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException; + + /** Intercepts {@code NameService#getHostByAddr}. */ + public String getHostByAddr(byte[] addr) throws UnknownHostException; + + /** Delegate {@code NameService} methods to {@link BlockingNameService}. */ + @Override public default Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String name = method.getName(); + + if ("lookupAllHostAddr".equals(name)) + return lookupAllHostAddr((String)args[0]); + else if ("getHostByAddr".equals(name)) + return getHostByAddr((byte[])args[0]); + else + throw new UnsupportedOperationException("Unsupported method: " + name); + } +} diff --git a/modules/ducktests/tests/ignitetest/services/ignite.py b/modules/ducktests/tests/ignitetest/services/ignite.py index da93c8771881c..50a34ad97aea1 100644 --- a/modules/ducktests/tests/ignitetest/services/ignite.py +++ b/modules/ducktests/tests/ignitetest/services/ignite.py @@ -27,6 +27,6 @@ class IgniteService(IgniteAwareService): APP_SERVICE_CLASS = "org.apache.ignite.startup.cmdline.CommandLineStartup" def __init__(self, context, config, num_nodes, jvm_opts=None, merge_with_default=True, startup_timeout_sec=60, - shutdown_timeout_sec=60, modules=None): - super().__init__(context, config, num_nodes, startup_timeout_sec, shutdown_timeout_sec, self.APP_SERVICE_CLASS, + shutdown_timeout_sec=60, modules=None, main_java_class=APP_SERVICE_CLASS): + super().__init__(context, config, num_nodes, startup_timeout_sec, shutdown_timeout_sec, main_java_class, modules, jvm_opts=jvm_opts, merge_with_default=merge_with_default) diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py b/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py index 81ff3fe58a95a..e8c2c036b8b36 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py +++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py @@ -245,7 +245,8 @@ def envs(self): return { 'EXCLUDE_TEST_CLASSES': 'true', 'IGNITE_LOG_DIR': self.service.log_dir, - 'USER_LIBS': ":".join(self.libs()) + 'USER_LIBS': ":".join(self.libs()), + "MAIN_CLASS": self.service.main_java_class } def config_file_path(self): @@ -356,6 +357,3 @@ def command(self, node): def config_file_path(self): return self.service.config_file if self.service.config.service_type == IgniteServiceType.NODE \ else self.service.thin_client_config_file - - def envs(self): - return {**super().envs(), **{"MAIN_CLASS": self.service.main_java_class}} diff --git a/modules/ducktests/tests/ignitetest/tests/dns_failure_test.py b/modules/ducktests/tests/ignitetest/tests/dns_failure_test.py index 2a9e676a8ad17..d2ccf6c39a1c4 100644 --- a/modules/ducktests/tests/ignitetest/tests/dns_failure_test.py +++ b/modules/ducktests/tests/ignitetest/tests/dns_failure_test.py @@ -16,7 +16,6 @@ """ Module contains DNS service failure test. """ -import os import socket from ducktape.mark import defaults @@ -27,7 +26,6 @@ from ignitetest.services.utils.ignite_configuration import IgniteConfiguration, DataStorageConfiguration from ignitetest.services.utils.ignite_configuration.data_storage import DataRegionConfiguration from ignitetest.services.utils.ignite_configuration.discovery import from_ignite_cluster -from ignitetest.services.utils.jvm_utils import java_major_version from ignitetest.utils import ignite_versions from ignitetest.utils.ignite_test import IgniteTest from ignitetest.utils.version import IgniteVersion, DEV_BRANCH @@ -110,19 +108,8 @@ def __prepare_service(self, ignite_config, num_nodes=1): self.test_context, ignite_config, startup_timeout_sec=120, - num_nodes=num_nodes) - - bootclasspath = list(map(lambda lib: os.path.join(lib, "classes"), ignite.spec._module_libs("ducktests"))) - - # Note: Support of impl.prefix property was removed since java 18. - ignite.spec.jvm_opts.append("-Dimpl.prefix=BlockingDns") - - java_version = ignite.java_version() - - if java_major_version(java_version) > 8: - ignite.spec.jvm_opts.append("\"--patch-module java.base=" + ":".join(bootclasspath) + "\"") - else: - ignite.spec.jvm_opts.append("-Xbootclasspath/a:" + ":".join(bootclasspath)) + num_nodes=num_nodes, + main_java_class="org.apache.ignite.internal.ducktest.tests.dns_failure_test.BlockingNameService") return ignite diff --git a/parent/pom.xml b/parent/pom.xml index b624cced27f24..56996b7996f38 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -933,6 +933,8 @@ java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-exports jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED + --add-exports + java.base/sun.net.util=ALL-UNNAMED