EMMA Coverage Report (generated Wed Jun 22 19:47:49 EDT 2011)
[all classes][org.jclouds.compute.callables]

COVERAGE SUMMARY FOR SOURCE FILE [RunScriptOnNodeAsInitScriptUsingSsh.java]

nameclass, %method, %block, %line, %
RunScriptOnNodeAsInitScriptUsingSsh.java0%   (0/1)0%   (0/12)0%   (0/396)0%   (0/49)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RunScriptOnNodeAsInitScriptUsingSsh0%   (0/1)0%   (0/12)0%   (0/396)0%   (0/49)
RunScriptOnNodeAsInitScriptUsingSsh (Function, NodeMetadata, Statement, RunSc... 0%   (0/1)0%   (0/72)0%   (0/14)
call (): ExecResponse 0%   (0/1)0%   (0/31)0%   (0/5)
createInitScript (String, Statement): InitBuilder 0%   (0/1)0%   (0/19)0%   (0/2)
doCall (): ExecResponse 0%   (0/1)0%   (0/72)0%   (0/7)
execScriptAsDefaultUser (String): String 0%   (0/1)0%   (0/14)0%   (0/1)
execScriptAsRoot (String): String 0%   (0/1)0%   (0/63)0%   (0/6)
getNode (): NodeMetadata 0%   (0/1)0%   (0/3)0%   (0/1)
getStatement (): Statement 0%   (0/1)0%   (0/3)0%   (0/1)
init (): RunScriptOnNode 0%   (0/1)0%   (0/10)0%   (0/2)
runAction (String): ExecResponse 0%   (0/1)0%   (0/52)0%   (0/6)
runCommand (String): ExecResponse 0%   (0/1)0%   (0/40)0%   (0/3)
toString (): String 0%   (0/1)0%   (0/17)0%   (0/1)

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 */
19package org.jclouds.compute.callables;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22import static com.google.common.base.Preconditions.checkState;
23 
24import java.util.Collections;
25 
26import javax.annotation.Resource;
27import javax.inject.Named;
28 
29import org.jclouds.compute.domain.ExecResponse;
30import org.jclouds.compute.domain.NodeMetadata;
31import org.jclouds.compute.options.RunScriptOptions;
32import org.jclouds.compute.reference.ComputeServiceConstants;
33import org.jclouds.logging.Logger;
34import org.jclouds.scriptbuilder.InitBuilder;
35import org.jclouds.scriptbuilder.domain.AppendFile;
36import org.jclouds.scriptbuilder.domain.OsFamily;
37import org.jclouds.scriptbuilder.domain.Statement;
38import org.jclouds.scriptbuilder.domain.Statements;
39import org.jclouds.ssh.SshClient;
40 
41import com.google.common.annotations.VisibleForTesting;
42import com.google.common.base.Function;
43import com.google.common.base.Objects;
44import com.google.common.base.Splitter;
45import com.google.inject.Inject;
46import com.google.inject.assistedinject.Assisted;
47import com.google.inject.assistedinject.AssistedInject;
48 
49/**
50 * 
51 * @author Adrian Cole
52 */
53public class RunScriptOnNodeAsInitScriptUsingSsh implements RunScriptOnNode {
54   public static final String PROPERTY_PUSH_INIT_SCRIPT_VIA_SFTP = "jclouds.compute.push-init-script-via-sftp";
55   @Resource
56   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
57   protected Logger logger = Logger.NULL;
58 
59   protected final Function<NodeMetadata, SshClient> sshFactory;
60   protected final NodeMetadata node;
61   protected final Statement init;
62   protected final String name;
63   protected final boolean runAsRoot;
64 
65   protected SshClient ssh;
66 
67   /**
68    * true to use sftp, false to use ssh. If there's a problem with the sftp configuration, setting
69    * this to false will help.
70    */
71   @Inject(optional = true)
72   @Named(PROPERTY_PUSH_INIT_SCRIPT_VIA_SFTP)
73   private boolean pushInitViaSftp = true;
74 
75   @AssistedInject
76   public RunScriptOnNodeAsInitScriptUsingSsh(Function<NodeMetadata, SshClient> sshFactory,
77            @Assisted NodeMetadata node, @Assisted Statement script, @Assisted RunScriptOptions options) {
78      this.sshFactory = checkNotNull(sshFactory, "sshFactory");
79      this.node = checkNotNull(node, "node");
80      String name = options.getTaskName();
81      if (name == null) {
82         if (checkNotNull(script, "script") instanceof InitBuilder)
83            name = InitBuilder.class.cast(script).getInstanceName();
84         else
85            name = "jclouds-script-" + System.currentTimeMillis();
86      }
87      this.name = checkNotNull(name, "name");
88      this.init = checkNotNull(script, "script") instanceof InitBuilder ? InitBuilder.class.cast(script)
89               : createInitScript(name, script);
90      this.runAsRoot = options.shouldRunAsRoot();
91   }
92 
93   public static InitBuilder createInitScript(String name, Statement script) {
94      String path = "/tmp/" + name;
95      return new InitBuilder(name, path, path, Collections.<String, String> emptyMap(), Collections.singleton(script));
96   }
97 
98   @Override
99   public ExecResponse call() {
100      checkState(ssh != null, "please call init() before invoking call");
101      try {
102         ssh.connect();
103         return doCall();
104      } finally {
105         if (ssh != null)
106            ssh.disconnect();
107      }
108   }
109 
110   @Override
111   public RunScriptOnNode init() {
112      ssh = sshFactory.apply(node);
113      return this;
114   }
115 
116   /**
117    * ssh client is initialized through this call.
118    */
119   protected ExecResponse doCall() {
120      if (pushInitViaSftp) {
121         ssh.put(name, init.render(OsFamily.UNIX));
122      } else {
123         ssh.exec("rm " + name);
124         ssh.exec(Statements.appendFile(name, Splitter.on('\n').split(init.render(OsFamily.UNIX)),
125                  AppendFile.MARKER + "_" + name).render(OsFamily.UNIX));
126      }
127      ssh.exec("chmod 755 " + name);
128      runAction("init");
129      return runAction("start");
130   }
131 
132   protected ExecResponse runAction(String action) {
133      ExecResponse returnVal;
134      String command = (runAsRoot) ? execScriptAsRoot(action) : execScriptAsDefaultUser(action);
135      returnVal = runCommand(command);
136      if (logger.isTraceEnabled())
137         logger.trace("<< %s[%s]", action, returnVal);
138      else
139         logger.debug("<< %s(%d)", action, returnVal.getExitCode());
140      return returnVal;
141   }
142 
143   protected ExecResponse runCommand(String command) {
144      ExecResponse returnVal;
145      logger.debug(">> running [%s] as %s@%s", command.replace(node.getAdminPassword() != null ? node
146               .getAdminPassword() : "XXXXX", "XXXXX"), ssh.getUsername(), ssh.getHostAddress());
147      returnVal = ssh.exec(command);
148      return returnVal;
149   }
150 
151   @VisibleForTesting
152   public String execScriptAsRoot(String action) {
153      String command;
154      if (node.getCredentials().identity.equals("root")) {
155         command = "./" + name + " " + action;
156      } else if (node.getAdminPassword() != null) {
157         command = String.format("echo '%s'|sudo -S ./%s %s", node.getAdminPassword(), name, action);
158      } else {
159         command = "sudo ./" + name + " " + action;
160      }
161      return command;
162   }
163 
164   protected String execScriptAsDefaultUser(String action) {
165      return "./" + name + " " + action;
166   }
167 
168   public NodeMetadata getNode() {
169      return node;
170   }
171 
172   @Override
173   public String toString() {
174      return Objects.toStringHelper(this).add("node", node).add("name", name).add("runAsRoot", runAsRoot).toString();
175   }
176 
177   @Override
178   public Statement getStatement() {
179      return init;
180   }
181 
182}

[all classes][org.jclouds.compute.callables]
EMMA 2.0.5312 (C) Vladimir Roubtsov