PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

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