1 | /** |
2 | * |
3 | * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com> |
4 | * |
5 | * ==================================================================== |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
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 | * @author Adrian Cole |
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 | } |