Add ec2 specific network hosts, closes #1037.
This commit is contained in:
parent
e1514aa8e0
commit
abd38720f1
|
@ -26,8 +26,10 @@ import com.amazonaws.services.ec2.AmazonEC2;
|
|||
import com.amazonaws.services.ec2.AmazonEC2Client;
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
||||
import org.elasticsearch.cloud.aws.network.Ec2NameResolver;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.network.NetworkService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsFilter;
|
||||
|
||||
|
@ -38,10 +40,11 @@ public class AwsEc2Service extends AbstractLifecycleComponent<AwsEc2Service> {
|
|||
|
||||
private AmazonEC2Client client;
|
||||
|
||||
@Inject public AwsEc2Service(Settings settings, SettingsFilter settingsFilter) {
|
||||
@Inject public AwsEc2Service(Settings settings, SettingsFilter settingsFilter, NetworkService networkService) {
|
||||
super(settings);
|
||||
|
||||
settingsFilter.addFilter(new AwsSettingsFilter());
|
||||
// add specific ec2 name resolver
|
||||
networkService.addCustomNameResolver(new Ec2NameResolver(settings));
|
||||
}
|
||||
|
||||
public synchronized AmazonEC2 client() {
|
||||
|
|
|
@ -19,118 +19,121 @@
|
|||
|
||||
package org.elasticsearch.cloud.aws.network;
|
||||
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.io.Closeables;
|
||||
import org.elasticsearch.common.network.NetworkService.CustomNameResolver;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.network.NetworkService.CustomNameResolver;
|
||||
import java.net.URLConnection;
|
||||
|
||||
/**
|
||||
* Resolves certain ec2 related 'meta' hostnames into an actual hostname
|
||||
* obtained from ec2 meta-data.
|
||||
* <p />
|
||||
* <p />
|
||||
* Valid config values for {@link Ec2HostnameType}s are -
|
||||
* <ul>
|
||||
* <li>_ec2_ - maps to privateIpv4</li>
|
||||
* <li>_ec2:privateIp_ - maps to privateIpv4</li>
|
||||
* <li>_ec2:privateIpv4_</li>
|
||||
* <li>_ec2:privateDns_</li>
|
||||
* <li>_ec2:publicIp_ - maps to publicIpv4</li>
|
||||
* <li>_ec2:publicIpv4_</li>
|
||||
* <li>_ec2:publicDns_</li>
|
||||
* <li>_ec2_ - maps to privateIpv4</li>
|
||||
* <li>_ec2:privateIp_ - maps to privateIpv4</li>
|
||||
* <li>_ec2:privateIpv4_</li>
|
||||
* <li>_ec2:privateDns_</li>
|
||||
* <li>_ec2:publicIp_ - maps to publicIpv4</li>
|
||||
* <li>_ec2:publicIpv4_</li>
|
||||
* <li>_ec2:publicDns_</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Paul_Loy (keteracel)
|
||||
*/
|
||||
public class Ec2NameResolver implements CustomNameResolver {
|
||||
public class Ec2NameResolver extends AbstractComponent implements CustomNameResolver {
|
||||
|
||||
/**
|
||||
* enum that can be added to over time with more meta-data types (such as ipv6 when this is available)
|
||||
*
|
||||
* @author Paul_Loy
|
||||
*/
|
||||
private static enum Ec2HostnameType {
|
||||
/**
|
||||
* enum that can be added to over time with more meta-data types (such as ipv6 when this is available)
|
||||
*
|
||||
* @author Paul_Loy
|
||||
*/
|
||||
private static enum Ec2HostnameType {
|
||||
|
||||
PRIVATE_IPv4("ec2:privateIpv4", "local-ipv4"),
|
||||
PRIVATE_DNS ("ec2:privateDns", "local-hostname"),
|
||||
PUBLIC_IPv4 ("ec2:publicIpv4", "public-ipv4"),
|
||||
PUBLIC_DNS ("ec2:publicDns", "public-hostname"),
|
||||
PRIVATE_IPv4("ec2:privateIpv4", "local-ipv4"),
|
||||
PRIVATE_DNS("ec2:privateDns", "local-hostname"),
|
||||
PUBLIC_IPv4("ec2:publicIpv4", "public-ipv4"),
|
||||
PUBLIC_DNS("ec2:publicDns", "public-hostname"),
|
||||
|
||||
// some less verbose defaults
|
||||
PUBLIC_IP ("ec2:publicIp", PUBLIC_IPv4.ec2Name),
|
||||
PRIVATE_IP ("ec2:privateIp", PRIVATE_IPv4.ec2Name),
|
||||
DEFAULT ("ec2", PRIVATE_IPv4.ec2Name);
|
||||
// some less verbose defaults
|
||||
PUBLIC_IP("ec2:publicIp", PUBLIC_IPv4.ec2Name),
|
||||
PRIVATE_IP("ec2:privateIp", PRIVATE_IPv4.ec2Name),
|
||||
EC2("ec2", PRIVATE_IPv4.ec2Name);
|
||||
|
||||
final String configName;
|
||||
final String ec2Name;
|
||||
final String configName;
|
||||
final String ec2Name;
|
||||
|
||||
private Ec2HostnameType(String configName, String ec2Name) {
|
||||
this.configName = configName;
|
||||
this.ec2Name = ec2Name;
|
||||
}
|
||||
private Ec2HostnameType(String configName, String ec2Name) {
|
||||
this.configName = configName;
|
||||
this.ec2Name = ec2Name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static final String EC2_METADATA_URL = "http://169.254.169.254/latest/meta-data/";
|
||||
|
||||
private static final String EC2_METADATA_URL = "http://169.254.169.254/latest/meta-data/";
|
||||
private final ESLogger logger;
|
||||
/**
|
||||
* Construct a {@link CustomNameResolver}.
|
||||
*/
|
||||
public Ec2NameResolver(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link CustomNameResolver}.
|
||||
*
|
||||
*/
|
||||
public Ec2NameResolver() {
|
||||
logger = Loggers.getLogger(getClass());
|
||||
}
|
||||
/**
|
||||
* @param type the ec2 hostname type to discover.
|
||||
* @return the appropriate host resolved from ec2 meta-data.
|
||||
* @throws IOException if ec2 meta-data cannot be obtained.
|
||||
* @see CustomNameResolver#resolveIfPossible(String)
|
||||
*/
|
||||
public InetAddress resolve(Ec2HostnameType type, boolean warnOnFailure) {
|
||||
URLConnection urlConnection = null;
|
||||
InputStream in = null;
|
||||
try {
|
||||
URL url = new URL(EC2_METADATA_URL + type.ec2Name);
|
||||
logger.debug("obtaining ec2 hostname from ec2 meta-data url {}", url);
|
||||
urlConnection = url.openConnection();
|
||||
urlConnection.setConnectTimeout(2000);
|
||||
in = urlConnection.getInputStream();
|
||||
BufferedReader urlReader = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
/**
|
||||
* @param type the ec2 hostname type to discover.
|
||||
* @return the appropriate host resolved from ec2 meta-data.
|
||||
* @throws IOException if ec2 meta-data cannot be obtained.
|
||||
*
|
||||
* @see CustomNameResolver#resolveIfPossible(String)
|
||||
*/
|
||||
public InetAddress resolve(Ec2HostnameType type) {
|
||||
try {
|
||||
URL url = new URL(EC2_METADATA_URL + type.ec2Name);
|
||||
logger.info("obtaining ec2 hostname from ec2 meta-data url {}", url);
|
||||
BufferedReader urlReader = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
String metadataResult = urlReader.readLine();
|
||||
if (metadataResult == null || metadataResult.length() == 0) {
|
||||
logger.error("no ec2 metadata returned from {}", url);
|
||||
return null;
|
||||
}
|
||||
return InetAddress.getByName(metadataResult);
|
||||
} catch (IOException e) {
|
||||
if (warnOnFailure) {
|
||||
logger.warn("failed to get metadata for [" + type.configName + "]: " + ExceptionsHelper.detailedMessage(e));
|
||||
} else {
|
||||
logger.debug("failed to get metadata for [" + type.configName + "]: " + ExceptionsHelper.detailedMessage(e));
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
Closeables.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
String metadataResult = urlReader.readLine();
|
||||
if (metadataResult == null || metadataResult.length() == 0) {
|
||||
logger.error("no ec2 metadata returned from {}", url);
|
||||
return null;
|
||||
}
|
||||
return InetAddress.getByName(metadataResult);
|
||||
} catch (IOException e) {
|
||||
logger.error("exception obtaining metadata", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override public InetAddress resolveDefault() {
|
||||
return null; // using this, one has to explicitly specify _ec2_ in network setting
|
||||
// return resolve(Ec2HostnameType.DEFAULT, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.elasticsearch.common.network.NetworkService.CustomNameResolver#resolveDefault()
|
||||
*/
|
||||
@Override
|
||||
public InetAddress resolveDefault() {
|
||||
return resolve(Ec2HostnameType.DEFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.elasticsearch.common.network.NetworkService.CustomNameResolver#resolveIfPossible(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public InetAddress resolveIfPossible(String value) {
|
||||
for (Ec2HostnameType type : Ec2HostnameType.values()) {
|
||||
if (type.configName.equals(value)) {
|
||||
return resolve(type);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override public InetAddress resolveIfPossible(String value) {
|
||||
for (Ec2HostnameType type : Ec2HostnameType.values()) {
|
||||
if (type.configName.equals(value)) {
|
||||
return resolve(type, true);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,12 +20,10 @@
|
|||
package org.elasticsearch.discovery.ec2;
|
||||
|
||||
import org.elasticsearch.cloud.aws.AwsEc2Service;
|
||||
import org.elasticsearch.cloud.aws.network.Ec2NameResolver;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.common.collect.ImmutableList;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.network.NetworkService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.discovery.zen.ZenDiscovery;
|
||||
import org.elasticsearch.discovery.zen.ping.ZenPing;
|
||||
|
@ -39,31 +37,27 @@ import org.elasticsearch.transport.TransportService;
|
|||
*/
|
||||
public class Ec2Discovery extends ZenDiscovery {
|
||||
|
||||
@Inject public Ec2Discovery(Settings settings, ClusterName clusterName, ThreadPool threadPool, TransportService transportService,
|
||||
ClusterService clusterService, ZenPingService pingService, AwsEc2Service ec2Service, NetworkService networkService) {
|
||||
super(settings, clusterName, threadPool, transportService, clusterService, pingService);
|
||||
if (settings.getAsBoolean("cloud.enabled", true)) {
|
||||
@Inject public Ec2Discovery(Settings settings, ClusterName clusterName, ThreadPool threadPool, TransportService transportService,
|
||||
ClusterService clusterService, ZenPingService pingService, AwsEc2Service ec2Service) {
|
||||
super(settings, clusterName, threadPool, transportService, clusterService, pingService);
|
||||
if (settings.getAsBoolean("cloud.enabled", true)) {
|
||||
ImmutableList<? extends ZenPing> zenPings = pingService.zenPings();
|
||||
UnicastZenPing unicastZenPing = null;
|
||||
for (ZenPing zenPing : zenPings) {
|
||||
if (zenPing instanceof UnicastZenPing) {
|
||||
unicastZenPing = (UnicastZenPing) zenPing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add ec2 hostname resolvers to NetworkService issue#940
|
||||
networkService.addCustomNameResolver(new Ec2NameResolver());
|
||||
|
||||
ImmutableList<? extends ZenPing> zenPings = pingService.zenPings();
|
||||
UnicastZenPing unicastZenPing = null;
|
||||
for (ZenPing zenPing : zenPings) {
|
||||
if (zenPing instanceof UnicastZenPing) {
|
||||
unicastZenPing = (UnicastZenPing) zenPing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unicastZenPing != null) {
|
||||
// update the unicast zen ping to add cloud hosts provider
|
||||
// and, while we are at it, use only it and not the multicast for example
|
||||
unicastZenPing.addHostsProvider(new AwsEc2UnicastHostsProvider(settings, transportService, ec2Service.client()));
|
||||
pingService.zenPings(ImmutableList.of(unicastZenPing));
|
||||
} else {
|
||||
logger.warn("failed to apply ec2 unicast discovery, no unicast ping found");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unicastZenPing != null) {
|
||||
// update the unicast zen ping to add cloud hosts provider
|
||||
// and, while we are at it, use only it and not the multicast for example
|
||||
unicastZenPing.addHostsProvider(new AwsEc2UnicastHostsProvider(settings, transportService, ec2Service.client()));
|
||||
pingService.zenPings(ImmutableList.of(unicastZenPing));
|
||||
} else {
|
||||
logger.warn("failed to apply ec2 unicast discovery, no unicast ping found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue