1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.compute.callables;
20
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkState;
23
24 import javax.annotation.Resource;
25 import javax.inject.Named;
26
27 import org.jclouds.compute.domain.ExecResponse;
28 import org.jclouds.compute.domain.NodeMetadata;
29 import org.jclouds.compute.options.RunScriptOptions;
30 import org.jclouds.compute.reference.ComputeServiceConstants;
31 import org.jclouds.logging.Logger;
32 import org.jclouds.scriptbuilder.domain.OsFamily;
33 import org.jclouds.scriptbuilder.domain.Statement;
34 import org.jclouds.ssh.SshClient;
35
36 import com.google.common.annotations.VisibleForTesting;
37 import com.google.common.base.Function;
38 import com.google.common.base.Objects;
39 import com.google.inject.assistedinject.Assisted;
40 import com.google.inject.assistedinject.AssistedInject;
41
42
43
44
45
46 public class RunScriptOnNodeUsingSsh implements RunScriptOnNode {
47 @Resource
48 @Named(ComputeServiceConstants.COMPUTE_LOGGER)
49 protected Logger logger = Logger.NULL;
50
51 protected final Function<NodeMetadata, SshClient> sshFactory;
52 protected final NodeMetadata node;
53 protected final Statement statement;
54 protected final boolean runAsRoot;
55
56 protected SshClient ssh;
57
58 @AssistedInject
59 public RunScriptOnNodeUsingSsh(Function<NodeMetadata, SshClient> sshFactory, @Assisted NodeMetadata node,
60 @Assisted Statement statement, @Assisted RunScriptOptions options) {
61 this.sshFactory = checkNotNull(sshFactory, "sshFactory");
62 this.node = checkNotNull(node, "node");
63 this.statement = checkNotNull(statement, "statement");
64 this.runAsRoot = options.shouldRunAsRoot();
65 }
66
67 @Override
68 public ExecResponse call() {
69 checkState(ssh != null, "please call init() before invoking call");
70 try {
71 ssh.connect();
72 ExecResponse returnVal;
73 String command = (runAsRoot) ? execAsRoot(statement.render(OsFamily.UNIX)) : execScriptAsDefaultUser(statement
74 .render(OsFamily.UNIX));
75 returnVal = runCommand(command);
76 if (logger.isTraceEnabled())
77 logger.trace("<< %s[%s]", statement, returnVal);
78 else
79 logger.debug("<< %s(%d)", statement, returnVal.getExitCode());
80 return returnVal;
81 } finally {
82 if (ssh != null)
83 ssh.disconnect();
84 }
85 }
86
87 @Override
88 public RunScriptOnNode init() {
89 ssh = sshFactory.apply(node);
90 return this;
91 }
92
93 protected ExecResponse runCommand(String command) {
94 ExecResponse returnVal;
95 logger.debug(">> running [%s] as %s@%s", command.replace(node.getAdminPassword() != null ? node
96 .getAdminPassword() : "XXXXX", "XXXXX"), ssh.getUsername(), ssh.getHostAddress());
97 returnVal = ssh.exec(command);
98 return returnVal;
99 }
100
101 @VisibleForTesting
102 public String execAsRoot(String command) {
103 if (node.getCredentials().identity.equals("root")) {
104 } else if (node.getAdminPassword() != null) {
105 command = String.format("echo '%s'|sudo -S %s", node.getAdminPassword(), command);
106 } else {
107 command = "sudo " + command;
108 }
109 return command;
110 }
111
112 protected String execScriptAsDefaultUser(String command) {
113 return command;
114 }
115
116 public NodeMetadata getNode() {
117 return node;
118 }
119
120 @Override
121 public String toString() {
122 return Objects.toStringHelper(this).add("node", node).add("name", statement).add("runAsRoot", runAsRoot)
123 .toString();
124 }
125
126 }