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 2014/12/09 17:11:39 UTC
[1/2] incubator-brooklyn git commit: Adds optional parameter to stop
effector for stopping underlying machine
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master f365b9b22 -> 5055b4009
Adds optional parameter to stop effector for stopping underlying machine
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f8c5f88f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f8c5f88f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f8c5f88f
Branch: refs/heads/master
Commit: f8c5f88ff6d560adbdbc246afba9b93665bdbd18
Parents: 566fd49
Author: Martin Harris <gi...@nakomis.com>
Authored: Tue Dec 9 14:51:40 2014 +0000
Committer: Martin Harris <gi...@nakomis.com>
Committed: Tue Dec 9 14:51:40 2014 +0000
----------------------------------------------------------------------
.../brooklyn/entity/basic/SoftwareProcess.java | 9 ++
.../software/MachineLifecycleEffectorTasks.java | 91 ++++++++++++-------
.../entity/basic/SoftwareProcessEntityTest.java | 94 ++++++++++++++++----
3 files changed, 142 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f8c5f88f/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
index b9008c2..62fe9e0 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
@@ -233,6 +233,7 @@ public interface SoftwareProcess extends Entity, Startable {
AttributeSensor<String> PID_FILE = Sensors.newStringSensor("softwareprocess.pid.file", "PID file");
+ @Beta
public static class RestartSoftwareParameters {
@Beta /** @since 0.7.0 semantics of parameters to restart being explored */
public static final ConfigKey<Boolean> RESTART_CHILDREN = ConfigKeys.newConfigKey(Boolean.class, "restartChildren",
@@ -253,6 +254,14 @@ public interface SoftwareProcess extends Entity, Startable {
public enum RestartMachineMode { TRUE, FALSE, AUTO }
}
+
+ @Beta
+ public static class StopSoftwareParameters {
+ @Beta /** @since 0.7.0 semantics of parameters to restart being explored */
+ public static final ConfigKey<Boolean> STOP_MACHINE = ConfigKeys.newBooleanConfigKey("stopMachine",
+ "Whether to stop the machine provisioned for this entity: 'true', or 'false' are supported, "
+ + "with the default being 'true'", true);
+ }
// NB: the START, STOP, and RESTART effectors themselves are (re)defined by MachineLifecycleEffectorTasks
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f8c5f88f/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
index 2168693..ab0cae4 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
@@ -45,6 +45,7 @@ import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.ServiceStateLogic;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters;
+import brooklyn.entity.basic.SoftwareProcess.StopSoftwareParameters;
import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters.RestartMachineMode;
import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
@@ -132,15 +133,19 @@ public abstract class MachineLifecycleEffectorTasks {
/** @see {@link #newStartEffector()} */
public Effector<Void> newRestartEffector() {
- return Effectors.effector(Startable.RESTART).
- parameter(RestartSoftwareParameters.RESTART_CHILDREN).
- parameter(RestartSoftwareParameters.RESTART_MACHINE).
- impl(newRestartEffectorTask()).build();
+ return Effectors.effector(Startable.RESTART)
+ .parameter(RestartSoftwareParameters.RESTART_CHILDREN)
+ .parameter(RestartSoftwareParameters.RESTART_MACHINE)
+ .impl(newRestartEffectorTask())
+ .build();
}
/** @see {@link #newStartEffector()} */
public Effector<Void> newStopEffector() {
- return Effectors.effector(Startable.STOP).impl(newStopEffectorTask()).build();
+ return Effectors.effector(Startable.STOP)
+ .parameter(StopSoftwareParameters.STOP_MACHINE)
+ .impl(newStopEffectorTask())
+ .build();
}
/**
@@ -192,7 +197,7 @@ public abstract class MachineLifecycleEffectorTasks {
return new EffectorBody<Void>() {
@Override
public Void call(ConfigBag parameters) {
- stop();
+ stop(parameters);
return null;
}
};
@@ -441,7 +446,7 @@ public abstract class MachineLifecycleEffectorTasks {
}
/**
- * whether when 'auto' mode is specified, the machine should be stopped
+ * whether when 'auto' mode is specified, the machine should be stopped when the restart effector is called
* <p>
* with {@link MachineLifecycleEffectorTasks}, a machine will always get created on restart if there wasn't one already
* (unlike certain subclasses which might attempt a shortcut process-level restart)
@@ -479,7 +484,7 @@ public abstract class MachineLifecycleEffectorTasks {
} else {
DynamicTasks.queue("stopping (machine)", new Callable<String>() { public String call() {
DynamicTasks.markInessential();
- stop();
+ stop(ConfigBag.newInstance().configure(StopSoftwareParameters.STOP_MACHINE, true));
DynamicTasks.waitForLast();
return "Stop of machine completed with no errors.";
}});
@@ -514,6 +519,12 @@ public abstract class MachineLifecycleEffectorTasks {
throw new IllegalArgumentException("Invalid value '"+isRestartChildren+"' for "+RestartSoftwareParameters.RESTART_CHILDREN.getName());
}
+ /** @deprecated since 0.7.0 use {@link #stop(ConfigBag)} */
+ @Deprecated
+ public void stop() {
+ stop(ConfigBag.EMPTY);
+ }
+
/**
* Default stop implementation for an entity.
* <p>
@@ -521,9 +532,14 @@ public abstract class MachineLifecycleEffectorTasks {
* invokes {@link #preStopCustom()}, {@link #stopProcessesAtMachine()}, then finally
* {@link #stopAnyProvisionedMachines()} and sets state {@link Lifecycle#STOPPED}
*/
- public void stop() {
+ public void stop(ConfigBag parameters) {
log.info("Stopping {} in {}", entity(), entity().getLocations());
+ Boolean isStopMachine = parameters.get(StopSoftwareParameters.STOP_MACHINE);
+
+ if (isStopMachine==null)
+ isStopMachine = Boolean.TRUE;
+
DynamicTasks.queue("pre-stop", new Callable<String>() { public String call() {
if (entity().getAttribute(SoftwareProcess.SERVICE_STATE_ACTUAL)==Lifecycle.STOPPED) {
log.debug("Skipping stop of entity "+entity()+" when already stopped");
@@ -534,7 +550,7 @@ public abstract class MachineLifecycleEffectorTasks {
preStopCustom();
return null;
}});
-
+
if (entity().getAttribute(SoftwareProcess.SERVICE_STATE_ACTUAL)==Lifecycle.STOPPED) {
return;
}
@@ -547,30 +563,40 @@ public abstract class MachineLifecycleEffectorTasks {
return "Stop at machine completed with no errors.";
}});
- // Release this machine (even if error trying to stop process - we rethrow that after)
- Task<StopMachineDetails<Integer>> stoppingMachine = DynamicTasks.queue("stopping (machine)", new Callable<StopMachineDetails<Integer>>() { public StopMachineDetails<Integer> call() {
- if (entity().getAttribute(SoftwareProcess.SERVICE_STATE_ACTUAL)==Lifecycle.STOPPED) {
- log.debug("Skipping stop of entity "+entity()+" when already stopped");
- return new StopMachineDetails<Integer>("Already stopped", 0);
- }
- return stopAnyProvisionedMachines();
- }});
-
- DynamicTasks.drain(entity().getConfig(STOP_PROCESS_TIMEOUT), false);
- // shutdown the machine if stopping process fails or takes too long
- synchronized (stoppingMachine) {
- // task also used as mutex by DST when it submits it; ensure it only submits once!
- if (!stoppingMachine.isSubmitted()) {
- // force the stoppingMachine task to run by submitting it here
- log.warn("Submitting machine stop early in background for "+entity()+" because process stop has "+
- (stoppingProcess.isDone() ? "finished abnormally" : "not finished"));
- Entities.submit(entity(), stoppingMachine);
+ Task<StopMachineDetails<Integer>> stoppingMachine = null;
+ if (isStopMachine) {
+ // Release this machine (even if error trying to stop process - we rethrow that after)
+ stoppingMachine = DynamicTasks.queue("stopping (machine)", new Callable<StopMachineDetails<Integer>>() {
+ public StopMachineDetails<Integer> call() {
+ if (entity().getAttribute(SoftwareProcess.SERVICE_STATE_ACTUAL) == Lifecycle.STOPPED) {
+ log.debug("Skipping stop of entity " + entity() + " when already stopped");
+ return new StopMachineDetails<Integer>("Already stopped", 0);
+ }
+ return stopAnyProvisionedMachines();
+ }
+ });
+
+ DynamicTasks.drain(entity().getConfig(STOP_PROCESS_TIMEOUT), false);
+
+ // shutdown the machine if stopping process fails or takes too long
+ synchronized (stoppingMachine) {
+ // task also used as mutex by DST when it submits it; ensure it only submits once!
+ if (!stoppingMachine.isSubmitted()) {
+ // force the stoppingMachine task to run by submitting it here
+ log.warn("Submitting machine stop early in background for "+entity()+" because process stop has "+
+ (stoppingProcess.isDone() ? "finished abnormally" : "not finished"));
+ Entities.submit(entity(), stoppingMachine);
+ }
}
}
try {
- if (stoppingMachine.get().value == 0) {
+ // This maintains previous behaviour of silently squashing any errors on the stoppingProcess task if the
+ // stoppingMachine exits with a nonzero value
+ boolean checkStopProcesses = (stoppingMachine == null || stoppingMachine.get().value == 0);
+
+ if (checkStopProcesses) {
// TODO we should test for destruction above, not merely successful "stop", as things like localhost and ssh won't be destroyed
DynamicTasks.waitForLast();
if (sshMachine.isPresent()) {
@@ -578,13 +604,12 @@ public abstract class MachineLifecycleEffectorTasks {
stoppingProcess.get();
}
}
-
- entity().setAttribute(SoftwareProcess.SERVICE_UP, false);
- ServiceStateLogic.setExpectedState(entity(), Lifecycle.STOPPED);
} catch (Throwable e) {
ServiceStateLogic.setExpectedState(entity(), Lifecycle.ON_FIRE);
Exceptions.propagate(e);
}
+ entity().setAttribute(SoftwareProcess.SERVICE_UP, false);
+ ServiceStateLogic.setExpectedState(entity(), Lifecycle.STOPPED);
if (log.isDebugEnabled()) log.debug("Stopped software process entity "+entity());
}
@@ -592,7 +617,7 @@ public abstract class MachineLifecycleEffectorTasks {
protected void preStopCustom() {
// nothing needed here
}
-
+
protected void postStopCustom() {
// nothing needed here
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f8c5f88f/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
index 8b9c065..3a9e544 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
@@ -18,29 +18,17 @@
*/
package brooklyn.entity.basic;
-import static org.testng.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.jclouds.util.Throwables2;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
import brooklyn.config.ConfigKey;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters;
import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters.RestartMachineMode;
+import brooklyn.entity.basic.SoftwareProcess.StopSoftwareParameters;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.entity.proxying.ImplementedBy;
import brooklyn.entity.trait.Startable;
+import brooklyn.location.Location;
import brooklyn.location.LocationSpec;
import brooklyn.location.basic.FixedListMachineProvisioningLocation;
import brooklyn.location.basic.Locations;
@@ -55,9 +43,25 @@ import brooklyn.util.task.DynamicTasks;
import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import org.jclouds.util.Throwables2;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
public class SoftwareProcessEntityTest extends BrooklynAppUnitTestSupport {
@@ -175,7 +179,7 @@ public class SoftwareProcessEntityTest extends BrooklynAppUnitTestSupport {
Assert.assertTrue(d.isRunning());
entity.stop();
Assert.assertEquals(d.events, ImmutableList.of("setup", "copyInstallResources", "install", "customize", "copyRuntimeResources", "launch", "stop"));
- Assert.assertFalse(d.isRunning());
+ assertFalse(d.isRunning());
}
@Test
@@ -189,8 +193,10 @@ public class SoftwareProcessEntityTest extends BrooklynAppUnitTestSupport {
loc.removeMachine(Locations.findUniqueSshMachineLocation(entity.getLocations()).get());
// with defaults, it won't reboot machine
+ d.events.clear();
entity.restart();
-
+ assertEquals(d.events, ImmutableList.of("stop", "launch"));
+
// but here, it will try to reboot, and fail because there is no machine available
TaskAdaptable<Void> t1 = Entities.submit(entity, Effectors.invocation(entity, Startable.RESTART,
ConfigBag.newInstance().configure(RestartSoftwareParameters.RESTART_MACHINE_TYPED, RestartMachineMode.TRUE)));
@@ -207,7 +213,57 @@ public class SoftwareProcessEntityTest extends BrooklynAppUnitTestSupport {
ConfigBag.newInstance().configure(RestartSoftwareParameters.RESTART_MACHINE_TYPED, RestartMachineMode.TRUE)));
t2.asTask().get();
- Assert.assertFalse(d.isRunning());
+ assertFalse(d.isRunning());
+ }
+
+ @Test
+ public void testBasicSoftwareProcessStopsEverything() throws Exception {
+ MyService entity = app.createAndManageChild(EntitySpec.create(MyService.class));
+ entity.start(ImmutableList.of(loc));
+ SimulatedDriver d = (SimulatedDriver) entity.getDriver();
+ Location machine = Iterables.getOnlyElement(entity.getLocations());
+
+ d.events.clear();
+ entity.stop();
+ assertEquals(d.events, ImmutableList.of("stop"));
+ assertEquals(entity.getLocations().size(), 0);
+ assertTrue(loc.getAvailable().contains(machine));
+ }
+
+ @Test
+ public void testBasicSoftwareProcessStopEverythingExplicitly() throws Exception {
+ MyService entity = app.createAndManageChild(EntitySpec.create(MyService.class));
+ entity.start(ImmutableList.of(loc));
+ SimulatedDriver d = (SimulatedDriver) entity.getDriver();
+ Location machine = Iterables.getOnlyElement(entity.getLocations());
+ d.events.clear();
+
+ TaskAdaptable<Void> t1 = Entities.submit(entity, Effectors.invocation(entity, Startable.STOP,
+ ConfigBag.newInstance().configure(StopSoftwareParameters.STOP_MACHINE, true)));
+ t1.asTask().get();
+
+ assertEquals(d.events, ImmutableList.of("stop"));
+ assertEquals(entity.getLocations().size(), 0);
+ assertTrue(loc.getAvailable().contains(machine));
+ }
+
+ @Test
+ public void testBasicSoftwareProcessStopsProcess() throws Exception {
+ MyService entity = app.createAndManageChild(EntitySpec.create(MyService.class));
+ entity.start(ImmutableList.of(loc));
+ SimulatedDriver d = (SimulatedDriver) entity.getDriver();
+ Location machine = Iterables.getOnlyElement(entity.getLocations());
+ d.events.clear();
+
+ TaskAdaptable<Void> t1 = Entities.submit(entity, Effectors.invocation(entity, Startable.STOP,
+ ConfigBag.newInstance().configure(StopSoftwareParameters.STOP_MACHINE, false
+
+ )));
+ t1.asTask().get(10, TimeUnit.SECONDS);
+
+ assertEquals(d.events, ImmutableList.of("stop"));
+ assertEquals(ImmutableList.copyOf(entity.getLocations()), ImmutableList.of(machine));
+ assertFalse(loc.getAvailable().contains(machine));
}
@Test
@@ -259,7 +315,7 @@ public class SoftwareProcessEntityTest extends BrooklynAppUnitTestSupport {
Task<Void> t = entity.invoke(Startable.STOP);
t.blockUntilEnded();
- Assert.assertFalse(t.isError(), "Expected parent to succeed, not fail with "+Tasks.getError(t));
+ assertFalse(t.isError(), "Expected parent to succeed, not fail with " + Tasks.getError(t));
Iterator<Task<?>> failures;
failures = Tasks.failed(Tasks.descendants(t, true)).iterator();
Assert.assertTrue(failures.hasNext(), "Expected error in descendants");
[2/2] incubator-brooklyn git commit: This closes #375
Posted by al...@apache.org.
This closes #375
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/5055b400
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/5055b400
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/5055b400
Branch: refs/heads/master
Commit: 5055b4009e4ecd995a12d7652916da01a836ac2f
Parents: f365b9b f8c5f88
Author: Aled Sage <al...@gmail.com>
Authored: Tue Dec 9 16:11:18 2014 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Dec 9 16:11:18 2014 +0000
----------------------------------------------------------------------
.../brooklyn/entity/basic/SoftwareProcess.java | 9 ++
.../software/MachineLifecycleEffectorTasks.java | 91 ++++++++++++-------
.../entity/basic/SoftwareProcessEntityTest.java | 94 ++++++++++++++++----
3 files changed, 142 insertions(+), 52 deletions(-)
----------------------------------------------------------------------