public void failover()

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());
        }

    }