From 640c7c086b0e2217bba3563deafb7cf08bf4f892 Mon Sep 17 00:00:00 2001 From: zmarois Date: Thu, 9 Nov 2017 14:30:52 -0500 Subject: [PATCH] Enabling running outside of ASG when using vnodes --- .../netflix/priam/AbstractConfigSource.java | 9 +- .../netflix/priam/CompositeConfigSource.java | 4 +- .../java/com/netflix/priam/IConfigSource.java | 4 +- .../com/netflix/priam/IConfiguration.java | 3 - .../netflix/priam/PropertiesConfigSource.java | 4 +- .../netflix/priam/SimpleDBConfigSource.java | 5 +- .../priam/SystemPropertiesConfigSource.java | 4 +- .../com/netflix/priam/aws/ASGMembership.java | 113 +++++++++++++ ...ership.java => AbstractAWSMembership.java} | 155 ++++++------------ .../priam/aws/EC2InstanceMembership.java | 95 +++++++++++ .../netflix/priam/cli/StaticMembership.java | 15 +- .../priam/defaultimpl/PriamConfiguration.java | 8 +- .../priam/defaultimpl/PriamGuiceModule.java | 4 + .../netflix/priam/identity/DoubleRing.java | 3 +- .../netflix/priam/identity/IMembership.java | 22 +-- .../identity/token/DeadTokenRetriever.java | 33 +--- .../token/PreGeneratedTokenRetriever.java | 4 +- .../com/netflix/priam/FakeConfiguration.java | 6 - .../com/netflix/priam/FakeMembership.java | 19 +-- .../priam/identity/DoubleRingTest.java | 3 +- .../priam/identity/InstanceIdentityTest.java | 3 +- 21 files changed, 294 insertions(+), 222 deletions(-) create mode 100644 priam/src/main/java/com/netflix/priam/aws/ASGMembership.java rename priam/src/main/java/com/netflix/priam/aws/{AWSMembership.java => AbstractAWSMembership.java} (59%) create mode 100644 priam/src/main/java/com/netflix/priam/aws/EC2InstanceMembership.java diff --git a/priam/src/main/java/com/netflix/priam/AbstractConfigSource.java b/priam/src/main/java/com/netflix/priam/AbstractConfigSource.java index 7bdba3025..7ab89ea2f 100644 --- a/priam/src/main/java/com/netflix/priam/AbstractConfigSource.java +++ b/priam/src/main/java/com/netflix/priam/AbstractConfigSource.java @@ -28,12 +28,11 @@ */ public abstract class AbstractConfigSource implements IConfigSource { - private String asgName; private String region; @Override - public void intialize(final String asgName, final String region) { - this.asgName = checkNotNull(asgName, "ASG name is not defined"); + public void intialize(final String appid, final String region) { + checkNotNull(appid, "app name is not defined"); this.region = checkNotNull(region, "Region is not defined"); } @@ -158,10 +157,6 @@ public List getList(String prop, List defaultValue) { return defaultValue; } - protected String getAsgName() { - return asgName; - } - protected String getRegion() { return region; } diff --git a/priam/src/main/java/com/netflix/priam/CompositeConfigSource.java b/priam/src/main/java/com/netflix/priam/CompositeConfigSource.java index ed823b3f7..4965377aa 100644 --- a/priam/src/main/java/com/netflix/priam/CompositeConfigSource.java +++ b/priam/src/main/java/com/netflix/priam/CompositeConfigSource.java @@ -53,10 +53,10 @@ public CompositeConfigSource(final IConfigSource... sources) { } @Override - public void intialize(final String asgName, final String region) { + public void intialize(final String appid, final String region) { for (final IConfigSource source : sources) { //TODO should this catch any potential exceptions? - source.intialize(asgName, region); + source.intialize(appid, region); } } diff --git a/priam/src/main/java/com/netflix/priam/IConfigSource.java b/priam/src/main/java/com/netflix/priam/IConfigSource.java index 58d383aa2..a0f79affa 100644 --- a/priam/src/main/java/com/netflix/priam/IConfigSource.java +++ b/priam/src/main/java/com/netflix/priam/IConfigSource.java @@ -29,10 +29,10 @@ public interface IConfigSource { /** * Must be called before any other method. This method will allow implementations to do any setup that they require * before being called. - * @param asgName: Name of the asg + * @param appid: Name of the cluster * @param region: Name of the region */ - void intialize(String asgName, String region); + void intialize(String appid, String region); /** * A non-negative integer indicating a count of elements. diff --git a/priam/src/main/java/com/netflix/priam/IConfiguration.java b/priam/src/main/java/com/netflix/priam/IConfiguration.java index 61464fe11..333631b17 100644 --- a/priam/src/main/java/com/netflix/priam/IConfiguration.java +++ b/priam/src/main/java/com/netflix/priam/IConfiguration.java @@ -582,9 +582,6 @@ public interface IConfiguration { public boolean getAutoBoostrap(); - //if using with Datastax Enterprise - public String getDseClusterType(); - public boolean isCreateNewTokenEnable(); /* diff --git a/priam/src/main/java/com/netflix/priam/PropertiesConfigSource.java b/priam/src/main/java/com/netflix/priam/PropertiesConfigSource.java index d116379cf..054bb3021 100644 --- a/priam/src/main/java/com/netflix/priam/PropertiesConfigSource.java +++ b/priam/src/main/java/com/netflix/priam/PropertiesConfigSource.java @@ -56,8 +56,8 @@ public PropertiesConfigSource(final Properties properties) { } @Override - public void intialize(final String asgName, final String region) { - super.intialize(asgName, region); + public void intialize(final String appid, final String region) { + super.intialize(appid, region); Properties properties = new Properties(); URL url = PropertiesConfigSource.class.getClassLoader().getResource(priamFile); if (url != null) { diff --git a/priam/src/main/java/com/netflix/priam/SimpleDBConfigSource.java b/priam/src/main/java/com/netflix/priam/SimpleDBConfigSource.java index b376acc80..5108e309d 100644 --- a/priam/src/main/java/com/netflix/priam/SimpleDBConfigSource.java +++ b/priam/src/main/java/com/netflix/priam/SimpleDBConfigSource.java @@ -59,14 +59,13 @@ public SimpleDBConfigSource(final ICredential provider) { } @Override - public void intialize(final String asgName, final String region) { - super.intialize(asgName, region); + public void intialize(final String appid, final String region) { + super.intialize(appid, region); // End point is us-east-1 AmazonSimpleDB simpleDBClient = AmazonSimpleDBClient.builder().withCredentials(provider.getAwsCredentialProvider()).build(); String nextToken = null; - String appid = asgName.lastIndexOf('-') > 0 ? asgName.substring(0, asgName.indexOf('-')) : asgName; logger.info("appid used to fetch properties is: {}", appid); do { SelectRequest request = new SelectRequest(String.format(ALL_QUERY, appid)); diff --git a/priam/src/main/java/com/netflix/priam/SystemPropertiesConfigSource.java b/priam/src/main/java/com/netflix/priam/SystemPropertiesConfigSource.java index b5ae924b6..31f0af7db 100644 --- a/priam/src/main/java/com/netflix/priam/SystemPropertiesConfigSource.java +++ b/priam/src/main/java/com/netflix/priam/SystemPropertiesConfigSource.java @@ -34,8 +34,8 @@ public final class SystemPropertiesConfigSource extends AbstractConfigSource { private final Map data = Maps.newConcurrentMap(); @Override - public void intialize(final String asgName, final String region) { - super.intialize(asgName, region); + public void intialize(final String appid, final String region) { + super.intialize(appid, region); Properties systemProps = System.getProperties(); diff --git a/priam/src/main/java/com/netflix/priam/aws/ASGMembership.java b/priam/src/main/java/com/netflix/priam/aws/ASGMembership.java new file mode 100644 index 000000000..bd4a7a75e --- /dev/null +++ b/priam/src/main/java/com/netflix/priam/aws/ASGMembership.java @@ -0,0 +1,113 @@ +/* + * Copyright 2013 Netflix, Inc. + * + * Licensed 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 com.netflix.priam.aws; + +import com.amazonaws.services.autoscaling.AmazonAutoScaling; +import com.amazonaws.services.autoscaling.AmazonAutoScalingClient; +import com.amazonaws.services.autoscaling.model.*; +import com.amazonaws.services.autoscaling.model.Instance; +import com.amazonaws.services.ec2.AmazonEC2; +import com.amazonaws.services.ec2.AmazonEC2Client; +import com.amazonaws.services.ec2.model.*; +import com.amazonaws.services.ec2.model.Filter; +import com.google.common.collect.Lists; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import com.netflix.priam.IConfiguration; +import com.netflix.priam.ICredential; +import com.netflix.priam.identity.IMembership; +import com.netflix.priam.identity.InstanceEnvIdentity; +import com.netflix.priam.identity.PriamInstance; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Class to query amazon ASG for its members to provide - Number of valid nodes + * in the ASG - Number of zones - Methods for adding ACLs for the nodes + */ +public class ASGMembership extends AbstractAWSMembership { + private static final Logger logger = LoggerFactory.getLogger(ASGMembership.class); + private final ICredential thisAccountProvider; + + @Inject + public ASGMembership(IConfiguration config, ICredential provider, @Named("awsec2roleassumption") ICredential crossAccountProvider, InstanceEnvIdentity insEnvIdentity) { + super(config, provider, crossAccountProvider, insEnvIdentity); + this.thisAccountProvider = provider; + } + + @Override + protected List getLiveInstances(ICredential provider) { + AmazonAutoScaling client = null; + try { + List asgNames = new ArrayList<>(); + asgNames.add(config.getASGName()); + asgNames.addAll(Arrays.asList(config.getSiblingASGNames().split("\\s*,\\s*"))); + client = getAutoScalingClient(provider); + DescribeAutoScalingGroupsRequest asgReq = new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(asgNames.toArray(new String[asgNames.size()])); + DescribeAutoScalingGroupsResult res = client.describeAutoScalingGroups(asgReq); + + List instanceIds = Lists.newArrayList(); + for (AutoScalingGroup asg : res.getAutoScalingGroups()) { + for (Instance ins : asg.getInstances()) + if (isInstanceStateLive(ins.getLifecycleState())) + instanceIds.add(ins.getInstanceId()); + } + if (logger.isInfoEnabled()) { + logger.info(String.format("Querying Amazon returned following instance in the RAC: %s, ASGs: %s --> %s", config.getRac(), StringUtils.join(asgNames, ","), StringUtils.join(instanceIds, ","))); + } + return instanceIds; + } finally { + if (client != null) + client.shutdown(); + } + } + + /** + * Actual membership AWS source of truth... + */ + @Override + public int getRacMembershipSize() { + AmazonAutoScaling client = null; + try { + client = getAutoScalingClient(thisAccountProvider); + DescribeAutoScalingGroupsRequest asgReq = new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(config.getASGName()); + DescribeAutoScalingGroupsResult res = client.describeAutoScalingGroups(asgReq); + int size = 0; + for (AutoScalingGroup asg : res.getAutoScalingGroups()) { + size += asg.getMaxSize(); + } + logger.info("Query on ASG returning {} instances", size); + return size; + } finally { + if (client != null) + client.shutdown(); + } + } + + private AmazonAutoScaling getAutoScalingClient(ICredential provider) + { + AmazonAutoScaling client = new AmazonAutoScalingClient(provider.getAwsCredentialProvider()); + client.setEndpoint("autoscaling." + config.getDC() + ".amazonaws.com"); + return client; + } +} \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/aws/AWSMembership.java b/priam/src/main/java/com/netflix/priam/aws/AbstractAWSMembership.java similarity index 59% rename from priam/src/main/java/com/netflix/priam/aws/AWSMembership.java rename to priam/src/main/java/com/netflix/priam/aws/AbstractAWSMembership.java index 5e675e195..9104fa241 100644 --- a/priam/src/main/java/com/netflix/priam/aws/AWSMembership.java +++ b/priam/src/main/java/com/netflix/priam/aws/AbstractAWSMembership.java @@ -31,6 +31,7 @@ import com.netflix.priam.ICredential; import com.netflix.priam.identity.IMembership; import com.netflix.priam.identity.InstanceEnvIdentity; +import com.netflix.priam.identity.PriamInstance; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,100 +42,68 @@ import java.util.List; /** - * Class to query amazon ASG for its members to provide - Number of valid nodes - * in the ASG - Number of zones - Methods for adding ACLs for the nodes + * Class to query amazon for its members to provide - Number of valid nodes + * in the cluster - Number of zones - Methods for adding ACLs for the nodes */ -public class AWSMembership implements IMembership { - private static final Logger logger = LoggerFactory.getLogger(AWSMembership.class); - private final IConfiguration config; - private final ICredential provider; +public abstract class AbstractAWSMembership implements IMembership { + private static final Logger logger = LoggerFactory.getLogger(AbstractAWSMembership.class); + protected final IConfiguration config; + private final ICredential thisAccountProvider; private final InstanceEnvIdentity insEnvIdentity; private final ICredential crossAccountProvider; @Inject - public AWSMembership(IConfiguration config, ICredential provider, @Named("awsec2roleassumption") ICredential crossAccountProvider, InstanceEnvIdentity insEnvIdentity) { + public AbstractAWSMembership(IConfiguration config, ICredential thisAccountProvider, @Named("awsec2roleassumption") ICredential crossAccountProvider, InstanceEnvIdentity insEnvIdentity) { this.config = config; - this.provider = provider; + this.thisAccountProvider = thisAccountProvider; this.insEnvIdentity = insEnvIdentity; this.crossAccountProvider = crossAccountProvider; } - @Override - public List getRacMembership() { - AmazonAutoScaling client = null; - try { - List asgNames = new ArrayList<>(); - asgNames.add(config.getASGName()); - asgNames.addAll(Arrays.asList(config.getSiblingASGNames().split("\\s*,\\s*"))); - client = getAutoScalingClient(); - DescribeAutoScalingGroupsRequest asgReq = new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(asgNames.toArray(new String[asgNames.size()])); - DescribeAutoScalingGroupsResult res = client.describeAutoScalingGroups(asgReq); - - List instanceIds = Lists.newArrayList(); - for (AutoScalingGroup asg : res.getAutoScalingGroups()) { - for (Instance ins : asg.getInstances()) - if (!(ins.getLifecycleState().equalsIgnoreCase("Terminating") || ins.getLifecycleState().equalsIgnoreCase("shutting-down") || ins.getLifecycleState() - .equalsIgnoreCase("Terminated"))) - instanceIds.add(ins.getInstanceId()); - } - if (logger.isInfoEnabled()) { - logger.info(String.format("Querying Amazon returned following instance in the RAC: %s, ASGs: %s --> %s", config.getRac(), StringUtils.join(asgNames, ","), StringUtils.join(instanceIds, ","))); - } - return instanceIds; - } finally { - if (client != null) - client.shutdown(); - } + abstract protected List getLiveInstances(ICredential provider); + + protected boolean isInstanceStateLive(String lifecycleState) { + return !(lifecycleState.equalsIgnoreCase("Terminating") || + lifecycleState.equalsIgnoreCase("shutting-down") || + lifecycleState.equalsIgnoreCase("Terminated")); } - /** - * Actual membership AWS source of truth... - */ @Override - public int getRacMembershipSize() { - AmazonAutoScaling client = null; - try { - client = getAutoScalingClient(); - DescribeAutoScalingGroupsRequest asgReq = new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(config.getASGName()); - DescribeAutoScalingGroupsResult res = client.describeAutoScalingGroups(asgReq); - int size = 0; - for (AutoScalingGroup asg : res.getAutoScalingGroups()) { - size += asg.getMaxSize(); - } - logger.info("Query on ASG returning {} instances", size); - return size; - } finally { - if (client != null) - client.shutdown(); + public boolean isInstanceAlive(PriamInstance instance) + { + List instances = getLiveInstances(thisAccountProvider); + if (config.isDualAccount()) { + instances = getDualAccountLiveInstances(instances); + } else { + logger.info("Single Account cluster"); } + + return instances.contains(instance.getInstanceId()); } - @Override - public List getCrossAccountRacMembership() { - AmazonAutoScaling client = null; - try { - List asgNames = new ArrayList<>(); - asgNames.add(config.getASGName()); - asgNames.addAll(Arrays.asList(config.getSiblingASGNames().split("\\s*,\\s*"))); - client = getCrossAccountAutoScalingClient(); - DescribeAutoScalingGroupsRequest asgReq = new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(asgNames.toArray(new String[asgNames.size()])); - DescribeAutoScalingGroupsResult res = client.describeAutoScalingGroups(asgReq); - - List instanceIds = Lists.newArrayList(); - for (AutoScalingGroup asg : res.getAutoScalingGroups()) { - for (Instance ins : asg.getInstances()) - if (!(ins.getLifecycleState().equalsIgnoreCase("Terminating") || ins.getLifecycleState().equalsIgnoreCase("shutting-down") || ins.getLifecycleState() - .equalsIgnoreCase("Terminated"))) - instanceIds.add(ins.getInstanceId()); - } - if (logger.isInfoEnabled()) { - logger.info(String.format("Querying Amazon returned following instance in the cross-account ASG: %s --> %s", config.getRac(), StringUtils.join(instanceIds, ","))); + private List getDualAccountLiveInstances(List instances) { + logger.info("Dual Account cluster"); + + List crossAccountInstances = getLiveInstances(crossAccountProvider); + + if (logger.isInfoEnabled()) { + if (insEnvIdentity.isClassic()) { + logger.info("EC2 classic instances (local account): " + Arrays.toString(instances.toArray())); + logger.info("VPC Account (cross-account): " + Arrays.toString(crossAccountInstances.toArray())); + } else { + logger.info("VPC Account (local account): " + Arrays.toString(instances.toArray())); + logger.info("EC2 classic instances (cross-account): " + Arrays.toString(crossAccountInstances.toArray())); } - return instanceIds; - } finally { - if (client != null) - client.shutdown(); } + + // Remove duplicates (probably there are not) + instances.removeAll(crossAccountInstances); + + // Merge the two lists + instances.addAll(crossAccountInstances); + logger.info("Combined Instances in the AZ: {}", instances); + + return instances; } @Override @@ -274,39 +243,11 @@ public List listACL(int from, int to) { } } - @Override - public void expandRacMembership(int count) { - AmazonAutoScaling client = null; - try { - client = getAutoScalingClient(); - DescribeAutoScalingGroupsRequest asgReq = new DescribeAutoScalingGroupsRequest().withAutoScalingGroupNames(config.getASGName()); - DescribeAutoScalingGroupsResult res = client.describeAutoScalingGroups(asgReq); - AutoScalingGroup asg = res.getAutoScalingGroups().get(0); - UpdateAutoScalingGroupRequest ureq = new UpdateAutoScalingGroupRequest(); - ureq.setAutoScalingGroupName(asg.getAutoScalingGroupName()); - ureq.setMinSize(asg.getMinSize() + 1); - ureq.setMaxSize(asg.getMinSize() + 1); - ureq.setDesiredCapacity(asg.getMinSize() + 1); - client.updateAutoScalingGroup(ureq); - } finally { - if (client != null) - client.shutdown(); - } - } - - protected AmazonAutoScaling getAutoScalingClient() { - AmazonAutoScaling client = new AmazonAutoScalingClient(provider.getAwsCredentialProvider()); - client.setEndpoint("autoscaling." + config.getDC() + ".amazonaws.com"); - return client; - } - - protected AmazonAutoScaling getCrossAccountAutoScalingClient() { - AmazonAutoScaling client = new AmazonAutoScalingClient(crossAccountProvider.getAwsCredentialProvider()); - client.setEndpoint("autoscaling." + config.getDC() + ".amazonaws.com"); - return client; + private AmazonEC2 getEc2Client() { + return getEc2Client(thisAccountProvider); } - protected AmazonEC2 getEc2Client() { + protected AmazonEC2 getEc2Client(ICredential provider) { AmazonEC2 client = new AmazonEC2Client(provider.getAwsCredentialProvider()); client.setEndpoint("ec2." + config.getDC() + ".amazonaws.com"); return client; diff --git a/priam/src/main/java/com/netflix/priam/aws/EC2InstanceMembership.java b/priam/src/main/java/com/netflix/priam/aws/EC2InstanceMembership.java new file mode 100644 index 000000000..e70131935 --- /dev/null +++ b/priam/src/main/java/com/netflix/priam/aws/EC2InstanceMembership.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013 Netflix, Inc. + * + * Licensed 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 com.netflix.priam.aws; + +import com.amazonaws.services.autoscaling.AmazonAutoScaling; +import com.amazonaws.services.autoscaling.model.AutoScalingGroup; +import com.amazonaws.services.autoscaling.model.DescribeAutoScalingGroupsRequest; +import com.amazonaws.services.autoscaling.model.DescribeAutoScalingGroupsResult; +import com.amazonaws.services.ec2.AmazonEC2; +import com.amazonaws.services.ec2.model.DescribeInstancesRequest; +import com.amazonaws.services.ec2.model.DescribeInstancesResult; +import com.amazonaws.services.ec2.model.Instance; +import com.amazonaws.services.ec2.model.Reservation; +import com.google.common.collect.Lists; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import com.netflix.priam.IConfiguration; +import com.netflix.priam.ICredential; +import com.netflix.priam.identity.InstanceEnvIdentity; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Class to query amazon for living ec2 instances that could be members of the cluster + */ +public class EC2InstanceMembership extends AbstractAWSMembership { + private static final Logger logger = LoggerFactory.getLogger(EC2InstanceMembership.class); + + @Inject + public EC2InstanceMembership(IConfiguration config, ICredential provider, @Named("awsec2roleassumption") ICredential crossAccountProvider, InstanceEnvIdentity insEnvIdentity) { + super(config, provider, crossAccountProvider, insEnvIdentity); + } + + @Override + protected List getLiveInstances(ICredential provider) { + AmazonEC2 client = null; + try { + client = getEc2Client(provider); + List instanceIds = Lists.newArrayList(); + String nextToken = null; + do { + DescribeInstancesResult res; + if (nextToken != null){ + res = client.describeInstances(new DescribeInstancesRequest().withNextToken(nextToken)); + } + else { + res = client.describeInstances(); + } + + nextToken = res.getNextToken(); + + for (Reservation reservation : res.getReservations()) + { + for (Instance instance : reservation.getInstances()) + if (isInstanceStateLive(instance.getState().getName())) + instanceIds.add(instance.getInstanceId()); + } + } + while (nextToken != null); + + if (logger.isInfoEnabled()) { + logger.info(String.format("Querying Amazon returned following instance in the RAC: %s, %s", config.getRac(), StringUtils.join(instanceIds, ","))); + } + + return instanceIds; + } finally { + if (client != null) + client.shutdown(); + } + } + + @Override + public int getRacMembershipSize() { + throw new RuntimeException("Cannot get rac membership size when running outside of autoscaling group"); + } +} \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/cli/StaticMembership.java b/priam/src/main/java/com/netflix/priam/cli/StaticMembership.java index 97d34b5d5..cb5ceed53 100644 --- a/priam/src/main/java/com/netflix/priam/cli/StaticMembership.java +++ b/priam/src/main/java/com/netflix/priam/cli/StaticMembership.java @@ -17,6 +17,7 @@ package com.netflix.priam.cli; import com.netflix.priam.identity.IMembership; +import com.netflix.priam.identity.PriamInstance; import org.apache.cassandra.io.util.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,13 +66,9 @@ public StaticMembership() throws IOException { } @Override - public List getRacMembership() { - return racMembership; - } - - @Override - public List getCrossAccountRacMembership() { - return null; + public boolean isInstanceAlive(PriamInstance instance) + { + return racMembership.contains(instance.getInstanceId()); } @Override @@ -98,8 +95,4 @@ public void removeACL(Collection listIPs, int from, int to) { public List listACL(int from, int to) { return null; } - - @Override - public void expandRacMembership(int count) { - } } \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java b/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java index 18fdb84af..820d6ea0d 100644 --- a/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java +++ b/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java @@ -283,7 +283,8 @@ public void intialize() { NETWORK_VPC = instanceDataRetriever.getVpcId(); setupEnvVars(); - this.config.intialize(ASG_NAME, REGION); + String appid = ASG_NAME.lastIndexOf('-') > 0 ? ASG_NAME.substring(0, ASG_NAME.indexOf('-')) : ASG_NAME; + this.config.intialize(appid, REGION); setDefaultRACList(REGION); populateProps(); SystemUtils.createDirs(getBackupCommitLogLocation()); @@ -996,11 +997,6 @@ public boolean getAutoBoostrap() { return config.get(CONFIG_AUTO_BOOTSTRAP, true); } - //values are cassandra, solr, hadoop, spark or hadoop-spark - public String getDseClusterType() { - return config.get(CONFIG_DSE_CLUSTER_TYPE + "." + ASG_NAME, "cassandra"); - } - @Override public boolean isCreateNewTokenEnable() { return config.get(CONFIG_CREATE_NEW_TOKEN_ENABLE, true); diff --git a/priam/src/main/java/com/netflix/priam/defaultimpl/PriamGuiceModule.java b/priam/src/main/java/com/netflix/priam/defaultimpl/PriamGuiceModule.java index 9a57177ce..91abe82bf 100644 --- a/priam/src/main/java/com/netflix/priam/defaultimpl/PriamGuiceModule.java +++ b/priam/src/main/java/com/netflix/priam/defaultimpl/PriamGuiceModule.java @@ -20,6 +20,7 @@ import com.google.inject.name.Names; import com.netflix.priam.ICredential; import com.netflix.priam.ICredentialGeneric; +import com.netflix.priam.aws.ASGMembership; import com.netflix.priam.aws.S3CrossAccountFileSystem; import com.netflix.priam.aws.S3EncryptedFileSystem; import com.netflix.priam.aws.S3FileSystem; @@ -38,6 +39,7 @@ import com.netflix.priam.google.GcsCredential; import com.netflix.priam.google.GoogleEncryptedFileSystem; import com.netflix.priam.identity.AwsInstanceEnvIdentity; +import com.netflix.priam.identity.IMembership; import com.netflix.priam.identity.InstanceEnvIdentity; import com.netflix.priam.identity.token.*; import com.netflix.priam.merics.BackupMetricsMgr; @@ -67,6 +69,8 @@ protected void configure() { { Class credentialImplementation = Class.forName(System.getProperty("ICREDENTIAL_IMPLEMENTATION", ClearCredential.class.getTypeName())); bind(ICredential.class).to(credentialImplementation); + Class membershipImplementation = Class.forName(System.getProperty("IMEMBERSHIP_IMPLEMENTATION", ASGMembership.class.getTypeName())); + bind(IMembership.class).to(membershipImplementation); } catch (ClassNotFoundException e) { diff --git a/priam/src/main/java/com/netflix/priam/identity/DoubleRing.java b/priam/src/main/java/com/netflix/priam/identity/DoubleRing.java index 30a52c0ea..2803bb3e5 100644 --- a/priam/src/main/java/com/netflix/priam/identity/DoubleRing.java +++ b/priam/src/main/java/com/netflix/priam/identity/DoubleRing.java @@ -19,6 +19,7 @@ import com.google.common.collect.Lists; import com.google.inject.Inject; import com.netflix.priam.IConfiguration; +import com.netflix.priam.identity.token.TokenRetrieverBase; import com.netflix.priam.utils.ITokenManager; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; @@ -69,7 +70,7 @@ public void doubleSlots() { int currentSlot = data.getId() - hash; int new_slot = currentSlot + 3 > new_ring_size ? (currentSlot + 3) - new_ring_size : currentSlot + 3; String token = tokenManager.createToken(new_slot, new_ring_size, config.getDC()); - factory.create(data.getApp(), new_slot + hash, InstanceIdentity.DUMMY_INSTANCE_ID, config.getHostname(), config.getHostIP(), data.getRac(), null, token); + factory.create(data.getApp(), new_slot + hash, TokenRetrieverBase.DUMMY_INSTANCE_ID, config.getHostname(), config.getHostIP(), data.getRac(), null, token); } } diff --git a/priam/src/main/java/com/netflix/priam/identity/IMembership.java b/priam/src/main/java/com/netflix/priam/identity/IMembership.java index c1cb26d95..479f65f93 100644 --- a/priam/src/main/java/com/netflix/priam/identity/IMembership.java +++ b/priam/src/main/java/com/netflix/priam/identity/IMembership.java @@ -17,7 +17,7 @@ package com.netflix.priam.identity; import com.google.inject.ImplementedBy; -import com.netflix.priam.aws.AWSMembership; +import com.netflix.priam.aws.ASGMembership; import java.util.Collection; import java.util.List; @@ -26,27 +26,20 @@ * Interface to manage membership meta information such as size of RAC, list of * nodes in RAC etc. Also perform ACL updates used in multi-regional clusters */ -@ImplementedBy(AWSMembership.class) +@ImplementedBy(ASGMembership.class) public interface IMembership { /** - * Get a list of Instances in the current RAC + * Determines if the provided instance is alive * * @return */ - public List getRacMembership(); + public boolean isInstanceAlive(PriamInstance instance); /** * @return Size of current RAC */ public int getRacMembershipSize(); - /** - * Get a list of Instances in the cross-account but current RAC - * - * @return - */ - public List getCrossAccountRacMembership(); - /** * Number of RACs * @@ -78,11 +71,4 @@ public interface IMembership { * @return */ public List listACL(int from, int to); - - /** - * Expand the membership size by 1. - * - * @param count - */ - public void expandRacMembership(int count); } \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java b/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java index 814812b4a..22a451ace 100755 --- a/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java +++ b/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java @@ -62,48 +62,17 @@ public DeadTokenRetriever(IPriamInstanceFactory factory, IMembership membership, this.insEnvIdentity = insEnvIdentity; } - private List getDualAccountRacMembership(List asgInstances) { - logger.info("Dual Account cluster"); - - List crossAccountAsgInstances = membership.getCrossAccountRacMembership(); - - if (logger.isInfoEnabled()) { - if (insEnvIdentity.isClassic()) { - logger.info("EC2 classic instances (local ASG): " + Arrays.toString(asgInstances.toArray())); - logger.info("VPC Account (cross-account ASG): " + Arrays.toString(crossAccountAsgInstances.toArray())); - } else { - logger.info("VPC Account (local ASG): " + Arrays.toString(asgInstances.toArray())); - logger.info("EC2 classic instances (cross-account ASG): " + Arrays.toString(crossAccountAsgInstances.toArray())); - } - } - - // Remove duplicates (probably there are not) - asgInstances.removeAll(crossAccountAsgInstances); - - // Merge the two lists - asgInstances.addAll(crossAccountAsgInstances); - logger.info("Combined Instances in the AZ: {}", asgInstances); - - return asgInstances; - } - @Override public PriamInstance get() throws Exception { logger.info("Looking for a token from any dead node"); final List allIds = factory.getAllIds(config.getAppName()); - List asgInstances = membership.getRacMembership(); - if (config.isDualAccount()) { - asgInstances = getDualAccountRacMembership(asgInstances); - } else { - logger.info("Single Account cluster"); - } // Sleep random interval - upto 15 sec sleeper.sleep(new Random().nextInt(5000) + 10000); for (PriamInstance dead : allIds) { // test same zone and is it is alive. - if (!dead.getRac().equals(config.getRac()) || asgInstances.contains(dead.getInstanceId()) || super.isInstanceDummy(dead)) + if (!dead.getRac().equals(config.getRac()) || membership.isInstanceAlive(dead) || super.isInstanceDummy(dead)) continue; logger.info("Found dead instances: {}", dead.getInstanceId()); PriamInstance markAsDead = factory.create(dead.getApp() + "-dead", dead.getId(), dead.getInstanceId(), dead.getHostName(), dead.getHostIP(), dead.getRac(), dead.getVolumes(), diff --git a/priam/src/main/java/com/netflix/priam/identity/token/PreGeneratedTokenRetriever.java b/priam/src/main/java/com/netflix/priam/identity/token/PreGeneratedTokenRetriever.java index 59a93ff4f..0aece7a53 100755 --- a/priam/src/main/java/com/netflix/priam/identity/token/PreGeneratedTokenRetriever.java +++ b/priam/src/main/java/com/netflix/priam/identity/token/PreGeneratedTokenRetriever.java @@ -50,12 +50,12 @@ public PriamInstance get() throws Exception { logger.info("Looking for any pre-generated token"); final List allIds = factory.getAllIds(config.getAppName()); - List asgInstances = membership.getRacMembership(); + // Sleep random interval - upto 15 sec sleeper.sleep(new Random().nextInt(5000) + 10000); for (PriamInstance dead : allIds) { // test same zone and is it is alive. - if (!dead.getRac().equals(config.getRac()) || asgInstances.contains(dead.getInstanceId()) || !isInstanceDummy(dead)) + if (!dead.getRac().equals(config.getRac()) || membership.isInstanceAlive(dead) || !isInstanceDummy(dead)) continue; logger.info("Found pre-generated token: {}", dead.getToken()); PriamInstance markAsDead = factory.create(dead.getApp() + "-dead", dead.getId(), dead.getInstanceId(), dead.getHostName(), dead.getHostIP(), dead.getRac(), dead.getVolumes(), diff --git a/priam/src/test/java/com/netflix/priam/FakeConfiguration.java b/priam/src/test/java/com/netflix/priam/FakeConfiguration.java index f653aba67..81025a3ca 100644 --- a/priam/src/test/java/com/netflix/priam/FakeConfiguration.java +++ b/priam/src/test/java/com/netflix/priam/FakeConfiguration.java @@ -703,12 +703,6 @@ public boolean getAutoBoostrap() { } @Override - public String getDseClusterType() { - // TODO Auto-generated method stub - return "cassandra"; - } - - @Override public boolean isCreateNewTokenEnable() { return true; //allow Junit test to create new tokens } diff --git a/priam/src/test/java/com/netflix/priam/FakeMembership.java b/priam/src/test/java/com/netflix/priam/FakeMembership.java index fdc999732..11ece815f 100644 --- a/priam/src/test/java/com/netflix/priam/FakeMembership.java +++ b/priam/src/test/java/com/netflix/priam/FakeMembership.java @@ -21,6 +21,7 @@ import java.util.List; import com.netflix.priam.identity.IMembership; +import com.netflix.priam.identity.PriamInstance; public class FakeMembership implements IMembership { @@ -38,17 +39,10 @@ public void setInstances( List priamInstances) } @Override - public List getRacMembership() + public boolean isInstanceAlive(PriamInstance instance) { - return instances; + return instances.contains(instance.getInstanceId()); } - - @Override - public List getCrossAccountRacMembership() - { - return null; - } - @Override public int getRacMembershipSize() @@ -82,11 +76,4 @@ public List listACL(int from, int to) // TODO Auto-generated method stub return null; } - - @Override - public void expandRacMembership(int count) - { - // TODO Auto-generated method stub - - } } diff --git a/priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java b/priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java index a645ff22f..60907138e 100644 --- a/priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java +++ b/priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java @@ -19,6 +19,7 @@ import java.util.List; +import com.netflix.priam.identity.token.TokenRetrieverBase; import org.junit.Test; import com.google.common.collect.Lists; @@ -57,7 +58,7 @@ private void validate(List doubled) int id = ins.getId() - tokenManager.regionOffset(config.getDC()); System.out.println(ins); if (0 != id % 2) - assertEquals(ins.getInstanceId(), InstanceIdentity.DUMMY_INSTANCE_ID); + assertEquals(ins.getInstanceId(), TokenRetrieverBase.DUMMY_INSTANCE_ID); } } diff --git a/priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java b/priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java index 4c952d8cf..f56636c65 100644 --- a/priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java +++ b/priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java @@ -17,6 +17,7 @@ package com.netflix.priam.identity; +import com.netflix.priam.identity.token.TokenRetrieverBase; import org.junit.Test; import java.util.Arrays; @@ -106,7 +107,7 @@ public void testDoubleSlots() throws Exception System.out.println(lst.get(i)); if (0 == i % 2) continue; - assertEquals(InstanceIdentity.DUMMY_INSTANCE_ID, lst.get(i).getInstanceId()); + assertEquals(TokenRetrieverBase.DUMMY_INSTANCE_ID, lst.get(i).getInstanceId()); } assertEquals(before * 2, lst.size()); }