EC2InstanceLaunch.java Source code

Java tutorial

Introduction

Here is the source code for EC2InstanceLaunch.java

Source

/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 */
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
import com.amazonaws.services.ec2.model.CreateKeyPairRequest;
import com.amazonaws.services.ec2.model.CreateKeyPairResult;
import com.amazonaws.services.ec2.model.CreateSecurityGroupRequest;
import com.amazonaws.services.ec2.model.CreateSecurityGroupResult;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DescribeAvailabilityZonesResult;
import com.amazonaws.services.ec2.model.DescribeImagesResult;
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.DescribeInstancesResult;
import com.amazonaws.services.ec2.model.DescribeKeyPairsResult;
import com.amazonaws.services.ec2.model.Image;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.InstanceState;
import com.amazonaws.services.ec2.model.InstanceStatus;
import com.amazonaws.services.ec2.model.IpPermission;
import com.amazonaws.services.ec2.model.KeyPair;
import com.amazonaws.services.ec2.model.RebootInstancesRequest;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.RunInstancesRequest;
import com.amazonaws.services.ec2.model.RunInstancesResult;
import com.amazonaws.services.ec2.model.StartInstancesRequest;
import com.amazonaws.services.ec2.model.StopInstancesRequest;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;
import com.jcabi.ssh.Shell;
import com.jcabi.ssh.SSH;
import com.jcabi.log.Logger;

/**
 * Welcome to your new AWS Java SDK based project!
 *
 * This class is meant as a starting point for your console-based application that
 * makes one or more calls to the AWS services supported by the Java SDK, such as EC2,
 * SimpleDB, and S3.
 *
 * In order to use the services in this sample, you need:
 *
 *  - A valid Amazon Web Services account. You can register for AWS at:
 *       https://aws-portal.amazon.com/gp/aws/developer/registration/index.html
 *
 *  - Your account's Access Key ID and Secret Access Key:
 *       http://aws.amazon.com/security-credentials
 *
 *  - A subscription to Amazon EC2. You can sign up for EC2 at:
 *       http://aws.amazon.com/ec2/
 *
 *  - A subscription to Amazon SimpleDB. You can sign up for Simple DB at:
 *       http://aws.amazon.com/simpledb/
 *
 *  - A subscription to Amazon S3. You can sign up for S3 at:
 *       http://aws.amazon.com/s3/
 */
public class EC2InstanceLaunch {

    /*
     * WANRNING:
     *      To avoid accidental leakage of your credentials, DO NOT keep
     *      the credentials file in your source directory.
     */

    static AmazonEC2 ec2;
    static String keyName = "mini-hw2";
    static String securityGroupName = "Min-HW2-SG";
    static String securityGroupDescription = "Min-HW2 Security Group";
    static String imageId = "ami-146e2a7c"; //Amazon Linux AMI 2014.09.2
    static int minInstanceCount = 1; // create 1 instance
    static int maxInstanceCount = 1;
    static String instanceType = "t2.micro";
    static String instanceNameTag = "Mini-HW2";
    static String loginUserName = "ec2-user";

    static enum instanceState {
        start, stop, reboot, terminate
    };

    /**
     * The only information needed to create a client are security credentials
     * consisting of the AWS Access Key ID and Secret Access Key. All other
     * configuration, such as the service endpoints, are performed
     * automatically. Client parameters, such as proxies, can be specified in an
     * optional ClientConfiguration object when constructing a client.
     *
     * @see com.amazonaws.auth.BasicAWSCredentials
     * @see com.amazonaws.auth.PropertiesCredentials
     * @see com.amazonaws.ClientConfiguration
     */
    private static void init() throws Exception {

        /*
         * The ProfileCredentialsProvider will return your [default]
         * credential profile by reading from the credentials file located at
         * (/Users/hps/.aws/credentials).
         */
        AWSCredentials credentials = null;
        try {
            credentials = new ProfileCredentialsProvider("default").getCredentials();
        } catch (Exception e) {
            throw new AmazonClientException("Cannot load the credentials from the credential profiles file. "
                    + "Please make sure that your credentials file is at the correct "
                    + "location (/Users/hps/.aws/credentials), and is in valid format.", e);
        }
        System.out.println("# Create Amazon Client object");
        ec2 = new AmazonEC2Client(credentials);
    }

