Sep 28, 2013

AWS SDK for Java - Tutorial 2 : EC2

Introduction

Amazon Elastic Compute Cloud (Amazon EC2) service provides resizable compute capacity in the cloud. It is designed to make web-scale computing easier for developers.
Let’s create EC2 instance using Java SDK.  

Prerequisite  

1. EC2 Instance (OnDemand, Reserved and Spot Instance)
2. KeyPair (Pem File)
3. EC2 Security Group
4. AWS AccessKey & SecretKey
5. EndPoint
6. Region


Step 1: Launch Eclipse
Step 2: File->New->Other->AWS
Step 3: Select “AWS Java Project”


Step 4: Create new class named “Main.java” with public static void main method.

Step 5: Define few constances, that we will use to create security group, keypair and ec2 instance.


 private Logger log = Logger.getInstance(Main.class);
 
 // require variable for every operation 
 private String accessKey = "YOUR ACCESS KEY";
 private String secretKey = "YOUR SECRET KEY" ;
 private AWSCredentials credentials;
 private String endPoint ;
 private Region region ;
 private AmazonEC2Client ec2client ;
 
 // EC2 Security Group  Variables
 private String groupName = "kpbirdec2securitygroup";
 private String groupDescription = "This is description";
 
 private String sshIpRange = "YOUR PUBLIC IP/32";
 private String sshprotocol = "tcp";
 private int sshFromPort = 22;
 private int sshToPort =22;
 
 private String httpIpRange = "0.0.0.0/0";
 private String httpProtocol = "tcp";
 private int httpFromPort = 80;
 private int httpToPort = 80;
 
 private String httpsIpRange = "0.0.0.0/0";
 private String httpsProtocol = "tcp";
 private int httpsFromPort = 443;
 private int httpsToProtocol = 443;
 
 // KeyPair variables
 private String keyName = "kpbirdkeypair";
 private String pemFilePath  = "PATH TO STORE PEM FILE"; //   /Users/kpbird/Desktop
 private String pemFileName = "kpbird_keypair.pem";
 
 
 // EC2 Instance variables
 private String imageId ="ami-64084736";
 private String instanceType ="t1.micro";
 private String instanceName = "kpbirdt1micro";
 
 // EC2 Spot Instance
 private String spotPrice = "0.080";
Step 6: initialize method create object of credentials, AmazonEC2Client and set endpoint and region for ec2client. Click here to read more about EndPoint and Region.
private void init(){
 credentials  = new BasicAWSCredentials(accessKey, secretKey);
 // end point for singapore 
 endPoint = "https://rds.ap-southeast-1.amazonaws.com";
 // regions for singapore
 region = Region.getRegion(Regions.AP_SOUTHEAST_1);
 ec2client = new AmazonEC2Client(credentials);
 ec2client.setEndpoint(endPoint);
 ec2client.setRegion(region); 
}
Step 7: Create Security Group includes three things 1. Security Group name and description 2. Permission (IP,Protocol and port range)and 3. Attach owner (AWS Account Owner) to security group.

 private void createEC2SecurityGroup(){
  try {
   log.Info("Create Security Group Request");   
   CreateSecurityGroupRequest createSecurityGroupRequest =  new CreateSecurityGroupRequest();
   createSecurityGroupRequest.withGroupName(groupName)
   .withDescription(groupDescription);
   createSecurityGroupRequest.setRequestCredentials(credentials);
   CreateSecurityGroupResult csgr = ec2client.createSecurityGroup(createSecurityGroupRequest);
   
   String groupid = csgr.getGroupId();
   log.Info("Security Group Id : " + groupid);
   
   log.Info("Create Security Group Permission");
   Collection<IpPermission> ips = new ArrayList<IpPermission>();
   // Permission for SSH only to your ip
   IpPermission ipssh = new IpPermission();
   ipssh.withIpRanges(sshIpRange).withIpProtocol(sshprotocol)
   .withFromPort(sshFromPort).withToPort(sshToPort);
   ips.add(ipssh);
   
   // Permission for HTTP, any one can access
   IpPermission iphttp = new IpPermission();
   iphttp.withIpRanges(httpIpRange).withIpProtocol(httpProtocol)
   .withFromPort(httpFromPort).withToPort(httpToPort);
   ips.add(iphttp);
   
   //Permission for HTTPS, any one can accesss
   IpPermission iphttps = new IpPermission();
   iphttps.withIpRanges(httpsIpRange).withIpProtocol(httpsProtocol)
   .withFromPort(httpsFromPort).withToPort(httpsToProtocol);
   ips.add(iphttps);
   
   log.Info("Attach Owner to security group");
   // Register this security group with owner
   AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = new AuthorizeSecurityGroupIngressRequest();
   authorizeSecurityGroupIngressRequest
   .withGroupName(groupName).withIpPermissions(ips);
   ec2client.authorizeSecurityGroupIngress(authorizeSecurityGroupIngressRequest);
   
  } catch (Exception e) {
   e.printStackTrace();
   System.exit(0);
  }
 }
