-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to listen on virtual interfaces. #19537
Conversation
Previously when trying to listen on virtual interfaces during bootstrap the application would stop working - the interface couldn't be found by the NetworkUtils class. The NetworkUtils utilize the underlying JDK NetworkInterface class which, when asked to lookup by name only takes physical interfaces into account, failing at virtual (or subinterfaces) ones (returning null). Note that when interating over all interfaces, both physical and virtual ones are taken into account. This changeset asks for all known interfaces, iterates over them and matches on the given name as part of the loop, allowing it to catch both physical and virtual interfaces. As a result, elasticsearch can now also serve on virtual interfaces. A test case has been added which at least makes sure that all iterable interfaces can be found by their respective name. (It's not easily possible in a unit test to "fake" virtual interfaces). Fixes elastic#17473
Can one of the admins verify this patch? |
I signed the CLA before sending this PR, maybe it didn't go "through" yet. |
In case someone wants to verify, you can easily create a virtual interface on linux like:
Now in the config set the Starting 2.3.4 prints
while with the change applied:
|
This is not right, testing is always possible. For example, this simple change adds a package-private method that can easily be tested with "fake" virtual interfaces: diff --git a/core/src/main/java/org/elasticsearch/common/network/NetworkUtils.java b/core/src/main/java/org/elasticsearch/common/network/NetworkUtils.java
index e15073e..6f098ef 100644
--- a/core/src/main/java/org/elasticsearch/common/network/NetworkUtils.java
+++ b/core/src/main/java/org/elasticsearch/common/network/NetworkUtils.java
@@ -227,8 +227,12 @@ public abstract class NetworkUtils {
/** Returns addresses for the given interface (it must be marked up) */
static InetAddress[] getAddressesForInterface(String name) throws SocketException {
+ return getAddressesForInterface(name, getInterfaces());
+ }
+
+ static InetAddress[] getAddressesForInterface(String name, List<NetworkInterface> interfaces) throws SocketException {
NetworkInterface intf = null;
- for (NetworkInterface networkInterface : getInterfaces()) {
+ for (NetworkInterface networkInterface : interfaces) {
if (name.equals(networkInterface.getName())) {
intf = networkInterface;
break;
@@ -236,7 +240,7 @@ public abstract class NetworkUtils {
}
if (intf == null) {
- throw new IllegalArgumentException("No interface named '" + name + "' found, got " + getInterfaces());
+ throw new IllegalArgumentException("No interface named '" + name + "' found, got " + interfaces);
}
if (!intf.isUp()) {
throw new IllegalArgumentException("Interface '" + name + "' is not up and running"); |
@jasontedor gotcha, I was actually referring to faking an actual virtual interface that would reproduce the scenario when interacting with the original JVM methods. Any idea how that could be done? Do you think I should make the change you suggested? Not sure it would provide more coverage for the specific case in question. |
The change is good. It should have been calling this method all along: it even calls it for error messages (making the bug more confusing, because it shows you the exact one you tried to set in the list). |
It's fine to just mock the behavior of the JVM method as I suggested.
Yes, it should be possible to write a test case that would fail without the change and will pass with your suggested change (which is good). |
@jasontedor sounds good I'll make the changes :) |
@jasontedor a quick follow up with some question/observations from my digging: Looks like it's not as easy as I thought because the So I propose doing one of the four things (please share your thoughts if there is something I have missed):
|
I agree, I think NetworkInterface is mostly initialized via native code, we have no chance. To be fair to @jasontedor's point, the bug probably happens because we don't test virtual interfaces :) But at the same time, we should not try to do something super-elaborate, or compromise the code itself with useless abstractions to do it. We should just test what is reasonable. |
Sadly, this is right. It is possible to get this tested, but I agree with Robert's point that it's probably not worth it for just this one test. If we were to go over this code and get it all tested, it might be worth doing what I suggest in this gist, but it's too far here. |
ok to test |
Looks like the git checkout failed https://elasticsearch-ci.elastic.co/job/elastic+elasticsearch+pull-request+multijob-intake/92/console |
test this please |
Thanks @daschl. |
Thank you for fixing this, @daschl :) |
@jasontedor and @daschl - this actually causes test failures if a virtual interface is not up:
(Reproduces every time for me), |
Reverted in c27237b. |
The test included in the fix here will blow up on any machine that has an interface that is down. |
Okay good to know, I'll rework the test case on monday and resubmit it. |
Previously when trying to listen on virtual interfaces during bootstrap the application would stop working - the interface couldn't be found by the NetworkUtils class. The NetworkUtils utilize the underlying JDK NetworkInterface class which, when asked to lookup by name only takes physical interfaces into account, failing at virtual (or subinterfaces) ones (returning null). Note that when interating over all interfaces, both physical and virtual ones are taken into account. This changeset asks for all known interfaces, iterates over them and matches on the given name as part of the loop, allowing it to catch both physical and virtual interfaces. As a result, elasticsearch can now also serve on virtual interfaces. A test case has been added which makes sure that all iterable interfaces can be found by their respective name. Note that this PR is a second iteration over the previously merged but later reverted elastic#19537 because it causes tests to fail when interfaces are down. The test has been modified to take this into account now. Closes elastic#17473 Relates elastic#19537
Previously when trying to listen on virtual interfaces during bootstrap the application would stop working - the interface couldn't be found by the NetworkUtils class. The NetworkUtils utilize the underlying JDK NetworkInterface class which, when asked to lookup by name only takes physical interfaces into account, failing at virtual (or subinterfaces) ones (returning null). Note that when interating over all interfaces, both physical and virtual ones are taken into account. This changeset asks for all known interfaces, iterates over them and matches on the given name as part of the loop, allowing it to catch both physical and virtual interfaces. As a result, elasticsearch can now also serve on virtual interfaces. A test case has been added which makes sure that all iterable interfaces can be found by their respective name. Note that this PR is a second iteration over the previously merged but later reverted elastic#19537 because it causes tests to fail when interfaces are down. The test has been modified to take this into account now. Closes elastic#17473 Closes elastic#19568 Relates elastic#19537
Previously when trying to listen on virtual interfaces during bootstrap the application would stop working - the interface couldn't be found by the NetworkUtils class. The NetworkUtils utilize the underlying JDK NetworkInterface class which, when asked to lookup by name only takes physical interfaces into account, failing at virtual (or subinterfaces) ones (returning null). Note that when interating over all interfaces, both physical and virtual ones are taken into account. This changeset asks for all known interfaces, iterates over them and matches on the given name as part of the loop, allowing it to catch both physical and virtual interfaces. As a result, elasticsearch can now also serve on virtual interfaces. A test case has been added which makes sure that all iterable interfaces can be found by their respective name. Note that this PR is a second iteration over the previously merged but later reverted #19537 because it causes tests to fail when interfaces are down. The test has been modified to take this into account now. Closes #17473 Closes #19568 Relates #19537
Previously when trying to listen on virtual interfaces during bootstrap the application would stop working - the interface couldn't be found by the NetworkUtils class. The NetworkUtils utilize the underlying JDK NetworkInterface class which, when asked to lookup by name only takes physical interfaces into account, failing at virtual (or subinterfaces) ones (returning null). Note that when interating over all interfaces, both physical and virtual ones are taken into account. This changeset asks for all known interfaces, iterates over them and matches on the given name as part of the loop, allowing it to catch both physical and virtual interfaces. As a result, elasticsearch can now also serve on virtual interfaces. A test case has been added which makes sure that all iterable interfaces can be found by their respective name. Note that this PR is a second iteration over the previously merged but later reverted #19537 because it causes tests to fail when interfaces are down. The test has been modified to take this into account now. Closes #17473 Closes #19568 Relates #19537
Previously when trying to listen on virtual interfaces during bootstrap the application would stop working - the interface couldn't be found by the NetworkUtils class. The NetworkUtils utilize the underlying JDK NetworkInterface class which, when asked to lookup by name only takes physical interfaces into account, failing at virtual (or subinterfaces) ones (returning null). Note that when interating over all interfaces, both physical and virtual ones are taken into account. This changeset asks for all known interfaces, iterates over them and matches on the given name as part of the loop, allowing it to catch both physical and virtual interfaces. As a result, elasticsearch can now also serve on virtual interfaces. A test case has been added which makes sure that all iterable interfaces can be found by their respective name. Note that this PR is a second iteration over the previously merged but later reverted #19537 because it causes tests to fail when interfaces are down. The test has been modified to take this into account now. Closes #17473 Closes #19568 Relates #19537
Previously when trying to listen on virtual interfaces during
bootstrap the application would stop working - the interface
couldn't be found by the NetworkUtils class.
The NetworkUtils utilize the underlying JDK NetworkInterface
class which, when asked to lookup by name only takes physical
interfaces into account, failing at virtual (or subinterfaces)
ones (returning null).
Note that when interating over all interfaces, both physical and
virtual ones are taken into account.
This changeset asks for all known interfaces, iterates over them
and matches on the given name as part of the loop, allowing it
to catch both physical and virtual interfaces.
As a result, elasticsearch can now also serve on virtual
interfaces.
A test case has been added which at least makes sure that all
iterable interfaces can be found by their respective name. (It's
not easily possible in a unit test to "fake" virtual interfaces).
Closes #17473