    private static String fetchInstancePublicIP(String instanceId) {
        DescribeInstancesRequest request = new DescribeInstancesRequest().withInstanceIds(instanceId);
        DescribeInstancesResult result = ec2.describeInstances(request);
        List<Reservation> list = result.getReservations();

        for (Reservation res : list) {
            List<Instance> instanceList = res.getInstances();

            for (Instance instance : instanceList) {

                System.out.println("Public IP :" + instance.getPublicIpAddress());
                /*
                System.out.println("Public DNS :" + instance.getPublicDnsName());
                System.out.println("Instance State :" + instance.getState());
                System.out.println("Instance TAGS :" + instance.getTags());
                */
                return instance.getPublicIpAddress();
            }
        }
        return null;
    }

    private static int getInstanceState(String instanceId) {
        DescribeInstancesRequest request = new DescribeInstancesRequest().withInstanceIds(instanceId);
        DescribeInstancesResult result = ec2.describeInstances(request);
        List<Reservation> list = result.getReservations();

        for (Reservation res : list) {
            List<Instance> instanceList = res.getInstances();

            for (Instance instance : instanceList) {
                //System.out.println("Instance state: " + instance.getState().getName());
                return instance.getState().getCode();
            }
        }
        return -1;
    }

    private static void sshToInstance(String instanceIP, String username, String privateKey) throws IOException {
        System.out.println("# SSH to ip: " + instanceIP);
        Shell shell = new SSH(instanceIP, 22, username, privateKey);
        /* 
         * http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
         * curl http://169.254.169.254/latest/meta-data/instance-id fetches instance id of the instance we have ssh'ed into.
         */
        String stdout = new Shell.Plain(shell).exec("lscpu");
        System.out.println("Output: " + stdout);
    }

