View Javadoc

1   /**
2    * Licensed to jclouds, Inc. (jclouds) under one or more
3    * contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  jclouds licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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     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 }