Skip to content

Commit

Permalink
Prototypical work using Typica for EC2 communication and Jay's comman…
Browse files Browse the repository at this point in the history
…d line class for executing arbitrary commands remotely.
  • Loading branch information
kirktrue committed Oct 22, 2009
1 parent d6a5017 commit c638ee0
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 0 deletions.
Binary file added contrib/ec2-testing/lib/typica.jar
Binary file not shown.
@@ -0,0 +1,136 @@
package voldemort.utils.ec2testing;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xerox.amazonws.ec2.EC2Exception;
import com.xerox.amazonws.ec2.InstanceType;
import com.xerox.amazonws.ec2.Jec2;
import com.xerox.amazonws.ec2.LaunchConfiguration;
import com.xerox.amazonws.ec2.ReservationDescription;
import com.xerox.amazonws.ec2.ReservationDescription.Instance;

public class Ec2InstanceCreator {

private final Jec2 ec2;

private Log logger = LogFactory.getLog(getClass());

public Ec2InstanceCreator(String accessId, String secretKey) {
ec2 = new Jec2(accessId, secretKey);
}

public Map<String, String> createInstances(String ami,
String keypairId,
String instanceSize,
int instanceCount,
long timeout) throws Exception {
List<String> instanceIds = launch(ami, keypairId, instanceSize, instanceCount);
Map<String, String> hostNameMap = new HashMap<String, String>();

long startTime = System.currentTimeMillis();

while(!instanceIds.isEmpty()) {
waitForInstances(instanceIds, hostNameMap);

if(instanceIds.isEmpty())
break;

try {
if(logger.isInfoEnabled())
logger.info("Sleeping for 30 seconds...");

Thread.sleep(30000);
} catch(InterruptedException e) {
break;
}

if(System.currentTimeMillis() > (startTime + timeout)) {
throw new Error("Rollback creation NYI");
}
}

return hostNameMap;
}

private List<String> launch(String ami, String keypairId, String instanceSize, int instanceCount)
throws EC2Exception {
LaunchConfiguration launchConfiguration = new LaunchConfiguration(ami);
launchConfiguration.setInstanceType(instanceSize == null ? InstanceType.DEFAULT
: InstanceType.valueOf(instanceSize));
launchConfiguration.setKeyName(keypairId);
launchConfiguration.setMinCount(instanceCount);
launchConfiguration.setMaxCount(instanceCount);

ReservationDescription reservationDescription = ec2.runInstances(launchConfiguration);

List<String> instanceIds = new ArrayList<String>();

for(ReservationDescription.Instance instance: reservationDescription.getInstances()) {
if(logger.isInfoEnabled())
logger.info("Instance " + instance.getInstanceId() + " launched");

instanceIds.add(instance.getInstanceId());
}

return instanceIds;
}

private void waitForInstances(List<String> instanceIds, Map<String, String> hostNameMap)
throws Exception {
if(logger.isInfoEnabled())
logger.info("Waiting for instances: " + instanceIds);

for(ReservationDescription res: ec2.describeInstances(instanceIds)) {
if(res.getInstances() != null) {
for(Instance instance: res.getInstances()) {
String state = String.valueOf(instance.getState()).toLowerCase();

if(state.equals("pending")) {
if(logger.isInfoEnabled())
logger.info("Instance " + instance.getInstanceId()
+ " in pending state");

continue;
}

if(!state.equals("running")) {
if(logger.isWarnEnabled())
logger.warn("Instance " + instance.getInstanceId()
+ " in unexpected state: " + state + ", code: "
+ instance.getStateCode());

continue;
}

String publicDnsName = instance.getDnsName() != null ? instance.getDnsName()
.trim() : "";
String privateDnsName = instance.getPrivateDnsName() != null ? instance.getPrivateDnsName()
.trim()
: "";

if(publicDnsName.length() > 0 && privateDnsName.length() > 0) {
hostNameMap.put(instance.getDnsName(), instance.getPrivateDnsName());
instanceIds.remove(instance.getInstanceId());

if(logger.isInfoEnabled())
logger.info("Instance " + instance.getInstanceId()
+ " running with public DNS: " + instance.getDnsName()
+ ", private DNS: " + instance.getPrivateDnsName());
} else {
if(logger.isWarnEnabled())
logger.warn("Instance "
+ instance.getInstanceId()
+ " in running state, but missing public and/or private DNS name");
}
}
}
}
}

}
@@ -0,0 +1,82 @@
package voldemort.utils.ec2testing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
* A wrapper for executing a unix command
*
* @author jay
*
*/
public class UnixCommand {

private final String[] args;

public static void main(String[] args) throws Exception {
UnixCommand cmd = new UnixCommand(args);
cmd.execute();
}

public UnixCommand(String... args) {
this.args = args;
}

public UnixCommand(List<String> args) {
this.args = args.toArray(new String[args.size()]);
}

public void execute() throws InterruptedException, IOException {
ProcessBuilder builder = new ProcessBuilder(this.args);
Process process = builder.start();

Thread stdout = new StreamPrinter(process.getInputStream());
Thread stderr = new StreamPrinter(process.getErrorStream());
stdout.start();
stderr.start();

process.waitFor();

int exitCode = process.exitValue();

if(exitCode > 0)
throw new RuntimeException(exitCode + "");
}

public String getCommand() {
return StringUtils.join(args, ' ');
}

@Override
public String toString() {
return StringUtils.join(args, ' ');
}

private static class StreamPrinter extends Thread {

private BufferedReader reader;

public StreamPrinter(InputStream inputStream) {
this.reader = new BufferedReader(new InputStreamReader(inputStream));
}

@Override
public void run() {
try {
String line = null;

while((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch(IOException e) {
e.printStackTrace();
}
}
}

}

0 comments on commit c638ee0

Please sign in to comment.