    private static String readFile(String file) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line = null;
        StringBuilder stringBuilder = new StringBuilder();
        String ls = System.getProperty("line.separator");

        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }
        reader.close();
        return stringBuilder.toString();
    }

    private static void describeAvailabilityZones() {
        System.out.println("# Describe availability zones");
        DescribeAvailabilityZonesResult availabilityZonesResult = ec2.describeAvailabilityZones();
        System.out.println("You have access to " + availabilityZonesResult.getAvailabilityZones().size()
                + " Availability Zones.");

    }

    private static void describeCurrentInstances() {
        System.out.println("# Describe current instances");

        DescribeInstancesResult describeInstancesRequest = ec2.describeInstances();
        List<Reservation> reservations = describeInstancesRequest.getReservations();
        Set<Instance> instances = new HashSet<Instance>();

        for (Reservation reservation : reservations) {
            instances.addAll(reservation.getInstances());
        }

        System.out.println("You have " + instances.size() + " Amazon EC2 instance(s).");

        for (Instance ins : instances) {
            // instance id
            String instanceId = ins.getInstanceId();
            // instance state
            InstanceState is = ins.getState();
            System.out.println(instanceId + " " + is.getName());
        }
    }

    private static void describeImages() {
        DescribeImagesResult dir = ec2.describeImages();
        List<Image> images = dir.getImages();
        System.out.println("You have " + images.size() + " Amazon images");
    }

    private static void describeKeyPairs() {
        System.out.println("# Describe Key Pair");
        DescribeKeyPairsResult dkr = ec2.describeKeyPairs();
        System.out.println(dkr.toString());
    }

    private static void createSecurityGroup(String groupName, String groupDescription) {
        /*
         * http://docs.aws.amazon.com/AWSSdkDocsJava/latest//DeveloperGuide/create-security-group.html
         */

        System.out.println("# Create EC2 security group");
        CreateSecurityGroupRequest createSecurityGroupRequest = new CreateSecurityGroupRequest();
        createSecurityGroupRequest.withGroupName(groupName).withDescription(groupDescription);

        CreateSecurityGroupResult createSecurityGroupResult = ec2.createSecurityGroup(createSecurityGroupRequest);

        System.out.println("# Add inbound traffic rules");

        /* allow ssh access */
        addInboundRule(groupName, "0.0.0.0/0", "tcp", 22, 22);
        System.out.println("allowing inbound ssh access");

        /* allow http access */
        addInboundRule(groupName, "0.0.0.0/0", "tcp", 80, 80);
        System.out.println("allowing inbound http access");

        /* allow tcp access from my IP*/
        String myIP = getIpAddress();
        //System.out.println("My IP Address: " + myIP );
        addInboundRule(groupName, myIP + "/0", "tcp", 0, 65535);
        System.out.println("allowing tcp access from my IP (" + myIP + ")");
    }

    public static String getIpAddress() {
        URL myIP;
        try {
            myIP = new URL("http://api.externalip.net/ip/");

            BufferedReader in = new BufferedReader(new InputStreamReader(myIP.openStream()));
            return in.readLine();
        } catch (Exception e) {
            try {
                myIP = new URL("http://myip.dnsomatic.com/");

                BufferedReader in = new BufferedReader(new InputStreamReader(myIP.openStream()));
                return in.readLine();
            } catch (Exception e1) {
                try {
                    myIP = new URL("http://icanhazip.com/");

                    BufferedReader in = new BufferedReader(new InputStreamReader(myIP.openStream()));
                    return in.readLine();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }

        return null;
    }

    private static void addInboundRule(String groupName, String ipRanges, String protocols, int fromPort,
            int toPort) {

        IpPermission ipPermission = new IpPermission();

        ipPermission.withIpRanges(ipRanges).withIpProtocol(protocols).withFromPort(fromPort).withToPort(toPort);

        AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = new AuthorizeSecurityGroupIngressRequest();

        authorizeSecurityGroupIngressRequest.withGroupName(groupName).withIpPermissions(ipPermission);

        ec2.authorizeSecurityGroupIngress(authorizeSecurityGroupIngressRequest);

    }

    private static String createKeyPair(String keyName) {
        System.out.println("# Create Key Pair");

        CreateKeyPairRequest createKeyPairRequest = new CreateKeyPairRequest();

        createKeyPairRequest.withKeyName(keyName);

        CreateKeyPairResult createKeyPairResult = ec2.createKeyPair(createKeyPairRequest);

        KeyPair keyPair = new KeyPair();
        keyPair = createKeyPairResult.getKeyPair();
        String privateKey = keyPair.getKeyMaterial();

        //System.out.println("Private Key: " + privateKey);
        /**
         * Stores the private key to file.
         */
        /*
           PrintWriter fout = null;
           try {
        fout = new PrintWriter("/Users/hps/.ssh/"+ keyName + ".pem");
           } catch (FileNotFoundException e) {
        e.printStackTrace();
           }
           fout.println(privateKey);
           fout.close();
        */
        return privateKey;

    }

    private static String createInstance(String imageId, String instanceType, int minInstanceCount,
            int maxInstanceCount, String keyName, String groupName) {
        /*
        * http://docs.aws.amazon.com/AWSSdkDocsJava/latest//DeveloperGuide/run-instance.html
        */

        System.out.println("# Create an Instance");

        RunInstancesRequest runInstancesRequest = new RunInstancesRequest();
        runInstancesRequest.withImageId(imageId).withInstanceType(instanceType).withMinCount(minInstanceCount)
                .withMaxCount(maxInstanceCount).withKeyName(keyName).withSecurityGroups(groupName);

        RunInstancesResult runInstancesResult = ec2.runInstances(runInstancesRequest);
        // get instanceId from the result
        List<Instance> resultInstance = runInstancesResult.getReservation().getInstances();
        String createdInstanceId = null;
        for (Instance ins : resultInstance) {
            createdInstanceId = ins.getInstanceId();
            System.out.println("New instance(s) has been created: " + createdInstanceId);
        }
        return createdInstanceId;
    }

    private static void createTag(String instanceId, String tagName, String tagValue) {
        System.out.println("# Create a 'tag' for the new instance.");
        List<String> resources = new LinkedList<String>();
        List<Tag> tags = new LinkedList<Tag>();
        Tag nameTag = new Tag(tagName, tagValue);

        resources.add(instanceId);
        tags.add(nameTag);

        CreateTagsRequest ctr = new CreateTagsRequest(resources, tags);
        ec2.createTags(ctr);

    }

    private static void changeInstanceState(String instanceId, instanceState state) {

        List<String> instanceIds = new LinkedList<String>();
        instanceIds.add(instanceId);

        if (state == instanceState.stop) {
            //stop
            System.out.println("# Stop the Instance");
            StopInstancesRequest stopIR = new StopInstancesRequest(instanceIds);
            ec2.stopInstances(stopIR);
        } else if (state == instanceState.start) {
            //start
            System.out.println("# Start the Instance");
            StartInstancesRequest startIR = new StartInstancesRequest(instanceIds);
            ec2.startInstances(startIR);
        } else if (state == instanceState.terminate) {
            //terminate
            System.out.println("# Terminate the Instance");
            TerminateInstancesRequest terminateIR = new TerminateInstancesRequest(instanceIds);
            ec2.terminateInstances(terminateIR);
        } else if (state == instanceState.reboot) {
            //terminate
            System.out.println("# Reboot the Instance");
            RebootInstancesRequest rebootIR = new RebootInstancesRequest(instanceIds);
            ec2.rebootInstances(rebootIR);
        }

    }

    public static void main(String[] args) throws Exception {

        System.out.println("===============================");
        System.out.println("AWS EC2 Instance Launch Progam");
        System.out.println("===============================");

        /*
        String pk = readFile("/Users/hps/.ssh/" + keyName + ".pem");
        try {
           Thread.sleep(5000);
           sshToInstance("52.1.49.155", "ec2-user", pk);
        } catch (Exception e) {
           System.out.println("Error: " + e);
        }
        */

        init();

        /*
         * Amazon EC2
         *
         * The AWS EC2 client allows you to create, delete, and administer
         * instances programmatically.
         *
         * In this sample, we use an EC2 client to get a list of all the
         * availability zones, and all instances sorted by reservation id.
         */
        try {
            //describeAvailabilityZones();
            describeCurrentInstances();
            //describeImages();
            //describeKeyPairs();

            createSecurityGroup(securityGroupName, securityGroupDescription);

            String privateKey = createKeyPair(keyName);
            String createdInstanceId = createInstance(imageId, instanceType, minInstanceCount, maxInstanceCount,
                    keyName, securityGroupName);

            /* Wait for 10 seconds before trying to create a tag */
            Thread.sleep(10000);

            createTag(createdInstanceId, "Name", instanceNameTag);

            while (getInstanceState(createdInstanceId) != 16) {
                Thread.sleep(5000);
                System.out.println("Instance not running yet. Waiting.");
            }

            String createdInstanceIP = fetchInstancePublicIP(createdInstanceId);

            boolean connected = false;
            do {
                try {
                    Thread.sleep(5000);
                    sshToInstance(createdInstanceIP, loginUserName, privateKey);
                    connected = true;
                } catch (Exception e) {
                    //System.out.println("Error: " + e);
                    System.out.println("Retrying");
                }
            } while (connected == false);

            changeInstanceState(createdInstanceId, instanceState.stop);

            ec2.shutdown();

        } catch (AmazonServiceException ase) {
            System.out.println("Caught Exception: " + ase.getMessage());
            System.out.println("Reponse Status Code: " + ase.getStatusCode());
            System.out.println("Error Code: " + ase.getErrorCode());
            System.out.println("Request ID: " + ase.getRequestId());
        }

    }
}