You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2016/09/30 09:00:28 UTC
[2/9] brooklyn-server git commit: Add tests to
SoftwareProcessRebindNotRunningEntityTest
Add tests to SoftwareProcessRebindNotRunningEntityTest
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/5d252d7e
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/5d252d7e
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/5d252d7e
Branch: refs/heads/master
Commit: 5d252d7ef1ec3f35ce874c05db95c9db2d9e2774
Parents: 001b02c
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 26 22:13:38 2016 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Sep 27 10:36:58 2016 +0100
----------------------------------------------------------------------
.../core/mgmt/rebind/RebindTestFixture.java | 4 +
.../core/internal/ssh/RecordingSshTool.java | 9 +-
...ftwareProcessRebindNotRunningEntityTest.java | 341 ++++++++++++++++---
3 files changed, 310 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5d252d7e/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
index 819b8f0..9a81cea 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
@@ -147,6 +147,10 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
return (newManagementContext != null) ? newManagementContext : origManagementContext;
}
+ protected T app() {
+ return (newApp != null) ? newApp : origApp;
+ }
+
public static void waitForTaskCountToBecome(final ManagementContext mgmt, final int allowedMax) {
waitForTaskCountToBecome(mgmt, allowedMax, false);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5d252d7e/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/RecordingSshTool.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/RecordingSshTool.java b/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/RecordingSshTool.java
index 2ac8acf..04e78cf 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/RecordingSshTool.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/RecordingSshTool.java
@@ -72,7 +72,7 @@ public class RecordingSshTool implements SshTool {
}
public interface CustomResponseGenerator {
- public CustomResponse generate(ExecParams execParams);
+ public CustomResponse generate(ExecParams execParams) throws Exception;
}
public static class CustomResponse {
@@ -225,7 +225,12 @@ public class RecordingSshTool implements SshTool {
for (Entry<String, CustomResponseGenerator> entry : customResponses.entrySet()) {
if (cmd.matches(entry.getKey())) {
CustomResponseGenerator responseGenerator = entry.getValue();
- CustomResponse response = responseGenerator.generate(new ExecParams(props, commands, env));
+ CustomResponse response;
+ try {
+ response = responseGenerator.generate(new ExecParams(props, commands, env));
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
writeCustomResponseStreams(props, response);
return response.exitCode;
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5d252d7e/software/base/src/test/java/org/apache/brooklyn/entity/software/base/SoftwareProcessRebindNotRunningEntityTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/SoftwareProcessRebindNotRunningEntityTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/SoftwareProcessRebindNotRunningEntityTest.java
index 3fb2188..f318d0e 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/SoftwareProcessRebindNotRunningEntityTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/SoftwareProcessRebindNotRunningEntityTest.java
@@ -16,83 +16,340 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.brooklyn.entity.software.base;
-import com.google.common.collect.ImmutableList;
-import org.apache.brooklyn.api.entity.Entity;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
-import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
-import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.CustomResponse;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.CustomResponseGenerator;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecParams;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import java.util.Date;
-import java.util.List;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.reflect.TypeToken;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
-public class SoftwareProcessRebindNotRunningEntityTest extends BrooklynAppUnitTestSupport {
+public class SoftwareProcessRebindNotRunningEntityTest extends RebindTestFixtureWithApp {
- private List<LocalhostMachineProvisioningLocation> locations;
+ // TODO We'd like to record the fact that we were starting or stopping, rather than just say "on-fire".
+ // For example, we can use the Attributes.SERVICE_NOT_UP_INDICATORS to say what went wrong.
+
+ // TODO If we fail during provisioningLocation.obtain() or provisioningLocation.release(), then we
+ // should tell the user that a VM might have started being provisioned but been forgotten about; or
+ // that termination of the VM may or may not have completed.
+ // We could use the Attributes.SERVICE_NOT_UP_INDICATORS to achieve that.
+
+ // TODO Parent app should go on-fire after restart, but it doesn't - it continues saying "starting".
+ // We probably need to set the "service.state.expected" to on-fire on the parent as well (i.e. for
+ // more things than just SoftwareProcess).
+ // Sensor: service.notUp.indicators (java.util.Map) = {service.state=Application starting, service-lifecycle-indicators-from-children-and-members=VanillaSoftwareProcessImpl{id=nyijf1980z} is not up}
+ // Sensor: entity.id (java.lang.String) = nz6qobkstx
+ // Sensor: application.id (java.lang.String) = nz6qobkstx
+ // Sensor: catalog.id (java.lang.String) = null
+ // Sensor: service.isUp (java.lang.Boolean) = false
+ // Sensor: service.problems (java.util.Map) = {service-lifecycle-indicators-from-children-and-members=Required entity not healthy: VanillaSoftwareProcessImpl{id=nyijf1980z}}
+ // Sensor: service.state (org.apache.brooklyn.core.entity.lifecycle.Lifecycle) = starting
+ // Sensor: service.state.expected (org.apache.brooklyn.core.entity.lifecycle.Lifecycle$Transition) = starting @ 1474967564852 / Tue Sep 27 10:12:44 BST 2016
+ //
+ // In each test, we should add at the end:
+ // EntityAsserts.assertAttributeEqualsEventually(newApp, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ // EntityAsserts.assertAttributeEqualsEventually(newApp, Attributes.SERVICE_UP, false);
+ private ListeningExecutorService executor;
+ private LocationSpec<SshMachineLocation> machineSpec;
+ private FixedListMachineProvisioningLocation<?> locationProvisioner;
+
+ // We track the latches, so we can countDown() them all to unblock them. Otherwise they can
+ // interfere with tearDown by blocking threads.
+ // TODO Longer term, we should investigate/fix that so tearDown finishes promptly no matter what!
+ private List<CountDownLatch> latches;
+
@BeforeMethod(alwaysRun=true)
+ @Override
public void setUp() throws Exception {
super.setUp();
- locations = ImmutableList.of(app.newLocalhostProvisioningLocation());
+
+ latches = Lists.newCopyOnWriteArrayList();
+
+ machineSpec = LocationSpec.create(SshMachineLocation.class)
+ .configure("address", "1.2.3.4")
+ .configure(SshMachineLocation.SSH_TOOL_CLASS, RecordingSshTool.class.getName());
+
+ locationProvisioner = app().getManagementContext().getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class)
+ .configure(FixedListMachineProvisioningLocation.MACHINE_SPECS, ImmutableList.<LocationSpec<? extends MachineLocation>>of(
+ machineSpec)));
+
+ executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+
+ RecordingSshTool.clear();
}
- //TODO cover more cases and all entity states
+ @AfterMethod(alwaysRun=true)
+ @Override
+ public void tearDown() throws Exception {
+ try {
+ for (CountDownLatch latch : latches) {
+ while (latch.getCount() > 0) {
+ latch.countDown();
+ }
+ }
+ super.tearDown();
+ if (executor != null) executor.shutdownNow();
+ } finally {
+ RecordingSshTool.clear();
+ }
+ }
+
+ @Override
+ protected TestApplication createApp() {
+ return mgmt().getEntityManager().createEntity(EntitySpec.create(TestApplication.class));
+ }
+
+ @Test
+ public void testRebindWhileWaitingForCheckRunning() throws Exception {
+ final CountDownLatch checkRunningCalledLatch = newLatch(1);
+ RecordingSshTool.setCustomResponse(".*myCheckRunning.*", new CustomResponseGenerator() {
+ @Override
+ public CustomResponse generate(ExecParams execParams) {
+ checkRunningCalledLatch.countDown();
+ return new CustomResponse(1, "", "");
+ }});
+
+ VanillaSoftwareProcess entity = app().createAndManageChild(EntitySpec.create(VanillaSoftwareProcess.class)
+ .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, "myLaunch")
+ .configure(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND, "myCheckRunning"));
+
+ startAsync(app(), ImmutableList.of(locationProvisioner));
+ awaitOrFail(checkRunningCalledLatch, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING);
+
+ TestApplication newApp = rebind();
+ final VanillaSoftwareProcess newEntity = (VanillaSoftwareProcess) Iterables.find(newApp.getChildren(), Predicates.instanceOf(VanillaSoftwareProcess.class));
+
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_UP, false);
+ }
+
+ @Test
+ public void testRebindWhileLaunching() throws Exception {
+ final CountDownLatch launchCalledLatch = newLatch(1);
+ final CountDownLatch launchBlockedLatch = newLatch(1);
+ RecordingSshTool.setCustomResponse(".*myLaunch.*", new CustomResponseGenerator() {
+ @Override
+ public CustomResponse generate(ExecParams execParams) throws Exception {
+ launchCalledLatch.countDown();
+ launchBlockedLatch.await();
+ return new CustomResponse(0, "", "");
+ }});
+
+ VanillaSoftwareProcess entity = app().createAndManageChild(EntitySpec.create(VanillaSoftwareProcess.class)
+ .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, "myLaunch")
+ .configure(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND, "myCheckRunning"));
+
+ startAsync(app(), ImmutableList.of(locationProvisioner));
+ awaitOrFail(launchCalledLatch, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING);
+
+ TestApplication newApp = rebind();
+ final VanillaSoftwareProcess newEntity = (VanillaSoftwareProcess) Iterables.find(newApp.getChildren(), Predicates.instanceOf(VanillaSoftwareProcess.class));
+
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_UP, false);
+ }
@Test
- public void testRebindAfterStarting() {
- MyService entity = app.createAndManageChild(EntitySpec.create(MyService.class));
- entity.start(locations); //FIXME - NPE
- //TODO find better solution to rebind starting app than only setting its attributes
- ((MyServiceImpl) entity).setAttribute(entity.SERVICE_STATE_EXPECTED, new Lifecycle.Transition(Lifecycle.ON_FIRE, new Date()));
- ((MyServiceImpl) entity).setAttribute(entity.SERVICE_STATE_ACTUAL, Lifecycle.STARTING);
- ((MyServiceImpl) entity).rebind();
-
- assertEntityIsOnFire(entity);
+ public void testRebindWhileStoppingProcess() throws Exception {
+ final CountDownLatch stopCalledLatch = newLatch(1);
+ final CountDownLatch stopBlockedLatch = newLatch(1);
+ RecordingSshTool.setCustomResponse(".*myStop.*", new CustomResponseGenerator() {
+ @Override
+ public CustomResponse generate(ExecParams execParams) throws Exception {
+ stopCalledLatch.countDown();
+ stopBlockedLatch.await();
+ return new CustomResponse(0, "", "");
+ }});
+
+ VanillaSoftwareProcess entity = app().createAndManageChild(EntitySpec.create(VanillaSoftwareProcess.class)
+ .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, "myLaunch")
+ .configure(VanillaSoftwareProcess.STOP_COMMAND, "myStop")
+ .configure(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND, "myCheckRunning"));
+ app().start(ImmutableList.of(locationProvisioner));
+
+ stopAsync(entity);
+ awaitOrFail(stopCalledLatch, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPING);
+
+ TestApplication newApp = rebind();
+ final VanillaSoftwareProcess newEntity = (VanillaSoftwareProcess) Iterables.find(newApp.getChildren(), Predicates.instanceOf(VanillaSoftwareProcess.class));
+
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_UP, false);
}
@Test
- public void testRebindAfterStopping() {
+ public void testRebindWhileProvisioning() throws Exception {
+ final CountDownLatch obtainCalledLatch = newLatch(1);
+ final CountDownLatch obtainBlockedLatch = newLatch(1);
+ MyProvisioningLocation blockingProvisioner = mgmt().getLocationManager().createLocation(LocationSpec.create(MyProvisioningLocation.class)
+ .configure(MyProvisioningLocation.OBTAIN_CALLED_LATCH, obtainCalledLatch)
+ .configure(MyProvisioningLocation.OBTAIN_BLOCKED_LATCH, obtainBlockedLatch)
+ .configure(MyProvisioningLocation.MACHINE_SPEC, machineSpec));
+
+ VanillaSoftwareProcess entity = app().createAndManageChild(EntitySpec.create(VanillaSoftwareProcess.class)
+ .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, "myLaunch")
+ .configure(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND, "myCheckRunning"));
+
+ startAsync(app(), ImmutableList.of(blockingProvisioner));
+ awaitOrFail(obtainCalledLatch, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING);
+
+ TestApplication newApp = rebind();
+ final VanillaSoftwareProcess newEntity = (VanillaSoftwareProcess) Iterables.find(newApp.getChildren(), Predicates.instanceOf(VanillaSoftwareProcess.class));
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_UP, false);
}
@Test
- public void testRebindRunningEntity() {
- MyService entity = app.createAndManageChild(EntitySpec.create(MyService.class));
- entity.start(locations);
- ((MyServiceImpl) entity).rebind();
- assertEntityIsRunning(entity);
+ public void testRebindWhileTerminatingVm() throws Exception {
+ final CountDownLatch releaseCalledLatch = newLatch(1);
+ final CountDownLatch obtainBlockedLatch = newLatch(1);
+ MyProvisioningLocation blockingProvisioner = mgmt().getLocationManager().createLocation(LocationSpec.create(MyProvisioningLocation.class)
+ .configure(MyProvisioningLocation.RELEASE_CALLED_LATCH, releaseCalledLatch)
+ .configure(MyProvisioningLocation.RELEASE_BLOCKED_LATCH, obtainBlockedLatch)
+ .configure(MyProvisioningLocation.MACHINE_SPEC, machineSpec));
+
+ VanillaSoftwareProcess entity = app().createAndManageChild(EntitySpec.create(VanillaSoftwareProcess.class)
+ .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, "myLaunch")
+ .configure(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND, "myCheckRunning"));
+
+ app().start(ImmutableList.of(blockingProvisioner));
+
+ stopAsync(entity);
+ awaitOrFail(releaseCalledLatch, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ EntityAsserts.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPING);
+
+ TestApplication newApp = rebind();
+ final VanillaSoftwareProcess newEntity = (VanillaSoftwareProcess) Iterables.find(newApp.getChildren(), Predicates.instanceOf(VanillaSoftwareProcess.class));
+
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Attributes.SERVICE_UP, false);
}
- //TODO - more precise assert?
- protected void assertEntityIsOnFire(MyService entity) {
- EntityAsserts.assertAttributeEquals(entity, entity.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
- //TODO assert SERVICE_STATE_EXPECTED
+ protected ListenableFuture<Void> startAsync(final Startable entity, final Collection<? extends Location> locs) {
+ return executor.submit(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ entity.start(locs);
+ return null;
+ }});
}
- protected void assertEntityIsRunning(MyService entity) {
- Asserts.assertTrue(((MyServiceImpl) entity).getDriver().isRunning());
+ protected ListenableFuture<Void> stopAsync(final Startable entity) {
+ return executor.submit(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ entity.stop();
+ return null;
+ }});
}
- //TODO
- @ImplementedBy(MyServiceImpl.class)
- public interface MyService extends SoftwareProcess {
+ protected void awaitOrFail(CountDownLatch latch, Duration timeout) throws Exception {
+ boolean success = latch.await(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
+ assertTrue(success, "latch "+latch+" not satisfied in "+timeout);
+ }
+
+ protected CountDownLatch newLatch(int count) {
+ CountDownLatch result = new CountDownLatch(count);
+ latches.add(result);
+ return result;
}
- public static class MyServiceImpl extends SoftwareProcessImpl implements MyService {
- public MyServiceImpl() {}
- public MyServiceImpl(Entity parent) { super(parent); }
+ public static class MyProvisioningLocation extends AbstractLocation implements MachineProvisioningLocation<SshMachineLocation> {
+ public static final ConfigKey<CountDownLatch> OBTAIN_CALLED_LATCH = ConfigKeys.newConfigKey(CountDownLatch.class, "obtainCalledLatch");
+ public static final ConfigKey<CountDownLatch> OBTAIN_BLOCKED_LATCH = ConfigKeys.newConfigKey(CountDownLatch.class, "obtainBlockedLatch");
+ public static final ConfigKey<CountDownLatch> RELEASE_CALLED_LATCH = ConfigKeys.newConfigKey(CountDownLatch.class, "releaseCalledLatch");
+ public static final ConfigKey<CountDownLatch> RELEASE_BLOCKED_LATCH = ConfigKeys.newConfigKey(CountDownLatch.class, "releaseBlockedLatch");
+ public static final ConfigKey<LocationSpec<SshMachineLocation>> MACHINE_SPEC = ConfigKeys.newConfigKey(
+ new TypeToken<LocationSpec<SshMachineLocation>>() {},
+ "machineSpec");
+
+ @Override
+ public MachineProvisioningLocation<SshMachineLocation> newSubLocation(Map<?, ?> newFlags) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SshMachineLocation obtain(Map<?,?> flags) throws NoMachinesAvailableException {
+ CountDownLatch calledLatch = config().get(OBTAIN_CALLED_LATCH);
+ CountDownLatch blockedLatch = config().get(OBTAIN_BLOCKED_LATCH);
+ LocationSpec<SshMachineLocation> machineSpec = config().get(MACHINE_SPEC);
+
+ if (calledLatch != null) calledLatch.countDown();
+ try {
+ if (blockedLatch != null) blockedLatch.await();
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ return getManagementContext().getLocationManager().createLocation(machineSpec);
+ }
+
+ @Override
+ public void release(SshMachineLocation machine) {
+ CountDownLatch calledLatch = config().get(RELEASE_CALLED_LATCH);
+ CountDownLatch blockedLatch = config().get(RELEASE_BLOCKED_LATCH);
+
+ if (calledLatch != null) calledLatch.countDown();
+ try {
+ if (blockedLatch != null) blockedLatch.await();
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
@Override
- public Class getDriverInterface() {
- return null;
+ public Map getProvisioningFlags(Collection<String> tags) {
+ return Collections.emptyMap();
}
}
-}
\ No newline at end of file
+}