Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prototypical work using Typica for EC2 communication and Jay's comman…
…d line class for executing arbitrary commands remotely.
- Loading branch information
kirktrue
committed
Oct 22, 2009
1 parent
d6a5017
commit c638ee0
Showing
3 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
136 changes: 136 additions & 0 deletions
136
contrib/ec2-testing/src/java/voldemort/utils/ec2testing/Ec2InstanceCreator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
} |
82 changes: 82 additions & 0 deletions
82
contrib/ec2-testing/src/java/voldemort/utils/ec2testing/UnixCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} | ||
} | ||
|
||
} |