diff --git a/compute/src/main/java/org/jclouds/compute/ComputeService.java b/compute/src/main/java/org/jclouds/compute/ComputeService.java index a57f92c95c..776fd6f16a 100644 --- a/compute/src/main/java/org/jclouds/compute/ComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/ComputeService.java @@ -158,23 +158,22 @@ public interface ComputeService { /** * Runs the script without any additional options * - * @see #runScriptOnNodesWithTag(String, org.jclouds.domain.Credentials, + * @see #runScriptOnNodesWithTag(String, * byte[], org.jclouds.compute.options.RunScriptOptions) */ - Map runScriptOnNodesWithTag(String tag, Credentials credentials, + Map runScriptOnNodesWithTag(String tag, byte[] runScript); /** * Run the script on all nodes with the specific tag. * * @param tag tag to look up the nodes - * @param credentials credentials to use (same for all nodes) * @param runScript script to run in byte format. If the script is a string, use * {@link String#getBytes()} to retrieve the bytes * @param options nullable options to how to run the script * @return map with node identifiers and corresponding responses */ - Map runScriptOnNodesWithTag(String tag, Credentials credentials, + Map runScriptOnNodesWithTag(String tag, byte[] runScript, RunScriptOptions options); } 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 8c7377fcb0..698f6f7bb8 100644 --- a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java @@ -323,26 +323,24 @@ public class BaseComputeService implements ComputeService { } /** - * @see #runScriptOnNodesWithTag(String, org.jclouds.domain.Credentials, byte[], + * @see #runScriptOnNodesWithTag(String, byte[], * org.jclouds.compute.options.RunScriptOptions) */ - public Map runScriptOnNodesWithTag(String tag, Credentials credentials, + public Map runScriptOnNodesWithTag(String tag, byte[] runScript) { - return runScriptOnNodesWithTag(tag, credentials, runScript, RunScriptOptions.NONE); + return runScriptOnNodesWithTag(tag, runScript, RunScriptOptions.NONE); } /** * Run the script on all nodes with the specific tag. * * @param tag tag to look up the nodes - * @param credentials nullable credentials to use (same for all nodes). * @param runScript script to run in byte format. If the script is a string, use * {@link String#getBytes()} to retrieve the bytes - * @param options nullable options to how to run the script + * @param options nullable options to how to run the script, whether to override credentials * @return map with node identifiers and corresponding responses */ - public Map runScriptOnNodesWithTag(String tag, @Nullable Credentials credentials, - byte[] runScript, @Nullable RunScriptOptions options) { + public Map runScriptOnNodesWithTag(String tag, byte[] runScript, @Nullable RunScriptOptions options) { checkNotEmpty(tag, "Tag must be provided"); checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided"); @@ -354,18 +352,19 @@ public class BaseComputeService implements ComputeService { for(NodeMetadata node : nodes.values()) { if(NodeState.RUNNING != node.getState()) continue; //make sure the node is active - if(options.isOverrideCredentials()) { + if(options.getOverrideCredentials() != null) { //override the credentials with provided to this method - checkNotNull(credentials, "If the credentials need to be overridden, they can't be null"); - node = ComputeUtils.installNewCredentials(node, credentials); + node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials()); } else { //don't override checkNotNull(node.getCredentials(), "If the default credentials need to be used, they can't be null"); } - //todo: execute script as root if required - - ComputeUtils.SshCallable callable = utils.runScriptOnNode(node, "computeserv.sh", runScript); + ComputeUtils.SshCallable callable; + if(options.isRunAsRoot()) + callable = utils.runScriptOnNode(node, "computeserv.sh", runScript); + else + callable = utils.runScriptOnNodeAsDefaultUser(node, "computeserv.sh", runScript); Map, ?> scriptRunResults = utils.runCallablesOnNode(node, Sets.newHashSet(callable), 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 9af380209d..e3eb60f792 100644 --- a/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java +++ b/compute/src/main/java/org/jclouds/compute/options/RunScriptOptions.java @@ -18,6 +18,8 @@ */ package org.jclouds.compute.options; +import org.jclouds.domain.Credentials; + /** * Enables additional options for running a script. * @@ -30,16 +32,16 @@ public class RunScriptOptions { *
    *
  • override the credentials with ones supplied in * call to {@link org.jclouds.compute.ComputeService#runScriptOnNodesWithTag}
  • - *
  • do not run the script as root (run with current privileges)
  • + *
  • run the script as root (versus running with current privileges)
  • *
*/ public static final RunScriptOptions NONE = new RunScriptOptions(); - private boolean overrideCredentials = true; - private boolean runAsRoot = false; + private Credentials overridingCredentials; + private boolean runAsRoot = true; - private void overrideCredentials(boolean overrideCredentials) { - this.overrideCredentials = overrideCredentials; + private void withOverridingCredentials(Credentials overridingCredentials) { + this.overridingCredentials = overridingCredentials; } private void runAsRoot(boolean runAsRoot) { @@ -52,13 +54,13 @@ public class RunScriptOptions { * By default, true. * @return value */ - public boolean isOverrideCredentials() { - return overrideCredentials; + public Credentials getOverrideCredentials() { + return overridingCredentials; } /** - * Whether to run the script as root (run with current privileges). - * By default, false. + * Whether to run the script as root (or run with current privileges). + * By default, true. * @return value */ public boolean isRunAsRoot() { @@ -68,9 +70,9 @@ public class RunScriptOptions { public static class Builder { private RunScriptOptions options; - public Builder overrideCredentials(boolean value) { + public Builder overrideCredentials(Credentials credentials) { if(options == null) options = new RunScriptOptions(); - options.overrideCredentials(value); + options.withOverridingCredentials(credentials); return this; } 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 84c600e748..ef6882223b 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java +++ b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java @@ -130,6 +130,10 @@ public class ComputeUtils { return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script); } + public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node, String scriptName, byte[] script) { + return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false); + } + public Map, ?> runCallablesOnNode(NodeMetadata node, Iterable> parallel, @Nullable SshCallable last) { checkState(this.sshFactory != null, "runScript requested, but no SshModule configured"); @@ -210,6 +214,7 @@ public class ComputeUtils { private final NodeMetadata node; private final String scriptName; private final byte[] script; + private final boolean runAsRoot; private Logger logger = Logger.NULL; RunScriptOnNode(@Named("NOT_RUNNING") Predicate runScriptNotRunning, @@ -221,6 +226,19 @@ public class ComputeUtils { . of(), Iterables.toArray(Splitter.on("\n").split( new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX) .getBytes(); + this.runAsRoot = true; + } + + RunScriptOnNode(@Named("NOT_RUNNING") Predicate runScriptNotRunning, + NodeMetadata node, String scriptName, byte[] script, boolean runAsRoot) { + this.runScriptNotRunning = runScriptNotRunning; + this.node = checkNotNull(node, "node"); + this.scriptName = checkNotNull(scriptName, "scriptName"); + this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap + . of(), Iterables.toArray(Splitter.on("\n").split( + new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX) + .getBytes(); + this.runAsRoot = runAsRoot; } @Override @@ -228,21 +246,9 @@ public class ComputeUtils { ssh.put(scriptName, new ByteArrayInputStream(script)); ExecResponse returnVal = ssh.exec("chmod 755 " + scriptName); returnVal = ssh.exec("./" + scriptName + " init"); - if (node.getCredentials().account.equals("root")) { - logger.debug(">> running %s as %s@%s", scriptName, node.getCredentials().account, - Iterables.get(node.getPublicAddresses(), 0).getHostAddress()); - returnVal = ssh.exec("./" + scriptName + " start"); - } else if (isKeyAuth(node)) { - logger.debug(">> running sudo %s as %s@%s", scriptName, node.getCredentials().account, - Iterables.get(node.getPublicAddresses(), 0).getHostAddress()); - returnVal = ssh.exec("sudo ./" + scriptName + " start"); - } else { - logger.debug(">> running sudo -S %s as %s@%s", scriptName, - node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0) - .getHostAddress()); - returnVal = ssh.exec(String.format("echo %s|sudo -S ./%s", node.getCredentials().key, - scriptName + " start")); - } + + if(runAsRoot) returnVal = runScriptAsRoot(); + else returnVal = runScriptAsDefaultUser(); runScriptNotRunning.apply(ssh); logger.debug("<< complete(%d)", returnVal.getExitCode()); return returnVal; @@ -253,6 +259,31 @@ public class ComputeUtils { this.logger = checkNotNull(logger, "logger"); this.ssh = checkNotNull(ssh, "ssh"); } + + private ExecResponse runScriptAsRoot() { + if (node.getCredentials().account.equals("root")) { + logger.debug(">> running %s as %s@%s", scriptName, node.getCredentials().account, + Iterables.get(node.getPublicAddresses(), 0).getHostAddress()); + return ssh.exec("./" + scriptName + " start"); + } else if (isKeyAuth(node)) { + logger.debug(">> running sudo %s as %s@%s", scriptName, node.getCredentials().account, + Iterables.get(node.getPublicAddresses(), 0).getHostAddress()); + return ssh.exec("sudo ./" + scriptName + " start"); + } else { + logger.debug(">> running sudo -S %s as %s@%s", scriptName, + node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0) + .getHostAddress()); + return ssh.exec(String.format("echo %s|sudo -S ./%s", node.getCredentials().key, + scriptName + " start")); + } + } + + private ExecResponse runScriptAsDefaultUser() { + logger.debug(">> running script %s as %s@%s", scriptName, + node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0) + .getHostAddress()); + return ssh.exec(String.format("./%s", scriptName + " start")); + } } public static class InstallRSAPrivateKey implements SshCallable {