Step 8: Amazon EC2 uses public–key cryptography to encrypt and decrypt login information. Public–key cryptography uses a public key to encrypt a piece of data, such as a password, then the recipient uses the private key to decrypt the data. The public and private keys are known as a key pair.

To log in to your instance, you must create a key pair, specify the name of the key pair when you launch the instance, and provide the private key when you connect to the instance. Linux/UNIX instances have no password, and you use a key pair to log in using SSH. Click here to read more about keypair.

 private void createKeyPair(){
  try {
   CreateKeyPairRequest ckpr = new CreateKeyPairRequest();
   ckpr.withKeyName(keyName);
   
   CreateKeyPairResult ckpresult = ec2client.createKeyPair(ckpr);
   KeyPair keypair = ckpresult.getKeyPair();
   String privateKey = keypair.getKeyMaterial();
   log.Info("KeyPair :" + privateKey);
   writePemFile(privateKey,pemFilePath,pemFileName); 
  } catch (Exception e) {
   e.printStackTrace();
   System.exit(0);
  }
 }


Step 9: EC2 instance require three things to create
1. Image ID (AMI), AMI -Amazon Machine Image, AMI is image of operating system and few extra software configured with it. There can be two type of AMI a) public AMI which I am using in following code b) Private AMI, To read more about AMI click here
2. Instance Type, Amazone provides different hardware configuration, you can choose as per your requirement, in this example I am using t1.micro which is smallest instance provided by Amazon AWS. To read more about Instance Type click here
3. Keypair name and security group name

Step 9a Create OnDemand Instance
 private void createEC2OnDemandInstance(){
  try {
   
   // request for new on demand instance
   RunInstancesRequest rir = new RunInstancesRequest();
   rir.withImageId(imageId);
   rir.withInstanceType(instanceType);
   rir.withMinCount(1);
   rir.withMaxCount(1);
   rir.withKeyName(keyName);
   rir.withMonitoring(true);
   rir.withSecurityGroups(groupName);
   
   RunInstancesResult riresult = ec2client.runInstances(rir);
   log.Info(riresult.getReservation().getReservationId());
   
   /// Find newly created instance id
   String instanceId=null;
   DescribeInstancesResult result = ec2client.describeInstances();
   Iterator<Reservation> i = result.getReservations().iterator();
   while (i.hasNext()) {
    Reservation r = i.next();
    List<Instance> instances = r.getInstances();
    for (Instance ii : instances) {
     log.Info(ii.getImageId() + "t" + ii.getInstanceId()+ "t" + ii.getState().getName() + "t"+ ii.getPrivateDnsName());
     if (ii.getState().getName().equals("pending")) {
      instanceId = ii.getInstanceId();
     }
    }
   }
   
   log.Info("New Instance ID :" + instanceId);
   /// Waiting for Instance Running////
   boolean isWaiting = true;
   while (isWaiting) {
    log.Info("*** Waiting ***");
    Thread.sleep(1000);
    DescribeInstancesResult r = ec2client.describeInstances();
    Iterator<Reservation> ir= r.getReservations().iterator();
    while(ir.hasNext()){
     Reservation rr = ir.next();
     List<Instance> instances = rr.getInstances();
     for(Instance ii : instances){
      log.Info(ii.getImageId() + "t" + ii.getInstanceId()+ "t" + ii.getState().getName() + "t"+ ii.getPrivateDnsName());
      if (ii.getState().getName().equals("running") && ii.getInstanceId().equals(instanceId) ) {
       log.Info(ii.getPublicDnsName());
       isWaiting=false;
      }
     }
    }
   }
   
   /// Creating Tag for New Instance ////
   log.Info("Creating Tags for New Instance");
   CreateTagsRequest crt = new CreateTagsRequest();
   ArrayList<Tag> arrTag = new ArrayList<Tag>();
   arrTag.add(new Tag().withKey("Name").withValue(instanceName));
   crt.setTags(arrTag);
   
   ArrayList<String> arrInstances = new ArrayList<String>();
   arrInstances.add(instanceId);
   crt.setResources(arrInstances);
   ec2client.createTags(crt);
   
   
  } catch (Exception e) {
   e.printStackTrace();
   System.exit(0);
  }
 }

