PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/compute/src/test/java/org/jclouds/compute/callables/RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilCompleteTest.java

https://github.com/richardcloudsoft/legacy-jclouds
Java | 344 lines | 227 code | 75 blank | 42 comment | 0 complexity | f84893d7530714df162e0db7f6d87386 MD5 | raw file
  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. import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
  21. import static com.google.inject.name.Names.named;
  22. import static org.easymock.EasyMock.createMock;
  23. import static org.easymock.EasyMock.expect;
  24. import static org.easymock.EasyMock.replay;
  25. import static org.easymock.EasyMock.verify;
  26. import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
  27. import static org.jclouds.Constants.PROPERTY_USER_THREADS;
  28. import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
  29. import static org.jclouds.scriptbuilder.domain.Statements.exec;
  30. import static org.testng.Assert.assertEquals;
  31. import org.jclouds.compute.domain.ExecResponse;
  32. import org.jclouds.compute.domain.NodeMetadata;
  33. import org.jclouds.compute.domain.NodeMetadata.Status;
  34. import org.jclouds.compute.domain.NodeMetadataBuilder;
  35. import org.jclouds.compute.options.RunScriptOptions;
  36. import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
  37. import org.jclouds.concurrent.config.ExecutorServiceModule;
  38. import org.jclouds.domain.LoginCredentials;
  39. import org.jclouds.scriptbuilder.InitScript;
  40. import org.jclouds.scriptbuilder.domain.OsFamily;
  41. import org.jclouds.scriptbuilder.domain.Statement;
  42. import org.jclouds.ssh.SshClient;
  43. import org.testng.annotations.Test;
  44. import com.google.common.base.Functions;
  45. import com.google.common.collect.ImmutableMap;
  46. import com.google.common.eventbus.EventBus;
  47. import com.google.inject.AbstractModule;
  48. import com.google.inject.Guice;
  49. import com.google.inject.Injector;
  50. import com.google.inject.assistedinject.FactoryModuleBuilder;
  51. /**
  52. * @author Adrian Cole
  53. */
  54. @Test(groups = "unit", singleThreaded = true, testName = "RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilCompleteTest")
  55. public class RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilCompleteTest {
  56. Injector injector = Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()),
  57. new AbstractModule() {
  58. protected void configure() {
  59. bindConstant().annotatedWith(named(PROPERTY_USER_THREADS)).to(1);
  60. bindConstant().annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).to(1);
  61. bindConstant().annotatedWith(named(TIMEOUT_SCRIPT_COMPLETE)).to(100);
  62. install(new FactoryModuleBuilder().build(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class));
  63. }
  64. });
  65. EventBus eventBus = new EventBus();
  66. BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory statusFactory = injector
  67. .getInstance(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class);
  68. // fail faster than normal
  69. Timeouts timeouts = injector.getInstance(Timeouts.class);
  70. @Test(expectedExceptions = IllegalStateException.class)
  71. public void testWithoutInitThrowsIllegalStateException() {
  72. Statement command = exec("doFoo");
  73. NodeMetadata node = new NodeMetadataBuilder().ids("id").status(Status.RUNNING).credentials(
  74. LoginCredentials.builder().user("tester").password("testpassword!").build()).build();
  75. SshClient sshClient = createMock(SshClient.class);
  76. replay(sshClient);
  77. RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete testMe = new RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete(
  78. statusFactory, timeouts, Functions.forMap(ImmutableMap.of(node, sshClient)),
  79. eventBus, InitScriptConfigurationForTasks.create().appendIncrementingNumberToAnonymousTaskNames(), node, command,
  80. new RunScriptOptions());
  81. testMe.call();
  82. }
  83. public void testDefault() {
  84. Statement command = exec("doFoo");
  85. NodeMetadata node = new NodeMetadataBuilder().ids("id").status(Status.RUNNING)
  86. .credentials(LoginCredentials.builder().user("tester").password("testpassword!").build()).build();
  87. SshClient sshClient = createMock(SshClient.class);
  88. InitScript init = InitScript.builder().name("jclouds-script-0").home("/tmp/jclouds-script-0").run(command)
  89. .build();
  90. sshClient.connect();
  91. sshClient.put("/tmp/init-jclouds-script-0", init.render(OsFamily.UNIX));
  92. expect(sshClient.getUsername()).andReturn("tester").atLeastOnce();
  93. expect(sshClient.getHostAddress()).andReturn("somewhere.example.com").atLeastOnce();
  94. // setup script as default user
  95. expect(sshClient.exec("chmod 755 /tmp/init-jclouds-script-0")).andReturn(new ExecResponse("", "", 0));
  96. expect(sshClient.exec("ln -fs /tmp/init-jclouds-script-0 jclouds-script-0")).andReturn(
  97. new ExecResponse("", "", 0));
  98. expect(sshClient.exec("/tmp/init-jclouds-script-0 init")).andReturn(new ExecResponse("", "", 0));
  99. // start script as root via sudo, note that since there's no adminPassword we do a straight
  100. // sudo
  101. expect(sshClient.exec("sudo /tmp/init-jclouds-script-0 start")).andReturn(new ExecResponse("", "", 0));
  102. // signal the command completed
  103. expect(sshClient.exec("/tmp/init-jclouds-script-0 status")).andReturn(new ExecResponse("", "", 1)).times(1);
  104. expect(sshClient.exec("/tmp/init-jclouds-script-0 stdout")).andReturn(new ExecResponse("out", "", 0));
  105. expect(sshClient.exec("/tmp/init-jclouds-script-0 stderr")).andReturn(new ExecResponse("err", "", 0));
  106. expect(sshClient.exec("/tmp/init-jclouds-script-0 exitstatus")).andReturn(new ExecResponse("0", "", 0));
  107. sshClient.disconnect();
  108. replay(sshClient);
  109. RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete testMe = new RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete(
  110. statusFactory, timeouts, Functions.forMap(ImmutableMap.of(node, sshClient)),
  111. eventBus, InitScriptConfigurationForTasks.create().appendIncrementingNumberToAnonymousTaskNames(), node, command,
  112. new RunScriptOptions());
  113. assertEquals(testMe.getInitFile(), "/tmp/init-jclouds-script-0");
  114. assertEquals(testMe.getNode(), node);
  115. assertEquals(testMe.getStatement(), init);
  116. testMe.init();
  117. assertEquals(testMe.call(), new ExecResponse("out", "err", 0));
  118. verify(sshClient);
  119. }
  120. public void testWithSudoPassword() {
  121. Statement command = exec("doFoo");
  122. NodeMetadata node = new NodeMetadataBuilder().ids("id").status(Status.RUNNING).credentials(
  123. LoginCredentials.builder().user("tester").password("testpassword!").authenticateSudo(true).build()).build();
  124. SshClient sshClient = createMock(SshClient.class);
  125. InitScript init = InitScript.builder().name("jclouds-script-0").home("/tmp/jclouds-script-0").run(command)
  126. .build();
  127. sshClient.connect();
  128. sshClient.put("/tmp/init-jclouds-script-0", init.render(OsFamily.UNIX));
  129. expect(sshClient.getUsername()).andReturn("tester").atLeastOnce();
  130. expect(sshClient.getHostAddress()).andReturn("somewhere.example.com").atLeastOnce();
  131. // setup script as default user
  132. expect(sshClient.exec("chmod 755 /tmp/init-jclouds-script-0")).andReturn(new ExecResponse("", "", 0));
  133. expect(sshClient.exec("ln -fs /tmp/init-jclouds-script-0 jclouds-script-0")).andReturn(
  134. new ExecResponse("", "", 0));
  135. expect(sshClient.exec("/tmp/init-jclouds-script-0 init")).andReturn(new ExecResponse("", "", 0));
  136. // since there's an adminPassword we must pass this in
  137. expect(sshClient.exec("echo 'testpassword!'|sudo -S /tmp/init-jclouds-script-0 start")).andReturn(new ExecResponse("", "", 0));
  138. // signal the command completed
  139. expect(sshClient.exec("/tmp/init-jclouds-script-0 status")).andReturn(new ExecResponse("", "", 1));
  140. expect(sshClient.exec("/tmp/init-jclouds-script-0 stdout")).andReturn(new ExecResponse("out", "", 0));
  141. expect(sshClient.exec("/tmp/init-jclouds-script-0 stderr")).andReturn(new ExecResponse("err", "", 0));
  142. expect(sshClient.exec("/tmp/init-jclouds-script-0 exitstatus")).andReturn(new ExecResponse("0", "", 0));
  143. sshClient.disconnect();
  144. replay(sshClient);
  145. RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete testMe = new RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete(
  146. statusFactory, timeouts, Functions.forMap(ImmutableMap.of(node, sshClient)),
  147. eventBus, InitScriptConfigurationForTasks.create().appendIncrementingNumberToAnonymousTaskNames(), node, command,
  148. new RunScriptOptions());
  149. assertEquals(testMe.getInitFile(), "/tmp/init-jclouds-script-0");
  150. assertEquals(testMe.getNode(), node);
  151. assertEquals(testMe.getStatement(), init);
  152. testMe.init();
  153. assertEquals(testMe.call(), new ExecResponse("out", "err", 0));
  154. verify(sshClient);
  155. }
  156. /**
  157. * in a couple versions of ubuntu on aws-ec2, status returneds no pid (ex. empty stdout w/exit code 1) transiently. sadly, we need to doublecheck status before assuming it has failed.
  158. *
  159. */
  160. public void testDoublecheckStatusInCaseTransientlyWrong() {
  161. Statement command = exec("doFoo");
  162. NodeMetadata node = new NodeMetadataBuilder().ids("id").status(Status.RUNNING).credentials(
  163. LoginCredentials.builder().user("tester").password("testpassword!").authenticateSudo(true).build()).build();
  164. SshClient sshClient = createMock(SshClient.class);
  165. InitScript init = InitScript.builder().name("jclouds-script-0").home("/tmp/jclouds-script-0").run(command)
  166. .build();
  167. sshClient.connect();
  168. sshClient.put("/tmp/init-jclouds-script-0", init.render(OsFamily.UNIX));
  169. expect(sshClient.getUsername()).andReturn("tester").atLeastOnce();
  170. expect(sshClient.getHostAddress()).andReturn("somewhere.example.com").atLeastOnce();
  171. // setup script as default user
  172. expect(sshClient.exec("chmod 755 /tmp/init-jclouds-script-0")).andReturn(new ExecResponse("", "", 0));
  173. expect(sshClient.exec("ln -fs /tmp/init-jclouds-script-0 jclouds-script-0")).andReturn(
  174. new ExecResponse("", "", 0));
  175. expect(sshClient.exec("/tmp/init-jclouds-script-0 init")).andReturn(new ExecResponse("", "", 0));
  176. // since there's an adminPassword we must pass this in
  177. expect(sshClient.exec("echo 'testpassword!'|sudo -S /tmp/init-jclouds-script-0 start")).andReturn(new ExecResponse("", "", 0));
  178. // signal the command completed
  179. expect(sshClient.exec("/tmp/init-jclouds-script-0 status")).andReturn(new ExecResponse("8001", "", 0));
  180. expect(sshClient.exec("/tmp/init-jclouds-script-0 status")).andReturn(new ExecResponse("", "", 1));
  181. expect(sshClient.exec("/tmp/init-jclouds-script-0 stdout")).andReturn(new ExecResponse("out", "", 0));
  182. expect(sshClient.exec("/tmp/init-jclouds-script-0 stderr")).andReturn(new ExecResponse("err", "", 0));
  183. expect(sshClient.exec("/tmp/init-jclouds-script-0 exitstatus")).andReturn(new ExecResponse("0", "", 0));
  184. sshClient.disconnect();
  185. replay(sshClient);
  186. RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete testMe = new RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete(
  187. statusFactory, timeouts, Functions.forMap(ImmutableMap.of(node, sshClient)),
  188. eventBus, InitScriptConfigurationForTasks.create().appendIncrementingNumberToAnonymousTaskNames(), node, command,
  189. new RunScriptOptions());
  190. assertEquals(testMe.getInitFile(), "/tmp/init-jclouds-script-0");
  191. assertEquals(testMe.getNode(), node);
  192. assertEquals(testMe.getStatement(), init);
  193. testMe.init();
  194. assertEquals(testMe.call(), new ExecResponse("out", "err", 0));
  195. verify(sshClient);
  196. }
  197. public void testNotRoot() {
  198. Statement command = exec("doFoo");
  199. NodeMetadata node = new NodeMetadataBuilder().ids("id").status(Status.RUNNING).credentials(
  200. LoginCredentials.builder().user("tester").password("testpassword!").authenticateSudo(true).build()).build();
  201. SshClient sshClient = createMock(SshClient.class);
  202. InitScript init = InitScript.builder().name("jclouds-script-0").home("/tmp/jclouds-script-0").run(command)
  203. .build();
  204. sshClient.connect();
  205. sshClient.put("/tmp/init-jclouds-script-0", init.render(OsFamily.UNIX));
  206. expect(sshClient.getUsername()).andReturn("tester").atLeastOnce();
  207. expect(sshClient.getHostAddress()).andReturn("somewhere.example.com").atLeastOnce();
  208. // setup script as default user
  209. expect(sshClient.exec("chmod 755 /tmp/init-jclouds-script-0")).andReturn(new ExecResponse("", "", 0));
  210. expect(sshClient.exec("ln -fs /tmp/init-jclouds-script-0 jclouds-script-0")).andReturn(
  211. new ExecResponse("", "", 0));
  212. expect(sshClient.exec("/tmp/init-jclouds-script-0 init")).andReturn(new ExecResponse("", "", 0));
  213. // kick off as current user
  214. expect(sshClient.exec("/tmp/init-jclouds-script-0 start")).andReturn(new ExecResponse("", "", 0));
  215. // signal the command completed
  216. expect(sshClient.exec("/tmp/init-jclouds-script-0 status")).andReturn(new ExecResponse("", "", 1));
  217. expect(sshClient.exec("/tmp/init-jclouds-script-0 stdout")).andReturn(new ExecResponse("out", "", 0));
  218. expect(sshClient.exec("/tmp/init-jclouds-script-0 stderr")).andReturn(new ExecResponse("err", "", 0));
  219. expect(sshClient.exec("/tmp/init-jclouds-script-0 exitstatus")).andReturn(new ExecResponse("0", "", 0));
  220. sshClient.disconnect();
  221. replay(sshClient);
  222. RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete testMe = new RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete(
  223. statusFactory, timeouts, Functions.forMap(ImmutableMap.of(node, sshClient)),
  224. eventBus, InitScriptConfigurationForTasks.create().appendIncrementingNumberToAnonymousTaskNames(), node, command,
  225. new RunScriptOptions().runAsRoot(false));
  226. assertEquals(testMe.getInitFile(), "/tmp/init-jclouds-script-0");
  227. assertEquals(testMe.getNode(), node);
  228. assertEquals(testMe.getStatement(), init);
  229. testMe.init();
  230. assertEquals(testMe.call(), new ExecResponse("out", "err", 0));
  231. verify(sshClient);
  232. }
  233. public void testBadReturnCode() {
  234. Statement command = exec("doFoo");
  235. NodeMetadata node = new NodeMetadataBuilder().ids("badreturncode").status(Status.RUNNING).credentials(
  236. LoginCredentials.builder().user("tester").password("testpassword!").authenticateSudo(true).build()).build();
  237. SshClient sshClient = createMock(SshClient.class);
  238. InitScript init = InitScript.builder().name("jclouds-script-0").home("/tmp/jclouds-script-0").run(command)
  239. .build();
  240. sshClient.connect();
  241. sshClient.put("/tmp/init-jclouds-script-0", init.render(OsFamily.UNIX));
  242. expect(sshClient.getUsername()).andReturn("tester").atLeastOnce();
  243. expect(sshClient.getHostAddress()).andReturn("somewhere.example.com").atLeastOnce();
  244. // setup script as default user
  245. expect(sshClient.exec("chmod 755 /tmp/init-jclouds-script-0")).andReturn(new ExecResponse("", "", 0));
  246. expect(sshClient.exec("ln -fs /tmp/init-jclouds-script-0 jclouds-script-0")).andReturn(
  247. new ExecResponse("", "", 0));
  248. expect(sshClient.exec("/tmp/init-jclouds-script-0 init")).andReturn(new ExecResponse("", "", 0));
  249. // kick off as current user
  250. expect(sshClient.exec("/tmp/init-jclouds-script-0 start")).andReturn(new ExecResponse("", "", 0));
  251. // signal the command completed
  252. expect(sshClient.exec("/tmp/init-jclouds-script-0 status")).andReturn(new ExecResponse("", "", 1));
  253. expect(sshClient.exec("/tmp/init-jclouds-script-0 stdout")).andReturn(new ExecResponse("out", "", 0));
  254. expect(sshClient.exec("/tmp/init-jclouds-script-0 stderr")).andReturn(new ExecResponse("err", "", 0));
  255. expect(sshClient.exec("/tmp/init-jclouds-script-0 exitstatus")).andReturn(new ExecResponse("1", "", 0));
  256. sshClient.disconnect();
  257. replay(sshClient);
  258. RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete testMe = new RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete(
  259. statusFactory, timeouts, Functions.forMap(ImmutableMap.of(node, sshClient)),
  260. eventBus, InitScriptConfigurationForTasks.create().appendIncrementingNumberToAnonymousTaskNames(), node, command,
  261. new RunScriptOptions().runAsRoot(false));
  262. assertEquals(testMe.getInitFile(), "/tmp/init-jclouds-script-0");
  263. assertEquals(testMe.getNode(), node);
  264. assertEquals(testMe.getStatement(), init);
  265. testMe.init();
  266. assertEquals(testMe.call(), new ExecResponse("out", "err", 1));
  267. verify(sshClient);
  268. }
  269. }