diff --git a/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java b/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java index 50d916a702..ab4d575da2 100644 --- a/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java +++ b/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java @@ -21,11 +21,13 @@ package org.jclouds.compute.callables; import static com.google.common.base.Preconditions.checkNotNull; +import java.util.Collections; + import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.util.ComputeServiceUtils; import org.jclouds.compute.util.ComputeServiceUtils.SshCallable; -import org.jclouds.io.Payloads; import org.jclouds.logging.Logger; +import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.ssh.ExecResponse; @@ -40,28 +42,36 @@ import com.google.common.collect.Iterables; public class InitAndStartScriptOnNode implements SshCallable { protected SshClient ssh; protected final NodeMetadata node; - protected final String scriptName; - protected final Statement script; + protected final InitBuilder init; protected final boolean runAsRoot; protected Logger logger = Logger.NULL; - public InitAndStartScriptOnNode(NodeMetadata node, String scriptName, Statement script, boolean runAsRoot) { + public InitAndStartScriptOnNode(NodeMetadata node, String name, Statement script, boolean runAsRoot) { this.node = checkNotNull(node, "node"); - this.scriptName = checkNotNull(scriptName, "scriptName"); - this.script = checkNotNull(script, "script"); + this.init = checkNotNull(script, "script") instanceof InitBuilder ? InitBuilder.class.cast(script) + : createInitScript(checkNotNull(name, "name"), script); this.runAsRoot = runAsRoot; } + public static InitBuilder createInitScript(String name, Statement script) { + String path = "/tmp/" + name; + return new InitBuilder(name, path, path, Collections. emptyMap(), Collections.singleton(script)); + } + @Override public ExecResponse call() { - ssh.put(scriptName, Payloads.newPayload(script.render(OsFamily.UNIX))); - ExecResponse returnVal = ssh.exec("chmod 755 " + scriptName); - returnVal = ssh.exec("./" + scriptName + " init"); - logger.debug("<< initialized(%d)", returnVal.getExitCode()); + ssh.put(init.getInstanceName(), init.render(OsFamily.UNIX)); + ssh.exec("chmod 755 " + init.getInstanceName()); + runAction("init"); + return runAction("start"); + } - String command = (runAsRoot) ? startScriptAsRoot() : startScriptAsDefaultUser(); + private ExecResponse runAction(String action) { + ExecResponse returnVal; + String command = (runAsRoot) ? execScriptAsRoot(action) : execScriptAsDefaultUser(action); returnVal = runCommand(command); - logger.debug("<< start(%d)", returnVal.getExitCode()); + logger.debug("<< %s(%d)", action, returnVal.getExitCode()); + logger.trace("<< %s[%s]", action, returnVal); return returnVal; } @@ -79,20 +89,21 @@ public class InitAndStartScriptOnNode implements SshCallable { this.ssh = checkNotNull(ssh, "ssh"); } - protected String startScriptAsRoot() { + protected String execScriptAsRoot(String action) { String command; if (node.getCredentials().identity.equals("root")) { - command = "./" + scriptName + " start"; + command = "./" + init.getInstanceName() + " " + action; } else if (ComputeServiceUtils.isKeyAuth(node)) { - command = "sudo ./" + scriptName + " start"; + command = "sudo ./" + init.getInstanceName() + " " + action; } else { - command = String.format("echo '%s'|sudo -S ./%s", node.getCredentials().credential, scriptName + " start"); + command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(), + action); } return command; } - protected String startScriptAsDefaultUser() { - return "./" + scriptName + " start"; + protected String execScriptAsDefaultUser(String action) { + return "./" + init.getInstanceName() + " " + action; } @Override diff --git a/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNode.java b/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNode.java index 19b864c939..214dc4d9ec 100644 --- a/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNode.java +++ b/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNode.java @@ -19,13 +19,10 @@ package org.jclouds.compute.callables; -import java.util.Collections; - import javax.inject.Named; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; -import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.ssh.ExecResponse; @@ -39,34 +36,23 @@ import com.google.common.collect.Iterables; public class RunScriptOnNode extends InitAndStartScriptOnNode { protected final Predicate runScriptNotRunning; - public RunScriptOnNode(@Named("SCRIPT_COMPLETE") Predicate runScriptNotRunning, - NodeMetadata node, String scriptName, Statement script) { - this(runScriptNotRunning, node, scriptName, script, true); - } - public RunScriptOnNode(@Named("SCRIPT_COMPLETE") Predicate runScriptNotRunning, NodeMetadata node, String scriptName, Statement script, boolean runAsRoot) { - super(node, scriptName, createInitScript(scriptName, script), runAsRoot); + super(node, scriptName, script, runAsRoot); this.runScriptNotRunning = runScriptNotRunning; } - public static Statement createInitScript(String scriptName, Statement script) { - String path = "/tmp/" + scriptName; - return new InitBuilder(scriptName, path, path, Collections. emptyMap(), Collections - .singleton(script)); - } @Override public ExecResponse call() { ExecResponse returnVal = super.call(); - - boolean complete = runScriptNotRunning.apply(new CommandUsingClient("./" + scriptName + " status", ssh)); + boolean complete = runScriptNotRunning.apply(new CommandUsingClient("./" + init.getInstanceName() + " status", ssh)); logger.debug("<< complete(%s)", complete); if (logger.isDebugEnabled() || returnVal.getExitCode() != 0) { - logger.debug("<< stdout from %s as %s@%s\n%s", scriptName, node.getCredentials().identity, Iterables.get(node - .getPublicAddresses(), 0), ssh.exec("./" + scriptName + " tail").getOutput()); - logger.debug("<< stderr from %s as %s@%s\n%s", scriptName, node.getCredentials().identity, Iterables.get(node - .getPublicAddresses(), 0), ssh.exec("./" + scriptName + " tailerr").getOutput()); + logger.debug("<< stdout from %s as %s@%s\n%s", init.getInstanceName(), node.getCredentials().identity, Iterables.get(node + .getPublicAddresses(), 0), ssh.exec("./" + init.getInstanceName() + " tail").getOutput()); + logger.debug("<< stderr from %s as %s@%s\n%s", init.getInstanceName(), node.getCredentials().identity, Iterables.get(node + .getPublicAddresses(), 0), ssh.exec("./" + init.getInstanceName() + " tailerr").getOutput()); } return returnVal; } diff --git a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java index 7c91fedef4..e250685ab0 100755 --- a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java @@ -67,6 +67,7 @@ import org.jclouds.domain.Location; import org.jclouds.io.Payload; import org.jclouds.logging.Logger; import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.ssh.ExecResponse; import org.jclouds.util.Utils; @@ -152,7 +153,8 @@ public class BaseComputeService implements ComputeService { throws RunNodesException { checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens"); checkNotNull(template.getLocation(), "location"); - if (template.getOptions().getTaskName() == null && template.getOptions().getRunScript() != null) + if (template.getOptions().getTaskName() == null && template.getOptions().getRunScript() != null + && !(template.getOptions().getRunScript() instanceof InitBuilder)) template.getOptions().nameTask("bootstrap"); logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template.getImage().getId(), template @@ -359,7 +361,7 @@ public class BaseComputeService implements ComputeService { checkNotNull(options, "options"); if (options.getTaskName() == null) options.nameTask("jclouds-script-" + System.currentTimeMillis()); - + Iterable nodes = Iterables.filter(detailsOnAllNodes(), filter); final Map execs = Maps.newHashMap(); diff --git a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java index 2b4b2e2776..d271ca0349 100644 --- a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java +++ b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java @@ -60,8 +60,8 @@ public class RunScriptOptions { } @Override - public boolean isRunAsRoot() { - return delegate.isRunAsRoot(); + public boolean shouldRunAsRoot() { + return delegate.shouldRunAsRoot(); } @@ -70,6 +70,17 @@ public class RunScriptOptions { throw new IllegalArgumentException("runAsRoot is immutable"); } + @Override + public boolean shouldBlockOnComplete() { + return delegate.shouldBlockOnComplete(); + + } + + @Override + public RunScriptOptions blockOnComplete(boolean blockOnComplete) { + throw new IllegalArgumentException("blockOnComplete is immutable"); + } + @Override public RunScriptOptions withOverridingCredentials(Credentials overridingCredentials) { throw new IllegalArgumentException("overridingCredentials is immutable"); @@ -106,6 +117,7 @@ public class RunScriptOptions { protected String taskName; protected Credentials overridingCredentials; protected boolean runAsRoot = true; + protected boolean blockOnComplete = true; public RunScriptOptions withOverridingCredentials(Credentials overridingCredentials) { checkNotNull(overridingCredentials, "overridingCredentials"); @@ -114,6 +126,7 @@ public class RunScriptOptions { this.overridingCredentials = overridingCredentials; return this; } + /** * @return What to call the task relating to this script; default {@code * jclouds-script-timestamp} where timestamp is millis since epoch @@ -128,6 +141,12 @@ public class RunScriptOptions { this.runAsRoot = runAsRoot; return this; } + + public RunScriptOptions blockOnComplete(boolean blockOnComplete) { + this.blockOnComplete = blockOnComplete; + return this; + } + /** * When the node is started, wait until the following port is active */ @@ -138,12 +157,11 @@ public class RunScriptOptions { this.seconds = seconds; return this; } - + public String getTaskName() { return taskName; } - public int getPort() { return port; } @@ -167,10 +185,19 @@ public class RunScriptOptions { * * @return value */ - public boolean isRunAsRoot() { + public boolean shouldRunAsRoot() { return runAsRoot; } + /** + * Whether to wait until the script has completed. By default, true. + * + * @return value + */ + public boolean shouldBlockOnComplete() { + return blockOnComplete; + } + public static class Builder { public static RunScriptOptions nameTask(String name) { @@ -187,10 +214,12 @@ public class RunScriptOptions { RunScriptOptions options = new RunScriptOptions(); return options.runAsRoot(value); } - - /** - * @see RunScriptOptions#blockOnPort - */ + + public static RunScriptOptions blockOnComplete(boolean value) { + RunScriptOptions options = new RunScriptOptions(); + return options.blockOnComplete(value); + } + public static RunScriptOptions blockOnPort(int port, int seconds) { RunScriptOptions options = new RunScriptOptions(); return options.blockOnPort(port, seconds); @@ -200,7 +229,8 @@ public class RunScriptOptions { @Override public String toString() { - return "[overridingCredentials=" + (overridingCredentials != null) + ", port:seconds=" + port + ":" + seconds + ", runAsRoot=" + runAsRoot + "]"; + return "[overridingCredentials=" + (overridingCredentials != null) + ", port:seconds=" + port + ":" + seconds + + ", runAsRoot=" + runAsRoot + ", blockOnComplete=" + blockOnComplete + "]"; } } diff --git a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java index 990367cba0..78d02af5d5 100644 --- a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java +++ b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java @@ -396,13 +396,19 @@ public class TemplateOptions extends RunScriptOptions { return options.withMetadata(); } + public static TemplateOptions blockOnComplete(boolean value) { + TemplateOptions options = new TemplateOptions(); + return options.blockOnComplete(value); + } + } @Override public String toString() { return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning - + ", port:seconds=" + port + ":" + seconds + ", metadata/details: " + includeMetadata + "]"; + + ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds + + ", metadata/details: " + includeMetadata + "]"; } public TemplateOptions blockUntilRunning(boolean blockUntilRunning) { @@ -483,4 +489,9 @@ public class TemplateOptions extends RunScriptOptions { public TemplateOptions withOverridingCredentials(Credentials overridingCredentials) { return TemplateOptions.class.cast(super.withOverridingCredentials(overridingCredentials)); } + + @Override + public TemplateOptions blockOnComplete(boolean blockOnComplete) { + return TemplateOptions.class.cast(super.blockOnComplete(blockOnComplete)); + } } diff --git a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java index 4c2f0e0af6..e09cbf509e 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java +++ b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java @@ -40,6 +40,7 @@ import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.Constants; +import org.jclouds.compute.callables.InitAndStartScriptOnNode; import org.jclouds.compute.callables.RunScriptOnNode; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.options.RunScriptOptions; @@ -146,8 +147,8 @@ public class ComputeUtils { bootstrap.add(new AuthorizeRSAPublicKey(options.getPublicKey())); if (options.getPrivateKey() != null) bootstrap.add(new InstallRSAPrivateKey(options.getPrivateKey())); - if (bootstrap.size() >0) - runScriptOnNode(node, new StatementList(bootstrap), options); + if (bootstrap.size() >= 1) + runScriptOnNode(node, bootstrap.size() == 1 ? bootstrap.get(0) : new StatementList(bootstrap), options); return node; } @@ -155,15 +156,9 @@ public class ComputeUtils { checkState(node.getPublicAddresses().size() > 0, "node does not have IP addresses configured: " + node); } - public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) - { - RunScriptOnNode callable; - String taskName = options.getTaskName(); + public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) { + InitAndStartScriptOnNode callable = generateScript(node, runScript, options); ExecResponse response; - if (options.isRunAsRoot()) { - callable = runScriptOnNode(node, taskName, runScript); - } else - callable = runScriptOnNodeAsDefaultUser(node, taskName, runScript); SshClient ssh = createSshClientOncePortIsListeningOnNode(node); try { ssh.connect(); @@ -192,12 +187,10 @@ public class ComputeUtils { logger.warn("<< port %s:%d didn't open after %d seconds", inetAddress, port, seconds); } - public RunScriptOnNode runScriptOnNode(NodeMetadata node, String scriptName, Statement script) { - return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script); - } - - public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node, String scriptName, Statement script) { - return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false); + public InitAndStartScriptOnNode generateScript(NodeMetadata node, Statement script, RunScriptOptions options) { + return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(), + script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script, + options.shouldRunAsRoot()); } public Map, ?> runCallablesOnNode(NodeMetadata node, Iterable> parallel, diff --git a/compute/src/main/java/org/jclouds/ssh/SshClient.java b/compute/src/main/java/org/jclouds/ssh/SshClient.java index b0a907b5e2..ca9c82b99d 100644 --- a/compute/src/main/java/org/jclouds/ssh/SshClient.java +++ b/compute/src/main/java/org/jclouds/ssh/SshClient.java @@ -52,4 +52,6 @@ public interface SshClient { @PreDestroy void disconnect(); + void put(String path, String contents); + } \ No newline at end of file diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index 6bd4dbe28e..dc39ce9404 100755 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -30,7 +30,8 @@ import static com.google.common.collect.Maps.newLinkedHashMap; import static com.google.common.collect.Maps.uniqueIndex; import static com.google.common.collect.Sets.filter; import static com.google.common.collect.Sets.newTreeSet; -import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideCredentialsWith; +import static org.jclouds.compute.options.TemplateOptions.Builder.blockOnComplete; +import static org.jclouds.compute.options.TemplateOptions.Builder.overrideCredentialsWith; import static org.jclouds.compute.predicates.NodePredicates.TERMINATED; import static org.jclouds.compute.predicates.NodePredicates.all; import static org.jclouds.compute.predicates.NodePredicates.runningWithTag; @@ -43,6 +44,7 @@ import static org.testng.Assert.assertNotNull; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.net.URI; import java.util.Collection; import java.util.Map; import java.util.NoSuchElementException; @@ -96,33 +98,6 @@ import com.google.inject.Module; */ @Test(groups = { "integration", "live" }, sequential = true, testName = "compute.ComputeServiceLiveTest") public abstract class BaseComputeServiceLiveTest { - public static final String APT_RUN_SCRIPT = new StringBuilder()// - .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// - .append("cp /etc/apt/sources.list /etc/apt/sources.list.old\n")// - .append( - "sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list\n")// - .append("apt-get update\n")// - .append("apt-get install -f -y --force-yes openjdk-6-jdk\n")// - .toString(); - - public static final String YUM_RUN_SCRIPT = new StringBuilder() - .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n") - // - .append("echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n") - // - .append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n") - // - .append( - "echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")// - .append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")// - .append("yum --nogpgcheck -y install java-1.6.0-openjdk\n")// - .append("echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")// - .toString(); - - public static final String ZYPPER_RUN_SCRIPT = new StringBuilder()// - .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// - .append("sudo zypper install java-1.6.0-openjdk-devl\n")// - .toString(); public void setServiceDefaults() { @@ -289,6 +264,37 @@ public abstract class BaseComputeServiceLiveTest { } @Test(enabled = true, dependsOnMethods = "testCompareSizes") + public void testCreateAndRunAService() throws Exception { + + String tag = this.tag + "service"; + try { + client.destroyNodesMatching(withTag(tag)); + } catch (Exception e) { + + } + + template = client.templateBuilder().options(blockOnComplete(false).blockOnPort(8080, 300).inboundPorts(22, 8080)) + .build(); + // note this is a dependency on the template resolution + template.getOptions().runScript( + RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage() + .getOperatingSystem())); + try { + TreeSet nodes = newTreeSet(client.runNodesWithTag(tag, 1, template)); + + checkHttpGet(nodes); + } finally { + client.destroyNodesMatching(withTag(tag)); + } + + } + + protected void checkHttpGet(TreeSet nodes) { + assert context.utils().http().get( + URI.create(String.format("http://%s:8080", get(nodes.last().getPublicAddresses(), 0)))) != null; + } + + @Test(enabled = true, dependsOnMethods = "testCreateAndRunAService") public void testCreateTwoNodesWithRunScript() throws Exception { try { client.destroyNodesMatching(withTag(tag)); @@ -389,11 +395,11 @@ public abstract class BaseComputeServiceLiveTest { public static String buildScript(OperatingSystem os) { if (OperatingSystemPredicates.supportsApt().apply(os)) - return APT_RUN_SCRIPT; + return RunScriptData.APT_RUN_SCRIPT; else if (OperatingSystemPredicates.supportsYum().apply(os)) - return YUM_RUN_SCRIPT; + return RunScriptData.YUM_RUN_SCRIPT; else if (OperatingSystemPredicates.supportsZypper().apply(os)) - return ZYPPER_RUN_SCRIPT; + return RunScriptData.ZYPPER_RUN_SCRIPT; else throw new IllegalArgumentException("don't know how to handle" + os.toString()); } diff --git a/compute/src/test/java/org/jclouds/compute/RunScriptData.java b/compute/src/test/java/org/jclouds/compute/RunScriptData.java new file mode 100644 index 0000000000..ec7a3326d9 --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/RunScriptData.java @@ -0,0 +1,109 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + * ==================================================================== + */ + +package org.jclouds.compute; + +import static org.jclouds.compute.util.ComputeServiceUtils.extractZipIntoDirectory; +import static org.jclouds.scriptbuilder.domain.Statements.exec; +import static org.jclouds.scriptbuilder.domain.Statements.interpret; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.predicates.OperatingSystemPredicates; +import org.jclouds.scriptbuilder.InitBuilder; +import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey; +import org.jclouds.scriptbuilder.domain.Statement; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +public class RunScriptData { + private static String jbossVersion = "5.0.0.CR2"; + private static String jboss = String.format("jboss-%s-jdk6", jbossVersion); + private static String jbossHome = "/usr/local/jboss"; + + public static String createScriptInstallBase(OperatingSystem os) { + if (os == null || OperatingSystemPredicates.supportsApt().apply(os)) + return APT_RUN_SCRIPT; + else if (OperatingSystemPredicates.supportsYum().apply(os)) + return YUM_RUN_SCRIPT; + else if (OperatingSystemPredicates.supportsZypper().apply(os)) + return ZYPPER_RUN_SCRIPT; + else + throw new IllegalArgumentException("don't know how to handle" + os.toString()); + } + + public static Statement createScriptInstallAndStartJBoss(String publicKey, OperatingSystem os) { + Map envVariables = ImmutableMap.of("jbossHome", jbossHome); + Statement toReturn = new InitBuilder( + "jboss", + jbossHome, + jbossHome, + envVariables, + ImmutableList. of(new AuthorizeRSAPublicKey(publicKey), exec(createScriptInstallBase(os)), + extractZipIntoDirectory(URI.create(String.format( + "http://superb-sea2.dl.sourceforge.net/project/jboss/JBoss/JBoss-%s/%s.zip", + jbossVersion, jboss)), "/usr/local"), exec("{md} " + jbossHome), + exec("mv /usr/local/jboss-" + jbossVersion + "/* " + jbossHome)), + ImmutableList + . of(interpret("java -Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djava.endorsed.dirs=lib/endorsed -Djboss.bind.address=0.0.0.0 -classpath bin/run.jar org.jboss.Main"))); + return toReturn; + } + + public static final String APT_RUN_SCRIPT = new StringBuilder()// + .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// + .append("cp /etc/apt/sources.list /etc/apt/sources.list.old\n")// + .append( + "sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list\n")// + .append("apt-get update -y -qq\n")// + .append("apt-get install -f -y -qq --force-yes curl\n")// + .append("apt-get install -f -y -qq --force-yes unzip\n")// + .append("apt-get install -f -y -qq --force-yes openjdk-6-jdk\n")// + .toString(); + + public static final String YUM_RUN_SCRIPT = new StringBuilder() + .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n") + // + .append("echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n") + // + .append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n") + // + .append( + "echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")// + .append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")// + .append("yum --nogpgcheck -y install unzip\n")// + .append("yum --nogpgcheck -y install curl\n")// + .append("yum --nogpgcheck -y install java-1.6.0-openjdk\n")// + .append("echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")// + .toString(); + + public static final String ZYPPER_RUN_SCRIPT = new StringBuilder()// + .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// + .append("sudo zypper install unzip\n")// + .append("sudo zypper install curl\n")// + .append("sudo zypper install java-1.6.0-openjdk-devl\n")// + .toString(); + +} diff --git a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java index 603bd33232..8830b4b14c 100644 --- a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java +++ b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java @@ -32,6 +32,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -96,12 +97,18 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes expect(socketOpen.apply(new IPSocket("144.175.1.2", 22))).andReturn(true); expect(socketOpen.apply(new IPSocket("144.175.1.3", 22))).andReturn(true); expect(socketOpen.apply(new IPSocket("144.175.1.4", 22))).andReturn(true); + expect(socketOpen.apply(new IPSocket("144.175.1.5", 22))).andReturn(true); replay(socketOpen); socketTester = new RetryablePredicate(socketOpen, 60, 1, TimeUnit.SECONDS); } + @Override + protected void checkHttpGet(TreeSet nodes) { + + } + @Override protected Module getSshModule() { return new AbstractModule() { @@ -113,31 +120,36 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes SshClient client2 = createMock(SshClient.class); SshClient client3 = createMock(SshClient.class); SshClient client4 = createMock(SshClient.class); + SshClient client5 = createMock(SshClient.class); - expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "romeo")).andThrow( - new SshException("Auth fail")); expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(client1) .atLeastOnce(); + runScriptAndService(client1, 1); - client1.connect(); + expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "romeo")).andThrow( + new SshException("Auth fail")); + expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2) + .atLeastOnce(); + + client2.connect(); try { - runScript(client1, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class - .getResourceAsStream("/runscript.sh")), 1); + runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class + .getResourceAsStream("/runscript.sh")), 2); } catch (IOException e) { Throwables.propagate(e); } - client1.disconnect(); + client2.disconnect(); - expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2) - .atLeastOnce(); expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(client3) .atLeastOnce(); expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(client4) .atLeastOnce(); + expect(factory.create(new IPSocket("144.175.1.5", 22), "root", "password5")).andReturn(client5) + .atLeastOnce(); - runScriptAndInstallSsh(client2, "bootstrap", 2); runScriptAndInstallSsh(client3, "bootstrap", 3); runScriptAndInstallSsh(client4, "bootstrap", 4); + runScriptAndInstallSsh(client5, "bootstrap", 5); expect( factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair.get("private") @@ -151,27 +163,45 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes expect( factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair.get("private") .getBytes()))).andReturn(client4).atLeastOnce(); + expect( + factory.create(eq(new IPSocket("155.175.1.5", 22)), eq("root"), aryEq(keyPair.get("private") + .getBytes()))).andReturn(client5).atLeastOnce(); - helloAndJava(client1); helloAndJava(client2); helloAndJava(client3); helloAndJava(client4); + helloAndJava(client5); replay(factory); replay(client1); replay(client2); replay(client3); replay(client4); + replay(client5); bind(SshClient.Factory.class).toInstance(factory); } + private void runScriptAndService(SshClient client, int nodeId) { + client.connect(); + + try { + runScript(client, "jboss", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class + .getResourceAsStream("/initscript_with_jboss.sh")), nodeId); + } catch (IOException e) { + Throwables.propagate(e); + } + + client.disconnect(); + + } + private void runScriptAndInstallSsh(SshClient client, String scriptName, int nodeId) { client.connect(); try { runScript(client, scriptName, Utils.toStringAndClose(StubComputeServiceIntegrationTest.class - .getResourceAsStream("/initscript_with_keys.sh")), nodeId); + .getResourceAsStream("/initscript_with_java.sh")), nodeId); } catch (IOException e) { Throwables.propagate(e); } @@ -181,7 +211,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes } private void runScript(SshClient client, String scriptName, String script, int nodeId) { - client.put(eq("" + scriptName + ""), payloadEq(script)); + client.put(scriptName, script); expect(client.exec("chmod 755 " + scriptName + "")).andReturn(EXEC_GOOD); expect(client.getUsername()).andReturn("root").atLeastOnce(); expect(client.getHostAddress()).andReturn(nodeId + "").atLeastOnce(); @@ -299,6 +329,11 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes super.testAScriptExecutionAfterBootWithBasicTemplate(); } + @Test(enabled = true, dependsOnMethods = { "testCompareSizes" }) + public void testCreateAndRunAService() throws Exception { + super.testCreateAndRunAService(); + } + @Test(enabled = true, dependsOnMethods = "testTemplateMatch") public void testCreateTwoNodesWithRunScript() throws Exception { super.testCreateTwoNodesWithRunScript(); diff --git a/compute/src/test/resources/initscript_with_keys.sh b/compute/src/test/resources/initscript_with_java.sh similarity index 89% rename from compute/src/test/resources/initscript_with_keys.sh rename to compute/src/test/resources/initscript_with_java.sh index ac11ffa738..df87d2435d 100644 --- a/compute/src/test/resources/initscript_with_keys.sh +++ b/compute/src/test/resources/initscript_with_java.sh @@ -79,20 +79,22 @@ cd $INSTANCE_HOME echo nameserver 208.67.222.222 >> /etc/resolv.conf cp /etc/apt/sources.list /etc/apt/sources.list.old sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list -apt-get update -apt-get install -f -y --force-yes openjdk-6-jdk +apt-get update -y -qq +apt-get install -f -y -qq --force-yes curl +apt-get install -f -y -qq --force-yes unzip +apt-get install -f -y -qq --force-yes openjdk-6-jdk -mkdir -p .ssh -cat >> .ssh/authorized_keys <<'END_OF_FILE' +mkdir -p ~/.ssh +cat >> ~/.ssh/authorized_keys <<'END_OF_FILE' ssh-rsa END_OF_FILE -chmod 600 .ssh/authorized_keys -mkdir -p .ssh -rm .ssh/id_rsa -cat >> .ssh/id_rsa <<'END_OF_FILE' +chmod 600 ~/.ssh/authorized_keys +mkdir -p ~/.ssh +rm ~/.ssh/id_rsa +cat >> ~/.ssh/id_rsa <<'END_OF_FILE' -----BEGIN RSA PRIVATE KEY----- END_OF_FILE -chmod 600 .ssh/id_rsa +chmod 600 ~/.ssh/id_rsa END_OF_SCRIPT diff --git a/compute/src/test/resources/initscript_with_jboss.sh b/compute/src/test/resources/initscript_with_jboss.sh new file mode 100644 index 0000000000..f28900a506 --- /dev/null +++ b/compute/src/test/resources/initscript_with_jboss.sh @@ -0,0 +1,137 @@ +#!/bin/bash +set +u +shopt -s xpg_echo +shopt -s expand_aliases +unset PATH JAVA_HOME LD_LIBRARY_PATH +function abort { + echo "aborting: $@" 1>&2 + exit 1 +} +function default { + export INSTANCE_NAME="jboss" +export INSTANCE_HOME="/usr/local/jboss" +export LOG_DIR="/usr/local/jboss" + return 0 +} +function jboss { + export JBOSS_HOME="/usr/local/jboss" + return 0 +} +function findPid { + unset FOUND_PID; + [ $# -eq 1 ] || { + abort "findPid requires a parameter of pattern to match" + return 1 + } + local PATTERN="$1"; shift + local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|awk '{print $2}'` + [ -n "$_FOUND" ] && { + export FOUND_PID=$_FOUND + return 0 + } || { + return 1 + } +} +function forget { + unset FOUND_PID; + [ $# -eq 3 ] || { + abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR" + return 1 + } + local INSTANCE_NAME="$1"; shift + local SCRIPT="$1"; shift + local LOG_DIR="$1"; shift + mkdir -p $LOG_DIR + findPid $INSTANCE_NAME + [ -n "$FOUND_PID" ] && { + echo $INSTANCE_NAME already running pid [$FOUND_PID] + } || { + nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log & + sleep 1 + findPid $INSTANCE_NAME + [ -n "$FOUND_PID" ] || abort "$INSTANCE_NAME did not start" + } + return 0 +} +export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin +case $1 in +init) + default || exit 1 + jboss || exit 1 + mkdir -p ~/.ssh + cat >> ~/.ssh/authorized_keys <<'END_OF_FILE' +ssh-rsa +END_OF_FILE + chmod 600 ~/.ssh/authorized_keys + echo nameserver 208.67.222.222 >> /etc/resolv.conf + cp /etc/apt/sources.list /etc/apt/sources.list.old + sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list + apt-get update -y -qq + apt-get install -f -y -qq --force-yes curl + apt-get install -f -y -qq --force-yes unzip + apt-get install -f -y -qq --force-yes openjdk-6-jdk + + (mkdir -p /usr/local &&cd /usr/local &&curl -X GET -s --retry 20 http://superb-sea2.dl.sourceforge.net/project/jboss/JBoss/JBoss-5.0.0.CR2/jboss-5.0.0.CR2-jdk6.zip >extract.zip && unzip -o -qq extract.zip&& rm extract.zip) + mkdir -p /usr/local/jboss + mv /usr/local/jboss-5.0.0.CR2/* /usr/local/jboss + mkdir -p $INSTANCE_HOME + + # create runscript header + cat > $INSTANCE_HOME/jboss.sh <> $INSTANCE_HOME/jboss.sh <<'END_OF_SCRIPT' +cd $INSTANCE_HOME +java -Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djava.endorsed.dirs=lib/endorsed -Djboss.bind.address=0.0.0.0 -classpath bin/run.jar org.jboss.Main +END_OF_SCRIPT + + # add runscript footer + cat >> $INSTANCE_HOME/jboss.sh <<'END_OF_SCRIPT' +exit 0 +END_OF_SCRIPT + + chmod u+x $INSTANCE_HOME/jboss.sh + ;; +status) + default || exit 1 + findPid $INSTANCE_NAME || exit 1 + echo [$FOUND_PID] + ;; +stop) + default || exit 1 + findPid $INSTANCE_NAME || exit 1 + [ -n "$FOUND_PID" ] && { + echo stopping $FOUND_PID + kill -9 $FOUND_PID + } + ;; +start) + default || exit 1 + forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1 + ;; +tail) + default || exit 1 + tail $LOG_DIR/stdout.log + ;; +tailerr) + default || exit 1 + tail $LOG_DIR/stderr.log + ;; +run) + default || exit 1 + $INSTANCE_HOME/$INSTANCE_NAME.sh + ;; +esac +exit 0 diff --git a/compute/src/test/resources/runscript.sh b/compute/src/test/resources/runscript.sh index a23d1c38fd..84f034da27 100644 --- a/compute/src/test/resources/runscript.sh +++ b/compute/src/test/resources/runscript.sh @@ -79,8 +79,10 @@ cd $INSTANCE_HOME echo nameserver 208.67.222.222 >> /etc/resolv.conf cp /etc/apt/sources.list /etc/apt/sources.list.old sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list -apt-get update -apt-get install -f -y --force-yes openjdk-6-jdk +apt-get update -y -qq +apt-get install -f -y -qq --force-yes curl +apt-get install -f -y -qq --force-yes unzip +apt-get install -f -y -qq --force-yes openjdk-6-jdk END_OF_SCRIPT diff --git a/extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java b/extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java index 343cd09550..83f3b54838 100644 --- a/extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java +++ b/extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java @@ -132,15 +132,7 @@ public class JschSshClient implements SshClient { public Payload get(String path) { checkNotNull(path, "path"); - checkConnected(); - logger.debug("%s@%s:%d: Opening sftp Channel.", username, host, port); - ChannelSftp sftp = null; - try { - sftp = (ChannelSftp) session.openChannel("sftp"); - sftp.connect(); - } catch (JSchException e) { - throw new SshException(String.format("%s@%s:%d: Error connecting to sftp.", username, host, port), e); - } + ChannelSftp sftp = getSftp(); try { return Payloads.newInputStreamPayload(new CloseFtpChannelOnCloseInputStream(sftp.get(path), sftp)); } catch (SftpException e) { @@ -148,10 +140,26 @@ public class JschSshClient implements SshClient { } } + @Override public void put(String path, Payload contents) { checkNotNull(path, "path"); checkNotNull(contents, "contents"); + ChannelSftp sftp = getSftp(); + try { + sftp.put(contents.getInput(), path); + } catch (SftpException e) { + throw new SshException(String.format("%s@%s:%d: Error putting path: %s", username, host, port, path), e); + } finally { + Closeables.closeQuietly(contents); + } + } + @Override + public void put(String path, String contents) { + put(path, Payloads.newStringPayload(checkNotNull(contents, "contents"))); + } + + private ChannelSftp getSftp() { checkConnected(); logger.debug("%s@%s:%d: Opening sftp Channel.", username, host, port); ChannelSftp sftp = null; @@ -161,13 +169,7 @@ public class JschSshClient implements SshClient { } catch (JSchException e) { throw new SshException(String.format("%s@%s:%d: Error connecting to sftp.", username, host, port), e); } - try { - sftp.put(contents.getInput(), path); - } catch (SftpException e) { - throw new SshException(String.format("%s@%s:%d: Error putting path: %s", username, host, port, path), e); - } finally { - Closeables.closeQuietly(contents); - } + return sftp; } private void checkConnected() { diff --git a/extensions/ssh/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java b/extensions/ssh/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java index 447152bd06..dd02cf693f 100644 --- a/extensions/ssh/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java +++ b/extensions/ssh/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java @@ -46,8 +46,8 @@ import com.google.inject.Injector; */ @Test(groups = "live", testName = "ssh.JschSshClientLiveTest") public class JschSshClientLiveTest { - protected static final String sshHost = System.getProperty("test.ssh.host"); - protected static final String sshPort = System.getProperty("test.ssh.port"); + protected static final String sshHost = System.getProperty("test.ssh.host", "localhost"); + protected static final String sshPort = System.getProperty("test.ssh.port", "22"); protected static final String sshUser = System.getProperty("test.ssh.username"); protected static final String sshPass = System.getProperty("test.ssh.password"); protected static final String sshKeyFile = System.getProperty("test.ssh.keyfile"); @@ -55,7 +55,7 @@ public class JschSshClientLiveTest { @BeforeGroups(groups = { "live" }) public SshClient setupClient() throws NumberFormatException, FileNotFoundException, IOException { - int port = (sshPort != null) ? Integer.parseInt(sshPort) : 22; + int port = Integer.parseInt(sshPort); if (sshUser == null || ((sshPass == null || sshPass.trim().equals("")) && (sshKeyFile == null || sshKeyFile.trim().equals(""))) || sshUser.trim().equals("")) { @@ -99,6 +99,11 @@ public class JschSshClientLiveTest { return null; } + @Override + public void put(String path, String contents) { + + } + }; } else { Injector i = Guice.createInjector(new JschSshClientModule()); diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java index f7ec65f6e0..361c2aa94a 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/InitBuilder.java @@ -19,6 +19,7 @@ package org.jclouds.scriptbuilder; +import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.scriptbuilder.domain.Statements.call; import static org.jclouds.scriptbuilder.domain.Statements.createRunScript; import static org.jclouds.scriptbuilder.domain.Statements.findPid; @@ -31,8 +32,10 @@ import static org.jclouds.scriptbuilder.domain.Statements.switchArg; import java.util.Map; import org.jclouds.scriptbuilder.domain.Statement; +import org.jclouds.scriptbuilder.domain.StatementList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; /** @@ -42,9 +45,21 @@ import com.google.common.collect.Iterables; */ public class InitBuilder extends ScriptBuilder { - @SuppressWarnings("unchecked") + private final String instanceName; + private final String instanceHome; + private final String logDir; + public InitBuilder(String instanceName, String instanceHome, String logDir, Map variables, Iterable statements) { + this(instanceName, instanceHome, logDir, variables, ImmutableSet.of(), statements); + } + + @SuppressWarnings("unchecked") + public InitBuilder(String instanceName, String instanceHome, String logDir, Map variables, + Iterable initStatements, Iterable statements) { + this.instanceName = checkNotNull(instanceName, "instanceName"); + this.instanceHome = checkNotNull(instanceHome, "instanceHome"); + this.logDir = checkNotNull(logDir, "logDir"); Map defaultVariables = ImmutableMap.of("instanceName", instanceName, "instanceHome", instanceHome, "logDir", logDir); addEnvironmentVariableScope("default", defaultVariables) @@ -56,7 +71,7 @@ public class InitBuilder extends ScriptBuilder { .put( "init", newStatementList(call("default"), call(instanceName), - createRunScript( + new StatementList(initStatements), createRunScript( instanceName,// TODO: convert // so // that @@ -98,4 +113,58 @@ public class InitBuilder extends ScriptBuilder { interpret("{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}{lf}"))) .build())); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((instanceHome == null) ? 0 : instanceHome.hashCode()); + result = prime * result + ((instanceName == null) ? 0 : instanceName.hashCode()); + result = prime * result + ((logDir == null) ? 0 : logDir.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + InitBuilder other = (InitBuilder) obj; + if (instanceHome == null) { + if (other.instanceHome != null) + return false; + } else if (!instanceHome.equals(other.instanceHome)) + return false; + if (instanceName == null) { + if (other.instanceName != null) + return false; + } else if (!instanceName.equals(other.instanceName)) + return false; + if (logDir == null) { + if (other.logDir != null) + return false; + } else if (!logDir.equals(other.logDir)) + return false; + return true; + } + + public String getInstanceName() { + return instanceName; + } + + public String getInstanceHome() { + return instanceHome; + } + + public String getLogDir() { + return logDir; + } + + @Override + public String toString() { + return "[instanceName=" + instanceName + ", instanceHome=" + instanceHome + ", logDir=" + logDir + "]"; + } } \ No newline at end of file diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKey.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKey.java index dbcc168b7a..4821342d0f 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKey.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKey.java @@ -50,7 +50,7 @@ public class AuthorizeRSAPublicKey implements Statement { checkNotNull(family, "family"); if (family == OsFamily.WINDOWS) throw new UnsupportedOperationException("windows not yet implemented"); - return new StatementList(ImmutableList.of(exec("{md} .ssh"), appendFile(".ssh/authorized_keys", Splitter.on('\n') - .split(publicKey)), exec("chmod 600 .ssh/authorized_keys"))).render(family); + return new StatementList(ImmutableList.of(exec("{md} ~/.ssh"), appendFile("~/.ssh/authorized_keys", Splitter.on('\n') + .split(publicKey)), exec("chmod 600 ~/.ssh/authorized_keys"))).render(family); } } \ No newline at end of file diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKey.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKey.java index 78763e5ec2..635affb406 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKey.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKey.java @@ -51,7 +51,7 @@ public class InstallRSAPrivateKey implements Statement { checkNotNull(family, "family"); if (family == OsFamily.WINDOWS) throw new UnsupportedOperationException("windows not yet implemented"); - return new StatementList(ImmutableList.of(exec("{md} .ssh"), rm(".ssh/id_rsa"), appendFile(".ssh/id_rsa", Splitter.on('\n') - .split(privateKey)), exec("chmod 600 .ssh/id_rsa"))).render(family); + return new StatementList(ImmutableList.of(exec("{md} ~/.ssh"), rm("~/.ssh/id_rsa"), appendFile("~/.ssh/id_rsa", Splitter.on('\n') + .split(privateKey)), exec("chmod 600 ~/.ssh/id_rsa"))).render(family); } } \ No newline at end of file diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectory.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectory.java index fe89f829cc..6da722a60a 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectory.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectory.java @@ -48,7 +48,7 @@ public class UnzipHttpResponseIntoDirectory extends InterpretableStatement { public UnzipHttpResponseIntoDirectory(String method, URI endpoint, Multimap headers, String dir) { super( format( - "({md} %s &&{cd} %s &&curl -X %s -s --retry 20 %s %s >extract.zip && unzip -qq extract.zip&& rm extract.zip)\n", + "({md} %s &&{cd} %s &&curl -X %s -s --retry 20 %s %s >extract.zip && unzip -o -qq extract.zip&& rm extract.zip)\n", dir, dir, method, Joiner.on(' ').join( transform(headers.entries(), new Function, String>() { diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CopyOfAuthorizeRSAPublicKeyTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKeyTest.java similarity index 87% rename from scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CopyOfAuthorizeRSAPublicKeyTest.java rename to scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKeyTest.java index 68b6d4a35f..9cfca03ccf 100644 --- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/CopyOfAuthorizeRSAPublicKeyTest.java +++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/AuthorizeRSAPublicKeyTest.java @@ -27,14 +27,14 @@ import org.testng.annotations.Test; * @author Adrian Cole */ @Test(groups = "unit", testName = "scriptbuilder.AuthorizeRSAPublicKeyTest") -public class CopyOfAuthorizeRSAPublicKeyTest { +public class AuthorizeRSAPublicKeyTest { AuthorizeRSAPublicKey auth = new AuthorizeRSAPublicKey("ssh-dss AAAAB"); public void testAuthorizeRSAPublicKeyUNIX() { assertEquals( auth.render(OsFamily.UNIX), - "mkdir -p .ssh\ncat >> .ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\nEND_OF_FILE\nchmod 600 .ssh/authorized_keys\n"); } + "mkdir -p ~/.ssh\ncat >> ~/.ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\nEND_OF_FILE\nchmod 600 ~/.ssh/authorized_keys\n"); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testAuthorizeRSAPublicKeyWINDOWS() { diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKeyTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKeyTest.java index 9775282f4a..0d0d2d8e83 100644 --- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKeyTest.java +++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/InstallRSAPrivateKeyTest.java @@ -34,7 +34,7 @@ public class InstallRSAPrivateKeyTest { public void testInstallRSAPrivateKeyUNIX() { assertEquals( key.render(OsFamily.UNIX), - "mkdir -p .ssh\nrm .ssh/id_rsa\ncat >> .ssh/id_rsa <<'END_OF_FILE'\n-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n\nEND_OF_FILE\nchmod 600 .ssh/id_rsa\n"); + "mkdir -p ~/.ssh\nrm ~/.ssh/id_rsa\ncat >> ~/.ssh/id_rsa <<'END_OF_FILE'\n-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n\nEND_OF_FILE\nchmod 600 ~/.ssh/id_rsa\n"); } @Test(expectedExceptions = UnsupportedOperationException.class) diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectoryToTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectoryToTest.java index 63afb46cf7..6171139b76 100644 --- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectoryToTest.java +++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/domain/UnzipHttpResponseIntoDirectoryToTest.java @@ -42,7 +42,7 @@ public class UnzipHttpResponseIntoDirectoryToTest { public void testUnzipHttpResponseIntoDirectoryUNIX() { assertEquals( jboss.render(OsFamily.UNIX), - "(mkdir -p /tmp &&cd /tmp &&curl -X GET -s --retry 20 http://superb-sea2.dl.sourceforge.net/project/jboss/JBoss/JBoss-5.0.0.CR2/jboss-5.0.0.CR2-jdk6.zip >extract.zip && unzip -qq extract.zip&& rm extract.zip)\n"); + "(mkdir -p /tmp &&cd /tmp &&curl -X GET -s --retry 20 http://superb-sea2.dl.sourceforge.net/project/jboss/JBoss/JBoss-5.0.0.CR2/jboss-5.0.0.CR2-jdk6.zip >extract.zip && unzip -o -qq extract.zip&& rm extract.zip)\n"); } public void testUnzipHttpResponseIntoDirectoryWINDOWS() {