/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package edu.ucsb.jpregel.clouds; import api.MachineGroup; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.inject.Inject; import com.google.inject.Module; import com.google.inject.name.Named; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import org.jclouds.apis.ApiMetadata; import org.jclouds.compute.ComputeService; import org.jclouds.compute.RunScriptOnNodesException; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.io.Payloads; import org.jclouds.ssh.SshClient; /** * * @author Charles Munger */ public abstract class CloudMachineGroup<T> extends MachineGroup<T> { protected final Set<? extends NodeMetadata> nodes; protected final ComputeService comp; public static final String JARNAME = "jpregel.jar"; public static final String BUCKET_NAME = "jpregel"; public static final File jar = new File("target/" + JARNAME); public static final String CREDENTIALS_MODULE = "credentialsModule"; private final String url; @Inject CloudMachineGroup(Set<? extends NodeMetadata> nodes, ComputeService compute, @Named("storage") ApiMetadata ap) { this.url = ap.getDefaultEndpoint().get(); this.nodes = nodes; this.comp = compute; } @Override public String getHostname() { return Iterables.getOnlyElement( Iterables.getOnlyElement( nodes).getPrivateAddresses()); } protected String getPublicHostname() { return Iterables.getOnlyElement( Iterables.getOnlyElement( nodes).getPublicAddresses()); } @Override public void reset() throws IOException { try { comp.runScriptOnNodesMatching(new Predicate<NodeMetadata>() { public boolean apply(NodeMetadata t) { return nodes.contains(t); } }, "killall -9 java; cd; rm -rf *", RunScriptOptions.Builder.blockOnComplete(true).overrideLoginUser(System.getProperty("user.name"))); } catch (RunScriptOnNodesException ex) { Logger.getLogger(CloudMachineGroup.class.getName()).log(Level.SEVERE, null, ex); } } @Override public void terminate() throws IOException { comp.destroyNodesMatching(new Predicate<NodeMetadata>() { public boolean apply(NodeMetadata t) { return nodes.contains(t); } }); } @Override public final T syncDeploy(String... args) { try { System.out.println("syncDeploying"); ExecutorService e = Executors.newCachedThreadPool(); for (NodeMetadata n : nodes) { e.submit(new LaunchTask(n, this.getClass().getName(), args)); } e.shutdown(); e.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); } catch (Exception ex) { Logger.getLogger(CloudMachineGroup.class.getName()).log(Level.SEVERE, null, ex); } return getRemoteReference(); } protected abstract T getRemoteReference(); private class LaunchTask implements Runnable { private final String mainClass; private final NodeMetadata nm; private final String[] args; LaunchTask(NodeMetadata nm, String mainClass, String[] args) { this.nm = nm; this.mainClass = mainClass; this.args = args; } @Override public void run() { System.out.println("Connecting"); SshClient ssh = comp.getContext().utils().sshForNode().apply(nm); System.out.println("Got client " + ssh.getUsername() + "@" + ssh.getHostAddress()); try { ssh.connect(); System.out.println("Connected"); ssh.exec("echo \"grant{ permission java.security.AllPermission;};\" > ~/policy "); System.out.println("Policy uploaded"); ssh.put(CREDENTIALS_MODULE, Payloads.newFilePayload(new File(CREDENTIALS_MODULE))); ssh.exec("wget -N "+url+"/"+BUCKET_NAME+ "/"+JARNAME); System.out.println("Jar downloaded from "+url+"/"+BUCKET_NAME+ "/"+JARNAME); ssh.execChannel("java -server " + "-XX:+UseConcMarkSweepGC " + "-XX:+AggressiveOpts " + "-XX:+UseFastAccessorMethods " + "-cp " + JARNAME + " -Djava.security.policy=policy " //ssh address so we know it's an address the client can reach + " -Djava.rmi.server.hostname=" + ssh.getHostAddress() + " " + heapSize(nm.getHardware().getRam()) + " " + mainClass + " " + args[0] + " >> log.log"); //save output until a real logger works System.out.println(ssh.getHostAddress() + " Executions submitted"); } catch (Exception ex) { Logger.getLogger(CloudMachineGroup.class.getName()).log(Level.SEVERE, null, ex); } finally { if (ssh != null) { ssh.disconnect(); } } } } protected static Module getCredentials() throws IOException, ClassNotFoundException { ObjectInputStream oi = new ObjectInputStream(new FileInputStream(CREDENTIALS_MODULE)); Module m = (Module) oi.readObject(); oi.close(); return m; } private String heapSize(int ram) { ram = (ram * 19) / 20; return "-Xmx" + ram + "m -Xms" + ram + "m "; } }