Step 9b Create Spot Instance

 private void createEC2SpotInstance(){
  try {
   /// Creating Spot Instance ////
   
   // Initializes a Spot Instance Request
   RequestSpotInstancesRequest requestRequest = new RequestSpotInstancesRequest();
   // Request 1 x t1.micro instance with a bid price of $0.03.
   requestRequest.setSpotPrice(spotPrice);
   requestRequest.setInstanceCount(Integer.valueOf(1));
   LaunchSpecification launchSpecification = new LaunchSpecification();
   launchSpecification.setImageId(imageId);
   launchSpecification.setInstanceType(instanceType);
   launchSpecification.setMonitoringEnabled(true);
   
   // Add the security group to the request.
   ArrayList<String> securityGroups = new ArrayList<String>();
   securityGroups.add(groupName);
   launchSpecification.setSecurityGroups(securityGroups);
   
   launchSpecification.setKeyName(keyName);

   // Add the launch specifications to the request.
   requestRequest.setLaunchSpecification(launchSpecification);

   // Call the RequestSpotInstance API.
   RequestSpotInstancesResult requestResult = ec2client.requestSpotInstances(requestRequest);
   
   List<SpotInstanceRequest> requestResponses = requestResult.getSpotInstanceRequests();

   // Setup an arraylist to collect all of the request ids we want to
   // watch hit the running state.
   ArrayList<String> spotInstanceRequestIds = new ArrayList<String>();

   // Add all of the request ids to the hashset, so we can determine when they hit the
   // active state.
   for (SpotInstanceRequest requestResponse : requestResponses) {
       System.out.println("Created Spot Request: "+requestResponse.getSpotInstanceRequestId());
       spotInstanceRequestIds.add(requestResponse.getSpotInstanceRequestId());
       log.Info(requestResponse.getInstanceId() + "t" + requestResponse.getState());
   }
   
   String instanceId=null;
   boolean isWaiting=true;
   while(isWaiting){
    log.Info("*** Waiting for Spot Instance Request ***");
    Thread.sleep(5000);
     DescribeSpotInstanceRequestsRequest describeRequest = new DescribeSpotInstanceRequestsRequest();
     describeRequest.setSpotInstanceRequestIds(spotInstanceRequestIds);
     
     DescribeSpotInstanceRequestsResult describeResult = ec2client.describeSpotInstanceRequests(describeRequest);
        List<SpotInstanceRequest> describeResponses = describeResult.getSpotInstanceRequests();
        for (SpotInstanceRequest describeResponse : describeResponses) {
         log.Info(describeResponse.getInstanceId() + "t" + describeResponse.getState() + "t" + describeResponse.getSpotInstanceRequestId() + "t" + describeResponse.getStatus().getCode() + "t" + describeResponse.getStatus().getMessage());
           if (describeResponse.getState().equals("active")) {
               isWaiting = false;
               instanceId = describeResponse.getInstanceId();
               break;
           }
        }
    
   }
   isWaiting = true;
   while (isWaiting) {
    log.Info("*** Waiting for Instance Running ***");
    Thread.sleep(1000);
    DescribeInstancesResult r = ec2client.describeInstances();
    Iterator<Reservation> ir= r.getReservations().iterator();
    while(ir.hasNext()){
     Reservation rr = ir.next();
     List<Instance> instances = rr.getInstances();
     for(Instance ii : instances){
      log.Info(ii.getImageId() + "t" + ii.getInstanceId()+ "t" + ii.getState().getName() + "t"+ ii.getPrivateDnsName());
      if (ii.getState().getName().equals("running") && ii.getInstanceId().equals(instanceId) ) {
       log.Info(ii.getPublicDnsName());
       String publicDNS = ii.getPublicDnsName();
       log.Info("Public DNS :" + publicDNS);
       isWaiting=false;
      }
     }
    }
   }
   
   /// Creating Tag for New Instance ////
   log.Info("Creating Tags for New Instance");
   CreateTagsRequest crt = new CreateTagsRequest();
   ArrayList<Tag> arrTag = new ArrayList<Tag>();
   arrTag.add(new Tag().withKey("Name").withValue(instanceName));
   crt.setTags(arrTag);
   
   ArrayList<String> arrInstances = new ArrayList<String>();
   arrInstances.add(instanceId);
   crt.setResources(arrInstances);
   ec2client.createTags(crt);
   
   
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

Amazon AWS Management Console Screen Shots

EC2 Instance

EC2 Security Group

KeyPair

References