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(-)
----------------------------------------------------------------------