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 public static final String MARKER = "RUN_SCRIPT_AS_ROOT_SSH";
48
49 @Resource
50 @Named(ComputeServiceConstants.COMPUTE_LOGGER)
51 protected Logger logger = Logger.NULL;
52
53 protected final Function<NodeMetadata, SshClient> sshFactory;
54 protected final NodeMetadata node;
55 protected final Statement statement;
56 protected final boolean runAsRoot;
57
58 protected SshClient ssh;
59
60 @AssistedInject
61 public RunScriptOnNodeUsingSsh(Function<NodeMetadata, SshClient> sshFactory, @Assisted NodeMetadata node,
62 @Assisted Statement statement, @Assisted RunScriptOptions options) {
63 this.sshFactory = checkNotNull(sshFactory, "sshFactory");
64 this.node = checkNotNull(node, "node");
65 this.statement = checkNotNull(statement, "statement");
66 this.runAsRoot = options.shouldRunAsRoot();
67 }
68
69 @Override
70 public ExecResponse call() {
71 checkState(ssh != null, "please call init() before invoking call");
72 try {
73 ssh.connect();
74 ExecResponse returnVal;
75 String command = (runAsRoot) ? execAsRoot(statement.render(OsFamily.UNIX)) : execScriptAsDefaultUser(statement
76 .render(OsFamily.UNIX));
77 returnVal = runCommand(command);
78 if (logger.isTraceEnabled())
79 logger.trace("<< %s[%s]", statement, returnVal);
80 else
81 logger.debug("<< %s(%d)", statement, returnVal.getExitCode());
82 return returnVal;
83 } finally {
84 if (ssh != null)
85 ssh.disconnect();
86 }
87 }
88
89 @Override
90 public RunScriptOnNode init() {
91 ssh = sshFactory.apply(node);
92 return this;
93 }
94
95 protected ExecResponse runCommand(String command) {
96 ExecResponse returnVal;
97 logger.debug(">> running [%s] as %s@%s", command.replace(node.getAdminPassword() != null ? node
98 .getAdminPassword() : "XXXXX", "XXXXX"), ssh.getUsername(), ssh.getHostAddress());
99 returnVal = ssh.exec(command);
100 return returnVal;
101 }
102
103 @VisibleForTesting
104 public String execAsRoot(String command) {
105 if (node.getCredentials().identity.equals("root")) {
106 } else if (node.getAdminPassword() != null) {
107 command = String.format("sudo -S sh <<'%s'\n%s\n%s%s\n", MARKER, node.getAdminPassword(), command, MARKER);
108 } else {
109 command = String.format("sudo sh <<'%s'\n%s%s\n", MARKER, command, MARKER);
110 }
111 return command;
112 }
113
114 protected String execScriptAsDefaultUser(String command) {
115 return command;
116 }
117
118 public NodeMetadata getNode() {
119 return node;
120 }
121
122 @Override
123 public String toString() {
124 return Objects.toStringHelper(this).add("node", node).add("name", statement).add("runAsRoot", runAsRoot)
125 .toString();
126 }
127
128 @Override
129 public Statement getStatement() {
130 return statement;
131 }
132
133 }