| /* |
| * 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.spi.discovery.tcp.ipfinder.elb; |
| |
| import java.net.InetSocketAddress; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| import com.amazonaws.auth.AWSCredentialsProvider; |
| import com.amazonaws.services.ec2.AmazonEC2; |
| import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; |
| import com.amazonaws.services.ec2.model.DescribeInstancesRequest; |
| import com.amazonaws.services.ec2.model.Reservation; |
| import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancing; |
| import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingClientBuilder; |
| import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersRequest; |
| import com.amazonaws.services.elasticloadbalancing.model.Instance; |
| import com.amazonaws.services.elasticloadbalancing.model.LoadBalancerDescription; |
| import org.apache.ignite.spi.IgniteSpiConfiguration; |
| import org.apache.ignite.spi.IgniteSpiException; |
| import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinderAdapter; |
| |
| import static com.amazonaws.util.StringUtils.isNullOrEmpty; |
| |
| /** |
| * AWS Classic load balancer based IP finder. |
| * |
| * <p> |
| * For information about Amazon Classic load balancers visit: |
| * <a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/introduction.html">aws.amazon.com</a>. |
| * </p> |
| * |
| * <h1 class="header">Configuration</h1> |
| * <h2 class="header">Mandatory</h2> |
| * <ul> |
| * <li>{@link #setCredentialsProvider(AWSCredentialsProvider)}</li> |
| * <li>Classic load balancer name (see {@link #setLoadBalancerName(String)})</li> |
| * <li>Classic load balancer region (see {@link #setRegion(String)})</li> |
| * </ul> |
| * |
| * <p> The finder will fetch all nodes connected under an Classic load balancer and share with its peers for cluster |
| * awareness.</p> |
| * |
| * <p> Note that using AWS Classic load balancer service will result in charges to your AWS account.</p> |
| * |
| * <p> |
| * Choose another implementation of {@link org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder} |
| * for local or home network tests.</p> |
| * |
| * <p> Note that this finder is shared.</p> |
| * |
| * <p> Note that this finder can only be used on AWS EC2 instances that belong on a Load Balancer based auto scaling group.</p> |
| * |
| * @see TcpDiscoveryAlbIpFinder |
| */ |
| public class TcpDiscoveryElbIpFinder extends TcpDiscoveryIpFinderAdapter { |
| /** */ |
| private AmazonElasticLoadBalancing amazonELBClient; |
| |
| /** */ |
| private AmazonEC2 amazonEC2Client; |
| |
| /** */ |
| private AWSCredentialsProvider credsProvider; |
| |
| /** */ |
| private String region; |
| |
| /** */ |
| private String loadBalancerName; |
| |
| /** |
| * Creates Classic load balancer IP finder instance. |
| */ |
| public TcpDiscoveryElbIpFinder() { |
| setShared(true); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Collection<InetSocketAddress> getRegisteredAddresses() throws IgniteSpiException { |
| initClients(); |
| |
| List<String> instanceIds = new ArrayList<>(); |
| |
| DescribeLoadBalancersRequest req = new DescribeLoadBalancersRequest().withLoadBalancerNames(loadBalancerName); |
| |
| List<LoadBalancerDescription> descs = amazonELBClient.describeLoadBalancers(req).getLoadBalancerDescriptions(); |
| |
| for (LoadBalancerDescription desc : descs) { |
| for (Instance instance : desc.getInstances()) |
| instanceIds.add(instance.getInstanceId()); |
| } |
| |
| DescribeInstancesRequest instReq = new DescribeInstancesRequest().withInstanceIds(instanceIds); |
| |
| List<Reservation> reservations = amazonEC2Client.describeInstances(instReq).getReservations(); |
| |
| List<InetSocketAddress> addrs = new ArrayList<>(); |
| |
| for (Reservation reservation : reservations) { |
| List<com.amazonaws.services.ec2.model.Instance> instances = reservation.getInstances(); |
| |
| for (com.amazonaws.services.ec2.model.Instance instance : instances) |
| addrs.add(new InetSocketAddress(instance.getPrivateIpAddress(), 0)); |
| } |
| |
| return addrs; |
| } |
| |
| /** |
| * Initializing the IP finder. |
| */ |
| private void initClients() { |
| if (credsProvider == null || isNullOrEmpty(loadBalancerName) || isNullOrEmpty(region)) |
| throw new IgniteSpiException("One or more configuration parameters are invalid [setCredentialsProvider=" + |
| credsProvider + ", setRegion=" + region + ", setLoadBalancerName=" + |
| loadBalancerName + "]"); |
| |
| if (amazonEC2Client == null) |
| amazonEC2Client = AmazonEC2ClientBuilder.standard().withRegion(region).withCredentials(credsProvider) |
| .build(); |
| |
| if (amazonELBClient == null) |
| amazonELBClient = AmazonElasticLoadBalancingClientBuilder.standard().withRegion(region) |
| .withCredentials(credsProvider).build(); |
| } |
| |
| /** |
| * Sets AWS Classic load balancer name which nodes are plugged under it. For details refer to Amazon API |
| * reference. |
| * |
| * @param loadBalancerName AWS Classic load balancer name. |
| */ |
| @IgniteSpiConfiguration(optional = false) |
| public void setLoadBalancerName(String loadBalancerName) { |
| this.loadBalancerName = loadBalancerName; |
| } |
| |
| /** |
| * Sets Classic load balancer's region. |
| * |
| * For details refer to Amazon API reference. |
| * |
| * @param region AWS Classic load balancer region (i.e: us-east-1) |
| */ |
| @IgniteSpiConfiguration(optional = false) |
| public void setRegion(String region) { |
| this.region = region; |
| } |
| |
| /** |
| * Sets AWS credentials provider. |
| * |
| * For details refer to Amazon API reference. |
| * |
| * @param credsProvider AWS credentials provider. |
| */ |
| @IgniteSpiConfiguration(optional = false) |
| public void setCredentialsProvider(AWSCredentialsProvider credsProvider) { |
| this.credsProvider = credsProvider; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void registerAddresses(Collection<InetSocketAddress> addrs) throws IgniteSpiException { |
| //No-op, Classic load balancer will take care of registration. |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void unregisterAddresses(Collection<InetSocketAddress> addrs) throws IgniteSpiException { |
| // No-op, Classic load balancer will take care of this process. |
| } |
| } |