Skip to content

Commit

Permalink
Support ipv6 in switch role uri creation
Browse files Browse the repository at this point in the history
  • Loading branch information
martinfurmanski committed Jul 1, 2017
1 parent cf2f46a commit 169d4b6
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 20 deletions.
Expand Up @@ -19,6 +19,8 @@
*/
package org.neo4j.kernel.ha.cluster;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.function.BiFunction;
import java.util.function.Supplier;
Expand Down Expand Up @@ -123,17 +125,31 @@ public URI switchToMaster( LifeSupport haCommunicationLife, URI me )

static URI getMasterUri( URI me, MasterServer masterServer, Config config )
{

String hostname = config.get( HaSettings.ha_server ).getHost();
if ( hostname == null || hostname.contains( "0.0.0.0" ) )
InetSocketAddress masterSocketAddress = masterServer.getSocketAddress();

if ( hostname == null || isWildcard( hostname ) )
{
String masterAddress = ServerUtil.getHostString( masterServer.getSocketAddress() );
hostname = masterAddress.contains( "0.0.0.0" ) ? me.getHost() : masterAddress;
InetAddress masterAddress = masterSocketAddress.getAddress();
hostname = masterAddress.isAnyLocalAddress() ? me.getHost() : ServerUtil.getHostString( masterSocketAddress );
hostname = ensureWrapForIPv6Uri( hostname );
}

int port = masterServer.getSocketAddress().getPort();
return URI.create( "ha://" + hostname + ":" + masterSocketAddress.getPort() + "?serverId=" + myId( config ) );
}

return URI.create( "ha://" + hostname + ":" + port + "?serverId=" + myId( config ) );
private static String ensureWrapForIPv6Uri( String hostname )
{
if ( hostname.contains( ":" ) && !hostname.contains( "[" ) )
{
hostname = "[" + hostname + "]";
}
return hostname;
}

private static boolean isWildcard( String hostname )
{
return hostname.contains( "0.0.0.0" ) || hostname.contains( "[::]" ) || hostname.contains( "[0:0:0:0:0:0:0:0]" );
}

private static InstanceId myId( Config config )
Expand Down
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.time.Clock;
import java.util.function.Function;
Expand Down Expand Up @@ -334,11 +335,28 @@ private boolean catchUpWithMaster( UpdatePuller updatePuller ) throws IllegalArg

private URI createHaURI( URI me, Server<?,?> server )
{
String hostString = ServerUtil.getHostString( server.getSocketAddress() );
int port = server.getSocketAddress().getPort();
InetSocketAddress serverSocketAddress = server.getSocketAddress();
String hostString = ServerUtil.getHostString( serverSocketAddress );

String host = isWildcard( hostString ) ? me.getHost() : hostString;
host = ensureWrapForIpv6Uri( host );

InstanceId serverId = config.get( ClusterSettings.server_id );
String host = hostString.contains( HighAvailabilityModeSwitcher.INADDR_ANY ) ? me.getHost() : hostString;
return URI.create( "ha://" + host + ":" + port + "?serverId=" + serverId );
return URI.create( "ha://" + host + ":" + serverSocketAddress.getPort() + "?serverId=" + serverId );
}

private String ensureWrapForIpv6Uri( String host )
{
if ( host.contains( ":" ) && !host.contains( "[" ) )
{
host = "[" + host + "]";
}
return host;
}

private static boolean isWildcard( String hostString )
{
return hostString.contains( "0.0.0.0" ) || hostString.contains( "::" ) || hostString.contains( "0:0:0:0:0:0:0:0" );
}

MasterClient newMasterClient( URI masterUri, URI me, StoreId storeId, LifeSupport life )
Expand Down
Expand Up @@ -29,11 +29,13 @@

import org.neo4j.cluster.ClusterSettings;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.HighlyAvailableGraphDatabaseFactory;
import org.neo4j.test.rule.TestDirectory;

import static org.junit.Assume.assumeTrue;

/**
* Test various IPv6 configuration options on a single HA instance.
*/
public class HaIPv6ConfigurationTest
{
@Rule
Expand All @@ -46,7 +48,7 @@ public void testClusterWithLocalhostAddresses() throws Throwable
.newEmbeddedDatabaseBuilder( dir.makeGraphDbDir() )
.setConfig( ClusterSettings.cluster_server, ipv6HostPortSetting( "::1", 5000 ) )
.setConfig( ClusterSettings.initial_hosts, ipv6HostPortSetting( "::1", 5000 ) )
.setConfig( HaSettings.ha_server, ipv6HostPortSetting( "::", 6000 ) )
.setConfig( HaSettings.ha_server, ipv6HostPortSetting( "::1", 6000 ) )
.setConfig( ClusterSettings.server_id, "1" )
.newGraphDatabase();

Expand All @@ -62,8 +64,7 @@ public void testClusterWithLocalhostAddresses() throws Throwable
@Test
public void testClusterWithLinkLocalAddress() throws Throwable
{
boolean foundAnIpv6LinkLocalAddress = false;
InetAddress inetAddress = null;
InetAddress inetAddress;

Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
while ( nics.hasMoreElements() )
Expand All @@ -73,16 +74,16 @@ public void testClusterWithLinkLocalAddress() throws Throwable
while ( inetAddresses.hasMoreElements() )
{
inetAddress = inetAddresses.nextElement();
if ( inetAddress instanceof Inet6Address && inetAddress.isLinkLocalAddress() )
if ( inetAddress instanceof Inet6Address && inetAddress.isLinkLocalAddress() && inetAddress.isReachable( 1000 ) )
{
foundAnIpv6LinkLocalAddress = true;
break;
testWithAddress( inetAddress );
}
}
}
}

assumeTrue( foundAnIpv6LinkLocalAddress );

private void testWithAddress( InetAddress inetAddress ) throws Exception
{
GraphDatabaseService db = new HighlyAvailableGraphDatabaseFactory()
.newEmbeddedDatabaseBuilder( dir.makeGraphDbDir() )
.setConfig( ClusterSettings.cluster_server, ipv6HostPortSetting( inetAddress.getHostAddress(), 5000 ) )
Expand All @@ -91,6 +92,12 @@ public void testClusterWithLinkLocalAddress() throws Throwable
.setConfig( ClusterSettings.server_id, "1" )
.newGraphDatabase();

try ( Transaction tx = db.beginTx() )
{
db.createNode();
tx.success();
}

db.shutdown();
}

Expand All @@ -105,6 +112,12 @@ public void testClusterWithWildcardAddresses() throws Throwable
.setConfig( ClusterSettings.server_id, "1" )
.newGraphDatabase();

try ( Transaction tx = db.beginTx() )
{
db.createNode();
tx.success();
}

db.shutdown();
}

Expand Down
Expand Up @@ -55,6 +55,25 @@ public void switchToMasterShouldUseConfigSettingIfSuitable() throws Exception
assertEquals( "Wrong address", "ha://192.168.1.99:6001?serverId=1", result.toString() );
}

@Test
public void switchToMasterShouldUseIPv6ConfigSettingIfSuitable() throws Exception
{
// given
Config config = new Config(
stringMap( ClusterSettings.server_id.name(), "1", HaSettings.ha_server.name(), "[fe80::1]:6001" ) );
URI me = new URI( "ha://[::1]" );

MasterServer masterServer = mock( MasterServer.class );

// when
when( masterServer.getSocketAddress() ).thenReturn( new InetSocketAddress( "[fe80::1]", 6001 ) );

URI result = SwitchToMaster.getMasterUri( me, masterServer, config );

// then
assertEquals( "Wrong address", "ha://[fe80::1]:6001?serverId=1", result.toString() );
}

@Test
public void switchToMasterShouldIgnoreWildcardInConfig() throws Exception
{
Expand Down Expand Up @@ -84,6 +103,35 @@ public void switchToMasterShouldIgnoreWildcardInConfig() throws Exception
assertEquals( "Wrong address", "ha://127.0.0.1:6001?serverId=1", result.toString() );
}

@Test
public void switchToMasterShouldIgnoreIPv6WildcardInConfig() throws Exception
{
// SwitchToMaster is used to advertise to the rest of the cluster and advertising 0.0.0.0 makes no sense

// given
Config config = new Config(
stringMap( ClusterSettings.server_id.name(), "1", HaSettings.ha_server.name(), "[::]:6001" ) );
URI me = new URI( "ha://[::1]" );

MasterServer masterServer = mock( MasterServer.class );

// when
when( masterServer.getSocketAddress() ).thenReturn( new InetSocketAddress( "[fe80::1]", 6001 ) );

URI result = SwitchToMaster.getMasterUri( me, masterServer, config );

// then
assertEquals( "Wrong address", "ha://[fe80:0:0:0:0:0:0:1]:6001?serverId=1", result.toString() );

// when masterServer is 0.0.0.0
when( masterServer.getSocketAddress() ).thenReturn( new InetSocketAddress( 6001 ) );

result = SwitchToMaster.getMasterUri( me, masterServer, config );

// then
assertEquals( "Wrong address", "ha://[::1]:6001?serverId=1", result.toString() );
}

@Test
public void switchToMasterShouldHandleNoIpInConfig() throws Exception
{
Expand Down

0 comments on commit 169d4b6

Please sign in to comment.