Issue 786:isolate stub computeservice contexts from eachother

This commit is contained in:
Adrian Cole 2011-12-18 15:19:49 -08:00
parent aa00e28d73
commit 39290d725c
4 changed files with 78 additions and 58 deletions

View File

@ -19,15 +19,17 @@
package org.jclouds.compute.stub.config; package org.jclouds.compute.stub.config;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.JCloudsNativeComputeServiceAdapter; import org.jclouds.compute.JCloudsNativeComputeServiceAdapter;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -46,8 +48,8 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableList.Builder;
/** /**
* *
@ -57,6 +59,7 @@ import com.google.common.collect.ImmutableSet;
public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter { public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter {
private final Supplier<Location> location; private final Supplier<Location> location;
private final ConcurrentMap<String, NodeMetadata> nodes; private final ConcurrentMap<String, NodeMetadata> nodes;
private final ExecutorService ioThreads;
private final Provider<Integer> idProvider; private final Provider<Integer> idProvider;
private final String publicIpPrefix; private final String publicIpPrefix;
private final String privateIpPrefix; private final String privateIpPrefix;
@ -65,11 +68,13 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
private final Map<OsFamily, Map<String, String>> osToVersionMap; private final Map<OsFamily, Map<String, String>> osToVersionMap;
@Inject @Inject
public StubComputeServiceAdapter(ConcurrentMap<String, NodeMetadata> nodes, Supplier<Location> location, public StubComputeServiceAdapter(ConcurrentMap<String, NodeMetadata> nodes,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix, @Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, Supplier<Location> location,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix, @Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
JustProvider locationSupplier, Map<OsFamily, Map<String, String>> osToVersionMap) { @Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix,
JustProvider locationSupplier, Map<OsFamily, Map<String, String>> osToVersionMap) {
this.nodes = nodes; this.nodes = nodes;
this.ioThreads=ioThreads;
this.location = location; this.location = location;
this.idProvider = idProvider; this.idProvider = idProvider;
this.publicIpPrefix = publicIpPrefix; this.publicIpPrefix = publicIpPrefix;
@ -79,6 +84,28 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
this.osToVersionMap = osToVersionMap; this.osToVersionMap = osToVersionMap;
} }
protected void setStateOnNode(NodeState state, NodeMetadata node) {
nodes.put(node.getId(), NodeMetadataBuilder.fromNodeMetadata(node).state(state).build());
}
protected void setStateOnNodeAfterDelay(final NodeState state, final NodeMetadata node, final long millis) {
if (millis == 0l)
setStateOnNode(state, node);
else
ioThreads.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Throwables.propagate(e);
}
setStateOnNode(state, node);
}
});
}
@Override @Override
public NodeWithInitialCredentials createNodeWithGroupEncodedIntoName(String group, String name, Template template) { public NodeWithInitialCredentials createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
NodeMetadataBuilder builder = new NodeMetadataBuilder(); NodeMetadataBuilder builder = new NodeMetadataBuilder();
@ -99,7 +126,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
builder.credentials(LoginCredentials.builder().user("root").password(passwordPrefix + id).build()); builder.credentials(LoginCredentials.builder().user("root").password(passwordPrefix + id).build());
NodeMetadata node = builder.build(); NodeMetadata node = builder.build();
nodes.put(node.getId(), node); nodes.put(node.getId(), node);
StubComputeServiceDependenciesModule.setState(node, NodeState.RUNNING, 100); setStateOnNodeAfterDelay(NodeState.RUNNING, node, 100);
return new NodeWithInitialCredentials(node); return new NodeWithInitialCredentials(node);
} }
@ -149,9 +176,9 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
NodeMetadata node = nodes.get(id); NodeMetadata node = nodes.get(id);
if (node == null) if (node == null)
return; return;
StubComputeServiceDependenciesModule.setState(node, NodeState.PENDING, 0); setStateOnNodeAfterDelay(NodeState.PENDING, node, 0);
StubComputeServiceDependenciesModule.setState(node, NodeState.TERMINATED, 50); setStateOnNodeAfterDelay(NodeState.TERMINATED, node, 50);
StubComputeServiceDependenciesModule.service.execute(new Runnable() { ioThreads.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -172,8 +199,8 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
NodeMetadata node = nodes.get(id); NodeMetadata node = nodes.get(id);
if (node == null) if (node == null)
throw new ResourceNotFoundException("node not found: " + id); throw new ResourceNotFoundException("node not found: " + id);
StubComputeServiceDependenciesModule.setState(node, NodeState.PENDING, 0); setStateOnNode(NodeState.PENDING, node);
StubComputeServiceDependenciesModule.setState(node, NodeState.RUNNING, 50); setStateOnNodeAfterDelay(NodeState.RUNNING, node, 50);
} }
@Override @Override
@ -185,8 +212,8 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return; return;
if (node.getState() != NodeState.SUSPENDED) if (node.getState() != NodeState.SUSPENDED)
throw new IllegalStateException("to resume a node, it must be in suspended state, not: " + node.getState()); throw new IllegalStateException("to resume a node, it must be in suspended state, not: " + node.getState());
StubComputeServiceDependenciesModule.setState(node, NodeState.PENDING, 0); setStateOnNode(NodeState.PENDING, node);
StubComputeServiceDependenciesModule.setState(node, NodeState.RUNNING, 50); setStateOnNodeAfterDelay(NodeState.RUNNING, node, 50);
} }
@Override @Override
@ -198,7 +225,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return; return;
if (node.getState() != NodeState.RUNNING) if (node.getState() != NodeState.RUNNING)
throw new IllegalStateException("to suspend a node, it must be in running state, not: " + node.getState()); throw new IllegalStateException("to suspend a node, it must be in running state, not: " + node.getState());
StubComputeServiceDependenciesModule.setState(node, NodeState.PENDING, 0); setStateOnNode(NodeState.PENDING, node);
StubComputeServiceDependenciesModule.setState(node, NodeState.SUSPENDED, 50); setStateOnNodeAfterDelay(NodeState.SUSPENDED, node, 50);
} }
} }

View File

@ -20,8 +20,7 @@ package org.jclouds.compute.stub.config;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject; import javax.inject.Inject;
@ -30,15 +29,17 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.VolumeImpl; import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.SocketOpen; import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Throwables; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -54,23 +55,38 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
} }
protected static final ConcurrentMap<String, NodeMetadata> backing = new ConcurrentHashMap<String, NodeMetadata>(); // STUB STUFF STATIC SO MULTIPLE CONTEXTS CAN SEE IT
protected static final LoadingCache<String, ConcurrentMap<String, NodeMetadata>> backing = CacheBuilder.newBuilder()
.build(new CacheLoader<String, ConcurrentMap<String, NodeMetadata>>() {
@Override
public ConcurrentMap<String, NodeMetadata> load(String arg0) throws Exception {
return new ConcurrentHashMap<String, NodeMetadata>();
}
});
// implementation details below
@Provides @Provides
@Singleton @Singleton
ConcurrentMap<String, NodeMetadata> provideNodes() { protected ConcurrentMap<String, NodeMetadata> provideNodesForIdentity(@Identity String identity)
return backing; throws ExecutionException {
return backing.get(identity);
} }
// STUB STUFF STATIC SO MULTIPLE CONTEXTS CAN SEE IT protected static final LoadingCache<String, AtomicInteger> nodeIds = CacheBuilder.newBuilder().build(
private static final AtomicInteger nodeIds = new AtomicInteger(0); new CacheLoader<String, AtomicInteger>() {
static final ExecutorService service = Executors.newCachedThreadPool();
@Override
public AtomicInteger load(String arg0) throws Exception {
return new AtomicInteger(0);
}
});
@Provides @Provides
@Named("NODE_ID") @Named("NODE_ID")
Integer provideNodeId() { protected Integer provideNodeIdForIdentity(@Identity String identity) throws ExecutionException {
return nodeIds.incrementAndGet(); return nodeIds.get(identity).incrementAndGet();
} }
@Singleton @Singleton
@ -122,29 +138,6 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
} }
protected static void nodeWithState(NodeMetadata node, NodeState state) {
backing.put(node.getId(), NodeMetadataBuilder.fromNodeMetadata(node).state(state).build());
}
public static void setState(final NodeMetadata node, final NodeState state, final long millis) {
if (millis == 0l)
nodeWithState(node, state);
else
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Throwables.propagate(e);
}
nodeWithState(node, state);
}
});
}
static Hardware stub(String type, int cores, int ram, float disk) { static Hardware stub(String type, int cores, int ram, float disk) {
return new org.jclouds.compute.domain.HardwareBuilder().ids(type).name(type) return new org.jclouds.compute.domain.HardwareBuilder().ids(type).name(type)
.processors(ImmutableList.of(new Processor(cores, 1.0))).ram(ram) .processors(ImmutableList.of(new Processor(cores, 1.0))).ram(ram)

View File

@ -42,7 +42,7 @@ 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)))))
(def compute-stub (compute-service "stub" "" "" :extensions [(ssh-test/ssh-test-client ssh-test/no-op-ssh-client)])) (def compute-stub (compute-service "stub" "compute2.clj" "" :extensions [(ssh-test/ssh-test-client ssh-test/no-op-ssh-client)]))
(defn clean-stub-fixture (defn clean-stub-fixture
"This should allow basic tests to easily be run with another service." "This should allow basic tests to easily be run with another service."
@ -58,7 +58,7 @@ list, Alan Dipert and MeikelBrandmeyer."
(is (compute-service? compute-stub))) (is (compute-service? compute-stub)))
(deftest as-compute-service-test (deftest as-compute-service-test
(is (compute-service? (compute-service "stub" "user" "password"))) (is (compute-service? (compute-service "stub" "compute2.clj" "")))
(is (compute-service? compute-stub)) (is (compute-service? compute-stub))
(is (compute-service? (compute-service (compute-context compute-stub))))) (is (compute-service? (compute-service (compute-context compute-stub)))))
@ -119,7 +119,7 @@ list, Alan Dipert and MeikelBrandmeyer."
(run-script-on-node compute-stub "nonexistingnode" echo script-options))))) (run-script-on-node compute-stub "nonexistingnode" echo script-options)))))
(deftest build-template-test (deftest build-template-test
(let [service (compute-service "stub" "user" "password")] (let [service (compute-service "stub" "compute2.clj" "")]
(testing "nullary" (testing "nullary"
(is (>= (-> (build-template service {:fastest true}) (is (>= (-> (build-template service {:fastest true})
bean :hardware bean :processors first bean :cores) bean :hardware bean :processors first bean :cores)

View File

@ -42,13 +42,13 @@ list, Alan Dipert and MeikelBrandmeyer."
(destroy-node (.getId node))) (destroy-node (.getId node)))
(f)))) (f))))
(use-fixtures :each (clean-stub-fixture "stub" "" "")) (use-fixtures :each (clean-stub-fixture "stub" "compute.clj" ""))
(deftest compute-service?-test (deftest compute-service?-test
(is (compute-service? *compute*))) (is (compute-service? *compute*)))
(deftest as-compute-service-test (deftest as-compute-service-test
(is (compute-service? (compute-service "stub" "user" "password"))) (is (compute-service? (compute-service "stub" "compute.clj" "")))
(is (compute-service? (as-compute-service *compute*))) (is (compute-service? (as-compute-service *compute*)))
(is (compute-service? (as-compute-service (compute-context *compute*))))) (is (compute-service? (as-compute-service (compute-context *compute*)))))
@ -90,7 +90,7 @@ list, Alan Dipert and MeikelBrandmeyer."
(is (terminated? (first (nodes-with-tag "deprecated"))))) (is (terminated? (first (nodes-with-tag "deprecated")))))
(deftest build-template-test (deftest build-template-test
(let [service (compute-service "stub" "user" "password")] (let [service (compute-service "stub" "compute.clj" "")]
(testing "nullary" (testing "nullary"
(is (>= (-> (build-template service {:fastest true}) (is (>= (-> (build-template service {:fastest true})
bean :hardware bean :processors first bean :cores) bean :hardware bean :processors first bean :cores)