in static/Reliability/300_Testing_for_Resiliency_of_EC2_RDS_and_S3/Code/FailureSimulations/java/appresiliency/src/main/java/com/app/resiliency/AZFailover.java [52:156]
public void failover() {
try {
AmazonAutoScaling autoScalingclient = AmazonAutoScalingClientBuilder.standard().build();
// Modify the autoscaling group to remove the AZ affected which is the AZ passed in the input
// Find the autoscaling group that this is deployed into
if (autoScalingclient.describeAutoScalingGroups() != null
&& autoScalingclient.describeAutoScalingGroups().getAutoScalingGroups().size() > 0) {
// Note: This assumes a group exists for readability
AutoScalingGroup autoScalingGroup = autoScalingclient.describeAutoScalingGroups().getAutoScalingGroups().get(0);
String autoScalingGroupName = autoScalingGroup.getAutoScalingGroupName();
// Find all subnets in the availability zone passed in the input
DescribeSubnetsResult describeSubnetsResult
= EC2_CLIENT.describeSubnets(new DescribeSubnetsRequest().withFilters(
new Filter("vpc-id", Collections.singletonList(vpcId))));
List<String> desiredSubnetsForASG = new ArrayList<>();
for (Subnet subnet : describeSubnetsResult.getSubnets()) {
if (!subnet.getAvailabilityZone().equalsIgnoreCase(azId)) {
desiredSubnetsForASG.add(subnet.getSubnetId());
}
}
String[] vpcZoneIdentifiers = autoScalingGroup.getVPCZoneIdentifier().split(",");
List<String> desiredSubnets = new LinkedList<>(Arrays.asList(vpcZoneIdentifiers));
for (String subnet : desiredSubnets) {
if(!desiredSubnetsForASG.contains(subnet)) {
desiredSubnets.remove(subnet);
}
}
UpdateAutoScalingGroupRequest request = new UpdateAutoScalingGroupRequest().withAutoScalingGroupName(autoScalingGroupName)
.withVPCZoneIdentifier(StringUtils.join(desiredSubnets, ','));
System.out.println("Updating the auto scaling group " + autoScalingGroupName + " to remove the subnet in the AZ");
autoScalingclient.updateAutoScalingGroup(request);
}
// Find all subnets in the availability zone passed in the input
DescribeSubnetsResult describeSubnetsResult
= EC2_CLIENT.describeSubnets(new DescribeSubnetsRequest().withFilters(
new Filter("vpc-id", Collections.singletonList(vpcId)),
new Filter("availabilityZone", Collections.singletonList(azId))));
List<String> desiredSubnetsForAddingNewNacl = new ArrayList<>();
for (Subnet subnet : describeSubnetsResult.getSubnets()) {
desiredSubnetsForAddingNewNacl.add(subnet.getSubnetId());
}
//Find all the network acl associations matching the subnets identified above
DescribeNetworkAclsResult describeNetworkAclsResult
= EC2_CLIENT.describeNetworkAcls(new DescribeNetworkAclsRequest().withFilters(
new Filter("association.subnet-id", desiredSubnetsForAddingNewNacl)));
List<NetworkAclAssociation> desiredAclAssociations = new ArrayList<>();
// Note: This assumes a Network ACL exists for readability
List<NetworkAclAssociation> networkAclsAssociatedWithSubnet = describeNetworkAclsResult.getNetworkAcls().get(0).getAssociations();
for (String subnetId : desiredSubnetsForAddingNewNacl) {
for (NetworkAclAssociation networkAcl : networkAclsAssociatedWithSubnet) {
if (networkAcl.getSubnetId().equalsIgnoreCase(subnetId)) {
desiredAclAssociations.add(networkAcl);
}
}
}
//create new network acl association with both ingress and egress denying to all the traffic
CreateNetworkAclRequest createNetworkAclRequest = new CreateNetworkAclRequest();
createNetworkAclRequest.setVpcId(vpcId);
// Note: This assumes a Network ACL exists for readability
String networkAclId = EC2_CLIENT.createNetworkAcl(createNetworkAclRequest).getNetworkAcl().getNetworkAclId();
createNetworkAclEntry(networkAclId, 100, "0.0.0.0/0", true, "-1",
createPortRange(0, 65535), RuleAction.Deny);
createNetworkAclEntry(networkAclId, 101, "0.0.0.0/0", false, "-1",
createPortRange(0, 65535), RuleAction.Deny);
// replace all the network acl associations identified for the above subnets with the new network
// acl association which will deny all traffic for those subnets in that AZ
System.out.println("Creating new network ACL associations");
replaceNetworkAclAssociations(desiredAclAssociations, networkAclId);
//fail over rds which is in the same AZ
DescribeDBInstancesResult describeDBInstancesResult = RDS_CLIENT.describeDBInstances();
List<DBInstance> dbInstances = describeDBInstancesResult.getDBInstances();
String dbInstancedId = null;
for (DBInstance dbInstance : dbInstances) {
if(dbInstance.getDBSubnetGroup().getVpcId().equalsIgnoreCase(vpcId)
&& dbInstance.getAvailabilityZone().equalsIgnoreCase(azId)
&& dbInstance.getStatusInfos().isEmpty()
&& dbInstance.getMultiAZ().booleanValue()) {
dbInstancedId = dbInstance.getDBInstanceIdentifier();
}
}
// we want to fail over rds if rds is present in the same az where it is affected
if (dbInstancedId != null) {
RebootDBInstanceRequest rebootDBInstanceRequest = new RebootDBInstanceRequest();
rebootDBInstanceRequest.setDBInstanceIdentifier(dbInstancedId);
rebootDBInstanceRequest.setForceFailover(true);
System.out.println("Rebooting dbInstanceId to secondary AZ" + dbInstancedId);
RDS_CLIENT.rebootDBInstance(rebootDBInstanceRequest);
}
} catch (Exception exception) {
System.out.println("Unknown exception occurred " + exception.getMessage());
}
}