mirror of https://github.com/apache/jclouds.git
Issue 220: added stub compute provider
This commit is contained in:
parent
f701e44049
commit
14e16fbfa6
|
@ -32,5 +32,7 @@ bluelock.contextbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudContextBuilder
|
||||||
bluelock.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudPropertiesBuilder
|
bluelock.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloudPropertiesBuilder
|
||||||
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
|
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
|
||||||
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder
|
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder
|
||||||
|
stub.propertiesbuilder=org.jclouds.compute.stub.StubComputeServicePropertiesBuilder
|
||||||
|
stub.contextbuilder=org.jclouds.compute.stub.StubComputeServiceContextBuilder
|
||||||
# example of where to change your endpoint
|
# example of where to change your endpoint
|
||||||
# bluelock.endpoint=https://express3.bluelock.com/api
|
# bluelock.endpoint=https://express3.bluelock.com/api
|
||||||
|
|
|
@ -29,3 +29,22 @@ list, Alan Dipert and MeikelBrandmeyer."
|
||||||
(deftest os-families-test
|
(deftest os-families-test
|
||||||
(is (some #{"centos"} (map str (os-families)))))
|
(is (some #{"centos"} (map str (os-families)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn clean-stub-fixture
|
||||||
|
"This should allow basic tests to easily be run with another service."
|
||||||
|
[service account key & options]
|
||||||
|
(fn [f]
|
||||||
|
(with-compute-service [(apply compute-service service account key options)]
|
||||||
|
(doseq [node (nodes)]
|
||||||
|
(destroy-node (.getId node)))
|
||||||
|
(f))))
|
||||||
|
|
||||||
|
(use-fixtures :each (clean-stub-fixture "stub" "" ""))
|
||||||
|
|
||||||
|
(deftest compute-service?-test
|
||||||
|
(is (compute-service? *compute*)))
|
||||||
|
|
||||||
|
(deftest as-compute-service-test
|
||||||
|
(is (compute-service? (compute-service "stub" "user" "password")))
|
||||||
|
(is (compute-service? (as-compute-service *compute*)))
|
||||||
|
(is (compute-service? (as-compute-service (compute-context *compute*)))))
|
|
@ -80,7 +80,7 @@ import com.google.inject.Module;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", sequential = true, testName = "compute.ComputeServiceLiveTest")
|
@Test(groups = { "integration", "live" }, sequential = true, testName = "compute.ComputeServiceLiveTest")
|
||||||
public abstract class BaseComputeServiceLiveTest {
|
public abstract class BaseComputeServiceLiveTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
abstract public void setServiceDefaults();
|
abstract public void setServiceDefaults();
|
||||||
|
@ -98,13 +98,12 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
protected Template template;
|
protected Template template;
|
||||||
protected Map<String, String> keyPair;
|
protected Map<String, String> keyPair;
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "integration", "live" })
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
||||||
IOException {
|
IOException {
|
||||||
if (tag == null)
|
if (tag == null)
|
||||||
tag = checkNotNull(service, "service");
|
tag = checkNotNull(service, "service");
|
||||||
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
setupCredentials();
|
||||||
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
|
||||||
String secretKeyFile;
|
String secretKeyFile;
|
||||||
try {
|
try {
|
||||||
secretKeyFile = checkNotNull(System.getProperty("jclouds.test.ssh.keyfile"),
|
secretKeyFile = checkNotNull(System.getProperty("jclouds.test.ssh.keyfile"),
|
||||||
|
@ -115,17 +114,25 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
checkSecretKeyFile(secretKeyFile);
|
checkSecretKeyFile(secretKeyFile);
|
||||||
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
|
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
|
||||||
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
|
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
|
||||||
|
keyPair = ImmutableMap.<String, String> of("private", secret, "public", Files.toString(
|
||||||
|
new File(secretKeyFile + ".pub"), Charsets.UTF_8));
|
||||||
initializeContextAndClient();
|
initializeContextAndClient();
|
||||||
|
|
||||||
Injector injector = Guice.createInjector(getSshModule());
|
Injector injector = createSshClientInjector();
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
sshFactory = injector.getInstance(SshClient.Factory.class);
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
||||||
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
||||||
injector.injectMembers(socketOpen); // add logger
|
injector.injectMembers(socketOpen); // add logger
|
||||||
// keyPair = sshFactory.generateRSAKeyPair("", "");
|
// keyPair = sshFactory.generateRSAKeyPair("", "");
|
||||||
keyPair = ImmutableMap.<String, String> of("private", secret, "public", Files.toString(
|
}
|
||||||
new File(secretKeyFile + ".pub"), Charsets.UTF_8));
|
|
||||||
|
protected void setupCredentials() {
|
||||||
|
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||||
|
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Injector createSshClientInjector() {
|
||||||
|
return Guice.createInjector(getSshModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeContextAndClient() throws IOException {
|
private void initializeContextAndClient() throws IOException {
|
||||||
|
@ -153,7 +160,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
ImmutableSet.<Module> of(new Log4JLoggingModule())).close();
|
ImmutableSet.<Module> of(new Log4JLoggingModule())).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
|
@Test(enabled = true)
|
||||||
public void testImagesCache() throws Exception {
|
public void testImagesCache() throws Exception {
|
||||||
client.listImages();
|
client.listImages();
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
|
@ -162,6 +169,42 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
assert duration < 1000 : String.format("%dms to get images", duration);
|
assert duration < 1000 : String.format("%dms to get images", duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// since surefire and eclipse don't otherwise guarantee the order, we are
|
||||||
|
// starting this one alphabetically before create2nodes..
|
||||||
|
@Test(enabled = true, dependsOnMethods = "testImagesCache")
|
||||||
|
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
|
||||||
|
String tag = this.tag + "run";
|
||||||
|
try {
|
||||||
|
client.destroyNodesMatching(NodePredicates.withTag(tag));
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateOptions options = client.templateOptions().blockOnPort(22, 120);
|
||||||
|
try {
|
||||||
|
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
|
||||||
|
Credentials good = nodes.iterator().next().getCredentials();
|
||||||
|
assert good.account != null;
|
||||||
|
assert good.key != null;
|
||||||
|
|
||||||
|
Image image = Iterables.get(nodes, 0).getImage();
|
||||||
|
try {
|
||||||
|
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, image
|
||||||
|
.getOsFamily(), new Credentials(good.account, "romeo"));
|
||||||
|
assert false : "shouldn't pass with a bad password\n" + responses;
|
||||||
|
} catch (RunScriptOnNodesException e) {
|
||||||
|
assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e;
|
||||||
|
}
|
||||||
|
|
||||||
|
runScriptWithCreds(tag, image.getOsFamily(), good);
|
||||||
|
|
||||||
|
checkNodes(nodes, tag);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
client.destroyNodesMatching(NodePredicates.withTag(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testImagesCache")
|
@Test(enabled = true, dependsOnMethods = "testImagesCache")
|
||||||
public void testTemplateMatch() throws Exception {
|
public void testTemplateMatch() throws Exception {
|
||||||
template = buildTemplate(client.templateBuilder());
|
template = buildTemplate(client.templateBuilder());
|
||||||
|
@ -225,40 +268,6 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
assertEquals(node.getImage(), template.getImage());
|
assertEquals(node.getImage(), template.getImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
|
|
||||||
public void testScriptExecutionAfterBootWithBasicTemplate() throws Exception {
|
|
||||||
String tag = this.tag + "run";
|
|
||||||
try {
|
|
||||||
client.destroyNodesMatching(NodePredicates.withTag(tag));
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateOptions options = client.templateOptions().blockOnPort(22, 120);
|
|
||||||
try {
|
|
||||||
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
|
|
||||||
Credentials good = nodes.iterator().next().getCredentials();
|
|
||||||
assert good.account != null;
|
|
||||||
assert good.key != null;
|
|
||||||
|
|
||||||
Image image = Iterables.get(nodes, 0).getImage();
|
|
||||||
try {
|
|
||||||
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, image
|
|
||||||
.getOsFamily(), new Credentials(good.account, "romeo"));
|
|
||||||
assert false : "shouldn't pass with a bad password\n" + responses;
|
|
||||||
} catch (RunScriptOnNodesException e) {
|
|
||||||
assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e;
|
|
||||||
}
|
|
||||||
|
|
||||||
runScriptWithCreds(tag, image.getOsFamily(), good);
|
|
||||||
|
|
||||||
checkNodes(nodes, tag);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
client.destroyNodesMatching(NodePredicates.withTag(tag));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag,
|
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag,
|
||||||
OsFamily osFamily, Credentials creds) throws RunScriptOnNodesException {
|
OsFamily osFamily, Credentials creds) throws RunScriptOnNodesException {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,310 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.compute;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.easymock.EasyMock.aryEq;
|
||||||
|
import static org.easymock.EasyMock.eq;
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.reportMatcher;
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import org.easymock.IArgumentMatcher;
|
||||||
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceContextModule.StubNodeMetadata;
|
||||||
|
import org.jclouds.net.IPSocket;
|
||||||
|
import org.jclouds.predicates.SocketOpen;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
import org.jclouds.scriptbuilder.InitBuilder;
|
||||||
|
import org.jclouds.ssh.ExecResponse;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.ssh.SshException;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", enabled = true, sequential = true, testName = "stub.StubComputeServiceIntegrationTest")
|
||||||
|
public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTest {
|
||||||
|
|
||||||
|
private static final ExecResponse EXEC_GOOD = new ExecResponse("", "", 0);
|
||||||
|
private static final ExecResponse EXEC_BAD = new ExecResponse("", "", 1);
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
@Override
|
||||||
|
public void setServiceDefaults() {
|
||||||
|
service = "stub";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testCorrectAuthException() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTemplateBuilder() {
|
||||||
|
Template defaultTemplate = client.templateBuilder().build();
|
||||||
|
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64);
|
||||||
|
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU);
|
||||||
|
assertEquals(defaultTemplate.getLocation().getId(), "memory");
|
||||||
|
assertEquals(defaultTemplate.getSize().getCores(), 4.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Injector createSshClientInjector() {
|
||||||
|
return Guice.createInjector(new AbstractModule() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
SshClient.Factory factory = createMock(SshClient.Factory.class);
|
||||||
|
SocketOpen open = createMock(SocketOpen.class);
|
||||||
|
SshClient client1 = createMock(SshClient.class);
|
||||||
|
SshClient client2 = createMock(SshClient.class);
|
||||||
|
SshClient client3 = createMock(SshClient.class);
|
||||||
|
SshClient client4 = createMock(SshClient.class);
|
||||||
|
|
||||||
|
expect(open.apply(new IPSocket("144.175.1.1", 22))).andReturn(true);
|
||||||
|
expect(open.apply(new IPSocket("144.175.1.2", 22))).andReturn(true);
|
||||||
|
expect(open.apply(new IPSocket("144.175.1.3", 22))).andReturn(true);
|
||||||
|
expect(open.apply(new IPSocket("144.175.1.4", 22))).andReturn(true);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair
|
||||||
|
.get("private").getBytes()))).andReturn(client1).atLeastOnce();
|
||||||
|
expect(
|
||||||
|
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair
|
||||||
|
.get("private").getBytes()))).andReturn(client2).atLeastOnce();
|
||||||
|
expect(
|
||||||
|
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair
|
||||||
|
.get("private").getBytes()))).andReturn(client3).atLeastOnce();
|
||||||
|
expect(
|
||||||
|
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair
|
||||||
|
.get("private").getBytes()))).andReturn(client4).atLeastOnce();
|
||||||
|
|
||||||
|
helloAndJava(client1);
|
||||||
|
helloAndJava(client2);
|
||||||
|
helloAndJava(client3);
|
||||||
|
helloAndJava(client4);
|
||||||
|
|
||||||
|
replay(open);
|
||||||
|
replay(factory);
|
||||||
|
replay(client1);
|
||||||
|
replay(client2);
|
||||||
|
replay(client3);
|
||||||
|
replay(client4);
|
||||||
|
|
||||||
|
bind(SshClient.Factory.class).toInstance(factory);
|
||||||
|
|
||||||
|
bind(SocketOpen.class).toInstance(open);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void helloAndJava(SshClient client) {
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
expect(client.exec("echo hello")).andReturn(new ExecResponse("hello", "", 0));
|
||||||
|
expect(client.exec("java -version")).andReturn(new ExecResponse("", "OpenJDK", 0));
|
||||||
|
|
||||||
|
client.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Module getSshModule() {
|
||||||
|
return new AbstractModule() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
SshClient.Factory factory = createMock(SshClient.Factory.class);
|
||||||
|
SshClient client1 = createMock(SshClient.class);
|
||||||
|
SshClient client2 = createMock(SshClient.class);
|
||||||
|
SshClient client3 = createMock(SshClient.class);
|
||||||
|
SshClient client4 = createMock(SshClient.class);
|
||||||
|
|
||||||
|
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "romeo")).andThrow(
|
||||||
|
new SshException("Auth fail"));
|
||||||
|
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(
|
||||||
|
client1).atLeastOnce();
|
||||||
|
|
||||||
|
client1.connect();
|
||||||
|
runScript(client1, "computeserv", 1);
|
||||||
|
client1.disconnect();
|
||||||
|
|
||||||
|
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(
|
||||||
|
client2).atLeastOnce();
|
||||||
|
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(
|
||||||
|
client3).atLeastOnce();
|
||||||
|
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(
|
||||||
|
client4).atLeastOnce();
|
||||||
|
|
||||||
|
runScriptAndInstallSsh(client2, "runscript", 2);
|
||||||
|
runScriptAndInstallSsh(client3, "runscript", 3);
|
||||||
|
runScriptAndInstallSsh(client4, "runscript", 4);
|
||||||
|
|
||||||
|
replay(factory);
|
||||||
|
replay(client1);
|
||||||
|
replay(client2);
|
||||||
|
replay(client3);
|
||||||
|
replay(client4);
|
||||||
|
|
||||||
|
bind(SshClient.Factory.class).toInstance(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runScriptAndInstallSsh(SshClient client, String scriptName, int nodeId) {
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
runScript(client, scriptName, nodeId);
|
||||||
|
|
||||||
|
expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD);
|
||||||
|
expect(client.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys")).andReturn(EXEC_GOOD);
|
||||||
|
expect(client.exec("chmod 600 .ssh/authorized_keys")).andReturn(EXEC_GOOD);
|
||||||
|
client.put(eq(".ssh/id_rsa.pub"), isEq(keyPair.get("public")));
|
||||||
|
|
||||||
|
expect(client.exec("mkdir .ssh")).andReturn(EXEC_GOOD);
|
||||||
|
client.put(eq(".ssh/id_rsa"), isEq(keyPair.get("private")));
|
||||||
|
expect(client.exec("chmod 600 .ssh/id_rsa")).andReturn(EXEC_GOOD);
|
||||||
|
|
||||||
|
client.disconnect();
|
||||||
|
client.disconnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runScript(SshClient client, String scriptName, int nodeId) {
|
||||||
|
client.put(eq("" + scriptName + ""), isEq(initScript(scriptName,
|
||||||
|
buildScript(OsFamily.UBUNTU))));
|
||||||
|
|
||||||
|
expect(client.exec("chmod 755 " + scriptName + "")).andReturn(EXEC_GOOD);
|
||||||
|
expect(client.getUsername()).andReturn("root").atLeastOnce();
|
||||||
|
expect(client.getHostAddress()).andReturn(nodeId + "").atLeastOnce();
|
||||||
|
expect(client.exec("./" + scriptName + " init")).andReturn(EXEC_GOOD);
|
||||||
|
expect(client.exec("./" + scriptName + " start")).andReturn(EXEC_GOOD);
|
||||||
|
expect(client.exec("./" + scriptName + " status")).andReturn(EXEC_GOOD);
|
||||||
|
// next status says the script is done, since not found.
|
||||||
|
expect(client.exec("./" + scriptName + " status")).andReturn(EXEC_BAD);
|
||||||
|
expect(client.exec("./" + scriptName + " tail")).andReturn(EXEC_GOOD);
|
||||||
|
expect(client.exec("./" + scriptName + " tailerr")).andReturn(EXEC_GOOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupCredentials() {
|
||||||
|
user = "stub";
|
||||||
|
password = "stub";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String initScript(String scriptName, String script) {
|
||||||
|
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName, ImmutableMap
|
||||||
|
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
||||||
|
new String(checkNotNull(script, "script"))), String.class))
|
||||||
|
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputStream isEq(String value) {
|
||||||
|
reportMatcher(new InputStreamEquals(value));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAssignability() throws Exception {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
RestContext<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> stubContext = new ComputeServiceContextFactory()
|
||||||
|
.createContext(service, user, password).getProviderSpecificContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class InputStreamEquals implements IArgumentMatcher, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 583055160049982067L;
|
||||||
|
|
||||||
|
private final Object expected;
|
||||||
|
|
||||||
|
public InputStreamEquals(Object expected) {
|
||||||
|
this.expected = expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(Object actual) {
|
||||||
|
if (this.expected == null) {
|
||||||
|
return actual == null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String real = Utils.toStringAndClose((InputStream) actual);
|
||||||
|
if (!expected.equals(real)) {
|
||||||
|
System.err.println(real);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendTo(StringBuffer buffer) {
|
||||||
|
appendQuoting(buffer);
|
||||||
|
buffer.append(expected);
|
||||||
|
appendQuoting(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendQuoting(StringBuffer buffer) {
|
||||||
|
if (expected instanceof String) {
|
||||||
|
buffer.append("\"");
|
||||||
|
} else if (expected instanceof Character) {
|
||||||
|
buffer.append("'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || !this.getClass().equals(o.getClass()))
|
||||||
|
return false;
|
||||||
|
InputStreamEquals other = (InputStreamEquals) o;
|
||||||
|
return this.expected == null && other.expected == null || this.expected != null
|
||||||
|
&& this.expected.equals(other.expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
throw new UnsupportedOperationException("hashCode() is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.compute.stub;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import org.jclouds.compute.ComputeServiceContextBuilder;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceContextModule;
|
||||||
|
import org.jclouds.compute.stub.config.StubComputeServiceContextModule.StubNodeMetadata;
|
||||||
|
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class StubComputeServiceContextBuilder
|
||||||
|
extends
|
||||||
|
ComputeServiceContextBuilder<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> {
|
||||||
|
|
||||||
|
public StubComputeServiceContextBuilder(String providerName, Properties props) {
|
||||||
|
super(providerName, new TypeLiteral<ConcurrentMap<Integer, StubNodeMetadata>>() {
|
||||||
|
}, new TypeLiteral<ConcurrentMap<Integer, StubNodeMetadata>>() {
|
||||||
|
}, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addContextModule(String providerName, List<Module> modules) {
|
||||||
|
modules.add(new StubComputeServiceContextModule(providerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addClientModule(List<Module> modules) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.compute.stub;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.PropertiesBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds properties used in stub compute services
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class StubComputeServicePropertiesBuilder extends PropertiesBuilder {
|
||||||
|
@Override
|
||||||
|
protected Properties defaultProperties() {
|
||||||
|
Properties properties = super.defaultProperties();
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StubComputeServicePropertiesBuilder(Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StubComputeServicePropertiesBuilder withCredentials(String id, String secret) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StubComputeServicePropertiesBuilder withEndpoint(URI endpoint) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,444 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.compute.stub.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
|
||||||
|
import static org.jclouds.compute.predicates.ImagePredicates.architectureIn;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.LoadBalancerService;
|
||||||
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.compute.domain.Size;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
|
import org.jclouds.compute.domain.internal.ImageImpl;
|
||||||
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
|
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
||||||
|
import org.jclouds.compute.predicates.NodePredicates;
|
||||||
|
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
|
||||||
|
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
||||||
|
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
|
||||||
|
import org.jclouds.compute.strategy.DestroyNodeStrategy;
|
||||||
|
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||||
|
import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||||
|
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||||
|
import org.jclouds.concurrent.SingleThreaded;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
|
import org.jclouds.lifecycle.Closer;
|
||||||
|
import org.jclouds.net.IPSocket;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.predicates.SocketOpen;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
import org.jclouds.rest.internal.RestContextImpl;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.Scopes;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.util.Providers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@SingleThreaded
|
||||||
|
public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
|
// STUB STUFF STATIC SO MULTIPLE CONTEXTS CAN SEE IT
|
||||||
|
private static final AtomicInteger nodeIds = new AtomicInteger(0);
|
||||||
|
private static final ConcurrentMap<Integer, StubNodeMetadata> nodes = new ConcurrentHashMap<Integer, StubNodeMetadata>();
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
ConcurrentMap<Integer, StubNodeMetadata> provideNodes() {
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named("NODE_ID")
|
||||||
|
Integer provideNodeId() {
|
||||||
|
return nodeIds.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
@Named("PUBLIC_IP_PREFIX")
|
||||||
|
String publicIpPrefix() {
|
||||||
|
return "144.175.1.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
@Named("PRIVATE_IP_PREFIX")
|
||||||
|
String privateIpPrefix() {
|
||||||
|
return "10.1.1.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
@Named("PASSWORD_PREFIX")
|
||||||
|
String passwordPrefix() {
|
||||||
|
return "password";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
SocketOpen socketOpen(StubSocketOpen in) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class StubSocketOpen implements SocketOpen {
|
||||||
|
private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
|
||||||
|
private final String publicIpPrefix;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public StubSocketOpen(ConcurrentMap<Integer, StubNodeMetadata> nodes,
|
||||||
|
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
this.publicIpPrefix = publicIpPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(IPSocket input) {
|
||||||
|
if (input.getAddress().indexOf(publicIpPrefix) == -1)
|
||||||
|
return false;
|
||||||
|
String id = input.getAddress().replace(publicIpPrefix, "");
|
||||||
|
int intId = Integer.parseInt(id);
|
||||||
|
StubNodeMetadata node = nodes.get(intId);
|
||||||
|
return node != null && node.getState() == NodeState.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
RestContext<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> provideRestContext(
|
||||||
|
Closer closer) {
|
||||||
|
return new RestContextImpl<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>>(
|
||||||
|
closer, nodes, nodes, URI.create("http://stub"), System.getProperty("user.name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// NORMAL STUFF
|
||||||
|
private final String providerName;
|
||||||
|
|
||||||
|
public StubComputeServiceContextModule(String providerName) {
|
||||||
|
this.providerName = providerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(new TypeLiteral<ComputeServiceContext>() {
|
||||||
|
})
|
||||||
|
.to(
|
||||||
|
new TypeLiteral<ComputeServiceContextImpl<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>>>() {
|
||||||
|
}).in(Scopes.SINGLETON);
|
||||||
|
bind(AddNodeWithTagStrategy.class).to(StubAddNodeWithTagStrategy.class);
|
||||||
|
bind(ListNodesStrategy.class).to(StubListNodesStrategy.class);
|
||||||
|
bind(GetNodeMetadataStrategy.class).to(StubGetNodeMetadataStrategy.class);
|
||||||
|
bind(RebootNodeStrategy.class).to(StubRebootNodeStrategy.class);
|
||||||
|
bind(DestroyNodeStrategy.class).to(StubDestroyNodeStrategy.class);
|
||||||
|
bind(LoadBalancerService.class).toProvider(Providers.<LoadBalancerService> of(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Predicate<IPSocket> socketTester(SocketOpen open) {
|
||||||
|
return new RetryablePredicate<IPSocket>(open, 130, 10, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named("DEFAULT")
|
||||||
|
protected TemplateBuilder provideTemplate(TemplateBuilder template) {
|
||||||
|
return template.osFamily(UBUNTU);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StubNodeMetadata extends NodeMetadataImpl {
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 5538798859671465494L;
|
||||||
|
private NodeState state;
|
||||||
|
private final ExecutorService service;
|
||||||
|
|
||||||
|
public StubNodeMetadata(String providerId, String name, String id, Location location,
|
||||||
|
URI uri, Map<String, String> userMetadata, String tag, Image image, NodeState state,
|
||||||
|
Iterable<String> publicAddresses, Iterable<String> privateAddresses,
|
||||||
|
Map<String, String> extra, Credentials credentials, ExecutorService service) {
|
||||||
|
super(providerId, name, id, location, uri, userMetadata, tag, image, state,
|
||||||
|
publicAddresses, privateAddresses, extra, credentials);
|
||||||
|
this.setState(state, 0);
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(final NodeState state, final long millis) {
|
||||||
|
if (millis == 0l)
|
||||||
|
this.state = state;
|
||||||
|
else
|
||||||
|
service.execute(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
StubNodeMetadata.this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeState getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class StubAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
|
||||||
|
private final Location location;
|
||||||
|
private final ExecutorService service;
|
||||||
|
private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
|
||||||
|
private final Provider<Integer> idProvider;
|
||||||
|
private final String publicIpPrefix;
|
||||||
|
private final String privateIpPrefix;
|
||||||
|
private final String passwordPrefix;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes,
|
||||||
|
Location location, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
||||||
|
@Named("NODE_ID") Provider<Integer> idProvider,
|
||||||
|
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
|
||||||
|
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix,
|
||||||
|
@Named("PASSWORD_PREFIX") String passwordPrefix) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
this.location = location;
|
||||||
|
this.service = service;
|
||||||
|
this.idProvider = idProvider;
|
||||||
|
this.publicIpPrefix = publicIpPrefix;
|
||||||
|
this.privateIpPrefix = privateIpPrefix;
|
||||||
|
this.passwordPrefix = passwordPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata execute(String tag, String name, Template template) {
|
||||||
|
checkArgument(location.equals(template.getLocation()), "invalid location: "
|
||||||
|
+ template.getLocation());
|
||||||
|
int id = idProvider.get();
|
||||||
|
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null,
|
||||||
|
ImmutableMap.<String, String> of(), tag, template.getImage(), NodeState.PENDING,
|
||||||
|
ImmutableSet.<String> of(publicIpPrefix + id), ImmutableSet
|
||||||
|
.<String> of(privateIpPrefix + id), ImmutableMap.<String, String> of(),
|
||||||
|
new Credentials("root", passwordPrefix + id), service);
|
||||||
|
node.setState(NodeState.RUNNING, 100);
|
||||||
|
nodes.put(id, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class StubGetNodeMetadataStrategy implements GetNodeMetadataStrategy {
|
||||||
|
private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected StubGetNodeMetadataStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeMetadata execute(String id) {
|
||||||
|
return nodes.get(Integer.parseInt(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class StubListNodesStrategy implements ListNodesStrategy {
|
||||||
|
private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected StubListNodesStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends ComputeMetadata> list() {
|
||||||
|
return listDetailsOnNodesMatching(NodePredicates.all());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
|
||||||
|
Predicate<ComputeMetadata> filter) {
|
||||||
|
return Iterables.filter(nodes.values(), filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class StubRebootNodeStrategy implements RebootNodeStrategy {
|
||||||
|
private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected StubRebootNodeStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(String id) {
|
||||||
|
StubNodeMetadata node = nodes.get(Integer.parseInt(id));
|
||||||
|
if (node == null)
|
||||||
|
throw new ResourceNotFoundException("node not found: " + id);
|
||||||
|
node.setState(NodeState.PENDING, 0);
|
||||||
|
node.setState(NodeState.RUNNING, 50);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class StubDestroyNodeStrategy implements DestroyNodeStrategy {
|
||||||
|
private final ConcurrentMap<Integer, StubNodeMetadata> nodes;
|
||||||
|
private final ExecutorService service;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected StubDestroyNodeStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(String id) {
|
||||||
|
final int nodeId = Integer.parseInt(id);
|
||||||
|
StubNodeMetadata node = nodes.get(nodeId);
|
||||||
|
if (node == null)
|
||||||
|
return true;
|
||||||
|
node.setState(NodeState.PENDING, 0);
|
||||||
|
node.setState(NodeState.TERMINATED, 50);
|
||||||
|
service.execute(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(200);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
} finally {
|
||||||
|
nodes.remove(nodeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named("NAMING_CONVENTION")
|
||||||
|
@Singleton
|
||||||
|
protected String provideNamingConvention() {
|
||||||
|
return "%s-%s";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Named("NOT_RUNNING")
|
||||||
|
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning) {
|
||||||
|
return new RetryablePredicate<CommandUsingClient>(Predicates.not(stateRunning), 600, 3,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Set<? extends Size> provideSizes() {
|
||||||
|
return ImmutableSet.of(new StubSize("small", 1, 1740, 160, ImmutableSet
|
||||||
|
.of(Architecture.X86_32)), new StubSize("medium", 4, 7680, 850, ImmutableSet
|
||||||
|
.of(Architecture.X86_64)), new StubSize("large", 8, 15360, 1690, ImmutableSet
|
||||||
|
.of(Architecture.X86_64)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl {
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = -1842135761654973637L;
|
||||||
|
|
||||||
|
StubSize(String type, int cores, int ram, int disk,
|
||||||
|
Iterable<Architecture> supportedArchitectures) {
|
||||||
|
super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk,
|
||||||
|
architectureIn(supportedArchitectures));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Set<? extends Image> provideImages(Location defaultLocation) {
|
||||||
|
return ImmutableSet.of(new ImageImpl("1", OsFamily.UBUNTU.name(), "1", defaultLocation, null,
|
||||||
|
ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU,
|
||||||
|
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2",
|
||||||
|
OsFamily.UBUNTU.name(), "2", defaultLocation, null, ImmutableMap
|
||||||
|
.<String, String> of(), "stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64",
|
||||||
|
Architecture.X86_64, new Credentials("root", null)), new ImageImpl("3",
|
||||||
|
OsFamily.CENTOS.name(), "3", defaultLocation, null, ImmutableMap
|
||||||
|
.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64",
|
||||||
|
Architecture.X86_64, new Credentials("root", null)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Location getLocation() {
|
||||||
|
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
|
||||||
|
return new LocationImpl(LocationScope.ZONE, "memory", "memory", provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Set<? extends Location> provideLocations(Location location) {
|
||||||
|
return ImmutableSet.of(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -100,8 +100,8 @@
|
||||||
<url>http://clojars.org/repo</url>
|
<url>http://clojars.org/repo</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>ning.http.client</id>
|
<id>sonatype-github-releases</id>
|
||||||
<url>http://oss.sonatype.org/service/local/repositories/snapshots/content</url>
|
<url>http://oss.sonatype.org/content/repositories/github-releases</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
|
@ -284,7 +284,8 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.theoryinpractise</groupId>
|
<groupId>com.theoryinpractise</groupId>
|
||||||
<artifactId>clojure-maven-plugin</artifactId>
|
<artifactId>clojure-maven-plugin</artifactId>
|
||||||
<version>1.3.3-SNAPSHOT</version>
|
<!-- snapshot repo is blank, so reverted to 1.3.2 -->
|
||||||
|
<version>1.3.2</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>compile-clojure</id>
|
<id>compile-clojure</id>
|
||||||
|
|
Loading…
Reference in New Issue