package vpc2vpc;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.DeleteRouteRequest;
import com.amazonaws.services.ec2.model.DeleteSecurityGroupRequest;
import com.amazonaws.services.ec2.model.DescribeInstanceStatusRequest;
import com.amazonaws.services.ec2.model.DescribeInstanceStatusResult;
import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.InstanceStatus;
import com.amazonaws.services.ec2.model.ReleaseAddressRequest;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.Route;
import com.amazonaws.services.ec2.model.RouteTable;
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;
import java.util.List;
import org.apache.log4j.Logger;
/**
* RollbackHelper
*
* @author Vinay Selvaraj
*/
public class RollbackHelper {
private Logger LOG = Logger.getLogger(RollbackHelper.class);
private static RollbackHelper instance;
private RollbackHelper() {
}
public static RollbackHelper getInstance() {
if (instance == null) {
instance = new RollbackHelper();
}
return instance;
}
public void rollback(AWSCredentials awsCreds, List<VPNEndpoint> vpnEndpoints, boolean showStatus) {
AmazonEC2Client ec2Client = new AmazonEC2Client(awsCreds);
for (VPNEndpoint vpnEndpoint : vpnEndpoints) {
ec2Client.setEndpoint(vpnEndpoint.getRegion().getEndpoint());
LOG.debug("Rolling back changes in " + vpnEndpoint.getRegion().getRegionName());
// Remove Route Table entries that were created
try {
List<RouteTable> routeTables = ec2Client.describeRouteTables().getRouteTables();
LOG.debug("Found " + routeTables.size() + " route tables in " + vpnEndpoint.getRegion().getRegionName());
for (RouteTable routeTable : routeTables) {
List<Route> routes = routeTable.getRoutes();
for (Route route : routes) {
LOG.debug("Checking if route is for vpc2vpc: " + route);
String routeInstanceId = route.getInstanceId();
if (routeInstanceId != null && routeInstanceId.equals(vpnEndpoint.getInstance().getInstanceId())) {
DeleteRouteRequest deleteRouteRequest = new DeleteRouteRequest();
deleteRouteRequest.setRouteTableId(routeTable.getRouteTableId());
deleteRouteRequest.setDestinationCidrBlock(route.getDestinationCidrBlock());
LOG.debug("About to delete route to " + route.getDestinationCidrBlock() + " from " + vpnEndpoint.getVpc());
ec2Client.deleteRoute(deleteRouteRequest);
LOG.debug("Deleted route");
}
}
}
} catch (Exception e) {
LOG.debug("Caught exception during rollback while deleting route table: " + e.getMessage());
}
// Remove EC2 instance if one exists
if (showStatus) {
try {
LOG.info(String.format("Deleting VPN instances in %s/%s (%s)",
vpnEndpoint.getVpc().getCidrBlock(),
vpnEndpoint.getVpc().getVpcId(),
vpnEndpoint.getRegion().getRegionName()));
} catch (Exception e) {
// Eat it
LOG.debug("Ignoring exception: " + e.getMessage());
}
}
try {
if (vpnEndpoint.getInstance() != null) {
Instance ec2Instance = vpnEndpoint.getInstance();
TerminateInstancesRequest request = new TerminateInstancesRequest().withInstanceIds(ec2Instance.getInstanceId());
ec2Client.terminateInstances(request);
LOG.debug("Sent request to terminate EC2 instance: " + ec2Instance.getInstanceId());
}
} catch (Exception e) {
LOG.debug("Caught exception during rollback while terminating EC2 instance: " + e.getMessage());
}
}
if (showStatus) {
LOG.info("Waiting on instances to terminate..");
}
int timeoutInMinutes = 10; // TODO: Remove hardcoding and put in config
long startTime = System.currentTimeMillis();
long endTime = startTime + (timeoutInMinutes * 60 * 1000);
boolean waitDone = false;
while (!waitDone && (System.currentTimeMillis() < endTime)) {
waitDone = true;
for (VPNEndpoint vpnEndpoint : vpnEndpoints) {
try {
ec2Client.setEndpoint(vpnEndpoint.getRegion().getEndpoint());
String instanceId = vpnEndpoint.getInstance().getInstanceId();
DescribeInstancesRequest descInstancesReq = new DescribeInstancesRequest().withInstanceIds(instanceId);
List<Reservation> reservations = ec2Client.describeInstances(descInstancesReq).getReservations();
Instance ec2InstanceBeingDeleted = null;
if (reservations != null && reservations.size() > 0) {
ec2InstanceBeingDeleted = reservations.get(0).getInstances().get(0);
LOG.debug("Waiting on instances: " + ec2InstanceBeingDeleted.getInstanceId() + " state: " + ec2InstanceBeingDeleted.getState());
if (!ec2InstanceBeingDeleted.getState().getName().equals("terminated")) {
waitDone = false;
}
} else {
LOG.debug("Unable to find the status on the instance: " + instanceId);
}
} catch (Exception e) {
LOG.debug("Ignoring exception: " + e.getMessage());
}
}
if (!waitDone) {
try {
Thread.sleep(15 * 1000);
} catch (Exception e) {
LOG.debug("Ignoring exception caught while sleeping");
// eat it
}
}
}
// TODO: USE RETRIES INSTEAD OF THIS SLEEP!
// This sleep is needed since sometimes the AWS API doesn't allow the
// SG / EIP to be removed since it still thinks it is in use by the
// instance(s) we just terminated
try {
Thread.sleep(15 * 1000);
} catch (Exception e) {
LOG.debug("Ignoring exception caught while sleeping");
// eat it
}
for (VPNEndpoint vpnEndpoint : vpnEndpoints) {
ec2Client.setEndpoint(vpnEndpoint.getRegion().getEndpoint());
// Release Elastic / Public IPs if one exists
try {
if (vpnEndpoint.getElasticIPAddress() != null && vpnEndpoint.getElasticIPAllocationId() != null) {
ReleaseAddressRequest request = new ReleaseAddressRequest().withAllocationId(vpnEndpoint.getElasticIPAllocationId());
LOG.debug("About to release elastic IP: " + request);
ec2Client.releaseAddress(request);
LOG.debug("Released elastic IP: " + vpnEndpoint.getElasticIPAddress());
} else {
LOG.debug("Unable to find the EIP Address or EIP Allocation ID");
}
} catch (Exception e) {
LOG.debug("Caught exception during rollback while releasing Elastic IPs: " + e.getMessage());
}
// Remove VPC Security Groups that were created
try {
DeleteSecurityGroupRequest deleteSecGrpReq = new DeleteSecurityGroupRequest();
deleteSecGrpReq.setGroupId(vpnEndpoint.getSecurityGroupId());
ec2Client.deleteSecurityGroup(deleteSecGrpReq);
LOG.debug("Deleted security group: " + vpnEndpoint.getSecurityGroupId());
} catch (Exception e) {
LOG.debug("Caught exception during rollback while deleting security group: " + e.getMessage());
}
}
}
}