View Javadoc

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 }